on master help sign in
Merge branch 'master' into text-jsstring
commite949bdad6bff1f2f1fe393f5fa2624f4b01ea68b authorMatthew Bauer <mjbauer95@gmail.com> dateMon 18 Jun 2018, 12:20 (8 years ago) parentd1253ab9fac5db
38 files changed+1136−237
.gitignore+10−3 .hgtags+1 .travis.yml+111 Data/Text.hs+174−45 Data/Text/Array.hs+4−1 Data/Text/Encoding.hs+67−11 Data/Text/Encoding/Error.hs−1 Data/Text/Foreign.hs+5−2 Data/Text/IO.hs+4−1 Data/Text/Internal/Fusion/CaseMapping.hs+164−4 Data/Text/Internal/Fusion/Size.hs+33−7 Data/Text/Internal/Fusion/Types.hs+4−4 Data/Text/Lazy.hs+54−20 Data/Text/Lazy/Builder.hs−1 Data/Text/Lazy/Builder/Int.hs+46−2 Data/Text/Lazy/Builder/RealFloat.hs+3 Data/Text/Lazy/Encoding.hs+13−3 Data/Text/Lazy/IO.hs−1 Data/Text/Lazy/Read.hs+3−4 Data/Text/Read.hs+3−4 Data/Text/Show.hs+2 Data/Text/Unsafe.hs+2−1 README.markdown+5−16 benchmarks/.gitignore+4−1 benchmarks/cabal.project+2 benchmarks/haskell/Benchmarks.hs+2 benchmarks/haskell/Benchmarks/Concat.hs+25 benchmarks/text-benchmarks.cabal+82−8 cabal.project+3 cbits/cbits.c+6−11 changelog.md+61−19 tests-and-benchmarks.markdown+13−8 tests/Makefile+6−1 tests/Tests/Properties.hs+94−21 tests/Tests/QuickCheckUtils.hs+1−1 tests/Tests/Regressions.hs+11 tests/text-tests.cabal+18−3 text.cabal+100−33
.gitignore+10−3
@@ -1,3 +1,10 @@
1−dist
2−cabal-dev
3−cabal.sandbox.config
1+/dist/
2+/dist-boot/
3+/dist-install/
4+/dist-newstyle/
5+/cabal-dev/
6+/cabal.sandbox.config
7+/ghc.mk
8+/GNUmakefile
9+/.ghc.environment.*
10+/cabal.project.local
.hgtags+1
@@ -64,3 +64,4 @@ f8a60279237c1c28e094868740d9188dd94fcc9e 1.2.0.0
6464631fd055e27fa10983e17e9ad36d1b285b85c661 1.2.1.3
65658221a68ed5ec37028357df9c6c25f52320e54ad9 1.2.2.0
6666ce1c5ac65eb9f5580114b4e380092b05a485e95d 1.2.2.1
67+d72c634a91ffe27ec5cd03921dd53efc8129d8f6 1.2.2.2
.travis.ymlnew file+111
@@ -0,0 +1,111 @@
1+# This Travis job script has been generated by a script via
2+#
3+# make_travis_yml_2.hs '-o' '.travis.yml' 'text.cabal'
4+#
5+# For more information, see https://github.com/hvr/multi-ghc-travis
6+#
7+language: c
8+sudo: false
9+
10+# Bryan threatens to turn off Travis-CI if he gets any email :-)
11+notifications:
12+ email: false
13+
14+cache:
15+ directories:
16+ - $HOME/.cabal/packages
17+ - $HOME/.cabal/store
18+
19+before_cache:
20+ - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log
21+ # remove files that are regenerated by 'cabal update'
22+ - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.*
23+ - rm -fv $HOME/.cabal/packages/hackage.haskell.org/*.json
24+ - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.cache
25+ - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.tar
26+ - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.tar.idx
27+
28+matrix:
29+ include:
30+ - compiler: "ghc-7.0.4"
31+ # env: TEST=--disable-tests BENCH=--disable-benchmarks
32+ addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-7.0.4], sources: [hvr-ghc]}}
33+ - compiler: "ghc-7.2.2"
34+ # env: TEST=--disable-tests BENCH=--disable-benchmarks
35+ addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-7.2.2], sources: [hvr-ghc]}}
36+ - compiler: "ghc-7.4.2"
37+ # env: TEST=--disable-tests BENCH=--disable-benchmarks
38+ addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-7.4.2], sources: [hvr-ghc]}}
39+ - compiler: "ghc-7.6.3"
40+ # env: TEST=--disable-tests BENCH=--disable-benchmarks
41+ addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-7.6.3], sources: [hvr-ghc]}}
42+ - compiler: "ghc-7.8.4"
43+ # env: TEST=--disable-tests BENCH=--disable-benchmarks
44+ addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-7.8.4], sources: [hvr-ghc]}}
45+ - compiler: "ghc-7.10.3"
46+ # env: TEST=--disable-tests BENCH=--disable-benchmarks
47+ addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-7.10.3], sources: [hvr-ghc]}}
48+ - compiler: "ghc-8.0.2"
49+ # env: TEST=--disable-tests BENCH=--disable-benchmarks
50+ addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-8.0.2], sources: [hvr-ghc]}}
51+ - compiler: "ghc-8.2.2"
52+ # env: TEST=--disable-tests BENCH=--disable-benchmarks
53+ addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-8.2.2], sources: [hvr-ghc]}}
54+
55+before_install:
56+ - HC=${CC}
57+ - HCPKG=${HC/ghc/ghc-pkg}
58+ - unset CC
59+ - PATH=/opt/ghc/bin:/opt/ghc-ppa-tools/bin:$PATH
60+ - PKGNAME='text'
61+
62+install:
63+ - cabal --version
64+ - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]"
65+ - BENCH=${BENCH---enable-benchmarks}
66+ - TEST=${TEST---enable-tests}
67+ - HADDOCK=${HADDOCK-true}
68+ - INSTALLED=${INSTALLED-true}
69+ - travis_retry cabal update -v
70+ - sed -i.bak 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config
71+ - rm -fv cabal.project.local
72+ - "echo 'packages: .' > cabal.project"
73+ - rm -f cabal.project.freeze
74+ - cabal new-build -w ${HC} ${TEST} ${BENCH} --dep -j2 all
75+ - cabal new-build -w ${HC} --disable-tests --disable-benchmarks --dep -j2 all
76+
77+# Here starts the actual work to be performed for the package under test;
78+# any command which exits with a non-zero exit code causes the build to fail.
79+script:
80+ - if [ -f configure.ac ]; then autoreconf -i; fi
81+ - rm -rf .ghc.environment.* dist/
82+ - cabal sdist # test that a source-distribution can be generated
83+ - cd dist/
84+ - SRCTAR=(${PKGNAME}-*.tar.gz)
85+ - SRC_BASENAME="${SRCTAR/%.tar.gz}"
86+ - tar -xvf "./$SRC_BASENAME.tar.gz"
87+ - cd "$SRC_BASENAME/"
88+## from here on, CWD is inside the extracted source-tarball
89+ - rm -fv cabal.project.local
90+ - "echo 'packages: .' > cabal.project"
91+ # this builds all libraries and executables (without tests/benchmarks)
92+ - rm -f cabal.project.freeze
93+ - cabal new-build -w ${HC} --disable-tests --disable-benchmarks all
94+ # this builds all libraries and executables (including tests/benchmarks)
95+ # - rm -rf ./dist-newstyle
96+
97+ # Build with installed constraints for packages in global-db
98+ - if $INSTALLED; then
99+ echo cabal new-build -w ${HC} --disable-tests --disable-benchmarks $(${HCPKG} list --global --simple-output --names-only | sed 's/\([a-zA-Z0-9-]\{1,\}\) */--constraint="\1 installed" /g') all | sh;
100+ else echo "Not building with installed constraints"; fi
101+
102+ # build & run tests, build benchmarks
103+ - cabal new-build -w ${HC} ${TEST} ${BENCH} all
104+ - if [ "x$TEST" = "x--enable-tests" ]; then cabal new-test -w ${HC} ${TEST} all; fi
105+
106+ # haddock
107+ - rm -rf ./dist-newstyle
108+ - if $HADDOCK; then cabal new-haddock -w ${HC} --disable-tests --disable-benchmarks all; else echo "Skipping haddock generation";fi
109+
110+# REGENDATA ["-o",".travis.yml","text.cabal"]
111+# EOF
Data/Text.hs+174−45
@@ -15,7 +15,6 @@
1515--
1616-- License : BSD-style
1717-- Maintainer : bos@serpentine.com
18−-- Stability : experimental
1918-- Portability : GHC
2019--
2120-- A time and space-efficient implementation of Unicode text.
@@ -32,8 +31,9 @@
3231--
3332-- To use an extended and very rich family of functions for working
3433-- with Unicode text (including normalization, regular expressions,
35−-- non-standard encodings, text breaking, and locales), see
36−-- <http://hackage.haskell.org/package/text-icu the text-icu package >.
34+-- non-standard encodings, text breaking, and locales), see the
35+-- <http://hackage.haskell.org/package/text-icu text-icu package >.
36+--
3737
3838module Data.Text
3939 (
@@ -43,6 +43,9 @@ module Data.Text
4343 -- * Acceptable data
4444 -- $replacement
4545
46+ -- * Definition of character
47+ -- $character_definition
48+
4649 -- * Fusion
4750 -- $fusion
4851
@@ -60,6 +63,7 @@ module Data.Text
6063 , snoc
6164 , append
6265 , uncons
66+ , unsnoc
6367 , head
6468 , last
6569 , tail
@@ -298,6 +302,17 @@ unpackCString# addr# = Text $ SJS.unstream (SJS.streamCString# addr#)
298302 = singleton a #-}
299303
300304---------------------------------------------------------------------
305+-- $character_definition
306+--
307+-- This package uses the term /character/ to denote Unicode /code points/.
308+--
309+-- Note that this is not the same thing as a grapheme (e.g. a
310+-- composition of code points that form one visual symbol). For
311+-- instance, consider the grapheme \"&#x00e4;\". This symbol has two
312+-- Unicode representations: a single code-point representation
313+-- @U+00E4@ (the @LATIN SMALL LETTER A WITH DIAERESIS@ code point),
314+-- and a two code point representation @U+0061@ (the \"@A@\" code
315+-- point) and @U+0308@ (the @COMBINING DIAERESIS@ code point).
301316
302317-- $strict
303318--
@@ -392,9 +407,13 @@ instance Read Text where
392407 readsPrec p str = [(pack x,y) | (x,y) <- readsPrec p str]
393408
394409#if MIN_VERSION_base(4,9,0)
395−-- Semigroup orphan instances for older GHCs are provided by
396−-- 'semigroups` package
397−
410+-- | Non-orphan 'Semigroup' instance only defined for
411+-- @base-4.9.0.0@ and later; orphan instances for older GHCs are
412+-- provided by
413+-- the [semigroups](http://hackage.haskell.org/package/semigroups)
414+-- package
415+--
416+-- @since 1.2.2.0
398417instance Semigroup Text where
399418 (<>) = append
400419#endif
@@ -412,6 +431,7 @@ instance IsString Text where
412431 fromString = pack
413432
414433#if __GLASGOW_HASKELL__ >= 708
434+-- | @since 1.2.0.0
415435instance Exts.IsList Text where
416436 type Item Text = Char
417437 fromList = pack
@@ -422,6 +442,7 @@ instance Exts.IsList Text where
422442instance NFData Text where rnf !_ = ()
423443#endif
424444
445+-- | @since 1.2.1.0
425446instance Binary Text where
426447 put t = put (encodeUtf8 t)
427448 get = do
@@ -455,6 +476,8 @@ instance Data Text where
455476
456477#if MIN_VERSION_base(4,7,0)
457478-- | Only defined for @base-4.7.0.0@ and later
479+--
480+-- @since 1.2.2.0
458481instance PrintfArg Text where
459482 formatArg t = formatString $ unpack t
460483#endif
@@ -612,6 +635,19 @@ init = coerce JSS.init
612635 unstream (S.init (stream t)) = init t
613636 #-}
614637
638+-- | /O(1)/ Returns all but the last character and the last character of a
639+-- 'Text', or 'Nothing' if empty.
640+--
641+-- @since 1.2.3.0
642+unsnoc :: Text -> Maybe (Text, Char)
643+unsnoc (Text arr off len)
644+ | len <= 0 = Nothing
645+ | n < 0xDC00 || n > 0xDFFF = Just (text arr off (len-1), unsafeChr n)
646+ | otherwise = Just (text arr off (len-2), U16.chr2 n0 n)
647+ where n = A.unsafeIndex arr (off+len-1)
648+ n0 = A.unsafeIndex arr (off+len-2)
649+{-# INLINE [1] unsnoc #-}
650+
615651-- | /O(1)/ Tests whether a 'Text' is empty or not. Subject to
616652-- fusion.
617653null :: Text -> Bool
@@ -693,8 +729,15 @@ compareLength t n = S.compareLengthI (stream t) n
693729-- -----------------------------------------------------------------------------
694730-- * Transformations
695731-- | /O(n)/ 'map' @f@ @t@ is the 'Text' obtained by applying @f@ to
696−-- each element of @t@. Subject to fusion. Performs replacement on
697−-- invalid scalar values.
732+-- each element of @t@.
733+--
734+-- Example:
735+--
736+-- >>> let message = pack "I am not angry. Not at all."
737+-- >>> T.map (\c -> if c == '.' then '!' else c) message
738+-- "I am not angry! Not at all!"
739+--
740+-- Subject to fusion. Performs replacement on invalid scalar values.
698741map :: (Char -> Char) -> Text -> Text
699742map = coerce JSS.map
700743-- map f t = unstream (S.map (safe . f) (stream t))
@@ -703,20 +746,38 @@ map = coerce JSS.map
703746-- | /O(n)/ The 'intercalate' function takes a 'Text' and a list of
704747-- 'Text's and concatenates the list after interspersing the first
705748-- argument between each element of the list.
749+--
750+-- Example:
751+--
752+-- >>> T.intercalate "NI!" ["We", "seek", "the", "Holy", "Grail"]
753+-- "WeNI!seekNI!theNI!HolyNI!Grail"
706754intercalate :: Text -> [Text] -> Text
707755intercalate = coerce JSS.intercalate
708756-- intercalate t = concat . (F.intersperse t)
709757{-# INLINE intercalate #-}
710758
711759-- | /O(n)/ The 'intersperse' function takes a character and places it
712−-- between the characters of a 'Text'. Subject to fusion. Performs
713−-- replacement on invalid scalar values.
760+-- between the characters of a 'Text'.
761+--
762+-- Example:
763+--
764+-- >>> T.intersperse '.' "SHIELD"
765+-- "S.H.I.E.L.D"
766+--
767+-- Subject to fusion. Performs replacement on invalid scalar values.
714768intersperse :: Char -> Text -> Text
715769intersperse = coerce JSS.intersperse
716770-- intersperse c t = unstream (S.intersperse (safe c) (stream t))
717771{-# INLINE intersperse #-}
718772
719−-- | /O(n)/ Reverse the characters of a string. Subject to fusion.
773+-- | /O(n)/ Reverse the characters of a string.
774+--
775+-- Example:
776+--
777+-- >>> T.reverse "desrever"
778+-- "reversed"
779+--
780+-- Subject to fusion.
720781reverse :: Text -> Text
721782reverse = coerce JSS.reverse
722783-- reverse t = S.reverse (stream t)
@@ -736,12 +797,14 @@ reverse = coerce JSS.reverse
736797-- @needle@ occurs in @replacement@, that occurrence will /not/ itself
737798-- be replaced recursively:
738799--
739−-- > replace "oo" "foo" "oo" == "foo"
800+-- >>> replace "oo" "foo" "oo"
801+-- "foo"
740802--
741803-- In cases where several instances of @needle@ overlap, only the
742804-- first one will be replaced:
743805--
744−-- > replace "ofo" "bar" "ofofo" == "barfo"
806+-- >>> replace "ofo" "bar" "ofofo"
807+-- "barfo"
745808--
746809-- In (unlikely) bad cases, this function's time complexity degrades
747810-- towards /O(n*m)/.
@@ -859,6 +922,8 @@ toUpper = coerce JSS.toUpper
859922-- guides disagree on whether the book name \"The Hill of the Red
860923-- Fox\" is correctly title cased&#x2014;but this function will
861924-- capitalize /every/ word.
925+--
926+-- @since 1.0.0.0
862927toTitle :: Text -> Text
863928toTitle = coerce JSS.toTitle
864929-- toTitle t = unstream (S.toTitle (stream t))
@@ -870,8 +935,11 @@ toTitle = coerce JSS.toTitle
870935--
871936-- Examples:
872937--
873−-- > justifyLeft 7 'x' "foo" == "fooxxxx"
874−-- > justifyLeft 3 'x' "foobar" == "foobar"
938+-- >>> justifyLeft 7 'x' "foo"
939+-- "fooxxxx"
940+--
941+-- >>> justifyLeft 3 'x' "foobar"
942+-- "foobar"
875943justifyLeft :: Int -> Char -> Text -> Text
876944justifyLeft = coerce JSS.justifyLeft
877945-- justifyLeft k c t
@@ -893,8 +961,11 @@ justifyLeft = coerce JSS.justifyLeft
893961--
894962-- Examples:
895963--
896−-- > justifyRight 7 'x' "bar" == "xxxxbar"
897−-- > justifyRight 3 'x' "foobar" == "foobar"
964+-- >>> justifyRight 7 'x' "bar"
965+-- "xxxxbar"
966+--
967+-- >>> justifyRight 3 'x' "foobar"
968+-- "foobar"
898969justifyRight :: Int -> Char -> Text -> Text
899970justifyRight = coerce JSS.justifyRight
900971-- justifyRight k c t
@@ -909,7 +980,8 @@ justifyRight = coerce JSS.justifyRight
909980--
910981-- Examples:
911982--
912−-- > center 8 'x' "HS" = "xxxHSxxx"
983+-- >>> center 8 'x' "HS"
984+-- "xxxHSxxx"
913985center :: Int -> Char -> Text -> Text
914986center = coerce JSS.center
915987-- center k c t
@@ -925,6 +997,14 @@ center = coerce JSS.center
925997-- of its 'Text' argument. Note that this function uses 'pack',
926998-- 'unpack', and the list version of transpose, and is thus not very
927999-- efficient.
1000+--
1001+-- Examples:
1002+--
1003+-- >>> transpose ["green","orange"]
1004+-- ["go","rr","ea","en","ng","e"]
1005+--
1006+-- >>> transpose ["blue","red"]
1007+-- ["br","le","ud","e"]
9281008transpose :: [Text] -> [Text]
9291009transpose = coerce JSS.transpose
9301010-- transpose ts = P.map pack (L.transpose (P.map unpack ts))
@@ -1207,7 +1287,10 @@ take = coerce JSS.take
12071287--
12081288-- Examples:
12091289--
1210−-- > takeEnd 3 "foobar" == "bar"
1290+-- >>> takeEnd 3 "foobar"
1291+-- "bar"
1292+--
1293+-- @since 1.1.1.0
12111294takeEnd :: Int -> Text -> Text
12121295takeEnd = coerce JSS.takeEnd
12131296-- takeEnd n t@(Text arr off len)
@@ -1248,7 +1331,10 @@ drop = coerce JSS.drop
12481331--
12491332-- Examples:
12501333--
1251−-- > dropEnd 3 "foobar" == "foo"
1334+-- >>> dropEnd 3 "foobar"
1335+-- "foo"
1336+--
1337+-- @since 1.1.1.0
12521338dropEnd :: Int -> Text -> Text
12531339dropEnd = coerce JSS.dropEnd
12541340-- dropEnd n t@(Text arr off len)
@@ -1280,7 +1366,10 @@ takeWhile = coerce JSS.takeWhile
12801366-- satisfy @p@. Subject to fusion.
12811367-- Examples:
12821368--
1283−-- > takeWhileEnd (=='o') "foo" == "oo"
1369+-- >>> takeWhileEnd (=='o') "foo"
1370+-- "oo"
1371+--
1372+-- @since 1.2.2.0
12841373takeWhileEnd :: (Char -> Bool) -> Text -> Text
12851374#ifndef __GHCJS__
12861375takeWhileEnd p t@(Text arr off len) = loop (len-1) len
@@ -1329,7 +1418,8 @@ dropWhile = coerce JSS.dropWhile
13291418--
13301419-- Examples:
13311420--
1332−-- > dropWhileEnd (=='.') "foo..." == "foo"
1421+-- >>> dropWhileEnd (=='.') "foo..."
1422+-- "foo"
13331423dropWhileEnd :: (Char -> Bool) -> Text -> Text
13341424dropWhileEnd = coerce JSS.dropWhileEnd
13351425-- dropWhileEnd p t@(Text arr off len) = loop (len-1) len
@@ -1454,9 +1544,14 @@ tails = coerce JSS.tails
14541544--
14551545-- Examples:
14561546--
1457−-- > splitOn "\r\n" "a\r\nb\r\nd\r\ne" == ["a","b","d","e"]
1458−-- > splitOn "aaa" "aaaXaaaXaaaXaaa" == ["","X","X","X",""]
1459−-- > splitOn "x" "x" == ["",""]
1547+-- >>> splitOn "\r\n" "a\r\nb\r\nd\r\ne"
1548+-- ["a","b","d","e"]
1549+--
1550+-- >>> splitOn "aaa" "aaaXaaaXaaaXaaa"
1551+-- ["","X","X","X",""]
1552+--
1553+-- >>> splitOn "x" "x"
1554+-- ["",""]
14601555--
14611556-- and
14621557--
@@ -1493,8 +1588,11 @@ splitOn = coerce JSS.splitOn
14931588-- resulting components do not contain the separators. Two adjacent
14941589-- separators result in an empty component in the output. eg.
14951590--
1496−-- > split (=='a') "aabbaca" == ["","","bb","c",""]
1497−-- > split (=='a') "" == [""]
1591+-- >>> split (=='a') "aabbaca"
1592+-- ["","","bb","c",""]
1593+--
1594+-- >>> split (=='a') ""
1595+-- [""]
14981596split :: (Char -> Bool) -> Text -> [Text]
14991597split = coerce JSS.split
15001598-- split _ t@(Text _off _arr 0) = [t]
@@ -1508,8 +1606,11 @@ split = coerce JSS.split
15081606-- element may be shorter than the other chunks, depending on the
15091607-- length of the input. Examples:
15101608--
1511−-- > chunksOf 3 "foobarbaz" == ["foo","bar","baz"]
1512−-- > chunksOf 4 "haskell.org" == ["hask","ell.","org"]
1609+-- >>> chunksOf 3 "foobarbaz"
1610+-- ["foo","bar","baz"]
1611+--
1612+-- >>> chunksOf 4 "haskell.org"
1613+-- ["hask","ell.","org"]
15131614chunksOf :: Int -> Text -> [Text]
15141615chunksOf = coerce JSS.chunksOf
15151616-- chunksOf k = go
@@ -1558,8 +1659,11 @@ filter = coerce JSS.filter
15581659--
15591660-- Examples:
15601661--
1561−-- > breakOn "::" "a::b::c" ==> ("a", "::b::c")
1562−-- > breakOn "/" "foobar" ==> ("foobar", "")
1662+-- >>> breakOn "::" "a::b::c"
1663+-- ("a","::b::c")
1664+--
1665+-- >>> breakOn "/" "foobar"
1666+-- ("foobar","")
15631667--
15641668-- Laws:
15651669--
@@ -1588,7 +1692,8 @@ breakOn = coerce JSS.breakOn
15881692-- up to and including the last match of @needle@. The second is the
15891693-- remainder of @haystack@, following the match.
15901694--
1591−-- > breakOnEnd "::" "a::b::c" ==> ("a::b::", "c")
1695+-- >>> breakOnEnd "::" "a::b::c"
1696+-- ("a::b::","c")
15921697breakOnEnd :: Text -> Text -> (Text, Text)
15931698breakOnEnd = coerce JSS.breakOnEnd
15941699-- breakOnEnd pat src = (reverse b, reverse a)
@@ -1604,10 +1709,11 @@ breakOnEnd = coerce JSS.breakOnEnd
16041709--
16051710-- Examples:
16061711--
1607−-- > breakOnAll "::" ""
1608−-- > ==> []
1609−-- > breakOnAll "/" "a/b/c/"
1610−-- > ==> [("a", "/b/c/"), ("a/b", "/c/"), ("a/b/c", "/")]
1712+-- >>> breakOnAll "::" ""
1713+-- []
1714+--
1715+-- >>> breakOnAll "/" "a/b/c/"
1716+-- [("a","/b/c/"),("a/b","/c/"),("a/b/c","/")]
16111717--
16121718-- In (unlikely) bad cases, this function's time complexity degrades
16131719-- towards /O(n*m)/.
@@ -1821,9 +1927,14 @@ isInfixOf = coerce JSS.isInfixOf
18211927--
18221928-- Examples:
18231929--
1824−-- > stripPrefix "foo" "foobar" == Just "bar"
1825−-- > stripPrefix "" "baz" == Just "baz"
1826−-- > stripPrefix "foo" "quux" == Nothing
1930+-- >>> stripPrefix "foo" "foobar"
1931+-- Just "bar"
1932+--
1933+-- >>> stripPrefix "" "baz"
1934+-- Just "baz"
1935+--
1936+-- >>> stripPrefix "foo" "quux"
1937+-- Nothing
18271938--
18281939-- This is particularly useful with the @ViewPatterns@ extension to
18291940-- GHC, as follows:
@@ -1849,9 +1960,14 @@ stripPrefix = coerce JSS.stripPrefix
18491960--
18501961-- Examples:
18511962--
1852−-- > commonPrefixes "foobar" "fooquux" == Just ("foo","bar","quux")
1853−-- > commonPrefixes "veeble" "fetzer" == Nothing
1854−-- > commonPrefixes "" "baz" == Nothing
1963+-- >>> commonPrefixes "foobar" "fooquux"
1964+-- Just ("foo","bar","quux")
1965+--
1966+-- >>> commonPrefixes "veeble" "fetzer"
1967+-- Nothing
1968+--
1969+-- >>> commonPrefixes "" "baz"
1970+-- Nothing
18551971commonPrefixes :: Text -> Text -> Maybe (Text,Text,Text)
18561972commonPrefixes = coerce JSS.commonPrefixes
18571973-- commonPrefixes t0@(Text arr0 off0 len0) t1@(Text arr1 off1 len1) = go 0 0
@@ -1869,9 +1985,14 @@ commonPrefixes = coerce JSS.commonPrefixes
18691985--
18701986-- Examples:
18711987--
1872−-- > stripSuffix "bar" "foobar" == Just "foo"
1873−-- > stripSuffix "" "baz" == Just "baz"
1874−-- > stripSuffix "foo" "quux" == Nothing
1988+-- >>> stripSuffix "bar" "foobar"
1989+-- Just "foo"
1990+--
1991+-- >>> stripSuffix "" "baz"
1992+-- Just "baz"
1993+--
1994+-- >>> stripSuffix "foo" "quux"
1995+-- Nothing
18751996--
18761997-- This is particularly useful with the @ViewPatterns@ extension to
18771998-- GHC, as follows:
@@ -1923,3 +2044,11 @@ foreign import javascript unsafe
19232044 "h$jsstringReplicateChar" js_replicateChar :: Int -> Char -> JSString
19242045foreign import javascript unsafe
19252046 "$2.substr($1)" js_substr1 :: Int -> JSString -> JSString
2047+
2048+-------------------------------------------------
2049+-- NOTE: the named chunk below used by doctest;
2050+-- verify the doctests via `doctest -fobject-code Data/Text.hs`
2051+
2052+-- $setup
2053+-- >>> :set -XOverloadedStrings
2054+-- >>> import qualified Data.Text as T
Data/Text/Array.hs+4−1
@@ -7,7 +7,6 @@
77--
88-- License : BSD-style
99-- Maintainer : bos@serpentine.com
10−-- Stability : experimental
1110-- Portability : portable
1211--
1312-- Packed, unboxed, heap-resident arrays. Suitable for performance
@@ -80,6 +79,8 @@ import GHC.Word (Word16(..))
8079import Prelude hiding (length, read)
8180
8281-- | Immutable array type.
82+--
83+-- The 'Array' constructor is exposed since @text-1.1.1.3@
8384data Array = Array {
8485 aBA :: ByteArray#
8586#if defined(ASSERTS)
@@ -88,6 +89,8 @@ data Array = Array {
8889 }
8990
9091-- | Mutable array type, for use in the ST monad.
92+--
93+-- The 'MArray' constructor is exposed since @text-1.1.1.3@
9194data MArray s = MArray {
9295 maBA :: MutableByteArray# s
9396#if defined(ASSERTS)
Data/Text/Encoding.hs+67−11
@@ -12,14 +12,13 @@
1212--
1313-- License : BSD-style
1414-- Maintainer : bos@serpentine.com
15−-- Stability : experimental
1615-- Portability : portable
1716--
1817-- Functions for converting 'Text' values to and from 'ByteString',
1918-- using several standard encodings.
2019--
2120-- To gain access to a much larger family of encodings, use the
22−-- @text-icu@ package: <http://hackage.haskell.org/package/text-icu>
21+-- <http://hackage.haskell.org/package/text-icu text-icu package>.
2322
2423module Data.Text.Encoding
2524 (
@@ -67,7 +66,7 @@ import Control.Monad.ST.Unsafe (unsafeIOToST, unsafeSTToIO)
6766import Control.Monad.ST (unsafeIOToST, unsafeSTToIO)
6867#endif
6968
70−import Control.Exception (evaluate, try)
69+import Control.Exception (evaluate, try, throwIO, ErrorCall(ErrorCall))
7170import Control.Monad.ST (runST)
7271import Data.Bits ((.&.))
7372import Data.ByteString as B
@@ -82,7 +81,11 @@ import Data.Text.Show ()
8281#endif
8382import Data.Text.Unsafe (unsafeDupablePerformIO)
8483import Data.Word (Word8, Word32)
85−import Foreign.C.Types (CSize(..))
84+#if __GLASGOW_HASKELL__ >= 703
85+import Foreign.C.Types (CSize(CSize))
86+#else
87+import Foreign.C.Types (CSize)
88+#endif
8689import Foreign.ForeignPtr (withForeignPtr)
8790import Foreign.Marshal.Utils (with)
8891import Foreign.Ptr (Ptr, minusPtr, nullPtr, plusPtr)
@@ -137,6 +140,13 @@ decodeLatin1 (PS fp off len) = text a 0 len
137140 return dest
138141
139142-- | Decode a 'ByteString' containing UTF-8 encoded text.
143+--
144+-- __NOTE__: The replacement character returned by 'OnDecodeError'
145+-- MUST be within the BMP plane; surrogate code points will
146+-- automatically be remapped to the replacement char @U+FFFD@
147+-- (/since 0.11.3.0/), whereas code points beyond the BMP will throw an
148+-- 'error' (/since 1.2.3.1/); For earlier versions of @text@ using
149+-- those unsupported code points would result in undefined behavior.
140150decodeUtf8With :: OnDecodeError -> ByteString -> Text
141151decodeUtf8With onErr (PS fp off len) = runText $ \done -> do
142152 let go dest = withForeignPtr fp $ \ptr ->
@@ -152,16 +162,52 @@ decodeUtf8With onErr (PS fp off len) = runText $ \done -> do
152162 x <- peek curPtr'
153163 case onErr desc (Just x) of
154164 Nothing -> loop $ curPtr' `plusPtr` 1
155− Just c -> do
156− destOff <- peek destOffPtr
157− w <- unsafeSTToIO $
158− unsafeWrite dest (fromIntegral destOff) (safe c)
159− poke destOffPtr (destOff + fromIntegral w)
160− loop $ curPtr' `plusPtr` 1
165+ Just c
166+ | c > '\xFFFF' -> throwUnsupportedReplChar
167+ | otherwise -> do
168+ destOff <- peek destOffPtr
169+ w <- unsafeSTToIO $
170+ unsafeWrite dest (fromIntegral destOff)
171+ (safe c)
172+ poke destOffPtr (destOff + fromIntegral w)
173+ loop $ curPtr' `plusPtr` 1
161174 loop (ptr `plusPtr` off)
162175 (unsafeIOToST . go) =<< A.new len
163176 where
164177 desc = "Data.Text.Internal.Encoding.decodeUtf8: Invalid UTF-8 stream"
178+
179+ throwUnsupportedReplChar = throwIO $
180+ ErrorCall "decodeUtf8With: non-BMP replacement characters not supported"
181+ -- TODO: The code currently assumes that the transcoded UTF-16
182+ -- stream is at most twice as long (in bytes) as the input UTF-8
183+ -- stream. To justify this assumption one has to assume that the
184+ -- error handler replacement character also satisfies this
185+ -- invariant, by emitting at most one UTF16 code unit.
186+ --
187+ -- One easy way to support the full range of code-points for
188+ -- replacement characters in the error handler is to simply change
189+ -- the (over-)allocation to `A.new (2*len)` and then shrink back the
190+ -- `ByteArray#` to the real size (recent GHCs have a cheap
191+ -- `ByteArray#` resize-primop for that which allow the GC to reclaim
192+ -- the overallocation). However, this would require 4 times as much
193+ -- (temporary) storage as the original UTF-8 required.
194+ --
195+ -- Another strategy would be to optimistically assume that
196+ -- replacement characters are within the BMP, and if the case of a
197+ -- non-BMP replacement occurs reallocate the target buffer (or throw
198+ -- an exception, and fallback to a pessimistic codepath, like e.g.
199+ -- `decodeUtf8With onErr bs = F.unstream (E.streamUtf8 onErr bs)`)
200+ --
201+ -- Alternatively, `OnDecodeError` could become a datastructure which
202+ -- statically encodes the replacement-character range,
203+ -- e.g. something isomorphic to
204+ --
205+ -- Either (... -> Maybe Word16) (... -> Maybe Char)
206+ --
207+ -- And allow to statically switch between the BMP/non-BMP
208+ -- replacement-character codepaths. There's multiple ways to address
209+ -- this with different tradeoffs; but ideally we should optimise for
210+ -- the optimistic/error-free case.
165211{- INLINE[0] decodeUtf8With #-}
166212
167213-- $stream
@@ -218,6 +264,8 @@ decodeUtf8With onErr (PS fp off len) = runText $ \done -> do
218264-- or continuation where it is encountered.
219265
220266-- | A stream oriented decoding result.
267+--
268+-- @since 1.0.0.0
221269data Decoding = Some Text ByteString (ByteString -> Decoding)
222270
223271instance Show Decoding where
@@ -237,11 +285,15 @@ newtype DecoderState = DecoderState Word32 deriving (Eq, Show, Num, Storable)
237285-- thrown (either by this function or a continuation) that cannot be
238286-- caught in pure code. For more control over the handling of invalid
239287-- data, use 'streamDecodeUtf8With'.
288+--
289+-- @since 1.0.0.0
240290streamDecodeUtf8 :: ByteString -> Decoding
241291streamDecodeUtf8 = streamDecodeUtf8With strictDecode
242292
243293-- | Decode, in a stream oriented way, a 'ByteString' containing UTF-8
244294-- encoded text.
295+--
296+-- @since 1.0.0.0
245297streamDecodeUtf8With :: OnDecodeError -> ByteString -> Decoding
246298streamDecodeUtf8With onErr = decodeChunk B.empty 0 0
247299 where
@@ -317,6 +369,8 @@ decodeUtf8' = unsafeDupablePerformIO . try . evaluate . decodeUtf8With strictDec
317369{-# INLINE decodeUtf8' #-}
318370
319371-- | Encode text to a ByteString 'B.Builder' using UTF-8 encoding.
372+--
373+-- @since 1.1.0.0
320374encodeUtf8Builder :: Text -> B.Builder
321375encodeUtf8Builder = encodeUtf8BuilderEscaped (BP.liftFixedToBounded BP.word8)
322376
@@ -325,6 +379,8 @@ encodeUtf8Builder = encodeUtf8BuilderEscaped (BP.liftFixedToBounded BP.word8)
325379--
326380-- Use this function is to implement efficient encoders for text-based formats
327381-- like JSON or HTML.
382+--
383+-- @since 1.1.0.0
328384{-# INLINE encodeUtf8BuilderEscaped #-}
329385-- TODO: Extend documentation with references to source code in @blaze-html@
330386-- or @aeson@ that uses this function.
@@ -392,7 +448,7 @@ encodeUtf8 :: Text -> ByteString
392448encodeUtf8 (Text arr off len)
393449 | len == 0 = B.empty
394450 | otherwise = unsafeDupablePerformIO $ do
395− fp <- mallocByteString (len*4)
451+ fp <- mallocByteString (len*3) -- see https://github.com/haskell/text/issues/194 for why len*3 is enough
396452 withForeignPtr fp $ \ptr ->
397453 with ptr $ \destPtr -> do
398454 c_encode_utf8 destPtr (A.aBA arr) (fromIntegral off) (fromIntegral len)
Data/Text/Encoding/Error.hs−1
@@ -10,7 +10,6 @@
1010--
1111-- License : BSD-style
1212-- Maintainer : bos@serpentine.com
13−-- Stability : experimental
1413-- Portability : GHC
1514--
1615-- Types and functions for dealing with encoding and decoding errors
Data/Text/Foreign.hs+5−2
@@ -5,7 +5,6 @@
55--
66-- License : BSD-style
77-- Maintainer : bos@serpentine.com
8−-- Stability : experimental
98-- Portability : GHC
109--
1110-- Support for using 'Text' data with native code via the Haskell
@@ -108,7 +107,7 @@ takeWord16 (I16 n) t@(Text arr off len)
108107 | n >= len || m >= len = t
109108 | otherwise = Text arr off m
110109 where
111− m | w < 0xDB00 || w > 0xD8FF = n
110+ m | w < 0xD800 || w > 0xDBFF = n
112111 | otherwise = n+1
113112 w = A.unsafeIndex arr (off+n-1)
114113
@@ -157,6 +156,8 @@ asForeignPtr t@(Text _arr _off len) = do
157156-- | /O(n)/ Decode a C string with explicit length, which is assumed
158157-- to have been encoded as UTF-8. If decoding fails, a
159158-- 'UnicodeException' is thrown.
159+--
160+-- @since 1.0.0.0
160161peekCStringLen :: CStringLen -> IO Text
161162peekCStringLen cs = do
162163 bs <- unsafePackCStringLen cs
@@ -169,5 +170,7 @@ peekCStringLen cs = do
169170-- The temporary storage is freed when the subcomputation terminates
170171-- (either normally or via an exception), so the pointer to the
171172-- temporary storage must /not/ be used after this function returns.
173+--
174+-- @since 1.0.0.0
172175withCStringLen :: Text -> (CStringLen -> IO a) -> IO a
173176withCStringLen t act = unsafeUseAsCStringLen (encodeUtf8 t) act
Data/Text/IO.hs+4−1
@@ -8,7 +8,6 @@
88-- (c) 2009 Simon Marlow
99-- License : BSD-style
1010-- Maintainer : bos@serpentine.com
11−-- Stability : experimental
1211-- Portability : GHC
1312--
1413-- Efficient locale-sensitive support for text I\/O.
@@ -352,3 +351,7 @@ putStrLn = hPutStrLn stdout
352351-- >
353352-- > putStr_Utf16LE :: Text -> IO ()
354353-- > putStr_Utf16LE t = B.putStr (encodeUtf16LE t)
354+--
355+-- On transcoding errors, an 'IOError' exception is thrown. You can
356+-- use the API in "Data.Text.Encoding" if you need more control over
357+-- error handling or transcoding.
Data/Text/Internal/Fusion/CaseMapping.hs+164−4
@@ -1,10 +1,10 @@
11{-# LANGUAGE Rank2Types #-}
22-- AUTOMATICALLY GENERATED - DO NOT EDIT
33-- Generated by scripts/CaseMapping.hs
4−-- CaseFolding-8.0.0.txt
5−-- Date: 2015-01-13, 18:16:36 GMT [MD]
6−-- SpecialCasing-8.0.0.txt
7−-- Date: 2014-12-16, 23:08:04 GMT [MD]
4+-- CaseFolding-9.0.0.txt
5+-- Date: 2016-03-02, 18:54:54 GMT
6+-- SpecialCasing-9.0.0.txt
7+-- Date: 2016-03-02, 18:55:13 GMT
88
99module Data.Text.Internal.Fusion.CaseMapping where
1010import Data.Char
@@ -371,6 +371,24 @@ foldMapping '\x13fb' s = Yield '\x13f3' (CC s '\x0000' '\x0000')
371371foldMapping '\x13fc' s = Yield '\x13f4' (CC s '\x0000' '\x0000')
372372-- CHEROKEE SMALL LETTER MV
373373foldMapping '\x13fd' s = Yield '\x13f5' (CC s '\x0000' '\x0000')
374+-- CYRILLIC SMALL LETTER ROUNDED VE
375+foldMapping '\x1c80' s = Yield '\x0432' (CC s '\x0000' '\x0000')
376+-- CYRILLIC SMALL LETTER LONG-LEGGED DE
377+foldMapping '\x1c81' s = Yield '\x0434' (CC s '\x0000' '\x0000')
378+-- CYRILLIC SMALL LETTER NARROW O
379+foldMapping '\x1c82' s = Yield '\x043e' (CC s '\x0000' '\x0000')
380+-- CYRILLIC SMALL LETTER WIDE ES
381+foldMapping '\x1c83' s = Yield '\x0441' (CC s '\x0000' '\x0000')
382+-- CYRILLIC SMALL LETTER TALL TE
383+foldMapping '\x1c84' s = Yield '\x0442' (CC s '\x0000' '\x0000')
384+-- CYRILLIC SMALL LETTER THREE-LEGGED TE
385+foldMapping '\x1c85' s = Yield '\x0442' (CC s '\x0000' '\x0000')
386+-- CYRILLIC SMALL LETTER TALL HARD SIGN
387+foldMapping '\x1c86' s = Yield '\x044a' (CC s '\x0000' '\x0000')
388+-- CYRILLIC SMALL LETTER TALL YAT
389+foldMapping '\x1c87' s = Yield '\x0463' (CC s '\x0000' '\x0000')
390+-- CYRILLIC SMALL LETTER UNBLENDED UK
391+foldMapping '\x1c88' s = Yield '\xa64b' (CC s '\x0000' '\x0000')
374392-- LATIN SMALL LETTER H WITH LINE BELOW
375393foldMapping '\x1e96' s = Yield '\x0068' (CC s '\x0331' '\x0000')
376394-- LATIN SMALL LETTER T WITH DIAERESIS
@@ -545,6 +563,8 @@ foldMapping '\x1ff6' s = Yield '\x03c9' (CC s '\x0342' '\x0000')
545563foldMapping '\x1ff7' s = Yield '\x03c9' (CC s '\x0342' '\x03b9')
546564-- GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI
547565foldMapping '\x1ffc' s = Yield '\x03c9' (CC s '\x03b9' '\x0000')
566+-- LATIN CAPITAL LETTER SMALL CAPITAL I
567+foldMapping '\xa7ae' s = Yield '\x026a' (CC s '\x0000' '\x0000')
548568-- LATIN CAPITAL LETTER J WITH CROSSED-TAIL
549569foldMapping '\xa7b2' s = Yield '\x029d' (CC s '\x0000' '\x0000')
550570-- LATIN CAPITAL LETTER CHI
@@ -737,6 +757,78 @@ foldMapping '\xfb15' s = Yield '\x0574' (CC s '\x056b' '\x0000')
737757foldMapping '\xfb16' s = Yield '\x057e' (CC s '\x0576' '\x0000')
738758-- ARMENIAN SMALL LIGATURE MEN XEH
739759foldMapping '\xfb17' s = Yield '\x0574' (CC s '\x056d' '\x0000')
760+-- OSAGE CAPITAL LETTER A
761+foldMapping '\x104b0' s = Yield '\x104d8' (CC s '\x0000' '\x0000')
762+-- OSAGE CAPITAL LETTER AI
763+foldMapping '\x104b1' s = Yield '\x104d9' (CC s '\x0000' '\x0000')
764+-- OSAGE CAPITAL LETTER AIN
765+foldMapping '\x104b2' s = Yield '\x104da' (CC s '\x0000' '\x0000')
766+-- OSAGE CAPITAL LETTER AH
767+foldMapping '\x104b3' s = Yield '\x104db' (CC s '\x0000' '\x0000')
768+-- OSAGE CAPITAL LETTER BRA
769+foldMapping '\x104b4' s = Yield '\x104dc' (CC s '\x0000' '\x0000')
770+-- OSAGE CAPITAL LETTER CHA
771+foldMapping '\x104b5' s = Yield '\x104dd' (CC s '\x0000' '\x0000')
772+-- OSAGE CAPITAL LETTER EHCHA
773+foldMapping '\x104b6' s = Yield '\x104de' (CC s '\x0000' '\x0000')
774+-- OSAGE CAPITAL LETTER E
775+foldMapping '\x104b7' s = Yield '\x104df' (CC s '\x0000' '\x0000')
776+-- OSAGE CAPITAL LETTER EIN
777+foldMapping '\x104b8' s = Yield '\x104e0' (CC s '\x0000' '\x0000')
778+-- OSAGE CAPITAL LETTER HA
779+foldMapping '\x104b9' s = Yield '\x104e1' (CC s '\x0000' '\x0000')
780+-- OSAGE CAPITAL LETTER HYA
781+foldMapping '\x104ba' s = Yield '\x104e2' (CC s '\x0000' '\x0000')
782+-- OSAGE CAPITAL LETTER I
783+foldMapping '\x104bb' s = Yield '\x104e3' (CC s '\x0000' '\x0000')
784+-- OSAGE CAPITAL LETTER KA
785+foldMapping '\x104bc' s = Yield '\x104e4' (CC s '\x0000' '\x0000')
786+-- OSAGE CAPITAL LETTER EHKA
787+foldMapping '\x104bd' s = Yield '\x104e5' (CC s '\x0000' '\x0000')
788+-- OSAGE CAPITAL LETTER KYA
789+foldMapping '\x104be' s = Yield '\x104e6' (CC s '\x0000' '\x0000')
790+-- OSAGE CAPITAL LETTER LA
791+foldMapping '\x104bf' s = Yield '\x104e7' (CC s '\x0000' '\x0000')
792+-- OSAGE CAPITAL LETTER MA
793+foldMapping '\x104c0' s = Yield '\x104e8' (CC s '\x0000' '\x0000')
794+-- OSAGE CAPITAL LETTER NA
795+foldMapping '\x104c1' s = Yield '\x104e9' (CC s '\x0000' '\x0000')
796+-- OSAGE CAPITAL LETTER O
797+foldMapping '\x104c2' s = Yield '\x104ea' (CC s '\x0000' '\x0000')
798+-- OSAGE CAPITAL LETTER OIN
799+foldMapping '\x104c3' s = Yield '\x104eb' (CC s '\x0000' '\x0000')
800+-- OSAGE CAPITAL LETTER PA
801+foldMapping '\x104c4' s = Yield '\x104ec' (CC s '\x0000' '\x0000')
802+-- OSAGE CAPITAL LETTER EHPA
803+foldMapping '\x104c5' s = Yield '\x104ed' (CC s '\x0000' '\x0000')
804+-- OSAGE CAPITAL LETTER SA
805+foldMapping '\x104c6' s = Yield '\x104ee' (CC s '\x0000' '\x0000')
806+-- OSAGE CAPITAL LETTER SHA
807+foldMapping '\x104c7' s = Yield '\x104ef' (CC s '\x0000' '\x0000')
808+-- OSAGE CAPITAL LETTER TA
809+foldMapping '\x104c8' s = Yield '\x104f0' (CC s '\x0000' '\x0000')
810+-- OSAGE CAPITAL LETTER EHTA
811+foldMapping '\x104c9' s = Yield '\x104f1' (CC s '\x0000' '\x0000')
812+-- OSAGE CAPITAL LETTER TSA
813+foldMapping '\x104ca' s = Yield '\x104f2' (CC s '\x0000' '\x0000')
814+-- OSAGE CAPITAL LETTER EHTSA
815+foldMapping '\x104cb' s = Yield '\x104f3' (CC s '\x0000' '\x0000')
816+-- OSAGE CAPITAL LETTER TSHA
817+foldMapping '\x104cc' s = Yield '\x104f4' (CC s '\x0000' '\x0000')
818+-- OSAGE CAPITAL LETTER DHA
819+foldMapping '\x104cd' s = Yield '\x104f5' (CC s '\x0000' '\x0000')
820+-- OSAGE CAPITAL LETTER U
821+foldMapping '\x104ce' s = Yield '\x104f6' (CC s '\x0000' '\x0000')
822+-- OSAGE CAPITAL LETTER WA
823+foldMapping '\x104cf' s = Yield '\x104f7' (CC s '\x0000' '\x0000')
824+-- OSAGE CAPITAL LETTER KHA
825+foldMapping '\x104d0' s = Yield '\x104f8' (CC s '\x0000' '\x0000')
826+-- OSAGE CAPITAL LETTER GHA
827+foldMapping '\x104d1' s = Yield '\x104f9' (CC s '\x0000' '\x0000')
828+-- OSAGE CAPITAL LETTER ZA
829+foldMapping '\x104d2' s = Yield '\x104fa' (CC s '\x0000' '\x0000')
830+-- OSAGE CAPITAL LETTER ZHA
831+foldMapping '\x104d3' s = Yield '\x104fb' (CC s '\x0000' '\x0000')
740832-- OLD HUNGARIAN CAPITAL LETTER A
741833foldMapping '\x10c80' s = Yield '\x10cc0' (CC s '\x0000' '\x0000')
742834-- OLD HUNGARIAN CAPITAL LETTER AA
@@ -839,4 +931,72 @@ foldMapping '\x10cb0' s = Yield '\x10cf0' (CC s '\x0000' '\x0000')
839931foldMapping '\x10cb1' s = Yield '\x10cf1' (CC s '\x0000' '\x0000')
840932-- OLD HUNGARIAN CAPITAL LETTER US
841933foldMapping '\x10cb2' s = Yield '\x10cf2' (CC s '\x0000' '\x0000')
934+-- ADLAM CAPITAL LETTER ALIF
935+foldMapping '\x1e900' s = Yield '\x1e922' (CC s '\x0000' '\x0000')
936+-- ADLAM CAPITAL LETTER DAALI
937+foldMapping '\x1e901' s = Yield '\x1e923' (CC s '\x0000' '\x0000')
938+-- ADLAM CAPITAL LETTER LAAM
939+foldMapping '\x1e902' s = Yield '\x1e924' (CC s '\x0000' '\x0000')
940+-- ADLAM CAPITAL LETTER MIIM
941+foldMapping '\x1e903' s = Yield '\x1e925' (CC s '\x0000' '\x0000')
942+-- ADLAM CAPITAL LETTER BA
943+foldMapping '\x1e904' s = Yield '\x1e926' (CC s '\x0000' '\x0000')
944+-- ADLAM CAPITAL LETTER SINNYIIYHE
945+foldMapping '\x1e905' s = Yield '\x1e927' (CC s '\x0000' '\x0000')
946+-- ADLAM CAPITAL LETTER PE
947+foldMapping '\x1e906' s = Yield '\x1e928' (CC s '\x0000' '\x0000')
948+-- ADLAM CAPITAL LETTER BHE
949+foldMapping '\x1e907' s = Yield '\x1e929' (CC s '\x0000' '\x0000')
950+-- ADLAM CAPITAL LETTER RA
951+foldMapping '\x1e908' s = Yield '\x1e92a' (CC s '\x0000' '\x0000')
952+-- ADLAM CAPITAL LETTER E
953+foldMapping '\x1e909' s = Yield '\x1e92b' (CC s '\x0000' '\x0000')
954+-- ADLAM CAPITAL LETTER FA
955+foldMapping '\x1e90a' s = Yield '\x1e92c' (CC s '\x0000' '\x0000')
956+-- ADLAM CAPITAL LETTER I
957+foldMapping '\x1e90b' s = Yield '\x1e92d' (CC s '\x0000' '\x0000')
958+-- ADLAM CAPITAL LETTER O
959+foldMapping '\x1e90c' s = Yield '\x1e92e' (CC s '\x0000' '\x0000')
960+-- ADLAM CAPITAL LETTER DHA
961+foldMapping '\x1e90d' s = Yield '\x1e92f' (CC s '\x0000' '\x0000')
962+-- ADLAM CAPITAL LETTER YHE
963+foldMapping '\x1e90e' s = Yield '\x1e930' (CC s '\x0000' '\x0000')
964+-- ADLAM CAPITAL LETTER WAW
965+foldMapping '\x1e90f' s = Yield '\x1e931' (CC s '\x0000' '\x0000')
966+-- ADLAM CAPITAL LETTER NUN
967+foldMapping '\x1e910' s = Yield '\x1e932' (CC s '\x0000' '\x0000')
968+-- ADLAM CAPITAL LETTER KAF
969+foldMapping '\x1e911' s = Yield '\x1e933' (CC s '\x0000' '\x0000')
970+-- ADLAM CAPITAL LETTER YA
971+foldMapping '\x1e912' s = Yield '\x1e934' (CC s '\x0000' '\x0000')
972+-- ADLAM CAPITAL LETTER U
973+foldMapping '\x1e913' s = Yield '\x1e935' (CC s '\x0000' '\x0000')
974+-- ADLAM CAPITAL LETTER JIIM
975+foldMapping '\x1e914' s = Yield '\x1e936' (CC s '\x0000' '\x0000')
976+-- ADLAM CAPITAL LETTER CHI
977+foldMapping '\x1e915' s = Yield '\x1e937' (CC s '\x0000' '\x0000')
978+-- ADLAM CAPITAL LETTER HA
979+foldMapping '\x1e916' s = Yield '\x1e938' (CC s '\x0000' '\x0000')
980+-- ADLAM CAPITAL LETTER QAAF
981+foldMapping '\x1e917' s = Yield '\x1e939' (CC s '\x0000' '\x0000')
982+-- ADLAM CAPITAL LETTER GA
983+foldMapping '\x1e918' s = Yield '\x1e93a' (CC s '\x0000' '\x0000')
984+-- ADLAM CAPITAL LETTER NYA
985+foldMapping '\x1e919' s = Yield '\x1e93b' (CC s '\x0000' '\x0000')
986+-- ADLAM CAPITAL LETTER TU
987+foldMapping '\x1e91a' s = Yield '\x1e93c' (CC s '\x0000' '\x0000')
988+-- ADLAM CAPITAL LETTER NHA
989+foldMapping '\x1e91b' s = Yield '\x1e93d' (CC s '\x0000' '\x0000')
990+-- ADLAM CAPITAL LETTER VA
991+foldMapping '\x1e91c' s = Yield '\x1e93e' (CC s '\x0000' '\x0000')
992+-- ADLAM CAPITAL LETTER KHA
993+foldMapping '\x1e91d' s = Yield '\x1e93f' (CC s '\x0000' '\x0000')
994+-- ADLAM CAPITAL LETTER GBE
995+foldMapping '\x1e91e' s = Yield '\x1e940' (CC s '\x0000' '\x0000')
996+-- ADLAM CAPITAL LETTER ZAL
997+foldMapping '\x1e91f' s = Yield '\x1e941' (CC s '\x0000' '\x0000')
998+-- ADLAM CAPITAL LETTER KPO
999+foldMapping '\x1e920' s = Yield '\x1e942' (CC s '\x0000' '\x0000')
1000+-- ADLAM CAPITAL LETTER SHA
1001+foldMapping '\x1e921' s = Yield '\x1e943' (CC s '\x0000' '\x0000')
8421002foldMapping c s = Yield (toLower c) (CC s '\0' '\0')
Data/Text/Internal/Fusion/Size.hs+33−7
@@ -1,4 +1,4 @@
1−{-# LANGUAGE CPP #-}
1+{-# LANGUAGE CPP, PatternGuards #-}
22{-# OPTIONS_GHC -fno-warn-missing-methods #-}
33-- |
44-- Module : Data.Text.Internal.Fusion.Internal
@@ -19,11 +19,16 @@
1919module Data.Text.Internal.Fusion.Size
2020 (
2121 Size
22− , exactly
22+ -- * Sizes
2323 , exactSize
2424 , maxSize
2525 , betweenSize
2626 , unknownSize
27+ , unionSize
28+ , charSize
29+ , codePointsSize
30+ -- * Querying sizes
31+ , exactly
2732 , smaller
2833 , larger
2934 , upperBound
@@ -32,11 +37,13 @@ module Data.Text.Internal.Fusion.Size
3237 , isEmpty
3338 ) where
3439
40+import Data.Char (ord)
3541import Data.Text.Internal (mul)
3642#if defined(ASSERTS)
3743import Control.Exception (assert)
3844#endif
3945
46+-- | A size in UTF-16 code units.
4047data Size = Between {-# UNPACK #-} !Int {-# UNPACK #-} !Int -- ^ Lower and upper bounds on size.
4148 | Unknown -- ^ Unknown size.
4249 deriving (Eq, Show)
@@ -46,6 +53,17 @@ exactly (Between na nb) | na == nb = Just na
4653exactly _ = Nothing
4754{-# INLINE exactly #-}
4855
56+-- | The 'Size' of the given code point.
57+charSize :: Char -> Size
58+charSize c
59+ | ord c < 0x10000 = exactSize 1
60+ | otherwise = exactSize 2
61+
62+-- | The 'Size' of @n@ code points.
63+codePointsSize :: Int -> Size
64+codePointsSize n = Between n (2*n)
65+{-# INLINE codePointsSize #-}
66+
4967exactSize :: Int -> Size
5068exactSize n =
5169#if defined(ASSERTS)
@@ -71,6 +89,10 @@ betweenSize m n =
7189 Between m n
7290{-# INLINE betweenSize #-}
7391
92+unionSize :: Size -> Size -> Size
93+unionSize (Between a b) (Between c d) = Between (min a c) (max b d)
94+unionSize _ _ = Unknown
95+
7496unknownSize :: Size
7597unknownSize = Unknown
7698{-# INLINE unknownSize #-}
@@ -140,11 +162,15 @@ lowerBound _ (Between n _) = n
140162lowerBound k _ = k
141163{-# INLINE lowerBound #-}
142164
143−compareSize :: Size -> Int -> Maybe Ordering
144−compareSize (Between ma mb) n
145− | mb < n = Just LT
146− | ma > n = Just GT
147− | ma == n && mb == n = Just EQ
165+-- | Determine the ordering relationship between two 'Size's, or 'Nothing' in
166+-- the indeterminate case.
167+compareSize :: Size -> Size -> Maybe Ordering
168+compareSize (Between ma mb) (Between na nb)
169+ | mb < na = Just LT
170+ | ma > nb = Just GT
171+ | ma == mb
172+ , ma == na
173+ , ma == nb = Just EQ
148174compareSize _ _ = Nothing
149175
150176
Data/Text/Internal/Fusion/Types.hs+4−4
@@ -78,16 +78,16 @@ import Data.JSString.Internal.Fusion.Types
7878-- -- unstreaming functions must be able to cope with the hint being too
7979-- -- small or too large.
8080-- --
81−-- -- The size hint tries to track the UTF-16 code points in a stream,
82−-- -- but often counts the number of characters instead. It can easily
81+-- -- The size hint tries to track the UTF-16 code units in a stream,
82+-- -- but often counts the number of code points instead. It can easily
8383-- -- undercount if, for instance, a transformed stream contains astral
84−-- -- plane characters (those above 0x10000).
84+-- -- plane code points (those above 0x10000).
8585
8686-- data Stream a =
8787-- forall s. Stream
8888-- (s -> Step s a) -- stepper function
8989-- !s -- current state
90−-- !Size -- size hint
90+-- !Size -- size hint in code units
9191
9292-- -- | /O(n)/ Determines if two streams are equal.
9393-- eq :: (Eq a) => Stream a -> Stream a -> Bool
Data/Text/Lazy.hs+54−20
@@ -15,7 +15,6 @@
1515--
1616-- License : BSD-style
1717-- Maintainer : bos@serpentine.com
18−-- Stability : experimental
1918-- Portability : GHC
2019--
2120-- A time and space-efficient implementation of Unicode text using
@@ -70,6 +69,7 @@ module Data.Text.Lazy
7069 , snoc
7170 , append
7271 , uncons
72+ , unsnoc
7373 , head
7474 , last
7575 , tail
@@ -278,14 +278,16 @@ import Data.JSString (JSString)
278278-- $replacement
279279--
280280-- A 'Text' value is a sequence of Unicode scalar values, as defined
281−-- in &#xa7;3.9, definition D76 of the Unicode 5.2 standard:
282−-- <http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf#page=35>. As
283−-- such, a 'Text' cannot contain values in the range U+D800 to U+DFFF
284−-- inclusive. Haskell implementations admit all Unicode code points
285−-- (&#xa7;3.4, definition D10) as 'Char' values, including code points
286−-- from this invalid range. This means that there are some 'Char'
287−-- values that are not valid Unicode scalar values, and the functions
288−-- in this module must handle those cases.
281+-- in
282+-- <http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf#page=35 §3.9, definition D76 of the Unicode 5.2 standard >.
283+-- As such, a 'Text' cannot contain values in the range U+D800 to
284+-- U+DFFF inclusive. Haskell implementations admit all Unicode code
285+-- points
286+-- (<http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf#page=13 §3.4, definition D10 >)
287+-- as 'Char' values, including code points from this invalid range.
288+-- This means that there are some 'Char' values that are not valid
289+-- Unicode scalar values, and the functions in this module must handle
290+-- those cases.
289291--
290292-- Within this module, many functions construct a 'Text' from one or
291293-- more 'Char' values. Those functions will substitute 'Char' values
@@ -299,8 +301,8 @@ import Data.JSString (JSString)
299301-- range U+D800 through U+DFFF are used by UTF-16 to denote surrogate
300302-- code points, and so cannot be represented. The functions replace
301303-- invalid scalar values, instead of dropping them, as a security
302−-- measure. For details, see Unicode Technical Report 36, &#xa7;3.5:
303−-- <http://unicode.org/reports/tr36#Deletion_of_Noncharacters>)
304+-- measure. For details, see
305+-- <http://unicode.org/reports/tr36/#Deletion_of_Noncharacters Unicode Technical Report 36, §3.5 >.)
304306
305307equal :: Text -> Text -> Bool
306308equal Empty Empty = True
@@ -362,9 +364,13 @@ instance Read Text where
362364 readsPrec p str = [(pack x,y) | (x,y) <- readsPrec p str]
363365
364366#if MIN_VERSION_base(4,9,0)
365−-- Semigroup orphan instances for older GHCs are provided by
366−-- 'semigroups` package
367−
367+-- | Non-orphan 'Semigroup' instance only defined for
368+-- @base-4.9.0.0@ and later; orphan instances for older GHCs are
369+-- provided by
370+-- the [semigroups](http://hackage.haskell.org/package/semigroups)
371+-- package
372+--
373+-- @since 1.2.2.0
368374instance Semigroup Text where
369375 (<>) = append
370376#endif
@@ -382,6 +388,7 @@ instance IsString Text where
382388 fromString = pack
383389
384390#if __GLASGOW_HASKELL__ >= 708
391+-- | @since 1.2.0.0
385392instance Exts.IsList Text where
386393 type Item Text = Char
387394 fromList = pack
@@ -394,6 +401,7 @@ instance NFData Text where
394401 rnf (Chunk _ ts) = rnf ts
395402#endif
396403
404+-- | @since 1.2.1.0
397405instance Binary Text where
398406 put t = put (encodeUtf8 t)
399407 get = do
@@ -417,6 +425,8 @@ instance Data Text where
417425
418426#if MIN_VERSION_base(4,7,0)
419427-- | Only defined for @base-4.7.0.0@ and later
428+--
429+-- @since 1.2.2.0
420430instance PrintfArg Text where
421431 formatArg txt = formatString $ unpack txt
422432#endif
@@ -495,9 +505,7 @@ fromStrict t = chunk t Empty
495505-- -----------------------------------------------------------------------------
496506-- * Basic functions
497507
498−-- | /O(n)/ Adds a character to the front of a 'Text'. This function
499−-- is more costly than its 'List' counterpart because it requires
500−-- copying a new array. Subject to fusion.
508+-- | /O(1)/ Adds a character to the front of a 'Text'. Subject to fusion.
501509cons :: Char -> Text -> Text
502510cons c t = Chunk (T.singleton c) t
503511{-# INLINE [1] cons #-}
@@ -581,6 +589,17 @@ init Empty = emptyError "init"
581589 unstream (S.init (stream t)) = init t
582590 #-}
583591
592+-- | /O(n\/c)/ Returns the 'init' and 'last' of a 'Text', or 'Nothing' if
593+-- empty.
594+--
595+-- * It is no faster than using 'init' and 'last'.
596+--
597+-- @since 1.2.3.0
598+unsnoc :: Text -> Maybe (Text, Char)
599+unsnoc Empty = Nothing
600+unsnoc ts@(Chunk _ _) = Just (init ts, last ts)
601+{-# INLINE unsnoc #-}
602+
584603-- | /O(1)/ Tests whether a 'Text' is empty or not. Subject to
585604-- fusion.
586605null :: Text -> Bool
@@ -840,6 +859,8 @@ toUpper t = unstream (S.toUpper (stream t))
840859-- guides disagree on whether the book name \"The Hill of the Red
841860-- Fox\" is correctly title cased&#x2014;but this function will
842861-- capitalize /every/ word.
862+--
863+-- @since 1.0.0.0
843864toTitle :: Text -> Text
844865toTitle t = unstream (S.toTitle (stream t))
845866{-# INLINE toTitle #-}
@@ -992,6 +1013,8 @@ mapAccumR f = go
9921013
9931014-- | @'repeat' x@ is an infinite 'Text', with @x@ the value of every
9941015-- element.
1016+--
1017+-- @since 1.2.0.5
9951018repeat :: Char -> Text
9961019repeat c = let t = Chunk (T.replicate smallChunkSize (T.singleton c)) t
9971020 in t
@@ -1009,6 +1032,8 @@ replicate n t
10091032
10101033-- | 'cycle' ties a finite, non-empty 'Text' into a circular one, or
10111034-- equivalently, the infinite repetition of the original 'Text'.
1035+--
1036+-- @since 1.2.0.5
10121037cycle :: Text -> Text
10131038cycle Empty = emptyError "cycle"
10141039cycle t = let t' = foldrChunks Chunk t' t
@@ -1018,6 +1043,8 @@ cycle t = let t' = foldrChunks Chunk t' t
10181043-- of @f@ to @x@:
10191044--
10201045-- > iterate f x == [x, f x, f (f x), ...]
1046+--
1047+-- @since 1.2.0.5
10211048iterate :: (Char -> Char) -> Char -> Text
10221049iterate f c = let t c' = Chunk (T.singleton c') (t (f c'))
10231050 in t c
@@ -1081,6 +1108,8 @@ take i t0 = take' i t0
10811108-- Examples:
10821109--
10831110-- > takeEnd 3 "foobar" == "bar"
1111+--
1112+-- @since 1.1.1.0
10841113takeEnd :: Int64 -> Text -> Text
10851114takeEnd n t0
10861115 | n <= 0 = empty
@@ -1119,6 +1148,8 @@ drop i t0
11191148-- Examples:
11201149--
11211150-- > dropEnd 3 "foobar" == "foo"
1151+--
1152+-- @since 1.1.1.0
11221153dropEnd :: Int64 -> Text -> Text
11231154dropEnd n t0
11241155 | n <= 0 = t0
@@ -1179,12 +1210,15 @@ takeWhile p t0 = takeWhile' t0
11791210-- Examples:
11801211--
11811212-- > takeWhileEnd (=='o') "foo" == "oo"
1213+--
1214+-- @since 1.2.2.0
11821215takeWhileEnd :: (Char -> Bool) -> Text -> Text
11831216takeWhileEnd p = takeChunk empty . L.reverse . toChunks
11841217 where takeChunk acc [] = acc
1185− takeChunk acc (t:ts) = if T.length t' < T.length t
1186− then (Chunk t' acc)
1187− else takeChunk (Chunk t' acc) ts
1218+ takeChunk acc (t:ts)
1219+ | T.lengthWord16 t' < T.lengthWord16 t
1220+ = chunk t' acc
1221+ | otherwise = takeChunk (Chunk t' acc) ts
11881222 where t' = T.takeWhileEnd p t
11891223{-# INLINE takeWhileEnd #-}
11901224
Data/Text/Lazy/Builder.hs−1
@@ -11,7 +11,6 @@
1111-- License : BSD-style (see LICENSE)
1212--
1313-- Maintainer : Johan Tibell <johan.tibell@gmail.com>
14−-- Stability : experimental
1514-- Portability : portable to Hugs and GHC
1615--
1716-- Efficient construction of lazy @Text@ values. The principal
Data/Text/Lazy/Builder/Int.hs+46−2
@@ -1,4 +1,17 @@
1−module Data.Text.Lazy.Builder.Int where
1+-- Module: Data.Text.Lazy.Builder.Int
2+-- Copyright: (c) 2013 Bryan O'Sullivan
3+-- (c) 2011 MailRank, Inc.
4+-- License: BSD-style
5+-- Maintainer: Bryan O'Sullivan <bos@serpentine.com>
6+-- Portability: portable
7+--
8+-- Efficiently write an integral value to a 'Builder'.
9+
10+module Data.Text.Lazy.Builder.Int
11+ (
12+ decimal
13+ , hexadecimal
14+ ) where
215
316-- import Data.Text.Lazy (Text)
417import qualified Data.Text.Lazy as L
@@ -6,7 +19,38 @@ import qualified Data.Text as T
619import qualified Data.JSString.Int as JSS
720import Data.Text.Internal (Text (..))
821import Data.Text.Lazy.Builder
9−import Data.Monoid
22+
23+import Data.Int (Int8, Int16, Int32, Int64)
24+import Data.Monoid (mempty)
25+import qualified Data.ByteString.Unsafe as B
26+import Data.Text.Internal.Builder.Functions ((<>), i2d)
27+import Data.Text.Internal.Builder
28+import Data.Text.Internal.Builder.Int.Digits (digits)
29+import Data.Text.Array
30+import Data.Word (Word, Word8, Word16, Word32, Word64)
31+import GHC.Base (quotInt, remInt)
32+import GHC.Num (quotRemInteger)
33+import GHC.Types (Int(..))
34+import Control.Monad.ST
35+#if MIN_VERSION_base(4,11,0)
36+import Prelude hiding ((<>))
37+#endif
38+
39+#ifdef __GLASGOW_HASKELL__
40+# if defined(INTEGER_GMP)
41+import GHC.Integer.GMP.Internals (Integer(S#))
42+# elif defined(INTEGER_SIMPLE)
43+import GHC.Integer
44+# else
45+# error "You need to use either GMP or integer-simple."
46+# endif
47+#endif
48+
49+#if defined(INTEGER_GMP) || defined(INTEGER_SIMPLE)
50+# define PAIR(a,b) (# a,b #)
51+#else
52+# define PAIR(a,b) (a,b)
53+#endif
1054
1155decimal :: Integral a => a -> Builder
1256decimal n = fromText $ Text $ JSS.decimal n
Data/Text/Lazy/Builder/RealFloat.hs+3
@@ -24,6 +24,9 @@ import Data.Text.Lazy.Builder.Int (decimal)
2424import Data.Text.Internal.Builder.RealFloat.Functions (roundTo)
2525import Data.Text.Lazy.Builder
2626import qualified Data.Text as T
27+#if MIN_VERSION_base(4,11,0)
28+import Prelude hiding ((<>))
29+#endif
2730
2831
2932-- | Control the rendering of floating point numbers.
Data/Text/Lazy/Encoding.hs+13−3
@@ -8,14 +8,13 @@
88--
99-- License : BSD-style
1010-- Maintainer : bos@serpentine.com
11−-- Stability : experimental
1211-- Portability : portable
1312--
1413-- Functions for converting lazy 'Text' values to and from lazy
1514-- 'ByteString', using several standard encodings.
1615--
17−-- To gain access to a much larger variety of encodings, use the
18−-- @text-icu@ package: <http://hackage.haskell.org/package/text-icu>
16+-- To gain access to a much larger family of encodings, use the
17+-- <http://hackage.haskell.org/package/text-icu text-icu package>.
1918
2019module Data.Text.Lazy.Encoding
2120 (
@@ -141,6 +140,7 @@ decodeUtf8' bs = unsafeDupablePerformIO $ do
141140 rnf (Chunk _ ts) = rnf ts
142141{-# INLINE decodeUtf8' #-}
143142
143+-- | Encode text using UTF-8 encoding.
144144encodeUtf8 :: Text -> B.ByteString
145145encodeUtf8 Empty = B.empty
146146encodeUtf8 lt@(Chunk t _) =
@@ -154,10 +154,20 @@ encodeUtf8 lt@(Chunk t _) =
154154 firstChunkSize = min B.smallChunkSize (4 * (T.length t + 1))
155155 strategy = B.safeStrategy firstChunkSize B.defaultChunkSize
156156
157+-- | Encode text to a ByteString 'B.Builder' using UTF-8 encoding.
158+--
159+-- @since 1.1.0.0
157160encodeUtf8Builder :: Text -> B.Builder
158161encodeUtf8Builder =
159162 foldrChunks (\c b -> TE.encodeUtf8Builder c `mappend` b) Data.Monoid.mempty
160163
164+-- | Encode text using UTF-8 encoding and escape the ASCII characters using
165+-- a 'BP.BoundedPrim'.
166+--
167+-- Use this function is to implement efficient encoders for text-based formats
168+-- like JSON or HTML.
169+--
170+-- @since 1.1.0.0
161171{-# INLINE encodeUtf8BuilderEscaped #-}
162172encodeUtf8BuilderEscaped :: BP.BoundedPrim Word8 -> Text -> B.Builder
163173encodeUtf8BuilderEscaped prim =
Data/Text/Lazy/IO.hs−1
@@ -8,7 +8,6 @@
88-- (c) 2009 Simon Marlow
99-- License : BSD-style
1010-- Maintainer : bos@serpentine.com
11−-- Stability : experimental
1211-- Portability : GHC
1312--
1413-- Efficient locale-sensitive support for lazy text I\/O.
Data/Text/Lazy/Read.hs+3−4
@@ -11,7 +11,6 @@
1111--
1212-- License : BSD-style
1313-- Maintainer : bos@serpentine.com
14−-- Stability : experimental
1514-- Portability : GHC
1615--
1716-- Functions used frequently when reading textual data.
@@ -68,9 +67,9 @@ decimal txt
6867 go n d = (n * 10 + fromIntegral (digitToInt d))
6968
7069-- | Read a hexadecimal integer, consisting of an optional leading
71−-- @\"0x\"@ followed by at least one decimal digit. Input is consumed
72−-- until a non-hex-digit or end of string is reached. This function
73−-- is case insensitive.
70+-- @\"0x\"@ followed by at least one hexadecimal digit. Input is
71+-- consumed until a non-hex-digit or end of string is reached.
72+-- This function is case insensitive.
7473--
7574-- This function does not handle leading sign characters. If you need
7675-- to handle signed input, use @'signed' 'hexadecimal'@.
Data/Text/Read.hs+3−4
@@ -9,7 +9,6 @@
99--
1010-- License : BSD-style
1111-- Maintainer : bos@serpentine.com
12−-- Stability : experimental
1312-- Portability : GHC
1413--
1514-- Functions used frequently when reading textual data.
@@ -67,9 +66,9 @@ decimal txt
6766 go n d = (n * 10 + fromIntegral (digitToInt d))
6867
6968-- | Read a hexadecimal integer, consisting of an optional leading
70−-- @\"0x\"@ followed by at least one decimal digit. Input is consumed
71−-- until a non-hex-digit or end of string is reached. This function
72−-- is case insensitive.
69+-- @\"0x\"@ followed by at least one hexadecimal digit. Input is
70+-- consumed until a non-hex-digit or end of string is reached.
71+-- This function is case insensitive.
7372--
7473-- This function does not handle leading sign characters. If you need
7574-- to handle signed input, use @'signed' 'hexadecimal'@.
Data/Text/Show.hs+2
@@ -46,6 +46,8 @@ unpack = S.unstreamList . stream
4646-- fusion.
4747--
4848-- This is exposed solely for people writing GHC rewrite rules.
49+--
50+-- @since 1.2.1.1
4951unpackCString# :: Addr# -> Text
5052unpackCString# addr# = unstream (S.streamCString# addr#)
5153{-# NOINLINE unpackCString# #-}
Data/Text/Unsafe.hs+2−1
@@ -7,7 +7,6 @@
77-- Copyright : (c) 2009, 2010, 2011 Bryan O'Sullivan
88-- License : BSD-style
99-- Maintainer : bos@serpentine.com
10−-- Stability : experimental
1110-- Portability : portable
1211--
1312-- A module containing unsafe 'Text' operations, for very very careful
@@ -150,6 +149,8 @@ reverseIter (Text txt) i
150149-- | /O(1)/ Iterate one step backwards through a UTF-16 array,
151150-- returning the delta to add (i.e. a negative number) to give the
152151-- next offset to iterate at.
152+--
153+-- @since 1.1.1.0
153154reverseIter_ :: Text -> Int -> Int
154155#ifndef __GHCJS__
155156reverseIter_ (Text arr off _len) i
README.markdown+5−16
@@ -1,29 +1,18 @@
1−# Text: Fast, packed Unicode strings, using stream fusion
1+# `text`: Fast, packed Unicode strings, using stream fusion
22
33This package provides the Data.Text library, a library for the space-
44and time-efficient manipulation of Unicode text in Haskell.
55
6−
7−# Normalization, conversion, and collation, oh my!
8−
9−This library intentionally provides a simple API based on the
10−Haskell prelude's list manipulation functions. For more complicated
11−real-world tasks, such as Unicode normalization, conversion to and
12−from a larger variety of encodings, and collation, use the [text-icu
13−package](http://hackage.haskell.org/cgi-bin/hackage-scripts/package/text-icu).
14−
15−That library uses the well-respected and liberally licensed ICU
16−library to provide these facilities.
17−
6+**Please refer to the [package description on Hackage](https://hackage.haskell.org/package/text#description) for more information.**
187
198# Get involved!
209
2110Please report bugs via the
22−[github issue tracker](https://github.com/bos/text/issues).
11+[github issue tracker](https://github.com/haskell/text/issues).
2312
24−Master [git repository](https://github.com/bos/text):
13+Master [git repository](https://github.com/haskell/text):
2514
26−* `git clone git://github.com/bos/text.git`
15+* `git clone git://github.com/haskell/text.git`
2716
2817There's also a [Mercurial mirror](https://bitbucket.org/bos/text):
2918
benchmarks/.gitignore+4−1
@@ -1 +1,4 @@
1−dist
1+/dist/
2+/dist-newstyle/
3+/.ghc.environment.*
4+/cabal.project.local
benchmarks/cabal.projectnew file+2
@@ -0,0 +1,2 @@
1+-- NB: we use a separate project
2+packages: .
benchmarks/haskell/Benchmarks.hs+2
@@ -10,6 +10,7 @@ import System.FilePath ((</>))
1010import System.IO (IOMode (WriteMode), openFile, hSetEncoding, utf8)
1111
1212import qualified Benchmarks.Builder as Builder
13+import qualified Benchmarks.Concat as Concat
1314import qualified Benchmarks.DecodeUtf8 as DecodeUtf8
1415import qualified Benchmarks.EncodeUtf8 as EncodeUtf8
1516import qualified Benchmarks.Equality as Equality
@@ -41,6 +42,7 @@ benchmarks = do
4142 -- Traditional benchmarks
4243 bs <- sequence
4344 [ Builder.benchmark
45+ , Concat.benchmark
4446 , DecodeUtf8.benchmark "html" (tf "libya-chinese.html")
4547 , DecodeUtf8.benchmark "xml" (tf "yiwiki.xml")
4648 , DecodeUtf8.benchmark "ascii" (tf "ascii.txt")
benchmarks/haskell/Benchmarks/Concat.hsnew file+25
@@ -0,0 +1,25 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+
3+module Benchmarks.Concat (benchmark) where
4+
5+import Control.Monad.Trans.Writer
6+import Criterion (Benchmark, bgroup, bench, whnf)
7+import Data.Text as T
8+
9+benchmark :: IO Benchmark
10+benchmark = return $ bgroup "Concat"
11+ [ bench "append" $ whnf (append4 "Text 1" "Text 2" "Text 3") "Text 4"
12+ , bench "concat" $ whnf (concat4 "Text 1" "Text 2" "Text 3") "Text 4"
13+ , bench "write" $ whnf (write4 "Text 1" "Text 2" "Text 3") "Text 4"
14+ ]
15+
16+append4, concat4, write4 :: Text -> Text -> Text -> Text -> Text
17+
18+{-# NOINLINE append4 #-}
19+append4 x1 x2 x3 x4 = x1 `append` x2 `append` x3 `append` x4
20+
21+{-# NOINLINE concat4 #-}
22+concat4 x1 x2 x3 x4 = T.concat [x1, x2, x3, x4]
23+
24+{-# NOINLINE write4 #-}
25+write4 x1 x2 x3 x4 = execWriter $ tell x1 >> tell x2 >> tell x3 >> tell x4
benchmarks/text-benchmarks.cabal+82−8
@@ -12,8 +12,7 @@ author: Jasper Van der Jeugt <jaspervdj@gmail.com>,
1212maintainer: jaspervdj@gmail.com
1313category: Text
1414build-type: Simple
15−
16−cabal-version: >=1.2
15+cabal-version: >=1.8
1716
1817flag bytestring-builder
1918 description: Depend on the bytestring-builder package for backwards compatibility.
@@ -26,16 +25,12 @@ flag llvm
2625 manual: True
2726
2827executable text-benchmarks
29− hs-source-dirs: haskell ..
30− c-sources: ../cbits/cbits.c
31− cbits/time_iconv.c
32− include-dirs: ../include
33− main-is: Benchmarks.hs
3428 ghc-options: -Wall -O2 -rtsopts
3529 if flag(llvm)
3630 ghc-options: -fllvm
3731 cpp-options: -DHAVE_DEEPSEQ -DINTEGER_GMP
38− build-depends: base == 4.*,
32+ build-depends: array,
33+ base == 4.*,
3934 binary,
4035 blaze-builder,
4136 bytestring-lexing >= 0.5.0,
@@ -47,6 +42,7 @@ executable text-benchmarks
4742 ghc-prim,
4843 integer-gmp,
4944 stringsearch,
45+ transformers,
5046 utf8-string,
5147 vector
5248
@@ -56,9 +52,87 @@ executable text-benchmarks
5652 else
5753 build-depends: bytestring >= 0.10.4
5854
55+ -- modules for benchmark proper
56+ c-sources: cbits/time_iconv.c
57+ hs-source-dirs: haskell
58+ main-is: Benchmarks.hs
59+ other-modules:
60+ Benchmarks.Builder
61+ Benchmarks.Concat
62+ Benchmarks.DecodeUtf8
63+ Benchmarks.EncodeUtf8
64+ Benchmarks.Equality
65+ Benchmarks.FileRead
66+ Benchmarks.FoldLines
67+ Benchmarks.Mul
68+ Benchmarks.Programs.BigTable
69+ Benchmarks.Programs.Cut
70+ Benchmarks.Programs.Fold
71+ Benchmarks.Programs.Sort
72+ Benchmarks.Programs.StripTags
73+ Benchmarks.Programs.Throughput
74+ Benchmarks.Pure
75+ Benchmarks.ReadNumbers
76+ Benchmarks.Replace
77+ Benchmarks.Search
78+ Benchmarks.Stream
79+ Benchmarks.WordFrequencies
80+
81+ -- Source code for IUT (implementation under test)
82+ -- "borrowed" from parent folder
83+ include-dirs: ../include
84+ c-sources: ../cbits/cbits.c
85+ hs-source-dirs: ..
86+ other-modules:
87+ Data.Text
88+ Data.Text.Array
89+ Data.Text.Encoding
90+ Data.Text.Encoding.Error
91+ Data.Text.Foreign
92+ Data.Text.IO
93+ Data.Text.Internal
94+ Data.Text.Internal.Builder
95+ Data.Text.Internal.Builder.Functions
96+ Data.Text.Internal.Builder.Int.Digits
97+ Data.Text.Internal.Builder.RealFloat.Functions
98+ Data.Text.Internal.Encoding.Fusion
99+ Data.Text.Internal.Encoding.Fusion.Common
100+ Data.Text.Internal.Encoding.Utf16
101+ Data.Text.Internal.Encoding.Utf32
102+ Data.Text.Internal.Encoding.Utf8
103+ Data.Text.Internal.Functions
104+ Data.Text.Internal.Fusion
105+ Data.Text.Internal.Fusion.CaseMapping
106+ Data.Text.Internal.Fusion.Common
107+ Data.Text.Internal.Fusion.Size
108+ Data.Text.Internal.Fusion.Types
109+ Data.Text.Internal.IO
110+ Data.Text.Internal.Lazy
111+ Data.Text.Internal.Lazy.Encoding.Fusion
112+ Data.Text.Internal.Lazy.Fusion
113+ Data.Text.Internal.Lazy.Search
114+ Data.Text.Internal.Private
115+ Data.Text.Internal.Read
116+ Data.Text.Internal.Search
117+ Data.Text.Internal.Unsafe
118+ Data.Text.Internal.Unsafe.Char
119+ Data.Text.Internal.Unsafe.Shift
120+ Data.Text.Lazy
121+ Data.Text.Lazy.Builder
122+ Data.Text.Lazy.Builder.Int
123+ Data.Text.Lazy.Builder.RealFloat
124+ Data.Text.Lazy.Encoding
125+ Data.Text.Lazy.IO
126+ Data.Text.Lazy.Internal
127+ Data.Text.Lazy.Read
128+ Data.Text.Read
129+ Data.Text.Unsafe
130+ Data.Text.Show
131+
59132executable text-multilang
60133 hs-source-dirs: haskell
61134 main-is: Multilang.hs
135+ other-modules: Timer
62136 ghc-options: -Wall -O2
63137 build-depends: base == 4.*,
64138 bytestring,
cabal.projectnew file+3
@@ -0,0 +1,3 @@
1+-- See http://cabal.readthedocs.io/en/latest/nix-local-build-overview.html
2+packages: .
3+tests: True
cbits/cbits.c+6−11
@@ -206,11 +206,9 @@ _hs_text_decode_utf8_state(uint16_t *const dest, size_t *destoff,
206206 const uint8_t *srcend,
207207 uint32_t *codepoint0, uint32_t *state0)
208208{
209− uint8_t const *ret = _hs_text_decode_utf8_int(dest, destoff, src, srcend,
210− codepoint0, state0);
211− if (*state0 == UTF8_REJECT)
212− ret -=1;
213− return ret;
209+ _hs_text_decode_utf8_int(dest, destoff, src, srcend, codepoint0, state0);
210+
211+ return *src;
214212}
215213
216214/*
@@ -222,12 +220,9 @@ _hs_text_decode_utf8(uint16_t *const dest, size_t *destoff,
222220{
223221 uint32_t codepoint;
224222 uint32_t state = UTF8_ACCEPT;
225− uint8_t const *ret = _hs_text_decode_utf8_int(dest, destoff, &src, srcend,
226− &codepoint, &state);
227− /* Back up if we have an incomplete or invalid encoding */
228− if (state != UTF8_ACCEPT)
229− ret -= 1;
230− return ret;
223+ _hs_text_decode_utf8_int(dest, destoff, &src, srcend,
224+ &codepoint, &state);
225+ return src;
231226}
232227
233228void
changelog.md+61−19
@@ -1,15 +1,57 @@
1−1.2.2.1
1+### 1.2.3.1 TBD
2+
3+* Make `decodeUtf8With` fail explicitly for unsupported non-BMP
4+ replacement characters instead silent undefined behaviour (gh-213)
5+
6+### 1.2.3.0
7+
8+* Spec compliance: `toCaseFold` now follows the Unicode 9.0 spec
9+ (updated from 8.0).
10+
11+* Bug fix: the lazy `takeWhileEnd` function violated the
12+ [lazy text invariant](https://github.com/bos/text/blob/1.2.3.0/Data/Text/Internal/Lazy.hs#L51)
13+ (gh-184).
14+
15+* Bug fix: Fixed usage of size hints causing incorrect behavior (gh-197).
16+
17+* New function: `unsnoc` (gh-173).
18+
19+* Reduce memory overhead in `encodeUTF8` (gh-194).
20+
21+* Improve UTF-8 decoder error-recovery (gh-182).
22+
23+* Minor documentation improvements (`@since` annotations, more
24+ examples, clarifications).
25+
26+#### 1.2.2.2
27+
28+* The `toTitle` function now correctly handles letters that
29+ immediately follow punctuation. Before, `"there's"` would turn into
30+ `"There'S"`. Now, it becomes `"There's"`.
31+
32+* The implementation of unstreaming is faster, resulting in operations
33+ such as `map` and `intersperse` speeding up by up to 30%, with
34+ smaller code generated.
35+
36+* The optimised length comparison function is now more likely to be
37+ used after some rewrite rule tweaking.
38+
39+* Bug fix: an off-by-one bug in `takeEnd` is fixed.
40+
41+* Bug fix: a logic error in `takeWord16` is fixed.
42+
43+#### 1.2.2.1
244
345* The switch to `integer-pure` in 1.2.2.0 was apparently mistaken.
446 The build flag has been renamed accordingly. Your army of diligent
547 maintainers apologizes for the churn.
648
7−* Spec compliance: toCaseFold now follows the Unicode 8.0 spec
49+* Spec compliance: `toCaseFold` now follows the Unicode 8.0 spec
850 (updated from 7.0)
951
1052* An STG lint error has been fixed
1153
12−1.2.2.0
54+### 1.2.2.0
1355
1456* The `integer-simple` package, upon which this package optionally
1557 depended, has been replaced with `integer-pure`. The build flag has
@@ -25,7 +67,7 @@
2567 * if `base` >= 4.7: `PrintfArg`
2668 * if `base` >= 4.9: `Semigroup`
2769
28−1.2.1.3
70+#### 1.2.1.3
2971
3072* Bug fix: As it turns out, moving the literal rewrite rules to simplifier
3173 phase 2 does not prevent competition with the `unpack` rule, which is
@@ -33,7 +75,7 @@
3375 test environment mistake. Moving literal rules back to phase 1 finally
3476 fixes GHC Trac #10528 correctly.
3577
36−1.2.1.2
78+#### 1.2.1.2
3779
3880* Bug fix: Run literal rewrite rules in simplifier phase 2.
3981 The behavior of the simplifier changed in GHC 7.10.2,
@@ -41,21 +83,21 @@
4183 and long compilation times. See
4284 [GHC Trac #10528](https://ghc.haskell.org/trac/ghc/ticket/10528).
4385
44−1.2.1.1
86+#### 1.2.1.1
4587
4688* Expose unpackCString#, which you should never use.
4789
48−1.2.1.0
90+### 1.2.1.0
4991
5092* Added Binary instances for both Text types. (If you have previously
5193 been using the text-binary package to get a Binary instance, it is
5294 now obsolete.)
5395
54−1.2.0.6
96+#### 1.2.0.6
5597
5698* Fixed a space leak in UTF-8 decoding
5799
58−1.2.0.5
100+#### 1.2.0.5
59101
60102* Feature parity: repeat, cycle, iterate are now implemented for lazy
61103 Text, and the Data instance is more complete
@@ -75,26 +117,26 @@
75117* Spec compliance: toCaseFold now follows the Unicode 7.0 spec
76118 (updated from 6.3)
77119
78−1.2.0.4
120+#### 1.2.0.4
79121
80122* Fixed an incompatibility with base < 4.5
81123
82−1.2.0.3
124+#### 1.2.0.3
83125
84126* Update formatRealFloat to correspond to the definition in versions
85127 of base newer than 4.5 (https://github.com/bos/text/issues/105)
86128
87−1.2.0.2
129+#### 1.2.0.2
88130
89131* Bumped lower bound on deepseq to 1.4 for compatibility with the
90132 upcoming GHC 7.10
91133
92−1.2.0.1
134+#### 1.2.0.1
93135
94136* Fixed a buffer overflow in rendering of large Integers
95137 (https://github.com/bos/text/issues/99)
96138
97−1.2.0.0
139+## 1.2.0.0
98140
99141* Fixed an integer overflow in the replace function
100142 (https://github.com/bos/text/issues/81)
@@ -107,7 +149,7 @@
107149
108150* Added an instance of IsList for GHC 7.8 and above
109151
110−1.1.1.0
152+### 1.1.1.0
111153
112154* The Data.Data instance now allows gunfold to work, via a virtual
113155 pack constructor
@@ -117,12 +159,12 @@
117159* Comparing the length of a Text against a number can now
118160 short-circuit in more cases
119161
120−1.1.0.1
162+#### 1.1.0.1
121163
122164* streamDecodeUtf8: fixed gh-70, did not return all unconsumed bytes
123165 in single-byte chunks
124166
125−1.1.0.0
167+## 1.1.0.0
126168
127169* encodeUtf8: Performance is improved by up to 4x.
128170
@@ -141,12 +183,12 @@
141183 use at your own risk - there are no API stability guarantees for
142184 internal modules!
143185
144−1.0.0.1
186+#### 1.0.0.1
145187
146188* decodeUtf8: Fixed a regression that caused us to incorrectly
147189 identify truncated UTF-8 as valid (gh-61)
148190
149−1.0.0.0
191+# 1.0.0.0
150192
151193* Added support for Unicode 6.3.0 to case conversion functions
152194
tests-and-benchmarks.markdown+13−8
@@ -13,10 +13,13 @@ you can clone from one of the following locations:
1313* Git mirror repository:
1414 [github.com/bos/text-test-data](https://github.com/bos/text-test-data)
1515
16−You should clone that repository into the `tests` subdirectory (your
17−clone must be named `text-test-data` locally), then run `make -C
18−tests/text-test-data` to uncompress the test files. Many tests and
19−benchmarks will fail if the test files are missing.
16+You can clone either repository into the `tests` subdirectory using
17+
18+ cd tests/
19+ make text-test-data # to clone from mercurial, OR
20+ make VCS=git text-test-data # to clone from git
21+
22+Many tests and benchmarks will fail if the test files are missing.
2023
2124Functional tests
2225----------------
@@ -54,10 +57,12 @@ To compile the benchmarks, navigate to the `benchmarks` subdirectory and run
5457
5558 ./dist/build/text-benchmarks/text-benchmarks
5659
57−However, since there's quite a lot of benchmarks, you usually don't want to
58−run them all. Instead, use the `-l` flag to get a list of benchmarks:
60+Or if you have a recent enough `cabal`, you can build and run the
61+benchmarks via
5962
60− ./dist/build/text-benchmarks/text-benchmarks
63+ cabal new-run exe:text-benchmarks -- --help
6164
62−And run the ones you want to inspect. If you want to configure the benchmarks
65+However, since there's quite a lot of benchmarks, you usually don't want to
66+run them all. Instead, use the `-l` flag to get a list of benchmarks
67+and run the ones you want to inspect. If you want to configure the benchmarks
6368further, the exact parameters can be changed in `Benchmarks.hs`.
tests/Makefile+6−1
@@ -1,3 +1,4 @@
1+VCS = hg
12count = 1000
23
34all: coverage literal-rule-test
@@ -12,7 +13,11 @@ build: text-test-data
1213 cabal build
1314
1415text-test-data:
16+ifeq ($(VCS),git)
17+ git clone https://github.com/bos/text-test-data.git
18+else
1519 hg clone https://bitbucket.org/bos/text-test-data
20+endif
1621 $(MAKE) -C text-test-data
1722
1823coverage/text-tests.tix:
@@ -37,4 +42,4 @@ coverage/hpc_index.html: coverage/coverage.tix
3742clean:
3843 rm -rf dist coverage .hpc
3944
40−.PHONY: build coverage all literal-rule-test
45+.PHONY: all build clean coverage literal-rule-test
tests/Tests/Properties.hs+94−21
@@ -9,9 +9,9 @@ module Tests.Properties
99 ) where
1010
1111import Control.Applicative ((<$>), (<*>))
12−import Control.Arrow ((***), second)
12+import Control.Arrow ((***), first, second)
1313import Data.Bits ((.&.))
14−import Data.Char (chr, isDigit, isHexDigit, isLower, isSpace, isUpper, ord)
14+import Data.Char (chr, isDigit, isHexDigit, isLower, isSpace, isLetter, isUpper, ord)
1515import Data.Int (Int8, Int16, Int32, Int64)
1616import Data.Monoid (Monoid(..))
1717import Data.String (IsString(fromString))
@@ -23,6 +23,7 @@ import Data.Text.Internal.Search (indices)
2323import Data.Text.Lazy.Read as TL
2424import Data.Text.Read as T
2525import Data.Word (Word, Word8, Word16, Word32, Word64)
26+import Data.Maybe (mapMaybe)
2627import Numeric (showEFloat, showFFloat, showGFloat, showHex)
2728import Prelude hiding (replicate)
2829import Test.Framework (Test, testGroup)
@@ -30,6 +31,7 @@ import Test.Framework.Providers.QuickCheck2 (testProperty)
3031import Test.QuickCheck hiding ((.&.))
3132import Test.QuickCheck.Monadic
3233import Test.QuickCheck.Property (Property(..))
34+import Test.QuickCheck.Unicode (char)
3335import Tests.QuickCheckUtils
3436import Tests.Utils
3537import Text.Show.Functions ()
@@ -37,6 +39,7 @@ import qualified Control.Exception as Exception
3739import qualified Data.Bits as Bits (shiftL, shiftR)
3840import qualified Data.ByteString as B
3941import qualified Data.ByteString.Lazy as BL
42+import qualified Data.Char as C
4043import qualified Data.List as L
4144import qualified Data.Text as T
4245import qualified Data.Text.Encoding as E
@@ -60,10 +63,10 @@ t_pack_unpack = (T.unpack . T.pack) `eq` id
6063tl_pack_unpack = (TL.unpack . TL.pack) `eq` id
6164t_stream_unstream = (S.unstream . S.stream) `eq` id
6265tl_stream_unstream = (SL.unstream . SL.stream) `eq` id
63−t_reverse_stream t = (S.reverse . S.reverseStream) t == t
64−t_singleton c = [c] == (T.unpack . T.singleton) c
65−tl_singleton c = [c] == (TL.unpack . TL.singleton) c
66−tl_unstreamChunks x = f 11 x == f 1000 x
66+t_reverse_stream t = (S.reverse . S.reverseStream) t === t
67+t_singleton c = [c] === (T.unpack . T.singleton) c
68+tl_singleton c = [c] === (TL.unpack . TL.singleton) c
69+tl_unstreamChunks x = f 11 x === f 1000 x
6770 where f n = SL.unstreamChunks n . S.streamList
6871tl_chunk_unchunk = (TL.fromChunks . TL.toChunks) `eq` id
6972tl_from_to_strict = (TL.fromStrict . TL.toStrict) `eq` id
@@ -74,13 +77,13 @@ encodeL1 = B.pack . map (fromIntegral . fromEnum) . T.unpack
7477encodeLazyL1 :: TL.Text -> BL.ByteString
7578encodeLazyL1 = BL.fromChunks . map encodeL1 . TL.toChunks
7679
77−t_ascii t = E.decodeASCII (E.encodeUtf8 a) == a
80+t_ascii t = E.decodeASCII (E.encodeUtf8 a) === a
7881 where a = T.map (\c -> chr (ord c `mod` 128)) t
79−tl_ascii t = EL.decodeASCII (EL.encodeUtf8 a) == a
82+tl_ascii t = EL.decodeASCII (EL.encodeUtf8 a) === a
8083 where a = TL.map (\c -> chr (ord c `mod` 128)) t
81−t_latin1 t = E.decodeLatin1 (encodeL1 a) == a
84+t_latin1 t = E.decodeLatin1 (encodeL1 a) === a
8285 where a = T.map (\c -> chr (ord c `mod` 256)) t
83−tl_latin1 t = EL.decodeLatin1 (encodeLazyL1 a) == a
86+tl_latin1 t = EL.decodeLatin1 (encodeLazyL1 a) === a
8487 where a = TL.map (\c -> chr (ord c `mod` 256)) t
8588t_utf8 = forAll genUnicode $ (E.decodeUtf8 . E.encodeUtf8) `eq` id
8689t_utf8' = forAll genUnicode $ (E.decodeUtf8' . E.encodeUtf8) `eq` (id . Right)
@@ -111,7 +114,7 @@ t_utf8_undecoded = forAll genUnicode $ \t ->
111114 let b = E.encodeUtf8 t
112115 ls = concatMap (leftover . E.encodeUtf8 . T.singleton) . T.unpack $ t
113116 leftover = (++ [B.empty]) . init . tail . B.inits
114− in (map snd . feedChunksOf 1 E.streamDecodeUtf8) b == ls
117+ in (map snd . feedChunksOf 1 E.streamDecodeUtf8) b === ls
115118
116119data Badness = Solo | Leading | Trailing
117120 deriving (Eq, Show)
@@ -177,6 +180,33 @@ genInvalidUTF8 = B.pack <$> oneof [
177180 k <- choose (0,n)
178181 vectorOf k gen
179182
183+-- See http://unicode.org/faq/utf_bom.html#gen8
184+-- A sequence such as <110xxxxx2 0xxxxxxx2> is illegal ...
185+-- When faced with this illegal byte sequence ... a UTF-8 conformant process
186+-- must treat the first byte 110xxxxx2 as an illegal termination error
187+-- (e.g. filter it out or replace by 0xFFFD) ...
188+-- ... and continue processing at the second byte 0xxxxxxx2
189+t_decode_with_error2 =
190+ E.decodeUtf8With (\_ _ -> Just 'x') (B.pack [0xC2, 97]) === "xa"
191+t_decode_with_error3 =
192+ E.decodeUtf8With (\_ _ -> Just 'x') (B.pack [0xE0, 97, 97]) === "xaa"
193+t_decode_with_error4 =
194+ E.decodeUtf8With (\_ _ -> Just 'x') (B.pack [0xF0, 97, 97, 97]) === "xaaa"
195+
196+t_decode_with_error2' =
197+ case E.streamDecodeUtf8With (\_ _ -> Just 'x') (B.pack [0xC2, 97]) of
198+ E.Some x _ _ -> x === "xa"
199+t_decode_with_error3' =
200+ case E.streamDecodeUtf8With (\_ _ -> Just 'x') (B.pack [0xC2, 97, 97]) of
201+ E.Some x _ _ -> x === "xaa"
202+t_decode_with_error4' =
203+ case E.streamDecodeUtf8With (\_ _ -> Just 'x') (B.pack [0xC2, 97, 97, 97]) of
204+ E.Some x _ _ -> x === "xaaa"
205+
206+t_infix_concat bs1 text bs2 rep =
207+ text `T.isInfixOf`
208+ E.decodeUtf8With (\_ _ -> rep) (B.concat [bs1, E.encodeUtf8 text, bs2])
209+
180210s_Eq s = (s==) `eq` ((S.streamList s==) . S.streamList)
181211 where _types = s :: String
182212sf_Eq p s =
@@ -201,8 +231,8 @@ t_mconcat = unsquare $
201231 mconcat `eq` (unpackS . mconcat . L.map T.pack)
202232tl_mconcat = unsquare $
203233 mconcat `eq` (unpackS . mconcat . L.map TL.pack)
204−t_mempty = mempty == (unpackS (mempty :: T.Text))
205−tl_mempty = mempty == (unpackS (mempty :: TL.Text))
234+t_mempty = mempty === (unpackS (mempty :: T.Text))
235+tl_mempty = mempty === (unpackS (mempty :: TL.Text))
206236t_IsString = fromString `eqP` (T.unpack . fromString)
207237tl_IsString = fromString `eqP` (TL.unpack . fromString)
208238
@@ -229,6 +259,13 @@ sf_uncons p = (uncons . L.filter p) `eqP`
229259 (fmap (second unpackS) . S.uncons . S.filter p)
230260t_uncons = uncons `eqP` (fmap (second unpackS) . T.uncons)
231261tl_uncons = uncons `eqP` (fmap (second unpackS) . TL.uncons)
262+
263+unsnoc xs@(_:_) = Just (init xs, last xs)
264+unsnoc [] = Nothing
265+
266+t_unsnoc = unsnoc `eqP` (fmap (first unpackS) . T.unsnoc)
267+tl_unsnoc = unsnoc `eqP` (fmap (first unpackS) . TL.unsnoc)
268+
232269s_head = head `eqP` S.head
233270sf_head p = (head . L.filter p) `eqP` (S.head . S.filter p)
234271t_head = head `eqP` T.head
@@ -326,6 +363,19 @@ t_toUpper_upper t = p (T.toUpper t) >= p t
326363 where p = T.length . T.filter isUpper
327364tl_toUpper_upper t = p (TL.toUpper t) >= p t
328365 where p = TL.length . TL.filter isUpper
366+t_toTitle_title t = all (<= 1) (caps w)
367+ where caps = fmap (T.length . T.filter isUpper) . T.words . T.toTitle
368+ -- TIL: there exist uppercase-only letters
369+ w = T.filter (\c -> if C.isUpper c then C.toLower c /= c else True) t
370+t_toTitle_1stNotLower = and . notLow . T.toTitle . T.filter stable
371+ where notLow = mapMaybe (fmap (not . isLower) . (T.find isLetter)) . T.words
372+ -- Surprise! The Spanish/Portuguese ordinal indicators changed
373+ -- from category Ll (letter, lowercase) to Lo (letter, other)
374+ -- in Unicode 7.0
375+ -- Oh, and there exist lowercase-only letters (see previous test)
376+ stable c = if isLower c
377+ then C.toUpper c /= c
378+ else c /= '\170' && c /= '\186'
329379
330380justifyLeft k c xs = xs ++ L.replicate (k - length xs) c
331381justifyRight m n xs = L.replicate (m - length xs) n ++ xs
@@ -514,12 +564,20 @@ s_takeWhile p = L.takeWhile p `eqP` (unpackS . S.takeWhile p)
514564s_takeWhile_s p = L.takeWhile p `eqP` (unpackS . S.unstream . S.takeWhile p)
515565sf_takeWhile q p = (L.takeWhile p . L.filter q) `eqP`
516566 (unpackS . S.takeWhile p . S.filter q)
567+noMatch = do
568+ c <- char
569+ d <- suchThat char (/= c)
570+ return (c,d)
517571t_takeWhile p = L.takeWhile p `eqP` (unpackS . T.takeWhile p)
518572tl_takeWhile p = L.takeWhile p `eqP` (unpackS . TL.takeWhile p)
519573t_takeWhileEnd p = (L.reverse . L.takeWhile p . L.reverse) `eqP`
520574 (unpackS . T.takeWhileEnd p)
575+t_takeWhileEnd_null t = forAll noMatch $ \(c,d) -> T.null $
576+ T.takeWhileEnd (==d) (T.snoc t c)
521577tl_takeWhileEnd p = (L.reverse . L.takeWhile p . L.reverse) `eqP`
522578 (unpackS . TL.takeWhileEnd p)
579+tl_takeWhileEnd_null t = forAll noMatch $ \(c,d) -> TL.null $
580+ TL.takeWhileEnd (==d) (TL.snoc t c)
523581s_dropWhile p = L.dropWhile p `eqP` (unpackS . S.dropWhile p)
524582s_dropWhile_s p = L.dropWhile p `eqP` (unpackS . S.unstream . S.dropWhile p)
525583sf_dropWhile q p = (L.dropWhile p . L.filter q) `eqP`
@@ -720,7 +778,7 @@ tl_indices (NotEmpty s) = lazyIndices s `eq` S.indices s
720778 conc = T.concat . TL.toChunks
721779t_indices_occurs = unsquare $ \(NotEmpty t) ts ->
722780 let s = T.intercalate t ts
723− in Slow.indices t s == indices t s
781+ in Slow.indices t s === indices t s
724782
725783-- Bit shifts.
726784shiftL w = forAll (choose (0,width-1)) $ \k -> Bits.shiftL w k == U.shiftL w k
@@ -812,18 +870,18 @@ tb_formatRealFloat_double (a::Double) = tb_formatRealFloat a
812870-- Reading.
813871
814872t_decimal (n::Int) s =
815− T.signed T.decimal (T.pack (show n) `T.append` t) == Right (n,t)
873+ T.signed T.decimal (T.pack (show n) `T.append` t) === Right (n,t)
816874 where t = T.dropWhile isDigit s
817875tl_decimal (n::Int) s =
818− TL.signed TL.decimal (TL.pack (show n) `TL.append` t) == Right (n,t)
876+ TL.signed TL.decimal (TL.pack (show n) `TL.append` t) === Right (n,t)
819877 where t = TL.dropWhile isDigit s
820878t_hexadecimal m s ox =
821− T.hexadecimal (T.concat [p, T.pack (showHex n ""), t]) == Right (n,t)
879+ T.hexadecimal (T.concat [p, T.pack (showHex n ""), t]) === Right (n,t)
822880 where t = T.dropWhile isHexDigit s
823881 p = if ox then "0x" else ""
824882 n = getPositive m :: Int
825883tl_hexadecimal m s ox =
826− TL.hexadecimal (TL.concat [p, TL.pack (showHex n ""), t]) == Right (n,t)
884+ TL.hexadecimal (TL.concat [p, TL.pack (showHex n ""), t]) === Right (n,t)
827885 where t = TL.dropWhile isHexDigit s
828886 p = if ox then "0x" else ""
829887 n = getPositive m :: Int
@@ -867,11 +925,11 @@ tl_write_read_line e m b t = write_read head TL.filter TL.hPutStrLn
867925
868926t_dropWord16 m t = dropWord16 m t `T.isSuffixOf` t
869927t_takeWord16 m t = takeWord16 m t `T.isPrefixOf` t
870−t_take_drop_16 m t = T.append (takeWord16 n t) (dropWord16 n t) == t
928+t_take_drop_16 m t = T.append (takeWord16 n t) (dropWord16 n t) === t
871929 where n = small m
872930t_use_from t = monadicIO $ assert . (==t) =<< run (useAsPtr t fromPtr)
873931
874−t_copy t = T.copy t == t
932+t_copy t = T.copy t === t
875933
876934-- Regression tests.
877935s_filter_eq s = S.filter p t == S.streamList (filter p s)
@@ -924,6 +982,15 @@ tests =
924982 testGroup "errors" [
925983 testProperty "t_utf8_err" t_utf8_err,
926984 testProperty "t_utf8_err'" t_utf8_err'
985+ ],
986+ testGroup "error recovery" [
987+ testProperty "t_decode_with_error2" t_decode_with_error2,
988+ testProperty "t_decode_with_error3" t_decode_with_error3,
989+ testProperty "t_decode_with_error4" t_decode_with_error4,
990+ testProperty "t_decode_with_error2'" t_decode_with_error2',
991+ testProperty "t_decode_with_error3'" t_decode_with_error3',
992+ testProperty "t_decode_with_error4'" t_decode_with_error4',
993+ testProperty "t_infix_concat" t_infix_concat
927994 ]
928995 ],
929996
@@ -967,6 +1034,8 @@ tests =
9671034 testProperty "sf_uncons" sf_uncons,
9681035 testProperty "t_uncons" t_uncons,
9691036 testProperty "tl_uncons" tl_uncons,
1037+ testProperty "t_unsnoc" t_unsnoc,
1038+ testProperty "tl_unsnoc" tl_unsnoc,
9701039 testProperty "s_head" s_head,
9711040 testProperty "sf_head" sf_head,
9721041 testProperty "t_head" t_head,
@@ -1030,7 +1099,9 @@ tests =
10301099 testProperty "tl_toLower_lower" tl_toLower_lower,
10311100 testProperty "t_toUpper_length" t_toUpper_length,
10321101 testProperty "t_toUpper_upper" t_toUpper_upper,
1033− testProperty "tl_toUpper_upper" tl_toUpper_upper
1102+ testProperty "tl_toUpper_upper" tl_toUpper_upper,
1103+ testProperty "t_toTitle_title" t_toTitle_title,
1104+ testProperty "t_toTitle_1stNotLower" t_toTitle_1stNotLower
10341105 ],
10351106
10361107 testGroup "justification" [
@@ -1147,7 +1218,9 @@ tests =
11471218 testProperty "t_takeWhile" t_takeWhile,
11481219 testProperty "tl_takeWhile" tl_takeWhile,
11491220 testProperty "t_takeWhileEnd" t_takeWhileEnd,
1221+ testProperty "t_takeWhileEnd_null" t_takeWhileEnd_null,
11501222 testProperty "tl_takeWhileEnd" tl_takeWhileEnd,
1223+ testProperty "tl_takeWhileEnd_null" tl_takeWhileEnd_null,
11511224 testProperty "sf_dropWhile" sf_dropWhile,
11521225 testProperty "s_dropWhile" s_dropWhile,
11531226 testProperty "s_dropWhile_s" s_dropWhile_s,
tests/Tests/QuickCheckUtils.hs+1−1
@@ -106,7 +106,7 @@ smallArbitrary = sized $ \n -> resize (smallish n) arbitrary
106106 where smallish = round . (sqrt :: Double -> Double) . fromIntegral . abs
107107
108108instance Arbitrary T.Text where
109− arbitrary = T.pack `fmap` arbitrary
109+ arbitrary = T.pack `fmap` string
110110 shrink = map T.pack . shrink . T.unpack
111111
112112instance Arbitrary TL.Text where
tests/Tests/Regressions.hs+11
@@ -72,6 +72,16 @@ mapAccumL_resize = do
7272 assertEqual "mapAccumL should correctly size buffers for two-word results"
7373 (count * 2) (T.lengthWord16 (snd val))
7474
75+-- See GitHub #197
76+t197 :: IO ()
77+t197 =
78+ assertBool "length (filter (==',') \"0,00\") should be 1" (currencyParser "0,00")
79+ where
80+ currencyParser x = cond == 1
81+ where
82+ cond = length fltr
83+ fltr = filter (== ',') x
84+
7585tests :: F.Test
7686tests = F.testGroup "Regressions"
7787 [ F.testCase "hGetContents_crash" hGetContents_crash
@@ -79,4 +89,5 @@ tests = F.testGroup "Regressions"
7989 , F.testCase "mapAccumL_resize" mapAccumL_resize
8090 , F.testCase "replicate_crash" replicate_crash
8191 , F.testCase "utf8_decode_unsafe" utf8_decode_unsafe
92+ , F.testCase "t197" t197
8293 ]
tests/text-tests.cabal+18−3
@@ -20,6 +20,11 @@ flag hpc
2020 default: False
2121 manual: True
2222
23+flag bytestring-builder
24+ description: Depend on the bytestring-builder package for backwards compatibility.
25+ default: False
26+ manual: False
27+
2328executable text-tests
2429 main-is: Tests.hs
2530
@@ -48,16 +53,21 @@ executable text-tests
4853 HUnit >= 1.2,
4954 QuickCheck >= 2.7,
5055 base == 4.*,
51− bytestring,
5256 deepseq,
5357 directory,
54− quickcheck-unicode,
58+ quickcheck-unicode >= 1.0.1.0,
5559 random,
5660 test-framework >= 0.4,
5761 test-framework-hunit >= 0.2,
5862 test-framework-quickcheck2 >= 0.2,
5963 text-tests
6064
65+ if flag(bytestring-builder)
66+ build-depends: bytestring >= 0.9 && < 0.10.4,
67+ bytestring-builder >= 0.10.4
68+ else
69+ build-depends: bytestring >= 0.10.4
70+
6171executable text-tests-stdio
6272 main-is: Tests/IO.hs
6373
@@ -137,7 +147,12 @@ library
137147 array,
138148 base == 4.*,
139149 binary,
140− bytestring,
141150 deepseq,
142151 ghc-prim,
143152 integer-gmp
153+
154+ if flag(bytestring-builder)
155+ build-depends: bytestring >= 0.9 && < 0.10.4,
156+ bytestring-builder >= 0.10.4
157+ else
158+ build-depends: bytestring >= 0.10.4
text.cabal+100−33
@@ -1,7 +1,7 @@
11name: text
2−version: 1.2.2.1
3−homepage: https://github.com/bos/text
4−bug-reports: https://github.com/bos/text/issues
2+version: 1.2.3.0
3+homepage: https://github.com/haskell/text
4+bug-reports: https://github.com/haskell/text/issues
55synopsis: An efficient packed Unicode text type.
66description:
77 .
@@ -14,11 +14,13 @@ description:
1414 in terms of large data quantities and high speed.
1515 .
1616 The 'Text' type provides character-encoding, type-safe case
17− conversion via whole-string case conversion functions. It also
18− provides a range of functions for converting 'Text' values to and from
19− 'ByteStrings', using several standard encodings.
17+ conversion via whole-string case conversion functions (see "Data.Text").
18+ It also provides a range of functions for converting 'Text' values to
19+ and from 'ByteStrings', using several standard encodings
20+ (see "Data.Text.Encoding").
2021 .
21− Efficient locale-sensitive support for text IO is also supported.
22+ Efficient locale-sensitive support for text IO is also supported
23+ (see "Data.Text.IO").
2224 .
2325 These modules are intended to be imported qualified, to avoid name
2426 clashes with Prelude functions, e.g.
@@ -28,8 +30,9 @@ description:
2830 To use an extended and very rich family of functions for working
2931 with Unicode text (including normalization, regular expressions,
3032 non-standard encodings, text breaking, and locales), see
31− the @text-icu@ package:
32− <http://hackage.haskell.org/package/text-icu>
33+ the [text-icu package](https://hackage.haskell.org/package/text-icu)
34+ based on the well-respected and liberally
35+ licensed [ICU library](http://site.icu-project.org/).
3336
3437license: BSD2
3538license-file: LICENSE
@@ -39,6 +42,8 @@ copyright: 2009-2011 Bryan O'Sullivan, 2008-2009 Tom Harper
3942category: Data, Text
4043build-type: Simple
4144cabal-version: >= 1.8
45+tested-with: GHC==8.2.2, GHC==8.0.2, GHC==7.10.3, GHC==7.8.4,
46+ GHC==7.6.3, GHC==7.4.2, GHC==7.2.2, GHC==7.0.4
4247extra-source-files:
4348 -- scripts/CaseFolding.txt
4449 -- scripts/SpecialCasing.txt
@@ -65,7 +70,9 @@ extra-source-files:
6570 tests/text-tests.cabal
6671
6772flag bytestring-builder
68− description: Depend on the bytestring-builder package for backwards compatibility.
73+ description:
74+ Depend on the [bytestring-builder](https://hackage.haskell.org/package/bytestring-builder)
75+ package for backwards compatibility.
6976 default: False
7077 manual: False
7178
@@ -75,7 +82,9 @@ flag developer
7582 manual: True
7683
7784flag integer-simple
78− description: Use the simple integer library instead of GMP
85+ description:
86+ Use the [simple integer library](http://hackage.haskell.org/package/integer-simple)
87+ instead of [integer-gmp](http://hackage.haskell.org/package/integer-gmp)
7988 default: False
8089 manual: False
8190
@@ -88,13 +97,13 @@ library
8897 Data.Text.Array
8998 Data.Text.Encoding
9099 Data.Text.Encoding.Error
91− -- Data.Text.Foreign
100+ Data.Text.Foreign
92101 Data.Text.IO
93102 Data.Text.Internal
94103 Data.Text.Internal.Builder
95− -- Data.Text.Internal.Builder.Functions
96− -- Data.Text.Internal.Builder.Int.Digits
97− -- Data.Text.Internal.Builder.RealFloat.Functions
104+ Data.Text.Internal.Builder.Functions
105+ Data.Text.Internal.Builder.Int.Digits
106+ Data.Text.Internal.Builder.RealFloat.Functions
98107 Data.Text.Internal.Encoding.Fusion
99108 Data.Text.Internal.Encoding.Fusion.Common
100109 Data.Text.Internal.Encoding.Utf16
@@ -106,14 +115,14 @@ library
106115 Data.Text.Internal.Fusion.Common
107116 Data.Text.Internal.Fusion.Size
108117 Data.Text.Internal.Fusion.Types
109− -- Data.Text.Internal.IO
118+ Data.Text.Internal.IO
110119 Data.Text.Internal.Lazy
111− -- Data.Text.Internal.Lazy.Encoding.Fusion
120+ Data.Text.Internal.Lazy.Encoding.Fusion
112121 Data.Text.Internal.Lazy.Fusion
113122 Data.Text.Internal.Lazy.Search
114123 Data.Text.Internal.Private
115124 Data.Text.Internal.Read
116− -- Data.Text.Internal.Search
125+ Data.Text.Internal.Search
117126 Data.Text.Internal.Unsafe
118127 Data.Text.Internal.Unsafe.Char
119128 Data.Text.Internal.Unsafe.Shift
@@ -124,23 +133,18 @@ library
124133 Data.Text.Lazy.Encoding
125134 Data.Text.Lazy.IO
126135 Data.Text.Lazy.Internal
127− -- Data.Text.Lazy.Read
136+ Data.Text.Lazy.Read
128137 Data.Text.Read
129138 Data.Text.Unsafe
130139
131− -- moved from ghcjs-base
132− -- reflex-dom depends in it
133− Data.JSString.Text
134− -- other-modules:
135− -- Data.Text.Show
140+ other-modules:
141+ Data.Text.Show
136142
137143 build-depends:
138− -- array >= 0.3,
144+ array >= 0.3,
139145 base >= 4.2 && < 5,
140146 binary,
141147 deepseq >= 1.1.0.0,
142− ghcjs-base,
143− ghcjs-prim,
144148 ghc-prim >= 0.2
145149
146150 if flag(bytestring-builder)
@@ -165,27 +169,90 @@ library
165169
166170-- test-suite tests
167171-- type: exitcode-stdio-1.0
168−-- hs-source-dirs: tests .
169−-- main-is: Tests.hs
170172-- c-sources: cbits/cbits.c
171173-- include-dirs: include
172174
173175-- ghc-options:
174−-- -Wall -threaded -O0 -rtsopts
176+-- -Wall -threaded -rtsopts
175177
176178-- cpp-options:
177179-- -DASSERTS -DHAVE_DEEPSEQ -DTEST_SUITE
178180
181+-- -- modules specific to test-suite
182+-- hs-source-dirs: tests
183+-- main-is: Tests.hs
184+-- other-modules:
185+-- Tests.Properties
186+-- Tests.Properties.Mul
187+-- Tests.QuickCheckUtils
188+-- Tests.Regressions
189+-- Tests.SlowFunctions
190+-- Tests.Utils
191+
192+-- -- Same as in `library` stanza; this is needed by cabal for accurate
193+-- -- file-monitoring as well as to avoid `-Wmissing-home-modules`
194+-- -- warnings We can't use an inter-package library dependency because
195+-- -- of different `ghc-options`/`cpp-options` (as a side-benefitt,
196+-- -- this enables per-component build parallelism in `cabal
197+-- -- new-build`!); We could, however, use cabal-version:2.2's `common`
198+-- -- blocks at some point in the future to reduce the duplication.
199+-- hs-source-dirs: .
200+-- other-modules:
201+-- Data.Text
202+-- Data.Text.Array
203+-- Data.Text.Encoding
204+-- Data.Text.Encoding.Error
205+-- Data.Text.Foreign
206+-- Data.Text.IO
207+-- Data.Text.Internal
208+-- Data.Text.Internal.Builder
209+-- Data.Text.Internal.Builder.Functions
210+-- Data.Text.Internal.Builder.Int.Digits
211+-- Data.Text.Internal.Builder.RealFloat.Functions
212+-- Data.Text.Internal.Encoding.Fusion
213+-- Data.Text.Internal.Encoding.Fusion.Common
214+-- Data.Text.Internal.Encoding.Utf16
215+-- Data.Text.Internal.Encoding.Utf32
216+-- Data.Text.Internal.Encoding.Utf8
217+-- Data.Text.Internal.Functions
218+-- Data.Text.Internal.Fusion
219+-- Data.Text.Internal.Fusion.CaseMapping
220+-- Data.Text.Internal.Fusion.Common
221+-- Data.Text.Internal.Fusion.Size
222+-- Data.Text.Internal.Fusion.Types
223+-- Data.Text.Internal.IO
224+-- Data.Text.Internal.Lazy
225+-- Data.Text.Internal.Lazy.Encoding.Fusion
226+-- Data.Text.Internal.Lazy.Fusion
227+-- Data.Text.Internal.Lazy.Search
228+-- Data.Text.Internal.Private
229+-- Data.Text.Internal.Read
230+-- Data.Text.Internal.Search
231+-- Data.Text.Internal.Unsafe
232+-- Data.Text.Internal.Unsafe.Char
233+-- Data.Text.Internal.Unsafe.Shift
234+-- Data.Text.Lazy
235+-- Data.Text.Lazy.Builder
236+-- Data.Text.Lazy.Builder.Int
237+-- Data.Text.Lazy.Builder.RealFloat
238+-- Data.Text.Lazy.Encoding
239+-- Data.Text.Lazy.IO
240+-- Data.Text.Lazy.Internal
241+-- Data.Text.Lazy.Read
242+-- Data.Text.Read
243+-- Data.Text.Unsafe
244+-- Data.Text.Show
245+
179246-- build-depends:
180247-- HUnit >= 1.2,
181−-- QuickCheck >= 2.7,
248+-- QuickCheck >= 2.7 && < 2.10,
182249-- array,
183250-- base,
184251-- binary,
185252-- deepseq,
186253-- directory,
187254-- ghc-prim,
188−-- quickcheck-unicode,
255+-- quickcheck-unicode >= 1.0.1.0,
189256-- random,
190257-- test-framework >= 0.4,
191258-- test-framework-hunit >= 0.2,
@@ -206,7 +273,7 @@ library
206273
207274-- source-repository head
208275-- type: git
209−-- location: https://github.com/bos/text
276+-- location: https://github.com/haskell/text
210277
211278-- source-repository head
212279-- type: mercurial