@@ -15,6 +15,7 @@
16-- License : BSD-style
16-- License : BSD-style
17-- Maintainer : bos@serpentine.com
17-- Maintainer : bos@serpentine.com
18+-- Stability : experimental
18-- Portability : GHC
19-- Portability : GHC
20-- A time and space-efficient implementation of Unicode text.
21-- A time and space-efficient implementation of Unicode text.
@@ -31,9 +32,8 @@
32-- To use an extended and very rich family of functions for working
33-- To use an extended and very rich family of functions for working
33-- with Unicode text (including normalization, regular expressions,
34-- with Unicode text (including normalization, regular expressions,
34−-- non-standard encodings, text breaking, and locales), see the
35+-- non-standard encodings, text breaking, and locales), see
35−-- <http://hackage.haskell.org/package/text-icu text-icu package >.
36+-- <http://hackage.haskell.org/package/text-icu the text-icu package >.
38module Data.Text
38module Data.Text
@@ -43,9 +43,6 @@ module Data.Text
43 -- * Acceptable data
43 -- * Acceptable data
44 -- $replacement
44 -- $replacement
46− -- * Definition of character
47− -- $character_definition
49 -- * Fusion
46 -- * Fusion
50 -- $fusion
47 -- $fusion
@@ -63,7 +60,6 @@ module Data.Text
@@ -250,18 +246,6 @@ import qualified GHC.Exts as Exts
250import Text.Printf (PrintfArg, formatArg, formatString)
246import Text.Printf (PrintfArg, formatArg, formatString)
253−-- $character_definition
255−-- This package uses the term /character/ to denote Unicode /code points/.
257−-- Note that this is not the same thing as a grapheme (e.g. a
258−-- composition of code points that form one visual symbol). For
259−-- instance, consider the grapheme \"ä\". This symbol has two
260−-- Unicode representations: a single code-point representation
261−-- @U+00E4@ (the @LATIN SMALL LETTER A WITH DIAERESIS@ code point),
262−-- and a two code point representation @U+0061@ (the \"@A@\" code
263−-- point) and @U+0308@ (the @COMBINING DIAERESIS@ code point).
265-- $strict
249-- $strict
267-- This package provides both strict and lazy 'Text' types. The
251-- This package provides both strict and lazy 'Text' types. The
@@ -350,13 +334,9 @@ instance Read Text where
350 readsPrec p str = [(pack x,y) | (x,y) <- readsPrec p str]
334 readsPrec p str = [(pack x,y) | (x,y) <- readsPrec p str]
352#if MIN_VERSION_base(4,9,0)
336#if MIN_VERSION_base(4,9,0)
353−-- | Non-orphan 'Semigroup' instance only defined for
354−-- @base-4.9.0.0@ and later; orphan instances for older GHCs are
337+-- Semigroup orphan instances for older GHCs are provided by
356−-- the [semigroups](http://hackage.haskell.org/package/semigroups)
357−-- package
338+-- 'semigroups` package
360instance Semigroup Text where
340instance Semigroup Text where
361 (<>) = append
341 (<>) = append
@@ -374,7 +354,6 @@ instance IsString Text where
374 fromString = pack
354 fromString = pack
376#if __GLASGOW_HASKELL__ >= 708
356#if __GLASGOW_HASKELL__ >= 708
378instance Exts.IsList Text where
357instance Exts.IsList Text where
379 type Item Text = Char
358 type Item Text = Char
380 fromList = pack
359 fromList = pack
@@ -385,7 +364,6 @@ instance Exts.IsList Text where
385instance NFData Text where rnf !_ = ()
364instance NFData Text where rnf !_ = ()
389instance Binary Text where
367instance Binary Text where
390 put t = put (encodeUtf8 t)
368 put t = put (encodeUtf8 t)
@@ -419,8 +397,6 @@ instance Data Text where
420#if MIN_VERSION_base(4,7,0)
398#if MIN_VERSION_base(4,7,0)
421-- | Only defined for @base-4.7.0.0@ and later
399-- | Only defined for @base-4.7.0.0@ and later
424instance PrintfArg Text where
400instance PrintfArg Text where
425 formatArg txt = formatString $ unpack txt
401 formatArg txt = formatString $ unpack txt
@@ -569,19 +545,6 @@ init (Text arr off len) | len <= 0 = emptyError "init"
569 unstream (S.init (stream t)) = init t
545 unstream (S.init (stream t)) = init t
572−-- | /O(1)/ Returns all but the last character and the last character of a
573−-- 'Text', or 'Nothing' if empty.
576−unsnoc :: Text -> Maybe (Text, Char)
577−unsnoc (Text arr off len)
578− | len <= 0 = Nothing
579− | n < 0xDC00 || n > 0xDFFF = Just (text arr off (len-1), unsafeChr n)
580− | otherwise = Just (text arr off (len-2), U16.chr2 n0 n)
581− where n = A.unsafeIndex arr (off+len-1)
582− n0 = A.unsafeIndex arr (off+len-2)
583−{-# INLINE [1] unsnoc #-}
585-- | /O(1)/ Tests whether a 'Text' is empty or not. Subject to
548-- | /O(1)/ Tests whether a 'Text' is empty or not. Subject to
586-- fusion.
549-- fusion.
587null :: Text -> Bool
550null :: Text -> Bool
@@ -661,15 +624,8 @@ compareLength t n = S.compareLengthI (stream t) n
661-- -----------------------------------------------------------------------------
624-- -----------------------------------------------------------------------------
662-- * Transformations
625-- * Transformations
663-- | /O(n)/ 'map' @f@ @t@ is the 'Text' obtained by applying @f@ to
626-- | /O(n)/ 'map' @f@ @t@ is the 'Text' obtained by applying @f@ to
664−-- each element of @t@.
668−-- >>> let message = pack "I am not angry. Not at all."
669−-- >>> T.map (\c -> if c == '.' then '!' else c) message
670−-- "I am not angry! Not at all!"
672−-- Subject to fusion. Performs replacement on invalid scalar values.
627+-- each element of @t@. Subject to fusion. Performs replacement on
628+-- invalid scalar values.
673map :: (Char -> Char) -> Text -> Text
629map :: (Char -> Char) -> Text -> Text
674map f t = unstream (S.map (safe . f) (stream t))
630map f t = unstream (S.map (safe . f) (stream t))
675{-# INLINE [1] map #-}
631{-# INLINE [1] map #-}
@@ -677,36 +633,18 @@ map f t = unstream (S.map (safe . f) (stream t))
677-- | /O(n)/ The 'intercalate' function takes a 'Text' and a list of
633-- | /O(n)/ The 'intercalate' function takes a 'Text' and a list of
678-- 'Text's and concatenates the list after interspersing the first
634-- 'Text's and concatenates the list after interspersing the first
679-- argument between each element of the list.
635-- argument between each element of the list.
683−-- >>> T.intercalate "NI!" ["We", "seek", "the", "Holy", "Grail"]
684−-- "WeNI!seekNI!theNI!HolyNI!Grail"
685intercalate :: Text -> [Text] -> Text
636intercalate :: Text -> [Text] -> Text
686intercalate t = concat . (F.intersperse t)
637intercalate t = concat . (F.intersperse t)
687{-# INLINE intercalate #-}
638{-# INLINE intercalate #-}
689-- | /O(n)/ The 'intersperse' function takes a character and places it
640-- | /O(n)/ The 'intersperse' function takes a character and places it
690−-- between the characters of a 'Text'.
641+-- between the characters of a 'Text'. Subject to fusion. Performs
694−-- >>> T.intersperse '.' "SHIELD"
697−-- Subject to fusion. Performs replacement on invalid scalar values.
642+-- replacement on invalid scalar values.
698intersperse :: Char -> Text -> Text
643intersperse :: Char -> Text -> Text
699intersperse c t = unstream (S.intersperse (safe c) (stream t))
644intersperse c t = unstream (S.intersperse (safe c) (stream t))
700{-# INLINE intersperse #-}
645{-# INLINE intersperse #-}
702−-- | /O(n)/ Reverse the characters of a string.
647+-- | /O(n)/ Reverse the characters of a string. Subject to fusion.
706−-- >>> T.reverse "desrever"
709−-- Subject to fusion.
710reverse :: Text -> Text
648reverse :: Text -> Text
711reverse t = S.reverse (stream t)
649reverse t = S.reverse (stream t)
712{-# INLINE reverse #-}
650{-# INLINE reverse #-}
@@ -725,14 +663,12 @@ reverse t = S.reverse (stream t)
725-- @needle@ occurs in @replacement@, that occurrence will /not/ itself
663-- @needle@ occurs in @replacement@, that occurrence will /not/ itself
726-- be replaced recursively:
664-- be replaced recursively:
728−-- >>> replace "oo" "foo" "oo"
666+-- > replace "oo" "foo" "oo" == "foo"
731-- In cases where several instances of @needle@ overlap, only the
668-- In cases where several instances of @needle@ overlap, only the
732-- first one will be replaced:
669-- first one will be replaced:
734−-- >>> replace "ofo" "bar" "ofofo"
671+-- > replace "ofo" "bar" "ofofo" == "barfo"
737-- In (unlikely) bad cases, this function's time complexity degrades
673-- In (unlikely) bad cases, this function's time complexity degrades
738-- towards /O(n*m)/.
674-- towards /O(n*m)/.
@@ -846,8 +782,6 @@ toUpper t = unstream (S.toUpper (stream t))
846-- guides disagree on whether the book name \"The Hill of the Red
782-- guides disagree on whether the book name \"The Hill of the Red
847-- Fox\" is correctly title cased—but this function will
783-- Fox\" is correctly title cased—but this function will
848-- capitalize /every/ word.
784-- capitalize /every/ word.
851toTitle :: Text -> Text
785toTitle :: Text -> Text
852toTitle t = unstream (S.toTitle (stream t))
786toTitle t = unstream (S.toTitle (stream t))
853{-# INLINE toTitle #-}
787{-# INLINE toTitle #-}
@@ -858,11 +792,8 @@ toTitle t = unstream (S.toTitle (stream t))
859-- Examples:
793-- Examples:
861−-- >>> justifyLeft 7 'x' "foo"
795+-- > justifyLeft 7 'x' "foo" == "fooxxxx"
864−-- >>> justifyLeft 3 'x' "foobar"
796+-- > justifyLeft 3 'x' "foobar" == "foobar"
866justifyLeft :: Int -> Char -> Text -> Text
797justifyLeft :: Int -> Char -> Text -> Text
867justifyLeft k c t
798justifyLeft k c t
868 | len >= k = t
799 | len >= k = t
@@ -883,11 +814,8 @@ justifyLeft k c t
884-- Examples:
815-- Examples:
886−-- >>> justifyRight 7 'x' "bar"
817+-- > justifyRight 7 'x' "bar" == "xxxxbar"
889−-- >>> justifyRight 3 'x' "foobar"
818+-- > justifyRight 3 'x' "foobar" == "foobar"
891justifyRight :: Int -> Char -> Text -> Text
819justifyRight :: Int -> Char -> Text -> Text
892justifyRight k c t
820justifyRight k c t
893 | len >= k = t
821 | len >= k = t
@@ -901,8 +829,7 @@ justifyRight k c t
902-- Examples:
830-- Examples:
904−-- >>> center 8 'x' "HS"
832+-- > center 8 'x' "HS" = "xxxHSxxx"
906center :: Int -> Char -> Text -> Text
833center :: Int -> Char -> Text -> Text
907center k c t
834center k c t
908 | len >= k = t
835 | len >= k = t
@@ -917,14 +844,6 @@ center k c t
917-- of its 'Text' argument. Note that this function uses 'pack',
844-- of its 'Text' argument. Note that this function uses 'pack',
918-- 'unpack', and the list version of transpose, and is thus not very
845-- 'unpack', and the list version of transpose, and is thus not very
919-- efficient.
846-- efficient.
923−-- >>> transpose ["green","orange"]
924−-- ["go","rr","ea","en","ng","e"]
926−-- >>> transpose ["blue","red"]
927−-- ["br","le","ud","e"]
928transpose :: [Text] -> [Text]
847transpose :: [Text] -> [Text]
929transpose ts = P.map pack (L.transpose (P.map unpack ts))
848transpose ts = P.map pack (L.transpose (P.map unpack ts))
@@ -1169,10 +1088,7 @@ iterN n t@(Text _arr _off len) = loop 0 0
1170-- Examples:
1089-- Examples:
1172−-- >>> takeEnd 3 "foobar"
1091+-- > takeEnd 3 "foobar" == "bar"
1176takeEnd :: Int -> Text -> Text
1092takeEnd :: Int -> Text -> Text
1177takeEnd n t@(Text arr off len)
1093takeEnd n t@(Text arr off len)
1178 | n <= 0 = empty
1094 | n <= 0 = empty
@@ -1183,8 +1099,8 @@ takeEnd n t@(Text arr off len)
1183iterNEnd :: Int -> Text -> Int
1099iterNEnd :: Int -> Text -> Int
1184iterNEnd n t@(Text _arr _off len) = loop (len-1) n
1100iterNEnd n t@(Text _arr _off len) = loop (len-1) n
1185 where loop i !m
1101 where loop i !m
1187 | i <= 0 = 0
1102 | i <= 0 = 0
1188 | otherwise = loop (i+d) (m-1)
1104 | otherwise = loop (i+d) (m-1)
1189 where d = reverseIter_ t i
1105 where d = reverseIter_ t i
@@ -1211,10 +1127,7 @@ drop n t@(Text arr off len)
1212-- Examples:
1128-- Examples:
1214−-- >>> dropEnd 3 "foobar"
1130+-- > dropEnd 3 "foobar" == "foo"
1218dropEnd :: Int -> Text -> Text
1131dropEnd :: Int -> Text -> Text
1219dropEnd n t@(Text arr off len)
1132dropEnd n t@(Text arr off len)
1220 | n <= 0 = t
1133 | n <= 0 = t
@@ -1244,10 +1157,7 @@ takeWhile p t@(Text arr off len) = loop 0
1244-- satisfy @p@. Subject to fusion.
1157-- satisfy @p@. Subject to fusion.
1245-- Examples:
1158-- Examples:
1247−-- >>> takeWhileEnd (=='o') "foo"
1160+-- > takeWhileEnd (=='o') "foo" == "oo"
1251takeWhileEnd :: (Char -> Bool) -> Text -> Text
1161takeWhileEnd :: (Char -> Bool) -> Text -> Text
1252takeWhileEnd p t@(Text arr off len) = loop (len-1) len
1162takeWhileEnd p t@(Text arr off len) = loop (len-1) len
1253 where loop !i !l | l <= 0 = t
1163 where loop !i !l | l <= 0 = t
@@ -1286,8 +1196,7 @@ dropWhile p t@(Text arr off len) = loop 0 0
1287-- Examples:
1197-- Examples:
1289−-- >>> dropWhileEnd (=='.') "foo..."
1199+-- > dropWhileEnd (=='.') "foo..." == "foo"
1291dropWhileEnd :: (Char -> Bool) -> Text -> Text
1200dropWhileEnd :: (Char -> Bool) -> Text -> Text
1292dropWhileEnd p t@(Text arr off len) = loop (len-1) len
1201dropWhileEnd p t@(Text arr off len) = loop (len-1) len
1293 where loop !i !l | l <= 0 = empty
1202 where loop !i !l | l <= 0 = empty
@@ -1405,14 +1314,9 @@ tails t | null t = [empty]
1406-- Examples:
1315-- Examples:
1408−-- >>> splitOn "\r\n" "a\r\nb\r\nd\r\ne"
1317+-- > splitOn "\r\n" "a\r\nb\r\nd\r\ne" == ["a","b","d","e"]
1409−-- ["a","b","d","e"]
1411−-- >>> splitOn "aaa" "aaaXaaaXaaaXaaa"
1318+-- > splitOn "aaa" "aaaXaaaXaaaXaaa" == ["","X","X","X",""]
1412−-- ["","X","X","X",""]
1414−-- >>> splitOn "x" "x"
1319+-- > splitOn "x" "x" == ["",""]
@@ -1448,11 +1352,8 @@ splitOn pat@(Text _ _ l) src@(Text arr off len)
1448-- resulting components do not contain the separators. Two adjacent
1352-- resulting components do not contain the separators. Two adjacent
1449-- separators result in an empty component in the output. eg.
1353-- separators result in an empty component in the output. eg.
1451−-- >>> split (=='a') "aabbaca"
1355+-- > split (=='a') "aabbaca" == ["","","bb","c",""]
1452−-- ["","","bb","c",""]
1454−-- >>> split (=='a') ""
1356+-- > split (=='a') "" == [""]
1456split :: (Char -> Bool) -> Text -> [Text]
1357split :: (Char -> Bool) -> Text -> [Text]
1457split _ t@(Text _off _arr 0) = [t]
1358split _ t@(Text _off _arr 0) = [t]
1458split p t = loop t
1359split p t = loop t
@@ -1465,11 +1366,8 @@ split p t = loop t
1465-- element may be shorter than the other chunks, depending on the
1366-- element may be shorter than the other chunks, depending on the
1466-- length of the input. Examples:
1367-- length of the input. Examples:
1468−-- >>> chunksOf 3 "foobarbaz"
1369+-- > chunksOf 3 "foobarbaz" == ["foo","bar","baz"]
1469−-- ["foo","bar","baz"]
1471−-- >>> chunksOf 4 "haskell.org"
1370+-- > chunksOf 4 "haskell.org" == ["hask","ell.","org"]
1472−-- ["hask","ell.","org"]
1473chunksOf :: Int -> Text -> [Text]
1371chunksOf :: Int -> Text -> [Text]
1474chunksOf k = go
1372chunksOf k = go
@@ -1514,11 +1412,8 @@ filter p t = unstream (S.filter p (stream t))
1515-- Examples:
1413-- Examples:
1517−-- >>> breakOn "::" "a::b::c"
1415+-- > breakOn "::" "a::b::c" ==> ("a", "::b::c")
1520−-- >>> breakOn "/" "foobar"
1416+-- > breakOn "/" "foobar" ==> ("foobar", "")
@@ -1546,8 +1441,7 @@ breakOn pat src@(Text arr off len)
1546-- up to and including the last match of @needle@. The second is the
1441-- up to and including the last match of @needle@. The second is the
1547-- remainder of @haystack@, following the match.
1442-- remainder of @haystack@, following the match.
1549−-- >>> breakOnEnd "::" "a::b::c"
1444+-- > breakOnEnd "::" "a::b::c" ==> ("a::b::", "c")
1551breakOnEnd :: Text -> Text -> (Text, Text)
1445breakOnEnd :: Text -> Text -> (Text, Text)
1552breakOnEnd pat src = (reverse b, reverse a)
1446breakOnEnd pat src = (reverse b, reverse a)
1553 where (a,b) = breakOn (reverse pat) (reverse src)
1447 where (a,b) = breakOn (reverse pat) (reverse src)
@@ -1562,11 +1456,10 @@ breakOnEnd pat src = (reverse b, reverse a)
1563-- Examples:
1457-- Examples:
1565−-- >>> breakOnAll "::" ""
1459+-- > breakOnAll "::" ""
1566−-- []
1460+-- > ==> []
1568−-- >>> breakOnAll "/" "a/b/c/"
1461+-- > breakOnAll "/" "a/b/c/"
1569−-- [("a","/b/c/"),("a/b","/c/"),("a/b/c","/")]
1462+-- > ==> [("a", "/b/c/"), ("a/b", "/c/"), ("a/b/c", "/")]
1571-- In (unlikely) bad cases, this function's time complexity degrades
1464-- In (unlikely) bad cases, this function's time complexity degrades
1572-- towards /O(n*m)/.
1465-- towards /O(n*m)/.
@@ -1765,14 +1658,9 @@ isInfixOf needle haystack
1766-- Examples:
1659-- Examples:
1768−-- >>> stripPrefix "foo" "foobar"
1661+-- > stripPrefix "foo" "foobar" == Just "bar"
1771−-- >>> stripPrefix "" "baz"
1662+-- > stripPrefix "" "baz" == Just "baz"
1774−-- >>> stripPrefix "foo" "quux"
1663+-- > stripPrefix "foo" "quux" == Nothing
1777-- This is particularly useful with the @ViewPatterns@ extension to
1665-- This is particularly useful with the @ViewPatterns@ extension to
1778-- GHC, as follows:
1666-- GHC, as follows:
@@ -1797,14 +1685,9 @@ stripPrefix p@(Text _arr _off plen) t@(Text arr off len)
1798-- Examples:
1686-- Examples:
1800−-- >>> commonPrefixes "foobar" "fooquux"
1688+-- > commonPrefixes "foobar" "fooquux" == Just ("foo","bar","quux")
1801−-- Just ("foo","bar","quux")
1803−-- >>> commonPrefixes "veeble" "fetzer"
1689+-- > commonPrefixes "veeble" "fetzer" == Nothing
1806−-- >>> commonPrefixes "" "baz"
1690+-- > commonPrefixes "" "baz" == Nothing
1808commonPrefixes :: Text -> Text -> Maybe (Text,Text,Text)
1691commonPrefixes :: Text -> Text -> Maybe (Text,Text,Text)
1809commonPrefixes t0@(Text arr0 off0 len0) t1@(Text arr1 off1 len1) = go 0 0
1692commonPrefixes t0@(Text arr0 off0 len0) t1@(Text arr1 off1 len1) = go 0 0
@@ -1821,14 +1704,9 @@ commonPrefixes t0@(Text arr0 off0 len0) t1@(Text arr1 off1 len1) = go 0 0
1822-- Examples:
1705-- Examples:
1824−-- >>> stripSuffix "bar" "foobar"
1707+-- > stripSuffix "bar" "foobar" == Just "foo"
1827−-- >>> stripSuffix "" "baz"
1708+-- > stripSuffix "" "baz" == Just "baz"
1830−-- >>> stripSuffix "foo" "quux"
1709+-- > stripSuffix "foo" "quux" == Nothing
1833-- This is particularly useful with the @ViewPatterns@ extension to
1711-- This is particularly useful with the @ViewPatterns@ extension to
1834-- GHC, as follows:
1712-- GHC, as follows:
@@ -1875,12 +1753,3 @@ copy (Text arr off len) = Text (A.run go) 0 len
1875 marr <- A.new len
1753 marr <- A.new len
1876 A.copyI marr 0 arr off len
1754 A.copyI marr 0 arr off len
1877 return marr
1755 return marr
1880−-------------------------------------------------
1881−-- NOTE: the named chunk below used by doctest;
1882−-- verify the doctests via `doctest -fobject-code Data/Text.hs`
1885−-- >>> :set -XOverloadedStrings
1886−-- >>> import qualified Data.Text as T