on master help sign in
Many improvements, all small.
2ceb577Bryan O'Sullivan
Data/Text.hs+9−13
@@ -1,11 +1,11 @@
1−{-# LANGUAGE BangPatterns, CPP, Rank2Types #-}
1+{-# LANGUAGE BangPatterns, CPP, Rank2Types, UnboxedTuples #-}
2{-# OPTIONS_GHC -fno-warn-orphans #-}
2{-# OPTIONS_GHC -fno-warn-orphans #-}
3
3
4-- |
4-- |
5-- Module : Data.Text
5-- Module : Data.Text
6−-- Copyright : (c) 2008, 2009 Tom Harper,
7−-- (c) 2009, 2010 Bryan O'Sullivan,
6+-- Copyright : (c) 2009, 2010, 2011 Bryan O'Sullivan,
8−-- (c) 2009 Duncan Coutts
7+-- (c) 2009 Duncan Coutts,
8+-- (c) 2008, 2009 Tom Harper
9--
9--
10-- License : BSD-style
10-- License : BSD-style
11-- Maintainer : bos@serpentine.com, rtomharper@googlemail.com,
11-- Maintainer : bos@serpentine.com, rtomharper@googlemail.com,
@@ -208,6 +208,7 @@ import Data.String (IsString(..))
208import qualified Data.Text.Fusion as S
208import qualified Data.Text.Fusion as S
209import qualified Data.Text.Fusion.Common as S
209import qualified Data.Text.Fusion.Common as S
210import Data.Text.Fusion (stream, reverseStream, unstream)
210import Data.Text.Fusion (stream, reverseStream, unstream)
211+import Data.Text.Private (span_)
211import Data.Text.Internal (Text(..), empty, firstf, safe, text, textP)
212import Data.Text.Internal (Text(..), empty, firstf, safe, text, textP)
212import qualified Prelude as P
213import qualified Prelude as P
213import Data.Text.Unsafe (Iter(..), iter, iter_, lengthWord16, reverseIter,
214import Data.Text.Unsafe (Iter(..), iter, iter_, lengthWord16, reverseIter,
@@ -1081,13 +1082,8 @@ splitAt n t@(Text arr off len)
1081-- of @t@ of elements that satisfy @p@, and whose second is the
1082-- of @t@ of elements that satisfy @p@, and whose second is the
1082-- remainder of the list.
1083-- remainder of the list.
1083span :: (Char -> Bool) -> Text -> (Text, Text)
1084span :: (Char -> Bool) -> Text -> (Text, Text)
1084−span p t@(Text arr off len) = (hd,tl)
1085+span p t = case span_ p t of
1085− where hd = textP arr off k
1086+ (# hd,tl #) -> (hd,tl)
1086− tl = textP arr (off+k) (len-k)
1087− !k = loop 0
1088− loop !i | i < len && p c = loop (i+d)
1089− | otherwise = i
1090− where Iter c d = iter t i
1091{-# INLINE span #-}
1087{-# INLINE span #-}
1092
1088
1093-- | /O(n)/ 'break' is like 'span', but the prefix returned is
1089-- | /O(n)/ 'break' is like 'span', but the prefix returned is
@@ -1182,7 +1178,7 @@ split _ t@(Text _off _arr 0) = [t]
1182split p t = loop t
1178split p t = loop t
1183 where loop s | null s' = [l]
1179 where loop s | null s' = [l]
1184 | otherwise = l : loop (unsafeTail s')
1180 | otherwise = l : loop (unsafeTail s')
1185− where (l, s') = break p s
1181+ where (# l, s' #) = span_ (not . p) s
1186{-# INLINE split #-}
1182{-# INLINE split #-}
1187
1183
1188-- | /O(n)/ Splits a 'Text' into components of length @k@. The last
1184-- | /O(n)/ Splits a 'Text' into components of length @k@. The last
@@ -1397,7 +1393,7 @@ lines ps | null ps = []
1397 | otherwise = h : if null t
1393 | otherwise = h : if null t
1398 then []
1394 then []
1399 else lines (unsafeTail t)
1395 else lines (unsafeTail t)
1400− where (h,t) = span (/= '\n') ps
1396+ where (# h,t #) = span_ (/= '\n') ps
1401{-# INLINE lines #-}
1397{-# INLINE lines #-}
1402
1398
1403{-
1399{-
Data/Text/Encoding.hs+5−4
@@ -2,9 +2,9 @@
2 UnliftedFFITypes #-}
2 UnliftedFFITypes #-}
3-- |
3-- |
4-- Module : Data.Text.Encoding
4-- Module : Data.Text.Encoding
5−-- Copyright : (c) 2008, 2009 Tom Harper,
6−-- (c) 2009, 2010 Bryan O'Sullivan,
5+-- Copyright : (c) 2009, 2010, 2011 Bryan O'Sullivan,
7−-- (c) 2009 Duncan Coutts
6+-- (c) 2009 Duncan Coutts,
7+-- (c) 2008, 2009 Tom Harper
8--
8--
9-- License : BSD-style
9-- License : BSD-style
10-- Maintainer : bos@serpentine.com, rtomharper@googlemail.com,
10-- Maintainer : bos@serpentine.com, rtomharper@googlemail.com,
@@ -175,7 +175,8 @@ encodeUtf8 (Text arr off len) = unsafePerformIO $ do
175 -- special-case this assumption.
175 -- special-case this assumption.
176 let end = ptr `plusPtr` size
176 let end = ptr `plusPtr` size
177 ascii !t !u
177 ascii !t !u
178− | t == offLen || u == end || v >= 0x80 = go t (u `minusPtr` ptr)
178+ | t == offLen || u == end || v >= 0x80 =
179+ go t (u `minusPtr` ptr)
179 | otherwise = do
180 | otherwise = do
180 poke u (fromIntegral v :: Word8)
181 poke u (fromIntegral v :: Word8)
181 ascii (t+1) (u `plusPtr` 1)
182 ascii (t+1) (u `plusPtr` 1)
Data/Text/Lazy/Read.hs+30−7
@@ -2,11 +2,10 @@
2
2
3-- |
3-- |
4-- Module : Data.Text.Lazy.Read
4-- Module : Data.Text.Lazy.Read
5−-- Copyright : (c) 2010 Bryan O'Sullivan
5+-- Copyright : (c) 2010, 2011 Bryan O'Sullivan
6--
6--
7-- License : BSD-style
7-- License : BSD-style
8−-- Maintainer : bos@serpentine.com, rtomharper@googlemail.com,
8+-- Maintainer : bos@serpentine.com
9−-- duncan@haskell.org
10-- Stability : experimental
9-- Stability : experimental
11-- Portability : GHC
10-- Portability : GHC
12--
11--
@@ -23,8 +22,10 @@ module Data.Text.Lazy.Read
23
22
24import Control.Monad (liftM)
23import Control.Monad (liftM)
25import Data.Char (isDigit, isHexDigit, ord)
24import Data.Char (isDigit, isHexDigit, ord)
25+import Data.Int (Int8, Int16, Int32, Int64)
26import Data.Ratio ((%))
26import Data.Ratio ((%))
27import Data.Text.Lazy as T
27import Data.Text.Lazy as T
28+import Data.Word (Word, Word8, Word16, Word32, Word64)
28
29
29-- | Read some text. If the read succeeds, return its value and the
30-- | Read some text. If the read succeeds, return its value and the
30-- remaining text, otherwise an error message.
31-- remaining text, otherwise an error message.
@@ -43,7 +44,16 @@ type Reader a = Text -> Either String (a,Text)
43-- 'Integer' for your result type.
44-- 'Integer' for your result type.
44decimal :: Integral a => Reader a
45decimal :: Integral a => Reader a
45{-# SPECIALIZE decimal :: Reader Int #-}
46{-# SPECIALIZE decimal :: Reader Int #-}
47+{-# SPECIALIZE decimal :: Reader Int8 #-}
48+{-# SPECIALIZE decimal :: Reader Int16 #-}
49+{-# SPECIALIZE decimal :: Reader Int32 #-}
50+{-# SPECIALIZE decimal :: Reader Int64 #-}
46{-# SPECIALIZE decimal :: Reader Integer #-}
51{-# SPECIALIZE decimal :: Reader Integer #-}
52+{-# SPECIALIZE decimal :: Reader Word #-}
53+{-# SPECIALIZE decimal :: Reader Word8 #-}
54+{-# SPECIALIZE decimal :: Reader Word16 #-}
55+{-# SPECIALIZE decimal :: Reader Word32 #-}
56+{-# SPECIALIZE decimal :: Reader Word64 #-}
47decimal txt
57decimal txt
48 | T.null h = Left "input does not start with a digit"
58 | T.null h = Left "input does not start with a digit"
49 | otherwise = Right (T.foldl' go 0 h, t)
59 | otherwise = Right (T.foldl' go 0 h, t)
@@ -71,8 +81,17 @@ hexadecimal txt
71 where (h,t) = T.splitAt 2 txt
81 where (h,t) = T.splitAt 2 txt
72
82
73hex :: Integral a => Reader a
83hex :: Integral a => Reader a
74−{-# SPECIALIZE hex :: Reader Int #-}
84+{-# SPECIALIZE hexadecimal :: Reader Int #-}
85+{-# SPECIALIZE hexadecimal :: Reader Int8 #-}
86+{-# SPECIALIZE hexadecimal :: Reader Int16 #-}
87+{-# SPECIALIZE hexadecimal :: Reader Int32 #-}
88+{-# SPECIALIZE hexadecimal :: Reader Int64 #-}
75−{-# SPECIALIZE hex :: Reader Integer #-}
89+{-# SPECIALIZE hexadecimal :: Reader Integer #-}
90+{-# SPECIALIZE hexadecimal :: Reader Word #-}
91+{-# SPECIALIZE hexadecimal :: Reader Word8 #-}
92+{-# SPECIALIZE hexadecimal :: Reader Word16 #-}
93+{-# SPECIALIZE hexadecimal :: Reader Word32 #-}
94+{-# SPECIALIZE hexadecimal :: Reader Word64 #-}
76hex txt
95hex txt
77 | T.null h = Left "input does not start with a hexadecimal digit"
96 | T.null h = Left "input does not start with a hexadecimal digit"
78 | otherwise = Right (T.foldl' go 0 h, t)
97 | otherwise = Right (T.foldl' go 0 h, t)
@@ -114,7 +133,7 @@ signed f = runP (signa (P f))
114--
133--
115-- >rational "3.foo" == Right (3.0, ".foo")
134-- >rational "3.foo" == Right (3.0, ".foo")
116-- >rational "3e" == Right (3.0, "e")
135-- >rational "3e" == Right (3.0, "e")
117−rational :: RealFloat a => Reader a
136+rational :: Fractional a => Reader a
118{-# SPECIALIZE rational :: Reader Double #-}
137{-# SPECIALIZE rational :: Reader Double #-}
119rational = floaty $ \real frac fracDenom -> fromRational $
138rational = floaty $ \real frac fracDenom -> fromRational $
120 real % 1 + frac % fracDenom
139 real % 1 + frac % fracDenom
@@ -138,6 +157,10 @@ double = floaty $ \real frac fracDenom ->
138
157
139signa :: Num a => Parser a -> Parser a
158signa :: Num a => Parser a -> Parser a
140{-# SPECIALIZE signa :: Parser Int -> Parser Int #-}
159{-# SPECIALIZE signa :: Parser Int -> Parser Int #-}
160+{-# SPECIALIZE signa :: Parser Int8 -> Parser Int8 #-}
161+{-# SPECIALIZE signa :: Parser Int16 -> Parser Int16 #-}
162+{-# SPECIALIZE signa :: Parser Int32 -> Parser Int32 #-}
163+{-# SPECIALIZE signa :: Parser Int64 -> Parser Int64 #-}
141{-# SPECIALIZE signa :: Parser Integer -> Parser Integer #-}
164{-# SPECIALIZE signa :: Parser Integer -> Parser Integer #-}
142signa p = do
165signa p = do
143 sign <- perhaps '+' $ char (\c -> c == '-' || c == '+')
166 sign <- perhaps '+' $ char (\c -> c == '-' || c == '+')
@@ -168,7 +191,7 @@ char p = P $ \t -> case T.uncons t of
168
191
169data T = T !Integer !Int
192data T = T !Integer !Int
170
193
171−floaty :: RealFloat a => (Integer -> Integer -> Integer -> a) -> Reader a
194+floaty :: Fractional a => (Integer -> Integer -> Integer -> a) -> Reader a
172{-# INLINE floaty #-}
195{-# INLINE floaty #-}
173floaty f = runP $ do
196floaty f = runP $ do
174 sign <- perhaps '+' $ char (\c -> c == '-' || c == '+')
197 sign <- perhaps '+' $ char (\c -> c == '-' || c == '+')
Data/Text/Private.hsnew file+28
@@ -0,0 +1,28 @@
1+{-# LANGUAGE BangPatterns, UnboxedTuples #-}
2+
3+-- |
4+-- Module : Data.Text.Private
5+-- Copyright : (c) 2011 Bryan O'Sullivan
6+--
7+-- License : BSD-style
8+-- Maintainer : bos@serpentine.com
9+-- Stability : experimental
10+-- Portability : GHC
11+
12+module Data.Text.Private
13+ (
14+ span_
15+ ) where
16+
17+import Data.Text.Internal (Text(..), textP)
18+import Data.Text.Unsafe (Iter(..), iter)
19+
20+span_ :: (Char -> Bool) -> Text -> (# Text, Text #)
21+span_ p t@(Text arr off len) = (# hd,tl #)
22+ where hd = textP arr off k
23+ tl = textP arr (off+k) (len-k)
24+ !k = loop 0
25+ loop !i | i < len && p c = loop (i+d)
26+ | otherwise = i
27+ where Iter c d = iter t i
28+{-# INLINE span_ #-}
Data/Text/Read.hs+41−8
@@ -1,12 +1,11 @@
1−{-# LANGUAGE OverloadedStrings #-}
1+{-# LANGUAGE OverloadedStrings, UnboxedTuples #-}
2
2
3-- |
3-- |
4-- Module : Data.Text.Read
4-- Module : Data.Text.Read
5−-- Copyright : (c) 2010 Bryan O'Sullivan
5+-- Copyright : (c) 2010, 2011 Bryan O'Sullivan
6--
6--
7-- License : BSD-style
7-- License : BSD-style
8−-- Maintainer : bos@serpentine.com, rtomharper@googlemail.com,
8+-- Maintainer : bos@serpentine.com
9−-- duncan@haskell.org
10-- Stability : experimental
9-- Stability : experimental
11-- Portability : GHC
10-- Portability : GHC
12--
11--
@@ -23,8 +22,11 @@ module Data.Text.Read
23
22
24import Control.Monad (liftM)
23import Control.Monad (liftM)
25import Data.Char (isDigit, isHexDigit, ord)
24import Data.Char (isDigit, isHexDigit, ord)
25+import Data.Int (Int8, Int16, Int32, Int64)
26import Data.Ratio ((%))
26import Data.Ratio ((%))
27import Data.Text as T
27import Data.Text as T
28+import Data.Text.Private (span_)
29+import Data.Word (Word, Word8, Word16, Word32, Word64)
28
30
29-- | Read some text. If the read succeeds, return its value and the
31-- | Read some text. If the read succeeds, return its value and the
30-- remaining text, otherwise an error message.
32-- remaining text, otherwise an error message.
@@ -43,11 +45,20 @@ type Reader a = Text -> Either String (a,Text)
43-- 'Integer' for your result type.
45-- 'Integer' for your result type.
44decimal :: Integral a => Reader a
46decimal :: Integral a => Reader a
45{-# SPECIALIZE decimal :: Reader Int #-}
47{-# SPECIALIZE decimal :: Reader Int #-}
48+{-# SPECIALIZE decimal :: Reader Int8 #-}
49+{-# SPECIALIZE decimal :: Reader Int16 #-}
50+{-# SPECIALIZE decimal :: Reader Int32 #-}
51+{-# SPECIALIZE decimal :: Reader Int64 #-}
46{-# SPECIALIZE decimal :: Reader Integer #-}
52{-# SPECIALIZE decimal :: Reader Integer #-}
53+{-# SPECIALIZE decimal :: Reader Word #-}
54+{-# SPECIALIZE decimal :: Reader Word8 #-}
55+{-# SPECIALIZE decimal :: Reader Word16 #-}
56+{-# SPECIALIZE decimal :: Reader Word32 #-}
57+{-# SPECIALIZE decimal :: Reader Word64 #-}
47decimal txt
58decimal txt
48 | T.null h = Left "input does not start with a digit"
59 | T.null h = Left "input does not start with a digit"
49 | otherwise = Right (T.foldl' go 0 h, t)
60 | otherwise = Right (T.foldl' go 0 h, t)
50− where (h,t) = T.span isDigit txt
61+ where (# h,t #) = span_ isDigit txt
51 go n d = (n * 10 + fromIntegral (digitToInt d))
62 go n d = (n * 10 + fromIntegral (digitToInt d))
52
63
53-- | Read a hexadecimal integer, consisting of an optional leading
64-- | Read a hexadecimal integer, consisting of an optional leading
@@ -64,7 +75,16 @@ decimal txt
64-- 'Integer' for your result type.
75-- 'Integer' for your result type.
65hexadecimal :: Integral a => Reader a
76hexadecimal :: Integral a => Reader a
66{-# SPECIALIZE hexadecimal :: Reader Int #-}
77{-# SPECIALIZE hexadecimal :: Reader Int #-}
78+{-# SPECIALIZE hexadecimal :: Reader Int8 #-}
79+{-# SPECIALIZE hexadecimal :: Reader Int16 #-}
80+{-# SPECIALIZE hexadecimal :: Reader Int32 #-}
81+{-# SPECIALIZE hexadecimal :: Reader Int64 #-}
67{-# SPECIALIZE hexadecimal :: Reader Integer #-}
82{-# SPECIALIZE hexadecimal :: Reader Integer #-}
83+{-# SPECIALIZE hexadecimal :: Reader Word #-}
84+{-# SPECIALIZE hexadecimal :: Reader Word8 #-}
85+{-# SPECIALIZE hexadecimal :: Reader Word16 #-}
86+{-# SPECIALIZE hexadecimal :: Reader Word32 #-}
87+{-# SPECIALIZE hexadecimal :: Reader Word64 #-}
68hexadecimal txt
88hexadecimal txt
69 | h == "0x" || h == "0X" = hex t
89 | h == "0x" || h == "0X" = hex t
70 | otherwise = hex txt
90 | otherwise = hex txt
@@ -72,11 +92,20 @@ hexadecimal txt
72
92
73hex :: Integral a => Reader a
93hex :: Integral a => Reader a
74{-# SPECIALIZE hex :: Reader Int #-}
94{-# SPECIALIZE hex :: Reader Int #-}
95+{-# SPECIALIZE hex :: Reader Int8 #-}
96+{-# SPECIALIZE hex :: Reader Int16 #-}
97+{-# SPECIALIZE hex :: Reader Int32 #-}
98+{-# SPECIALIZE hex :: Reader Int64 #-}
75{-# SPECIALIZE hex :: Reader Integer #-}
99{-# SPECIALIZE hex :: Reader Integer #-}
100+{-# SPECIALIZE hex :: Reader Word #-}
101+{-# SPECIALIZE hex :: Reader Word8 #-}
102+{-# SPECIALIZE hex :: Reader Word16 #-}
103+{-# SPECIALIZE hex :: Reader Word32 #-}
104+{-# SPECIALIZE hex :: Reader Word64 #-}
76hex txt
105hex txt
77 | T.null h = Left "input does not start with a hexadecimal digit"
106 | T.null h = Left "input does not start with a hexadecimal digit"
78 | otherwise = Right (T.foldl' go 0 h, t)
107 | otherwise = Right (T.foldl' go 0 h, t)
79− where (h,t) = T.span isHexDigit txt
108+ where (# h,t #) = span_ isHexDigit txt
80 go n d = (n * 16 + fromIntegral (hexDigitToInt d))
109 go n d = (n * 16 + fromIntegral (hexDigitToInt d))
81
110
82hexDigitToInt :: Char -> Int
111hexDigitToInt :: Char -> Int
@@ -114,7 +143,7 @@ signed f = runP (signa (P f))
114--
143--
115-- >rational "3.foo" == Right (3.0, ".foo")
144-- >rational "3.foo" == Right (3.0, ".foo")
116-- >rational "3e" == Right (3.0, "e")
145-- >rational "3e" == Right (3.0, "e")
117−rational :: RealFloat a => Reader a
146+rational :: Fractional a => Reader a
118{-# SPECIALIZE rational :: Reader Double #-}
147{-# SPECIALIZE rational :: Reader Double #-}
119rational = floaty $ \real frac fracDenom -> fromRational $
148rational = floaty $ \real frac fracDenom -> fromRational $
120 real % 1 + frac % fracDenom
149 real % 1 + frac % fracDenom
@@ -138,6 +167,10 @@ double = floaty $ \real frac fracDenom ->
138
167
139signa :: Num a => Parser a -> Parser a
168signa :: Num a => Parser a -> Parser a
140{-# SPECIALIZE signa :: Parser Int -> Parser Int #-}
169{-# SPECIALIZE signa :: Parser Int -> Parser Int #-}
170+{-# SPECIALIZE signa :: Parser Int8 -> Parser Int8 #-}
171+{-# SPECIALIZE signa :: Parser Int16 -> Parser Int16 #-}
172+{-# SPECIALIZE signa :: Parser Int32 -> Parser Int32 #-}
173+{-# SPECIALIZE signa :: Parser Int64 -> Parser Int64 #-}
141{-# SPECIALIZE signa :: Parser Integer -> Parser Integer #-}
174{-# SPECIALIZE signa :: Parser Integer -> Parser Integer #-}
142signa p = do
175signa p = do
143 sign <- perhaps '+' $ char (\c -> c == '-' || c == '+')
176 sign <- perhaps '+' $ char (\c -> c == '-' || c == '+')
@@ -168,7 +201,7 @@ char p = P $ \t -> case T.uncons t of
168
201
169data T = T !Integer !Int
202data T = T !Integer !Int
170
203
171−floaty :: RealFloat a => (Integer -> Integer -> Integer -> a) -> Reader a
204+floaty :: Fractional a => (Integer -> Integer -> Integer -> a) -> Reader a
172{-# INLINE floaty #-}
205{-# INLINE floaty #-}
173floaty f = runP $ do
206floaty f = runP $ do
174 sign <- perhaps '+' $ char (\c -> c == '-' || c == '+')
207 sign <- perhaps '+' $ char (\c -> c == '-' || c == '+')
text.cabal+1
@@ -100,6 +100,7 @@ library
100 Data.Text.Lazy.Encoding.Fusion
100 Data.Text.Lazy.Encoding.Fusion
101 Data.Text.Lazy.Fusion
101 Data.Text.Lazy.Fusion
102 Data.Text.Lazy.Search
102 Data.Text.Lazy.Search
103+ Data.Text.Private
103 Data.Text.Search
104 Data.Text.Search
104 Data.Text.Unsafe
105 Data.Text.Unsafe
105 Data.Text.Unsafe.Base
106 Data.Text.Unsafe.Base