@@ -3,9 +3,6 @@
3#if __GLASGOW_HASKELL__ >= 702
3#if __GLASGOW_HASKELL__ >= 702
4{-# LANGUAGE Trustworthy #-}
4{-# LANGUAGE Trustworthy #-}
6−#if __GLASGOW_HASKELL__ >= 708
7−{-# LANGUAGE TypeFamilies #-}
11-- Module : Data.Text
8-- Module : Data.Text
@@ -129,7 +126,6 @@ module Data.Text
130 , dropEnd
127 , dropEnd
131 , takeWhile
128 , takeWhile
133 , dropWhile
129 , dropWhile
134 , dropWhileEnd
130 , dropWhileEnd
135 , dropAround
131 , dropAround
@@ -192,16 +188,15 @@ module Data.Text
193 -- * Low level operations
189 -- * Low level operations
198import Prelude (Char, Bool(..), Int, Maybe(..), String,
193import Prelude (Char, Bool(..), Int, Maybe(..), String,
199 Eq(..), Ord(..), Ordering(..), (++),
194 Eq(..), Ord(..), Ordering(..), (++),
200− Read(..),
195+ Read(..), Show(..),
201 (&&), (||), (+), (-), (.), ($), ($!), (>>),
196 (&&), (||), (+), (-), (.), ($), ($!), (>>),
202− not, return, otherwise, quot)
197+ maxBound, not, return, otherwise, quot)
203#if defined(HAVE_DEEPSEQ)
198#if defined(HAVE_DEEPSEQ)
204−import Control.DeepSeq (NFData(rnf))
199+import Control.DeepSeq (NFData)
206#if defined(ASSERTS)
201#if defined(ASSERTS)
207import Control.Exception (assert)
202import Control.Exception (assert)
@@ -210,22 +205,15 @@ import Data.Char (isSpace)
210import Data.Data (Data(gfoldl, toConstr, gunfold, dataTypeOf), constrIndex,
205import Data.Data (Data(gfoldl, toConstr, gunfold, dataTypeOf), constrIndex,
211 Constr, mkConstr, DataType, mkDataType, Fixity(Prefix))
206 Constr, mkConstr, DataType, mkDataType, Fixity(Prefix))
212import Control.Monad (foldM)
207import Control.Monad (foldM)
213−import Control.Monad.ST (ST)
214import qualified Data.Text.Array as A
208import qualified Data.Text.Array as A
215import qualified Data.List as L
209import qualified Data.List as L
216−import Data.Binary (Binary(get, put))
217import Data.Monoid (Monoid(..))
210import Data.Monoid (Monoid(..))
218−#if MIN_VERSION_base(4,9,0)
219−import Data.Semigroup (Semigroup(..))
221import Data.String (IsString(..))
211import Data.String (IsString(..))
222import qualified Data.Text.Internal.Fusion as S
212import qualified Data.Text.Internal.Fusion as S
223import qualified Data.Text.Internal.Fusion.Common as S
213import qualified Data.Text.Internal.Fusion.Common as S
224−import Data.Text.Encoding (decodeUtf8', encodeUtf8)
225import Data.Text.Internal.Fusion (stream, reverseStream, unstream)
214import Data.Text.Internal.Fusion (stream, reverseStream, unstream)
226import Data.Text.Internal.Private (span_)
215import Data.Text.Internal.Private (span_)
227import Data.Text.Internal (Text(..), empty, firstf, mul, safe, text)
216import Data.Text.Internal (Text(..), empty, firstf, mul, safe, text)
228−import Data.Text.Show (singleton, unpack, unpackCString#)
229import qualified Prelude as P
217import qualified Prelude as P
230import Data.Text.Unsafe (Iter(..), iter, iter_, lengthWord16, reverseIter,
218import Data.Text.Unsafe (Iter(..), iter, iter_, lengthWord16, reverseIter,
231 reverseIter_, unsafeHead, unsafeTail)
219 reverseIter_, unsafeHead, unsafeTail)
@@ -238,13 +226,12 @@ import Data.ByteString (ByteString)
238import qualified Data.Text.Lazy as L
226import qualified Data.Text.Lazy as L
239import Data.Int (Int64)
227import Data.Int (Int64)
241−import GHC.Base (eqInt, neInt, gtInt, geInt, ltInt, leInt)
242−#if __GLASGOW_HASKELL__ >= 708
229+#if __GLASGOW_HASKELL__ >= 702
243−import qualified GHC.Exts as Exts
230+import qualified GHC.CString as GHC
245−#if MIN_VERSION_base(4,7,0)
232+import qualified GHC.Base as GHC
246−import Text.Printf (PrintfArg, formatArg, formatString)
234+import GHC.Prim (Addr#)
249-- $strict
236-- $strict
@@ -330,48 +317,24 @@ instance Eq Text where
330instance Ord Text where
317instance Ord Text where
331 compare = compareText
318 compare = compareText
320+instance Show Text where
321+ showsPrec p ps r = showsPrec p (unpack ps) r
333instance Read Text where
323instance Read Text where
334 readsPrec p str = [(pack x,y) | (x,y) <- readsPrec p str]
324 readsPrec p str = [(pack x,y) | (x,y) <- readsPrec p str]
336−#if MIN_VERSION_base(4,9,0)
337−-- Semigroup orphan instances for older GHCs are provided by
338−-- 'semigroups` package
340−instance Semigroup Text where
344instance Monoid Text where
326instance Monoid Text where
345 mempty = empty
327 mempty = empty
346−#if MIN_VERSION_base(4,9,0)
347− mappend = (<>) -- future-proof definition
349 mappend = append
328 mappend = append
351 mconcat = concat
329 mconcat = concat
353instance IsString Text where
331instance IsString Text where
354 fromString = pack
332 fromString = pack
356−#if __GLASGOW_HASKELL__ >= 708
357−instance Exts.IsList Text where
358− type Item Text = Char
363#if defined(HAVE_DEEPSEQ)
334#if defined(HAVE_DEEPSEQ)
364−instance NFData Text where rnf !_ = ()
335+instance NFData Text
367−instance Binary Text where
368− put t = put (encodeUtf8 t)
371− case decodeUtf8' bs of
372− P.Left exn -> P.fail (P.show exn)
373− P.Right a -> P.return a
375-- | This instance preserves data abstraction at the cost of inefficiency.
338-- | This instance preserves data abstraction at the cost of inefficiency.
376-- We omit reflection services for the sake of data abstraction.
339-- We omit reflection services for the sake of data abstraction.
@@ -395,12 +358,6 @@ instance Data Text where
395 _ -> P.error "gunfold"
358 _ -> P.error "gunfold"
396 dataTypeOf _ = textDataType
359 dataTypeOf _ = textDataType
398−#if MIN_VERSION_base(4,7,0)
399−-- | Only defined for @base-4.7.0.0@ and later
400−instance PrintfArg Text where
401− formatArg txt = formatString $ unpack txt
404packConstr :: Constr
361packConstr :: Constr
405packConstr = mkConstr textDataType "pack" [] Prefix
362packConstr = mkConstr textDataType "pack" [] Prefix
@@ -430,6 +387,30 @@ pack :: String -> Text
430pack = unstream . S.map safe . S.streamList
387pack = unstream . S.map safe . S.streamList
431{-# INLINE [1] pack #-}
388{-# INLINE [1] pack #-}
390+-- | /O(n)/ Convert a 'Text' into a 'String'. Subject to fusion.
391+unpack :: Text -> String
392+unpack = S.unstreamList . stream
393+{-# INLINE [1] unpack #-}
395+-- | /O(n)/ Convert a literal string into a Text. Subject to fusion.
396+unpackCString# :: Addr# -> Text
397+unpackCString# addr# = unstream (S.streamCString# addr#)
398+{-# NOINLINE unpackCString# #-}
400+{-# RULES "TEXT literal" forall a.
401+ unstream (S.map safe (S.streamList (GHC.unpackCString# a)))
402+ = unpackCString# a #-}
404+{-# RULES "TEXT literal UTF8" forall a.
405+ unstream (S.map safe (S.streamList (GHC.unpackCStringUtf8# a)))
406+ = unpackCString# a #-}
408+-- | /O(1)/ Convert a character into a Text. Subject to fusion.
409+-- Performs replacement on invalid scalar values.
410+singleton :: Char -> Text
411+singleton = unstream . S.singleton . safe
412+{-# INLINE [1] singleton #-}
433-- -----------------------------------------------------------------------------
414-- -----------------------------------------------------------------------------
434-- * Basic functions
415-- * Basic functions
@@ -460,7 +441,6 @@ append a@(Text arr1 off1 len1) b@(Text arr2 off2 len2)
460 | otherwise = overflowError "append"
441 | otherwise = overflowError "append"
462 len = len1+len2
443 len = len1+len2
463− x :: ST s (A.MArray s)
465 arr <- A.new len
445 arr <- A.new len
466 A.copyI arr 0 arr1 off1 len1
446 A.copyI arr 0 arr1 off1 len1
@@ -486,8 +466,8 @@ head t = S.head (stream t)
486uncons :: Text -> Maybe (Char, Text)
466uncons :: Text -> Maybe (Char, Text)
487uncons t@(Text arr off len)
467uncons t@(Text arr off len)
488 | len <= 0 = Nothing
468 | len <= 0 = Nothing
489− | otherwise = Just $ let !(Iter c d) = iter t 0
490− in (c, text arr (off+d) (len-d))
469+ | otherwise = Just (c, text arr (off+d) (len-d))
470+ where Iter c d = iter t 0
491{-# INLINE [1] uncons #-}
471{-# INLINE [1] uncons #-}
493-- | Lifted from Control.Arrow and specialized.
473-- | Lifted from Control.Arrow and specialized.
@@ -572,9 +552,7 @@ isSingleton = S.isSingleton . stream
572-- Subject to fusion.
552-- Subject to fusion.
573length :: Text -> Int
553length :: Text -> Int
574length t = S.length (stream t)
554length t = S.length (stream t)
575−{-# INLINE [0] length #-}
555+{-# INLINE length #-}
576−-- length needs to be phased after the compareN/length rules otherwise
577−-- it may inline before the rules have an opportunity to fire.
579-- | /O(n)/ Compare the count of characters in a 'Text' to a number.
557-- | /O(n)/ Compare the count of characters in a 'Text' to a number.
580-- Subject to fusion.
558-- Subject to fusion.
@@ -593,32 +571,32 @@ compareLength t n = S.compareLengthI (stream t) n
595"TEXT ==N/length -> compareLength/==EQ" [~1] forall t n.
573"TEXT ==N/length -> compareLength/==EQ" [~1] forall t n.
596− eqInt (length t) n = compareLength t n == EQ
574+ (==) (length t) n = compareLength t n == EQ
600"TEXT /=N/length -> compareLength//=EQ" [~1] forall t n.
578"TEXT /=N/length -> compareLength//=EQ" [~1] forall t n.
601− neInt (length t) n = compareLength t n /= EQ
579+ (/=) (length t) n = compareLength t n /= EQ
605"TEXT <N/length -> compareLength/==LT" [~1] forall t n.
583"TEXT <N/length -> compareLength/==LT" [~1] forall t n.
606− ltInt (length t) n = compareLength t n == LT
584+ (<) (length t) n = compareLength t n == LT
610"TEXT <=N/length -> compareLength//=GT" [~1] forall t n.
588"TEXT <=N/length -> compareLength//=GT" [~1] forall t n.
611− leInt (length t) n = compareLength t n /= GT
589+ (<=) (length t) n = compareLength t n /= GT
615"TEXT >N/length -> compareLength/==GT" [~1] forall t n.
593"TEXT >N/length -> compareLength/==GT" [~1] forall t n.
616− gtInt (length t) n = compareLength t n == GT
594+ (>) (length t) n = compareLength t n == GT
620"TEXT >=N/length -> compareLength//=LT" [~1] forall t n.
598"TEXT >=N/length -> compareLength//=LT" [~1] forall t n.
621− geInt (length t) n = compareLength t n /= LT
599+ (>=) (length t) n = compareLength t n /= LT
624-- -----------------------------------------------------------------------------
602-- -----------------------------------------------------------------------------
@@ -649,37 +627,11 @@ reverse :: Text -> Text
649reverse t = S.reverse (stream t)
627reverse t = S.reverse (stream t)
650{-# INLINE reverse #-}
628{-# INLINE reverse #-}
652−-- | /O(m+n)/ Replace every non-overlapping occurrence of @needle@ in
630+-- | /O(m+n)/ Replace every occurrence of one substring with another.
653−-- @haystack@ with @replacement@.
655−-- This function behaves as though it was defined as follows:
658−-- replace needle replacement haystack =
659−-- 'intercalate' replacement ('splitOn' needle haystack)
662−-- As this suggests, each occurrence is replaced exactly once. So if
663−-- @needle@ occurs in @replacement@, that occurrence will /not/ itself
664−-- be replaced recursively:
666−-- > replace "oo" "foo" "oo" == "foo"
668−-- In cases where several instances of @needle@ overlap, only the
669−-- first one will be replaced:
671−-- > replace "ofo" "bar" "ofofo" == "barfo"
673-- In (unlikely) bad cases, this function's time complexity degrades
632-- In (unlikely) bad cases, this function's time complexity degrades
674-- towards /O(n*m)/.
633-- towards /O(n*m)/.
675−replace :: Text
634+replace :: Text -> Text -> Text -> Text
676− -- ^ @needle@ to search for. If this string is empty, an
677− -- error will occur.
679− -- ^ @replacement@ to replace @needle@ with.
681− -- ^ @haystack@ in which to search.
683replace needle@(Text _ _ neeLen)
635replace needle@(Text _ _ neeLen)
684 (Text repArr repOff repLen)
636 (Text repArr repOff repLen)
685 haystack@(Text hayArr hayOff hayLen)
637 haystack@(Text hayArr hayOff hayLen)
@@ -690,7 +642,6 @@ replace needle@(Text _ _ neeLen)
691 ixs = indices needle haystack
643 ixs = indices needle haystack
692 len = hayLen - (neeLen - repLen) `mul` L.length ixs
644 len = hayLen - (neeLen - repLen) `mul` L.length ixs
693− x :: ST s (A.MArray s)
695 marr <- A.new len
646 marr <- A.new len
696 let loop (i:is) o d = do
647 let loop (i:is) o d = do
@@ -741,7 +692,7 @@ replace needle@(Text _ _ neeLen)
741-- instead of itself.
692-- instead of itself.
742toCaseFold :: Text -> Text
693toCaseFold :: Text -> Text
743toCaseFold t = unstream (S.toCaseFold (stream t))
694toCaseFold t = unstream (S.toCaseFold (stream t))
744−{-# INLINE toCaseFold #-}
695+{-# INLINE [0] toCaseFold #-}
746-- | /O(n)/ Convert a string to lower case, using simple case
697-- | /O(n)/ Convert a string to lower case, using simple case
747-- conversion. Subject to fusion.
698-- conversion. Subject to fusion.
@@ -901,7 +852,6 @@ concat ts = case ts' of
902 ts' = L.filter (not . null) ts
853 ts' = L.filter (not . null) ts
903 len = sumP "concat" $ L.map lengthWord16 ts'
854 len = sumP "concat" $ L.map lengthWord16 ts'
904− go :: ST s (A.MArray s)
906 arr <- A.new len
856 arr <- A.new len
907 let step i (Text a o l) =
857 let step i (Text a o l) =
@@ -915,13 +865,13 @@ concatMap f = concat . foldr ((:) . f) []
915{-# INLINE concatMap #-}
865{-# INLINE concatMap #-}
917-- | /O(n)/ 'any' @p@ @t@ determines whether any character in the
867-- | /O(n)/ 'any' @p@ @t@ determines whether any character in the
918−-- 'Text' @t@ satisfies the predicate @p@. Subject to fusion.
868+-- 'Text' @t@ satisifes the predicate @p@. Subject to fusion.
919any :: (Char -> Bool) -> Text -> Bool
869any :: (Char -> Bool) -> Text -> Bool
920any p t = S.any p (stream t)
870any p t = S.any p (stream t)
921{-# INLINE any #-}
871{-# INLINE any #-}
923-- | /O(n)/ 'all' @p@ @t@ determines whether all characters in the
873-- | /O(n)/ 'all' @p@ @t@ determines whether all characters in the
924−-- 'Text' @t@ satisfy the predicate @p@. Subject to fusion.
874+-- 'Text' @t@ satisify the predicate @p@. Subject to fusion.
925all :: (Char -> Bool) -> Text -> Bool
875all :: (Char -> Bool) -> Text -> Bool
926all p t = S.all p (stream t)
876all p t = S.all p (stream t)
927{-# INLINE all #-}
877{-# INLINE all #-}
@@ -1015,7 +965,6 @@ replicate n t@(Text a o l)
1015 | otherwise = Text (A.run x) 0 len
965 | otherwise = Text (A.run x) 0 len
1017 len = l `mul` n
967 len = l `mul` n
1018− x :: ST s (A.MArray s)
1020 arr <- A.new len
969 arr <- A.new len
1021 let loop !d !i | i >= n = return arr
970 let loop !d !i | i >= n = return arr
@@ -1152,27 +1101,6 @@ takeWhile p t@(Text arr off len) = loop 0
1152 unstream (S.takeWhile p (stream t)) = takeWhile p t
1101 unstream (S.takeWhile p (stream t)) = takeWhile p t
1155−-- | /O(n)/ 'takeWhileEnd', applied to a predicate @p@ and a 'Text',
1156−-- returns the longest suffix (possibly empty) of elements that
1157−-- satisfy @p@. Subject to fusion.
1160−-- > takeWhileEnd (=='o') "foo" == "oo"
1161−takeWhileEnd :: (Char -> Bool) -> Text -> Text
1162−takeWhileEnd p t@(Text arr off len) = loop (len-1) len
1163− where loop !i !l | l <= 0 = t
1164− | p c = loop (i+d) (l+d)
1165− | otherwise = text arr (off+l) (len-l)
1166− where (c,d) = reverseIter t i
1167−{-# INLINE [1] takeWhileEnd #-}
1170−"TEXT takeWhileEnd -> fused" [~1] forall p t.
1171− takeWhileEnd p t = S.reverse (S.takeWhile p (S.reverseStream t))
1172−"TEXT takeWhileEnd -> unfused" [1] forall p t.
1173− S.reverse (S.takeWhile p (S.reverseStream t)) = takeWhileEnd p t
1176-- | /O(n)/ 'dropWhile' @p@ @t@ returns the suffix remaining after
1104-- | /O(n)/ 'dropWhile' @p@ @t@ returns the suffix remaining after
1177-- 'takeWhile' @p@ @t@. Subject to fusion.
1105-- 'takeWhile' @p@ @t@. Subject to fusion.
1178dropWhile :: (Char -> Bool) -> Text -> Text
1106dropWhile :: (Char -> Bool) -> Text -> Text
@@ -1191,9 +1119,8 @@ dropWhile p t@(Text arr off len) = loop 0 0
1193-- | /O(n)/ 'dropWhileEnd' @p@ @t@ returns the prefix remaining after
1121-- | /O(n)/ 'dropWhileEnd' @p@ @t@ returns the prefix remaining after
1194−-- dropping characters that satisfy the predicate @p@ from the end of
1122+-- dropping characters that fail the predicate @p@ from the end of
1195-- @t@. Subject to fusion.
1123-- @t@. Subject to fusion.
1197-- Examples:
1124-- Examples:
1199-- > dropWhileEnd (=='.') "foo..." == "foo"
1126-- > dropWhileEnd (=='.') "foo..." == "foo"
@@ -1213,7 +1140,7 @@ dropWhileEnd p t@(Text arr off len) = loop (len-1) len
1215-- | /O(n)/ 'dropAround' @p@ @t@ returns the substring remaining after
1142-- | /O(n)/ 'dropAround' @p@ @t@ returns the substring remaining after
1216−-- dropping characters that satisfy the predicate @p@ from both the
1143+-- dropping characters that fail the predicate @p@ from both the
1217-- beginning and end of @t@. Subject to fusion.
1144-- beginning and end of @t@. Subject to fusion.
1218dropAround :: (Char -> Bool) -> Text -> Text
1145dropAround :: (Char -> Bool) -> Text -> Text
1219dropAround p = dropWhile p . dropWhileEnd p
1146dropAround p = dropWhile p . dropWhileEnd p
@@ -1308,9 +1235,9 @@ tails t | null t = [empty]
1308-- copies to create substrings; they just construct new 'Text's that
1235-- copies to create substrings; they just construct new 'Text's that
1309-- are slices of the original.
1236-- are slices of the original.
1311−-- | /O(m+n)/ Break a 'Text' into pieces separated by the first 'Text'
1238+-- | /O(m+n)/ Break a 'Text' into pieces separated by the first
1312−-- argument (which cannot be empty), consuming the delimiter. An empty
1239+-- 'Text' argument, consuming the delimiter. An empty delimiter is
1313−-- delimiter is invalid, and will cause an error to be raised.
1240+-- invalid, and will cause an error to be raised.
1315-- Examples:
1242-- Examples:
@@ -1323,16 +1250,9 @@ tails t | null t = [empty]
1323-- > intercalate s . splitOn s == id
1250-- > intercalate s . splitOn s == id
1324-- > splitOn (singleton c) == split (==c)
1251-- > splitOn (singleton c) == split (==c)
1326−-- (Note: the string @s@ to split on above cannot be empty.)
1328-- In (unlikely) bad cases, this function's time complexity degrades
1253-- In (unlikely) bad cases, this function's time complexity degrades
1329-- towards /O(n*m)/.
1254-- towards /O(n*m)/.
1330−splitOn :: Text
1255+splitOn :: Text -> Text -> [Text]
1331− -- ^ String to split on. If this string is empty, an error
1336splitOn pat@(Text _ _ l) src@(Text arr off len)
1256splitOn pat@(Text _ _ l) src@(Text arr off len)
1337 | l <= 0 = emptyError "splitOn"
1257 | l <= 0 = emptyError "splitOn"
1338 | isSingleton pat = split (== unsafeHead pat) src
1258 | isSingleton pat = split (== unsafeHead pat) src
@@ -1540,7 +1460,7 @@ countChar c t = S.countChar c (stream t)
1540-- equivalent to a pair of 'unpack' operations.
1460-- equivalent to a pair of 'unpack' operations.
1541zip :: Text -> Text -> [(Char,Char)]
1461zip :: Text -> Text -> [(Char,Char)]
1542zip a b = S.unstreamList $ S.zipWith (,) (stream a) (stream b)
1462zip a b = S.unstreamList $ S.zipWith (,) (stream a) (stream b)
1543−{-# INLINE zip #-}
1463+{-# INLINE [0] zip #-}
1545-- | /O(n)/ 'zipWith' generalises 'zip' by zipping with the function
1465-- | /O(n)/ 'zipWith' generalises 'zip' by zipping with the function
1546-- given as the first argument, instead of a tupling function.
1466-- given as the first argument, instead of a tupling function.
@@ -1548,7 +1468,7 @@ zip a b = S.unstreamList $ S.zipWith (,) (stream a) (stream b)
1548zipWith :: (Char -> Char -> Char) -> Text -> Text -> Text
1468zipWith :: (Char -> Char -> Char) -> Text -> Text -> Text
1549zipWith f t1 t2 = unstream (S.zipWith g (stream t1) (stream t2))
1469zipWith f t1 t2 = unstream (S.zipWith g (stream t1) (stream t2))
1550 where g a b = safe (f a b)
1470 where g a b = safe (f a b)
1551−{-# INLINE zipWith #-}
1471+{-# INLINE [0] zipWith #-}
1553-- | /O(n)/ Breaks a 'Text' up into a list of words, delimited by 'Char's
1473-- | /O(n)/ Breaks a 'Text' up into a list of words, delimited by 'Char's
1554-- representing white space.
1474-- representing white space.
@@ -1748,7 +1668,6 @@ overflowError fun = P.error $ "Data.Text." ++ fun ++ ": size overflow"
1748copy :: Text -> Text
1668copy :: Text -> Text
1749copy (Text arr off len) = Text (A.run go) 0 len
1669copy (Text arr off len) = Text (A.run go) 0 len
1751− go :: ST s (A.MArray s)
1753 marr <- A.new len
1672 marr <- A.new len
1754 A.copyI marr 0 arr off len
1673 A.copyI marr 0 arr off len