1{-# LANGUAGE BangPatterns, CPP, MagicHash, Rank2Types, UnboxedTuples #-}
2{-# OPTIONS_GHC -fno-warn-orphans #-}
3#if __GLASGOW_HASKELL__ >= 702
4{-# LANGUAGE Trustworthy #-}
6#if __GLASGOW_HASKELL__ >= 708
7{-# LANGUAGE TypeFamilies #-}
9{-# LANGUAGE ForeignFunctionInterface, JavaScriptFFI, UnliftedFFITypes #-}
12-- Copyright : (c) 2009, 2010, 2011, 2012 Bryan O'Sullivan,
13-- (c) 2009 Duncan Coutts,
14-- (c) 2008, 2009 Tom Harper
17-- Maintainer : bos@serpentine.com
18-- Stability : experimental
21-- A time and space-efficient implementation of Unicode text.
22-- Suitable for performance critical use, both in terms of large data
23-- quantities and high speed.
25-- /Note/: Read below the synopsis for important notes on the use of
28-- This module is intended to be imported @qualified@, to avoid name
29-- clashes with "Prelude" functions, e.g.
31-- > import qualified Data.Text as T
33-- To use an extended and very rich family of functions for working
34-- 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 >.
40 -- * Strict vs lazy types
52 -- * Creation and elimination
115 -- ** Accumulating maps
119 -- ** Generation and unfolding
126 -- ** Breaking strings
149 -- ** Breaking into many substrings
155 -- ** Breaking into lines and words
193 -- * Low level operations
198import Prelude (Char, Bool(..), Int, Maybe(..), String,
199 Eq(..), Ord(..), Ordering(..), (++),
201 (&&), (||), (+), (-), (.), ($), ($!), (>>),
202 not, return, otherwise, quot)
203#if defined(HAVE_DEEPSEQ)
204import Control.DeepSeq (NFData(rnf))
207import Control.Exception (assert)
209import Data.Char (isSpace)
210import Data.Data (Data(gfoldl, toConstr, gunfold, dataTypeOf), constrIndex,
211 Constr, mkConstr, DataType, mkDataType, Fixity(Prefix))
212import Control.Monad (foldM)
213import Control.Monad.ST (ST)
214import qualified Data.Text.Array as A
215import qualified Data.List as L
216import Data.Binary (Binary(get, put))
217import Data.Monoid (Monoid(..))
218#if MIN_VERSION_base(4,9,0)
219import Data.Semigroup (Semigroup(..))
221import Data.String (IsString(..))
222import qualified Data.Text.Internal.Fusion as S
223import qualified Data.Text.Internal.Fusion.Common as S
224import Data.Text.Encoding (decodeUtf8', encodeUtf8)
225import Data.Text.Internal.Fusion (stream, reverseStream, unstream)
226-- import Data.Text.Internal.Private (span_)
227import Data.Text.Internal (Text(..), empty, empty_, firstf, mul, safe, text)
228-- import Data.Text.Show (singleton, unpack, unpackCString#)
229import qualified Prelude as P
230import Data.Text.Unsafe (Iter(..), iter, iter_, lengthWord16, reverseIter,
231 reverseIter_, unsafeHead, unsafeTail)
232import Data.Text.Internal.Unsafe.Char (unsafeChr)
233import qualified Data.Text.Internal.Functions as F
234import qualified Data.Text.Internal.Encoding.Utf16 as U16
235-- import Data.Text.Internal.Search (indices)
236#if defined(__HADDOCK__)
237import Data.ByteString (ByteString)
238import qualified Data.Text.Lazy as L
239import Data.Int (Int64)
241import GHC.Base (eqInt, neInt, gtInt, geInt, ltInt, leInt)
242#if __GLASGOW_HASKELL__ >= 708
243import qualified GHC.Exts as Exts
245#if MIN_VERSION_base(4,7,0)
246import Text.Printf (PrintfArg, formatArg, formatString)
249-- GHCJS ------------------------------------------------------------
250import Data.JSString.Internal.Type (JSString (..))
251import qualified Data.JSString as JSS
252import qualified Data.JSString.Internal.Fusion as SJS
253import qualified Data.JSString.Internal.Fusion.Common as SJS
255import GHC.Base (build)
256import qualified GHC.CString as GHC
257import GHC.Exts (Addr#, ByteArray#)
258import GHCJS.Prim (JSVal (..))
260unpack :: Text -> String
261unpack = coerce JSS.unpack
262{-# INLINE [1] unpack #-}
264singleton :: Char -> Text
265singleton = coerce JSS.singleton
266{-# INLINE [1] singleton #-}
269"JSSTRING singleton -> fused" [~1] forall a.
270 singleton a = unstream (S.singleton (safe a))
271"JSSTRING singleton -> unfused" [1] forall a.
272 unstream (S.singleton (safe a)) = singleton a
275foreign import javascript unsafe "$r = $1;" addrToByteArray :: Addr# -> ByteArray#
277{-# RULES "inlineJSString" forall s. pack (GHC.Base.build (GHC.unpackFoldrCString# s)) = Text (JSString (JSVal (addrToByteArray s))) #-}
279-- | /O(n)/ Convert a literal string into a JSString. Subject to fusion.
280unpackCString# :: Addr# -> Text
281unpackCString# addr# = Text $ SJS.unstream (SJS.streamCString# addr#)
282{-# NOINLINE unpackCString# #-}
284{-# RULES "TEXT literal" forall a.
285 unstream (S.map safe (S.streamList (GHC.unpackCString# a)))
286 = unpackCString# a #-}
288{-# RULES "TEXT literal UTF8" [1] forall a.
289 unstream (S.map safe (S.streamList (GHC.unpackCStringUtf8# a)))
290 = unpackCString# a #-}
292{-# RULES "TEXT empty literal" [1]
293 unstream (S.map safe (S.streamList []))
296{-# RULES "TEXT singleton literal" [1] forall a.
297 unstream (S.map safe (S.streamList [a]))
300---------------------------------------------------------------------
304-- This package provides both strict and lazy 'Text' types. The
305-- strict type is provided by the "Data.Text" module, while the lazy
306-- type is provided by the "Data.Text.Lazy" module. Internally, the
307-- lazy @Text@ type consists of a list of strict chunks.
309-- The strict 'Text' type requires that an entire string fit into
310-- memory at once. The lazy 'Data.Text.Lazy.Text' type is capable of
311-- streaming strings that are larger than memory using a small memory
312-- footprint. In many cases, the overhead of chunked streaming makes
313-- the lazy 'Data.Text.Lazy.Text' type slower than its strict
314-- counterpart, but this is not always the case. Sometimes, the time
315-- complexity of a function in one module may be different from the
316-- other, due to their differing internal structures.
318-- Each module provides an almost identical API, with the main
319-- difference being that the strict module uses 'Int' values for
320-- lengths and counts, while the lazy module uses 'Data.Int.Int64'
325-- A 'Text' value is a sequence of Unicode scalar values, as defined
327-- <http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf#page=35 §3.9, definition D76 of the Unicode 5.2 standard >.
328-- As such, a 'Text' cannot contain values in the range U+D800 to
329-- U+DFFF inclusive. Haskell implementations admit all Unicode code
331-- (<http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf#page=13 §3.4, definition D10 >)
332-- as 'Char' values, including code points from this invalid range.
333-- This means that there are some 'Char' values that are not valid
334-- Unicode scalar values, and the functions in this module must handle
337-- Within this module, many functions construct a 'Text' from one or
338-- more 'Char' values. Those functions will substitute 'Char' values
339-- that are not valid Unicode scalar values with the replacement
340-- character \"�\" (U+FFFD). Functions that perform this
341-- inspection and replacement are documented with the phrase
342-- \"Performs replacement on invalid scalar values\".
344-- (One reason for this policy of replacement is that internally, a
345-- 'Text' value is represented as packed UTF-16 data. Values in the
346-- range U+D800 through U+DFFF are used by UTF-16 to denote surrogate
347-- code points, and so cannot be represented. The functions replace
348-- invalid scalar values, instead of dropping them, as a security
349-- measure. For details, see
350-- <http://unicode.org/reports/tr36/#Deletion_of_Noncharacters Unicode Technical Report 36, §3.5 >.)
354-- Most of the functions in this module are subject to /fusion/,
355-- meaning that a pipeline of such functions will usually allocate at
356-- most one 'Text' value.
358-- As an example, consider the following pipeline:
360-- > import Data.Text as T
361-- > import Data.Text.Encoding as E
362-- > import Data.ByteString (ByteString)
364-- > countChars :: ByteString -> Int
365-- > countChars = T.length . T.toUpper . E.decodeUtf8
367-- From the type signatures involved, this looks like it should
368-- allocate one 'Data.ByteString.ByteString' value, and two 'Text'
369-- values. However, when a module is compiled with optimisation
370-- enabled under GHC, the two intermediate 'Text' values will be
371-- optimised away, and the function will be compiled down to a single
372-- loop over the source 'Data.ByteString.ByteString'.
374-- Functions that can be fused by the compiler are documented with the
375-- phrase \"Subject to fusion\".
377-- instance Eq Text where
378-- Text arrA offA lenA == Text arrB offB lenB
379-- | lenA == lenB = A.equal arrA offA arrB offB lenA
380-- | otherwise = False
381-- {-# INLINE (==) #-}
382instance Eq Text where
383 Text x == Text y = x == y
385-- instance Ord Text where
386-- compare = compareText
388instance Ord Text where
389 compare (Text x) (Text y) = compare x y
391instance Read Text where
392 readsPrec p str = [(pack x,y) | (x,y) <- readsPrec p str]
394#if MIN_VERSION_base(4,9,0)
395-- Semigroup orphan instances for older GHCs are provided by
396-- 'semigroups` package
398instance Semigroup Text where
402instance Monoid Text where
404#if MIN_VERSION_base(4,9,0)
405 mappend = (<>) -- future-proof definition
411instance IsString Text where
414#if __GLASGOW_HASKELL__ >= 708
415instance Exts.IsList Text where
416 type Item Text = Char
421#if defined(HAVE_DEEPSEQ)
422instance NFData Text where rnf !_ = ()
425instance Binary Text where
426 put t = put (encodeUtf8 t)
429 case decodeUtf8' bs of
430 P.Left exn -> P.fail (P.show exn)
431 P.Right a -> P.return a
433-- | This instance preserves data abstraction at the cost of inefficiency.
434-- We omit reflection services for the sake of data abstraction.
436-- This instance was created by copying the updated behavior of
437-- @"Data.Set".@'Data.Set.Set' and @"Data.Map".@'Data.Map.Map'. If you
438-- feel a mistake has been made, please feel free to submit
441-- The original discussion is archived here:
442-- <http://groups.google.com/group/haskell-cafe/browse_thread/thread/b5bbb1b28a7e525d/0639d46852575b93 could we get a Data instance for Data.Text.Text? >
444-- The followup discussion that changed the behavior of 'Data.Set.Set'
445-- and 'Data.Map.Map' is archived here:
446-- <http://markmail.org/message/trovdc6zkphyi3cr#query:+page:1+mid:a46der3iacwjcf6n+state:results Proposal: Allow gunfold for Data.Map, ... >
448instance Data Text where
449 gfoldl f z txt = z pack `f` (unpack txt)
450 toConstr _ = packConstr
451 gunfold k z c = case constrIndex c of
453 _ -> P.error "gunfold"
454 dataTypeOf _ = textDataType
456#if MIN_VERSION_base(4,7,0)
457-- | Only defined for @base-4.7.0.0@ and later
458instance PrintfArg Text where
459 formatArg t = formatString $ unpack t
463packConstr = mkConstr textDataType "pack" [] Prefix
465textDataType :: DataType
466textDataType = mkDataType "Data.Text.Text" [packConstr]
468-- -- | /O(n)/ Compare two 'Text' values lexicographically.
469-- compareText :: Text -> Text -> Ordering
470-- compareText ta@(Text _arrA _offA lenA) tb@(Text _arrB _offB lenB)
471-- | lenA == 0 && lenB == 0 = EQ
472-- | otherwise = go 0 0
475-- | i >= lenA || j >= lenB = compare lenA lenB
478-- | otherwise = go (i+di) (j+dj)
479-- where Iter a di = iter ta i
480-- Iter b dj = iter tb j
482-- -----------------------------------------------------------------------------
483-- * Conversion to/from 'Text'
485-- | /O(n)/ Convert a 'String' into a 'Text'. Subject to
486-- fusion. Performs replacement on invalid scalar values.
487pack :: String -> Text
488pack = coerce JSS.pack
489-- pack = unstream . S.map safe . S.streamList
490{-# INLINE [1] pack #-}
492-- -----------------------------------------------------------------------------
495-- | /O(n)/ Adds a character to the front of a 'Text'. This function
496-- is more costly than its 'List' counterpart because it requires
497-- copying a new array. Subject to fusion. Performs replacement on
498-- invalid scalar values.
499cons :: Char -> Text -> Text
500cons = coerce JSS.cons
501-- cons c t = unstream (S.cons (safe c) (stream t))
506-- | /O(n)/ Adds a character to the end of a 'Text'. This copies the
507-- entire array in the process, unless fused. Subject to fusion.
508-- Performs replacement on invalid scalar values.
509snoc :: Text -> Char -> Text
510snoc = coerce JSS.snoc
511-- snoc t c = unstream (S.snoc (stream t) (safe c))
514-- | /O(n)/ Appends one 'Text' to the other by copying both of them
515-- into a new 'Text'. Subject to fusion.
516append :: Text -> Text -> Text
517append = coerce JSS.append
518-- append a@(Text arr1 off1 len1) b@(Text arr2 off2 len2)
521-- | len > 0 = Text (A.run x) 0 len
522-- | otherwise = overflowError "append"
525-- x :: ST s (A.MArray s)
528-- A.copyI arr 0 arr1 off1 len1
529-- A.copyI arr len1 arr2 off2 len
531{-# NOINLINE append #-}
534"TEXT append -> fused" [~1] forall t1 t2.
535 append t1 t2 = unstream (S.append (stream t1) (stream t2))
536"TEXT append -> unfused" [1] forall t1 t2.
537 unstream (S.append (stream t1) (stream t2)) = append t1 t2
540-- | /O(1)/ Returns the first character of a 'Text', which must be
541-- non-empty. Subject to fusion.
543head = coerce JSS.head
544-- head t = S.head (stream t)
547-- | /O(1)/ Returns the first character and rest of a 'Text', or
548-- 'Nothing' if empty. Subject to fusion.
549uncons :: Text -> Maybe (Char, Text)
550uncons = coerce JSS.uncons
551-- uncons t@(Text arr off len)
552-- | len <= 0 = Nothing
553-- | otherwise = Just $ let !(Iter c d) = iter t 0
554-- in (c, text arr (off+d) (len-d))
555{-# INLINE [1] uncons #-}
557-- | Lifted from Control.Arrow and specialized.
558second :: (b -> c) -> (a,b) -> (a,c)
559second f (a, b) = (a, f b)
561-- | /O(1)/ Returns the last character of a 'Text', which must be
562-- non-empty. Subject to fusion.
564last = coerce JSS.last
565-- last (Text arr off len)
566-- | len <= 0 = emptyError "last"
567-- | n < 0xDC00 || n > 0xDFFF = unsafeChr n
568-- | otherwise = U16.chr2 n0 n
569-- where n = A.unsafeIndex arr (off+len-1)
570-- n0 = A.unsafeIndex arr (off+len-2)
571{-# INLINE [1] last #-}
574"TEXT last -> fused" [~1] forall t.
575 last t = S.last (stream t)
576"TEXT last -> unfused" [1] forall t.
577 S.last (stream t) = last t
580-- | /O(1)/ Returns all characters after the head of a 'Text', which
581-- must be non-empty. Subject to fusion.
583tail = coerce JSS.tail
584-- tail t@(Text arr off len)
585-- | len <= 0 = emptyError "tail"
586-- | otherwise = text arr (off+d) (len-d)
587-- where d = iter_ t 0
588{-# INLINE [1] tail #-}
591"TEXT tail -> fused" [~1] forall t.
592 tail t = unstream (S.tail (stream t))
593"TEXT tail -> unfused" [1] forall t.
594 unstream (S.tail (stream t)) = tail t
597-- | /O(1)/ Returns all but the last character of a 'Text', which must
598-- be non-empty. Subject to fusion.
600init = coerce JSS.init
601-- init (Text arr off len) | len <= 0 = emptyError "init"
602-- | n >= 0xDC00 && n <= 0xDFFF = text arr off (len-2)
603-- | otherwise = text arr off (len-1)
605-- n = A.unsafeIndex arr (off+len-1)
606{-# INLINE [1] init #-}
609"TEXT init -> fused" [~1] forall t.
610 init t = unstream (S.init (stream t))
611"TEXT init -> unfused" [1] forall t.
612 unstream (S.init (stream t)) = init t
615-- | /O(1)/ Tests whether a 'Text' is empty or not. Subject to
618null = coerce JSS.null
619-- null (Text _arr _off len) =
620-- #if defined(ASSERTS)
621-- assert (len >= 0) $
624{-# INLINE [1] null #-}
627"TEXT null -> fused" [~1] forall t.
628 null t = S.null (stream t)
629"TEXT null -> unfused" [1] forall t.
630 S.null (stream t) = null t
633-- | /O(1)/ Tests whether a 'Text' contains exactly one character.
635-- isSingleton :: Text -> Bool
636-- isSingleton = S.isSingleton . stream
637-- {-# INLINE isSingleton #-}
639-- | /O(n)/ Returns the number of characters in a 'Text'.
642length = coerce JSS.length
643-- length t = S.length (stream t)
644{-# INLINE [0] length #-}
645-- length needs to be phased after the compareN/length rules otherwise
646-- it may inline before the rules have an opportunity to fire.
648-- | /O(n)/ Compare the count of characters in a 'Text' to a number.
651-- This function gives the same answer as comparing against the result
652-- of 'length', but can short circuit if the count of characters is
653-- greater than the number, and hence be more efficient.
654compareLength :: Text -> Int -> Ordering
655compareLength t n = S.compareLengthI (stream t) n
656{-# INLINE [1] compareLength #-}
659"TEXT compareN/length -> compareLength" [~1] forall t n.
660 compare (length t) n = compareLength t n
664"TEXT ==N/length -> compareLength/==EQ" [~1] forall t n.
665 eqInt (length t) n = compareLength t n == EQ
669"TEXT /=N/length -> compareLength//=EQ" [~1] forall t n.
670 neInt (length t) n = compareLength t n /= EQ
674"TEXT <N/length -> compareLength/==LT" [~1] forall t n.
675 ltInt (length t) n = compareLength t n == LT
679"TEXT <=N/length -> compareLength//=GT" [~1] forall t n.
680 leInt (length t) n = compareLength t n /= GT
684"TEXT >N/length -> compareLength/==GT" [~1] forall t n.
685 gtInt (length t) n = compareLength t n == GT
689"TEXT >=N/length -> compareLength//=LT" [~1] forall t n.
690 geInt (length t) n = compareLength t n /= LT
693-- -----------------------------------------------------------------------------
695-- | /O(n)/ 'map' @f@ @t@ is the 'Text' obtained by applying @f@ to
696-- each element of @t@. Subject to fusion. Performs replacement on
697-- invalid scalar values.
698map :: (Char -> Char) -> Text -> Text
700-- map f t = unstream (S.map (safe . f) (stream t))
701{-# INLINE [1] map #-}
703-- | /O(n)/ The 'intercalate' function takes a 'Text' and a list of
704-- 'Text's and concatenates the list after interspersing the first
705-- argument between each element of the list.
706intercalate :: Text -> [Text] -> Text
707intercalate = coerce JSS.intercalate
708-- intercalate t = concat . (F.intersperse t)
709{-# INLINE intercalate #-}
711-- | /O(n)/ The 'intersperse' function takes a character and places it
712-- between the characters of a 'Text'. Subject to fusion. Performs
713-- replacement on invalid scalar values.
714intersperse :: Char -> Text -> Text
715intersperse = coerce JSS.intersperse
716-- intersperse c t = unstream (S.intersperse (safe c) (stream t))
717{-# INLINE intersperse #-}
719-- | /O(n)/ Reverse the characters of a string. Subject to fusion.
720reverse :: Text -> Text
721reverse = coerce JSS.reverse
722-- reverse t = S.reverse (stream t)
723{-# INLINE reverse #-}
725-- | /O(m+n)/ Replace every non-overlapping occurrence of @needle@ in
726-- @haystack@ with @replacement@.
728-- This function behaves as though it was defined as follows:
731-- replace needle replacement haystack =
732-- 'intercalate' replacement ('splitOn' needle haystack)
735-- As this suggests, each occurrence is replaced exactly once. So if
736-- @needle@ occurs in @replacement@, that occurrence will /not/ itself
737-- be replaced recursively:
739-- > replace "oo" "foo" "oo" == "foo"
741-- In cases where several instances of @needle@ overlap, only the
742-- first one will be replaced:
744-- > replace "ofo" "bar" "ofofo" == "barfo"
746-- In (unlikely) bad cases, this function's time complexity degrades
749 -- ^ @needle@ to search for. If this string is empty, an
752 -- ^ @replacement@ to replace @needle@ with.
754 -- ^ @haystack@ in which to search.
756replace = coerce JSS.replace
757-- replace needle@(Text _ _ neeLen)
758-- (Text repArr repOff repLen)
759-- haystack@(Text hayArr hayOff hayLen)
760-- | neeLen == 0 = emptyError "replace"
761-- | L.null ixs = haystack
762-- | len > 0 = Text (A.run x) 0 len
763-- | otherwise = empty
765-- ixs = indices needle haystack
766-- len = hayLen - (neeLen - repLen) `mul` L.length ixs
767-- x :: ST s (A.MArray s)
770-- let loop (i:is) o d = do
773-- A.copyI marr d hayArr (hayOff+o) d0
774-- A.copyI marr d0 repArr repOff d1
775-- loop is (i + neeLen) d1
776-- loop [] o d = A.copyI marr d hayArr (hayOff+o) len
780-- ----------------------------------------------------------------------------
781-- ** Case conversions (folds)
785-- When case converting 'Text' values, do not use combinators like
786-- @map toUpper@ to case convert each character of a string
787-- individually, as this gives incorrect results according to the
788-- rules of some writing systems. The whole-string case conversion
789-- functions from this module, such as @toUpper@, obey the correct
790-- case conversion rules. As a result, these functions may map one
791-- input character to two or three output characters. For examples,
792-- see the documentation of each function.
794-- /Note/: In some languages, case conversion is a locale- and
795-- context-dependent operation. The case conversion functions in this
796-- module are /not/ locale sensitive. Programs that require locale
797-- sensitivity should use appropriate versions of the
798-- <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 >.
800-- | /O(n)/ Convert a string to folded case. Subject to fusion.
802-- This function is mainly useful for performing caseless (also known
803-- as case insensitive) string comparisons.
805-- A string @x@ is a caseless match for a string @y@ if and only if:
807-- @toCaseFold x == toCaseFold y@
809-- The result string may be longer than the input string, and may
810-- differ from applying 'toLower' to the input string. For instance,
811-- the Armenian small ligature \"ﬓ\" (men now, U+FB13) is case
812-- folded to the sequence \"մ\" (men, U+0574) followed by
813-- \"ն\" (now, U+0576), while the Greek \"µ\" (micro sign,
814-- U+00B5) is case folded to \"μ\" (small letter mu, U+03BC)
816toCaseFold :: Text -> Text
817-- toCaseFold t = unstream (S.toCaseFold (stream t))
818toCaseFold = coerce JSS.toCaseFold
819{-# INLINE toCaseFold #-}
821-- | /O(n)/ Convert a string to lower case, using simple case
822-- conversion. Subject to fusion.
824-- The result string may be longer than the input string. For
825-- instance, \"İ\" (Latin capital letter I with dot above,
826-- U+0130) maps to the sequence \"i\" (Latin small letter i, U+0069)
827-- followed by \" ̇\" (combining dot above, U+0307).
828toLower :: Text -> Text
829-- toLower t = unstream (S.toLower (stream t))
830toLower = coerce JSS.toLower
831{-# INLINE toLower #-}
833-- | /O(n)/ Convert a string to upper case, using simple case
834-- conversion. Subject to fusion.
836-- The result string may be longer than the input string. For
837-- instance, the German \"ß\" (eszett, U+00DF) maps to the
838-- two-letter sequence \"SS\".
839toUpper :: Text -> Text
840-- toUpper t = unstream (S.toUpper (stream t))
841toUpper = coerce JSS.toUpper
842{-# INLINE toUpper #-}
844-- | /O(n)/ Convert a string to title case, using simple case
845-- conversion. Subject to fusion.
847-- The first letter of the input is converted to title case, as is
848-- every subsequent letter that immediately follows a non-letter.
849-- Every letter that immediately follows another letter is converted
852-- The result string may be longer than the input string. For example,
853-- the Latin small ligature fl (U+FB02) is converted to the
854-- sequence Latin capital letter F (U+0046) followed by Latin small
857-- /Note/: this function does not take language or culture specific
858-- rules into account. For instance, in English, different style
859-- guides disagree on whether the book name \"The Hill of the Red
860-- Fox\" is correctly title cased—but this function will
861-- capitalize /every/ word.
862toTitle :: Text -> Text
863toTitle = coerce JSS.toTitle
864-- toTitle t = unstream (S.toTitle (stream t))
865{-# INLINE toTitle #-}
867-- | /O(n)/ Left-justify a string to the given length, using the
868-- specified fill character on the right. Subject to fusion.
869-- Performs replacement on invalid scalar values.
873-- > justifyLeft 7 'x' "foo" == "fooxxxx"
874-- > justifyLeft 3 'x' "foobar" == "foobar"
875justifyLeft :: Int -> Char -> Text -> Text
876justifyLeft = coerce JSS.justifyLeft
879-- | otherwise = t `append` replicateChar (k-len) c
880-- where len = length t
881{-# INLINE [1] justifyLeft #-}
884"TEXT justifyLeft -> fused" [~1] forall k c t.
885 justifyLeft k c t = unstream (S.justifyLeftI k c (stream t))
886"TEXT justifyLeft -> unfused" [1] forall k c t.
887 unstream (S.justifyLeftI k c (stream t)) = justifyLeft k c t
890-- | /O(n)/ Right-justify a string to the given length, using the
891-- specified fill character on the left. Performs replacement on
892-- invalid scalar values.
896-- > justifyRight 7 'x' "bar" == "xxxxbar"
897-- > justifyRight 3 'x' "foobar" == "foobar"
898justifyRight :: Int -> Char -> Text -> Text
899justifyRight = coerce JSS.justifyRight
902-- | otherwise = replicateChar (k-len) c `append` t
903-- where len = length t
904{-# INLINE justifyRight #-}
906-- | /O(n)/ Center a string to the given length, using the specified
907-- fill character on either side. Performs replacement on invalid
912-- > center 8 'x' "HS" = "xxxHSxxx"
913center :: Int -> Char -> Text -> Text
914center = coerce JSS.center
917-- | otherwise = replicateChar l c `append` t `append` replicateChar r c
918-- where len = length t
924-- | /O(n)/ The 'transpose' function transposes the rows and columns
925-- of its 'Text' argument. Note that this function uses 'pack',
926-- 'unpack', and the list version of transpose, and is thus not very
928transpose :: [Text] -> [Text]
929transpose = coerce JSS.transpose
930-- transpose ts = P.map pack (L.transpose (P.map unpack ts))
932-- -----------------------------------------------------------------------------
933-- * Reducing 'Text's (folds)
935-- | /O(n)/ 'foldl', applied to a binary operator, a starting value
936-- (typically the left-identity of the operator), and a 'Text',
937-- reduces the 'Text' using the binary operator, from left to right.
939foldl :: (a -> Char -> a) -> a -> Text -> a
940foldl f a0 (Text t) = JSS.foldl f a0 t
941-- foldl f z t = S.foldl f z (stream t)
944-- | /O(n)/ A strict version of 'foldl'. Subject to fusion.
945foldl' :: (a -> Char -> a) -> a -> Text -> a
946foldl' f a0 (Text t) = JSS.foldl' f a0 t
947-- foldl' f z t = S.foldl' f z (stream t)
950-- | /O(n)/ A variant of 'foldl' that has no starting value argument,
951-- and thus must be applied to a non-empty 'Text'. Subject to fusion.
952foldl1 :: (Char -> Char -> Char) -> Text -> Char
953foldl1 = coerce JSS.foldl1
954-- foldl1 f t = S.foldl1 f (stream t)
957-- | /O(n)/ A strict version of 'foldl1'. Subject to fusion.
958foldl1' :: (Char -> Char -> Char) -> Text -> Char
959foldl1' = coerce JSS.foldl1'
960-- foldl1' f t = S.foldl1' f (stream t)
961{-# INLINE foldl1' #-}
963-- | /O(n)/ 'foldr', applied to a binary operator, a starting value
964-- (typically the right-identity of the operator), and a 'Text',
965-- reduces the 'Text' using the binary operator, from right to left.
967foldr :: (Char -> a -> a) -> a -> Text -> a
968foldr f a0 (Text t) = JSS.foldr f a0 t
969-- foldr f z t = S.foldr f z (stream t)
972-- | /O(n)/ A variant of 'foldr' that has no starting value argument,
973-- and thus must be applied to a non-empty 'Text'. Subject to
975foldr1 :: (Char -> Char -> Char) -> Text -> Char
976foldr1 = coerce JSS.foldr1
977-- foldr1 f t = S.foldr1 f (stream t)
980-- -----------------------------------------------------------------------------
983-- | /O(n)/ Concatenate a list of 'Text's.
984concat :: [Text] -> Text
985concat = coerce JSS.concat
986-- concat ts = case ts' of
989-- _ -> Text (A.run go) 0 len
991-- ts' = L.filter (not . null) ts
992-- len = sumP "concat" $ L.map lengthWord16 ts'
993-- go :: ST s (A.MArray s)
996-- let step i (Text a o l) =
997-- let !j = i + l in A.copyI arr i a o j >> return j
998-- foldM step 0 ts' >> return arr
1000-- | /O(n)/ Map a function over a 'Text' that results in a 'Text', and
1001-- concatenate the results.
1002concatMap :: (Char -> Text) -> Text -> Text
1003concatMap = coerce JSS.concatMap
1004-- concatMap f = concat . foldr ((:) . f) []
1005{-# INLINE concatMap #-}
1007-- | /O(n)/ 'any' @p@ @t@ determines whether any character in the
1008-- 'Text' @t@ satisfies the predicate @p@. Subject to fusion.
1009any :: (Char -> Bool) -> Text -> Bool
1011-- any p t = S.any p (stream t)
1014-- | /O(n)/ 'all' @p@ @t@ determines whether all characters in the
1015-- 'Text' @t@ satisfy the predicate @p@. Subject to fusion.
1016all :: (Char -> Bool) -> Text -> Bool
1018-- all p t = S.all p (stream t)
1021-- | /O(n)/ 'maximum' returns the maximum value from a 'Text', which
1022-- must be non-empty. Subject to fusion.
1023maximum :: Text -> Char
1024maximum = coerce JSS.maximum
1025-- maximum t = S.maximum (stream t)
1026{-# INLINE maximum #-}
1028-- | /O(n)/ 'minimum' returns the minimum value from a 'Text', which
1029-- must be non-empty. Subject to fusion.
1030minimum :: Text -> Char
1031minimum = coerce JSS.minimum
1032-- minimum t = S.minimum (stream t)
1033{-# INLINE minimum #-}
1035-- -----------------------------------------------------------------------------
1036-- * Building 'Text's
1038-- | /O(n)/ 'scanl' is similar to 'foldl', but returns a list of
1039-- successive reduced values from the left. Subject to fusion.
1040-- Performs replacement on invalid scalar values.
1042-- > scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]
1046-- > last (scanl f z xs) == foldl f z xs.
1047scanl :: (Char -> Char -> Char) -> Char -> Text -> Text
1048scanl = coerce JSS.scanl
1049-- scanl f z t = unstream (S.scanl g z (stream t))
1050-- where g a b = safe (f a b)
1053-- | /O(n)/ 'scanl1' is a variant of 'scanl' that has no starting
1054-- value argument. Subject to fusion. Performs replacement on
1055-- invalid scalar values.
1057-- > scanl1 f [x1, x2, ...] == [x1, x1 `f` x2, ...]
1058scanl1 :: (Char -> Char -> Char) -> Text -> Text
1059scanl1 = coerce JSS.scanl1
1060-- scanl1 f t | null t = empty
1061-- | otherwise = scanl f (unsafeHead t) (unsafeTail t)
1062{-# INLINE scanl1 #-}
1064-- | /O(n)/ 'scanr' is the right-to-left dual of 'scanl'. Performs
1065-- replacement on invalid scalar values.
1067-- > scanr f v == reverse . scanl (flip f) v . reverse
1068scanr :: (Char -> Char -> Char) -> Char -> Text -> Text
1069scanr = coerce JSS.scanr
1070-- scanr f z = S.reverse . S.reverseScanr g z . reverseStream
1071-- where g a b = safe (f a b)
1074-- | /O(n)/ 'scanr1' is a variant of 'scanr' that has no starting
1075-- value argument. Subject to fusion. Performs replacement on
1076-- invalid scalar values.
1077scanr1 :: (Char -> Char -> Char) -> Text -> Text
1078scanr1 = coerce JSS.scanr1
1079-- scanr1 f t | null t = empty
1080-- | otherwise = scanr f (last t) (init t)
1081{-# INLINE scanr1 #-}
1083-- | /O(n)/ Like a combination of 'map' and 'foldl''. Applies a
1084-- function to each element of a 'Text', passing an accumulating
1085-- parameter from left to right, and returns a final 'Text'. Performs
1086-- replacement on invalid scalar values.
1087mapAccumL :: (a -> Char -> (a,Char)) -> a -> Text -> (a, Text)
1088mapAccumL f z0 (Text a) =
1089 let (a', t) = JSS.mapAccumL f z0 a
1091-- mapAccumL f z0 = S.mapAccumL g z0 . stream
1092-- where g a b = second safe (f a b)
1093{-# INLINE mapAccumL #-}
1095-- | The 'mapAccumR' function behaves like a combination of 'map' and
1096-- a strict 'foldr'; it applies a function to each element of a
1097-- 'Text', passing an accumulating parameter from right to left, and
1098-- returning a final value of this accumulator together with the new
1100-- Performs replacement on invalid scalar values.
1101mapAccumR :: (a -> Char -> (a,Char)) -> a -> Text -> (a, Text)
1102mapAccumR f z0 (Text a) =
1103 let (a', t) = JSS.mapAccumR f z0 a
1105-- mapAccumR f z0 = second reverse . S.mapAccumL g z0 . reverseStream
1106-- where g a b = second safe (f a b)
1107{-# INLINE mapAccumR #-}
1109-- -----------------------------------------------------------------------------
1110-- ** Generating and unfolding 'Text's
1112-- | /O(n*m)/ 'replicate' @n@ @t@ is a 'Text' consisting of the input
1113-- @t@ repeated @n@ times.
1114replicate :: Int -> Text -> Text
1115replicate = coerce JSS.replicate
1116-- replicate n t@(Text a o l)
1117-- | n <= 0 || l <= 0 = empty
1119-- | isSingleton t = replicateChar n (unsafeHead t)
1120-- | otherwise = Text (A.run x) 0 len
1123-- x :: ST s (A.MArray s)
1126-- let loop !d !i | i >= n = return arr
1127-- | otherwise = let m = d + l
1128-- in A.copyI arr d a o m >> loop m (i+1)
1130{-# INLINE [1] replicate #-}
1133"TEXT replicate/singleton -> replicateChar" [~1] forall n c.
1134 replicate n (singleton c) = replicateChar n c
1137-- | /O(n)/ 'replicateChar' @n@ @c@ is a 'Text' of length @n@ with @c@ the
1138-- value of every element. Subject to fusion.
1139replicateChar :: Int -> Char -> Text
1141replicateChar n c = unstream (S.replicateCharI n (safe c))
1142{-# INLINE replicateChar #-}
1144replicateChar n c = Text $ js_replicateChar n c
1145{-# INLINE [1] replicateChar #-}
1147"JSSTRING replicateChar -> fused" [~1] forall n c.
1148 replicateChar n c = unstream (S.replicateCharI n (safe c))
1149"JSSTRING replicateChar -> unfused" [1] forall n c.
1150 unstream (S.replicateCharI n (safe c)) = replicateChar n c
1154-- | /O(n)/, where @n@ is the length of the result. The 'unfoldr'
1155-- function is analogous to the List 'L.unfoldr'. 'unfoldr' builds a
1156-- 'Text' from a seed value. The function takes the element and
1157-- returns 'Nothing' if it is done producing the 'Text', otherwise
1158-- 'Just' @(a,b)@. In this case, @a@ is the next 'Char' in the
1159-- string, and @b@ is the seed value for further production. Subject
1160-- to fusion. Performs replacement on invalid scalar values.
1161unfoldr :: (a -> Maybe (Char,a)) -> a -> Text
1162unfoldr f a = Text $ JSS.unfoldr f a
1163-- unfoldr f s = unstream (S.unfoldr (firstf safe . f) s)
1164{-# INLINE unfoldr #-}
1166-- | /O(n)/ Like 'unfoldr', 'unfoldrN' builds a 'Text' from a seed
1167-- value. However, the length of the result should be limited by the
1168-- first argument to 'unfoldrN'. This function is more efficient than
1169-- 'unfoldr' when the maximum length of the result is known and
1170-- correct, otherwise its performance is similar to 'unfoldr'. Subject
1171-- to fusion. Performs replacement on invalid scalar values.
1172unfoldrN :: Int -> (a -> Maybe (Char,a)) -> a -> Text
1173unfoldrN n f a0 = Text $ JSS.unfoldrN n f a0
1174-- unfoldrN n f s = unstream (S.unfoldrN n (firstf safe . f) s)
1175{-# INLINE unfoldrN #-}
1177-- -----------------------------------------------------------------------------
1180-- | /O(n)/ 'take' @n@, applied to a 'Text', returns the prefix of the
1181-- 'Text' of length @n@, or the 'Text' itself if @n@ is greater than
1182-- the length of the Text. Subject to fusion.
1183take :: Int -> Text -> Text
1184take = coerce JSS.take
1185-- take n t@(Text arr off len)
1188-- | otherwise = text arr off (iterN n t)
1189{-# INLINE [1] take #-}
1191-- iterN :: Int -> Text -> Int
1192-- iterN n t@(Text _arr _off len) = loop 0 0
1193-- where loop !i !cnt
1194-- | i >= len || cnt >= n = i
1195-- | otherwise = loop (i+d) (cnt+1)
1196-- where d = iter_ t i
1199"TEXT take -> fused" [~1] forall n t.
1200 take n t = unstream (S.take n (stream t))
1201"TEXT take -> unfused" [1] forall n t.
1202 unstream (S.take n (stream t)) = take n t
1205-- | /O(n)/ 'takeEnd' @n@ @t@ returns the suffix remaining after
1206-- taking @n@ characters from the end of @t@.
1210-- > takeEnd 3 "foobar" == "bar"
1211takeEnd :: Int -> Text -> Text
1212takeEnd = coerce JSS.takeEnd
1213-- takeEnd n t@(Text arr off len)
1216-- | otherwise = text arr (off+i) (len-i)
1217-- where i = iterNEnd n t
1219-- iterNEnd :: Int -> Text -> Int
1220-- iterNEnd n t@(Text _arr _off len) = loop (len-1) n
1224-- | otherwise = loop (i+d) (m-1)
1225-- where d = reverseIter_ t i
1227-- | /O(n)/ 'drop' @n@, applied to a 'Text', returns the suffix of the
1228-- 'Text' after the first @n@ characters, or the empty 'Text' if @n@
1229-- is greater than the length of the 'Text'. Subject to fusion.
1230drop :: Int -> Text -> Text
1231drop = coerce JSS.drop
1232-- drop n t@(Text arr off len)
1234-- | n >= len = empty
1235-- | otherwise = text arr (off+i) (len-i)
1236-- where i = iterN n t
1237{-# INLINE [1] drop #-}
1240"TEXT drop -> fused" [~1] forall n t.
1241 drop n t = unstream (S.drop n (stream t))
1242"TEXT drop -> unfused" [1] forall n t.
1243 unstream (S.drop n (stream t)) = drop n t
1246-- | /O(n)/ 'dropEnd' @n@ @t@ returns the prefix remaining after
1247-- dropping @n@ characters from the end of @t@.
1251-- > dropEnd 3 "foobar" == "foo"
1252dropEnd :: Int -> Text -> Text
1253dropEnd = coerce JSS.dropEnd
1254-- dropEnd n t@(Text arr off len)
1256-- | n >= len = empty
1257-- | otherwise = text arr off (iterNEnd n t)
1259-- | /O(n)/ 'takeWhile', applied to a predicate @p@ and a 'Text',
1260-- returns the longest prefix (possibly empty) of elements that
1261-- satisfy @p@. Subject to fusion.
1262takeWhile :: (Char -> Bool) -> Text -> Text
1263takeWhile = coerce JSS.takeWhile
1264-- takeWhile p t@(Text arr off len) = loop 0
1265-- where loop !i | i >= len = t
1266-- | p c = loop (i+d)
1267-- | otherwise = text arr off i
1268-- where Iter c d = iter t i
1269{-# INLINE [1] takeWhile #-}
1272"TEXT takeWhile -> fused" [~1] forall p t.
1273 takeWhile p t = unstream (S.takeWhile p (stream t))
1274"TEXT takeWhile -> unfused" [1] forall p t.
1275 unstream (S.takeWhile p (stream t)) = takeWhile p t
1278-- | /O(n)/ 'takeWhileEnd', applied to a predicate @p@ and a 'Text',
1279-- returns the longest suffix (possibly empty) of elements that
1280-- satisfy @p@. Subject to fusion.
1283-- > takeWhileEnd (=='o') "foo" == "oo"
1284takeWhileEnd :: (Char -> Bool) -> Text -> Text
1286takeWhileEnd p t@(Text arr off len) = loop (len-1) len
1287 where loop !i !l | l <= 0 = t
1288 | p c = loop (i+d) (l+d)
1289 | otherwise = text arr (off+l) (len-l)
1290 where (c,d) = reverseIter t i
1292takeWhileEnd p t@(Text jst) = loop (len-1) len
1293 where loop !i !l | l <= 0 = t
1294 | p c = loop (i+d) (l+d)
1295 | otherwise = Text $ js_substr1 l jst
1296 where (c,d) = reverseIter t i
1299{-# INLINE [1] takeWhileEnd #-}
1302"TEXT takeWhileEnd -> fused" [~1] forall p t.
1303 takeWhileEnd p t = S.reverse (S.takeWhile p (S.reverseStream t))
1304"TEXT takeWhileEnd -> unfused" [1] forall p t.
1305 S.reverse (S.takeWhile p (S.reverseStream t)) = takeWhileEnd p t
1308-- | /O(n)/ 'dropWhile' @p@ @t@ returns the suffix remaining after
1309-- 'takeWhile' @p@ @t@. Subject to fusion.
1310dropWhile :: (Char -> Bool) -> Text -> Text
1311dropWhile = coerce JSS.dropWhile
1312-- dropWhile p t@(Text arr off len) = loop 0 0
1313-- where loop !i !l | l >= len = empty
1314-- | p c = loop (i+d) (l+d)
1315-- | otherwise = Text arr (off+i) (len-l)
1317{-# INLINE [1] dropWhile #-}
1320"TEXT dropWhile -> fused" [~1] forall p t.
1321 dropWhile p t = unstream (S.dropWhile p (stream t))
1322"TEXT dropWhile -> unfused" [1] forall p t.
1323 unstream (S.dropWhile p (stream t)) = dropWhile p t
1326-- | /O(n)/ 'dropWhileEnd' @p@ @t@ returns the prefix remaining after
1327-- dropping characters that satisfy the predicate @p@ from the end of
1328-- @t@. Subject to fusion.
1332-- > dropWhileEnd (=='.') "foo..." == "foo"
1333dropWhileEnd :: (Char -> Bool) -> Text -> Text
1334dropWhileEnd = coerce JSS.dropWhileEnd
1335-- dropWhileEnd p t@(Text arr off len) = loop (len-1) len
1336-- where loop !i !l | l <= 0 = empty
1337-- | p c = loop (i+d) (l+d)
1338-- | otherwise = Text arr off l
1339-- where (c,d) = reverseIter t i
1340{-# INLINE [1] dropWhileEnd #-}
1343"TEXT dropWhileEnd -> fused" [~1] forall p t.
1344 dropWhileEnd p t = S.reverse (S.dropWhile p (S.reverseStream t))
1345"TEXT dropWhileEnd -> unfused" [1] forall p t.
1346 S.reverse (S.dropWhile p (S.reverseStream t)) = dropWhileEnd p t
1349-- | /O(n)/ 'dropAround' @p@ @t@ returns the substring remaining after
1350-- dropping characters that satisfy the predicate @p@ from both the
1351-- beginning and end of @t@. Subject to fusion.
1352dropAround :: (Char -> Bool) -> Text -> Text
1353dropAround p = dropWhile p . dropWhileEnd p
1354{-# INLINE [1] dropAround #-}
1356-- | /O(n)/ Remove leading white space from a string. Equivalent to:
1358-- > dropWhile isSpace
1359stripStart :: Text -> Text
1360stripStart = dropWhile isSpace
1361{-# INLINE [1] stripStart #-}
1363-- | /O(n)/ Remove trailing white space from a string. Equivalent to:
1365-- > dropWhileEnd isSpace
1366stripEnd :: Text -> Text
1367stripEnd = dropWhileEnd isSpace
1368{-# INLINE [1] stripEnd #-}
1370-- | /O(n)/ Remove leading and trailing white space from a string.
1373-- > dropAround isSpace
1374strip :: Text -> Text
1375strip = dropAround isSpace
1376{-# INLINE [1] strip #-}
1378-- | /O(n)/ 'splitAt' @n t@ returns a pair whose first element is a
1379-- prefix of @t@ of length @n@, and whose second is the remainder of
1380-- the string. It is equivalent to @('take' n t, 'drop' n t)@.
1381splitAt :: Int -> Text -> (Text, Text)
1382splitAt = coerce JSS.splitAt
1383-- splitAt n t@(Text arr off len)
1384-- | n <= 0 = (empty, t)
1385-- | n >= len = (t, empty)
1386-- | otherwise = let k = iterN n t
1387-- in (text arr off k, text arr (off+k) (len-k))
1389-- | /O(n)/ 'span', applied to a predicate @p@ and text @t@, returns
1390-- a pair whose first element is the longest prefix (possibly empty)
1391-- of @t@ of elements that satisfy @p@, and whose second is the
1392-- remainder of the list.
1393span :: (Char -> Bool) -> Text -> (Text, Text)
1394span = coerce JSS.span
1395-- span p t = case span_ p t of
1396-- (# hd,tl #) -> (hd,tl)
1399-- | /O(n)/ 'break' is like 'span', but the prefix returned is
1400-- over elements that fail the predicate @p@.
1401break :: (Char -> Bool) -> Text -> (Text, Text)
1402break = coerce JSS.break
1403-- break p = span (not . p)
1406-- | /O(n)/ Group characters in a string according to a predicate.
1407groupBy :: (Char -> Char -> Bool) -> Text -> [Text]
1408groupBy = coerce JSS.groupBy
1411-- loop t@(Text arr off len)
1413-- | otherwise = text arr off n : loop (text arr (off+n) (len-n))
1414-- where Iter c d = iter t 0
1415-- n = d + findAIndexOrEnd (not . p c) (Text arr (off+d) (len-d))
1417-- | Returns the /array/ index (in units of 'Word16') at which a
1418-- character may be found. This is /not/ the same as the logical
1419-- index returned by e.g. 'findIndex'.
1420-- findAIndexOrEnd :: (Char -> Bool) -> Text -> Int
1421-- findAIndexOrEnd q t@(Text _arr _off len) = go 0
1422-- where go !i | i >= len || q c = i
1423-- | otherwise = go (i+d)
1424-- where Iter c d = iter t i
1426-- | /O(n)/ Group characters in a string by equality.
1427group :: Text -> [Text]
1430-- | /O(n)/ Return all initial segments of the given 'Text', shortest
1432inits :: Text -> [Text]
1433inits = coerce JSS.inits
1434-- inits t@(Text arr off len) = loop 0
1435-- where loop i | i >= len = [t]
1436-- | otherwise = Text arr off i : loop (i + iter_ t i)
1438-- | /O(n)/ Return all final segments of the given 'Text', longest
1440tails :: Text -> [Text]
1441tails = coerce JSS.tails
1442-- tails t | null t = [empty]
1443-- | otherwise = t : tails (unsafeTail t)
1447-- Splitting functions in this library do not perform character-wise
1448-- copies to create substrings; they just construct new 'Text's that
1449-- are slices of the original.
1451-- | /O(m+n)/ Break a 'Text' into pieces separated by the first 'Text'
1452-- argument (which cannot be empty), consuming the delimiter. An empty
1453-- delimiter is invalid, and will cause an error to be raised.
1457-- > splitOn "\r\n" "a\r\nb\r\nd\r\ne" == ["a","b","d","e"]
1458-- > splitOn "aaa" "aaaXaaaXaaaXaaa" == ["","X","X","X",""]
1459-- > splitOn "x" "x" == ["",""]
1463-- > intercalate s . splitOn s == id
1464-- > splitOn (singleton c) == split (==c)
1466-- (Note: the string @s@ to split on above cannot be empty.)
1468-- In (unlikely) bad cases, this function's time complexity degrades
1471 -- ^ String to split on. If this string is empty, an error
1476splitOn = coerce JSS.splitOn
1477-- splitOn pat@(Text _ _ l) src@(Text arr off len)
1478-- | l <= 0 = emptyError "splitOn"
1479-- | isSingleton pat = split (== unsafeHead pat) src
1480-- | otherwise = go 0 (indices pat src)
1482-- go !s (x:xs) = text arr (s+off) (x-s) : go (x+l) xs
1483-- go s _ = [text arr (s+off) (len-s)]
1484{-# INLINE [1] splitOn #-}
1487"TEXT splitOn/singleton -> split/==" [~1] forall c t.
1488 splitOn (singleton c) t = split (==c) t
1491-- | /O(n)/ Splits a 'Text' into components delimited by separators,
1492-- where the predicate returns True for a separator element. The
1493-- resulting components do not contain the separators. Two adjacent
1494-- separators result in an empty component in the output. eg.
1496-- > split (=='a') "aabbaca" == ["","","bb","c",""]
1497-- > split (=='a') "" == [""]
1498split :: (Char -> Bool) -> Text -> [Text]
1499split = coerce JSS.split
1500-- split _ t@(Text _off _arr 0) = [t]
1501-- split p t = loop t
1502-- where loop s | null s' = [l]
1503-- | otherwise = l : loop (unsafeTail s')
1504-- where (# l, s' #) = span_ (not . p) s
1507-- | /O(n)/ Splits a 'Text' into components of length @k@. The last
1508-- element may be shorter than the other chunks, depending on the
1509-- length of the input. Examples:
1511-- > chunksOf 3 "foobarbaz" == ["foo","bar","baz"]
1512-- > chunksOf 4 "haskell.org" == ["hask","ell.","org"]
1513chunksOf :: Int -> Text -> [Text]
1514chunksOf = coerce JSS.chunksOf
1517-- go t = case splitAt k t of
1518-- (a,b) | null a -> []
1519-- | otherwise -> a : go b
1520{-# INLINE chunksOf #-}
1522-- ----------------------------------------------------------------------------
1525-------------------------------------------------------------------------------
1526-- ** Searching with a predicate
1528-- | /O(n)/ The 'find' function takes a predicate and a 'Text', and
1529-- returns the first element matching the predicate, or 'Nothing' if
1530-- there is no such element.
1531find :: (Char -> Bool) -> Text -> Maybe Char
1532find = coerce JSS.find
1533-- find p t = S.findBy p (stream t)
1536-- | /O(n)/ The 'partition' function takes a predicate and a 'Text',
1537-- and returns the pair of 'Text's with elements which do and do not
1538-- satisfy the predicate, respectively; i.e.
1540-- > partition p t == (filter p t, filter (not . p) t)
1541partition :: (Char -> Bool) -> Text -> (Text, Text)
1542partition = coerce JSS.partition
1543-- partition p t = (filter p t, filter (not . p) t)
1544{-# INLINE partition #-}
1546-- | /O(n)/ 'filter', applied to a predicate and a 'Text',
1547-- returns a 'Text' containing those characters that satisfy the
1549filter :: (Char -> Bool) -> Text -> Text
1550filter = coerce JSS.filter
1551-- filter p t = unstream (S.filter p (stream t))
1552{-# INLINE filter #-}
1554-- | /O(n+m)/ Find the first instance of @needle@ (which must be
1555-- non-'null') in @haystack@. The first element of the returned tuple
1556-- is the prefix of @haystack@ before @needle@ is matched. The second
1557-- is the remainder of @haystack@, starting with the match.
1561-- > breakOn "::" "a::b::c" ==> ("a", "::b::c")
1562-- > breakOn "/" "foobar" ==> ("foobar", "")
1566-- > append prefix match == haystack
1567-- > where (prefix, match) = breakOn needle haystack
1569-- If you need to break a string by a substring repeatedly (e.g. you
1570-- want to break on every instance of a substring), use 'breakOnAll'
1571-- instead, as it has lower startup overhead.
1573-- In (unlikely) bad cases, this function's time complexity degrades
1575breakOn :: Text -> Text -> (Text, Text)
1576breakOn = coerce JSS.breakOn
1577-- breakOn pat src@(Text arr off len)
1578-- | null pat = emptyError "breakOn"
1579-- | otherwise = case indices pat src of
1580-- [] -> (src, empty)
1581-- (x:_) -> (text arr off x, text arr (off+x) (len-x))
1582{-# INLINE breakOn #-}
1584-- | /O(n+m)/ Similar to 'breakOn', but searches from the end of the
1587-- The first element of the returned tuple is the prefix of @haystack@
1588-- up to and including the last match of @needle@. The second is the
1589-- remainder of @haystack@, following the match.
1591-- > breakOnEnd "::" "a::b::c" ==> ("a::b::", "c")
1592breakOnEnd :: Text -> Text -> (Text, Text)
1593breakOnEnd = coerce JSS.breakOnEnd
1594-- breakOnEnd pat src = (reverse b, reverse a)
1595-- where (a,b) = breakOn (reverse pat) (reverse src)
1596{-# INLINE breakOnEnd #-}
1598-- | /O(n+m)/ Find all non-overlapping instances of @needle@ in
1599-- @haystack@. Each element of the returned list consists of a pair:
1601-- * The entire string prior to the /k/th match (i.e. the prefix)
1603-- * The /k/th match, followed by the remainder of the string
1607-- > breakOnAll "::" ""
1609-- > breakOnAll "/" "a/b/c/"
1610-- > ==> [("a", "/b/c/"), ("a/b", "/c/"), ("a/b/c", "/")]
1612-- In (unlikely) bad cases, this function's time complexity degrades
1615-- The @needle@ parameter may not be empty.
1616breakOnAll :: Text -- ^ @needle@ to search for
1617 -> Text -- ^ @haystack@ in which to search
1619breakOnAll = coerce JSS.breakOnAll
1620-- breakOnAll pat src@(Text arr off slen)
1621-- | null pat = emptyError "breakOnAll"
1622-- | otherwise = L.map step (indices pat src)
1624-- step x = (chunk 0 x, chunk x (slen-x))
1625-- chunk !n !l = text arr (n+off) l
1626{-# INLINE breakOnAll #-}
1628-------------------------------------------------------------------------------
1629-- ** Indexing 'Text's
1633-- If you think of a 'Text' value as an array of 'Char' values (which
1634-- it is not), you run the risk of writing inefficient code.
1636-- An idiom that is common in some languages is to find the numeric
1637-- offset of a character or substring, then use that number to split
1638-- or trim the searched string. With a 'Text' value, this approach
1639-- would require two /O(n)/ operations: one to perform the search, and
1640-- one to operate from wherever the search ended.
1642-- For example, suppose you have a string that you want to split on
1643-- the substring @\"::\"@, such as @\"foo::bar::quux\"@. Instead of
1644-- searching for the index of @\"::\"@ and taking the substrings
1645-- before and after that index, you would instead use @breakOnAll \"::\"@.
1647-- | /O(n)/ 'Text' index (subscript) operator, starting from 0.
1648index :: Text -> Int -> Char
1649index = coerce JSS.index
1650-- index t n = S.index (stream t) n
1653-- | /O(n)/ The 'findIndex' function takes a predicate and a 'Text'
1654-- and returns the index of the first element in the 'Text' satisfying
1655-- the predicate. Subject to fusion.
1656findIndex :: (Char -> Bool) -> Text -> Maybe Int
1657findIndex = coerce JSS.findIndex
1658-- findIndex p t = S.findIndex p (stream t)
1659{-# INLINE findIndex #-}
1661-- | /O(n+m)/ The 'count' function returns the number of times the
1662-- query string appears in the given 'Text'. An empty query string is
1663-- invalid, and will cause an error to be raised.
1665-- In (unlikely) bad cases, this function's time complexity degrades
1667count :: Text -> Text -> Int
1668count = coerce JSS.count
1670-- | null pat = emptyError "count"
1671-- | isSingleton pat = countChar (unsafeHead pat) src
1672-- | otherwise = L.length (indices pat src)
1673{-# INLINE [1] count #-}
1676"TEXT count/singleton -> countChar" [~1] forall c t.
1677 count (singleton c) t = countChar c t
1680-- | /O(n)/ The 'countChar' function returns the number of times the
1681-- query element appears in the given 'Text'. Subject to fusion.
1682countChar :: Char -> Text -> Int
1683countChar c t = S.countChar c (stream t)
1684{-# INLINE countChar #-}
1686-------------------------------------------------------------------------------
1689-- | /O(n)/ 'zip' takes two 'Text's and returns a list of
1690-- corresponding pairs of bytes. If one input 'Text' is short,
1691-- excess elements of the longer 'Text' are discarded. This is
1692-- equivalent to a pair of 'unpack' operations.
1693zip :: Text -> Text -> [(Char,Char)]
1695-- zip a b = S.unstreamList $ S.zipWith (,) (stream a) (stream b)
1698-- | /O(n)/ 'zipWith' generalises 'zip' by zipping with the function
1699-- given as the first argument, instead of a tupling function.
1700-- Performs replacement on invalid scalar values.
1701zipWith :: (Char -> Char -> Char) -> Text -> Text -> Text
1702zipWith = coerce JSS.zipWith
1703-- zipWith f t1 t2 = unstream (S.zipWith g (stream t1) (stream t2))
1704-- where g a b = safe (f a b)
1705{-# INLINE zipWith #-}
1707-- | /O(n)/ Breaks a 'Text' up into a list of words, delimited by 'Char's
1708-- representing white space.
1709words :: Text -> [Text]
1710words = coerce JSS.words
1711-- words t@(Text arr off len) = loop 0 0
1714-- | n >= len = if start == n
1716-- else [Text arr (start+off) (n-start)]
1719-- then loop (start+1) (start+1)
1720-- else Text arr (start+off) (n-start) : loop (n+d) (n+d)
1721-- | otherwise = loop start (n+d)
1722-- where Iter c d = iter t n
1725-- | /O(n)/ Breaks a 'Text' up into a list of 'Text's at
1726-- newline 'Char's. The resulting strings do not contain newlines.
1727lines :: Text -> [Text]
1728lines = coerce JSS.lines
1729-- lines ps | null ps = []
1730-- | otherwise = h : if null t
1732-- else lines (unsafeTail t)
1733-- where (# h,t #) = span_ (/= '\n') ps
1737-- | /O(n)/ Portably breaks a 'Text' up into a list of 'Text's at line
1740-- A line boundary is considered to be either a line feed, a carriage
1741-- return immediately followed by a line feed, or a carriage return.
1742-- This accounts for both Unix and Windows line ending conventions,
1743-- and for the old convention used on Mac OS 9 and earlier.
1744lines' :: Text -> [Text]
1745lines' ps | null ps = []
1746 | otherwise = h : case uncons t of
1749 | c == '\n' -> lines t'
1750 | c == '\r' -> case uncons t' of
1751 Just ('\n',t'') -> lines t''
1753 where (h,t) = span notEOL ps
1754 notEOL c = c /= '\n' && c /= '\r'
1755{-# INLINE lines' #-}
1758-- | /O(n)/ Joins lines, after appending a terminating newline to
1760unlines :: [Text] -> Text
1761unlines = coerce JSS.unlines
1762-- unlines = concat . L.map (`snoc` '\n')
1763{-# INLINE unlines #-}
1765-- | /O(n)/ Joins words using single space characters.
1766unwords :: [Text] -> Text
1767unwords = coerce JSS.unwords
1768-- unwords = intercalate (singleton ' ')
1769{-# INLINE unwords #-}
1771-- | /O(n)/ The 'isPrefixOf' function takes two 'Text's and returns
1772-- 'True' iff the first is a prefix of the second. Subject to fusion.
1773isPrefixOf :: Text -> Text -> Bool
1774isPrefixOf = coerce JSS.isPrefixOf
1775-- isPrefixOf a@(Text _ _ alen) b@(Text _ _ blen) =
1776-- alen <= blen && S.isPrefixOf (stream a) (stream b)
1777{-# INLINE [1] isPrefixOf #-}
1780"TEXT isPrefixOf -> fused" [~1] forall s t.
1781 isPrefixOf s t = S.isPrefixOf (stream s) (stream t)
1782"JSSTRING isPrefixOf -> unfused" [1] forall x y.
1783 S.isPrefixOf (stream x) (stream y) = isPrefixOf x y
1786-- | /O(n)/ The 'isSuffixOf' function takes two 'Text's and returns
1787-- 'True' iff the first is a suffix of the second.
1788isSuffixOf :: Text -> Text -> Bool
1789isSuffixOf = coerce JSS.isSuffixOf
1790-- isSuffixOf a@(Text _aarr _aoff alen) b@(Text barr boff blen) =
1792-- where d = blen - alen
1794-- | otherwise = Text barr (boff+d) alen
1795{-# INLINE isSuffixOf #-}
1797-- | /O(n+m)/ The 'isInfixOf' function takes two 'Text's and returns
1798-- 'True' iff the first is contained, wholly and intact, anywhere
1799-- within the second.
1801-- In (unlikely) bad cases, this function's time complexity degrades
1803isInfixOf :: Text -> Text -> Bool
1804isInfixOf = coerce JSS.isInfixOf
1805-- isInfixOf needle haystack
1806-- | null needle = True
1807-- | isSingleton needle = S.elem (unsafeHead needle) . S.stream $ haystack
1808-- | otherwise = not . L.null . indices needle $ haystack
1809{-# INLINE [1] isInfixOf #-}
1812"TEXT isInfixOf/singleton -> S.elem/S.stream" [~1] forall n h.
1813 isInfixOf (singleton n) h = S.elem n (S.stream h)
1816-------------------------------------------------------------------------------
1819-- | /O(n)/ Return the suffix of the second string if its prefix
1820-- matches the entire first string.
1824-- > stripPrefix "foo" "foobar" == Just "bar"
1825-- > stripPrefix "" "baz" == Just "baz"
1826-- > stripPrefix "foo" "quux" == Nothing
1828-- This is particularly useful with the @ViewPatterns@ extension to
1831-- > {-# LANGUAGE ViewPatterns #-}
1832-- > import Data.Text as T
1834-- > fnordLength :: Text -> Int
1835-- > fnordLength (stripPrefix "fnord" -> Just suf) = T.length suf
1836-- > fnordLength _ = -1
1837stripPrefix :: Text -> Text -> Maybe Text
1838stripPrefix = coerce JSS.stripPrefix
1839-- stripPrefix p@(Text _arr _off plen) t@(Text arr off len)
1840-- | p `isPrefixOf` t = Just $! text arr (off+plen) (len-plen)
1841-- | otherwise = Nothing
1843-- | /O(n)/ Find the longest non-empty common prefix of two strings
1844-- and return it, along with the suffixes of each string at which they
1847-- If the strings do not have a common prefix or either one is empty,
1848-- this function returns 'Nothing'.
1852-- > commonPrefixes "foobar" "fooquux" == Just ("foo","bar","quux")
1853-- > commonPrefixes "veeble" "fetzer" == Nothing
1854-- > commonPrefixes "" "baz" == Nothing
1855commonPrefixes :: Text -> Text -> Maybe (Text,Text,Text)
1856commonPrefixes = coerce JSS.commonPrefixes
1857-- commonPrefixes t0@(Text arr0 off0 len0) t1@(Text arr1 off1 len1) = go 0 0
1859-- go !i !j | i < len0 && j < len1 && a == b = go (i+d0) (j+d1)
1860-- | i > 0 = Just (Text arr0 off0 i,
1861-- text arr0 (off0+i) (len0-i),
1862-- text arr1 (off1+j) (len1-j))
1863-- | otherwise = Nothing
1864-- where Iter a d0 = iter t0 i
1865-- Iter b d1 = iter t1 j
1867-- | /O(n)/ Return the prefix of the second string if its suffix
1868-- matches the entire first string.
1872-- > stripSuffix "bar" "foobar" == Just "foo"
1873-- > stripSuffix "" "baz" == Just "baz"
1874-- > stripSuffix "foo" "quux" == Nothing
1876-- This is particularly useful with the @ViewPatterns@ extension to
1879-- > {-# LANGUAGE ViewPatterns #-}
1880-- > import Data.Text as T
1882-- > quuxLength :: Text -> Int
1883-- > quuxLength (stripSuffix "quux" -> Just pre) = T.length pre
1884-- > quuxLength _ = -1
1885stripSuffix :: Text -> Text -> Maybe Text
1886stripSuffix = coerce JSS.stripSuffix
1887-- stripSuffix p@(Text _arr _off plen) t@(Text arr off len)
1888-- | p `isSuffixOf` t = Just $! text arr off (len-plen)
1889-- | otherwise = Nothing
1891-- -- | Add a list of non-negative numbers. Errors out on overflow.
1892-- sumP :: String -> [Int] -> Int
1894-- where go !a (x:xs)
1895-- | ax >= 0 = go ax xs
1896-- | otherwise = overflowError fun
1900-- emptyError :: String -> a
1901-- emptyError fun = P.error $ "Data.Text." ++ fun ++ ": empty input"
1903overflowError :: String -> a
1904overflowError fun = P.error $ "Data.Text." ++ fun ++ ": size overflow"
1906-- | /O(n)/ Make a distinct copy of the given string, sharing no
1907-- storage with the original string.
1909-- As an example, suppose you read a large string, of which you need
1910-- only a small portion. If you do not use 'copy', the entire original
1911-- array will be kept alive in memory by the smaller string. Making a
1912-- copy \"breaks the link\" to the original array, allowing it to be
1913-- garbage collected if there are no other live references to it.
1916-- copy (Text arr off len) = Text (A.run go) 0 len
1918-- go :: ST s (A.MArray s)
1922foreign import javascript unsafe
1923 "h$jsstringReplicateChar" js_replicateChar :: Int -> Char -> JSString
1924foreign import javascript unsafe
1925 "$2.substr($1)" js_substr1 :: Int -> JSString -> JSString
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list