on master help sign in
Refactor Read modules to share code
commit15034aaacfc7b34ecadda3570926c5afbd0e9fc1 authorBryan O'Sullivan <bos@serpentine.com> dateThu 6 Mar 2014, 09:30 (13 years ago) parent5eaa1af
6 files changed+64−64
Data/Text/Encoding.hs−1 Data/Text/Internal/Read.hs+52 Data/Text/Lazy/Builder/Int.hs+3−1 Data/Text/Lazy/Read.hs+4−31 Data/Text/Read.hs+4−31 text.cabal+1
Data/Text/Encoding.hs−1
@@ -74,7 +74,6 @@ import Control.Monad.ST (unsafeIOToST, unsafeSTToIO)
7474import Data.Bits ((.&.))
7575import Data.Text.Internal.Unsafe.Char (ord)
7676import qualified Data.ByteString.Builder as B
77−import qualified Data.ByteString.Builder.Extra as B
7877import qualified Data.ByteString.Builder.Internal as B hiding (empty, append)
7978import qualified Data.ByteString.Builder.Prim as BP
8079import qualified Data.ByteString.Builder.Prim.Internal as BP
Data/Text/Internal/Read.hsnew file+52
@@ -0,0 +1,52 @@
1+-- |
2+-- Module : Data.Text.Internal.Read
3+-- Copyright : (c) 2014 Bryan O'Sullivan
4+--
5+-- License : BSD-style
6+-- Maintainer : bos@serpentine.com
7+-- Stability : experimental
8+-- Portability : GHC
9+--
10+-- Common internal functiopns for reading textual data.
11+module Data.Text.Internal.Read
12+ (
13+ IReader
14+ , IParser(..)
15+ , T(..)
16+ , digitToInt
17+ , hexDigitToInt
18+ , perhaps
19+ ) where
20+
21+import Data.Char (ord)
22+
23+type IReader t a = t -> Either String (a,t)
24+
25+newtype IParser t a = P {
26+ runP :: IReader t a
27+ }
28+
29+instance Monad (IParser t) where
30+ return a = P $ \t -> Right (a,t)
31+ {-# INLINE return #-}
32+ m >>= k = P $ \t -> case runP m t of
33+ Left err -> Left err
34+ Right (a,t') -> runP (k a) t'
35+ {-# INLINE (>>=) #-}
36+ fail msg = P $ \_ -> Left msg
37+
38+data T = T !Integer !Int
39+
40+perhaps :: a -> IParser t a -> IParser t a
41+perhaps def m = P $ \t -> case runP m t of
42+ Left _ -> Right (def,t)
43+ r@(Right _) -> r
44+
45+hexDigitToInt :: Char -> Int
46+hexDigitToInt c
47+ | c >= '0' && c <= '9' = ord c - ord '0'
48+ | c >= 'a' && c <= 'f' = ord c - (ord 'a' - 10)
49+ | otherwise = ord c - (ord 'A' - 10)
50+
51+digitToInt :: Char -> Int
52+digitToInt c = ord c - ord '0'
Data/Text/Lazy/Builder/Int.hs+3−1
@@ -49,7 +49,7 @@ import GHC.Integer
4949#endif
5050
5151decimal :: Integral a => a -> Builder
52−{-# SPECIALIZE decimal :: Int8 -> Builder #-}
52+{-# RULES "decimal/Int8" decimal = boundedDecimal :: Int8 -> Builder #-}
5353{-# RULES "decimal/Int" decimal = boundedDecimal :: Int -> Builder #-}
5454{-# RULES "decimal/Int16" decimal = boundedDecimal :: Int16 -> Builder #-}
5555{-# RULES "decimal/Int32" decimal = boundedDecimal :: Int32 -> Builder #-}
@@ -61,6 +61,7 @@ decimal :: Integral a => a -> Builder
6161{-# RULES "decimal/Word64" decimal = positive :: Word64 -> Builder #-}
6262{-# RULES "decimal/Integer" decimal = integer 10 :: Integer -> Builder #-}
6363decimal i = decimal' (<= -128) i
64+{-# NOINLINE decimal #-}
6465
6566boundedDecimal :: (Integral a, Bounded a) => a -> Builder
6667{-# SPECIALIZE boundedDecimal :: Int -> Builder #-}
@@ -169,6 +170,7 @@ hexadecimal i
169170 where
170171 go n | n < 16 = hexDigit n
171172 | otherwise = go (n `quot` 16) <> hexDigit (n `rem` 16)
173+{-# NOINLINE[0] hexadecimal #-}
172174
173175hexInteger :: Integer -> Builder
174176hexInteger i
Data/Text/Lazy/Read.hs+4−31
@@ -24,15 +24,17 @@ module Data.Text.Lazy.Read
2424 ) where
2525
2626import Control.Monad (liftM)
27−import Data.Char (isDigit, isHexDigit, ord)
27+import Data.Char (isDigit, isHexDigit)
2828import Data.Int (Int8, Int16, Int32, Int64)
2929import Data.Ratio ((%))
30+import Data.Text.Internal.Read
3031import Data.Text.Lazy as T
3132import Data.Word (Word, Word8, Word16, Word32, Word64)
3233
3334-- | Read some text. If the read succeeds, return its value and the
3435-- remaining text, otherwise an error message.
35−type Reader a = Text -> Either String (a,Text)
36+type Reader a = IReader Text a
37+type Parser = IParser Text
3638
3739-- | Read a decimal integer. The input must begin with at least one
3840-- decimal digit, and is consumed until a non-digit or end of string
@@ -101,15 +103,6 @@ hex txt
101103 where (h,t) = T.span isHexDigit txt
102104 go n d = (n * 16 + fromIntegral (hexDigitToInt d))
103105
104−hexDigitToInt :: Char -> Int
105−hexDigitToInt c
106− | c >= '0' && c <= '9' = ord c - ord '0'
107− | c >= 'a' && c <= 'f' = ord c - (ord 'a' - 10)
108− | otherwise = ord c - (ord 'A' - 10)
109−
110−digitToInt :: Char -> Int
111−digitToInt c = ord c - ord '0'
112−
113106-- | Read an optional leading sign character (@\'-\'@ or @\'+\'@) and
114107-- apply it to the result of applying the given reader.
115108signed :: Num a => Reader a -> Reader a
@@ -169,31 +162,11 @@ signa p = do
169162 sign <- perhaps '+' $ char (\c -> c == '-' || c == '+')
170163 if sign == '+' then p else negate `liftM` p
171164
172−newtype Parser a = P {
173− runP :: Reader a
174− }
175−
176−instance Monad Parser where
177− return a = P $ \t -> Right (a,t)
178− {-# INLINE return #-}
179− m >>= k = P $ \t -> case runP m t of
180− Left err -> Left err
181− Right (a,t') -> runP (k a) t'
182− {-# INLINE (>>=) #-}
183− fail msg = P $ \_ -> Left msg
184−
185−perhaps :: a -> Parser a -> Parser a
186−perhaps def m = P $ \t -> case runP m t of
187− Left _ -> Right (def,t)
188− r@(Right _) -> r
189−
190165char :: (Char -> Bool) -> Parser Char
191166char p = P $ \t -> case T.uncons t of
192167 Just (c,t') | p c -> Right (c,t')
193168 _ -> Left "character does not match"
194169
195−data T = T !Integer !Int
196−
197170floaty :: Fractional a => (Integer -> Integer -> Integer -> a) -> Reader a
198171{-# INLINE floaty #-}
199172floaty f = runP $ do
Data/Text/Read.hs+4−31
@@ -24,16 +24,18 @@ module Data.Text.Read
2424 ) where
2525
2626import Control.Monad (liftM)
27−import Data.Char (isDigit, isHexDigit, ord)
27+import Data.Char (isDigit, isHexDigit)
2828import Data.Int (Int8, Int16, Int32, Int64)
2929import Data.Ratio ((%))
3030import Data.Text as T
3131import Data.Text.Internal.Private (span_)
32+import Data.Text.Internal.Read
3233import Data.Word (Word, Word8, Word16, Word32, Word64)
3334
3435-- | Read some text. If the read succeeds, return its value and the
3536-- remaining text, otherwise an error message.
36−type Reader a = Text -> Either String (a,Text)
37+type Reader a = IReader Text a
38+type Parser a = IParser Text a
3739
3840-- | Read a decimal integer. The input must begin with at least one
3941-- decimal digit, and is consumed until a non-digit or end of string
@@ -111,15 +113,6 @@ hex txt
111113 where (# h,t #) = span_ isHexDigit txt
112114 go n d = (n * 16 + fromIntegral (hexDigitToInt d))
113115
114−hexDigitToInt :: Char -> Int
115−hexDigitToInt c
116− | c >= '0' && c <= '9' = ord c - ord '0'
117− | c >= 'a' && c <= 'f' = ord c - (ord 'a' - 10)
118− | otherwise = ord c - (ord 'A' - 10)
119−
120−digitToInt :: Char -> Int
121−digitToInt c = ord c - ord '0'
122−
123116-- | Read an optional leading sign character (@\'-\'@ or @\'+\'@) and
124117-- apply it to the result of applying the given reader.
125118signed :: Num a => Reader a -> Reader a
@@ -179,31 +172,11 @@ signa p = do
179172 sign <- perhaps '+' $ char (\c -> c == '-' || c == '+')
180173 if sign == '+' then p else negate `liftM` p
181174
182−newtype Parser a = P {
183− runP :: Reader a
184− }
185−
186−instance Monad Parser where
187− return a = P $ \t -> Right (a,t)
188− {-# INLINE return #-}
189− m >>= k = P $ \t -> case runP m t of
190− Left err -> Left err
191− Right (a,t') -> runP (k a) t'
192− {-# INLINE (>>=) #-}
193− fail msg = P $ \_ -> Left msg
194−
195−perhaps :: a -> Parser a -> Parser a
196−perhaps def m = P $ \t -> case runP m t of
197− Left _ -> Right (def,t)
198− r@(Right _) -> r
199−
200175char :: (Char -> Bool) -> Parser Char
201176char p = P $ \t -> case T.uncons t of
202177 Just (c,t') | p c -> Right (c,t')
203178 _ -> Left "character does not match"
204179
205−data T = T !Integer !Int
206−
207180floaty :: Fractional a => (Integer -> Integer -> Integer -> a) -> Reader a
208181{-# INLINE floaty #-}
209182floaty f = runP $ do
text.cabal+1
@@ -103,6 +103,7 @@ library
103103 Data.Text.Internal.Lazy.Fusion
104104 Data.Text.Internal.Lazy.Search
105105 Data.Text.Internal.Private
106+ Data.Text.Internal.Read
106107 Data.Text.Internal.Search
107108 Data.Text.Internal.Unsafe
108109 Data.Text.Internal.Unsafe.Char