on 09cd408 help sign in
56 files changed+708−1988
since splitsnapshots
unifiedsplit
.gitignore−1 .hgtags−18 Data/Text.hs+135−256 Data/Text/Array.hs+6−7 Data/Text/Encoding.hs+26−13 Data/Text/Encoding/Error.hs+1−7 Data/Text/Internal.hs+10−74 Data/Text/Internal/Builder.hs+16−19 Data/Text/Internal/Builder/Functions.hs+1−2 Data/Text/Internal/Builder/Int/Digits.hs+1−1 Data/Text/Internal/Builder/RealFloat/Functions.hs−28 Data/Text/Internal/Fusion.hs+28−38 Data/Text/Internal/Fusion/CaseMapping.hs+19−291 Data/Text/Internal/Fusion/Common.hs+75−63 Data/Text/Internal/Fusion/Size.hs+52−60 Data/Text/Internal/Fusion/Types.hs+13−8 Data/Text/Internal/Private.hs+4−4 Data/Text/Internal/Read.hs+3−3 Data/Text/Lazy.hs+25−200 Data/Text/Lazy/Builder.hs+1−1 Data/Text/Lazy/Builder/Int.hs+14−19 Data/Text/Lazy/Encoding.hs+21−9 Data/Text/Lazy/Read.hs+2−4 Data/Text/Read.hs+1−1 Data/Text/Show.hs−89 Data/Text/Unsafe.hs−11 benchmarks/haskell/Benchmarks.hs+1−3 benchmarks/haskell/Benchmarks/DecodeUtf8.hs+2−2 benchmarks/haskell/Benchmarks/FileRead.hs+11−11 benchmarks/haskell/Benchmarks/FoldLines.hs+2−2 benchmarks/haskell/Benchmarks/Mul.hs−138 benchmarks/haskell/Benchmarks/Programs/BigTable.hs+2−2 benchmarks/haskell/Benchmarks/Programs/Cut.hs+2−2 benchmarks/haskell/Benchmarks/Programs/Fold.hs+2−2 benchmarks/haskell/Benchmarks/Programs/Sort.hs+9−10 benchmarks/haskell/Benchmarks/Programs/StripTags.hs+5−5 benchmarks/haskell/Benchmarks/Programs/Throughput.hs+8−8 benchmarks/haskell/Benchmarks/Pure.hs−7 benchmarks/haskell/Benchmarks/ReadNumbers.hs+5−2 benchmarks/haskell/Benchmarks/Stream.hs+5−16 benchmarks/text-benchmarks.cabal+6−18 cbits/cbits.c+6−6 changelog+41 changelog.md−164 scripts/CaseFolding.hs+1−1 scripts/CaseMapping.hs+3−3 scripts/SpecialCasing.hs+1−1 tests/LiteralRuleTest.hs−21 tests/Makefile+1−6 tests/Tests/Properties.hs+48−136 tests/Tests/Properties/Mul.hs−40 tests/Tests/QuickCheckUtils.hs+82−73 tests/cabal.config−6 tests/literal-rule-test.sh−29 tests/text-tests.cabal+3−18 text.cabal+8−29
.gitignore−1
@@ -1,3 +1,2 @@
11dist
22cabal-dev
3−cabal.sandbox.config
.hgtags−18
@@ -46,21 +46,3 @@ d99cd091cdf71ce807a4255f6cc509c3154f51ea 0.11.3.1
46467cba97c86467c1881dfced68613891f3c65561b0 1.0.0.1
474762674a9bbc83145d1d7be28a05d456ab6bb5ff89 1.1.0.0
484868a32d80c0829da164d1e6b3acedcc3efeda0957 1.1.0.1
49−6d863daafbf0e1289ec0a0eb9b4be2a0a9cb8d3d 1.1.1.0
50−fb7299f22449750c653ac64dee4bd63c13ea6e4c 1.1.1.1
51−eb170cb533b63534d166b5fd5344b36676adf140 1.1.1.2
52−e749e05f715d02445803f653cd3d97d5395d7c6f 1.1.1.3
53−b0dff8ca1142595bab489a768ca62e6a6805aac4 1.1.1.4
54−f8a60279237c1c28e094868740d9188dd94fcc9e 1.2.0.0
55−6231451979b2d33e28038b75f2dab19c9731f5c3 1.2.0.1
56−99a3503b4ad001fc1894e90286e96d7dea1e9195 1.2.0.2
57−47f138edf15576b9adaeed64784e30811099f202 1.2.0.3
58−0b064b0c69106bbcd13cb0099e72ae5fa2347bf0 1.2.0.4
59−8bbb3e222a0037035d893f731b0a23be449f7346 1.2.0.5
60−18c7f8e19872762b7e28ee1871e72f70ea54e3cd 1.2.0.6
61−42f751b87b4a187db93f595a8166d51746ff57d4 1.2.1.0
62−78227a84740b70dcd4cf7a65f3bcf603d87e48e2 1.2.1.1
63−40f268e6735749ef36f487e1d928eaa957bb431d 1.2.1.2
64−631fd055e27fa10983e17e9ad36d1b285b85c661 1.2.1.3
65−8221a68ed5ec37028357df9c6c25f52320e54ad9 1.2.2.0
66−ce1c5ac65eb9f5580114b4e380092b05a485e95d 1.2.2.1
Data/Text.hs+135−256
@@ -3,9 +3,6 @@
33#if __GLASGOW_HASKELL__ >= 702
44{-# LANGUAGE Trustworthy #-}
55#endif
6−#if __GLASGOW_HASKELL__ >= 708
7−{-# LANGUAGE TypeFamilies #-}
8−#endif
96
107-- |
118-- Module : Data.Text
@@ -32,8 +29,8 @@
3229--
3330-- To use an extended and very rich family of functions for working
3431-- 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 >.
32+-- non-standard encodings, text breaking, and locales), see the
33+-- @text-icu@ package: <http://hackage.haskell.org/package/text-icu>
3734
3835module Data.Text
3936 (
@@ -125,11 +122,8 @@ module Data.Text
125122
126123 -- ** Breaking strings
127124 , take
128− , takeEnd
129125 , drop
130− , dropEnd
131126 , takeWhile
132− , takeWhileEnd
133127 , dropWhile
134128 , dropWhileEnd
135129 , dropAround
@@ -192,43 +186,35 @@ module Data.Text
192186
193187 -- * Low level operations
194188 , copy
195− , unpackCString#
196189 ) where
197190
198191import Prelude (Char, Bool(..), Int, Maybe(..), String,
199192 Eq(..), Ord(..), Ordering(..), (++),
200− Read(..),
201− (&&), (||), (+), (-), (.), ($), ($!), (>>),
202− not, return, otherwise, quot)
193+ Read(..), Show(..),
194+ (&&), (||), (+), (-), (.), ($), ($!), (>>), (*),
195+ maxBound, not, return, otherwise, quot)
203196#if defined(HAVE_DEEPSEQ)
204−import Control.DeepSeq (NFData(rnf))
197+import Control.DeepSeq (NFData)
205198#endif
206199#if defined(ASSERTS)
207200import Control.Exception (assert)
208201#endif
209202import Data.Char (isSpace)
210−import Data.Data (Data(gfoldl, toConstr, gunfold, dataTypeOf), constrIndex,
211− Constr, mkConstr, DataType, mkDataType, Fixity(Prefix))
203+import Data.Data (Data(gfoldl, toConstr, gunfold, dataTypeOf))
204+import Data.Data (mkNoRepType)
212205import Control.Monad (foldM)
213−import Control.Monad.ST (ST)
214206import qualified Data.Text.Array as A
215207import qualified Data.List as L
216−import Data.Binary (Binary(get, put))
217208import Data.Monoid (Monoid(..))
218−#if MIN_VERSION_base(4,9,0)
219−import Data.Semigroup (Semigroup(..))
220−#endif
221209import Data.String (IsString(..))
222210import qualified Data.Text.Internal.Fusion as S
223211import qualified Data.Text.Internal.Fusion.Common as S
224−import Data.Text.Encoding (decodeUtf8', encodeUtf8)
225212import Data.Text.Internal.Fusion (stream, reverseStream, unstream)
226213import Data.Text.Internal.Private (span_)
227−import Data.Text.Internal (Text(..), empty, firstf, mul, safe, text)
228−import Data.Text.Show (singleton, unpack, unpackCString#)
214+import Data.Text.Internal (Text(..), empty, firstf, safe, text, textP)
229215import qualified Prelude as P
230216import Data.Text.Unsafe (Iter(..), iter, iter_, lengthWord16, reverseIter,
231− reverseIter_, unsafeHead, unsafeTail)
217+ unsafeHead, unsafeTail)
232218import Data.Text.Internal.Unsafe.Char (unsafeChr)
233219import qualified Data.Text.Internal.Functions as F
234220import qualified Data.Text.Internal.Encoding.Utf16 as U16
@@ -238,13 +224,12 @@ import Data.ByteString (ByteString)
238224import qualified Data.Text.Lazy as L
239225import Data.Int (Int64)
240226#endif
241−import GHC.Base (eqInt, neInt, gtInt, geInt, ltInt, leInt)
242−#if __GLASGOW_HASKELL__ >= 708
243−import qualified GHC.Exts as Exts
244−#endif
245−#if MIN_VERSION_base(4,7,0)
246−import Text.Printf (PrintfArg, formatArg, formatString)
227+#if __GLASGOW_HASKELL__ >= 702
228+import qualified GHC.CString as GHC
229+#else
230+import qualified GHC.Base as GHC
247231#endif
232+import GHC.Prim (Addr#)
248233
249234-- $strict
250235--
@@ -254,32 +239,29 @@ import Text.Printf (PrintfArg, formatArg, formatString)
254239-- lazy @Text@ type consists of a list of strict chunks.
255240--
256241-- The strict 'Text' type requires that an entire string fit into
257−-- memory at once. The lazy 'Data.Text.Lazy.Text' type is capable of
258−-- streaming strings that are larger than memory using a small memory
259−-- footprint. In many cases, the overhead of chunked streaming makes
260−-- the lazy 'Data.Text.Lazy.Text' type slower than its strict
261−-- counterpart, but this is not always the case. Sometimes, the time
262−-- complexity of a function in one module may be different from the
263−-- other, due to their differing internal structures.
242+-- memory at once. The lazy @Text@ type is capable of streaming
243+-- strings that are larger than memory using a small memory footprint.
244+-- In many cases, the overhead of chunked streaming makes the lazy
245+-- @Text@ type slower than its strict counterpart, but this is not
246+-- always the case. Sometimes, the time complexity of a function in
247+-- one module may be different from the other, due to their differing
248+-- internal structures.
264249--
265250-- Each module provides an almost identical API, with the main
266251-- difference being that the strict module uses 'Int' values for
267−-- lengths and counts, while the lazy module uses 'Data.Int.Int64'
268−-- lengths.
252+-- lengths and counts, while the lazy module uses 'Int64' lengths.
269253
270254-- $replacement
271255--
272256-- A 'Text' value is a sequence of Unicode scalar values, as defined
273−-- in
274−-- <http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf#page=35 §3.9, definition D76 of the Unicode 5.2 standard >.
275−-- As such, a 'Text' cannot contain values in the range U+D800 to
276−-- U+DFFF inclusive. Haskell implementations admit all Unicode code
277−-- points
278−-- (<http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf#page=13 §3.4, definition D10 >)
279−-- as 'Char' values, including code points from this invalid range.
280−-- This means that there are some 'Char' values that are not valid
281−-- Unicode scalar values, and the functions in this module must handle
282−-- those cases.
257+-- in &#xa7;3.9, definition D76 of the Unicode 5.2 standard:
258+-- <http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf#page=35>. As
259+-- such, a 'Text' cannot contain values in the range U+D800 to U+DFFF
260+-- inclusive. Haskell implementations admit all Unicode code points
261+-- (&#xa7;3.4, definition D10) as 'Char' values, including code points
262+-- from this invalid range. This means that there are some 'Char'
263+-- values that are not valid Unicode scalar values, and the functions
264+-- in this module must handle those cases.
283265--
284266-- Within this module, many functions construct a 'Text' from one or
285267-- more 'Char' values. Those functions will substitute 'Char' values
@@ -293,8 +275,8 @@ import Text.Printf (PrintfArg, formatArg, formatString)
293275-- range U+D800 through U+DFFF are used by UTF-16 to denote surrogate
294276-- code points, and so cannot be represented. The functions replace
295277-- invalid scalar values, instead of dropping them, as a security
296−-- measure. For details, see
297−-- <http://unicode.org/reports/tr36/#Deletion_of_Noncharacters Unicode Technical Report 36, §3.5 >.)
278+-- measure. For details, see Unicode Technical Report 36, &#xa7;3.5:
279+-- <http://unicode.org/reports/tr36/#Deletion_of_Noncharacters>)
298280
299281-- $fusion
300282--
@@ -312,11 +294,11 @@ import Text.Printf (PrintfArg, formatArg, formatString)
312294-- > countChars = T.length . T.toUpper . E.decodeUtf8
313295--
314296-- From the type signatures involved, this looks like it should
315−-- allocate one 'Data.ByteString.ByteString' value, and two 'Text'
316−-- values. However, when a module is compiled with optimisation
317−-- enabled under GHC, the two intermediate 'Text' values will be
318−-- optimised away, and the function will be compiled down to a single
319−-- loop over the source 'Data.ByteString.ByteString'.
297+-- allocate one 'ByteString' value, and two 'Text' values. However,
298+-- when a module is compiled with optimisation enabled under GHC, the
299+-- two intermediate 'Text' values will be optimised away, and the
300+-- function will be compiled down to a single loop over the source
301+-- 'ByteString'.
320302--
321303-- Functions that can be fused by the compiler are documented with the
322304-- phrase \"Subject to fusion\".
@@ -330,82 +312,41 @@ instance Eq Text where
330312instance Ord Text where
331313 compare = compareText
332314
315+instance Show Text where
316+ showsPrec p ps r = showsPrec p (unpack ps) r
317+
333318instance Read Text where
334319 readsPrec p str = [(pack x,y) | (x,y) <- readsPrec p str]
335320
336−#if MIN_VERSION_base(4,9,0)
337−-- Semigroup orphan instances for older GHCs are provided by
338−-- 'semigroups` package
339−
340−instance Semigroup Text where
341− (<>) = append
342−#endif
343−
344321instance Monoid Text where
345322 mempty = empty
346−#if MIN_VERSION_base(4,9,0)
347− mappend = (<>) -- future-proof definition
348−#else
349323 mappend = append
350−#endif
351324 mconcat = concat
352325
353326instance IsString Text where
354327 fromString = pack
355328
356−#if __GLASGOW_HASKELL__ >= 708
357−instance Exts.IsList Text where
358− type Item Text = Char
359− fromList = pack
360− toList = unpack
361−#endif
362−
363329#if defined(HAVE_DEEPSEQ)
364−instance NFData Text where rnf !_ = ()
330+instance NFData Text
365331#endif
366332
367−instance Binary Text where
368− put t = put (encodeUtf8 t)
369− get = do
370− bs <- get
371− case decodeUtf8' bs of
372− P.Left exn -> P.fail (P.show exn)
373− P.Right a -> P.return a
374−
375333-- | This instance preserves data abstraction at the cost of inefficiency.
376334-- We omit reflection services for the sake of data abstraction.
377335--
378−-- This instance was created by copying the updated behavior of
379−-- @"Data.Set".@'Data.Set.Set' and @"Data.Map".@'Data.Map.Map'. If you
380−-- feel a mistake has been made, please feel free to submit
381−-- improvements.
336+-- This instance was created by copying the behavior of Data.Set and
337+-- Data.Map. If you feel a mistake has been made, please feel free to
338+-- submit improvements.
382339--
383−-- The original discussion is archived here:
384−-- <http://groups.google.com/group/haskell-cafe/browse_thread/thread/b5bbb1b28a7e525d/0639d46852575b93 could we get a Data instance for Data.Text.Text? >
340+-- Original discussion is archived here:
385341--
386−-- The followup discussion that changed the behavior of 'Data.Set.Set'
387−-- and 'Data.Map.Map' is archived here:
388−-- <http://markmail.org/message/trovdc6zkphyi3cr#query:+page:1+mid:a46der3iacwjcf6n+state:results Proposal: Allow gunfold for Data.Map, ... >
342+-- "could we get a Data instance for Data.Text.Text?"
343+-- http://groups.google.com/group/haskell-cafe/browse_thread/thread/b5bbb1b28a7e525d/0639d46852575b93
389344
390345instance Data Text where
391346 gfoldl f z txt = z pack `f` (unpack txt)
392− toConstr _ = packConstr
393− gunfold k z c = case constrIndex c of
394− 1 -> k (z pack)
395− _ -> P.error "gunfold"
396− dataTypeOf _ = textDataType
397−
398−#if MIN_VERSION_base(4,7,0)
399−-- | Only defined for @base-4.7.0.0@ and later
400−instance PrintfArg Text where
401− formatArg txt = formatString $ unpack txt
402−#endif
403−
404−packConstr :: Constr
405−packConstr = mkConstr textDataType "pack" [] Prefix
406−
407−textDataType :: DataType
408−textDataType = mkDataType "Data.Text.Text" [packConstr]
347+ toConstr _ = P.error "Data.Text.Text.toConstr"
348+ gunfold _ _ = P.error "Data.Text.Text.gunfold"
349+ dataTypeOf _ = mkNoRepType "Data.Text.Text"
409350
410351-- | /O(n)/ Compare two 'Text' values lexicographically.
411352compareText :: Text -> Text -> Ordering
@@ -430,6 +371,30 @@ pack :: String -> Text
430371pack = unstream . S.map safe . S.streamList
431372{-# INLINE [1] pack #-}
432373
374+-- | /O(n)/ Convert a 'Text' into a 'String'. Subject to fusion.
375+unpack :: Text -> String
376+unpack = S.unstreamList . stream
377+{-# INLINE [1] unpack #-}
378+
379+-- | /O(n)/ Convert a literal string into a Text. Subject to fusion.
380+unpackCString# :: Addr# -> Text
381+unpackCString# addr# = unstream (S.streamCString# addr#)
382+{-# NOINLINE unpackCString# #-}
383+
384+{-# RULES "TEXT literal" forall a.
385+ unstream (S.map safe (S.streamList (GHC.unpackCString# a)))
386+ = unpackCString# a #-}
387+
388+{-# RULES "TEXT literal UTF8" forall a.
389+ unstream (S.map safe (S.streamList (GHC.unpackCStringUtf8# a)))
390+ = unpackCString# a #-}
391+
392+-- | /O(1)/ Convert a character into a Text. Subject to fusion.
393+-- Performs replacement on invalid scalar values.
394+singleton :: Char -> Text
395+singleton = unstream . S.singleton . safe
396+{-# INLINE [1] singleton #-}
397+
433398-- -----------------------------------------------------------------------------
434399-- * Basic functions
435400
@@ -460,7 +425,6 @@ append a@(Text arr1 off1 len1) b@(Text arr2 off2 len2)
460425 | otherwise = overflowError "append"
461426 where
462427 len = len1+len2
463− x :: ST s (A.MArray s)
464428 x = do
465429 arr <- A.new len
466430 A.copyI arr 0 arr1 off1 len1
@@ -486,8 +450,8 @@ head t = S.head (stream t)
486450uncons :: Text -> Maybe (Char, Text)
487451uncons t@(Text arr off len)
488452 | len <= 0 = Nothing
489− | otherwise = Just $ let !(Iter c d) = iter t 0
490− in (c, text arr (off+d) (len-d))
453+ | otherwise = Just (c, textP arr (off+d) (len-d))
454+ where Iter c d = iter t 0
491455{-# INLINE [1] uncons #-}
492456
493457-- | Lifted from Control.Arrow and specialized.
@@ -517,7 +481,7 @@ last (Text arr off len)
517481tail :: Text -> Text
518482tail t@(Text arr off len)
519483 | len <= 0 = emptyError "tail"
520− | otherwise = text arr (off+d) (len-d)
484+ | otherwise = textP arr (off+d) (len-d)
521485 where d = iter_ t 0
522486{-# INLINE [1] tail #-}
523487
@@ -532,8 +496,8 @@ tail t@(Text arr off len)
532496-- be non-empty. Subject to fusion.
533497init :: Text -> Text
534498init (Text arr off len) | len <= 0 = emptyError "init"
535− | n >= 0xDC00 && n <= 0xDFFF = text arr off (len-2)
536− | otherwise = text arr off (len-1)
499+ | n >= 0xDC00 && n <= 0xDFFF = textP arr off (len-2)
500+ | otherwise = textP arr off (len-1)
537501 where
538502 n = A.unsafeIndex arr (off+len-1)
539503{-# INLINE [1] init #-}
@@ -572,9 +536,7 @@ isSingleton = S.isSingleton . stream
572536-- Subject to fusion.
573537length :: Text -> Int
574538length t = S.length (stream t)
575−{-# INLINE [0] length #-}
576−-- length needs to be phased after the compareN/length rules otherwise
577−-- it may inline before the rules have an opportunity to fire.
539+{-# INLINE length #-}
578540
579541-- | /O(n)/ Compare the count of characters in a 'Text' to a number.
580542-- Subject to fusion.
@@ -593,32 +555,32 @@ compareLength t n = S.compareLengthI (stream t) n
593555
594556{-# RULES
595557"TEXT ==N/length -> compareLength/==EQ" [~1] forall t n.
596− eqInt (length t) n = compareLength t n == EQ
558+ (==) (length t) n = compareLength t n == EQ
597559 #-}
598560
599561{-# RULES
600562"TEXT /=N/length -> compareLength//=EQ" [~1] forall t n.
601− neInt (length t) n = compareLength t n /= EQ
563+ (/=) (length t) n = compareLength t n /= EQ
602564 #-}
603565
604566{-# RULES
605567"TEXT <N/length -> compareLength/==LT" [~1] forall t n.
606− ltInt (length t) n = compareLength t n == LT
568+ (<) (length t) n = compareLength t n == LT
607569 #-}
608570
609571{-# RULES
610572"TEXT <=N/length -> compareLength//=GT" [~1] forall t n.
611− leInt (length t) n = compareLength t n /= GT
573+ (<=) (length t) n = compareLength t n /= GT
612574 #-}
613575
614576{-# RULES
615577"TEXT >N/length -> compareLength/==GT" [~1] forall t n.
616− gtInt (length t) n = compareLength t n == GT
578+ (>) (length t) n = compareLength t n == GT
617579 #-}
618580
619581{-# RULES
620582"TEXT >=N/length -> compareLength//=LT" [~1] forall t n.
621− geInt (length t) n = compareLength t n /= LT
583+ (>=) (length t) n = compareLength t n /= LT
622584 #-}
623585
624586-- -----------------------------------------------------------------------------
@@ -649,48 +611,22 @@ reverse :: Text -> Text
649611reverse t = S.reverse (stream t)
650612{-# INLINE reverse #-}
651613
652−-- | /O(m+n)/ Replace every non-overlapping occurrence of @needle@ in
653−-- @haystack@ with @replacement@.
654−--
655−-- This function behaves as though it was defined as follows:
656−--
657−-- @
658−-- replace needle replacement haystack =
659−-- 'intercalate' replacement ('splitOn' needle haystack)
660−-- @
661−--
662−-- As this suggests, each occurrence is replaced exactly once. So if
663−-- @needle@ occurs in @replacement@, that occurrence will /not/ itself
664−-- be replaced recursively:
665−--
666−-- > replace "oo" "foo" "oo" == "foo"
667−--
668−-- In cases where several instances of @needle@ overlap, only the
669−-- first one will be replaced:
670−--
671−-- > replace "ofo" "bar" "ofofo" == "barfo"
614+-- | /O(m+n)/ Replace every occurrence of one substring with another.
672615--
673616-- In (unlikely) bad cases, this function's time complexity degrades
674617-- towards /O(n*m)/.
675−replace :: Text
676− -- ^ @needle@ to search for. If this string is empty, an
677− -- error will occur.
678− -> Text
679− -- ^ @replacement@ to replace @needle@ with.
680− -> Text
681− -- ^ @haystack@ in which to search.
682− -> Text
618+replace :: Text -> Text -> Text -> Text
683619replace needle@(Text _ _ neeLen)
684620 (Text repArr repOff repLen)
685621 haystack@(Text hayArr hayOff hayLen)
686622 | neeLen == 0 = emptyError "replace"
687623 | L.null ixs = haystack
688624 | len > 0 = Text (A.run x) 0 len
625+ | len < 0 = overflowError "replace"
689626 | otherwise = empty
690627 where
691628 ixs = indices needle haystack
692− len = hayLen - (neeLen - repLen) `mul` L.length ixs
693− x :: ST s (A.MArray s)
629+ len = hayLen - (neeLen - repLen) * L.length ixs
694630 x = do
695631 marr <- A.new len
696632 let loop (i:is) o d = do
@@ -720,8 +656,9 @@ replace needle@(Text _ _ neeLen)
720656-- /Note/: In some languages, case conversion is a locale- and
721657-- context-dependent operation. The case conversion functions in this
722658-- module are /not/ locale sensitive. Programs that require locale
723−-- sensitivity should use appropriate versions of the
724−-- <http://hackage.haskell.org/package/text-icu-0.6.3.7/docs/Data-Text-ICU.html#g:4 case mapping functions from the text-icu package >.
659+-- sensitivity should use appropriate versions of the case mapping
660+-- functions from the @text-icu@ package:
661+-- <http://hackage.haskell.org/package/text-icu>
725662
726663-- | /O(n)/ Convert a string to folded case. Subject to fusion.
727664--
@@ -741,7 +678,7 @@ replace needle@(Text _ _ neeLen)
741678-- instead of itself.
742679toCaseFold :: Text -> Text
743680toCaseFold t = unstream (S.toCaseFold (stream t))
744−{-# INLINE toCaseFold #-}
681+{-# INLINE [0] toCaseFold #-}
745682
746683-- | /O(n)/ Convert a string to lower case, using simple case
747684-- conversion. Subject to fusion.
@@ -901,7 +838,6 @@ concat ts = case ts' of
901838 where
902839 ts' = L.filter (not . null) ts
903840 len = sumP "concat" $ L.map lengthWord16 ts'
904− go :: ST s (A.MArray s)
905841 go = do
906842 arr <- A.new len
907843 let step i (Text a o l) =
@@ -915,13 +851,13 @@ concatMap f = concat . foldr ((:) . f) []
915851{-# INLINE concatMap #-}
916852
917853-- | /O(n)/ 'any' @p@ @t@ determines whether any character in the
918−-- 'Text' @t@ satisfies the predicate @p@. Subject to fusion.
854+-- 'Text' @t@ satisifes the predicate @p@. Subject to fusion.
919855any :: (Char -> Bool) -> Text -> Bool
920856any p t = S.any p (stream t)
921857{-# INLINE any #-}
922858
923859-- | /O(n)/ 'all' @p@ @t@ determines whether all characters in the
924−-- 'Text' @t@ satisfy the predicate @p@. Subject to fusion.
860+-- 'Text' @t@ satisify the predicate @p@. Subject to fusion.
925861all :: (Char -> Bool) -> Text -> Bool
926862all p t = S.all p (stream t)
927863{-# INLINE all #-}
@@ -1012,10 +948,10 @@ replicate n t@(Text a o l)
1012948 | n <= 0 || l <= 0 = empty
1013949 | n == 1 = t
1014950 | isSingleton t = replicateChar n (unsafeHead t)
1015− | otherwise = Text (A.run x) 0 len
951+ | n <= maxBound `quot` l = Text (A.run x) 0 len
952+ | otherwise = overflowError "replicate"
1016953 where
1017− len = l `mul` n
1018− x :: ST s (A.MArray s)
954+ len = l * n
1019955 x = do
1020956 arr <- A.new len
1021957 let loop !d !i | i >= n = return arr
@@ -1066,16 +1002,14 @@ take :: Int -> Text -> Text
10661002take n t@(Text arr off len)
10671003 | n <= 0 = empty
10681004 | n >= len = t
1069− | otherwise = text arr off (iterN n t)
1005+ | otherwise = Text arr off (loop 0 0)
1006+ where
1007+ loop !i !cnt
1008+ | i >= len || cnt >= n = i
1009+ | otherwise = loop (i+d) (cnt+1)
1010+ where d = iter_ t i
10701011{-# INLINE [1] take #-}
10711012
1072−iterN :: Int -> Text -> Int
1073−iterN n t@(Text _arr _off len) = loop 0 0
1074− where loop !i !cnt
1075− | i >= len || cnt >= n = i
1076− | otherwise = loop (i+d) (cnt+1)
1077− where d = iter_ t i
1078−
10791013{-# RULES
10801014"TEXT take -> fused" [~1] forall n t.
10811015 take n t = unstream (S.take n (stream t))
@@ -1083,27 +1017,6 @@ iterN n t@(Text _arr _off len) = loop 0 0
10831017 unstream (S.take n (stream t)) = take n t
10841018 #-}
10851019
1086−-- | /O(n)/ 'takeEnd' @n@ @t@ returns the suffix remaining after
1087−-- taking @n@ characters from the end of @t@.
1088−--
1089−-- Examples:
1090−--
1091−-- > takeEnd 3 "foobar" == "bar"
1092−takeEnd :: Int -> Text -> Text
1093−takeEnd n t@(Text arr off len)
1094− | n <= 0 = empty
1095− | n >= len = t
1096− | otherwise = text arr (off+i) (len-i)
1097− where i = iterNEnd n t
1098−
1099−iterNEnd :: Int -> Text -> Int
1100−iterNEnd n t@(Text _arr _off len) = loop (len-1) n
1101− where loop i !m
1102− | i <= 0 = 0
1103− | m <= 1 = i
1104− | otherwise = loop (i+d) (m-1)
1105− where d = reverseIter_ t i
1106−
11071020-- | /O(n)/ 'drop' @n@, applied to a 'Text', returns the suffix of the
11081021-- 'Text' after the first @n@ characters, or the empty 'Text' if @n@
11091022-- is greater than the length of the 'Text'. Subject to fusion.
@@ -1111,8 +1024,11 @@ drop :: Int -> Text -> Text
11111024drop n t@(Text arr off len)
11121025 | n <= 0 = t
11131026 | n >= len = empty
1114− | otherwise = text arr (off+i) (len-i)
1115− where i = iterN n t
1027+ | otherwise = loop 0 0
1028+ where loop !i !cnt
1029+ | i >= len || cnt >= n = Text arr (off+i) (len-i)
1030+ | otherwise = loop (i+d) (cnt+1)
1031+ where d = iter_ t i
11161032{-# INLINE [1] drop #-}
11171033
11181034{-# RULES
@@ -1122,18 +1038,6 @@ drop n t@(Text arr off len)
11221038 unstream (S.drop n (stream t)) = drop n t
11231039 #-}
11241040
1125−-- | /O(n)/ 'dropEnd' @n@ @t@ returns the prefix remaining after
1126−-- dropping @n@ characters from the end of @t@.
1127−--
1128−-- Examples:
1129−--
1130−-- > dropEnd 3 "foobar" == "foo"
1131−dropEnd :: Int -> Text -> Text
1132−dropEnd n t@(Text arr off len)
1133− | n <= 0 = t
1134− | n >= len = empty
1135− | otherwise = text arr off (iterNEnd n t)
1136−
11371041-- | /O(n)/ 'takeWhile', applied to a predicate @p@ and a 'Text',
11381042-- returns the longest prefix (possibly empty) of elements that
11391043-- satisfy @p@. Subject to fusion.
@@ -1141,7 +1045,7 @@ takeWhile :: (Char -> Bool) -> Text -> Text
11411045takeWhile p t@(Text arr off len) = loop 0
11421046 where loop !i | i >= len = t
11431047 | p c = loop (i+d)
1144− | otherwise = text arr off i
1048+ | otherwise = textP arr off i
11451049 where Iter c d = iter t i
11461050{-# INLINE [1] takeWhile #-}
11471051
@@ -1152,27 +1056,6 @@ takeWhile p t@(Text arr off len) = loop 0
11521056 unstream (S.takeWhile p (stream t)) = takeWhile p t
11531057 #-}
11541058
1155−-- | /O(n)/ 'takeWhileEnd', applied to a predicate @p@ and a 'Text',
1156−-- returns the longest suffix (possibly empty) of elements that
1157−-- satisfy @p@. Subject to fusion.
1158−-- Examples:
1159−--
1160−-- > takeWhileEnd (=='o') "foo" == "oo"
1161−takeWhileEnd :: (Char -> Bool) -> Text -> Text
1162−takeWhileEnd p t@(Text arr off len) = loop (len-1) len
1163− where loop !i !l | l <= 0 = t
1164− | p c = loop (i+d) (l+d)
1165− | otherwise = text arr (off+l) (len-l)
1166− where (c,d) = reverseIter t i
1167−{-# INLINE [1] takeWhileEnd #-}
1168−
1169−{-# RULES
1170−"TEXT takeWhileEnd -> fused" [~1] forall p t.
1171− takeWhileEnd p t = S.reverse (S.takeWhile p (S.reverseStream t))
1172−"TEXT takeWhileEnd -> unfused" [1] forall p t.
1173− S.reverse (S.takeWhile p (S.reverseStream t)) = takeWhileEnd p t
1174− #-}
1175−
11761059-- | /O(n)/ 'dropWhile' @p@ @t@ returns the suffix remaining after
11771060-- 'takeWhile' @p@ @t@. Subject to fusion.
11781061dropWhile :: (Char -> Bool) -> Text -> Text
@@ -1191,9 +1074,8 @@ dropWhile p t@(Text arr off len) = loop 0 0
11911074 #-}
11921075
11931076-- | /O(n)/ 'dropWhileEnd' @p@ @t@ returns the prefix remaining after
1194−-- dropping characters that satisfy the predicate @p@ from the end of
1077+-- dropping characters that fail the predicate @p@ from the end of
11951078-- @t@. Subject to fusion.
1196−--
11971079-- Examples:
11981080--
11991081-- > dropWhileEnd (=='.') "foo..." == "foo"
@@ -1213,7 +1095,7 @@ dropWhileEnd p t@(Text arr off len) = loop (len-1) len
12131095 #-}
12141096
12151097-- | /O(n)/ 'dropAround' @p@ @t@ returns the substring remaining after
1216−-- dropping characters that satisfy the predicate @p@ from both the
1098+-- dropping characters that fail the predicate @p@ from both the
12171099-- beginning and end of @t@. Subject to fusion.
12181100dropAround :: (Char -> Bool) -> Text -> Text
12191101dropAround p = dropWhile p . dropWhileEnd p
@@ -1248,8 +1130,13 @@ splitAt :: Int -> Text -> (Text, Text)
12481130splitAt n t@(Text arr off len)
12491131 | n <= 0 = (empty, t)
12501132 | n >= len = (t, empty)
1251− | otherwise = let k = iterN n t
1252− in (text arr off k, text arr (off+k) (len-k))
1133+ | otherwise = (Text arr off k, Text arr (off+k) (len-k))
1134+ where k = loop 0 0
1135+ loop !i !cnt
1136+ | i >= len || cnt >= n = i
1137+ | otherwise = loop (i+d) (cnt+1)
1138+ where d = iter_ t i
1139+{-# INLINE splitAt #-}
12531140
12541141-- | /O(n)/ 'span', applied to a predicate @p@ and text @t@, returns
12551142-- a pair whose first element is the longest prefix (possibly empty)
@@ -1308,9 +1195,9 @@ tails t | null t = [empty]
13081195-- copies to create substrings; they just construct new 'Text's that
13091196-- are slices of the original.
13101197
1311−-- | /O(m+n)/ Break a 'Text' into pieces separated by the first 'Text'
1312−-- argument (which cannot be empty), consuming the delimiter. An empty
1313−-- delimiter is invalid, and will cause an error to be raised.
1198+-- | /O(m+n)/ Break a 'Text' into pieces separated by the first
1199+-- 'Text' argument, consuming the delimiter. An empty delimiter is
1200+-- invalid, and will cause an error to be raised.
13141201--
13151202-- Examples:
13161203--
@@ -1323,23 +1210,16 @@ tails t | null t = [empty]
13231210-- > intercalate s . splitOn s == id
13241211-- > splitOn (singleton c) == split (==c)
13251212--
1326−-- (Note: the string @s@ to split on above cannot be empty.)
1327−--
13281213-- In (unlikely) bad cases, this function's time complexity degrades
13291214-- towards /O(n*m)/.
1330−splitOn :: Text
1331− -- ^ String to split on. If this string is empty, an error
1332− -- will occur.
1333− -> Text
1334− -- ^ Input text.
1335− -> [Text]
1215+splitOn :: Text -> Text -> [Text]
13361216splitOn pat@(Text _ _ l) src@(Text arr off len)
13371217 | l <= 0 = emptyError "splitOn"
13381218 | isSingleton pat = split (== unsafeHead pat) src
13391219 | otherwise = go 0 (indices pat src)
13401220 where
1341− go !s (x:xs) = text arr (s+off) (x-s) : go (x+l) xs
1342− go s _ = [text arr (s+off) (len-s)]
1221+ go !s (x:xs) = textP arr (s+off) (x-s) : go (x+l) xs
1222+ go s _ = [textP arr (s+off) (len-s)]
13431223{-# INLINE [1] splitOn #-}
13441224
13451225{-# RULES
@@ -1431,7 +1311,7 @@ breakOn pat src@(Text arr off len)
14311311 | null pat = emptyError "breakOn"
14321312 | otherwise = case indices pat src of
14331313 [] -> (src, empty)
1434− (x:_) -> (text arr off x, text arr (off+x) (len-x))
1314+ (x:_) -> (textP arr off x, textP arr (off+x) (len-x))
14351315{-# INLINE breakOn #-}
14361316
14371317-- | /O(n+m)/ Similar to 'breakOn', but searches from the end of the
@@ -1473,7 +1353,7 @@ breakOnAll pat src@(Text arr off slen)
14731353 | otherwise = L.map step (indices pat src)
14741354 where
14751355 step x = (chunk 0 x, chunk x (slen-x))
1476− chunk !n !l = text arr (n+off) l
1356+ chunk !n !l = textP arr (n+off) l
14771357{-# INLINE breakOnAll #-}
14781358
14791359-------------------------------------------------------------------------------
@@ -1540,7 +1420,7 @@ countChar c t = S.countChar c (stream t)
15401420-- equivalent to a pair of 'unpack' operations.
15411421zip :: Text -> Text -> [(Char,Char)]
15421422zip a b = S.unstreamList $ S.zipWith (,) (stream a) (stream b)
1543−{-# INLINE zip #-}
1423+{-# INLINE [0] zip #-}
15441424
15451425-- | /O(n)/ 'zipWith' generalises 'zip' by zipping with the function
15461426-- given as the first argument, instead of a tupling function.
@@ -1548,7 +1428,7 @@ zip a b = S.unstreamList $ S.zipWith (,) (stream a) (stream b)
15481428zipWith :: (Char -> Char -> Char) -> Text -> Text -> Text
15491429zipWith f t1 t2 = unstream (S.zipWith g (stream t1) (stream t2))
15501430 where g a b = safe (f a b)
1551−{-# INLINE zipWith #-}
1431+{-# INLINE [0] zipWith #-}
15521432
15531433-- | /O(n)/ Breaks a 'Text' up into a list of words, delimited by 'Char's
15541434-- representing white space.
@@ -1673,7 +1553,7 @@ isInfixOf needle haystack
16731553-- > fnordLength _ = -1
16741554stripPrefix :: Text -> Text -> Maybe Text
16751555stripPrefix p@(Text _arr _off plen) t@(Text arr off len)
1676− | p `isPrefixOf` t = Just $! text arr (off+plen) (len-plen)
1556+ | p `isPrefixOf` t = Just $! textP arr (off+plen) (len-plen)
16771557 | otherwise = Nothing
16781558
16791559-- | /O(n)/ Find the longest non-empty common prefix of two strings
@@ -1693,8 +1573,8 @@ commonPrefixes t0@(Text arr0 off0 len0) t1@(Text arr1 off1 len1) = go 0 0
16931573 where
16941574 go !i !j | i < len0 && j < len1 && a == b = go (i+d0) (j+d1)
16951575 | i > 0 = Just (Text arr0 off0 i,
1696− text arr0 (off0+i) (len0-i),
1697− text arr1 (off1+j) (len1-j))
1576+ textP arr0 (off0+i) (len0-i),
1577+ textP arr1 (off1+j) (len1-j))
16981578 | otherwise = Nothing
16991579 where Iter a d0 = iter t0 i
17001580 Iter b d1 = iter t1 j
@@ -1719,7 +1599,7 @@ commonPrefixes t0@(Text arr0 off0 len0) t1@(Text arr1 off1 len1) = go 0 0
17191599-- > quuxLength _ = -1
17201600stripSuffix :: Text -> Text -> Maybe Text
17211601stripSuffix p@(Text _arr _off plen) t@(Text arr off len)
1722− | p `isSuffixOf` t = Just $! text arr off (len-plen)
1602+ | p `isSuffixOf` t = Just $! textP arr off (len-plen)
17231603 | otherwise = Nothing
17241604
17251605-- | Add a list of non-negative numbers. Errors out on overflow.
@@ -1748,7 +1628,6 @@ overflowError fun = P.error $ "Data.Text." ++ fun ++ ": size overflow"
17481628copy :: Text -> Text
17491629copy (Text arr off len) = Text (A.run go) 0 len
17501630 where
1751− go :: ST s (A.MArray s)
17521631 go = do
17531632 marr <- A.new len
17541633 A.copyI marr 0 arr off len
Data/Text/Array.hs+6−7
@@ -20,13 +20,13 @@
2020-- > import qualified Data.Text.Array as A
2121--
2222-- The names in this module resemble those in the 'Data.Array' family
23−-- of modules, but are shorter due to the assumption of qualified
23+-- of modules, but are shorter due to the assumption of qualifid
2424-- naming.
2525module Data.Text.Array
2626 (
2727 -- * Types
28− Array(Array, aBA)
29− , MArray(MArray, maBA)
28+ Array(aBA)
29+ , MArray(maBA)
3030
3131 -- * Functions
3232 , copyM
@@ -74,7 +74,7 @@ import Foreign.C.Types (CInt, CSize)
7474#endif
7575import GHC.Base (ByteArray#, MutableByteArray#, Int(..),
7676 indexWord16Array#, newByteArray#,
77− unsafeFreezeByteArray#, writeWord16Array#)
77+ unsafeCoerce#, writeWord16Array#)
7878import GHC.ST (ST(..), runST)
7979import GHC.Word (Word16(..))
8080import Prelude hiding (length, read)
@@ -130,9 +130,8 @@ array_size_error = error "Data.Text.Array.new: size overflow"
130130
131131-- | Freeze a mutable array. Do not mutate the 'MArray' afterwards!
132132unsafeFreeze :: MArray s -> ST s Array
133−unsafeFreeze MArray{..} = ST $ \s1# ->
134− case unsafeFreezeByteArray# maBA s1# of
135− (# s2#, ba# #) -> (# s2#, Array ba#
133+unsafeFreeze MArray{..} = ST $ \s# ->
134+ (# s#, Array (unsafeCoerce# maBA)
136135#if defined(ASSERTS)
137136 maLen
138137#endif
Data/Text/Encoding.hs+26−13
@@ -55,9 +55,13 @@ module Data.Text.Encoding
5555 , encodeUtf32LE
5656 , encodeUtf32BE
5757
58+#if MIN_VERSION_bytestring(0,10,4)
5859 -- * Encoding Text using ByteString Builders
60+ -- | /Note/ that these functions are only available if built against
61+ -- @bytestring >= 0.10.4.0@.
5962 , encodeUtf8Builder
6063 , encodeUtf8BuilderEscaped
64+#endif
6165 ) where
6266
6367#if __GLASGOW_HASKELL__ >= 702
@@ -66,17 +70,26 @@ import Control.Monad.ST.Unsafe (unsafeIOToST, unsafeSTToIO)
6670import Control.Monad.ST (unsafeIOToST, unsafeSTToIO)
6771#endif
6872
73+#if MIN_VERSION_bytestring(0,10,4)
74+import Data.Bits ((.&.))
75+import Data.Text.Internal.Unsafe.Char (ord)
76+import qualified Data.ByteString.Builder as B
77+import qualified Data.ByteString.Builder.Internal as B hiding (empty, append)
78+import qualified Data.ByteString.Builder.Prim as BP
79+import qualified Data.ByteString.Builder.Prim.Internal as BP
80+import qualified Data.Text.Internal.Encoding.Utf16 as U16
81+#endif
82+
6983import Control.Exception (evaluate, try)
7084import Control.Monad.ST (runST)
71−import Data.Bits ((.&.))
7285import Data.ByteString as B
7386import Data.ByteString.Internal as B hiding (c2w)
87+import Data.Text ()
7488import Data.Text.Encoding.Error (OnDecodeError, UnicodeException, strictDecode)
75−import Data.Text.Internal (Text(..), safe, text)
89+import Data.Text.Internal (Text(..), safe, textP)
7690import Data.Text.Internal.Private (runText)
77−import Data.Text.Internal.Unsafe.Char (ord, unsafeWrite)
91+import Data.Text.Internal.Unsafe.Char (unsafeWrite)
7892import Data.Text.Internal.Unsafe.Shift (shiftR)
79−import Data.Text.Show ()
8093import Data.Text.Unsafe (unsafeDupablePerformIO)
8194import Data.Word (Word8, Word32)
8295import Foreign.C.Types (CSize(..))
@@ -85,13 +98,8 @@ import Foreign.Marshal.Utils (with)
8598import Foreign.Ptr (Ptr, minusPtr, nullPtr, plusPtr)
8699import Foreign.Storable (Storable, peek, poke)
87100import GHC.Base (ByteArray#, MutableByteArray#)
88−import qualified Data.ByteString.Builder as B
89−import qualified Data.ByteString.Builder.Internal as B hiding (empty, append)
90−import qualified Data.ByteString.Builder.Prim as BP
91−import qualified Data.ByteString.Builder.Prim.Internal as BP
92101import qualified Data.Text.Array as A
93102import qualified Data.Text.Internal.Encoding.Fusion as E
94−import qualified Data.Text.Internal.Encoding.Utf16 as U16
95103import qualified Data.Text.Internal.Fusion as F
96104
97105#include "text_cbits.h"
@@ -111,6 +119,8 @@ import qualified Data.Text.Internal.Fusion as F
111119
112120-- | /Deprecated/. Decode a 'ByteString' containing 7-bit ASCII
113121-- encoded text.
122+--
123+-- This function is deprecated. Use 'decodeLatin1' instead.
114124decodeASCII :: ByteString -> Text
115125decodeASCII = decodeUtf8
116126{-# DEPRECATED decodeASCII "Use decodeUtf8 instead" #-}
@@ -120,7 +130,7 @@ decodeASCII = decodeUtf8
120130-- 'decodeLatin1' is semantically equivalent to
121131-- @Data.Text.pack . Data.ByteString.Char8.unpack@
122132decodeLatin1 :: ByteString -> Text
123−decodeLatin1 (PS fp off len) = text a 0 len
133+decodeLatin1 (PS fp off len) = textP a 0 len
124134 where
125135 a = A.run (A.new len >>= unsafeIOToST . go)
126136 go dest = withForeignPtr fp $ \ptr -> do
@@ -259,7 +269,6 @@ streamDecodeUtf8With onErr = decodeChunk B.empty 0 0
259269 UTF8_REJECT -> do
260270 -- We encountered an encoding error
261271 x <- peek curPtr'
262− poke statePtr 0
263272 case onErr desc (Just x) of
264273 Nothing -> loop $ curPtr' `plusPtr` 1
265274 Just c -> do
@@ -267,6 +276,7 @@ streamDecodeUtf8With onErr = decodeChunk B.empty 0 0
267276 w <- unsafeSTToIO $
268277 unsafeWrite dest (fromIntegral destOff) (safe c)
269278 poke destOffPtr (destOff + fromIntegral w)
279+ poke statePtr 0
270280 loop $ curPtr' `plusPtr` 1
271281
272282 _ -> do
@@ -275,10 +285,10 @@ streamDecodeUtf8With onErr = decodeChunk B.empty 0 0
275285 codepoint <- peek codepointPtr
276286 chunkText <- unsafeSTToIO $ do
277287 arr <- A.unsafeFreeze dest
278− return $! text arr 0 (fromIntegral n)
288+ return $! textP arr 0 (fromIntegral n)
279289 lastPtr <- peek curPtrPtr
280290 let left = lastPtr `minusPtr` curPtr
281− !undecoded = case state of
291+ undecoded = case state of
282292 UTF8_ACCEPT -> B.empty
283293 _ -> B.append undecoded0 (B.drop left bs)
284294 return $ Some chunkText undecoded
@@ -307,6 +317,8 @@ decodeUtf8' :: ByteString -> Either UnicodeException Text
307317decodeUtf8' = unsafeDupablePerformIO . try . evaluate . decodeUtf8With strictDecode
308318{-# INLINE decodeUtf8' #-}
309319
320+#if MIN_VERSION_bytestring(0,10,4)
321+
310322-- | Encode text to a ByteString 'B.Builder' using UTF-8 encoding.
311323encodeUtf8Builder :: Text -> B.Builder
312324encodeUtf8Builder = encodeUtf8BuilderEscaped (BP.liftFixedToBounded BP.word8)
@@ -367,6 +379,7 @@ encodeUtf8BuilderEscaped be =
367379 outerLoop i (B.BufferRange op ope)
368380 where
369381 poke8 j v = poke (op `plusPtr` j) (fromIntegral v :: Word8)
382+#endif
370383
371384-- | Encode text using UTF-8 encoding.
372385encodeUtf8 :: Text -> ByteString
Data/Text/Encoding/Error.hs+1−7
@@ -1,7 +1,5 @@
11{-# LANGUAGE CPP, DeriveDataTypeable #-}
2−#if __GLASGOW_HASKELL__ >= 704
3−{-# LANGUAGE Safe #-}
4−#elif __GLASGOW_HASKELL__ >= 702
2+#if __GLASGOW_HASKELL__ >= 702
53{-# LANGUAGE Trustworthy #-}
64#endif
75-- |
@@ -68,7 +66,6 @@ type OnError a b = String -> Maybe a -> Maybe b
6866type OnDecodeError = OnError Word8 Char
6967
7068-- | A handler for an encoding error.
71−{-# DEPRECATED OnEncodeError "This exception is never used in practice, and will be removed." #-}
7269type OnEncodeError = OnError Char Word8
7370
7471-- | An exception type for representing Unicode encoding errors.
@@ -81,8 +78,6 @@ data UnicodeException =
8178 -- under the given encoding, or ran out of input in mid-encode.
8279 deriving (Eq, Typeable)
8380
84−{-# DEPRECATED EncodeError "This constructor is never used, and will be removed." #-}
85−
8681showUnicodeException :: UnicodeException -> String
8782showUnicodeException (DecodeError desc (Just w))
8883 = "Cannot decode byte '\\x" ++ showHex w ("': " ++ desc)
@@ -112,7 +107,6 @@ lenientDecode :: OnDecodeError
112107lenientDecode _ _ = Just '\xfffd'
113108
114109-- | Throw a 'UnicodeException' if encoding fails.
115−{-# DEPRECATED strictEncode "This function always throws an exception, and will be removed." #-}
116110strictEncode :: OnEncodeError
117111strictEncode desc c = throw (EncodeError desc c)
118112
Data/Text/Internal.hs+10−74
@@ -1,4 +1,4 @@
1−{-# LANGUAGE CPP, DeriveDataTypeable, UnboxedTuples #-}
1+{-# LANGUAGE CPP, DeriveDataTypeable #-}
22{-# OPTIONS_HADDOCK not-home #-}
33
44-- |
@@ -20,10 +20,6 @@
2020-- with the internals, as the functions here do just about nothing to
2121-- preserve data invariants. You have been warned!
2222
23−#if defined(__GLASGOW_HASKELL__) && !defined(__HADDOCK__)
24−#include "MachDeps.h"
25−#endif
26−
2723module Data.Text.Internal
2824 (
2925 -- * Types
@@ -36,13 +32,8 @@ module Data.Text.Internal
3632 , safe
3733 -- * Code that must be here for accessibility
3834 , empty
39− , empty_
4035 -- * Utilities
4136 , firstf
42− -- * Checked multiplication
43− , mul
44− , mul32
45− , mul64
4637 -- * Debugging
4738 , showText
4839 ) where
@@ -50,11 +41,10 @@ module Data.Text.Internal
5041#if defined(ASSERTS)
5142import Control.Exception (assert)
5243#endif
53−import Data.Bits
54−import Data.Int (Int32, Int64)
44+import Data.Bits ((.&.))
45+import qualified Data.Text.Array as A
5546import Data.Text.Internal.Unsafe.Char (ord)
5647import Data.Typeable (Typeable)
57−import qualified Data.Text.Array as A
5848
5949-- | A space efficient, packed, unboxed Unicode text type.
6050data Text = Text
@@ -64,8 +54,8 @@ data Text = Text
6454 deriving (Typeable)
6555
6656-- | Smart constructor.
67−text_ :: A.Array -> Int -> Int -> Text
68−text_ arr off len =
57+text :: A.Array -> Int -> Int -> Text
58+text arr off len =
6959#if defined(ASSERTS)
7060 let c = A.unsafeIndex arr off
7161 alen = A.length arr
@@ -75,28 +65,19 @@ text_ arr off len =
7565 assert (len == 0 || c < 0xDC00 || c > 0xDFFF) $
7666#endif
7767 Text arr off len
78−{-# INLINE text_ #-}
68+{-# INLINE text #-}
7969
8070-- | /O(1)/ The empty 'Text'.
8171empty :: Text
8272empty = Text A.empty 0 0
8373{-# INLINE [1] empty #-}
8474
85−-- | A non-inlined version of 'empty'.
86−empty_ :: Text
87−empty_ = Text A.empty 0 0
88−{-# NOINLINE empty_ #-}
89−
9075-- | Construct a 'Text' without invisibly pinning its byte array in
9176-- memory if its length has dwindled to zero.
92−text :: A.Array -> Int -> Int -> Text
93−text arr off len | len == 0 = empty
94− | otherwise = text_ arr off len
95−{-# INLINE text #-}
96−
9777textP :: A.Array -> Int -> Int -> Text
98−{-# DEPRECATED textP "Use text instead" #-}
99−textP = text
78+textP arr off len | len == 0 = empty
79+ | otherwise = text arr off len
80+{-# INLINE textP #-}
10081
10182-- | A useful 'show'-like function for debugging purposes.
10283showText :: Text -> String
@@ -116,58 +97,13 @@ safe :: Char -> Char
11697safe c
11798 | ord c .&. 0x1ff800 /= 0xd800 = c
11899 | otherwise = '\xfffd'
119−{-# INLINE [0] safe #-}
100+{-# INLINE safe #-}
120101
121102-- | Apply a function to the first element of an optional pair.
122103firstf :: (a -> c) -> Maybe (a,b) -> Maybe (c,b)
123104firstf f (Just (a, b)) = Just (f a, b)
124105firstf _ Nothing = Nothing
125106
126−-- | Checked multiplication. Calls 'error' if the result would
127−-- overflow.
128−mul :: Int -> Int -> Int
129−#if WORD_SIZE_IN_BITS == 64
130−mul a b = fromIntegral $ fromIntegral a `mul64` fromIntegral b
131−#else
132−mul a b = fromIntegral $ fromIntegral a `mul32` fromIntegral b
133−#endif
134−{-# INLINE mul #-}
135−infixl 7 `mul`
136−
137−-- | Checked multiplication. Calls 'error' if the result would
138−-- overflow.
139−mul64 :: Int64 -> Int64 -> Int64
140−mul64 a b
141− | a >= 0 && b >= 0 = mul64_ a b
142− | a >= 0 = -mul64_ a (-b)
143− | b >= 0 = -mul64_ (-a) b
144− | otherwise = mul64_ (-a) (-b)
145−{-# INLINE mul64 #-}
146−infixl 7 `mul64`
147−
148−mul64_ :: Int64 -> Int64 -> Int64
149−mul64_ a b
150− | ahi > 0 && bhi > 0 = error "overflow"
151− | top > 0x7fffffff = error "overflow"
152− | total < 0 = error "overflow"
153− | otherwise = total
154− where (# ahi, alo #) = (# a `shiftR` 32, a .&. 0xffffffff #)
155− (# bhi, blo #) = (# b `shiftR` 32, b .&. 0xffffffff #)
156− top = ahi * blo + alo * bhi
157− total = (top `shiftL` 32) + alo * blo
158−{-# INLINE mul64_ #-}
159−
160−-- | Checked multiplication. Calls 'error' if the result would
161−-- overflow.
162−mul32 :: Int32 -> Int32 -> Int32
163−mul32 a b = case fromIntegral a * fromIntegral b of
164− ab | ab < min32 || ab > max32 -> error "overflow"
165− | otherwise -> fromIntegral ab
166− where min32 = -0x80000000 :: Int64
167− max32 = 0x7fffffff
168−{-# INLINE mul32 #-}
169−infixl 7 `mul32`
170−
171107-- $internals
172108--
173109-- Internally, the 'Text' type is represented as an array of 'Word16'
Data/Text/Internal/Builder.hs+16−19
@@ -6,7 +6,7 @@
66-- Module : Data.Text.Internal.Builder
77-- Copyright : (c) 2013 Bryan O'Sullivan
88-- (c) 2010 Johan Tibell
9−-- License : BSD-style (see LICENSE)
9+-- License : BSD3-style (see LICENSE)
1010--
1111-- Maintainer : Johan Tibell <johan.tibell@gmail.com>
1212-- Stability : experimental
@@ -58,14 +58,13 @@ module Data.Text.Internal.Builder
5858 ) where
5959
6060import Control.Monad.ST (ST, runST)
61+import Data.Bits ((.&.))
6162import Data.Monoid (Monoid(..))
62−#if MIN_VERSION_base(4,9,0)
63−import Data.Semigroup (Semigroup(..))
64−#endif
6563import Data.Text.Internal (Text(..))
6664import Data.Text.Internal.Lazy (smallChunkSize)
6765import Data.Text.Unsafe (inlineInterleaveST)
68−import Data.Text.Internal.Unsafe.Char (unsafeWrite)
66+import Data.Text.Internal.Unsafe.Char (ord, unsafeWrite)
67+import Data.Text.Internal.Unsafe.Shift (shiftR)
6968import Prelude hiding (map, putChar)
7069
7170import qualified Data.String as String
@@ -92,22 +91,12 @@ newtype Builder = Builder {
9291 -> ST s [S.Text]
9392 }
9493
95−#if MIN_VERSION_base(4,9,0)
96−instance Semigroup Builder where
97− (<>) = append
98− {-# INLINE (<>) #-}
99−#endif
100−
10194instance Monoid Builder where
10295 mempty = empty
10396 {-# INLINE mempty #-}
104−#if MIN_VERSION_base(4,9,0)
105− mappend = (<>) -- future-proof definition
106−#else
10797 mappend = append
108−#endif
10998 {-# INLINE mappend #-}
110− mconcat = foldr mappend Data.Monoid.mempty
99+ mconcat = foldr mappend mempty
111100 {-# INLINE mconcat #-}
112101
113102instance String.IsString Builder where
@@ -138,7 +127,17 @@ empty = Builder (\ k buf -> k buf)
138127-- * @'toLazyText' ('singleton' c) = 'L.singleton' c@
139128--
140129singleton :: Char -> Builder
141−singleton c = writeAtMost 2 $ \ marr o -> unsafeWrite marr o c
130+singleton c = writeAtMost 2 $ \ marr o ->
131+ if n < 0x10000
132+ then A.unsafeWrite marr o (fromIntegral n) >> return 1
133+ else do
134+ A.unsafeWrite marr o lo
135+ A.unsafeWrite marr (o+1) hi
136+ return 2
137+ where n = ord c
138+ m = n - 0x10000
139+ lo = fromIntegral $ (m `shiftR` 10) + 0xD800
140+ hi = fromIntegral $ (m .&. 0x3FF) + 0xDC00
142141{-# INLINE singleton #-}
143142
144143------------------------------------------------------------------------
@@ -242,8 +241,6 @@ flush = Builder $ \ k buf@(Buffer p o u l) ->
242241 !t = Text arr o u
243242 ts <- inlineInterleaveST (k b)
244243 return $! t : ts
245−{-# INLINE [1] flush #-}
246−-- defer inlining so that flush/flush rule may fire.
247244
248245------------------------------------------------------------------------
249246
Data/Text/Internal/Builder/Functions.hs+1−2
@@ -23,8 +23,7 @@ module Data.Text.Internal.Builder.Functions
2323
2424import Data.Monoid (mappend)
2525import Data.Text.Lazy.Builder (Builder)
26−import GHC.Base (chr#,ord#,(+#),Int(I#),Char(C#))
27−import Prelude ()
26+import GHC.Base
2827
2928-- | Unsafe conversion for decimal digits.
3029{-# INLINE i2d #-}
Data/Text/Internal/Builder/Int/Digits.hs+1−1
@@ -2,7 +2,7 @@
22
33-- Module: Data.Text.Internal.Builder.Int.Digits
44-- Copyright: (c) 2013 Bryan O'Sullivan
5−-- License: BSD-style
5+-- License: BSD3
66-- Maintainer: Bryan O'Sullivan <bos@serpentine.com>
77-- Stability: experimental
88-- Portability: portable
Data/Text/Internal/Builder/RealFloat/Functions.hs−28
@@ -1,5 +1,3 @@
1−{-# LANGUAGE CPP #-}
2−
31-- |
42-- Module: Data.Text.Internal.Builder.RealFloat.Functions
53-- Copyright: (c) The University of Glasgow 1994-2002
@@ -15,30 +13,6 @@ module Data.Text.Internal.Builder.RealFloat.Functions
1513 ) where
1614
1715roundTo :: Int -> [Int] -> (Int,[Int])
18−
19−#if MIN_VERSION_base(4,6,0)
20−
21−roundTo d is =
22− case f d True is of
23− x@(0,_) -> x
24− (1,xs) -> (1, 1:xs)
25− _ -> error "roundTo: bad Value"
26− where
27− b2 = base `quot` 2
28−
29− f n _ [] = (0, replicate n 0)
30− f 0 e (x:xs) | x == b2 && e && all (== 0) xs = (0, []) -- Round to even when at exactly half the base
31− | otherwise = (if x >= b2 then 1 else 0, [])
32− f n _ (i:xs)
33− | i' == base = (1,0:ds)
34− | otherwise = (0,i':ds)
35− where
36− (c,ds) = f (n-1) (even i) xs
37− i' = c + i
38− base = 10
39−
40−#else
41−
4216roundTo d is =
4317 case f d is of
4418 x@(0,_) -> x
@@ -53,5 +27,3 @@ roundTo d is =
5327 where
5428 (c,ds) = f (n-1) xs
5529 i' = c + i
56−
57−#endif
Data/Text/Internal/Fusion.hs+28−38
@@ -68,7 +68,7 @@ default(Int)
6868
6969-- | /O(n)/ Convert a 'Text' into a 'Stream Char'.
7070stream :: Text -> Stream Char
71−stream (Text arr off len) = Stream next off (betweenSize (len `shiftR` 1) len)
71+stream (Text arr off len) = Stream next off (maxSize len)
7272 where
7373 !end = off+len
7474 next !i
@@ -83,7 +83,7 @@ stream (Text arr off len) = Stream next off (betweenSize (len `shiftR` 1) len)
8383-- | /O(n)/ Convert a 'Text' into a 'Stream Char', but iterate
8484-- backwards.
8585reverseStream :: Text -> Stream Char
86−reverseStream (Text arr off len) = Stream next (off+len-1) (betweenSize (len `shiftR` 1) len)
86+reverseStream (Text arr off len) = Stream next (off+len-1) (maxSize len)
8787 where
8888 {-# INLINE next #-}
8989 next !i
@@ -98,35 +98,25 @@ reverseStream (Text arr off len) = Stream next (off+len-1) (betweenSize (len `sh
9898-- | /O(n)/ Convert a 'Stream Char' into a 'Text'.
9999unstream :: Stream Char -> Text
100100unstream (Stream next0 s0 len) = runText $ \done -> do
101− -- Before encoding each char we perform a buffer realloc check assuming
102− -- worst case encoding size of two 16-bit units for the char. Just add an
103− -- extra space to the buffer so that we do not end up reallocating even when
104− -- all the chars are encoded as single unit.
105− let mlen = upperBound 4 len + 1
101+ let mlen = upperBound 4 len
106102 arr0 <- A.new mlen
107− let outer !arr !maxi = encode
103+ let outer arr top = loop
108104 where
109− -- keep the common case loop as small as possible
110− encode !si !di =
111− case next0 si of
112− Done -> done arr di
113− Skip si' -> encode si' di
114− Yield c si'
115− -- simply check for the worst case
116− | maxi < di + 1 -> realloc si di
117− | otherwise -> do
118− n <- unsafeWrite arr di c
119− encode si' (di + n)
120−
121− -- keep uncommon case separate from the common case code
122− {-# NOINLINE realloc #-}
123− realloc !si !di = do
124− let newlen = (maxi + 1) * 2
125− arr' <- A.new newlen
126− A.copyM arr' 0 arr 0 di
127− outer arr' (newlen - 1) si di
128−
129− outer arr0 (mlen - 1) s0 0
105+ loop !s !i =
106+ case next0 s of
107+ Done -> done arr i
108+ Skip s' -> loop s' i
109+ Yield x s'
110+ | j >= top -> {-# SCC "unstream/resize" #-} do
111+ let top' = (top + 1) `shiftL` 1
112+ arr' <- A.new top'
113+ A.copyM arr' 0 arr 0 top
114+ outer arr' top' s i
115+ | otherwise -> do d <- unsafeWrite arr i x
116+ loop s' (i+d)
117+ where j | ord x < 0x10000 = i
118+ | otherwise = i + 1
119+ outer arr0 mlen s0 0
130120{-# INLINE [0] unstream #-}
131121{-# RULES "STREAM stream/unstream fusion" forall s. stream (unstream s) = s #-}
132122
@@ -142,7 +132,7 @@ length = S.lengthI
142132reverse :: Stream Char -> Text
143133reverse (Stream next s len0)
144134 | isEmpty len0 = I.empty
145− | otherwise = I.text arr off' len'
135+ | otherwise = I.textP arr off' len'
146136 where
147137 len0' = upperBound 4 (larger len0 4)
148138 (arr, (off', len')) = A.run2 (A.new len0' >>= loop s (len0'-1) len0')
@@ -176,15 +166,15 @@ reverse (Stream next s len0)
176166-- | /O(n)/ Perform the equivalent of 'scanr' over a list, only with
177167-- the input and result reversed.
178168reverseScanr :: (Char -> Char -> Char) -> Char -> Stream Char -> Stream Char
179−reverseScanr f z0 (Stream next0 s0 len) = Stream next (Scan1 z0 s0) (len+1) -- HINT maybe too low
169+reverseScanr f z0 (Stream next0 s0 len) = Stream next (S1 :*: z0 :*: s0) (len+1) -- HINT maybe too low
180170 where
181171 {-# INLINE next #-}
182− next (Scan1 z s) = Yield z (Scan2 z s)
183− next (Scan2 z s) = case next0 s of
184− Yield x s' -> let !x' = f x z
185− in Yield x' (Scan2 x' s')
186− Skip s' -> Skip (Scan2 z s')
187− Done -> Done
172+ next (S1 :*: z :*: s) = Yield z (S2 :*: z :*: s)
173+ next (S2 :*: z :*: s) = case next0 s of
174+ Yield x s' -> let !x' = f x z
175+ in Yield x' (S2 :*: x' :*: s')
176+ Skip s' -> Skip (S2 :*: z :*: s')
177+ Done -> Done
188178{-# INLINE reverseScanr #-}
189179
190180-- | /O(n)/ Like 'unfoldr', 'unfoldrN' builds a stream from a seed
@@ -220,7 +210,7 @@ countChar = S.countCharI
220210-- function to each element of a 'Text', passing an accumulating
221211-- parameter from left to right, and returns a final 'Text'.
222212mapAccumL :: (a -> Char -> (a,Char)) -> a -> Stream Char -> (a, Text)
223−mapAccumL f z0 (Stream next0 s0 len) = (nz, I.text na 0 nl)
213+mapAccumL f z0 (Stream next0 s0 len) = (nz,I.textP na 0 nl)
224214 where
225215 (na,(nz,nl)) = A.run2 (A.new mlen >>= \arr -> outer arr mlen z0 s0 0)
226216 where mlen = upperBound 4 len
Data/Text/Internal/Fusion/CaseMapping.hs+19−291
@@ -1,17 +1,17 @@
11{-# LANGUAGE Rank2Types #-}
22-- AUTOMATICALLY GENERATED - DO NOT EDIT
3−-- 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]
3+-- Generated by scripts/SpecialCasing.hs
4+-- CaseFolding-6.3.0.txt
5+-- Date: 2012-12-20, 22:14:35 GMT [MD]
6+-- SpecialCasing-6.3.0.txt
7+-- Date: 2013-05-08, 13:54:51 GMT [MD]
88
99module Data.Text.Internal.Fusion.CaseMapping where
1010import Data.Char
1111import Data.Text.Internal.Fusion.Types
1212
1313upperMapping :: forall s. Char -> s -> Step (CC s) Char
14−{-# NOINLINE upperMapping #-}
14+{-# INLINE upperMapping #-}
1515-- LATIN SMALL LETTER SHARP S
1616upperMapping '\x00df' s = Yield '\x0053' (CC s '\x0053' '\x0000')
1717-- LATIN SMALL LIGATURE FF
@@ -218,12 +218,12 @@ upperMapping '\x1fc7' s = Yield '\x0397' (CC s '\x0342' '\x0399')
218218upperMapping '\x1ff7' s = Yield '\x03a9' (CC s '\x0342' '\x0399')
219219upperMapping c s = Yield (toUpper c) (CC s '\0' '\0')
220220lowerMapping :: forall s. Char -> s -> Step (CC s) Char
221−{-# NOINLINE lowerMapping #-}
221+{-# INLINE lowerMapping #-}
222222-- LATIN CAPITAL LETTER I WITH DOT ABOVE
223223lowerMapping '\x0130' s = Yield '\x0069' (CC s '\x0307' '\x0000')
224224lowerMapping c s = Yield (toLower c) (CC s '\0' '\0')
225225titleMapping :: forall s. Char -> s -> Step (CC s) Char
226−{-# NOINLINE titleMapping #-}
226+{-# INLINE titleMapping #-}
227227-- LATIN SMALL LETTER SHARP S
228228titleMapping '\x00df' s = Yield '\x0053' (CC s '\x0073' '\x0000')
229229-- LATIN SMALL LIGATURE FF
@@ -322,7 +322,7 @@ titleMapping '\x1fc7' s = Yield '\x0397' (CC s '\x0342' '\x0345')
322322titleMapping '\x1ff7' s = Yield '\x03a9' (CC s '\x0342' '\x0345')
323323titleMapping c s = Yield (toTitle c) (CC s '\0' '\0')
324324foldMapping :: forall s. Char -> s -> Step (CC s) Char
325−{-# NOINLINE foldMapping #-}
325+{-# INLINE foldMapping #-}
326326-- MICRO SIGN
327327foldMapping '\x00b5' s = Yield '\x03bc' (CC s '\x0000' '\x0000')
328328-- LATIN SMALL LETTER SHARP S
@@ -359,18 +359,10 @@ foldMapping '\x03f1' s = Yield '\x03c1' (CC s '\x0000' '\x0000')
359359foldMapping '\x03f5' s = Yield '\x03b5' (CC s '\x0000' '\x0000')
360360-- ARMENIAN SMALL LIGATURE ECH YIWN
361361foldMapping '\x0587' s = Yield '\x0565' (CC s '\x0582' '\x0000')
362−-- CHEROKEE SMALL LETTER YE
363−foldMapping '\x13f8' s = Yield '\x13f0' (CC s '\x0000' '\x0000')
364−-- CHEROKEE SMALL LETTER YI
365−foldMapping '\x13f9' s = Yield '\x13f1' (CC s '\x0000' '\x0000')
366−-- CHEROKEE SMALL LETTER YO
367−foldMapping '\x13fa' s = Yield '\x13f2' (CC s '\x0000' '\x0000')
368−-- CHEROKEE SMALL LETTER YU
369−foldMapping '\x13fb' s = Yield '\x13f3' (CC s '\x0000' '\x0000')
370−-- CHEROKEE SMALL LETTER YV
371−foldMapping '\x13fc' s = Yield '\x13f4' (CC s '\x0000' '\x0000')
372−-- CHEROKEE SMALL LETTER MV
373−foldMapping '\x13fd' s = Yield '\x13f5' (CC s '\x0000' '\x0000')
362+-- GEORGIAN CAPITAL LETTER YN
363+foldMapping '\x10c7' s = Yield '\x2d27' (CC s '\x0000' '\x0000')
364+-- GEORGIAN CAPITAL LETTER AEN
365+foldMapping '\x10cd' s = Yield '\x2d2d' (CC s '\x0000' '\x0000')
374366-- LATIN SMALL LETTER H WITH LINE BELOW
375367foldMapping '\x1e96' s = Yield '\x0068' (CC s '\x0331' '\x0000')
376368-- LATIN SMALL LETTER T WITH DIAERESIS
@@ -545,174 +537,12 @@ foldMapping '\x1ff6' s = Yield '\x03c9' (CC s '\x0342' '\x0000')
545537foldMapping '\x1ff7' s = Yield '\x03c9' (CC s '\x0342' '\x03b9')
546538-- GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI
547539foldMapping '\x1ffc' s = Yield '\x03c9' (CC s '\x03b9' '\x0000')
548−-- LATIN CAPITAL LETTER J WITH CROSSED-TAIL
549−foldMapping '\xa7b2' s = Yield '\x029d' (CC s '\x0000' '\x0000')
550−-- LATIN CAPITAL LETTER CHI
551−foldMapping '\xa7b3' s = Yield '\xab53' (CC s '\x0000' '\x0000')
552−-- LATIN CAPITAL LETTER BETA
553−foldMapping '\xa7b4' s = Yield '\xa7b5' (CC s '\x0000' '\x0000')
554−-- LATIN CAPITAL LETTER OMEGA
555−foldMapping '\xa7b6' s = Yield '\xa7b7' (CC s '\x0000' '\x0000')
556−-- CHEROKEE SMALL LETTER A
557−foldMapping '\xab70' s = Yield '\x13a0' (CC s '\x0000' '\x0000')
558−-- CHEROKEE SMALL LETTER E
559−foldMapping '\xab71' s = Yield '\x13a1' (CC s '\x0000' '\x0000')
560−-- CHEROKEE SMALL LETTER I
561−foldMapping '\xab72' s = Yield '\x13a2' (CC s '\x0000' '\x0000')
562−-- CHEROKEE SMALL LETTER O
563−foldMapping '\xab73' s = Yield '\x13a3' (CC s '\x0000' '\x0000')
564−-- CHEROKEE SMALL LETTER U
565−foldMapping '\xab74' s = Yield '\x13a4' (CC s '\x0000' '\x0000')
566−-- CHEROKEE SMALL LETTER V
567−foldMapping '\xab75' s = Yield '\x13a5' (CC s '\x0000' '\x0000')
568−-- CHEROKEE SMALL LETTER GA
569−foldMapping '\xab76' s = Yield '\x13a6' (CC s '\x0000' '\x0000')
570−-- CHEROKEE SMALL LETTER KA
571−foldMapping '\xab77' s = Yield '\x13a7' (CC s '\x0000' '\x0000')
572−-- CHEROKEE SMALL LETTER GE
573−foldMapping '\xab78' s = Yield '\x13a8' (CC s '\x0000' '\x0000')
574−-- CHEROKEE SMALL LETTER GI
575−foldMapping '\xab79' s = Yield '\x13a9' (CC s '\x0000' '\x0000')
576−-- CHEROKEE SMALL LETTER GO
577−foldMapping '\xab7a' s = Yield '\x13aa' (CC s '\x0000' '\x0000')
578−-- CHEROKEE SMALL LETTER GU
579−foldMapping '\xab7b' s = Yield '\x13ab' (CC s '\x0000' '\x0000')
580−-- CHEROKEE SMALL LETTER GV
581−foldMapping '\xab7c' s = Yield '\x13ac' (CC s '\x0000' '\x0000')
582−-- CHEROKEE SMALL LETTER HA
583−foldMapping '\xab7d' s = Yield '\x13ad' (CC s '\x0000' '\x0000')
584−-- CHEROKEE SMALL LETTER HE
585−foldMapping '\xab7e' s = Yield '\x13ae' (CC s '\x0000' '\x0000')
586−-- CHEROKEE SMALL LETTER HI
587−foldMapping '\xab7f' s = Yield '\x13af' (CC s '\x0000' '\x0000')
588−-- CHEROKEE SMALL LETTER HO
589−foldMapping '\xab80' s = Yield '\x13b0' (CC s '\x0000' '\x0000')
590−-- CHEROKEE SMALL LETTER HU
591−foldMapping '\xab81' s = Yield '\x13b1' (CC s '\x0000' '\x0000')
592−-- CHEROKEE SMALL LETTER HV
593−foldMapping '\xab82' s = Yield '\x13b2' (CC s '\x0000' '\x0000')
594−-- CHEROKEE SMALL LETTER LA
595−foldMapping '\xab83' s = Yield '\x13b3' (CC s '\x0000' '\x0000')
596−-- CHEROKEE SMALL LETTER LE
597−foldMapping '\xab84' s = Yield '\x13b4' (CC s '\x0000' '\x0000')
598−-- CHEROKEE SMALL LETTER LI
599−foldMapping '\xab85' s = Yield '\x13b5' (CC s '\x0000' '\x0000')
600−-- CHEROKEE SMALL LETTER LO
601−foldMapping '\xab86' s = Yield '\x13b6' (CC s '\x0000' '\x0000')
602−-- CHEROKEE SMALL LETTER LU
603−foldMapping '\xab87' s = Yield '\x13b7' (CC s '\x0000' '\x0000')
604−-- CHEROKEE SMALL LETTER LV
605−foldMapping '\xab88' s = Yield '\x13b8' (CC s '\x0000' '\x0000')
606−-- CHEROKEE SMALL LETTER MA
607−foldMapping '\xab89' s = Yield '\x13b9' (CC s '\x0000' '\x0000')
608−-- CHEROKEE SMALL LETTER ME
609−foldMapping '\xab8a' s = Yield '\x13ba' (CC s '\x0000' '\x0000')
610−-- CHEROKEE SMALL LETTER MI
611−foldMapping '\xab8b' s = Yield '\x13bb' (CC s '\x0000' '\x0000')
612−-- CHEROKEE SMALL LETTER MO
613−foldMapping '\xab8c' s = Yield '\x13bc' (CC s '\x0000' '\x0000')
614−-- CHEROKEE SMALL LETTER MU
615−foldMapping '\xab8d' s = Yield '\x13bd' (CC s '\x0000' '\x0000')
616−-- CHEROKEE SMALL LETTER NA
617−foldMapping '\xab8e' s = Yield '\x13be' (CC s '\x0000' '\x0000')
618−-- CHEROKEE SMALL LETTER HNA
619−foldMapping '\xab8f' s = Yield '\x13bf' (CC s '\x0000' '\x0000')
620−-- CHEROKEE SMALL LETTER NAH
621−foldMapping '\xab90' s = Yield '\x13c0' (CC s '\x0000' '\x0000')
622−-- CHEROKEE SMALL LETTER NE
623−foldMapping '\xab91' s = Yield '\x13c1' (CC s '\x0000' '\x0000')
624−-- CHEROKEE SMALL LETTER NI
625−foldMapping '\xab92' s = Yield '\x13c2' (CC s '\x0000' '\x0000')
626−-- CHEROKEE SMALL LETTER NO
627−foldMapping '\xab93' s = Yield '\x13c3' (CC s '\x0000' '\x0000')
628−-- CHEROKEE SMALL LETTER NU
629−foldMapping '\xab94' s = Yield '\x13c4' (CC s '\x0000' '\x0000')
630−-- CHEROKEE SMALL LETTER NV
631−foldMapping '\xab95' s = Yield '\x13c5' (CC s '\x0000' '\x0000')
632−-- CHEROKEE SMALL LETTER QUA
633−foldMapping '\xab96' s = Yield '\x13c6' (CC s '\x0000' '\x0000')
634−-- CHEROKEE SMALL LETTER QUE
635−foldMapping '\xab97' s = Yield '\x13c7' (CC s '\x0000' '\x0000')
636−-- CHEROKEE SMALL LETTER QUI
637−foldMapping '\xab98' s = Yield '\x13c8' (CC s '\x0000' '\x0000')
638−-- CHEROKEE SMALL LETTER QUO
639−foldMapping '\xab99' s = Yield '\x13c9' (CC s '\x0000' '\x0000')
640−-- CHEROKEE SMALL LETTER QUU
641−foldMapping '\xab9a' s = Yield '\x13ca' (CC s '\x0000' '\x0000')
642−-- CHEROKEE SMALL LETTER QUV
643−foldMapping '\xab9b' s = Yield '\x13cb' (CC s '\x0000' '\x0000')
644−-- CHEROKEE SMALL LETTER SA
645−foldMapping '\xab9c' s = Yield '\x13cc' (CC s '\x0000' '\x0000')
646−-- CHEROKEE SMALL LETTER S
647−foldMapping '\xab9d' s = Yield '\x13cd' (CC s '\x0000' '\x0000')
648−-- CHEROKEE SMALL LETTER SE
649−foldMapping '\xab9e' s = Yield '\x13ce' (CC s '\x0000' '\x0000')
650−-- CHEROKEE SMALL LETTER SI
651−foldMapping '\xab9f' s = Yield '\x13cf' (CC s '\x0000' '\x0000')
652−-- CHEROKEE SMALL LETTER SO
653−foldMapping '\xaba0' s = Yield '\x13d0' (CC s '\x0000' '\x0000')
654−-- CHEROKEE SMALL LETTER SU
655−foldMapping '\xaba1' s = Yield '\x13d1' (CC s '\x0000' '\x0000')
656−-- CHEROKEE SMALL LETTER SV
657−foldMapping '\xaba2' s = Yield '\x13d2' (CC s '\x0000' '\x0000')
658−-- CHEROKEE SMALL LETTER DA
659−foldMapping '\xaba3' s = Yield '\x13d3' (CC s '\x0000' '\x0000')
660−-- CHEROKEE SMALL LETTER TA
661−foldMapping '\xaba4' s = Yield '\x13d4' (CC s '\x0000' '\x0000')
662−-- CHEROKEE SMALL LETTER DE
663−foldMapping '\xaba5' s = Yield '\x13d5' (CC s '\x0000' '\x0000')
664−-- CHEROKEE SMALL LETTER TE
665−foldMapping '\xaba6' s = Yield '\x13d6' (CC s '\x0000' '\x0000')
666−-- CHEROKEE SMALL LETTER DI
667−foldMapping '\xaba7' s = Yield '\x13d7' (CC s '\x0000' '\x0000')
668−-- CHEROKEE SMALL LETTER TI
669−foldMapping '\xaba8' s = Yield '\x13d8' (CC s '\x0000' '\x0000')
670−-- CHEROKEE SMALL LETTER DO
671−foldMapping '\xaba9' s = Yield '\x13d9' (CC s '\x0000' '\x0000')
672−-- CHEROKEE SMALL LETTER DU
673−foldMapping '\xabaa' s = Yield '\x13da' (CC s '\x0000' '\x0000')
674−-- CHEROKEE SMALL LETTER DV
675−foldMapping '\xabab' s = Yield '\x13db' (CC s '\x0000' '\x0000')
676−-- CHEROKEE SMALL LETTER DLA
677−foldMapping '\xabac' s = Yield '\x13dc' (CC s '\x0000' '\x0000')
678−-- CHEROKEE SMALL LETTER TLA
679−foldMapping '\xabad' s = Yield '\x13dd' (CC s '\x0000' '\x0000')
680−-- CHEROKEE SMALL LETTER TLE
681−foldMapping '\xabae' s = Yield '\x13de' (CC s '\x0000' '\x0000')
682−-- CHEROKEE SMALL LETTER TLI
683−foldMapping '\xabaf' s = Yield '\x13df' (CC s '\x0000' '\x0000')
684−-- CHEROKEE SMALL LETTER TLO
685−foldMapping '\xabb0' s = Yield '\x13e0' (CC s '\x0000' '\x0000')
686−-- CHEROKEE SMALL LETTER TLU
687−foldMapping '\xabb1' s = Yield '\x13e1' (CC s '\x0000' '\x0000')
688−-- CHEROKEE SMALL LETTER TLV
689−foldMapping '\xabb2' s = Yield '\x13e2' (CC s '\x0000' '\x0000')
690−-- CHEROKEE SMALL LETTER TSA
691−foldMapping '\xabb3' s = Yield '\x13e3' (CC s '\x0000' '\x0000')
692−-- CHEROKEE SMALL LETTER TSE
693−foldMapping '\xabb4' s = Yield '\x13e4' (CC s '\x0000' '\x0000')
694−-- CHEROKEE SMALL LETTER TSI
695−foldMapping '\xabb5' s = Yield '\x13e5' (CC s '\x0000' '\x0000')
696−-- CHEROKEE SMALL LETTER TSO
697−foldMapping '\xabb6' s = Yield '\x13e6' (CC s '\x0000' '\x0000')
698−-- CHEROKEE SMALL LETTER TSU
699−foldMapping '\xabb7' s = Yield '\x13e7' (CC s '\x0000' '\x0000')
700−-- CHEROKEE SMALL LETTER TSV
701−foldMapping '\xabb8' s = Yield '\x13e8' (CC s '\x0000' '\x0000')
702−-- CHEROKEE SMALL LETTER WA
703−foldMapping '\xabb9' s = Yield '\x13e9' (CC s '\x0000' '\x0000')
704−-- CHEROKEE SMALL LETTER WE
705−foldMapping '\xabba' s = Yield '\x13ea' (CC s '\x0000' '\x0000')
706−-- CHEROKEE SMALL LETTER WI
707−foldMapping '\xabbb' s = Yield '\x13eb' (CC s '\x0000' '\x0000')
708−-- CHEROKEE SMALL LETTER WO
709−foldMapping '\xabbc' s = Yield '\x13ec' (CC s '\x0000' '\x0000')
710−-- CHEROKEE SMALL LETTER WU
711−foldMapping '\xabbd' s = Yield '\x13ed' (CC s '\x0000' '\x0000')
712−-- CHEROKEE SMALL LETTER WV
713−foldMapping '\xabbe' s = Yield '\x13ee' (CC s '\x0000' '\x0000')
714−-- CHEROKEE SMALL LETTER YA
715−foldMapping '\xabbf' s = Yield '\x13ef' (CC s '\x0000' '\x0000')
540+-- COPTIC CAPITAL LETTER BOHAIRIC KHEI
541+foldMapping '\x2cf2' s = Yield '\x2cf3' (CC s '\x0000' '\x0000')
542+-- LATIN CAPITAL LETTER C WITH BAR
543+foldMapping '\xa792' s = Yield '\xa793' (CC s '\x0000' '\x0000')
544+-- LATIN CAPITAL LETTER H WITH HOOK
545+foldMapping '\xa7aa' s = Yield '\x0266' (CC s '\x0000' '\x0000')
716546-- LATIN SMALL LIGATURE FF
717547foldMapping '\xfb00' s = Yield '\x0066' (CC s '\x0066' '\x0000')
718548-- LATIN SMALL LIGATURE FI
@@ -737,106 +567,4 @@ foldMapping '\xfb15' s = Yield '\x0574' (CC s '\x056b' '\x0000')
737567foldMapping '\xfb16' s = Yield '\x057e' (CC s '\x0576' '\x0000')
738568-- ARMENIAN SMALL LIGATURE MEN XEH
739569foldMapping '\xfb17' s = Yield '\x0574' (CC s '\x056d' '\x0000')
740−-- OLD HUNGARIAN CAPITAL LETTER A
741−foldMapping '\x10c80' s = Yield '\x10cc0' (CC s '\x0000' '\x0000')
742−-- OLD HUNGARIAN CAPITAL LETTER AA
743−foldMapping '\x10c81' s = Yield '\x10cc1' (CC s '\x0000' '\x0000')
744−-- OLD HUNGARIAN CAPITAL LETTER EB
745−foldMapping '\x10c82' s = Yield '\x10cc2' (CC s '\x0000' '\x0000')
746−-- OLD HUNGARIAN CAPITAL LETTER AMB
747−foldMapping '\x10c83' s = Yield '\x10cc3' (CC s '\x0000' '\x0000')
748−-- OLD HUNGARIAN CAPITAL LETTER EC
749−foldMapping '\x10c84' s = Yield '\x10cc4' (CC s '\x0000' '\x0000')
750−-- OLD HUNGARIAN CAPITAL LETTER ENC
751−foldMapping '\x10c85' s = Yield '\x10cc5' (CC s '\x0000' '\x0000')
752−-- OLD HUNGARIAN CAPITAL LETTER ECS
753−foldMapping '\x10c86' s = Yield '\x10cc6' (CC s '\x0000' '\x0000')
754−-- OLD HUNGARIAN CAPITAL LETTER ED
755−foldMapping '\x10c87' s = Yield '\x10cc7' (CC s '\x0000' '\x0000')
756−-- OLD HUNGARIAN CAPITAL LETTER AND
757−foldMapping '\x10c88' s = Yield '\x10cc8' (CC s '\x0000' '\x0000')
758−-- OLD HUNGARIAN CAPITAL LETTER E
759−foldMapping '\x10c89' s = Yield '\x10cc9' (CC s '\x0000' '\x0000')
760−-- OLD HUNGARIAN CAPITAL LETTER CLOSE E
761−foldMapping '\x10c8a' s = Yield '\x10cca' (CC s '\x0000' '\x0000')
762−-- OLD HUNGARIAN CAPITAL LETTER EE
763−foldMapping '\x10c8b' s = Yield '\x10ccb' (CC s '\x0000' '\x0000')
764−-- OLD HUNGARIAN CAPITAL LETTER EF
765−foldMapping '\x10c8c' s = Yield '\x10ccc' (CC s '\x0000' '\x0000')
766−-- OLD HUNGARIAN CAPITAL LETTER EG
767−foldMapping '\x10c8d' s = Yield '\x10ccd' (CC s '\x0000' '\x0000')
768−-- OLD HUNGARIAN CAPITAL LETTER EGY
769−foldMapping '\x10c8e' s = Yield '\x10cce' (CC s '\x0000' '\x0000')
770−-- OLD HUNGARIAN CAPITAL LETTER EH
771−foldMapping '\x10c8f' s = Yield '\x10ccf' (CC s '\x0000' '\x0000')
772−-- OLD HUNGARIAN CAPITAL LETTER I
773−foldMapping '\x10c90' s = Yield '\x10cd0' (CC s '\x0000' '\x0000')
774−-- OLD HUNGARIAN CAPITAL LETTER II
775−foldMapping '\x10c91' s = Yield '\x10cd1' (CC s '\x0000' '\x0000')
776−-- OLD HUNGARIAN CAPITAL LETTER EJ
777−foldMapping '\x10c92' s = Yield '\x10cd2' (CC s '\x0000' '\x0000')
778−-- OLD HUNGARIAN CAPITAL LETTER EK
779−foldMapping '\x10c93' s = Yield '\x10cd3' (CC s '\x0000' '\x0000')
780−-- OLD HUNGARIAN CAPITAL LETTER AK
781−foldMapping '\x10c94' s = Yield '\x10cd4' (CC s '\x0000' '\x0000')
782−-- OLD HUNGARIAN CAPITAL LETTER UNK
783−foldMapping '\x10c95' s = Yield '\x10cd5' (CC s '\x0000' '\x0000')
784−-- OLD HUNGARIAN CAPITAL LETTER EL
785−foldMapping '\x10c96' s = Yield '\x10cd6' (CC s '\x0000' '\x0000')
786−-- OLD HUNGARIAN CAPITAL LETTER ELY
787−foldMapping '\x10c97' s = Yield '\x10cd7' (CC s '\x0000' '\x0000')
788−-- OLD HUNGARIAN CAPITAL LETTER EM
789−foldMapping '\x10c98' s = Yield '\x10cd8' (CC s '\x0000' '\x0000')
790−-- OLD HUNGARIAN CAPITAL LETTER EN
791−foldMapping '\x10c99' s = Yield '\x10cd9' (CC s '\x0000' '\x0000')
792−-- OLD HUNGARIAN CAPITAL LETTER ENY
793−foldMapping '\x10c9a' s = Yield '\x10cda' (CC s '\x0000' '\x0000')
794−-- OLD HUNGARIAN CAPITAL LETTER O
795−foldMapping '\x10c9b' s = Yield '\x10cdb' (CC s '\x0000' '\x0000')
796−-- OLD HUNGARIAN CAPITAL LETTER OO
797−foldMapping '\x10c9c' s = Yield '\x10cdc' (CC s '\x0000' '\x0000')
798−-- OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG OE
799−foldMapping '\x10c9d' s = Yield '\x10cdd' (CC s '\x0000' '\x0000')
800−-- OLD HUNGARIAN CAPITAL LETTER RUDIMENTA OE
801−foldMapping '\x10c9e' s = Yield '\x10cde' (CC s '\x0000' '\x0000')
802−-- OLD HUNGARIAN CAPITAL LETTER OEE
803−foldMapping '\x10c9f' s = Yield '\x10cdf' (CC s '\x0000' '\x0000')
804−-- OLD HUNGARIAN CAPITAL LETTER EP
805−foldMapping '\x10ca0' s = Yield '\x10ce0' (CC s '\x0000' '\x0000')
806−-- OLD HUNGARIAN CAPITAL LETTER EMP
807−foldMapping '\x10ca1' s = Yield '\x10ce1' (CC s '\x0000' '\x0000')
808−-- OLD HUNGARIAN CAPITAL LETTER ER
809−foldMapping '\x10ca2' s = Yield '\x10ce2' (CC s '\x0000' '\x0000')
810−-- OLD HUNGARIAN CAPITAL LETTER SHORT ER
811−foldMapping '\x10ca3' s = Yield '\x10ce3' (CC s '\x0000' '\x0000')
812−-- OLD HUNGARIAN CAPITAL LETTER ES
813−foldMapping '\x10ca4' s = Yield '\x10ce4' (CC s '\x0000' '\x0000')
814−-- OLD HUNGARIAN CAPITAL LETTER ESZ
815−foldMapping '\x10ca5' s = Yield '\x10ce5' (CC s '\x0000' '\x0000')
816−-- OLD HUNGARIAN CAPITAL LETTER ET
817−foldMapping '\x10ca6' s = Yield '\x10ce6' (CC s '\x0000' '\x0000')
818−-- OLD HUNGARIAN CAPITAL LETTER ENT
819−foldMapping '\x10ca7' s = Yield '\x10ce7' (CC s '\x0000' '\x0000')
820−-- OLD HUNGARIAN CAPITAL LETTER ETY
821−foldMapping '\x10ca8' s = Yield '\x10ce8' (CC s '\x0000' '\x0000')
822−-- OLD HUNGARIAN CAPITAL LETTER ECH
823−foldMapping '\x10ca9' s = Yield '\x10ce9' (CC s '\x0000' '\x0000')
824−-- OLD HUNGARIAN CAPITAL LETTER U
825−foldMapping '\x10caa' s = Yield '\x10cea' (CC s '\x0000' '\x0000')
826−-- OLD HUNGARIAN CAPITAL LETTER UU
827−foldMapping '\x10cab' s = Yield '\x10ceb' (CC s '\x0000' '\x0000')
828−-- OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG UE
829−foldMapping '\x10cac' s = Yield '\x10cec' (CC s '\x0000' '\x0000')
830−-- OLD HUNGARIAN CAPITAL LETTER RUDIMENTA UE
831−foldMapping '\x10cad' s = Yield '\x10ced' (CC s '\x0000' '\x0000')
832−-- OLD HUNGARIAN CAPITAL LETTER EV
833−foldMapping '\x10cae' s = Yield '\x10cee' (CC s '\x0000' '\x0000')
834−-- OLD HUNGARIAN CAPITAL LETTER EZ
835−foldMapping '\x10caf' s = Yield '\x10cef' (CC s '\x0000' '\x0000')
836−-- OLD HUNGARIAN CAPITAL LETTER EZS
837−foldMapping '\x10cb0' s = Yield '\x10cf0' (CC s '\x0000' '\x0000')
838−-- OLD HUNGARIAN CAPITAL LETTER ENT-SHAPED SIGN
839−foldMapping '\x10cb1' s = Yield '\x10cf1' (CC s '\x0000' '\x0000')
840−-- OLD HUNGARIAN CAPITAL LETTER US
841−foldMapping '\x10cb2' s = Yield '\x10cf2' (CC s '\x0000' '\x0000')
842570foldMapping c s = Yield (toLower c) (CC s '\0' '\0')
Data/Text/Internal/Fusion/Common.hs+75−63
@@ -71,6 +71,9 @@ module Data.Text.Internal.Fusion.Common
7171 -- ** Scans
7272 , scanl
7373
74+ -- ** Accumulating maps
75+ -- , mapAccumL
76+
7477 -- ** Generation and unfolding
7578 , replicateCharI
7679 , replicateI
@@ -120,7 +123,7 @@ singleton :: Char -> Stream Char
120123singleton c = Stream next False 1
121124 where next False = Yield c True
122125 next True = Done
123−{-# INLINE [0] singleton #-}
126+{-# INLINE singleton #-}
124127
125128streamList :: [a] -> Stream a
126129{-# INLINE [0] streamList #-}
@@ -184,9 +187,6 @@ cons !w (Stream next0 s0 len) = Stream next (C1 s0) (len+1)
184187 Yield x s' -> Yield x (C0 s')
185188{-# INLINE [0] cons #-}
186189
187−data Snoc a = N
188− | J !a
189−
190190-- | /O(n)/ Adds a character to the end of a stream.
191191snoc :: Stream Char -> Char -> Stream Char
192192snoc (Stream next0 xs0 len) w = Stream next (J xs0) (len+1)
@@ -315,13 +315,12 @@ lengthI (Stream next s0 _len) = loop_length 0 s0
315315--
316316-- This function gives the same answer as comparing against the result
317317-- of 'lengthI', but can short circuit if the count of characters is
318−-- greater than the number or if the stream can't possibly be as long
319−-- as the number supplied, and hence be more efficient.
318+-- greater than the number, and hence be more efficient.
320319compareLengthI :: Integral a => Stream Char -> a -> Ordering
321320compareLengthI (Stream next s0 len) n =
322− case compareSize len (fromIntegral n) of
323− Just o -> o
321+ case exactly len of
324322 Nothing -> loop_cmp 0 s0
323+ Just i -> compare (fromIntegral i) n
325324 where
326325 loop_cmp !z s = case next s of
327326 Done -> compare z n
@@ -473,20 +472,17 @@ toTitle (Stream next0 s0 len) = Stream next (CC (False :*: s0) '\0' '\0') len
473472 next (CC s a b) = Yield a (CC s b '\0')
474473{-# INLINE [0] toTitle #-}
475474
476−data Justify i s = Just1 !i !s
477− | Just2 !i !s
478−
479475justifyLeftI :: Integral a => a -> Char -> Stream Char -> Stream Char
480476justifyLeftI k c (Stream next0 s0 len) =
481− Stream next (Just1 0 s0) (larger (fromIntegral k) len)
477+ Stream next (s0 :*: S1 :*: 0) (larger (fromIntegral k) len)
482478 where
483− next (Just1 n s) =
479+ next (s :*: S1 :*: n) =
484480 case next0 s of
485− Done -> next (Just2 n s)
486− Skip s' -> Skip (Just1 n s')
487− Yield x s' -> Yield x (Just1 (n+1) s')
488− next (Just2 n s)
489− | n < k = Yield c (Just2 (n+1) s)
481+ Done -> next (s :*: S2 :*: n)
482+ Skip s' -> Skip (s' :*: S1 :*: n)
483+ Yield x s' -> Yield x (s' :*: S1 :*: n+1)
484+ next (s :*: S2 :*: n)
485+ | n < k = Yield c (s :*: S2 :*: n+1)
490486 | otherwise = Done
491487 {-# INLINE next #-}
492488{-# INLINE [0] justifyLeftI #-}
@@ -593,7 +589,7 @@ concatMap f = foldr (append . f) empty
593589{-# INLINE [0] concatMap #-}
594590
595591-- | /O(n)/ any @p @xs determines if any character in the stream
596−-- @xs@ satisfies the predicate @p@.
592+-- @xs@ satisifes the predicate @p@.
597593any :: (Char -> Bool) -> Stream Char -> Bool
598594any p (Stream next0 s0 _len) = loop_any s0
599595 where
@@ -605,7 +601,7 @@ any p (Stream next0 s0 _len) = loop_any s0
605601{-# INLINE [0] any #-}
606602
607603-- | /O(n)/ all @p @xs determines if all characters in the 'Text'
608−-- @xs@ satisfy the predicate @p@.
604+-- @xs@ satisify the predicate @p@.
609605all :: (Char -> Bool) -> Stream Char -> Bool
610606all p (Stream next0 s0 _len) = loop_all s0
611607 where
@@ -654,27 +650,50 @@ minimum (Stream next0 s0 _len) = loop0_minimum s0
654650-- * Building streams
655651
656652scanl :: (Char -> Char -> Char) -> Char -> Stream Char -> Stream Char
657−scanl f z0 (Stream next0 s0 len) = Stream next (Scan1 z0 s0) (len+1) -- HINT maybe too low
653+scanl f z0 (Stream next0 s0 len) = Stream next (S1 :*: z0 :*: s0) (len+1) -- HINT maybe too low
658654 where
659655 {-# INLINE next #-}
660− next (Scan1 z s) = Yield z (Scan2 z s)
661− next (Scan2 z s) = case next0 s of
662− Yield x s' -> let !x' = f z x
663− in Yield x' (Scan2 x' s')
664− Skip s' -> Skip (Scan2 z s')
665− Done -> Done
656+ next (S1 :*: z :*: s) = Yield z (S2 :*: z :*: s)
657+ next (S2 :*: z :*: s) = case next0 s of
658+ Yield x s' -> let !x' = f z x
659+ in Yield x' (S2 :*: x' :*: s')
660+ Skip s' -> Skip (S2 :*: z :*: s')
661+ Done -> Done
666662{-# INLINE [0] scanl #-}
667663
664+-- -----------------------------------------------------------------------------
665+-- ** Accumulating maps
666+
667+{-
668+-- | /O(n)/ Like a combination of 'map' and 'foldl'. Applies a
669+-- function to each element of a stream, passing an accumulating
670+-- parameter from left to right, and returns a final stream.
671+--
672+-- /Note/: Unlike the version over lists, this function does not
673+-- return a final value for the accumulator, because the nature of
674+-- streams precludes it.
675+mapAccumL :: (a -> b -> (a,b)) -> a -> Stream b -> Stream b
676+mapAccumL f z0 (Stream next0 s0 len) = Stream next (s0 :*: z0) len -- HINT depends on f
677+ where
678+ {-# INLINE next #-}
679+ next (s :*: z) = case next0 s of
680+ Yield x s' -> let (z',y) = f z x
681+ in Yield y (s' :*: z')
682+ Skip s' -> Skip (s' :*: z)
683+ Done -> Done
684+{-# INLINE [0] mapAccumL #-}
685+-}
686+
668687-- -----------------------------------------------------------------------------
669688-- ** Generating and unfolding streams
670689
671690replicateCharI :: Integral a => a -> Char -> Stream Char
672−replicateCharI !n !c
691+replicateCharI n c
673692 | n < 0 = empty
674693 | otherwise = Stream next 0 (fromIntegral n) -- HINT maybe too low
675694 where
676− next !i | i >= n = Done
677− | otherwise = Yield c (i + 1)
695+ next i | i >= n = Done
696+ | otherwise = Yield c (i + 1)
678697{-# INLINE [0] replicateCharI #-}
679698
680699data RI s = RI !s {-# UNPACK #-} !Int64
@@ -739,27 +758,24 @@ take n0 (Stream next0 s0 len) =
739758 Yield x s' -> Yield x ((n-1) :*: s')
740759{-# INLINE [0] take #-}
741760
742−data Drop a s = NS !s
743− | JS !a !s
744−
745761-- | /O(n)/ drop n, applied to a stream, returns the suffix of the
746762-- stream after the first @n@ characters, or the empty stream if @n@
747763-- is greater than the length of the stream.
748764drop :: Integral a => a -> Stream Char -> Stream Char
749765drop n0 (Stream next0 s0 len) =
750− Stream next (JS n0 s0) (len - fromIntegral (max 0 n0))
766+ Stream next (J n0 :*: s0) (len - fromIntegral (max 0 n0))
751767 where
752768 {-# INLINE next #-}
753− next (JS n s)
754− | n <= 0 = Skip (NS s)
769+ next (J n :*: s)
770+ | n <= 0 = Skip (N :*: s)
755771 | otherwise = case next0 s of
756772 Done -> Done
757− Skip s' -> Skip (JS n s')
758− Yield _ s' -> Skip (JS (n-1) s')
759− next (NS s) = case next0 s of
773+ Skip s' -> Skip (J n :*: s')
774+ Yield _ s' -> Skip (J (n-1) :*: s')
775+ next (N :*: s) = case next0 s of
760776 Done -> Done
761− Skip s' -> Skip (NS s')
762− Yield x s' -> Yield x (NS s')
777+ Skip s' -> Skip (N :*: s')
778+ Yield x s' -> Yield x (N :*: s')
763779{-# INLINE [0] drop #-}
764780
765781-- | takeWhile, applied to a predicate @p@ and a stream, returns the
@@ -777,18 +793,18 @@ takeWhile p (Stream next0 s0 len) = Stream next s0 len -- HINT maybe too high
777793
778794-- | dropWhile @p @xs returns the suffix remaining after takeWhile @p @xs.
779795dropWhile :: (Char -> Bool) -> Stream Char -> Stream Char
780−dropWhile p (Stream next0 s0 len) = Stream next (L s0) len -- HINT maybe too high
796+dropWhile p (Stream next0 s0 len) = Stream next (S1 :*: s0) len -- HINT maybe too high
781797 where
782798 {-# INLINE next #-}
783− next (L s) = case next0 s of
799+ next (S1 :*: s) = case next0 s of
784800 Done -> Done
785− Skip s' -> Skip (L s')
786− Yield x s' | p x -> Skip (L s')
787− | otherwise -> Yield x (R s')
788− next (R s) = case next0 s of
801+ Skip s' -> Skip (S1 :*: s')
802+ Yield x s' | p x -> Skip (S1 :*: s')
803+ | otherwise -> Yield x (S2 :*: s')
804+ next (S2 :*: s) = case next0 s of
789805 Done -> Done
790− Skip s' -> Skip (R s')
791− Yield x s' -> Yield x (R s')
806+ Skip s' -> Skip (S2 :*: s')
807+ Yield x s' -> Yield x (S2 :*: s')
792808{-# INLINE [0] dropWhile #-}
793809
794810-- | /O(n)/ The 'isPrefixOf' function takes two 'Stream's and returns
@@ -895,25 +911,21 @@ findIndicesI p (Stream next s0 _len) = loop_findIndex 0 s0
895911-------------------------------------------------------------------------------
896912-- * Zipping
897913
898−-- | Strict triple.
899−data Zip a b m = Z1 !a !b
900− | Z2 !a !b !m
901−
902914-- | zipWith generalises 'zip' by zipping with the function given as
903915-- the first argument, instead of a tupling function.
904916zipWith :: (a -> a -> b) -> Stream a -> Stream a -> Stream b
905917zipWith f (Stream next0 sa0 len1) (Stream next1 sb0 len2) =
906− Stream next (Z1 sa0 sb0) (smaller len1 len2)
918+ Stream next (sa0 :*: sb0 :*: N) (smaller len1 len2)
907919 where
908− next (Z1 sa sb) = case next0 sa of
909− Done -> Done
910− Skip sa' -> Skip (Z1 sa' sb)
911− Yield a sa' -> Skip (Z2 sa' sb a)
912−
913− next (Z2 sa' sb a) = case next1 sb of
914− Done -> Done
915− Skip sb' -> Skip (Z2 sa' sb' a)
916− Yield b sb' -> Yield (f a b) (Z1 sa' sb')
920+ next (sa :*: sb :*: N) = case next0 sa of
921+ Done -> Done
922+ Skip sa' -> Skip (sa' :*: sb :*: N)
923+ Yield a sa' -> Skip (sa' :*: sb :*: J a)
924+
925+ next (sa' :*: sb :*: J a) = case next1 sb of
926+ Done -> Done
927+ Skip sb' -> Skip (sa' :*: sb' :*: J a)
928+ Yield b sb' -> Yield (f a b) (sa' :*: sb' :*: N)
917929{-# INLINE [0] zipWith #-}
918930
919931-- | /O(n)/ The 'countCharI' function returns the number of times the
Data/Text/Internal/Fusion/Size.hs+52−60
@@ -22,28 +22,25 @@ module Data.Text.Internal.Fusion.Size
2222 , exactly
2323 , exactSize
2424 , maxSize
25− , betweenSize
2625 , unknownSize
2726 , smaller
2827 , larger
2928 , upperBound
30− , lowerBound
31− , compareSize
3229 , isEmpty
3330 ) where
3431
35−import Data.Text.Internal (mul)
3632#if defined(ASSERTS)
3733import Control.Exception (assert)
3834#endif
3935
40−data Size = Between {-# UNPACK #-} !Int {-# UNPACK #-} !Int -- ^ Lower and upper bounds on size.
41− | Unknown -- ^ Unknown size.
36+data Size = Exact {-# UNPACK #-} !Int -- ^ Exact size.
37+ | Max {-# UNPACK #-} !Int -- ^ Upper bound on size.
38+ | Unknown -- ^ Unknown size.
4239 deriving (Eq, Show)
4340
4441exactly :: Size -> Maybe Int
45−exactly (Between na nb) | na == nb = Just na
46−exactly _ = Nothing
42+exactly (Exact n) = Just n
43+exactly _ = Nothing
4744{-# INLINE exactly #-}
4845
4946exactSize :: Int -> Size
@@ -51,7 +48,7 @@ exactSize n =
5148#if defined(ASSERTS)
5249 assert (n >= 0)
5350#endif
54− Between n n
51+ Exact n
5552{-# INLINE exactSize #-}
5653
5754maxSize :: Int -> Size
@@ -59,18 +56,9 @@ maxSize n =
5956#if defined(ASSERTS)
6057 assert (n >= 0)
6158#endif
62− Between 0 n
59+ Max n
6360{-# INLINE maxSize #-}
6461
65−betweenSize :: Int -> Int -> Size
66−betweenSize m n =
67−#if defined(ASSERTS)
68− assert (m >= 0)
69− assert (n >= m)
70−#endif
71− Between m n
72−{-# INLINE betweenSize #-}
73−
7462unknownSize :: Size
7563unknownSize = Unknown
7664{-# INLINE unknownSize #-}
@@ -80,7 +68,7 @@ instance Num Size where
8068 (-) = subtractSize
8169 (*) = mulSize
8270
83− fromInteger = f where f = exactSize . fromInteger
71+ fromInteger = f where f = Exact . fromInteger
8472 {-# INLINE f #-}
8573
8674add :: Int -> Int -> Int
@@ -90,67 +78,71 @@ add m n | mn >= 0 = mn
9078{-# INLINE add #-}
9179
9280addSize :: Size -> Size -> Size
93−addSize (Between ma mb) (Between na nb) = Between (add ma na) (add mb nb)
94−addSize _ _ = Unknown
81+addSize (Exact m) (Exact n) = Exact (add m n)
82+addSize (Exact m) (Max n) = Max (add m n)
83+addSize (Max m) (Exact n) = Max (add m n)
84+addSize (Max m) (Max n) = Max (add m n)
85+addSize _ _ = Unknown
9586{-# INLINE addSize #-}
9687
9788subtractSize :: Size -> Size -> Size
98−subtractSize (Between ma mb) (Between na nb) = Between (max (ma-nb) 0) (max (mb-na) 0)
99−subtractSize a@(Between 0 _) Unknown = a
100−subtractSize (Between _ mb) Unknown = Between 0 mb
101−subtractSize _ _ = Unknown
89+subtractSize (Exact m) (Exact n) = Exact (max (m-n) 0)
90+subtractSize (Exact m) (Max _) = Max m
91+subtractSize (Max m) (Exact n) = Max (max (m-n) 0)
92+subtractSize a@(Max _) (Max _) = a
93+subtractSize a@(Max _) Unknown = a
94+subtractSize _ _ = Unknown
10295{-# INLINE subtractSize #-}
10396
97+mul :: Int -> Int -> Int
98+mul m n
99+ | m <= maxBound `quot` n = m * n
100+ | otherwise = overflowError
101+{-# INLINE mul #-}
102+
104103mulSize :: Size -> Size -> Size
105−mulSize (Between ma mb) (Between na nb) = Between (mul ma na) (mul mb nb)
106−mulSize _ _ = Unknown
104+mulSize (Exact m) (Exact n) = Exact (mul m n)
105+mulSize (Exact m) (Max n) = Max (mul m n)
106+mulSize (Max m) (Exact n) = Max (mul m n)
107+mulSize (Max m) (Max n) = Max (mul m n)
108+mulSize _ _ = Unknown
107109{-# INLINE mulSize #-}
108110
109111-- | Minimum of two size hints.
110112smaller :: Size -> Size -> Size
111−smaller a@(Between ma mb) b@(Between na nb)
112− | mb <= na = a
113− | nb <= ma = b
114− | otherwise = Between (ma `min` na) (mb `min` nb)
115−smaller a@(Between 0 _) Unknown = a
116−smaller (Between _ mb) Unknown = Between 0 mb
117−smaller Unknown b@(Between 0 _) = b
118−smaller Unknown (Between _ nb) = Between 0 nb
119−smaller Unknown Unknown = Unknown
113+smaller (Exact m) (Exact n) = Exact (m `min` n)
114+smaller (Exact m) (Max n) = Max (m `min` n)
115+smaller (Exact m) Unknown = Max m
116+smaller (Max m) (Exact n) = Max (m `min` n)
117+smaller (Max m) (Max n) = Max (m `min` n)
118+smaller a@(Max _) Unknown = a
119+smaller Unknown (Exact n) = Max n
120+smaller Unknown (Max n) = Max n
121+smaller Unknown Unknown = Unknown
120122{-# INLINE smaller #-}
121123
122124-- | Maximum of two size hints.
123125larger :: Size -> Size -> Size
124−larger a@(Between ma mb) b@(Between na nb)
125− | ma >= nb = a
126− | na >= mb = b
127− | otherwise = Between (ma `max` na) (mb `max` nb)
128−larger _ _ = Unknown
126+larger (Exact m) (Exact n) = Exact (m `max` n)
127+larger a@(Exact m) b@(Max n) | m >= n = a
128+ | otherwise = b
129+larger a@(Max m) b@(Exact n) | n >= m = b
130+ | otherwise = a
131+larger (Max m) (Max n) = Max (m `max` n)
132+larger _ _ = Unknown
129133{-# INLINE larger #-}
130134
131135-- | Compute the maximum size from a size hint, if possible.
132136upperBound :: Int -> Size -> Int
133−upperBound _ (Between _ n) = n
134−upperBound k _ = k
137+upperBound _ (Exact n) = n
138+upperBound _ (Max n) = n
139+upperBound k _ = k
135140{-# INLINE upperBound #-}
136141
137−-- | Compute the maximum size from a size hint, if possible.
138−lowerBound :: Int -> Size -> Int
139−lowerBound _ (Between n _) = n
140−lowerBound k _ = k
141−{-# INLINE lowerBound #-}
142−
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
148−compareSize _ _ = Nothing
149−
150−
151142isEmpty :: Size -> Bool
152−isEmpty (Between _ n) = n <= 0
153−isEmpty _ = False
143+isEmpty (Exact n) = n <= 0
144+isEmpty (Max n) = n <= 0
145+isEmpty _ = False
154146{-# INLINE isEmpty #-}
155147
156148overflowError :: Int
Data/Text/Internal/Fusion/Types.hs+13−8
@@ -20,11 +20,13 @@
2020module Data.Text.Internal.Fusion.Types
2121 (
2222 CC(..)
23+ , M(..)
24+ , M8
2325 , PairS(..)
24− , Scan(..)
2526 , RS(..)
2627 , Step(..)
2728 , Stream(..)
29+ , Switch(..)
2830 , empty
2931 ) where
3032
@@ -34,23 +36,26 @@ import Data.Word (Word8)
3436-- | Specialised tuple for case conversion.
3537data CC s = CC !s {-# UNPACK #-} !Char {-# UNPACK #-} !Char
3638
37−-- | Restreaming state.
39+-- | Specialised, strict Maybe-like type.
40+data M a = N
41+ | J !a
42+
43+type M8 = M Word8
44+
45+-- Restreaming state.
3846data RS s
3947 = RS0 !s
4048 | RS1 !s {-# UNPACK #-} !Word8
4149 | RS2 !s {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8
4250 | RS3 !s {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8 {-# UNPACK #-} !Word8
4351
44−-- | Strict pair.
52+infixl 2 :*:
4553data PairS a b = !a :*: !b
4654 -- deriving (Eq, Ord, Show)
47−infixl 2 :*:
4855
49−-- | An intermediate result in a scan.
50−data Scan s = Scan1 {-# UNPACK #-} !Char !s
51− | Scan2 {-# UNPACK #-} !Char !s
56+-- | Allow a function over a stream to switch between two states.
57+data Switch = S1 | S2
5258
53−-- | Intermediate result in a processing pipeline.
5459data Step s a = Done
5560 | Skip !s
5661 | Yield !a !s
Data/Text/Internal/Private.hs+4−4
@@ -16,14 +16,14 @@ module Data.Text.Internal.Private
1616 ) where
1717
1818import Control.Monad.ST (ST, runST)
19−import Data.Text.Internal (Text(..), text)
19+import Data.Text.Internal (Text(..), textP)
2020import Data.Text.Unsafe (Iter(..), iter)
2121import qualified Data.Text.Array as A
2222
2323span_ :: (Char -> Bool) -> Text -> (# Text, Text #)
2424span_ p t@(Text arr off len) = (# hd,tl #)
25− where hd = text arr off k
26− tl = text arr (off+k) (len-k)
25+ where hd = textP arr off k
26+ tl = textP arr (off+k) (len-k)
2727 !k = loop 0
2828 loop !i | i < len && p c = loop (i+d)
2929 | otherwise = i
@@ -33,5 +33,5 @@ span_ p t@(Text arr off len) = (# hd,tl #)
3333runText :: (forall s. (A.MArray s -> Int -> ST s Text) -> ST s Text) -> Text
3434runText act = runST (act $ \ !marr !len -> do
3535 arr <- A.unsafeFreeze marr
36− return $! text arr 0 len)
36+ return $! textP arr 0 len)
3737{-# INLINE runText #-}
Data/Text/Internal/Read.hs+3−3
@@ -7,7 +7,7 @@
77-- Stability : experimental
88-- Portability : GHC
99--
10−-- Common internal functions for reading textual data.
10+-- Common internal functiopns for reading textual data.
1111module Data.Text.Internal.Read
1212 (
1313 IReader
@@ -18,7 +18,7 @@ module Data.Text.Internal.Read
1818 , perhaps
1919 ) where
2020
21−import Control.Applicative as App (Applicative(..))
21+import Control.Applicative (Applicative(..))
2222import Control.Arrow (first)
2323import Control.Monad (ap)
2424import Data.Char (ord)
@@ -38,7 +38,7 @@ instance Applicative (IParser t) where
3838 (<*>) = ap
3939
4040instance Monad (IParser t) where
41− return = App.pure
41+ return = pure
4242 m >>= k = P $ \t -> case runP m t of
4343 Left err -> Left err
4444 Right (a,t') -> runP (k a) t'
Data/Text/Lazy.hs+25−200
@@ -3,10 +3,6 @@
33#if __GLASGOW_HASKELL__ >= 702
44{-# LANGUAGE Trustworthy #-}
55#endif
6−#if __GLASGOW_HASKELL__ >= 708
7−{-# LANGUAGE TypeFamilies #-}
8−#endif
9−
106-- |
117-- Module : Data.Text.Lazy
128-- Copyright : (c) 2009, 2010, 2012 Bryan O'Sullivan
@@ -125,10 +121,7 @@ module Data.Text.Lazy
125121 , mapAccumR
126122
127123 -- ** Generation and unfolding
128− , repeat
129124 , replicate
130− , cycle
131− , iterate
132125 , unfoldr
133126 , unfoldrN
134127
@@ -136,11 +129,8 @@ module Data.Text.Lazy
136129
137130 -- ** Breaking strings
138131 , take
139− , takeEnd
140132 , drop
141− , dropEnd
142133 , takeWhile
143− , takeWhileEnd
144134 , dropWhile
145135 , dropWhileEnd
146136 , dropAround
@@ -211,13 +201,9 @@ import Control.DeepSeq (NFData(..))
211201import Data.Int (Int64)
212202import qualified Data.List as L
213203import Data.Char (isSpace)
214−import Data.Data (Data(gfoldl, toConstr, gunfold, dataTypeOf), constrIndex,
215− Constr, mkConstr, DataType, mkDataType, Fixity(Prefix))
216−import Data.Binary (Binary(get, put))
204+import Data.Data (Data(gfoldl, toConstr, gunfold, dataTypeOf))
205+import Data.Data (mkNoRepType)
217206import Data.Monoid (Monoid(..))
218−#if MIN_VERSION_base(4,9,0)
219−import Data.Semigroup (Semigroup(..))
220−#endif
221207import Data.String (IsString(..))
222208import qualified Data.Text as T
223209import qualified Data.Text.Internal as T
@@ -226,10 +212,8 @@ import qualified Data.Text.Unsafe as T
226212import qualified Data.Text.Internal.Lazy.Fusion as S
227213import Data.Text.Internal.Fusion.Types (PairS(..))
228214import Data.Text.Internal.Lazy.Fusion (stream, unstream)
229−import Data.Text.Internal.Lazy (Text(..), chunk, empty, foldlChunks,
230− foldrChunks, smallChunkSize)
231−import Data.Text.Internal (firstf, safe, text)
232−import Data.Text.Lazy.Encoding (decodeUtf8', encodeUtf8)
215+import Data.Text.Internal.Lazy (Text(..), chunk, empty, foldlChunks, foldrChunks)
216+import Data.Text.Internal (firstf, safe, textP)
233217import qualified Data.Text.Internal.Functions as F
234218import Data.Text.Internal.Lazy.Search (indices)
235219#if __GLASGOW_HASKELL__ >= 702
@@ -237,13 +221,7 @@ import qualified GHC.CString as GHC
237221#else
238222import qualified GHC.Base as GHC
239223#endif
240−#if __GLASGOW_HASKELL__ >= 708
241−import qualified GHC.Exts as Exts
242−#endif
243224import GHC.Prim (Addr#)
244−#if MIN_VERSION_base(4,7,0)
245−import Text.Printf (PrintfArg, formatArg, formatString)
246−#endif
247225
248226-- $fusion
249227--
@@ -341,71 +319,25 @@ instance Show Text where
341319instance Read Text where
342320 readsPrec p str = [(pack x,y) | (x,y) <- readsPrec p str]
343321
344−#if MIN_VERSION_base(4,9,0)
345−-- Semigroup orphan instances for older GHCs are provided by
346−-- 'semigroups` package
347−
348−instance Semigroup Text where
349− (<>) = append
350−#endif
351−
352322instance Monoid Text where
353323 mempty = empty
354−#if MIN_VERSION_base(4,9,0)
355− mappend = (<>) -- future-proof definition
356−#else
357324 mappend = append
358−#endif
359325 mconcat = concat
360326
361327instance IsString Text where
362328 fromString = pack
363329
364−#if __GLASGOW_HASKELL__ >= 708
365−instance Exts.IsList Text where
366− type Item Text = Char
367− fromList = pack
368− toList = unpack
369−#endif
370−
371330#if defined(HAVE_DEEPSEQ)
372331instance NFData Text where
373332 rnf Empty = ()
374333 rnf (Chunk _ ts) = rnf ts
375334#endif
376335
377−instance Binary Text where
378− put t = put (encodeUtf8 t)
379− get = do
380− bs <- get
381− case decodeUtf8' bs of
382− P.Left exn -> P.fail (P.show exn)
383− P.Right a -> P.return a
384−
385−-- | This instance preserves data abstraction at the cost of inefficiency.
386−-- We omit reflection services for the sake of data abstraction.
387−--
388−-- This instance was created by copying the updated behavior of
389−-- @"Data.Text".@'Data.Text.Text'
390336instance Data Text where
391337 gfoldl f z txt = z pack `f` (unpack txt)
392− toConstr _ = packConstr
393− gunfold k z c = case constrIndex c of
394− 1 -> k (z pack)
395− _ -> error "Data.Text.Lazy.Text.gunfold"
396− dataTypeOf _ = textDataType
397−
398−#if MIN_VERSION_base(4,7,0)
399−-- | Only defined for @base-4.7.0.0@ and later
400−instance PrintfArg Text where
401− formatArg txt = formatString $ unpack txt
402−#endif
403−
404−packConstr :: Constr
405−packConstr = mkConstr textDataType "pack" [] Prefix
406−
407−textDataType :: DataType
408−textDataType = mkDataType "Data.Text.Lazy.Text" [packConstr]
338+ toConstr _ = error "Data.Text.Lazy.Text.toConstr"
339+ gunfold _ _ = error "Data.Text.Lazy.Text.gunfold"
340+ dataTypeOf _ = mkNoRepType "Data.Text.Lazy.Text"
409341
410342-- | /O(n)/ Convert a 'String' into a 'Text'.
411343--
@@ -433,14 +365,6 @@ unpackCString# addr# = unstream (S.streamCString# addr#)
433365 unstream (S.streamList (L.map safe (GHC.unpackCStringUtf8# a)))
434366 = unpackCString# a #-}
435367
436−{-# RULES "LAZY TEXT empty literal"
437− unstream (S.streamList (L.map safe []))
438− = Empty #-}
439−
440−{-# RULES "LAZY TEXT empty literal" forall a.
441− unstream (S.streamList (L.map safe [a]))
442− = Chunk (T.singleton a) Empty #-}
443−
444368-- | /O(1)/ Convert a character into a Text. Subject to fusion.
445369-- Performs replacement on invalid scalar values.
446370singleton :: Char -> Text
@@ -545,7 +469,7 @@ tail Empty = emptyError "tail"
545469 unstream (S.tail (stream t)) = tail t
546470 #-}
547471
548−-- | /O(n\/c)/ Returns all but the last character of a 'Text', which must
472+-- | /O(1)/ Returns all but the last character of a 'Text', which must
549473-- be non-empty. Subject to fusion.
550474init :: Text -> Text
551475init (Chunk t0 ts0) = go t0 ts0
@@ -581,7 +505,7 @@ isSingleton :: Text -> Bool
581505isSingleton = S.isSingleton . stream
582506{-# INLINE isSingleton #-}
583507
584−-- | /O(n\/c)/ Returns the last character of a 'Text', which must be
508+-- | /O(1)/ Returns the last character of a 'Text', which must be
585509-- non-empty. Subject to fusion.
586510last :: Text -> Char
587511last Empty = emptyError "last"
@@ -715,36 +639,13 @@ reverse = rev Empty
715639 where rev a Empty = a
716640 rev a (Chunk t ts) = rev (Chunk (T.reverse t) a) ts
717641
718−-- | /O(m+n)/ Replace every non-overlapping occurrence of @needle@ in
719−-- @haystack@ with @replacement@.
720−--
721−-- This function behaves as though it was defined as follows:
722−--
723−-- @
724−-- replace needle replacement haystack =
725−-- 'intercalate' replacement ('splitOn' needle haystack)
726−-- @
727−--
728−-- As this suggests, each occurrence is replaced exactly once. So if
729−-- @needle@ occurs in @replacement@, that occurrence will /not/ itself
730−-- be replaced recursively:
731−--
732−-- > replace "oo" "foo" "oo" == "foo"
733−--
734−-- In cases where several instances of @needle@ overlap, only the
735−-- first one will be replaced:
736−--
737−-- > replace "ofo" "bar" "ofofo" == "barfo"
642+-- | /O(m+n)/ Replace every occurrence of one substring with another.
738643--
739644-- In (unlikely) bad cases, this function's time complexity degrades
740645-- towards /O(n*m)/.
741−replace :: Text
742− -- ^ @needle@ to search for. If this string is empty, an
743− -- error will occur.
744− -> Text
745− -- ^ @replacement@ to replace @needle@ with.
746− -> Text
747− -- ^ @haystack@ in which to search.
646+replace :: Text -- ^ Text to search for
647+ -> Text -- ^ Replacement text
648+ -> Text -- ^ Input text
748649 -> Text
749650replace s d = intercalate d . splitOn s
750651{-# INLINE replace #-}
@@ -881,13 +782,13 @@ concatMap f = concat . foldr ((:) . f) []
881782{-# INLINE concatMap #-}
882783
883784-- | /O(n)/ 'any' @p@ @t@ determines whether any character in the
884−-- 'Text' @t@ satisfies the predicate @p@. Subject to fusion.
785+-- 'Text' @t@ satisifes the predicate @p@. Subject to fusion.
885786any :: (Char -> Bool) -> Text -> Bool
886787any p t = S.any p (stream t)
887788{-# INLINE any #-}
888789
889790-- | /O(n)/ 'all' @p@ @t@ determines whether all characters in the
890−-- 'Text' @t@ satisfy the predicate @p@. Subject to fusion.
791+-- 'Text' @t@ satisify the predicate @p@. Subject to fusion.
891792all :: (Char -> Bool) -> Text -> Bool
892793all p t = S.all p (stream t)
893794{-# INLINE all #-}
@@ -970,12 +871,6 @@ mapAccumR f = go
970871 go z Empty = (z, Empty)
971872{-# INLINE mapAccumR #-}
972873
973−-- | @'repeat' x@ is an infinite 'Text', with @x@ the value of every
974−-- element.
975−repeat :: Char -> Text
976−repeat c = let t = Chunk (T.replicate smallChunkSize (T.singleton c)) t
977− in t
978−
979874-- | /O(n*m)/ 'replicate' @n@ @t@ is a 'Text' consisting of the input
980875-- @t@ repeated @n@ times.
981876replicate :: Int64 -> Text -> Text
@@ -987,21 +882,6 @@ replicate n t
987882 | otherwise = t : rep (i+1)
988883{-# INLINE [1] replicate #-}
989884
990−-- | 'cycle' ties a finite, non-empty 'Text' into a circular one, or
991−-- equivalently, the infinite repetition of the original 'Text'.
992−cycle :: Text -> Text
993−cycle Empty = emptyError "cycle"
994−cycle t = let t' = foldrChunks Chunk t' t
995− in t'
996−
997−-- | @'iterate' f x@ returns an infinite 'Text' of repeated applications
998−-- of @f@ to @x@:
999−--
1000−-- > iterate f x == [x, f x, f (f x), ...]
1001−iterate :: (Char -> Char) -> Char -> Text
1002−iterate f c = let t c' = Chunk (T.singleton c') (t (f c'))
1003− in t c
1004−
1005885-- | /O(n)/ 'replicateChar' @n@ @c@ is a 'Text' of length @n@ with @c@ the
1006886-- value of every element. Subject to fusion.
1007887replicateChar :: Int64 -> Char -> Text
@@ -1055,22 +935,6 @@ take i t0 = take' i t0
1055935 unstream (S.take n (stream t)) = take n t
1056936 #-}
1057937
1058−-- | /O(n)/ 'takeEnd' @n@ @t@ returns the suffix remaining after
1059−-- taking @n@ characters from the end of @t@.
1060−--
1061−-- Examples:
1062−--
1063−-- > takeEnd 3 "foobar" == "bar"
1064−takeEnd :: Int64 -> Text -> Text
1065−takeEnd n t0
1066− | n <= 0 = empty
1067− | otherwise = takeChunk n empty . L.reverse . toChunks $ t0
1068− where takeChunk _ acc [] = acc
1069− takeChunk i acc (t:ts)
1070− | i <= l = chunk (T.takeEnd (fromIntegral i) t) acc
1071− | otherwise = takeChunk (i-l) (Chunk t acc) ts
1072− where l = fromIntegral (T.length t)
1073−
1074938-- | /O(n)/ 'drop' @n@, applied to a 'Text', returns the suffix of the
1075939-- 'Text' after the first @n@ characters, or the empty 'Text' if @n@
1076940-- is greater than the length of the 'Text'. Subject to fusion.
@@ -1093,23 +957,6 @@ drop i t0
1093957 unstream (S.drop n (stream t)) = drop n t
1094958 #-}
1095959
1096−-- | /O(n)/ 'dropEnd' @n@ @t@ returns the prefix remaining after
1097−-- dropping @n@ characters from the end of @t@.
1098−--
1099−-- Examples:
1100−--
1101−-- > dropEnd 3 "foobar" == "foo"
1102−dropEnd :: Int64 -> Text -> Text
1103−dropEnd n t0
1104− | n <= 0 = t0
1105− | otherwise = dropChunk n . L.reverse . toChunks $ t0
1106− where dropChunk _ [] = empty
1107− dropChunk m (t:ts)
1108− | m >= l = dropChunk (m-l) ts
1109− | otherwise = fromChunks . L.reverse $
1110− T.dropEnd (fromIntegral m) t : ts
1111− where l = fromIntegral (T.length t)
1112−
1113960-- | /O(n)/ 'dropWords' @n@ returns the suffix with @n@ 'Word16'
1114961-- values dropped, or the empty 'Text' if @n@ is greater than the
1115962-- number of 'Word16' values present.
@@ -1120,7 +967,7 @@ dropWords i t0
1120967 where drop' 0 ts = ts
1121968 drop' _ Empty = Empty
1122969 drop' n (Chunk (T.Text arr off len) ts)
1123− | n < len' = chunk (text arr (off+n') (len-n')) ts
970+ | n < len' = chunk (textP arr (off+n') (len-n')) ts
1124971 | otherwise = drop' (n - len') ts
1125972 where len' = fromIntegral len
1126973 n' = fromIntegral n
@@ -1144,20 +991,6 @@ takeWhile p t0 = takeWhile' t0
1144991"LAZY TEXT takeWhile -> unfused" [1] forall p t.
1145992 unstream (S.takeWhile p (stream t)) = takeWhile p t
1146993 #-}
1147−-- | /O(n)/ 'takeWhileEnd', applied to a predicate @p@ and a 'Text',
1148−-- returns the longest suffix (possibly empty) of elements that
1149−-- satisfy @p@.
1150−-- Examples:
1151−--
1152−-- > takeWhileEnd (=='o') "foo" == "oo"
1153−takeWhileEnd :: (Char -> Bool) -> Text -> Text
1154−takeWhileEnd p = takeChunk empty . L.reverse . toChunks
1155− where takeChunk acc [] = acc
1156− takeChunk acc (t:ts) = if T.length t' < T.length t
1157− then (Chunk t' acc)
1158− else takeChunk (Chunk t' acc) ts
1159− where t' = T.takeWhileEnd p t
1160−{-# INLINE takeWhileEnd #-}
1161994
1162995-- | /O(n)/ 'dropWhile' @p@ @t@ returns the suffix remaining after
1163996-- 'takeWhile' @p@ @t@. Subject to fusion.
@@ -1176,11 +1009,9 @@ dropWhile p t0 = dropWhile' t0
11761009"LAZY TEXT dropWhile -> unfused" [1] forall p t.
11771010 unstream (S.dropWhile p (stream t)) = dropWhile p t
11781011 #-}
1179−
11801012-- | /O(n)/ 'dropWhileEnd' @p@ @t@ returns the prefix remaining after
1181−-- dropping characters that satisfy the predicate @p@ from the end of
1013+-- dropping characters that fail the predicate @p@ from the end of
11821014-- @t@.
1183−--
11841015-- Examples:
11851016--
11861017-- > dropWhileEnd (=='.') "foo..." == "foo"
@@ -1197,7 +1028,7 @@ dropWhileEnd p = go
11971028{-# INLINE dropWhileEnd #-}
11981029
11991030-- | /O(n)/ 'dropAround' @p@ @t@ returns the substring remaining after
1200−-- dropping characters that satisfy the predicate @p@ from both the
1031+-- dropping characters that fail the predicate @p@ from both the
12011032-- beginning and end of @t@. Subject to fusion.
12021033dropAround :: (Char -> Bool) -> Text -> Text
12031034dropAround p = dropWhile p . dropWhileEnd p
@@ -1247,8 +1078,8 @@ splitAtWord _ Empty = empty :*: empty
12471078splitAtWord x (Chunk c@(T.Text arr off len) cs)
12481079 | y >= len = let h :*: t = splitAtWord (x-fromIntegral len) cs
12491080 in Chunk c h :*: t
1250− | otherwise = chunk (text arr off y) empty :*:
1251− chunk (text arr (off+y) (len-y)) cs
1081+ | otherwise = chunk (textP arr off y) empty :*:
1082+ chunk (textP arr (off+y) (len-y)) cs
12521083 where y = fromIntegral x
12531084
12541085-- | /O(n+m)/ Find the first instance of @needle@ (which must be
@@ -1392,10 +1223,9 @@ tails ts@(Chunk t ts')
13921223-- copies to create substrings; they just construct new 'Text's that
13931224-- are slices of the original.
13941225
1395−-- | /O(m+n)/ Break a 'Text' into pieces separated by the first 'Text'
1396−-- argument (which cannot be an empty string), consuming the
1397−-- delimiter. An empty delimiter is invalid, and will cause an error
1398−-- to be raised.
1226+-- | /O(m+n)/ Break a 'Text' into pieces separated by the first
1227+-- 'Text' argument, consuming the delimiter. An empty delimiter is
1228+-- invalid, and will cause an error to be raised.
13991229--
14001230-- Examples:
14011231--
@@ -1408,18 +1238,13 @@ tails ts@(Chunk t ts')
14081238-- > intercalate s . splitOn s == id
14091239-- > splitOn (singleton c) == split (==c)
14101240--
1411−-- (Note: the string @s@ to split on above cannot be empty.)
1412−--
14131241-- This function is strict in its first argument, and lazy in its
14141242-- second.
14151243--
14161244-- In (unlikely) bad cases, this function's time complexity degrades
14171245-- towards /O(n*m)/.
1418−splitOn :: Text
1419− -- ^ String to split on. If this string is empty, an error
1420− -- will occur.
1421− -> Text
1422− -- ^ Input text.
1246+splitOn :: Text -- ^ Text to split on
1247+ -> Text -- ^ Input text
14231248 -> [Text]
14241249splitOn pat src
14251250 | null pat = emptyError "splitOn"
Data/Text/Lazy/Builder.hs+1−1
@@ -8,7 +8,7 @@
88-- Module : Data.Text.Lazy.Builder
99-- Copyright : (c) 2013 Bryan O'Sullivan
1010-- (c) 2010 Johan Tibell
11−-- License : BSD-style (see LICENSE)
11+-- License : BSD3-style (see LICENSE)
1212--
1313-- Maintainer : Johan Tibell <johan.tibell@gmail.com>
1414-- Stability : experimental
Data/Text/Lazy/Builder/Int.hs+14−19
@@ -1,5 +1,4 @@
1−{-# LANGUAGE BangPatterns, CPP, MagicHash, RankNTypes, ScopedTypeVariables,
2− UnboxedTuples #-}
1+{-# LANGUAGE BangPatterns, CPP, MagicHash, RankNTypes, UnboxedTuples #-}
32#if __GLASGOW_HASKELL__ >= 702
43{-# LANGUAGE Trustworthy #-}
54#endif
@@ -7,7 +6,7 @@
76-- Module: Data.Text.Lazy.Builder.Int
87-- Copyright: (c) 2013 Bryan O'Sullivan
98-- (c) 2011 MailRank, Inc.
10−-- License: BSD-style
9+-- License: BSD3
1110-- Maintainer: Bryan O'Sullivan <bos@serpentine.com>
1211-- Stability: experimental
1312-- Portability: portable
@@ -35,7 +34,7 @@ import Control.Monad.ST
3534
3635#ifdef __GLASGOW_HASKELL__
3736# if defined(INTEGER_GMP)
38−import GHC.Integer.GMP.Internals (Integer(S#))
37+import GHC.Integer.GMP.Internals
3938# elif defined(INTEGER_SIMPLE)
4039import GHC.Integer
4140# else
@@ -55,7 +54,7 @@ decimal :: Integral a => a -> Builder
5554{-# RULES "decimal/Int16" decimal = boundedDecimal :: Int16 -> Builder #-}
5655{-# RULES "decimal/Int32" decimal = boundedDecimal :: Int32 -> Builder #-}
5756{-# RULES "decimal/Int64" decimal = boundedDecimal :: Int64 -> Builder #-}
58−{-# RULES "decimal/Word" decimal = positive :: Data.Word.Word -> Builder #-}
57+{-# RULES "decimal/Word" decimal = positive :: Word -> Builder #-}
5958{-# RULES "decimal/Word8" decimal = positive :: Word8 -> Builder #-}
6059{-# RULES "decimal/Word16" decimal = positive :: Word16 -> Builder #-}
6160{-# RULES "decimal/Word32" decimal = positive :: Word32 -> Builder #-}
@@ -134,15 +133,8 @@ i2w v = zero + fromIntegral v
134133
135134countDigits :: (Integral a) => a -> Int
136135{-# INLINE countDigits #-}
137−countDigits v0
138− | fromIntegral v64 == v0 = go 1 v64
139− | otherwise = goBig 1 (fromIntegral v0)
140− where v64 = fromIntegral v0
141− goBig !k (v :: Integer)
142− | v > big = goBig (k + 19) (v `quot` big)
143− | otherwise = go k (fromIntegral v)
144− big = 10000000000000000000
145− go !k (v :: Word64)
136+countDigits v0 = go 1 (fromIntegral v0 :: Word64)
137+ where go !k v
146138 | v < 10 = k
147139 | v < 100 = k + 1
148140 | v < 1000 = k + 2
@@ -194,12 +186,19 @@ hexDigit n
194186 | otherwise = singleton $! toEnum (fromIntegral n + 87)
195187{-# INLINE hexDigit #-}
196188
189+int :: Int -> Builder
190+int = decimal
191+{-# INLINE int #-}
192+
197193data T = T !Integer !Int
198194
199195integer :: Int -> Integer -> Builder
200196#ifdef INTEGER_GMP
201197integer 10 (S# i#) = decimal (I# i#)
202198integer 16 (S# i#) = hexadecimal (I# i#)
199+#else
200+integer 10 i = decimal i
201+integer 16 i = hexadecimal i
203202#endif
204203integer base i
205204 | i < 0 = singleton '-' <> go (-i)
@@ -247,11 +246,7 @@ integer base i
247246 PAIR(x,y) -> pblock q <> pblock r <> putB ns
248247 where q = fromInteger x
249248 r = fromInteger y
250− putB _ = Data.Monoid.mempty
251−
252− int :: Int -> Builder
253− int x | base == 10 = decimal x
254− | otherwise = hexadecimal x
249+ putB _ = mempty
255250
256251 pblock = loop maxDigits
257252 where
Data/Text/Lazy/Encoding.hs+21−9
@@ -46,25 +46,30 @@ module Data.Text.Lazy.Encoding
4646 , encodeUtf32LE
4747 , encodeUtf32BE
4848
49+#if MIN_VERSION_bytestring(0,10,4)
4950 -- * Encoding Text using ByteString Builders
5051 , encodeUtf8Builder
5152 , encodeUtf8BuilderEscaped
53+#endif
5254 ) where
5355
5456import Control.Exception (evaluate, try)
55−import Data.Monoid (Monoid(..))
5657import Data.Text.Encoding.Error (OnDecodeError, UnicodeException, strictDecode)
5758import Data.Text.Internal.Lazy (Text(..), chunk, empty, foldrChunks)
58−import Data.Word (Word8)
5959import qualified Data.ByteString as S
60−import qualified Data.ByteString.Builder as B
61−import qualified Data.ByteString.Builder.Extra as B (safeStrategy, toLazyByteStringWith)
62−import qualified Data.ByteString.Builder.Prim as BP
6360import qualified Data.ByteString.Lazy as B
6461import qualified Data.ByteString.Lazy.Internal as B
6562import qualified Data.ByteString.Unsafe as B
63+#if MIN_VERSION_bytestring(0,10,4)
64+import Data.Word (Word8)
65+import Data.Monoid (mempty, (<>))
66+import qualified Data.ByteString.Builder as B
67+import qualified Data.ByteString.Builder.Extra as B (safeStrategy, toLazyByteStringWith)
68+import qualified Data.ByteString.Builder.Prim as BP
6669import qualified Data.Text as T
70+#endif
6771import qualified Data.Text.Encoding as TE
72+import qualified Data.Text.Lazy as L
6873import qualified Data.Text.Internal.Lazy.Encoding.Fusion as E
6974import qualified Data.Text.Internal.Lazy.Fusion as F
7075import Data.Text.Unsafe (unsafeDupablePerformIO)
@@ -84,6 +89,8 @@ import Data.Text.Unsafe (unsafeDupablePerformIO)
8489
8590-- | /Deprecated/. Decode a 'ByteString' containing 7-bit ASCII
8691-- encoded text.
92+--
93+-- This function is deprecated. Use 'decodeLatin1' instead.
8794decodeASCII :: B.ByteString -> Text
8895decodeASCII = decodeUtf8
8996{-# DEPRECATED decodeASCII "Use decodeUtf8 instead" #-}
@@ -105,7 +112,7 @@ decodeUtf8With onErr (B.Chunk b0 bs0) =
105112 | S.null l = empty
106113 | otherwise = case onErr desc (Just (B.unsafeHead l)) of
107114 Nothing -> empty
108− Just c -> Chunk (T.singleton c) Empty
115+ Just c -> L.singleton c
109116 desc = "Data.Text.Lazy.Encoding.decodeUtf8With: Invalid UTF-8 stream"
110117decodeUtf8With _ _ = empty
111118
@@ -142,6 +149,7 @@ decodeUtf8' bs = unsafeDupablePerformIO $ do
142149{-# INLINE decodeUtf8' #-}
143150
144151encodeUtf8 :: Text -> B.ByteString
152+#if MIN_VERSION_bytestring(0,10,4)
145153encodeUtf8 Empty = B.empty
146154encodeUtf8 lt@(Chunk t _) =
147155 B.toLazyByteStringWith strategy B.empty $ encodeUtf8Builder lt
@@ -155,13 +163,17 @@ encodeUtf8 lt@(Chunk t _) =
155163 strategy = B.safeStrategy firstChunkSize B.defaultChunkSize
156164
157165encodeUtf8Builder :: Text -> B.Builder
158−encodeUtf8Builder =
159− foldrChunks (\c b -> TE.encodeUtf8Builder c `mappend` b) Data.Monoid.mempty
166+encodeUtf8Builder = foldrChunks (\c b -> TE.encodeUtf8Builder c <> b) mempty
160167
161168{-# INLINE encodeUtf8BuilderEscaped #-}
162169encodeUtf8BuilderEscaped :: BP.BoundedPrim Word8 -> Text -> B.Builder
163170encodeUtf8BuilderEscaped prim =
164− foldrChunks (\c b -> TE.encodeUtf8BuilderEscaped prim c `mappend` b) mempty
171+ foldrChunks (\c b -> TE.encodeUtf8BuilderEscaped prim c <> b) mempty
172+
173+#else
174+encodeUtf8 (Chunk c cs) = B.Chunk (TE.encodeUtf8 c) (encodeUtf8 cs)
175+encodeUtf8 Empty = B.Empty
176+#endif
165177
166178-- | Decode text from little endian UTF-16 encoding.
167179decodeUtf16LEWith :: OnDecodeError -> B.ByteString -> Text
Data/Text/Lazy/Read.hs+2−4
@@ -1,7 +1,5 @@
11{-# LANGUAGE OverloadedStrings, CPP #-}
2−#if __GLASGOW_HASKELL__ >= 704
3−{-# LANGUAGE Safe #-}
4−#elif __GLASGOW_HASKELL__ >= 702
2+#if __GLASGOW_HASKELL__ >= 702
53{-# LANGUAGE Trustworthy #-}
64#endif
75
@@ -56,7 +54,7 @@ decimal :: Integral a => Reader a
5654{-# SPECIALIZE decimal :: Reader Int32 #-}
5755{-# SPECIALIZE decimal :: Reader Int64 #-}
5856{-# SPECIALIZE decimal :: Reader Integer #-}
59−{-# SPECIALIZE decimal :: Reader Data.Word.Word #-}
57+{-# SPECIALIZE decimal :: Reader Word #-}
6058{-# SPECIALIZE decimal :: Reader Word8 #-}
6159{-# SPECIALIZE decimal :: Reader Word16 #-}
6260{-# SPECIALIZE decimal :: Reader Word32 #-}
Data/Text/Read.hs+1−1
@@ -55,7 +55,7 @@ decimal :: Integral a => Reader a
5555{-# SPECIALIZE decimal :: Reader Int32 #-}
5656{-# SPECIALIZE decimal :: Reader Int64 #-}
5757{-# SPECIALIZE decimal :: Reader Integer #-}
58−{-# SPECIALIZE decimal :: Reader Data.Word.Word #-}
58+{-# SPECIALIZE decimal :: Reader Word #-}
5959{-# SPECIALIZE decimal :: Reader Word8 #-}
6060{-# SPECIALIZE decimal :: Reader Word16 #-}
6161{-# SPECIALIZE decimal :: Reader Word32 #-}
Data/Text/Show.hsdeleted−89
@@ -1,89 +0,0 @@
1−{-# LANGUAGE CPP, MagicHash #-}
2−{-# OPTIONS_GHC -fno-warn-orphans #-}
3−#if __GLASGOW_HASKELL__ >= 702
4−{-# LANGUAGE Trustworthy #-}
5−#endif
6−
7−-- |
8−-- Module : Data.Text.Show
9−-- Copyright : (c) 2009-2015 Bryan O'Sullivan
10−--
11−-- License : BSD-style
12−-- Maintainer : bos@serpentine.com
13−-- Stability : experimental
14−-- Portability : GHC
15−
16−module Data.Text.Show
17− (
18− singleton
19− , unpack
20− , unpackCString#
21− ) where
22−
23−import Control.Monad.ST (ST)
24−import Data.Text.Internal (Text(..), empty_, safe)
25−import Data.Text.Internal.Fusion (stream, unstream)
26−import Data.Text.Internal.Unsafe.Char (unsafeWrite)
27−import GHC.Prim (Addr#)
28−import qualified Data.Text.Array as A
29−import qualified Data.Text.Internal.Fusion.Common as S
30−
31−#if __GLASGOW_HASKELL__ >= 702
32−import qualified GHC.CString as GHC
33−#else
34−import qualified GHC.Base as GHC
35−#endif
36−
37−instance Show Text where
38− showsPrec p ps r = showsPrec p (unpack ps) r
39−
40−-- | /O(n)/ Convert a 'Text' into a 'String'. Subject to fusion.
41−unpack :: Text -> String
42−unpack = S.unstreamList . stream
43−{-# INLINE [1] unpack #-}
44−
45−-- | /O(n)/ Convert a literal string into a 'Text'. Subject to
46−-- fusion.
47−--
48−-- This is exposed solely for people writing GHC rewrite rules.
49−unpackCString# :: Addr# -> Text
50−unpackCString# addr# = unstream (S.streamCString# addr#)
51−{-# NOINLINE unpackCString# #-}
52−
53−{-# RULES "TEXT literal" [1] forall a.
54− unstream (S.map safe (S.streamList (GHC.unpackCString# a)))
55− = unpackCString# a #-}
56−
57−{-# RULES "TEXT literal UTF8" [1] forall a.
58− unstream (S.map safe (S.streamList (GHC.unpackCStringUtf8# a)))
59− = unpackCString# a #-}
60−
61−{-# RULES "TEXT empty literal" [1]
62− unstream (S.map safe (S.streamList []))
63− = empty_ #-}
64−
65−{-# RULES "TEXT singleton literal" [1] forall a.
66− unstream (S.map safe (S.streamList [a]))
67− = singleton_ a #-}
68−
69−-- | /O(1)/ Convert a character into a Text. Subject to fusion.
70−-- Performs replacement on invalid scalar values.
71−singleton :: Char -> Text
72−singleton = unstream . S.singleton . safe
73−{-# INLINE [1] singleton #-}
74−
75−{-# RULES "TEXT singleton" forall a.
76− unstream (S.singleton (safe a))
77− = singleton_ a #-}
78−
79−-- This is intended to reduce inlining bloat.
80−singleton_ :: Char -> Text
81−singleton_ c = Text (A.run x) 0 len
82− where x :: ST s (A.MArray s)
83− x = do arr <- A.new len
84− _ <- unsafeWrite arr 0 d
85− return arr
86− len | d < '\x10000' = 1
87− | otherwise = 2
88− d = safe c
89−{-# NOINLINE singleton_ #-}
Data/Text/Unsafe.hs−11
@@ -18,7 +18,6 @@ module Data.Text.Unsafe
1818 , iter
1919 , iter_
2020 , reverseIter
21− , reverseIter_
2221 , unsafeHead
2322 , unsafeTail
2423 , lengthWord16
@@ -95,16 +94,6 @@ reverseIter (Text arr off _len) i
9594 k = j - 1
9695{-# INLINE reverseIter #-}
9796
98−-- | /O(1)/ Iterate one step backwards through a UTF-16 array,
99−-- returning the delta to add (i.e. a negative number) to give the
100−-- next offset to iterate at.
101−reverseIter_ :: Text -> Int -> Int
102−reverseIter_ (Text arr off _len) i
103− | m < 0xDC00 || m > 0xDFFF = -1
104− | otherwise = -2
105− where m = A.unsafeIndex arr (off+i)
106−{-# INLINE reverseIter_ #-}
107−
10897-- | /O(1)/ Return the length of a 'Text' in units of 'Word16'. This
10998-- is useful for sizing a target array appropriately before using
11099-- 'unsafeCopyToPtr'.
benchmarks/haskell/Benchmarks.hs+1−3
@@ -15,7 +15,6 @@ import qualified Benchmarks.EncodeUtf8 as EncodeUtf8
1515import qualified Benchmarks.Equality as Equality
1616import qualified Benchmarks.FileRead as FileRead
1717import qualified Benchmarks.FoldLines as FoldLines
18−import qualified Benchmarks.Mul as Mul
1918import qualified Benchmarks.Pure as Pure
2019import qualified Benchmarks.ReadNumbers as ReadNumbers
2120import qualified Benchmarks.Replace as Replace
@@ -50,10 +49,9 @@ benchmarks = do
5049 , Equality.benchmark (tf "japanese.txt")
5150 , FileRead.benchmark (tf "russian.txt")
5251 , FoldLines.benchmark (tf "russian.txt")
53− , Mul.benchmark
5452 , Pure.benchmark "tiny" (tf "tiny.txt")
5553 , Pure.benchmark "ascii" (tf "ascii-small.txt")
56− -- , Pure.benchmark "france" (tf "france.html")
54+ , Pure.benchmark "france" (tf "france.html")
5755 , Pure.benchmark "russian" (tf "russian-small.txt")
5856 , Pure.benchmark "japanese" (tf "japanese.txt")
5957 , ReadNumbers.benchmark (tf "numbers.txt")
benchmarks/haskell/Benchmarks/DecodeUtf8.hs+2−2
@@ -25,7 +25,7 @@ import Foreign.Ptr (Ptr, plusPtr)
2525import Foreign.ForeignPtr (withForeignPtr)
2626import Data.Word (Word8)
2727import qualified Criterion as C
28−import Criterion (Benchmark, bgroup, nf, whnfIO)
28+import Criterion (Benchmark, bgroup, nf)
2929import qualified Codec.Binary.UTF8.Generic as U8
3030import qualified Data.ByteString as B
3131import qualified Data.ByteString.Lazy as BL
@@ -48,7 +48,7 @@ benchmark kind fp = do
4848 return $ bgroup "DecodeUtf8"
4949 [ bench "Strict" $ nf T.decodeUtf8 bs
5050 , bench "Stream" $ nf decodeStream lbs
51− , bench "IConv" $ whnfIO $ iconv bs
51+ , bench "IConv" $ iconv bs
5252 , bench "StrictLength" $ nf (T.length . T.decodeUtf8) bs
5353 , bench "StrictInitLength" $ nf (T.length . T.init . T.decodeUtf8) bs
5454 , bench "Lazy" $ nf TL.decodeUtf8 lbs
benchmarks/haskell/Benchmarks/FileRead.hs+11−11
@@ -8,8 +8,8 @@ module Benchmarks.FileRead
88 ( benchmark
99 ) where
1010
11−import Control.Applicative ((<$>))
12−import Criterion (Benchmark, bgroup, bench, whnfIO)
11+import Control.Exception (evaluate)
12+import Criterion (Benchmark, bgroup, bench)
1313import qualified Data.ByteString as SB
1414import qualified Data.ByteString.Lazy as LB
1515import qualified Data.Text as T
@@ -21,13 +21,13 @@ import qualified Data.Text.Lazy.IO as LT
2121
2222benchmark :: FilePath -> IO Benchmark
2323benchmark p = return $ bgroup "FileRead"
24− [ bench "String" $ whnfIO $ length <$> readFile p
25− , bench "ByteString" $ whnfIO $ SB.length <$> SB.readFile p
26− , bench "LazyByteString" $ whnfIO $ LB.length <$> LB.readFile p
27− , bench "Text" $ whnfIO $ T.length <$> T.readFile p
28− , bench "LazyText" $ whnfIO $ LT.length <$> LT.readFile p
29− , bench "TextByteString" $ whnfIO $
30− (T.length . T.decodeUtf8) <$> SB.readFile p
31− , bench "LazyTextByteString" $ whnfIO $
32− (LT.length . LT.decodeUtf8) <$> LB.readFile p
24+ [ bench "String" $ readFile p >>= evaluate . length
25+ , bench "ByteString" $ SB.readFile p >>= evaluate . SB.length
26+ , bench "LazyByteString" $ LB.readFile p >>= evaluate . LB.length
27+ , bench "Text" $ T.readFile p >>= evaluate . T.length
28+ , bench "LazyText" $ LT.readFile p >>= evaluate . LT.length
29+ , bench "TextByteString" $
30+ SB.readFile p >>= evaluate . T.length . T.decodeUtf8
31+ , bench "LazyTextByteString" $
32+ LB.readFile p >>= evaluate . LT.length . LT.decodeUtf8
3333 ]
benchmarks/haskell/Benchmarks/FoldLines.hs+2−2
@@ -10,7 +10,7 @@ module Benchmarks.FoldLines
1010 ( benchmark
1111 ) where
1212
13−import Criterion (Benchmark, bgroup, bench, whnfIO)
13+import Criterion (Benchmark, bgroup, bench)
1414import System.IO
1515import qualified Data.ByteString as B
1616import qualified Data.Text as T
@@ -22,7 +22,7 @@ benchmark fp = return $ bgroup "ReadLines"
2222 , bench "ByteString" $ withHandle $ foldLinesB (\n _ -> n + 1) (0 :: Int)
2323 ]
2424 where
25− withHandle f = whnfIO $ do
25+ withHandle f = do
2626 h <- openFile fp ReadMode
2727 hSetBuffering h (BlockBuffering (Just 16384))
2828 x <- f h
benchmarks/haskell/Benchmarks/Mul.hsdeleted−138
@@ -1,138 +0,0 @@
1−module Benchmarks.Mul (benchmark) where
2−
3−import Control.Exception (evaluate)
4−import Criterion.Main
5−import Data.Int (Int32, Int64)
6−import Data.Text.Internal (mul32, mul64)
7−import qualified Data.Vector.Unboxed as U
8−
9−oldMul :: Int64 -> Int64 -> Int64
10−oldMul m n
11− | n == 0 = 0
12− | m <= maxBound `quot` n = m * n
13− | otherwise = error "overflow"
14−
15−benchmark :: IO Benchmark
16−benchmark = do
17− _ <- evaluate testVector32
18− _ <- evaluate testVector64
19− return $ bgroup "Mul" [
20− bench "oldMul" $ whnf (U.map (uncurry oldMul)) testVector64
21− , bench "mul64" $ whnf (U.map (uncurry mul64)) testVector64
22− , bench "*64" $ whnf (U.map (uncurry (*))) testVector64
23− , bench "mul32" $ whnf (U.map (uncurry mul32)) testVector32
24− , bench "*32" $ whnf (U.map (uncurry (*))) testVector32
25− ]
26−
27−testVector64 :: U.Vector (Int64,Int64)
28−testVector64 = U.fromList [
29− (0,1248868987182846646),(169004623633872,24458),(482549039517835,7614),
30− (372,8157063115504364),(27,107095594861148252),(3,63249878517962420),
31− (4363,255694473572912),(86678474,1732634806),(1572453024,1800489338),
32− (9384523143,77053781),(49024709555,75095046),(7,43457620410239131),
33− (8,8201563008844571),(387719037,1520696708),(189869238220197,1423),
34− (46788016849611,23063),(503077742109974359,0),(104,1502010908706487),
35− (30478140346,207525518),(80961140129236192,14),(4283,368012829143675),
36− (1028719181728108146,6),(318904,5874863049591),(56724427166898,110794),
37− (234539368,31369110449),(2,251729663598178612),(103291548194451219,5),
38− (76013,5345328755566),(1769631,2980846129318),(40898,60598477385754),
39− (0,98931348893227155),(573555872156917492,3),(318821187115,4476566),
40− (11152874213584,243582),(40274276,16636653248),(127,4249988676030597),
41− (103543712111871836,5),(71,16954462148248238),(3963027173504,216570),
42− (13000,503523808916753),(17038308,20018685905),(0,510350226577891549),
43− (175898,3875698895405),(425299191292676,5651),(17223451323664536,50),
44− (61755131,14247665326),(0,1018195131697569303),(36433751497238985,20),
45− (3473607861601050,1837),(1392342328,1733971838),(225770297367,3249655),
46− (14,127545244155254102),(1751488975299136,2634),(3949208,504190668767),
47− (153329,831454434345),(1066212122928663658,2),(351224,2663633539556),
48− (344565,53388869217),(35825609350446863,54),(276011553660081475,10),
49− (1969754174790470349,3),(35,68088438338633),(506710,3247689556438),
50− (11099382291,327739909),(105787303549,32824363),(210366111,14759049409),
51− (688893241579,3102676),(8490,70047474429581),(152085,29923000251880),
52− (5046974599257095,400),(4183167795,263434071),(10089728,502781960687),
53− (44831977765,4725378),(91,8978094664238578),(30990165721,44053350),
54− (1772377,149651820860),(243420621763408572,4),(32,5790357453815138),
55− (27980806337993771,5),(47696295759774,20848),(1745874142313778,1098),
56− (46869334770121,1203),(886995283,1564424789),(40679396544,76002479),
57− (1,672849481568486995),(337656187205,3157069),(816980552858963,6003),
58− (2271434085804831543,1),(0,1934521023868747186),(6266220038281,15825),
59− (4160,107115946987394),(524,246808621791561),(0,1952519482439636339),
60− (128,2865935904539691),(1044,3211982069426297),(16000511542473,88922),
61− (1253596745404082,2226),(27041,56836278958002),(23201,49247489754471),
62− (175906590497,21252392),(185163584757182295,24),(34742225226802197,150),
63− (2363228,250824838408),(216327527109550,45),(24,81574076994520675),
64− (28559899906542,15356),(10890139774837133,511),(2293,707179303654492),
65− (2749366833,40703233),(0,4498229704622845986),(439,4962056468281937),
66− (662,1453820621089921),(16336770612459631,220),(24282989393,74239137),
67− (2724564648490195,3),(743672760,124992589),(4528103,704330948891),
68− (6050483122491561,250),(13322953,13594265152),(181794,22268101450214),
69− (25957941712,75384092),(43352,7322262295009),(32838,52609059549923),
70− (33003585202001564,2),(103019,68430142267402),(129918230800,8742978),
71− (0,2114347379589080688),(2548,905723041545274),(222745067962838382,0),
72− (1671683850790425181,1),(455,4836932776795684),(794227702827214,6620),
73− (212534135175874,1365),(96432431858,29784975),(466626763743380,3484),
74− (29793949,53041519613),(8359,309952753409844),(3908960585331901,26),
75− (45185288970365760,114),(10131829775,68110174),(58039242399640479,83),
76− (628092278238719399,6),(1,196469106875361889),(302336625,16347502444),
77− (148,3748088684181047),(1,1649096568849015456),(1019866864,2349753026),
78− (8211344830,569363306),(65647579546873,34753),(2340190,1692053129069),
79− (64263301,30758930355),(48681618072372209,110),(7074794736,47640197),
80− (249634721521,7991792),(1162917363807215,232),(7446433349,420634045),
81− (63398619383,60709817),(51359004508011,14200),(131788797028647,7072),
82− (52079887791430043,7),(7,136277667582599838),(28582879735696,50327),
83− (1404582800566278,833),(469164435,15017166943),(99567079957578263,49),
84− (1015285971,3625801566),(321504843,4104079293),(5196954,464515406632),
85− (114246832260876,7468),(8149664437,487119673),(12265299,378168974869),
86− (37711995764,30766513),(3971137243,710996152),(483120070302,603162),
87− (103009942,61645547145),(8476344625340,6987),(547948761229739,1446),
88− (42234,18624767306301),(13486714173011,58948),(4,198309153268019840),
89− (9913176974,325539248),(28246225540203,116822),(2882463945582154,18),
90− (959,25504987505398),(3,1504372236378217710),(13505229956793,374987),
91− (751661959,457611342),(27375926,36219151769),(482168869,5301952074),
92− (1,1577425863241520640),(714116235611821,1164),(904492524250310488,0),
93− (5983514941763398,68),(10759472423,23540686),(72539568471529,34919),
94− (4,176090672310337473),(938702842110356453,1),(673652445,3335287382),
95− (3111998893666122,917),(1568013,3168419765469)]
96−
97−testVector32 :: U.Vector (Int32,Int32)
98−testVector32 = U.fromList [
99− (39242,410),(0,100077553),(2206,9538),(509400240,1),(38048,6368),
100− (1789,651480),(2399,157032),(701,170017),(5241456,14),(11212,70449),
101− (1,227804876),(749687254,1),(74559,2954),(1158,147957),(410604456,1),
102− (170851,1561),(92643422,1),(6192,180509),(7,24202210),(3440,241481),
103− (5753677,5),(294327,1622),(252,4454673),(127684121,11),(28315800,30),
104− (340370905,0),(1,667887987),(592782090,1),(49023,27641),(750,290387),
105− (72886,3847),(0,301047933),(3050276,473),(1,788366142),(59457,15813),
106− (637726933,1),(1135,344317),(853616,264),(696816,493),(7038,12046),
107− (125219574,4),(803694088,1),(107081726,1),(39294,21699),(16361,38191),
108− (132561123,12),(1760,23499),(847543,484),(175687349,1),(2963,252678),
109− (6248,224553),(27596,4606),(5422922,121),(1542,485890),(131,583035),
110− (59096,4925),(3637115,132),(0,947225435),(86854,6794),(2984745,339),
111− (760129569,1),(1,68260595),(380835652,2),(430575,2579),(54514,7211),
112− (15550606,3),(9,27367402),(3007053,207),(7060988,60),(28560,27130),
113− (1355,21087),(10880,53059),(14563646,4),(461886361,1),(2,169260724),
114− (241454126,2),(406797,1),(61631630,16),(44473,5943),(63869104,12),
115− (950300,1528),(2113,62333),(120817,9358),(100261456,1),(426764723,1),
116− (119,12723684),(3,53358711),(4448071,18),(1,230278091),(238,232102),
117− (8,57316440),(42437979,10),(6769,19555),(48590,22006),(11500585,79),
118− (2808,97638),(42,26952545),(11,32104194),(23954638,1),(785427272,0),
119− (513,81379),(31333960,37),(897772,1009),(4,25679692),(103027993,12),
120− (104972702,11),(546,443401),(7,65137092),(88574269,3),(872139069,0),
121− (2,97417121),(378802603,0),(141071401,4),(22613,10575),(2191743,118),
122− (470,116119),(7062,38166),(231056,1847),(43901963,9),(2400,70640),
123− (63553,1555),(34,11249573),(815174,1820),(997894011,0),(98881794,2),
124− (5448,43132),(27956,9),(904926,1357),(112608626,3),(124,613021),
125− (282086,1966),(99,10656881),(113799,1501),(433318,2085),(442,948171),
126− (165380,1043),(28,14372905),(14880,50462),(2386,219918),(229,1797565),
127− (1174961,298),(3925,41833),(3903515,299),(15690452,111),(360860521,3),
128− (7440846,81),(2541026,507),(0,492448477),(6869,82469),(245,8322939),
129− (3503496,253),(123495298,0),(150963,2299),(33,4408482),(1,200911107),
130− (305,252121),(13,123369189),(215846,8181),(2440,65387),(776764401,1),
131− (1241172,434),(8,15493155),(81953961,6),(17884993,5),(26,6893822),
132− (0,502035190),(1,582451018),(2,514870139),(227,3625619),(49,12720258),
133− (1456769,207),(94797661,10),(234407,893),(26843,5783),(15688,24547),
134− (4091,86268),(4339448,151),(21360,6294),(397046497,2),(1227,205936),
135− (9966,21959),(160046791,1),(0,159992224),(27,24974797),(19177,29334),
136− (4136148,42),(21179785,53),(61256583,31),(385,344176),(7,11934915),
137− (1,18992566),(3488065,5),(768021,224),(36288474,7),(8624,117561),
138− (8,20341439),(5903,261475),(561,1007618),(1738,392327),(633049,1708)]
benchmarks/haskell/Benchmarks/Programs/BigTable.hs+2−2
@@ -11,7 +11,7 @@ module Benchmarks.Programs.BigTable
1111 ( benchmark
1212 ) where
1313
14−import Criterion (Benchmark, bench, whnfIO)
14+import Criterion (Benchmark, bench)
1515import Data.Monoid (mappend, mconcat)
1616import Data.Text.Lazy.Builder (Builder, fromText, toLazyText)
1717import Data.Text.Lazy.IO (hPutStr)
@@ -19,7 +19,7 @@ import System.IO (Handle)
1919import qualified Data.Text as T
2020
2121benchmark :: Handle -> IO Benchmark
22−benchmark sink = return $ bench "BigTable" $ whnfIO $ do
22+benchmark sink = return $ bench "BigTable" $ do
2323 hPutStr sink "Content-Type: text/html\n\n<table>"
2424 hPutStr sink . toLazyText . makeTable =<< rows
2525 hPutStr sink "</table>"
benchmarks/haskell/Benchmarks/Programs/Cut.hs+2−2
@@ -16,7 +16,7 @@ module Benchmarks.Programs.Cut
1616 ( benchmark
1717 ) where
1818
19−import Criterion (Benchmark, bgroup, bench, whnfIO)
19+import Criterion (Benchmark, bgroup, bench)
2020import System.IO (Handle, hPutStr)
2121import qualified Data.ByteString as B
2222import qualified Data.ByteString.Char8 as BC
@@ -40,7 +40,7 @@ benchmark p sink from to = return $ bgroup "Cut"
4040 , bench' "LazyTextByteString" lazyTextByteString
4141 ]
4242 where
43− bench' n s = bench n $ whnfIO (s p sink from to)
43+ bench' n s = bench n (s p sink from to)
4444
4545string :: FilePath -> Handle -> Int -> Int -> IO ()
4646string fp sink from to = do
benchmarks/haskell/Benchmarks/Programs/Fold.hs+2−2
@@ -21,7 +21,7 @@ import Data.List (foldl')
2121import Data.List (intersperse)
2222import Data.Monoid (mempty, mappend, mconcat)
2323import System.IO (Handle)
24−import Criterion (Benchmark, bench, whnfIO)
24+import Criterion (Benchmark, bench)
2525import qualified Data.Text as T
2626import qualified Data.Text.IO as T
2727import qualified Data.Text.Lazy.Builder as TLB
@@ -30,7 +30,7 @@ import qualified Data.Text.Lazy.IO as TL
3030
3131benchmark :: FilePath -> Handle -> IO Benchmark
3232benchmark i o = return $
33− bench "Fold" $ whnfIO $ T.readFile i >>= TL.hPutStr o . fold 80
33+ bench "Fold" $ T.readFile i >>= TL.hPutStr o . fold 80
3434
3535-- | We represent a paragraph by a word list
3636--
benchmarks/haskell/Benchmarks/Programs/Sort.hs+9−10
@@ -17,7 +17,7 @@ module Benchmarks.Programs.Sort
1717 ( benchmark
1818 ) where
1919
20−import Criterion (Benchmark, bgroup, bench, whnfIO)
20+import Criterion (Benchmark, bgroup, bench)
2121import Data.Monoid (mconcat)
2222import System.IO (Handle, hPutStr)
2323import qualified Data.ByteString as B
@@ -35,17 +35,16 @@ import qualified Data.Text.Lazy.IO as TL
3535
3636benchmark :: FilePath -> Handle -> IO Benchmark
3737benchmark i o = return $ bgroup "Sort"
38− [ bench "String" $ whnfIO $ readFile i >>= hPutStr o . string
39− , bench "ByteString" $ whnfIO $ B.readFile i >>= B.hPutStr o . byteString
40− , bench "LazyByteString" $ whnfIO $
41− BL.readFile i >>= BL.hPutStr o . lazyByteString
42− , bench "Text" $ whnfIO $ T.readFile i >>= T.hPutStr o . text
43− , bench "LazyText" $ whnfIO $ TL.readFile i >>= TL.hPutStr o . lazyText
44− , bench "TextByteString" $ whnfIO $ B.readFile i >>=
38+ [ bench "String" $ readFile i >>= hPutStr o . string
39+ , bench "ByteString" $ B.readFile i >>= B.hPutStr o . byteString
40+ , bench "LazyByteString" $ BL.readFile i >>= BL.hPutStr o . lazyByteString
41+ , bench "Text" $ T.readFile i >>= T.hPutStr o . text
42+ , bench "LazyText" $ TL.readFile i >>= TL.hPutStr o . lazyText
43+ , bench "TextByteString" $ B.readFile i >>=
4544 B.hPutStr o . T.encodeUtf8 . text . T.decodeUtf8
46− , bench "LazyTextByteString" $ whnfIO $ BL.readFile i >>=
45+ , bench "LazyTextByteString" $ BL.readFile i >>=
4746 BL.hPutStr o . TL.encodeUtf8 . lazyText . TL.decodeUtf8
48− , bench "TextBuilder" $ whnfIO $ B.readFile i >>=
47+ , bench "TextBuilder" $ B.readFile i >>=
4948 BL.hPutStr o . TL.encodeUtf8 . textBuilder . T.decodeUtf8
5049 ]
5150
benchmarks/haskell/Benchmarks/Programs/StripTags.hs+5−5
@@ -15,7 +15,7 @@ module Benchmarks.Programs.StripTags
1515 ( benchmark
1616 ) where
1717
18−import Criterion (Benchmark, bgroup, bench, whnfIO)
18+import Criterion (Benchmark, bgroup, bench)
1919import Data.List (mapAccumL)
2020import System.IO (Handle, hPutStr)
2121import qualified Data.ByteString as B
@@ -26,10 +26,10 @@ import qualified Data.Text.IO as T
2626
2727benchmark :: FilePath -> Handle -> IO Benchmark
2828benchmark i o = return $ bgroup "StripTags"
29− [ bench "String" $ whnfIO $ readFile i >>= hPutStr o . string
30− , bench "ByteString" $ whnfIO $ B.readFile i >>= B.hPutStr o . byteString
31− , bench "Text" $ whnfIO $ T.readFile i >>= T.hPutStr o . text
32− , bench "TextByteString" $ whnfIO $
29+ [ bench "String" $ readFile i >>= hPutStr o . string
30+ , bench "ByteString" $ B.readFile i >>= B.hPutStr o . byteString
31+ , bench "Text" $ T.readFile i >>= T.hPutStr o . text
32+ , bench "TextByteString" $
3333 B.readFile i >>= B.hPutStr o . T.encodeUtf8 . text . T.decodeUtf8
3434 ]
3535
benchmarks/haskell/Benchmarks/Programs/Throughput.hs+8−8
@@ -18,7 +18,7 @@ module Benchmarks.Programs.Throughput
1818 ( benchmark
1919 ) where
2020
21−import Criterion (Benchmark, bgroup, bench, whnfIO)
21+import Criterion (Benchmark, bgroup, bench)
2222import System.IO (Handle, hPutStr)
2323import qualified Data.ByteString as B
2424import qualified Data.ByteString.Lazy as BL
@@ -29,13 +29,13 @@ import qualified Data.Text.Lazy.IO as TL
2929
3030benchmark :: FilePath -> Handle -> IO Benchmark
3131benchmark fp sink = return $ bgroup "Throughput"
32− [ bench "String" $ whnfIO $ readFile fp >>= hPutStr sink
33− , bench "ByteString" $ whnfIO $ B.readFile fp >>= B.hPutStr sink
34− , bench "LazyByteString" $ whnfIO $ BL.readFile fp >>= BL.hPutStr sink
35− , bench "Text" $ whnfIO $ T.readFile fp >>= T.hPutStr sink
36− , bench "LazyText" $ whnfIO $ TL.readFile fp >>= TL.hPutStr sink
37− , bench "TextByteString" $ whnfIO $
32+ [ bench "String" $ readFile fp >>= hPutStr sink
33+ , bench "ByteString" $ B.readFile fp >>= B.hPutStr sink
34+ , bench "LazyByteString" $ BL.readFile fp >>= BL.hPutStr sink
35+ , bench "Text" $ T.readFile fp >>= T.hPutStr sink
36+ , bench "LazyText" $ TL.readFile fp >>= TL.hPutStr sink
37+ , bench "TextByteString" $
3838 B.readFile fp >>= B.hPutStr sink . T.encodeUtf8 . T.decodeUtf8
39− , bench "LazyTextByteString" $ whnfIO $
39+ , bench "LazyTextByteString" $
4040 BL.readFile fp >>= BL.hPutStr sink . TL.encodeUtf8 . TL.decodeUtf8
4141 ]
benchmarks/haskell/Benchmarks/Pure.hs−7
@@ -262,13 +262,6 @@ benchmark kind fp = do
262262 , benchBSL $ nf (BL.map toUpper) bla
263263 , benchS $ nf (L.map toUpper) sa
264264 ]
265− , bgroup "uncons"
266− [ benchT $ nf T.uncons ta
267− , benchTL $ nf TL.uncons tla
268− , benchBS $ nf BS.uncons bsa
269− , benchBSL $ nf BL.uncons bla
270− , benchS $ nf L.uncons sa
271− ]
272265 , bgroup "words"
273266 [ benchT $ nf T.words ta
274267 , benchTL $ nf TL.words tla
benchmarks/haskell/Benchmarks/ReadNumbers.hs+5−2
@@ -25,7 +25,8 @@ import Data.List (foldl')
2525import Numeric (readDec, readFloat, readHex)
2626import qualified Data.ByteString.Char8 as B
2727import qualified Data.ByteString.Lazy.Char8 as BL
28−import qualified Data.ByteString.Lex.Fractional as B
28+import qualified Data.ByteString.Lex.Double as B
29+import qualified Data.ByteString.Lex.Lazy.Double as BL
2930import qualified Data.Text as T
3031import qualified Data.Text.IO as T
3132import qualified Data.Text.Lazy as TL
@@ -62,10 +63,12 @@ benchmark fp = do
6263 whnf (double . text TL.rational) tl
6364
6465 , bench "DecimalByteString" $ whnf (int . byteString B.readInt) b
65− , bench "DoubleByteString" $ whnf (double . byteString B.readDecimal) b
66+ , bench "DoubleByteString" $ whnf (double . byteString B.readDouble) b
6667
6768 , bench "DecimalLazyByteString" $
6869 whnf (int . byteString BL.readInt) bl
70+ , bench "DoubleLazyByteString" $
71+ whnf (double . byteString BL.readDouble) bl
6972 ]
7073 where
7174 -- Used for fixing types
benchmarks/haskell/Benchmarks/Stream.hs+5−16
@@ -18,11 +18,11 @@ import qualified Data.Text.Encoding as T
1818import qualified Data.Text.Encoding.Error as E
1919import qualified Data.Text.Internal.Encoding.Fusion as T
2020import qualified Data.Text.Internal.Encoding.Fusion.Common as F
21−import qualified Data.Text.Internal.Fusion as F
21+import qualified Data.Text.Internal.Fusion as T
2222import qualified Data.Text.IO as T
2323import qualified Data.Text.Lazy.Encoding as TL
2424import qualified Data.Text.Internal.Lazy.Encoding.Fusion as TL
25−import qualified Data.Text.Internal.Lazy.Fusion as FL
25+import qualified Data.Text.Internal.Lazy.Fusion as TL
2626import qualified Data.Text.Lazy.IO as TL
2727
2828instance NFData a => NFData (Stream a) where
@@ -53,25 +53,14 @@ benchmark fp = do
5353 !utf32beL = TL.encodeUtf32BE tl
5454
5555 -- For the functions which operate on streams
56− let !s = F.stream t
56+ let !s = T.stream t
5757
5858 return $ bgroup "Stream"
5959
6060 -- Fusion
6161 [ bgroup "stream" $
62− [ bench "Text" $ nf F.stream t
63− , bench "LazyText" $ nf FL.stream tl
64− ]
65− -- must perform exactly the same as stream above due to
66− -- stream/unstream (i.e. stream after unstream) fusion
67− , bgroup "stream-fusion" $
68− [ bench "Text" $ nf (F.stream . F.unstream . F.stream) t
69− , bench "LazyText" $ nf (FL.stream . FL.unstream . FL.stream) tl
70− ]
71− -- measure the overhead of unstream after stream
72− , bgroup "stream-unstream" $
73− [ bench "Text" $ nf (F.unstream . F.stream) t
74− , bench "LazyText" $ nf (FL.unstream . FL.stream) tl
62+ [ bench "Text" $ nf T.stream t
63+ , bench "LazyText" $ nf TL.stream tl
7564 ]
7665
7766 -- Encoding.Fusion
benchmarks/text-benchmarks.cabal+6−18
@@ -3,7 +3,7 @@ version: 0.0.0.0
33synopsis: Benchmarks for the text package
44description: Benchmarks for the text package
55homepage: https://bitbucket.org/bos/text
6−license: BSD2
6+license: BSD3
77license-file: ../LICENSE
88author: Jasper Van der Jeugt <jaspervdj@gmail.com>,
99 Bryan O'Sullivan <bos@serpentine.com>,
@@ -15,15 +15,9 @@ build-type: Simple
1515
1616cabal-version: >=1.2
1717
18−flag bytestring-builder
19− description: Depend on the bytestring-builder package for backwards compatibility.
20− default: False
21− manual: False
22−
2318flag llvm
2419 description: use LLVM
2520 default: False
26− manual: True
2721
2822executable text-benchmarks
2923 hs-source-dirs: haskell ..
@@ -31,30 +25,24 @@ executable text-benchmarks
3125 cbits/time_iconv.c
3226 include-dirs: ../include
3327 main-is: Benchmarks.hs
34− ghc-options: -Wall -O2 -rtsopts
28+ ghc-options: -Wall -O2
3529 if flag(llvm)
3630 ghc-options: -fllvm
3731 cpp-options: -DHAVE_DEEPSEQ -DINTEGER_GMP
3832 build-depends: base == 4.*,
3933 binary,
4034 blaze-builder,
41− bytestring-lexing >= 0.5.0,
35+ bytestring,
36+ bytestring-lexing,
4237 containers,
43− criterion >= 0.10.0.0,
38+ criterion >= 0.6.0.1,
4439 deepseq,
4540 directory,
4641 filepath,
4742 ghc-prim,
4843 integer-gmp,
4944 stringsearch,
50− utf8-string,
51− vector
52−
53− if flag(bytestring-builder)
54− build-depends: bytestring >= 0.9 && < 0.10.4,
55− bytestring-builder >= 0.10.4
56− else
57− build-depends: bytestring >= 0.10.4
45+ utf8-string
5846
5947executable text-multilang
6048 hs-source-dirs: haskell
cbits/cbits.c+6−6
@@ -68,8 +68,8 @@ decode(uint32_t *state, uint32_t* codep, uint32_t byte) {
6868 * an UTF16 array
6969 */
7070void
71−_hs_text_decode_latin1(uint16_t *dest, const uint8_t *src,
72− const uint8_t *srcend)
71+_hs_text_decode_latin1(uint16_t *dest, const uint8_t const *src,
72+ const uint8_t const *srcend)
7373{
7474 const uint8_t *p = src;
7575
@@ -130,14 +130,14 @@ _hs_text_decode_latin1(uint16_t *dest, const uint8_t *src,
130130#if defined(__GNUC__) || defined(__clang__)
131131static inline uint8_t const *
132132_hs_text_decode_utf8_int(uint16_t *const dest, size_t *destoff,
133− const uint8_t **src, const uint8_t *srcend,
133+ const uint8_t const **src, const uint8_t const *srcend,
134134 uint32_t *codepoint0, uint32_t *state0)
135135 __attribute((always_inline));
136136#endif
137137
138138static inline uint8_t const *
139139_hs_text_decode_utf8_int(uint16_t *const dest, size_t *destoff,
140− const uint8_t **src, const uint8_t *srcend,
140+ const uint8_t const **src, const uint8_t const *srcend,
141141 uint32_t *codepoint0, uint32_t *state0)
142142{
143143 uint16_t *d = dest + *destoff;
@@ -202,8 +202,8 @@ _hs_text_decode_utf8_int(uint16_t *const dest, size_t *destoff,
202202
203203uint8_t const *
204204_hs_text_decode_utf8_state(uint16_t *const dest, size_t *destoff,
205− const uint8_t **src,
206− const uint8_t *srcend,
205+ const uint8_t const **src,
206+ const uint8_t const *srcend,
207207 uint32_t *codepoint0, uint32_t *state0)
208208{
209209 uint8_t const *ret = _hs_text_decode_utf8_int(dest, destoff, src, srcend,
changelognew file+41
@@ -0,0 +1,41 @@
1+1.1.0.0
2+
3+ * encodeUtf8: Performance is improved by up to 4x.
4+
5+ * encodeUtf8Builder, encodeUtf8BuilderEscaped: new functions,
6+ available only if bytestring >= 0.10.4.0 is installed, that
7+ allow very fast and flexible encoding of a Text value to a
8+ bytestring Builder.
9+
10+ As an example of the performance gain to be had, the
11+ encodeUtf8BuilderEscaped function helps to double the speed
12+ of JSON encoding in the latest version of aeson! (Note: if
13+ all you need is a plain ByteString, encodeUtf8 is still the
14+ faster way to go.)
15+
16+ * All of the internal module hierarchy is now publicly
17+ exposed. If a module is in the .Internal hierarchy, or is
18+ documented as internal, use at your own risk - there are no
19+ API stability guarantees for internal modules!
20+
21+1.0.0.1
22+
23+ * decodeUtf8: Fixed a regression that caused us to incorrectly
24+ identify truncated UTF-8 as valid (gh-61)
25+
26+1.0.0.0
27+
28+ * Added support for Unicode 6.3.0 to case conversion functions
29+
30+ * New function toTitle converts words in a string to title case
31+
32+ * New functions peekCStringLen and withCStringLen simplify
33+ interoperability with C functionns
34+
35+ * Added support for decoding UTF-8 in stream-friendly fashion
36+
37+ * Fixed a bug in mapAccumL
38+
39+ * Added trusted Haskell support
40+
41+ * Removed support for GHC 6.10 (released in 2008) and older
changelog.mddeleted−164
@@ -1,164 +0,0 @@
1−1.2.2.1
2−
3−* The switch to `integer-pure` in 1.2.2.0 was apparently mistaken.
4− The build flag has been renamed accordingly. Your army of diligent
5− maintainers apologizes for the churn.
6−
7−* Spec compliance: toCaseFold now follows the Unicode 8.0 spec
8− (updated from 7.0)
9−
10−* An STG lint error has been fixed
11−
12−1.2.2.0
13−
14−* The `integer-simple` package, upon which this package optionally
15− depended, has been replaced with `integer-pure`. The build flag has
16− been renamed accordingly.
17−
18−* Bug fix: For the `Binary` instance, If UTF-8 decoding fails during a
19− `get`, the error is propagated via `fail` instead of an uncatchable
20− crash.
21−
22−* New function: `takeWhileEnd`
23−
24−* New instances for the `Text` types:
25− * if `base` >= 4.7: `PrintfArg`
26− * if `base` >= 4.9: `Semigroup`
27−
28−1.2.1.3
29−
30−* Bug fix: As it turns out, moving the literal rewrite rules to simplifier
31− phase 2 does not prevent competition with the `unpack` rule, which is
32− also active in this phase. Unfortunately this was hidden due to a silly
33− test environment mistake. Moving literal rules back to phase 1 finally
34− fixes GHC Trac #10528 correctly.
35−
36−1.2.1.2
37−
38−* Bug fix: Run literal rewrite rules in simplifier phase 2.
39− The behavior of the simplifier changed in GHC 7.10.2,
40− causing these rules to fail to fire, leading to poor code generation
41− and long compilation times. See
42− [GHC Trac #10528](https://ghc.haskell.org/trac/ghc/ticket/10528).
43−
44−1.2.1.1
45−
46−* Expose unpackCString#, which you should never use.
47−
48−1.2.1.0
49−
50−* Added Binary instances for both Text types. (If you have previously
51− been using the text-binary package to get a Binary instance, it is
52− now obsolete.)
53−
54−1.2.0.6
55−
56−* Fixed a space leak in UTF-8 decoding
57−
58−1.2.0.5
59−
60−* Feature parity: repeat, cycle, iterate are now implemented for lazy
61− Text, and the Data instance is more complete
62−
63−* Build speed: an inliner space explosion has been fixed with toCaseFold
64−
65−* Bug fix: encoding Int to a Builder would infinite-loop if the
66− integer-simple package was used
67−
68−* Deprecation: OnEncodeError and EncodeError are deprecated, as they
69− are never used
70−
71−* Internals: some types that are used internally in fusion-related
72− functions have moved around, been renamed, or been deleted (we don't
73− bump the major version if .Internal modules change)
74−
75−* Spec compliance: toCaseFold now follows the Unicode 7.0 spec
76− (updated from 6.3)
77−
78−1.2.0.4
79−
80−* Fixed an incompatibility with base < 4.5
81−
82−1.2.0.3
83−
84−* Update formatRealFloat to correspond to the definition in versions
85− of base newer than 4.5 (https://github.com/bos/text/issues/105)
86−
87−1.2.0.2
88−
89−* Bumped lower bound on deepseq to 1.4 for compatibility with the
90− upcoming GHC 7.10
91−
92−1.2.0.1
93−
94−* Fixed a buffer overflow in rendering of large Integers
95− (https://github.com/bos/text/issues/99)
96−
97−1.2.0.0
98−
99−* Fixed an integer overflow in the replace function
100− (https://github.com/bos/text/issues/81)
101−
102−* Fixed a hang in lazy decodeUtf8With
103− (https://github.com/bos/text/issues/87)
104−
105−* Reduced codegen bloat caused by use of empty and single-character
106− literals
107−
108−* Added an instance of IsList for GHC 7.8 and above
109−
110−1.1.1.0
111−
112−* The Data.Data instance now allows gunfold to work, via a virtual
113− pack constructor
114−
115−* dropEnd, takeEnd: new functions
116−
117−* Comparing the length of a Text against a number can now
118− short-circuit in more cases
119−
120−1.1.0.1
121−
122−* streamDecodeUtf8: fixed gh-70, did not return all unconsumed bytes
123− in single-byte chunks
124−
125−1.1.0.0
126−
127−* encodeUtf8: Performance is improved by up to 4x.
128−
129−* encodeUtf8Builder, encodeUtf8BuilderEscaped: new functions,
130− available only if bytestring >= 0.10.4.0 is installed, that allow
131− very fast and flexible encoding of a Text value to a bytestring
132− Builder.
133−
134− As an example of the performance gain to be had, the
135− encodeUtf8BuilderEscaped function helps to double the speed of JSON
136− encoding in the latest version of aeson! (Note: if all you need is a
137− plain ByteString, encodeUtf8 is still the faster way to go.)
138−
139−* All of the internal module hierarchy is now publicly exposed. If a
140− module is in the .Internal hierarchy, or is documented as internal,
141− use at your own risk - there are no API stability guarantees for
142− internal modules!
143−
144−1.0.0.1
145−
146−* decodeUtf8: Fixed a regression that caused us to incorrectly
147− identify truncated UTF-8 as valid (gh-61)
148−
149−1.0.0.0
150−
151−* Added support for Unicode 6.3.0 to case conversion functions
152−
153−* New function toTitle converts words in a string to title case
154−
155−* New functions peekCStringLen and withCStringLen simplify
156− interoperability with C functionns
157−
158−* Added support for decoding UTF-8 in stream-friendly fashion
159−
160−* Fixed a bug in mapAccumL
161−
162−* Added trusted Haskell support
163−
164−* Removed support for GHC 6.10 (released in 2008) and older
scripts/CaseFolding.hs+1−1
@@ -37,7 +37,7 @@ mapCF :: CaseFolding -> [String]
3737mapCF (CF _ ms) = typ ++ (map nice . filter p $ ms) ++ [last]
3838 where
3939 typ = ["foldMapping :: forall s. Char -> s -> Step (CC s) Char"
40− ,"{-# NOINLINE foldMapping #-}"]
40+ ,"{-# INLINE foldMapping #-}"]
4141 last = "foldMapping c s = Yield (toLower c) (CC s '\\0' '\\0')"
4242 nice c = "-- " ++ name c ++ "\n" ++
4343 "foldMapping " ++ showC (code c) ++ " s = Yield " ++ x ++ " (CC s " ++ y ++ " " ++ z ++ ")"
scripts/CaseMapping.hs+3−3
@@ -8,7 +8,7 @@ import SpecialCasing
88main = do
99 args <- getArgs
1010 let oname = case args of
11− [] -> "../Data/Text/Internal/Fusion/CaseMapping.hs"
11+ [] -> "../Data/Text/Fusion/CaseMapping.hs"
1212 [o] -> o
1313 psc <- parseSC "SpecialCasing.txt"
1414 pcf <- parseCF "CaseFolding.txt"
@@ -24,10 +24,10 @@ main = do
2424 mapM_ (hPutStrLn h) $
2525 ["{-# LANGUAGE Rank2Types #-}"
2626 ,"-- AUTOMATICALLY GENERATED - DO NOT EDIT"
27− ,"-- Generated by scripts/CaseMapping.hs"] ++
27+ ,"-- Generated by scripts/SpecialCasing.hs"] ++
2828 comments ++
2929 [""
30− ,"module Data.Text.Internal.Fusion.CaseMapping where"
30+ ,"module Data.Text.Fusion.CaseMapping where"
3131 ,"import Data.Char"
3232 ,"import Data.Text.Internal.Fusion.Types"
3333 ,""]
scripts/SpecialCasing.hs+1−1
@@ -43,7 +43,7 @@ mapSC which access twiddle (SC _ ms) =
4343 typ ++ (map nice . filter p $ ms) ++ [last]
4444 where
4545 typ = [which ++ "Mapping :: forall s. Char -> s -> Step (CC s) Char"
46− ,"{-# NOINLINE " ++ which ++ "Mapping #-}"]
46+ ,"{-# INLINE " ++ which ++ "Mapping #-}"]
4747 last = which ++ "Mapping c s = Yield (to" ++ ucFirst which ++ " c) (CC s '\\0' '\\0')"
4848 nice c = "-- " ++ name c ++ "\n" ++
4949 which ++ "Mapping " ++ showC (code c) ++ " s = Yield " ++ x ++ " (CC s " ++ y ++ " " ++ z ++ ")"
tests/LiteralRuleTest.hsdeleted−21
@@ -1,21 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−
3−module LiteralRuleTest where
4−
5−import Data.Text (Text)
6−
7−-- This should produce 8 firings of the "TEXT literal" rule
8−strings :: [Text]
9−strings = [ "abstime", "aclitem", "bit", "bool", "box", "bpchar", "bytea", "char" ]
10−
11−-- This should produce 7 firings of the "TEXT literal UTF8" rule
12−utf8Strings :: [Text]
13−utf8Strings = [ "\0abstime", "\0aclitem", "\xfefe bit", "\0bool", "\0box", "\0bpchar", "\0bytea" ]
14−
15−-- This should produce 4 firings of the "TEXT empty literal" rule
16−empties :: [Text]
17−empties = [ "", "", "", "" ]
18−
19−-- This should produce 5 firings of the "TEXT empty literal" rule
20−--singletons :: [Text]
21−--singletons = [ "a", "b", "c", "d", "e" ]
tests/Makefile+1−6
@@ -1,10 +1,5 @@
11count = 1000
22
3−all: coverage literal-rule-test
4−
5−literal-rule-test:
6− ./literal-rule-test.sh
7−
83coverage: build coverage/hpc_index.html
94
105build: text-test-data
@@ -37,4 +32,4 @@ coverage/hpc_index.html: coverage/coverage.tix
3732clean:
3833 rm -rf dist coverage .hpc
3934
40−.PHONY: build coverage all literal-rule-test
35+.PHONY: build coverage
tests/Tests/Properties.hs+48−136
@@ -1,8 +1,9 @@
1−-- | QuickCheck properties for the text library.
2−
1+-- | General quicktest properties for the text library
2+--
33{-# LANGUAGE BangPatterns, FlexibleInstances, OverloadedStrings,
44 ScopedTypeVariables, TypeSynonymInstances #-}
5−{-# OPTIONS_GHC -fno-enable-rewrite-rules -fno-warn-missing-signatures #-}
5+{-# OPTIONS_GHC -fno-enable-rewrite-rules #-}
6+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
67module Tests.Properties
78 (
89 tests
@@ -14,7 +15,7 @@ import Data.Bits ((.&.))
1415import Data.Char (chr, isDigit, isHexDigit, isLower, isSpace, isUpper, ord)
1516import Data.Int (Int8, Int16, Int32, Int64)
1617import Data.Monoid (Monoid(..))
17−import Data.String (IsString(fromString))
18+import Data.String (fromString)
1819import Data.Text.Encoding.Error
1920import Data.Text.Foreign
2021import Data.Text.Internal.Encoding.Utf8
@@ -23,13 +24,12 @@ import Data.Text.Internal.Search (indices)
2324import Data.Text.Lazy.Read as TL
2425import Data.Text.Read as T
2526import Data.Word (Word, Word8, Word16, Word32, Word64)
26−import Numeric (showEFloat, showFFloat, showGFloat, showHex)
27+import Numeric (showHex)
2728import Prelude hiding (replicate)
2829import Test.Framework (Test, testGroup)
2930import Test.Framework.Providers.QuickCheck2 (testProperty)
3031import Test.QuickCheck hiding ((.&.))
3132import Test.QuickCheck.Monadic
32−import Test.QuickCheck.Property (Property(..))
3333import Tests.QuickCheckUtils
3434import Tests.Utils
3535import Text.Show.Functions ()
@@ -53,7 +53,6 @@ import qualified Data.Text.Lazy.Builder.RealFloat as TB
5353import qualified Data.Text.Lazy.Encoding as EL
5454import qualified Data.Text.Lazy.IO as TL
5555import qualified System.IO as IO
56−import qualified Tests.Properties.Mul as Mul
5756import qualified Tests.SlowFunctions as Slow
5857
5958t_pack_unpack = (T.unpack . T.pack) `eq` id
@@ -95,7 +94,9 @@ tl_utf32LE = forAll genUnicode $ (EL.decodeUtf32LE . EL.encodeUtf32LE) `eq` id
9594t_utf32BE = forAll genUnicode $ (E.decodeUtf32BE . E.encodeUtf32BE) `eq` id
9695tl_utf32BE = forAll genUnicode $ (EL.decodeUtf32BE . EL.encodeUtf32BE) `eq` id
9796
98−t_utf8_incr = forAll genUnicode $ \s (Positive n) -> (recode n `eq` id) s
97+t_utf8_incr = do
98+ Positive n <- arbitrary
99+ forAll genUnicode $ recode n `eq` id
99100 where recode n = T.concat . map fst . feedChunksOf n E.streamDecodeUtf8 .
100101 E.encodeUtf8
101102
@@ -126,9 +127,9 @@ t_utf8_err bad de = do
126127 Leading -> B.append <$> genInvalidUTF8 <*> genUTF8
127128 Trailing -> B.append <$> genUTF8 <*> genInvalidUTF8
128129 genUTF8 = E.encodeUtf8 <$> genUnicode
129− forAll gen $ \bs -> MkProperty $ do
130+ forAll gen $ \bs -> do
130131 onErr <- genDecodeErr de
131− unProperty . monadicIO $ do
132+ monadicIO $ do
132133 l <- run $ let len = T.length (E.decodeUtf8With onErr bs)
133134 in (len `seq` return (Right len)) `Exception.catch`
134135 (\(e::UnicodeException) -> return (Left e))
@@ -197,10 +198,8 @@ t_Show = show `eq` (show . T.pack)
197198tl_Show = show `eq` (show . TL.pack)
198199t_mappend s = mappend s`eqP` (unpackS . mappend (T.pack s))
199200tl_mappend s = mappend s`eqP` (unpackS . mappend (TL.pack s))
200−t_mconcat = unsquare $
201− mconcat `eq` (unpackS . mconcat . L.map T.pack)
202−tl_mconcat = unsquare $
203− mconcat `eq` (unpackS . mconcat . L.map TL.pack)
201+t_mconcat = mconcat `eq` (unpackS . mconcat . L.map T.pack)
202+tl_mconcat = mconcat `eq` (unpackS . mconcat . L.map TL.pack)
204203t_mempty = mempty == (unpackS (mempty :: T.Text))
205204tl_mempty = mempty == (unpackS (mempty :: TL.Text))
206205t_IsString = fromString `eqP` (T.unpack . fromString)
@@ -264,14 +263,11 @@ s_map_s f = map f `eqP` (unpackS . S.unstream . S.map f)
264263sf_map p f = (map f . L.filter p) `eqP` (unpackS . S.map f . S.filter p)
265264t_map f = map f `eqP` (unpackS . T.map f)
266265tl_map f = map f `eqP` (unpackS . TL.map f)
267−s_intercalate c = unsquare $
268− L.intercalate c `eq`
266+s_intercalate c = L.intercalate c `eq`
269267 (unpackS . S.intercalate (packS c) . map packS)
270−t_intercalate c = unsquare $
271− L.intercalate c `eq`
268+t_intercalate c = L.intercalate c `eq`
272269 (unpackS . T.intercalate (packS c) . map packS)
273−tl_intercalate c = unsquare $
274− L.intercalate c `eq`
270+tl_intercalate c = L.intercalate c `eq`
275271 (unpackS . TL.intercalate (TL.pack c) . map TL.pack)
276272s_intersperse c = L.intersperse c `eqP`
277273 (unpackS . S.intersperse c)
@@ -279,14 +275,10 @@ s_intersperse_s c = L.intersperse c `eqP`
279275 (unpackS . S.unstream . S.intersperse c)
280276sf_intersperse p c= (L.intersperse c . L.filter p) `eqP`
281277 (unpackS . S.intersperse c . S.filter p)
282−t_intersperse c = unsquare $
283− L.intersperse c `eqP` (unpackS . T.intersperse c)
284−tl_intersperse c = unsquare $
285− L.intersperse c `eqP` (unpackS . TL.intersperse c)
286−t_transpose = unsquare $
287− L.transpose `eq` (map unpackS . T.transpose . map packS)
288−tl_transpose = unsquare $
289− L.transpose `eq` (map unpackS . TL.transpose . map TL.pack)
278+t_intersperse c = L.intersperse c `eqP` (unpackS . T.intersperse c)
279+tl_intersperse c = L.intersperse c `eqP` (unpackS . TL.intersperse c)
280+t_transpose = L.transpose `eq` (map unpackS . T.transpose . map packS)
281+tl_transpose = L.transpose `eq` (map unpackS . TL.transpose . map TL.pack)
290282t_reverse = L.reverse `eqP` (unpackS . T.reverse)
291283tl_reverse = L.reverse `eqP` (unpackS . TL.reverse)
292284t_reverse_short n = L.reverse `eqP` (unpackS . S.reverse . shorten n . S.stream)
@@ -383,24 +375,17 @@ sf_foldr p f z = (L.foldr f z . L.filter p) `eqP` (S.foldr f z . S.filter p)
383375 where _types = f :: Char -> Char -> Char
384376t_foldr f z = L.foldr f z `eqP` T.foldr f z
385377 where _types = f :: Char -> Char -> Char
386−tl_foldr f z = unsquare $
387− L.foldr f z `eqP` TL.foldr f z
378+tl_foldr f z = L.foldr f z `eqP` TL.foldr f z
388379 where _types = f :: Char -> Char -> Char
389−sf_foldr1 p f = unsquare $
390− (L.foldr1 f . L.filter p) `eqP` (S.foldr1 f . S.filter p)
380+sf_foldr1 p f = (L.foldr1 f . L.filter p) `eqP` (S.foldr1 f . S.filter p)
391381t_foldr1 f = L.foldr1 f `eqP` T.foldr1 f
392−tl_foldr1 f = unsquare $
393− L.foldr1 f `eqP` TL.foldr1 f
382+tl_foldr1 f = L.foldr1 f `eqP` TL.foldr1 f
394383
395−s_concat_s = unsquare $
396− L.concat `eq` (unpackS . S.unstream . S.concat . map packS)
397−sf_concat p = unsquare $
398− (L.concat . map (L.filter p)) `eq`
384+s_concat_s = L.concat `eq` (unpackS . S.unstream . S.concat . map packS)
385+sf_concat p = (L.concat . map (L.filter p)) `eq`
399386 (unpackS . S.concat . map (S.filter p . packS))
400−t_concat = unsquare $
401− L.concat `eq` (unpackS . T.concat . map packS)
402−tl_concat = unsquare $
403− L.concat `eq` (unpackS . TL.concat . map TL.pack)
387+t_concat = L.concat `eq` (unpackS . T.concat . map packS)
388+tl_concat = L.concat `eq` (unpackS . TL.concat . map TL.pack)
404389sf_concatMap p f = unsquare $ (L.concatMap f . L.filter p) `eqP`
405390 (unpackS . S.concatMap (packS . f) . S.filter p)
406391t_concatMap f = unsquare $
@@ -440,10 +425,6 @@ t_mapAccumR f z = L.mapAccumR f z `eqP` (second unpackS . T.mapAccumR f z)
440425tl_mapAccumR f z = L.mapAccumR f z `eqP` (second unpackS . TL.mapAccumR f z)
441426 where _types = f :: Int -> Char -> (Int,Char)
442427
443−tl_repeat n = (L.take m . L.repeat) `eq`
444− (unpackS . TL.take (fromIntegral m) . TL.repeat)
445− where m = fromIntegral (n :: Word8)
446−
447428replicate n l = concat (L.replicate n l)
448429
449430s_replicate n = replicate m `eq`
@@ -455,14 +436,6 @@ tl_replicate n = replicate m `eq`
455436 (unpackS . TL.replicate (fromIntegral m) . packS)
456437 where m = fromIntegral (n :: Word8)
457438
458−tl_cycle n = (L.take m . L.cycle) `eq`
459− (unpackS . TL.take (fromIntegral m) . TL.cycle . packS)
460− where m = fromIntegral (n :: Word8)
461−
462−tl_iterate f n = (L.take m . L.iterate f) `eq`
463− (unpackS . TL.take (fromIntegral m) . TL.iterate f)
464− where m = fromIntegral (n :: Word8)
465−
466439unf :: Int -> Char -> Maybe (Char, Char)
467440unf n c | fromEnum c * 100 > n = Nothing
468441 | otherwise = Just (c, succ c)
@@ -489,22 +462,14 @@ s_take_s m = L.take n `eqP` (unpackS . S.unstream . S.take n)
489462sf_take p n = (L.take n . L.filter p) `eqP`
490463 (unpackS . S.take n . S.filter p)
491464t_take n = L.take n `eqP` (unpackS . T.take n)
492−t_takeEnd n = (L.reverse . L.take n . L.reverse) `eqP`
493− (unpackS . T.takeEnd n)
494465tl_take n = L.take n `eqP` (unpackS . TL.take (fromIntegral n))
495−tl_takeEnd n = (L.reverse . L.take (fromIntegral n) . L.reverse) `eqP`
496− (unpackS . TL.takeEnd n)
497466s_drop n = L.drop n `eqP` (unpackS . S.drop n)
498467s_drop_s m = L.drop n `eqP` (unpackS . S.unstream . S.drop n)
499468 where n = small m
500469sf_drop p n = (L.drop n . L.filter p) `eqP`
501470 (unpackS . S.drop n . S.filter p)
502471t_drop n = L.drop n `eqP` (unpackS . T.drop n)
503−t_dropEnd n = (L.reverse . L.drop n . L.reverse) `eqP`
504− (unpackS . T.dropEnd n)
505472tl_drop n = L.drop n `eqP` (unpackS . TL.drop (fromIntegral n))
506−tl_dropEnd n = (L.reverse . L.drop n . L.reverse) `eqP`
507− (unpackS . TL.dropEnd (fromIntegral n))
508473s_take_drop m = (L.take n . L.drop n) `eqP` (unpackS . S.take n . S.drop n)
509474 where n = small m
510475s_take_drop_s m = (L.take n . L.drop n) `eqP`
@@ -516,10 +481,6 @@ sf_takeWhile q p = (L.takeWhile p . L.filter q) `eqP`
516481 (unpackS . S.takeWhile p . S.filter q)
517482t_takeWhile p = L.takeWhile p `eqP` (unpackS . T.takeWhile p)
518483tl_takeWhile p = L.takeWhile p `eqP` (unpackS . TL.takeWhile p)
519−t_takeWhileEnd p = (L.reverse . L.takeWhile p . L.reverse) `eqP`
520− (unpackS . T.takeWhileEnd p)
521−tl_takeWhileEnd p = (L.reverse . L.takeWhile p . L.reverse) `eqP`
522− (unpackS . TL.takeWhileEnd p)
523484s_dropWhile p = L.dropWhile p `eqP` (unpackS . S.dropWhile p)
524485s_dropWhile_s p = L.dropWhile p `eqP` (unpackS . S.unstream . S.dropWhile p)
525486sf_dropWhile q p = (L.dropWhile p . L.filter q) `eqP`
@@ -572,27 +533,24 @@ tl_groupBy p = L.groupBy p `eqP` (map unpackS . TL.groupBy p)
572533t_inits = L.inits `eqP` (map unpackS . T.inits)
573534tl_inits = L.inits `eqP` (map unpackS . TL.inits)
574535t_tails = L.tails `eqP` (map unpackS . T.tails)
575−tl_tails = unsquare $
576− L.tails `eqP` (map unpackS . TL.tails)
577−t_findAppendId = unsquare $ \(NotEmpty s) ts ->
536+tl_tails = L.tails `eqP` (map unpackS . TL.tails)
537+t_findAppendId (NotEmpty s) = unsquare $ \ts ->
578538 let t = T.intercalate s ts
579539 in all (==t) $ map (uncurry T.append) (T.breakOnAll s t)
580−tl_findAppendId = unsquare $ \(NotEmpty s) ts ->
540+tl_findAppendId (NotEmpty s) = unsquare $ \ts ->
581541 let t = TL.intercalate s ts
582542 in all (==t) $ map (uncurry TL.append) (TL.breakOnAll s t)
583−t_findContains = unsquare $ \(NotEmpty s) ->
584− all (T.isPrefixOf s . snd) . T.breakOnAll s . T.intercalate s
585−tl_findContains = unsquare $ \(NotEmpty s) -> all (TL.isPrefixOf s . snd) .
543+t_findContains (NotEmpty s) = all (T.isPrefixOf s . snd) . T.breakOnAll s .
544+ T.intercalate s
545+tl_findContains (NotEmpty s) = all (TL.isPrefixOf s . snd) .
586546 TL.breakOnAll s . TL.intercalate s
587547sl_filterCount c = (L.genericLength . L.filter (==c)) `eqP` SL.countChar c
588548t_findCount s = (L.length . T.breakOnAll s) `eq` T.count s
589549tl_findCount s = (L.genericLength . TL.breakOnAll s) `eq` TL.count s
590550
591−t_splitOn_split s = unsquare $
592− (T.splitOn s `eq` Slow.splitOn s) . T.intercalate s
593−tl_splitOn_split s = unsquare $
594− ((TL.splitOn (TL.fromStrict s) . TL.fromStrict) `eq`
595− (map TL.fromStrict . T.splitOn s)) . T.intercalate s
551+t_splitOn_split s = (T.splitOn s `eq` Slow.splitOn s) . T.intercalate s
552+tl_splitOn_split s = ((TL.splitOn (TL.fromStrict s) . TL.fromStrict) `eq`
553+ (map TL.fromStrict . T.splitOn s)) . T.intercalate s
596554t_splitOn_i (NotEmpty t) = id `eq` (T.intercalate t . T.splitOn t)
597555tl_splitOn_i (NotEmpty t) = id `eq` (TL.intercalate t . TL.splitOn t)
598556
@@ -634,14 +592,10 @@ t_lines' = lines' `eqP` (map unpackS . T.lines')
634592t_words = L.words `eqP` (map unpackS . T.words)
635593
636594tl_words = L.words `eqP` (map unpackS . TL.words)
637−t_unlines = unsquare $
638− L.unlines `eq` (unpackS . T.unlines . map packS)
639−tl_unlines = unsquare $
640− L.unlines `eq` (unpackS . TL.unlines . map packS)
641−t_unwords = unsquare $
642− L.unwords `eq` (unpackS . T.unwords . map packS)
643−tl_unwords = unsquare $
644− L.unwords `eq` (unpackS . TL.unwords . map packS)
595+t_unlines = L.unlines `eq` (unpackS . T.unlines . map packS)
596+tl_unlines = L.unlines `eq` (unpackS . TL.unlines . map packS)
597+t_unwords = L.unwords `eq` (unpackS . T.unwords . map packS)
598+tl_unwords = L.unwords `eq` (unpackS . TL.unwords . map packS)
645599
646600s_isPrefixOf s = L.isPrefixOf s `eqP`
647601 (S.isPrefixOf (S.stream $ packS s) . S.stream)
@@ -718,9 +672,8 @@ t_indices (NotEmpty s) = Slow.indices s `eq` indices s
718672tl_indices (NotEmpty s) = lazyIndices s `eq` S.indices s
719673 where lazyIndices ss t = map fromIntegral $ Slow.indices (conc ss) (conc t)
720674 conc = T.concat . TL.toChunks
721−t_indices_occurs = unsquare $ \(NotEmpty t) ts ->
722− let s = T.intercalate t ts
723− in Slow.indices t s == indices t s
675+t_indices_occurs (NotEmpty t) ts = let s = T.intercalate t ts
676+ in Slow.indices t s == indices t s
724677
725678-- Bit shifts.
726679shiftL w = forAll (choose (0,width-1)) $ \k -> Bits.shiftL w k == U.shiftL w k
@@ -756,7 +709,6 @@ tb_decimal :: (Integral a, Show a) => a -> Bool
756709tb_decimal = (TB.toLazyText . TB.decimal) `eq` (TL.pack . show)
757710
758711tb_decimal_integer (a::Integer) = tb_decimal a
759−tb_decimal_integer_big (Big a) = tb_decimal a
760712tb_decimal_int (a::Int) = tb_decimal a
761713tb_decimal_int8 (a::Int8) = tb_decimal a
762714tb_decimal_int16 (a::Int16) = tb_decimal a
@@ -768,11 +720,6 @@ tb_decimal_word16 (a::Word16) = tb_decimal a
768720tb_decimal_word32 (a::Word32) = tb_decimal a
769721tb_decimal_word64 (a::Word64) = tb_decimal a
770722
771−tb_decimal_big_int (BigBounded (a::Int)) = tb_decimal a
772−tb_decimal_big_int64 (BigBounded (a::Int64)) = tb_decimal a
773−tb_decimal_big_word (BigBounded (a::Word)) = tb_decimal a
774−tb_decimal_big_word64 (BigBounded (a::Word64)) = tb_decimal a
775−
776723tb_hex :: (Integral a, Show a) => a -> Bool
777724tb_hex = (TB.toLazyText . TB.hexadecimal) `eq` (TL.pack . flip showHex "")
778725
@@ -794,21 +741,6 @@ tb_realfloat = (TB.toLazyText . TB.realFloat) `eq` (TL.pack . show)
794741tb_realfloat_float (a::Float) = tb_realfloat a
795742tb_realfloat_double (a::Double) = tb_realfloat a
796743
797−showFloat :: (RealFloat a) => TB.FPFormat -> Maybe Int -> a -> ShowS
798−showFloat TB.Exponent = showEFloat
799−showFloat TB.Fixed = showFFloat
800−showFloat TB.Generic = showGFloat
801−
802−tb_formatRealFloat :: (RealFloat a, Show a) =>
803− a -> TB.FPFormat -> Precision a -> Property
804−tb_formatRealFloat a fmt prec =
805− TB.formatRealFloat fmt p a ===
806− TB.fromString (showFloat fmt p a "")
807− where p = precision a prec
808−
809−tb_formatRealFloat_float (a::Float) = tb_formatRealFloat a
810−tb_formatRealFloat_double (a::Double) = tb_formatRealFloat a
811−
812744-- Reading.
813745
814746t_decimal (n::Int) s =
@@ -817,18 +749,16 @@ t_decimal (n::Int) s =
817749tl_decimal (n::Int) s =
818750 TL.signed TL.decimal (TL.pack (show n) `TL.append` t) == Right (n,t)
819751 where t = TL.dropWhile isDigit s
820−t_hexadecimal m s ox =
752+t_hexadecimal (n::Positive Int) s ox =
821753 T.hexadecimal (T.concat [p, T.pack (showHex n ""), t]) == Right (n,t)
822754 where t = T.dropWhile isHexDigit s
823755 p = if ox then "0x" else ""
824− n = getPositive m :: Int
825−tl_hexadecimal m s ox =
756+tl_hexadecimal (n::Positive Int) s ox =
826757 TL.hexadecimal (TL.concat [p, TL.pack (showHex n ""), t]) == Right (n,t)
827758 where t = TL.dropWhile isHexDigit s
828759 p = if ox then "0x" else ""
829− n = getPositive m :: Int
830760
831−isFloaty c = c `elem` ("+-.0123456789eE" :: String)
761+isFloaty c = c `elem` "+-.0123456789eE"
832762
833763t_read_rational p tol (n::Double) s =
834764 case p (T.pack (show n) `T.append` t) of
@@ -1110,12 +1040,9 @@ tests =
11101040 ],
11111041
11121042 testGroup "unfolds" [
1113− testProperty "tl_repeat" tl_repeat,
11141043 testProperty "s_replicate" s_replicate,
11151044 testProperty "t_replicate" t_replicate,
11161045 testProperty "tl_replicate" tl_replicate,
1117− testProperty "tl_cycle" tl_cycle,
1118− testProperty "tl_iterate" tl_iterate,
11191046 testProperty "t_unfoldr" t_unfoldr,
11201047 testProperty "tl_unfoldr" tl_unfoldr,
11211048 testProperty "t_unfoldrN" t_unfoldrN,
@@ -1129,16 +1056,12 @@ tests =
11291056 testProperty "s_take_s" s_take_s,
11301057 testProperty "sf_take" sf_take,
11311058 testProperty "t_take" t_take,
1132− testProperty "t_takeEnd" t_takeEnd,
11331059 testProperty "tl_take" tl_take,
1134− testProperty "tl_takeEnd" tl_takeEnd,
11351060 testProperty "s_drop" s_drop,
11361061 testProperty "s_drop_s" s_drop_s,
11371062 testProperty "sf_drop" sf_drop,
11381063 testProperty "t_drop" t_drop,
1139− testProperty "t_dropEnd" t_dropEnd,
11401064 testProperty "tl_drop" tl_drop,
1141− testProperty "tl_dropEnd" tl_dropEnd,
11421065 testProperty "s_take_drop" s_take_drop,
11431066 testProperty "s_take_drop_s" s_take_drop_s,
11441067 testProperty "s_takeWhile" s_takeWhile,
@@ -1146,8 +1069,6 @@ tests =
11461069 testProperty "sf_takeWhile" sf_takeWhile,
11471070 testProperty "t_takeWhile" t_takeWhile,
11481071 testProperty "tl_takeWhile" tl_takeWhile,
1149− testProperty "t_takeWhileEnd" t_takeWhileEnd,
1150− testProperty "tl_takeWhileEnd" tl_takeWhileEnd,
11511072 testProperty "sf_dropWhile" sf_dropWhile,
11521073 testProperty "s_dropWhile" s_dropWhile,
11531074 testProperty "s_dropWhile_s" s_dropWhile_s,
@@ -1293,16 +1214,11 @@ tests =
12931214 testProperty "tb_decimal_int32" tb_decimal_int32,
12941215 testProperty "tb_decimal_int64" tb_decimal_int64,
12951216 testProperty "tb_decimal_integer" tb_decimal_integer,
1296− testProperty "tb_decimal_integer_big" tb_decimal_integer_big,
12971217 testProperty "tb_decimal_word" tb_decimal_word,
12981218 testProperty "tb_decimal_word8" tb_decimal_word8,
12991219 testProperty "tb_decimal_word16" tb_decimal_word16,
13001220 testProperty "tb_decimal_word32" tb_decimal_word32,
1301− testProperty "tb_decimal_word64" tb_decimal_word64,
1302− testProperty "tb_decimal_big_int" tb_decimal_big_int,
1303− testProperty "tb_decimal_big_word" tb_decimal_big_word,
1304− testProperty "tb_decimal_big_int64" tb_decimal_big_int64,
1305− testProperty "tb_decimal_big_word64" tb_decimal_big_word64
1221+ testProperty "tb_decimal_word64" tb_decimal_word64
13061222 ],
13071223 testGroup "hexadecimal" [
13081224 testProperty "tb_hexadecimal_int" tb_hexadecimal_int,
@@ -1319,9 +1235,7 @@ tests =
13191235 ],
13201236 testGroup "realfloat" [
13211237 testProperty "tb_realfloat_double" tb_realfloat_double,
1322− testProperty "tb_realfloat_float" tb_realfloat_float,
1323− testProperty "tb_formatRealFloat_float" tb_formatRealFloat_float,
1324− testProperty "tb_formatRealFloat_double" tb_formatRealFloat_double
1238+ testProperty "tb_realfloat_float" tb_realfloat_float
13251239 ],
13261240 testProperty "tb_fromText" tb_fromText,
13271241 testProperty "tb_singleton" tb_singleton
@@ -1357,7 +1271,5 @@ tests =
13571271 testProperty "t_take_drop_16" t_take_drop_16,
13581272 testProperty "t_use_from" t_use_from,
13591273 testProperty "t_copy" t_copy
1360− ],
1361−
1362− testGroup "mul" Mul.tests
1274+ ]
13631275 ]
tests/Tests/Properties/Mul.hsdeleted−40
@@ -1,40 +0,0 @@
1−{-# LANGUAGE ScopedTypeVariables #-}
2−
3−module Tests.Properties.Mul (tests) where
4−
5−import Control.Applicative ((<$>), pure)
6−import Control.Exception as E (SomeException, catch, evaluate)
7−import Data.Int (Int32, Int64)
8−import Data.Text.Internal (mul, mul32, mul64)
9−import System.IO.Unsafe (unsafePerformIO)
10−import Test.Framework (Test)
11−import Test.Framework.Providers.QuickCheck2 (testProperty)
12−import Test.QuickCheck hiding ((.&.))
13−
14−mulRef :: (Integral a, Bounded a) => a -> a -> Maybe a
15−mulRef a b
16− | ab < bot || ab > top = Nothing
17− | otherwise = Just (fromIntegral ab)
18− where ab = fromIntegral a * fromIntegral b
19− top = fromIntegral (maxBound `asTypeOf` a) :: Integer
20− bot = fromIntegral (minBound `asTypeOf` a) :: Integer
21−
22−eval :: (a -> b -> c) -> a -> b -> Maybe c
23−eval f a b = unsafePerformIO $
24− (Just <$> evaluate (f a b)) `E.catch` (\(_::SomeException) -> pure Nothing)
25−
26−t_mul32 :: Int32 -> Int32 -> Property
27−t_mul32 a b = mulRef a b === eval mul32 a b
28−
29−t_mul64 :: Int64 -> Int64 -> Property
30−t_mul64 a b = mulRef a b === eval mul64 a b
31−
32−t_mul :: Int -> Int -> Property
33−t_mul a b = mulRef a b === eval mul a b
34−
35−tests :: [Test]
36−tests = [
37− testProperty "t_mul" t_mul
38− , testProperty "t_mul32" t_mul32
39− , testProperty "t_mul64" t_mul64
40− ]
tests/Tests/QuickCheckUtils.hs+82−73
@@ -7,46 +7,48 @@
77module Tests.QuickCheckUtils
88 (
99 genUnicode
10+ , genUnicodeWith
11+ , ascii
12+ , plane0
13+ , plane1
14+ , plane2
15+ , plane14
16+ , planes
17+
1018 , unsquare
1119 , smallArbitrary
1220
13− , BigBounded(..)
14− , BigInt(..)
15− , NotEmpty(..)
21+ , NotEmpty (..)
1622
17− , Small(..)
23+ , Small (..)
1824 , small
1925
20− , Precision(..)
21− , precision
22−
2326 , integralRandomR
2427
25− , DecodeErr(..)
28+ , DecodeErr (..)
2629 , genDecodeErr
2730
28− , Stringy(..)
31+ , Stringy (..)
2932 , eq
3033 , eqP
3134
32− , Encoding(..)
35+ , Encoding (..)
3336
3437 , write_read
3538 ) where
3639
37−import Control.Applicative ((<$>))
3840import Control.Arrow (first, (***))
3941import Control.DeepSeq (NFData (..), deepseq)
4042import Control.Exception (bracket)
43+import Data.Bits ((.&.))
44+import Data.Char (chr)
4145import Data.String (IsString, fromString)
4246import Data.Text.Foreign (I16)
43−import Data.Text.Lazy.Builder.RealFloat (FPFormat(..))
4447import Data.Word (Word8, Word16)
4548import Debug.Trace (trace)
46−import System.Random (Random(..), RandomGen)
47−import Test.QuickCheck hiding (Fixed(..), Small (..), (.&.))
49+import System.Random (Random (..), RandomGen)
50+import Test.QuickCheck hiding ((.&.))
4851import Test.QuickCheck.Monadic (assert, monadicIO, run)
49−import Test.QuickCheck.Unicode (string)
5052import Tests.Utils
5153import qualified Data.ByteString as B
5254import qualified Data.Text as T
@@ -58,14 +60,6 @@ import qualified Data.Text.Internal.Lazy.Fusion as TLF
5860import qualified Data.Text.Lazy as TL
5961import qualified System.IO as IO
6062
61−#if !MIN_VERSION_base(4,4,0)
62−import Data.Int (Int64)
63−import Data.Word (Word, Word64)
64−#endif
65−
66−genUnicode :: IsString a => Gen a
67−genUnicode = fromString <$> string
68−
6963instance Random I16 where
7064 randomR = integralRandomR
7165 random = randomR (minBound,maxBound)
@@ -79,23 +73,76 @@ instance Arbitrary B.ByteString where
7973 shrink = map B.pack . shrink . B.unpack
8074
8175#if !MIN_VERSION_base(4,4,0)
82−instance Random Int64 where
83− randomR = integralRandomR
84− random = randomR (minBound,maxBound)
85−
86−instance Random Word where
87− randomR = integralRandomR
88− random = randomR (minBound,maxBound)
89−
9076instance Random Word8 where
9177 randomR = integralRandomR
9278 random = randomR (minBound,maxBound)
93−
94−instance Random Word64 where
95− randomR = integralRandomR
96− random = randomR (minBound,maxBound)
9779#endif
9880
81+genUnicode :: IsString a => Gen a
82+genUnicode = genUnicodeWith planes
83+
84+genUnicodeWith :: IsString a => [Gen Int] -> Gen a
85+genUnicodeWith gens = fmap fromString string
86+ where
87+ string = sized $ \n ->
88+ do k <- choose (0,n)
89+ sequence [ char | _ <- [1..k] ]
90+
91+ excluding :: [a -> Bool] -> Gen a -> Gen a
92+ excluding bad gen = loop
93+ where
94+ loop = do
95+ x <- gen
96+ if or (map ($ x) bad)
97+ then loop
98+ else return x
99+
100+ reserved = [lowSurrogate, highSurrogate, noncharacter]
101+ lowSurrogate c = c >= 0xDC00 && c <= 0xDFFF
102+ highSurrogate c = c >= 0xD800 && c <= 0xDBFF
103+ noncharacter c = masked == 0xFFFE || masked == 0xFFFF
104+ where
105+ masked = c .&. 0xFFFF
106+
107+ char = chr `fmap` excluding reserved (oneof gens)
108+
109+ascii :: Gen Int
110+ascii = choose (0,0x7F)
111+
112+plane0 :: Gen Int
113+plane0 = choose (0xF0, 0xFFFF)
114+
115+plane1 :: Gen Int
116+plane1 = oneof [ choose (0x10000, 0x10FFF)
117+ , choose (0x11000, 0x11FFF)
118+ , choose (0x12000, 0x12FFF)
119+ , choose (0x13000, 0x13FFF)
120+ , choose (0x1D000, 0x1DFFF)
121+ , choose (0x1F000, 0x1FFFF)
122+ ]
123+
124+plane2 :: Gen Int
125+plane2 = oneof [ choose (0x20000, 0x20FFF)
126+ , choose (0x21000, 0x21FFF)
127+ , choose (0x22000, 0x22FFF)
128+ , choose (0x23000, 0x23FFF)
129+ , choose (0x24000, 0x24FFF)
130+ , choose (0x25000, 0x25FFF)
131+ , choose (0x26000, 0x26FFF)
132+ , choose (0x27000, 0x27FFF)
133+ , choose (0x28000, 0x28FFF)
134+ , choose (0x29000, 0x29FFF)
135+ , choose (0x2A000, 0x2AFFF)
136+ , choose (0x2B000, 0x2BFFF)
137+ , choose (0x2F000, 0x2FFFF)
138+ ]
139+
140+plane14 :: Gen Int
141+plane14 = choose (0xE0000, 0xE0FFF)
142+
143+planes :: [Gen Int]
144+planes = [ascii, plane0, plane1, plane2, plane14]
145+
99146-- For tests that have O(n^2) running times or input sizes, resize
100147-- their inputs to the square root of the originals.
101148unsquare :: (Arbitrary a, Show a, Testable b) => (a -> b) -> Property
@@ -113,20 +160,6 @@ instance Arbitrary TL.Text where
113160 arbitrary = (TL.fromChunks . map notEmpty) `fmap` smallArbitrary
114161 shrink = map TL.pack . shrink . TL.unpack
115162
116−newtype BigInt = Big Integer
117− deriving (Eq, Show)
118−
119−instance Arbitrary BigInt where
120− arbitrary = choose (1::Int,200) >>= \e -> Big <$> choose (10^(e-1),10^e)
121− shrink (Big a) = [Big (a `div` 2^(l-e)) | e <- shrink l]
122− where l = truncate (log (fromIntegral a) / log 2 :: Double) :: Integer
123−
124−newtype BigBounded a = BigBounded a
125− deriving (Eq, Show)
126−
127−instance (Bounded a, Random a, Arbitrary a) => Arbitrary (BigBounded a) where
128− arbitrary = BigBounded <$> choose (minBound, maxBound)
129−
130163newtype NotEmpty a = NotEmpty { notEmpty :: a }
131164 deriving (Eq, Ord)
132165
@@ -267,30 +300,6 @@ eqP f g s w = eql "orig" (f s) (g t) &&
267300 | a =^= b = True
268301 | otherwise = trace (d ++ ": " ++ show a ++ " /= " ++ show b) False
269302
270−instance Arbitrary FPFormat where
271− arbitrary = elements [Exponent, Fixed, Generic]
272−
273−newtype Precision a = Precision (Maybe Int)
274− deriving (Eq, Show)
275−
276−precision :: a -> Precision a -> Maybe Int
277−precision _ (Precision prec) = prec
278−
279−arbitraryPrecision :: Int -> Gen (Precision a)
280−arbitraryPrecision maxDigits = Precision <$> do
281− n <- choose (-1,maxDigits)
282− return $ if n == -1
283− then Nothing
284− else Just n
285−
286−instance Arbitrary (Precision Float) where
287− arbitrary = arbitraryPrecision 11
288− shrink = map Precision . shrink . precision undefined
289−
290−instance Arbitrary (Precision Double) where
291− arbitrary = arbitraryPrecision 22
292− shrink = map Precision . shrink . precision undefined
293−
294303-- Work around lack of Show instance for TextEncoding.
295304data Encoding = E String IO.TextEncoding
296305
tests/cabal.configdeleted−6
@@ -1,6 +0,0 @@
1−-- These flags help to speed up building the test suite.
2−
3−documentation: False
4−executable-stripping: False
5−flags: developer
6−library-profiling: False
tests/literal-rule-test.shdeleted−29
@@ -1,29 +0,0 @@
1−#!/bin/bash -e
2−
3−failed=0
4−
5−function check_firings() {
6− rule=$1
7− expected=$2
8− build="ghc -O -ddump-rule-firings LiteralRuleTest.hs"
9− build="$build -i.. -I../include"
10− touch LiteralRuleTest.hs
11− echo -n "Want to see $expected firings of rule $rule... " >&2
12− firings=$($build 2>&1 | grep "Rule fired: $rule\$" | wc -l)
13− rm -f LiteralRuleTest.{o.hi}
14−
15− if [ $firings != $expected ]; then
16− echo "failed, saw $firings" >&2
17− failed=1
18− else
19− echo "pass" >&2
20− fi
21−}
22−
23−check_firings "TEXT literal" 8
24−check_firings "TEXT literal UTF8" 7
25−check_firings "TEXT empty literal" 4
26−# This is broken at the moment. "TEXT literal" rule fires instead.
27−#check_firings "TEXT singleton literal" 5
28−
29−exit $failed
tests/text-tests.cabal+3−18
@@ -2,8 +2,8 @@ name: text-tests
22version: 0.0.0.0
33synopsis: Functional tests for the text package
44description: Functional tests for the text package
5−homepage: https://github.com/bos/text
6−license: BSD2
5+homepage: https://bitbucket.org/bos/text
6+license: BSD3
77license-file: ../LICENSE
88author: Jasper Van der Jeugt <jaspervdj@gmail.com>,
99 Bryan O'Sullivan <bos@serpentine.com>,
@@ -18,20 +18,10 @@ cabal-version: >=1.8
1818flag hpc
1919 description: Enable HPC to generate coverage reports
2020 default: False
21− manual: True
2221
2322executable text-tests
2423 main-is: Tests.hs
2524
26− other-modules:
27− Tests.IO
28− Tests.Properties
29− Tests.Properties.Mul
30− Tests.QuickCheckUtils
31− Tests.Regressions
32− Tests.SlowFunctions
33− Tests.Utils
34−
3525 ghc-options:
3626 -Wall -threaded -O0 -rtsopts
3727
@@ -46,12 +36,11 @@ executable text-tests
4636
4737 build-depends:
4838 HUnit >= 1.2,
49− QuickCheck >= 2.7,
39+ QuickCheck >= 2.4,
5040 base == 4.*,
5141 bytestring,
5242 deepseq,
5343 directory,
54− quickcheck-unicode,
5544 random,
5645 test-framework >= 0.4,
5746 test-framework-hunit >= 0.2,
@@ -77,7 +66,6 @@ library
7766 hs-source-dirs: ..
7867 c-sources: ../cbits/cbits.c
7968 include-dirs: ../include
80− ghc-options: -Wall
8169 exposed-modules:
8270 Data.Text
8371 Data.Text.Array
@@ -114,8 +102,6 @@ library
114102 Data.Text.Internal.Lazy.Search
115103 Data.Text.Internal.Private
116104 Data.Text.Read
117− Data.Text.Show
118− Data.Text.Internal.Read
119105 Data.Text.Internal.Search
120106 Data.Text.Unsafe
121107 Data.Text.Internal.Unsafe
@@ -136,7 +122,6 @@ library
136122 build-depends:
137123 array,
138124 base == 4.*,
139− binary,
140125 bytestring,
141126 deepseq,
142127 ghc-prim,
text.cabal+8−29
@@ -1,5 +1,5 @@
11name: text
2−version: 1.2.2.1
2+version: 1.1.0.1
33homepage: https://github.com/bos/text
44bug-reports: https://github.com/bos/text/issues
55synopsis: An efficient packed Unicode text type.
@@ -31,7 +31,7 @@ description:
3131 the @text-icu@ package:
3232 <http://hackage.haskell.org/package/text-icu>
3333
34−license: BSD2
34+license: BSD3
3535license-file: LICENSE
3636author: Bryan O'Sullivan <bos@serpentine.com>
3737maintainer: Bryan O'Sullivan <bos@serpentine.com>
@@ -51,7 +51,7 @@ extra-source-files:
5151 benchmarks/python/*.py
5252 benchmarks/ruby/*.rb
5353 benchmarks/text-benchmarks.cabal
54− changelog.md
54+ changelog
5555 include/*.h
5656 scripts/*.hs
5757 tests-and-benchmarks.markdown
@@ -59,25 +59,16 @@ extra-source-files:
5959 tests/.ghci
6060 tests/Makefile
6161 tests/Tests/*.hs
62− tests/Tests/Properties/*.hs
63− tests/cabal.config
6462 tests/scripts/*.sh
6563 tests/text-tests.cabal
6664
67−flag bytestring-builder
68− description: Depend on the bytestring-builder package for backwards compatibility.
69− default: False
70− manual: False
71−
7265flag developer
7366 description: operate in developer mode
7467 default: False
75− manual: True
7668
7769flag integer-simple
7870 description: Use the simple integer library instead of GMP
7971 default: False
80− manual: False
8172
8273library
8374 c-sources: cbits/cbits.c
@@ -128,21 +119,16 @@ library
128119 Data.Text.Read
129120 Data.Text.Unsafe
130121
131− other-modules:
132− Data.Text.Show
133−
134122 build-depends:
135123 array >= 0.3,
136124 base >= 4.2 && < 5,
137− binary,
138125 deepseq >= 1.1.0.0,
139126 ghc-prim >= 0.2
140127
141− if flag(bytestring-builder)
142− build-depends: bytestring >= 0.9 && < 0.10.4,
143− bytestring-builder >= 0.10.4
128+ if impl(ghc >= 7.7)
129+ build-depends: bytestring >= 0.10.4.0
144130 else
145− build-depends: bytestring >= 0.10.4
131+ build-depends: bytestring >= 0.9
146132
147133 cpp-options: -DHAVE_DEEPSEQ
148134 ghc-options: -Wall -fwarn-tabs -funbox-strict-fields -O2
@@ -173,25 +159,18 @@ test-suite tests
173159
174160 build-depends:
175161 HUnit >= 1.2,
176− QuickCheck >= 2.7,
162+ QuickCheck >= 2.4,
177163 array,
178164 base,
179− binary,
165+ bytestring,
180166 deepseq,
181167 directory,
182168 ghc-prim,
183− quickcheck-unicode,
184169 random,
185170 test-framework >= 0.4,
186171 test-framework-hunit >= 0.2,
187172 test-framework-quickcheck2 >= 0.2
188173
189− if flag(bytestring-builder)
190− build-depends: bytestring >= 0.9 && < 0.10.4,
191− bytestring-builder >= 0.10.4
192− else
193− build-depends: bytestring >= 0.10.4
194−
195174 if flag(integer-simple)
196175 cpp-options: -DINTEGER_SIMPLE
197176 build-depends: integer-simple >= 0.1 && < 0.5