{-# LANGUAGE BangPatterns #-}
{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}
{-# OPTIONS_HADDOCK prune #-}
{-# LANGUAGE Trustworthy #-}

-- |
-- Module      : Data.ByteString.Lazy
-- Copyright   : (c) Don Stewart 2006
--               (c) Duncan Coutts 2006-2011
-- License     : BSD-style
--
-- Maintainer  : dons00@gmail.com, duncan@community.haskell.org
-- Stability   : stable
-- Portability : portable
--
-- A time and space-efficient implementation of lazy byte vectors
-- using lists of packed 'Word8' arrays, suitable for high performance
-- use, both in terms of large data quantities, or high speed
-- requirements. Lazy ByteStrings are encoded as lazy lists of strict chunks
-- of bytes.
--
-- A key feature of lazy ByteStrings is the means to manipulate large or
-- unbounded streams of data without requiring the entire sequence to be
-- resident in memory. To take advantage of this you have to write your
-- functions in a lazy streaming style, e.g. classic pipeline composition. The
-- default I\/O chunk size is 32k, which should be good in most circumstances.
--
-- Some operations, such as 'concat', 'append', 'reverse' and 'cons', have
-- better complexity than their "Data.ByteString" equivalents, due to
-- optimisations resulting from the list spine structure. For other
-- operations lazy ByteStrings are usually within a few percent of
-- strict ones.
--
-- The recomended way to assemble lazy ByteStrings from smaller parts
-- is to use the builder monoid from "Data.ByteString.Builder".
--
-- This module is intended to be imported @qualified@, to avoid name
-- clashes with "Prelude" functions.  eg.
--
-- > import qualified Data.ByteString.Lazy as B
--
-- Original GHC implementation by Bryan O\'Sullivan.
-- Rewritten to use 'Data.Array.Unboxed.UArray' by Simon Marlow.
-- Rewritten to support slices and use 'Foreign.ForeignPtr.ForeignPtr'
-- by David Roundy.
-- Rewritten again and extended by Don Stewart and Duncan Coutts.
-- Lazy variant by Duncan Coutts and Don Stewart.
--

module Data.ByteString.Lazy (

        -- * Lazy @ByteString@
        ByteString,
        LazyByteString,

        -- * Introducing and eliminating 'ByteString's
        empty,
        singleton,
        pack,
        unpack,
        fromStrict,
        toStrict,
        fromChunks,
        toChunks,
        foldrChunks,
        foldlChunks,

        -- * Basic interface
        cons,
        cons',
        snoc,
        append,
        head,
        uncons,
        unsnoc,
        last,
        tail,
        init,
        null,
        length,

        -- * Transforming ByteStrings
        map,
        reverse,
        intersperse,
        intercalate,
        transpose,

        -- * Reducing 'ByteString's (folds)
        foldl,
        foldl',
        foldl1,
        foldl1',
        foldr,
        foldr',
        foldr1,
        foldr1',

        -- ** Special folds
        concat,
        concatMap,
        any,
        all,
        maximum,
        minimum,
        compareLength,

        -- * Building ByteStrings
        -- ** Scans
        scanl,
        scanl1,
        scanr,
        scanr1,

        -- ** Accumulating maps
        mapAccumL,
        mapAccumR,

        -- ** Infinite ByteStrings
        repeat,
        replicate,
        cycle,
        iterate,

        -- ** Unfolding ByteStrings
        unfoldr,

        -- * Substrings

        -- ** Breaking strings
        take,
        takeEnd,
        drop,
        dropEnd,
        splitAt,
        takeWhile,
        takeWhileEnd,
        dropWhile,
        dropWhileEnd,
        span,
        spanEnd,
        break,
        breakEnd,
        group,
        groupBy,
        inits,
        tails,
        initsNE,
        tailsNE,
        stripPrefix,
        stripSuffix,

        -- ** Breaking into many substrings
        split,
        splitWith,

        -- * Predicates
        isPrefixOf,
        isSuffixOf,
--        isInfixOf,

        -- ** Search for arbitrary substrings
--        isSubstringOf,

        -- * Searching ByteStrings

        -- ** Searching by equality
        elem,
        notElem,

        -- ** Searching with a predicate
        find,
        filter,
        partition,

        -- * Indexing ByteStrings
        index,
        indexMaybe,
        (!?),
        elemIndex,
        elemIndexEnd,
        elemIndices,
        findIndex,
        findIndexEnd,
        findIndices,
        count,

        -- * Zipping and unzipping ByteStrings
        zip,
        zipWith,
        packZipWith,
        unzip,

        -- * Ordered ByteStrings
--        sort,

        -- * Low level conversions
        -- ** Copying ByteStrings
        copy,
--        defrag,

        -- * I\/O with 'ByteString's
        -- $IOChunk

        -- ** Standard input and output
        getContents,
        putStr,
        interact,

        -- ** Files
        readFile,
        writeFile,
        appendFile,

        -- ** I\/O with Handles
        hGetContents,
        hGet,
        hGetNonBlocking,
        hPut,
        hPutNonBlocking,
        hPutStr,

  ) where

import Prelude hiding
    (reverse,head,tail,last,init,Foldable(..),map,lines,unlines
    ,concat,any,take,drop,splitAt,takeWhile,dropWhile,span,break,filter
    ,all,concatMap,scanl, scanl1, scanr, scanr1
    ,repeat, cycle, interact, iterate,readFile,writeFile,appendFile,replicate
    ,getContents,getLine,putStr,putStrLn ,zip,zipWith,unzip,notElem)

import qualified Data.List              as List
import qualified Data.List.NonEmpty     as NE
import Data.List.NonEmpty (NonEmpty(..))
import qualified Data.Bifunctor         as BF
import qualified Data.ByteString        as P  (ByteString) -- type name only
import qualified Data.ByteString        as S  -- S for strict (hmm...)
import qualified Data.ByteString.Internal.Type as S
import qualified Data.ByteString.Unsafe as S
import qualified Data.ByteString.Lazy.Internal.Deque as D
import Data.ByteString.Lazy.Internal

import Control.Monad            (mplus)
import Data.Word                (Word8)
import Data.Int                 (Int64)
import GHC.Stack.Types          (HasCallStack)
import System.IO                (Handle,openBinaryFile,stdin,stdout,withBinaryFile,IOMode(..)
                                ,hClose)
import System.IO.Error          (mkIOError, illegalOperationErrorType)
import System.IO.Unsafe

import Foreign.Ptr
import Foreign.Storable


-- -----------------------------------------------------------------------------
-- Introducing and eliminating 'ByteString's

-- | /O(1)/ The empty 'ByteString'
empty :: ByteString
empty :: ByteString
empty = ByteString
Empty
{-# INLINE empty #-}

-- | /O(1)/ Convert a 'Word8' into a 'ByteString'
singleton :: Word8 -> ByteString
singleton :: Word8 -> ByteString
singleton Word8
w = ByteString -> ByteString -> ByteString
Chunk (Word8 -> ByteString
S.singleton Word8
w) ByteString
Empty
{-# INLINE singleton #-}

-- | /O(n)/ Convert a '[Word8]' into a 'ByteString'.
pack :: [Word8] -> ByteString
pack :: [Word8] -> ByteString
pack = [Word8] -> ByteString
packBytes

-- | /O(n)/ Converts a 'ByteString' to a '[Word8]'.
unpack :: ByteString -> [Word8]
unpack :: ByteString -> [Word8]
unpack = ByteString -> [Word8]
unpackBytes

-- | /O(c)/ Convert a list of strict 'ByteString' into a lazy 'ByteString'
fromChunks :: [P.ByteString] -> ByteString
fromChunks :: [ByteString] -> ByteString
fromChunks = (ByteString -> ByteString -> ByteString)
-> ByteString -> [ByteString] -> ByteString
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
List.foldr ByteString -> ByteString -> ByteString
chunk ByteString
Empty

-- | /O(c)/ Convert a lazy 'ByteString' into a list of strict 'ByteString'
toChunks :: ByteString -> [P.ByteString]
toChunks :: ByteString -> [ByteString]
toChunks = (ByteString -> [ByteString] -> [ByteString])
-> [ByteString] -> ByteString -> [ByteString]
forall a. (ByteString -> a -> a) -> a -> ByteString -> a
foldrChunks (:) []

------------------------------------------------------------------------

{-
-- | /O(n)/ Convert a '[a]' into a 'ByteString' using some
-- conversion function
packWith :: (a -> Word8) -> [a] -> ByteString
packWith k str = LPS $ L.map (P.packWith k) (chunk defaultChunkSize str)
{-# INLINE packWith #-}
{-# SPECIALIZE packWith :: (Char -> Word8) -> [Char] -> ByteString #-}

-- | /O(n)/ Converts a 'ByteString' to a '[a]', using a conversion function.
unpackWith :: (Word8 -> a) -> ByteString -> [a]
unpackWith k (LPS ss) = L.concatMap (S.unpackWith k) ss
{-# INLINE unpackWith #-}
{-# SPECIALIZE unpackWith :: (Word8 -> Char) -> ByteString -> [Char] #-}
-}

-- ---------------------------------------------------------------------
-- Basic interface

-- | /O(1)/ Test whether a ByteString is empty.
null :: ByteString -> Bool
null :: ByteString -> Bool
null ByteString
Empty = Bool
True
null ByteString
_     = Bool
False
{-# INLINE null #-}

-- | /O(c)/ 'length' returns the length of a ByteString as an 'Int64'
length :: ByteString -> Int64
length :: ByteString -> Int64
length = (Int64 -> ByteString -> Int64) -> Int64 -> ByteString -> Int64
forall a. (a -> ByteString -> a) -> a -> ByteString -> a
foldlChunks (\Int64
n ByteString
c -> Int64
n Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+ Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
S.length ByteString
c)) Int64
0
{-# INLINE [1] length #-}

infixr 5 `cons`, `cons'` --same as list (:)
infixl 5 `snoc`

-- | /O(1)/ 'cons' is analogous to '(Prelude.:)' for lists.
--
cons :: Word8 -> ByteString -> ByteString
cons :: Word8 -> ByteString -> ByteString
cons Word8
c = ByteString -> ByteString -> ByteString
Chunk (Word8 -> ByteString
S.singleton Word8
c)
{-# INLINE cons #-}

-- | /O(1)/ Unlike 'cons', 'cons'' is
-- strict in the ByteString that we are consing onto. More precisely, it forces
-- the head and the first chunk. It does this because, for space efficiency, it
-- may coalesce the new byte onto the first \'chunk\' rather than starting a
-- new \'chunk\'.
--
-- So that means you can't use a lazy recursive contruction like this:
--
-- > let xs = cons' c xs in xs
--
-- You can however use 'cons', as well as 'repeat' and 'cycle', to build
-- infinite lazy ByteStrings.
--
cons' :: Word8 -> ByteString -> ByteString
cons' :: Word8 -> ByteString -> ByteString
cons' Word8
w (Chunk ByteString
c ByteString
cs) | ByteString -> Int
S.length ByteString
c Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
16 = ByteString -> ByteString -> ByteString
Chunk (Word8 -> ByteString -> ByteString
S.cons Word8
w ByteString
c) ByteString
cs
cons' Word8
w ByteString
cs                             = ByteString -> ByteString -> ByteString
Chunk (Word8 -> ByteString
S.singleton Word8
w) ByteString
cs
{-# INLINE cons' #-}

-- | /O(n\/c)/ Append a byte to the end of a 'ByteString'
snoc :: ByteString -> Word8 -> ByteString
snoc :: ByteString -> Word8 -> ByteString
snoc ByteString
cs Word8
w = (ByteString -> ByteString -> ByteString)
-> ByteString -> ByteString -> ByteString
forall a. (ByteString -> a -> a) -> a -> ByteString -> a
foldrChunks ByteString -> ByteString -> ByteString
Chunk (Word8 -> ByteString
singleton Word8
w) ByteString
cs
{-# INLINE snoc #-}

-- | /O(1)/ Extract the first element of a ByteString, which must be non-empty.
--
-- This is a partial function, consider using 'uncons' instead.
head :: HasCallStack => ByteString -> Word8
head :: HasCallStack => ByteString -> Word8
head ByteString
Empty       = String -> Word8
forall a. HasCallStack => String -> a
errorEmptyList String
"head"
head (Chunk ByteString
c ByteString
_) = ByteString -> Word8
S.unsafeHead ByteString
c
{-# INLINE head #-}

-- | /O(1)/ Extract the 'head' and 'tail' of a ByteString, returning 'Nothing'
-- if it is empty.
uncons :: ByteString -> Maybe (Word8, ByteString)
uncons :: ByteString -> Maybe (Word8, ByteString)
uncons ByteString
Empty = Maybe (Word8, ByteString)
forall a. Maybe a
Nothing
uncons (Chunk ByteString
c ByteString
cs) = case ByteString -> Int
S.length ByteString
c of
  -- Don't move this test inside of the Just or (,).
  -- We don't want to allocate a thunk to put inside of the tuple!
  -- And if "let !tl = ... in Just (..., tl)" seems more appealing,
  -- remember that this function must remain lazy in cs.
  Int
1 -> (Word8, ByteString) -> Maybe (Word8, ByteString)
forall a. a -> Maybe a
Just (ByteString -> Word8
S.unsafeHead ByteString
c, ByteString
cs)
  Int
_ -> (Word8, ByteString) -> Maybe (Word8, ByteString)
forall a. a -> Maybe a
Just (ByteString -> Word8
S.unsafeHead ByteString
c, ByteString -> ByteString -> ByteString
Chunk (ByteString -> ByteString
S.unsafeTail ByteString
c) ByteString
cs)
{-# INLINE uncons #-}

-- | /O(1)/ Extract the elements after the head of a ByteString, which must be
-- non-empty.
--
-- This is a partial function, consider using 'uncons' instead.
tail :: HasCallStack => ByteString -> ByteString
tail :: HasCallStack => ByteString -> ByteString
tail ByteString
Empty          = String -> ByteString
forall a. HasCallStack => String -> a
errorEmptyList String
"tail"
tail (Chunk ByteString
c ByteString
cs)
  | ByteString -> Int
S.length ByteString
c Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 = ByteString
cs
  | Bool
otherwise       = ByteString -> ByteString -> ByteString
Chunk (ByteString -> ByteString
S.unsafeTail ByteString
c) ByteString
cs
{-# INLINE tail #-}

-- | /O(n\/c)/ Extract the last element of a ByteString, which must be finite
-- and non-empty.
--
-- This is a partial function, consider using 'unsnoc' instead.
last :: HasCallStack => ByteString -> Word8
last :: HasCallStack => ByteString -> Word8
last ByteString
Empty          = String -> Word8
forall a. HasCallStack => String -> a
errorEmptyList String
"last"
last (Chunk ByteString
c0 ByteString
cs0) = ByteString -> ByteString -> Word8
go ByteString
c0 ByteString
cs0
  where go :: ByteString -> ByteString -> Word8
go ByteString
c ByteString
Empty        = ByteString -> Word8
S.unsafeLast ByteString
c
        go ByteString
_ (Chunk ByteString
c ByteString
cs) = ByteString -> ByteString -> Word8
go ByteString
c ByteString
cs
-- XXX Don't inline this. Something breaks with 6.8.2 (haven't investigated yet)

-- | /O(n\/c)/ Returns all the elements of a 'ByteString' except the last one.
--
-- This is a partial function, consider using 'unsnoc' instead.
init :: HasCallStack => ByteString -> ByteString
init :: HasCallStack => ByteString -> ByteString
init ByteString
Empty          = String -> ByteString
forall a. HasCallStack => String -> a
errorEmptyList String
"init"
init (Chunk ByteString
c0 ByteString
cs0) = ByteString -> ByteString -> ByteString
go ByteString
c0 ByteString
cs0
  where go :: ByteString -> ByteString -> ByteString
go ByteString
c ByteString
Empty | ByteString -> Int
S.length ByteString
c Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 = ByteString
Empty
                   | Bool
otherwise       = ByteString -> ByteString -> ByteString
Chunk (ByteString -> ByteString
S.unsafeInit ByteString
c) ByteString
Empty
        go ByteString
c (Chunk ByteString
c' ByteString
cs)           = ByteString -> ByteString -> ByteString
Chunk ByteString
c (ByteString -> ByteString -> ByteString
go ByteString
c' ByteString
cs)

-- | /O(n\/c)/ Extract the 'init' and 'last' of a ByteString, returning 'Nothing'
-- if it is empty.
--
-- * It is no faster than using 'init' and 'last'
unsnoc :: ByteString -> Maybe (ByteString, Word8)
unsnoc :: ByteString -> Maybe (ByteString, Word8)
unsnoc ByteString
Empty        = Maybe (ByteString, Word8)
forall a. Maybe a
Nothing
unsnoc (Chunk ByteString
c ByteString
cs) = (ByteString, Word8) -> Maybe (ByteString, Word8)
forall a. a -> Maybe a
Just (HasCallStack => ByteString -> ByteString
ByteString -> ByteString
init (ByteString -> ByteString -> ByteString
Chunk ByteString
c ByteString
cs), HasCallStack => ByteString -> Word8
ByteString -> Word8
last (ByteString -> ByteString -> ByteString
Chunk ByteString
c ByteString
cs))

-- | /O(n\/c)/ Append two ByteStrings
append :: ByteString -> ByteString -> ByteString
append :: ByteString -> ByteString -> ByteString
append = ByteString -> ByteString -> ByteString
forall a. Monoid a => a -> a -> a
mappend
{-# INLINE append #-}

-- ---------------------------------------------------------------------
-- Transformations

-- | /O(n)/ 'map' @f xs@ is the ByteString obtained by applying @f@ to each
-- element of @xs@.
map :: (Word8 -> Word8) -> ByteString -> ByteString
map :: (Word8 -> Word8) -> ByteString -> ByteString
map Word8 -> Word8
f = ByteString -> ByteString
go
    where
        go :: ByteString -> ByteString
go ByteString
Empty        = ByteString
Empty
        go (Chunk ByteString
x ByteString
xs) = ByteString -> ByteString -> ByteString
Chunk ByteString
y ByteString
ys
            where
                y :: ByteString
y  = (Word8 -> Word8) -> ByteString -> ByteString
S.map Word8 -> Word8
f ByteString
x
                ys :: ByteString
ys = ByteString -> ByteString
go ByteString
xs
{-# INLINE map #-}

-- | /O(n)/ 'reverse' @xs@ returns the elements of @xs@ in reverse order.
reverse :: ByteString -> ByteString
reverse :: ByteString -> ByteString
reverse = ByteString -> ByteString -> ByteString
rev ByteString
Empty
  where rev :: ByteString -> ByteString -> ByteString
rev ByteString
a ByteString
Empty        = ByteString
a
        rev ByteString
a (Chunk ByteString
c ByteString
cs) = ByteString -> ByteString -> ByteString
rev (ByteString -> ByteString -> ByteString
Chunk (ByteString -> ByteString
S.reverse ByteString
c) ByteString
a) ByteString
cs
{-# INLINE reverse #-}

-- | The 'intersperse' function takes a 'Word8' and a 'ByteString' and
-- \`intersperses\' that byte between the elements of the 'ByteString'.
-- It is analogous to the intersperse function on Lists.
intersperse :: Word8 -> ByteString -> ByteString
intersperse :: Word8 -> ByteString -> ByteString
intersperse Word8
_ ByteString
Empty        = ByteString
Empty
intersperse Word8
w (Chunk ByteString
c ByteString
cs) = ByteString -> ByteString -> ByteString
Chunk (Word8 -> ByteString -> ByteString
S.intersperse Word8
w ByteString
c)
                                   ((ByteString -> ByteString -> ByteString)
-> ByteString -> ByteString -> ByteString
forall a. (ByteString -> a -> a) -> a -> ByteString -> a
foldrChunks (ByteString -> ByteString -> ByteString
Chunk (ByteString -> ByteString -> ByteString)
-> (ByteString -> ByteString)
-> ByteString
-> ByteString
-> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
intersperse') ByteString
Empty ByteString
cs)
  where intersperse' :: P.ByteString -> P.ByteString
        intersperse' :: ByteString -> ByteString
intersperse' (S.BS ForeignPtr Word8
fp Int
l) =
          Int -> (ForeignPtr Word8 -> IO ()) -> ByteString
S.unsafeCreateFp (Int
2Int -> Int -> Int
forall a. Num a => a -> a -> a
*Int
l) ((ForeignPtr Word8 -> IO ()) -> ByteString)
-> (ForeignPtr Word8 -> IO ()) -> ByteString
forall a b. (a -> b) -> a -> b
$ \ForeignPtr Word8
fp' ->
            ForeignPtr Word8 -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
S.unsafeWithForeignPtr ForeignPtr Word8
fp' ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p' ->
              ForeignPtr Word8 -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
S.unsafeWithForeignPtr ForeignPtr Word8
fp ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p -> do
                Ptr Word8 -> Word8 -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr Word8
p' Word8
w
                Ptr Word8 -> Ptr Word8 -> CSize -> Word8 -> IO ()
S.c_intersperse (Ptr Word8
p' Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
1) Ptr Word8
p (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
l) Word8
w

-- | The 'transpose' function transposes the rows and columns of its
-- 'ByteString' argument.
transpose :: [ByteString] -> [ByteString]
transpose :: [ByteString] -> [ByteString]
transpose [ByteString]
css = ([Word8] -> ByteString) -> [[Word8]] -> [ByteString]
forall a b. (a -> b) -> [a] -> [b]
List.map (\[Word8]
ss -> ByteString -> ByteString -> ByteString
Chunk ([Word8] -> ByteString
S.pack [Word8]
ss) ByteString
Empty)
                      ([[Word8]] -> [[Word8]]
forall a. [[a]] -> [[a]]
List.transpose ((ByteString -> [Word8]) -> [ByteString] -> [[Word8]]
forall a b. (a -> b) -> [a] -> [b]
List.map ByteString -> [Word8]
unpack [ByteString]
css))
--TODO: make this fast

-- ---------------------------------------------------------------------
-- Reducing 'ByteString's

-- | 'foldl', applied to a binary operator, a starting value (typically
-- the left-identity of the operator), and a ByteString, reduces the
-- ByteString using the binary operator, from left to right.
foldl :: (a -> Word8 -> a) -> a -> ByteString -> a
foldl :: forall a. (a -> Word8 -> a) -> a -> ByteString -> a
foldl a -> Word8 -> a
f = a -> ByteString -> a
go
  where go :: a -> ByteString -> a
go a
a ByteString
Empty        = a
a
        go a
a (Chunk ByteString
c ByteString
cs) = a -> ByteString -> a
go ((a -> Word8 -> a) -> a -> ByteString -> a
forall a. (a -> Word8 -> a) -> a -> ByteString -> a
S.foldl a -> Word8 -> a
f a
a ByteString
c) ByteString
cs
{-# INLINE foldl #-}

-- | 'foldl'' is like 'foldl', but strict in the accumulator.
foldl' :: (a -> Word8 -> a) -> a -> ByteString -> a
foldl' :: forall a. (a -> Word8 -> a) -> a -> ByteString -> a
foldl' a -> Word8 -> a
f = a -> ByteString -> a
go
  where go :: a -> ByteString -> a
go !a
a ByteString
Empty        = a
a
        go !a
a (Chunk ByteString
c ByteString
cs) = a -> ByteString -> a
go ((a -> Word8 -> a) -> a -> ByteString -> a
forall a. (a -> Word8 -> a) -> a -> ByteString -> a
S.foldl' a -> Word8 -> a
f a
a ByteString
c) ByteString
cs
{-# INLINE foldl' #-}

-- | 'foldr', applied to a binary operator, a starting value
-- (typically the right-identity of the operator), and a ByteString,
-- reduces the ByteString using the binary operator, from right to left.
foldr :: (Word8 -> a -> a) -> a -> ByteString -> a
foldr :: forall a. (Word8 -> a -> a) -> a -> ByteString -> a
foldr Word8 -> a -> a
k = (ByteString -> a -> a) -> a -> ByteString -> a
forall a. (ByteString -> a -> a) -> a -> ByteString -> a
foldrChunks ((a -> ByteString -> a) -> ByteString -> a -> a
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((Word8 -> a -> a) -> a -> ByteString -> a
forall a. (Word8 -> a -> a) -> a -> ByteString -> a
S.foldr Word8 -> a -> a
k))
{-# INLINE foldr #-}

-- | 'foldr'' is like 'foldr', but strict in the accumulator.
--
-- @since 0.11.2.0
foldr' :: (Word8 -> a -> a) -> a -> ByteString -> a
foldr' :: forall a. (Word8 -> a -> a) -> a -> ByteString -> a
foldr' Word8 -> a -> a
f a
a = ByteString -> a
go
  where
    go :: ByteString -> a
go ByteString
Empty = a
a
    go (Chunk ByteString
c ByteString
cs) = (Word8 -> a -> a) -> a -> ByteString -> a
forall a. (Word8 -> a -> a) -> a -> ByteString -> a
S.foldr' Word8 -> a -> a
f ((Word8 -> a -> a) -> a -> ByteString -> a
forall a. (Word8 -> a -> a) -> a -> ByteString -> a
foldr' Word8 -> a -> a
f a
a ByteString
cs) ByteString
c
{-# INLINE foldr' #-}

-- | 'foldl1' is a variant of 'foldl' that has no starting value
-- argument, and thus must be applied to non-empty 'ByteString's.
foldl1 :: HasCallStack => (Word8 -> Word8 -> Word8) -> ByteString -> Word8
foldl1 :: HasCallStack => (Word8 -> Word8 -> Word8) -> ByteString -> Word8
foldl1 Word8 -> Word8 -> Word8
_ ByteString
Empty        = String -> Word8
forall a. HasCallStack => String -> a
errorEmptyList String
"foldl1"
foldl1 Word8 -> Word8 -> Word8
f (Chunk ByteString
c ByteString
cs) = Word8 -> ByteString -> ByteString -> Word8
go (ByteString -> Word8
S.unsafeHead ByteString
c) (ByteString -> ByteString
S.unsafeTail ByteString
c) ByteString
cs
  where
    go :: Word8 -> ByteString -> ByteString -> Word8
go Word8
v ByteString
x ByteString
xs = let v' :: Word8
v' = (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> Word8
forall a. (a -> Word8 -> a) -> a -> ByteString -> a
S.foldl Word8 -> Word8 -> Word8
f Word8
v ByteString
x
      in case ByteString
xs of
      ByteString
Empty -> Word8
v'
      Chunk ByteString
x' ByteString
xs' -> Word8 -> ByteString -> ByteString -> Word8
go Word8
v' ByteString
x' ByteString
xs'

-- | 'foldl1'' is like 'foldl1', but strict in the accumulator.
foldl1' :: HasCallStack => (Word8 -> Word8 -> Word8) -> ByteString -> Word8
foldl1' :: HasCallStack => (Word8 -> Word8 -> Word8) -> ByteString -> Word8
foldl1' Word8 -> Word8 -> Word8
_ ByteString
Empty        = String -> Word8
forall a. HasCallStack => String -> a
errorEmptyList String
"foldl1'"
foldl1' Word8 -> Word8 -> Word8
f (Chunk ByteString
c ByteString
cs) = Word8 -> ByteString -> ByteString -> Word8
go (ByteString -> Word8
S.unsafeHead ByteString
c) (ByteString -> ByteString
S.unsafeTail ByteString
c) ByteString
cs
  where
    go :: Word8 -> ByteString -> ByteString -> Word8
go !Word8
v ByteString
x ByteString
xs = let v' :: Word8
v' = (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> Word8
forall a. (a -> Word8 -> a) -> a -> ByteString -> a
S.foldl' Word8 -> Word8 -> Word8
f Word8
v ByteString
x
      in case ByteString
xs of
      ByteString
Empty -> Word8
v'
      Chunk ByteString
x' ByteString
xs' -> Word8 -> ByteString -> ByteString -> Word8
go Word8
v' ByteString
x' ByteString
xs'

-- | 'foldr1' is a variant of 'foldr' that has no starting value argument,
-- and thus must be applied to non-empty 'ByteString's
foldr1 :: HasCallStack => (Word8 -> Word8 -> Word8) -> ByteString -> Word8
foldr1 :: HasCallStack => (Word8 -> Word8 -> Word8) -> ByteString -> Word8
foldr1 Word8 -> Word8 -> Word8
_ ByteString
Empty          = String -> Word8
forall a. HasCallStack => String -> a
errorEmptyList String
"foldr1"
foldr1 Word8 -> Word8 -> Word8
f (Chunk ByteString
c0 ByteString
cs0) = ByteString -> ByteString -> Word8
go ByteString
c0 ByteString
cs0
  where go :: ByteString -> ByteString -> Word8
go ByteString
c ByteString
Empty         = HasCallStack => (Word8 -> Word8 -> Word8) -> ByteString -> Word8
(Word8 -> Word8 -> Word8) -> ByteString -> Word8
S.foldr1 Word8 -> Word8 -> Word8
f ByteString
c
        go ByteString
c (Chunk ByteString
c' ByteString
cs) = (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> Word8
forall a. (Word8 -> a -> a) -> a -> ByteString -> a
S.foldr  Word8 -> Word8 -> Word8
f (ByteString -> ByteString -> Word8
go ByteString
c' ByteString
cs) ByteString
c

-- | 'foldr1'' is like 'foldr1', but strict in the accumulator.
--
-- @since 0.11.2.0
foldr1' :: HasCallStack => (Word8 -> Word8 -> Word8) -> ByteString -> Word8
foldr1' :: HasCallStack => (Word8 -> Word8 -> Word8) -> ByteString -> Word8
foldr1' Word8 -> Word8 -> Word8
_ ByteString
Empty          = String -> Word8
forall a. HasCallStack => String -> a
errorEmptyList String
"foldr1'"
foldr1' Word8 -> Word8 -> Word8
f (Chunk ByteString
c0 ByteString
cs0) = ByteString -> ByteString -> Word8
go ByteString
c0 ByteString
cs0
  where go :: ByteString -> ByteString -> Word8
go ByteString
c ByteString
Empty         = HasCallStack => (Word8 -> Word8 -> Word8) -> ByteString -> Word8
(Word8 -> Word8 -> Word8) -> ByteString -> Word8
S.foldr1' Word8 -> Word8 -> Word8
f ByteString
c
        go ByteString
c (Chunk ByteString
c' ByteString
cs) = (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> Word8
forall a. (Word8 -> a -> a) -> a -> ByteString -> a
S.foldr'  Word8 -> Word8 -> Word8
f (ByteString -> ByteString -> Word8
go ByteString
c' ByteString
cs) ByteString
c

-- ---------------------------------------------------------------------
-- Special folds

-- | /O(n)/ Concatenate a list of ByteStrings.
concat :: [ByteString] -> ByteString
concat :: [ByteString] -> ByteString
concat = [ByteString] -> ByteString
forall a. Monoid a => [a] -> a
mconcat

-- | Map a function over a 'ByteString' and concatenate the results
concatMap :: (Word8 -> ByteString) -> ByteString -> ByteString
concatMap :: (Word8 -> ByteString) -> ByteString -> ByteString
concatMap Word8 -> ByteString
_ ByteString
Empty        = ByteString
Empty
concatMap Word8 -> ByteString
f (Chunk ByteString
c0 ByteString
cs0) = ByteString -> ByteString -> ByteString
to ByteString
c0 ByteString
cs0
  where
    go :: ByteString -> P.ByteString -> ByteString -> ByteString
    go :: ByteString -> ByteString -> ByteString -> ByteString
go ByteString
Empty        ByteString
c' ByteString
cs' = ByteString -> ByteString -> ByteString
to ByteString
c' ByteString
cs'
    go (Chunk ByteString
c ByteString
cs) ByteString
c' ByteString
cs' = ByteString -> ByteString -> ByteString
Chunk ByteString
c (ByteString -> ByteString -> ByteString -> ByteString
go ByteString
cs ByteString
c' ByteString
cs')

    to :: P.ByteString -> ByteString -> ByteString
    to :: ByteString -> ByteString -> ByteString
to ByteString
c ByteString
cs | ByteString -> Bool
S.null ByteString
c  = case ByteString
cs of
        ByteString
Empty          -> ByteString
Empty
        (Chunk ByteString
c' ByteString
cs') -> ByteString -> ByteString -> ByteString
to ByteString
c' ByteString
cs'
            | Bool
otherwise = ByteString -> ByteString -> ByteString -> ByteString
go (Word8 -> ByteString
f (ByteString -> Word8
S.unsafeHead ByteString
c)) (ByteString -> ByteString
S.unsafeTail ByteString
c) ByteString
cs

-- | /O(n)/ Applied to a predicate and a ByteString, 'any' determines if
-- any element of the 'ByteString' satisfies the predicate.
any :: (Word8 -> Bool) -> ByteString -> Bool
any :: (Word8 -> Bool) -> ByteString -> Bool
any Word8 -> Bool
f = (ByteString -> Bool -> Bool) -> Bool -> ByteString -> Bool
forall a. (ByteString -> a -> a) -> a -> ByteString -> a
foldrChunks (\ByteString
c Bool
rest -> (Word8 -> Bool) -> ByteString -> Bool
S.any Word8 -> Bool
f ByteString
c Bool -> Bool -> Bool
|| Bool
rest) Bool
False
{-# INLINE any #-}

-- | /O(n)/ Applied to a predicate and a 'ByteString', 'all' determines
-- if all elements of the 'ByteString' satisfy the predicate.
all :: (Word8 -> Bool) -> ByteString -> Bool
all :: (Word8 -> Bool) -> ByteString -> Bool
all Word8 -> Bool
f = (ByteString -> Bool -> Bool) -> Bool -> ByteString -> Bool
forall a. (ByteString -> a -> a) -> a -> ByteString -> a
foldrChunks (\ByteString
c Bool
rest -> (Word8 -> Bool) -> ByteString -> Bool
S.all Word8 -> Bool
f ByteString
c Bool -> Bool -> Bool
&& Bool
rest) Bool
True
{-# INLINE all #-}

-- | /O(n)/ 'maximum' returns the maximum value from a 'ByteString'
maximum :: HasCallStack => ByteString -> Word8
maximum :: HasCallStack => ByteString -> Word8
maximum ByteString
Empty        = String -> Word8
forall a. HasCallStack => String -> a
errorEmptyList String
"maximum"
maximum (Chunk ByteString
c ByteString
cs) = (Word8 -> ByteString -> Word8) -> Word8 -> ByteString -> Word8
forall a. (a -> ByteString -> a) -> a -> ByteString -> a
foldlChunks (\Word8
n ByteString
c' -> Word8
n Word8 -> Word8 -> Word8
forall a. Ord a => a -> a -> a
`max` HasCallStack => ByteString -> Word8
ByteString -> Word8
S.maximum ByteString
c')
                                   (HasCallStack => ByteString -> Word8
ByteString -> Word8
S.maximum ByteString
c) ByteString
cs
{-# INLINE maximum #-}

-- | /O(n)/ 'minimum' returns the minimum value from a 'ByteString'
minimum :: HasCallStack => ByteString -> Word8
minimum :: HasCallStack => ByteString -> Word8
minimum ByteString
Empty        = String -> Word8
forall a. HasCallStack => String -> a
errorEmptyList String
"minimum"
minimum (Chunk ByteString
c ByteString
cs) = (Word8 -> ByteString -> Word8) -> Word8 -> ByteString -> Word8
forall a. (a -> ByteString -> a) -> a -> ByteString -> a
foldlChunks (\Word8
n ByteString
c' -> Word8
n Word8 -> Word8 -> Word8
forall a. Ord a => a -> a -> a
`min` HasCallStack => ByteString -> Word8
ByteString -> Word8
S.minimum ByteString
c')
                                     (HasCallStack => ByteString -> Word8
ByteString -> Word8
S.minimum ByteString
c) ByteString
cs
{-# INLINE minimum #-}

-- | /O(c)/ 'compareLength' compares the length of a 'ByteString'
-- to an 'Int64'
--
-- @since 0.11.1.0
compareLength :: ByteString -> Int64 -> Ordering
compareLength :: ByteString -> Int64 -> Ordering
compareLength ByteString
_ Int64
toCmp | Int64
toCmp Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< Int64
0 = Ordering
GT
compareLength ByteString
Empty Int64
toCmp         = Int64 -> Int64 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Int64
0 Int64
toCmp
compareLength (Chunk ByteString
c ByteString
cs) Int64
toCmp  = ByteString -> Int64 -> Ordering
compareLength ByteString
cs (Int64
toCmp Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
- Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
S.length ByteString
c))
{-# INLINE compareLength #-}

{-# RULES
"ByteString.Lazy length/compareN -> compareLength" [~1] forall t n.
  compare (length t) n = compareLength t n
"ByteString.Lazy compareN/length -> compareLength" [~1] forall t n.
  -- compare EQ LT = GT and vice versa
  compare n (length t) = compare EQ $ compareLength t n
"ByteString.Lazy length/==N -> compareLength/==EQ" [~1] forall t n.
   length t == n = compareLength t n == EQ
"ByteString.Lazy N==/length -> compareLength/==EQ" [~1] forall t n.
   n == length t = compareLength t n == EQ
"ByteString.Lazy length//=N -> compareLength//=EQ" [~1] forall t n.
   length t /= n = compareLength t n /= EQ
"ByteString.Lazy N/=/length -> compareLength//=EQ" [~1] forall t n.
   n /= length t = compareLength t n /= EQ
"ByteString.Lazy length/<N -> compareLength/==LT" [~1] forall t n.
   length t < n = compareLength t n == LT
"ByteString.Lazy >N/length -> compareLength/==LT" [~1] forall t n.
   n > length t = compareLength t n == LT
"ByteString.Lazy length/<=N -> compareLength//=GT" [~1] forall t n.
   length t <= n = compareLength t n /= GT
"ByteString.Lazy <=N/length -> compareLength//=GT" [~1] forall t n.
   n >= length t = compareLength t n /= GT
"ByteString.Lazy length/>N -> compareLength/==GT" [~1] forall t n.
   length t > n = compareLength t n == GT
"ByteString.Lazy <N/length -> compareLength/==GT" [~1] forall t n.
   n < length t = compareLength t n == GT
"ByteString.Lazy length/>=N -> compareLength//=LT" [~1] forall t n.
   length t >= n = compareLength t n /= LT
"ByteString.Lazy >=N/length -> compareLength//=LT" [~1] forall t n.
   n <= length t = compareLength t n /= LT
  #-}

-- | The 'mapAccumL' function behaves like a combination of 'map' and
-- 'foldl'; it applies a function to each element of a ByteString,
-- passing an accumulating parameter from left to right, and returning a
-- final value of this accumulator together with the new ByteString.
mapAccumL :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)
mapAccumL :: forall acc.
(acc -> Word8 -> (acc, Word8))
-> acc -> ByteString -> (acc, ByteString)
mapAccumL acc -> Word8 -> (acc, Word8)
f = acc -> ByteString -> (acc, ByteString)
go
  where
    go :: acc -> ByteString -> (acc, ByteString)
go acc
s ByteString
Empty        = (acc
s, ByteString
Empty)
    go acc
s (Chunk ByteString
c ByteString
cs) = (acc
s'', ByteString -> ByteString -> ByteString
Chunk ByteString
c' ByteString
cs')
        where (acc
s',  ByteString
c')  = (acc -> Word8 -> (acc, Word8))
-> acc -> ByteString -> (acc, ByteString)
forall acc.
(acc -> Word8 -> (acc, Word8))
-> acc -> ByteString -> (acc, ByteString)
S.mapAccumL acc -> Word8 -> (acc, Word8)
f acc
s ByteString
c
              (acc
s'', ByteString
cs') = acc -> ByteString -> (acc, ByteString)
go acc
s' ByteString
cs

-- | The 'mapAccumR' function behaves like a combination of 'map' and
-- 'foldr'; it applies a function to each element of a ByteString,
-- passing an accumulating parameter from right to left, and returning a
-- final value of this accumulator together with the new ByteString.
mapAccumR :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)
mapAccumR :: forall acc.
(acc -> Word8 -> (acc, Word8))
-> acc -> ByteString -> (acc, ByteString)
mapAccumR acc -> Word8 -> (acc, Word8)
f = acc -> ByteString -> (acc, ByteString)
go
  where
    go :: acc -> ByteString -> (acc, ByteString)
go acc
s ByteString
Empty        = (acc
s, ByteString
Empty)
    go acc
s (Chunk ByteString
c ByteString
cs) = (acc
s'', ByteString -> ByteString -> ByteString
Chunk ByteString
c' ByteString
cs')
        where (acc
s'', ByteString
c') = (acc -> Word8 -> (acc, Word8))
-> acc -> ByteString -> (acc, ByteString)
forall acc.
(acc -> Word8 -> (acc, Word8))
-> acc -> ByteString -> (acc, ByteString)
S.mapAccumR acc -> Word8 -> (acc, Word8)
f acc
s' ByteString
c
              (acc
s', ByteString
cs') = acc -> ByteString -> (acc, ByteString)
go acc
s ByteString
cs

-- ---------------------------------------------------------------------
-- Building ByteStrings

-- | 'scanl' is similar to 'foldl', but returns a list of successive
-- reduced values from the left.
--
-- > scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]
--
-- Note that
--
-- > head (scanl f z xs) == z
-- > last (scanl f z xs) == foldl f z xs
--
scanl
    :: (Word8 -> Word8 -> Word8)
    -- ^ accumulator -> element -> new accumulator
    -> Word8
    -- ^ starting value of accumulator
    -> ByteString
    -- ^ input of length n
    -> ByteString
    -- ^ output of length n+1
scanl :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString
scanl Word8 -> Word8 -> Word8
function = ((Word8, ByteString) -> ByteString)
-> (ByteString -> (Word8, ByteString)) -> ByteString -> ByteString
forall a b. (a -> b) -> (ByteString -> a) -> ByteString -> b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Word8 -> ByteString -> ByteString)
-> (Word8, ByteString) -> ByteString
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry ((ByteString -> Word8 -> ByteString)
-> Word8 -> ByteString -> ByteString
forall a b c. (a -> b -> c) -> b -> a -> c
flip ByteString -> Word8 -> ByteString
snoc)) ((ByteString -> (Word8, ByteString)) -> ByteString -> ByteString)
-> (Word8 -> ByteString -> (Word8, ByteString))
-> Word8
-> ByteString
-> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word8 -> Word8 -> (Word8, Word8))
-> Word8 -> ByteString -> (Word8, ByteString)
forall acc.
(acc -> Word8 -> (acc, Word8))
-> acc -> ByteString -> (acc, ByteString)
mapAccumL (\Word8
x Word8
y -> (Word8 -> Word8 -> Word8
function Word8
x Word8
y, Word8
x))
{-# INLINE scanl #-}

-- | 'scanl1' is a variant of 'scanl' that has no starting value argument.
--
-- > scanl1 f [x1, x2, ...] == [x1, x1 `f` x2, ...]
--
-- @since 0.11.2.0
scanl1 :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString
scanl1 :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString
scanl1 Word8 -> Word8 -> Word8
function ByteString
byteStream = case ByteString -> Maybe (Word8, ByteString)
uncons ByteString
byteStream of
  Maybe (Word8, ByteString)
Nothing -> ByteString
Empty
  Just (Word8
firstByte, ByteString
remainingBytes) -> (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString
scanl Word8 -> Word8 -> Word8
function Word8
firstByte ByteString
remainingBytes

-- | 'scanr' is similar to 'foldr', but returns a list of successive
-- reduced values from the right.
--
-- > scanr f z [..., x{n-1}, xn] == [..., x{n-1} `f` (xn `f` z), xn `f` z, z]
--
-- Note that
--
-- > head (scanr f z xs) == foldr f z xs
-- > last (scanr f z xs) == z
--
-- @since 0.11.2.0
scanr
    :: (Word8 -> Word8 -> Word8)
    -- ^ element -> accumulator -> new accumulator
    -> Word8
    -- ^ starting value of accumulator
    -> ByteString
    -- ^ input of length n
    -> ByteString
    -- ^ output of length n+1
scanr :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString
scanr Word8 -> Word8 -> Word8
function = ((Word8, ByteString) -> ByteString)
-> (ByteString -> (Word8, ByteString)) -> ByteString -> ByteString
forall a b. (a -> b) -> (ByteString -> a) -> ByteString -> b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Word8 -> ByteString -> ByteString)
-> (Word8, ByteString) -> ByteString
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Word8 -> ByteString -> ByteString
cons) ((ByteString -> (Word8, ByteString)) -> ByteString -> ByteString)
-> (Word8 -> ByteString -> (Word8, ByteString))
-> Word8
-> ByteString
-> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word8 -> Word8 -> (Word8, Word8))
-> Word8 -> ByteString -> (Word8, ByteString)
forall acc.
(acc -> Word8 -> (acc, Word8))
-> acc -> ByteString -> (acc, ByteString)
mapAccumR (\Word8
x Word8
y -> (Word8 -> Word8 -> Word8
function Word8
y Word8
x, Word8
x))

-- | 'scanr1' is a variant of 'scanr' that has no starting value argument.
--
-- @since 0.11.2.0
scanr1 :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString
scanr1 :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString
scanr1 Word8 -> Word8 -> Word8
function ByteString
byteStream = case ByteString -> Maybe (ByteString, Word8)
unsnoc ByteString
byteStream of
  Maybe (ByteString, Word8)
Nothing -> ByteString
Empty
  Just (ByteString
initialBytes, Word8
lastByte) -> (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString
scanr Word8 -> Word8 -> Word8
function Word8
lastByte ByteString
initialBytes

-- ---------------------------------------------------------------------
-- Unfolds and replicates

-- | @'iterate' f x@ returns an infinite ByteString of repeated applications
-- of @f@ to @x@:
--
-- > iterate f x == [x, f x, f (f x), ...]
--
iterate :: (Word8 -> Word8) -> Word8 -> ByteString
iterate :: (Word8 -> Word8) -> Word8 -> ByteString
iterate Word8 -> Word8
f = (Word8 -> Maybe (Word8, Word8)) -> Word8 -> ByteString
forall a. (a -> Maybe (Word8, a)) -> a -> ByteString
unfoldr (\Word8
x -> case Word8 -> Word8
f Word8
x of !Word8
x' -> (Word8, Word8) -> Maybe (Word8, Word8)
forall a. a -> Maybe a
Just (Word8
x', Word8
x'))

-- | @'repeat' x@ is an infinite ByteString, with @x@ the value of every
-- element.
--
repeat :: Word8 -> ByteString
repeat :: Word8 -> ByteString
repeat Word8
w = ByteString
cs where cs :: ByteString
cs = ByteString -> ByteString -> ByteString
Chunk (Int -> Word8 -> ByteString
S.replicate Int
smallChunkSize Word8
w) ByteString
cs

-- | /O(n)/ @'replicate' n x@ is a ByteString of length @n@ with @x@
-- the value of every element.
--
replicate :: Int64 -> Word8 -> ByteString
replicate :: Int64 -> Word8 -> ByteString
replicate Int64
n Word8
w
    | Int64
n Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
0             = ByteString
Empty
    | Int64
n Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
smallChunkSize = ByteString -> ByteString -> ByteString
Chunk (Int -> Word8 -> ByteString
S.replicate (Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
n) Word8
w) ByteString
Empty
    | Int64
r Int64 -> Int64 -> Bool
forall a. Eq a => a -> a -> Bool
== Int64
0             = ByteString
cs -- preserve invariant
    | Bool
otherwise          = ByteString -> ByteString -> ByteString
Chunk (Int -> ByteString -> ByteString
S.unsafeTake (Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
r) ByteString
c) ByteString
cs
 where
    c :: ByteString
c      = Int -> Word8 -> ByteString
S.replicate Int
smallChunkSize Word8
w
    cs :: ByteString
cs     = Int64 -> ByteString
forall {t}. (Eq t, Num t) => t -> ByteString
nChunks Int64
q
    (Int64
q, Int64
r) = Int64 -> Int64 -> (Int64, Int64)
forall a. Integral a => a -> a -> (a, a)
quotRem Int64
n (Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
smallChunkSize)
    nChunks :: t -> ByteString
nChunks t
0 = ByteString
Empty
    nChunks t
m = ByteString -> ByteString -> ByteString
Chunk ByteString
c (t -> ByteString
nChunks (t
mt -> t -> t
forall a. Num a => a -> a -> a
-t
1))

-- | 'cycle' ties a finite ByteString into a circular one, or equivalently,
-- the infinite repetition of the original ByteString.
--
cycle :: HasCallStack => ByteString -> ByteString
cycle :: HasCallStack => ByteString -> ByteString
cycle ByteString
Empty = String -> ByteString
forall a. HasCallStack => String -> a
errorEmptyList String
"cycle"
cycle ByteString
cs    = ByteString
cs' where cs' :: ByteString
cs' = (ByteString -> ByteString -> ByteString)
-> ByteString -> ByteString -> ByteString
forall a. (ByteString -> a -> a) -> a -> ByteString -> a
foldrChunks ByteString -> ByteString -> ByteString
Chunk ByteString
cs' ByteString
cs

-- | /O(n)/ The 'unfoldr' function is analogous to the List \'unfoldr\'.
-- 'unfoldr' builds a ByteString from a seed value.  The function takes
-- the element and returns 'Nothing' if it is done producing the
-- ByteString or returns 'Just' @(a,b)@, in which case, @a@ is a
-- prepending to the ByteString and @b@ is used as the next element in a
-- recursive call.
unfoldr :: (a -> Maybe (Word8, a)) -> a -> ByteString
unfoldr :: forall a. (a -> Maybe (Word8, a)) -> a -> ByteString
unfoldr a -> Maybe (Word8, a)
f = Int -> a -> ByteString
unfoldChunk Int
32
  where unfoldChunk :: Int -> a -> ByteString
unfoldChunk Int
n a
x =
          case Int -> (a -> Maybe (Word8, a)) -> a -> (ByteString, Maybe a)
forall a.
Int -> (a -> Maybe (Word8, a)) -> a -> (ByteString, Maybe a)
S.unfoldrN Int
n a -> Maybe (Word8, a)
f a
x of
            (ByteString
c, Maybe a
Nothing)
              | ByteString -> Bool
S.null ByteString
c  -> ByteString
Empty
              | Bool
otherwise -> ByteString -> ByteString -> ByteString
Chunk ByteString
c ByteString
Empty
            (ByteString
c, Just a
x')  -> ByteString -> ByteString -> ByteString
Chunk ByteString
c (Int -> a -> ByteString
unfoldChunk (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
*Int
2) a
x')

-- ---------------------------------------------------------------------
-- Substrings

-- | /O(n\/c)/ 'take' @n@, applied to a ByteString @xs@, returns the prefix
-- of @xs@ of length @n@, or @xs@ itself if @n > 'length' xs@.
take :: Int64 -> ByteString -> ByteString
take :: Int64 -> ByteString -> ByteString
take Int64
i ByteString
_ | Int64
i Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
0 = ByteString
Empty
take Int64
i ByteString
cs0         = Int64 -> ByteString -> ByteString
forall {t}. Integral t => t -> ByteString -> ByteString
take' Int64
i ByteString
cs0
  where take' :: t -> ByteString -> ByteString
take' t
0 ByteString
_            = ByteString
Empty
        take' t
_ ByteString
Empty        = ByteString
Empty
        take' t
n (Chunk ByteString
c ByteString
cs) =
          if t
n t -> t -> Bool
forall a. Ord a => a -> a -> Bool
< Int -> t
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
S.length ByteString
c)
            then ByteString -> ByteString -> ByteString
Chunk (Int -> ByteString -> ByteString
S.take (t -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral t
n) ByteString
c) ByteString
Empty
            else ByteString -> ByteString -> ByteString
Chunk ByteString
c (t -> ByteString -> ByteString
take' (t
n t -> t -> t
forall a. Num a => a -> a -> a
- Int -> t
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
S.length ByteString
c)) ByteString
cs)

-- | /O(c)/ @'takeEnd' n xs@ is equivalent to @'drop' ('length' xs - n) xs@.
-- Takes @n@ elements from end of bytestring.
--
-- >>> takeEnd 3 "abcdefg"
-- "efg"
-- >>> takeEnd 0 "abcdefg"
-- ""
-- >>> takeEnd 4 "abc"
-- "abc"
--
-- @since 0.11.2.0
takeEnd :: Int64 -> ByteString -> ByteString
takeEnd :: Int64 -> ByteString -> ByteString
takeEnd Int64
i ByteString
_ | Int64
i Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
0 = ByteString
Empty
takeEnd Int64
i ByteString
cs0        = Int64 -> ByteString -> ByteString
forall {t}. Integral t => t -> ByteString -> ByteString
takeEnd' Int64
i ByteString
cs0
  where takeEnd' :: a -> ByteString -> ByteString
takeEnd' a
0 ByteString
_         = ByteString
Empty
        takeEnd' a
n ByteString
cs        =
            (a, ByteString) -> ByteString
forall a b. (a, b) -> b
snd ((a, ByteString) -> ByteString) -> (a, ByteString) -> ByteString
forall a b. (a -> b) -> a -> b
$ (ByteString -> (a, ByteString) -> (a, ByteString))
-> (a, ByteString) -> ByteString -> (a, ByteString)
forall a. (ByteString -> a -> a) -> a -> ByteString -> a
foldrChunks ByteString -> (a, ByteString) -> (a, ByteString)
forall {a}.
Integral a =>
ByteString -> (a, ByteString) -> (a, ByteString)
takeTuple (a
n,ByteString
Empty) ByteString
cs
        takeTuple :: ByteString -> (a, ByteString) -> (a, ByteString)
takeTuple ByteString
_ (a
0, ByteString
cs)  = (a
0, ByteString
cs)
        takeTuple ByteString
c (a
n, ByteString
cs)
            | a
n a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
S.length ByteString
c) = (a
n a -> a -> a
forall a. Num a => a -> a -> a
- Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
S.length ByteString
c), ByteString -> ByteString -> ByteString
Chunk ByteString
c ByteString
cs)
            | Bool
otherwise      = (a
0, ByteString -> ByteString -> ByteString
Chunk (Int -> ByteString -> ByteString
S.takeEnd (a -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
n) ByteString
c) ByteString
cs)

-- | /O(n\/c)/ 'drop' @n xs@ returns the suffix of @xs@ after the first @n@
-- elements, or 'empty' if @n > 'length' xs@.
drop  :: Int64 -> ByteString -> ByteString
drop :: Int64 -> ByteString -> ByteString
drop Int64
i ByteString
p | Int64
i Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
0 = ByteString
p
drop Int64
i ByteString
cs0 = Int64 -> ByteString -> ByteString
forall {t}. Integral t => t -> ByteString -> ByteString
drop' Int64
i ByteString
cs0
  where drop' :: t -> ByteString -> ByteString
drop' t
0 ByteString
cs           = ByteString
cs
        drop' t
_ ByteString
Empty        = ByteString
Empty
        drop' t
n (Chunk ByteString
c ByteString
cs) =
          if t
n t -> t -> Bool
forall a. Ord a => a -> a -> Bool
< Int -> t
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
S.length ByteString
c)
            then ByteString -> ByteString -> ByteString
Chunk (Int -> ByteString -> ByteString
S.drop (t -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral t
n) ByteString
c) ByteString
cs
            else t -> ByteString -> ByteString
drop' (t
n t -> t -> t
forall a. Num a => a -> a -> a
- Int -> t
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
S.length ByteString
c)) ByteString
cs

-- | /O(n)/ @'dropEnd' n xs@ is equivalent to @'take' ('length' xs - n) xs@.
-- Drops @n@ elements from end of bytestring.
--
-- >>> dropEnd 3 "abcdefg"
-- "abcd"
-- >>> dropEnd 0 "abcdefg"
-- "abcdefg"
-- >>> dropEnd 4 "abc"
-- ""
--
-- @since 0.11.2.0
dropEnd :: Int64 -> ByteString -> ByteString
dropEnd :: Int64 -> ByteString -> ByteString
dropEnd Int64
i ByteString
p | Int64
i Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
0 = ByteString
p
dropEnd Int64
i ByteString
p          = Deque -> ByteString -> ByteString
go Deque
D.empty ByteString
p
  where go :: D.Deque -> ByteString -> ByteString
        go :: Deque -> ByteString -> ByteString
go Deque
deque (Chunk ByteString
c ByteString
cs)
            | Deque -> Int64
D.byteLength Deque
deque Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< Int64
i = Deque -> ByteString -> ByteString
go (ByteString -> Deque -> Deque
D.snoc ByteString
c Deque
deque) ByteString
cs
            | Bool
otherwise              =
                  let (ByteString
output, Deque
deque') = ByteString -> Deque -> (ByteString, Deque)
getOutput ByteString
empty (ByteString -> Deque -> Deque
D.snoc ByteString
c Deque
deque)
                    in (ByteString -> ByteString -> ByteString)
-> ByteString -> ByteString -> ByteString
forall a. (ByteString -> a -> a) -> a -> ByteString -> a
foldrChunks ByteString -> ByteString -> ByteString
Chunk (Deque -> ByteString -> ByteString
go Deque
deque' ByteString
cs) ByteString
output
        go Deque
deque ByteString
Empty               = Deque -> ByteString
fromDeque (Deque -> ByteString) -> Deque -> ByteString
forall a b. (a -> b) -> a -> b
$ Deque -> Int64 -> Deque
dropEndBytes Deque
deque Int64
i

        len :: ByteString -> b
len ByteString
c = Int -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
S.length ByteString
c)

        -- get a `ByteString` from all the front chunks of the accumulating deque
        -- for which we know they won't be dropped
        getOutput :: ByteString -> D.Deque -> (ByteString, D.Deque)
        getOutput :: ByteString -> Deque -> (ByteString, Deque)
getOutput ByteString
out Deque
deque = case Deque -> Maybe (ByteString, Deque)
D.popFront Deque
deque of
            Maybe (ByteString, Deque)
Nothing                       -> (ByteString -> ByteString
reverseChunks ByteString
out, Deque
deque)
            Just (ByteString
x, Deque
deque') | Deque -> Int64
D.byteLength Deque
deque' Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
>= Int64
i ->
                            ByteString -> Deque -> (ByteString, Deque)
getOutput (ByteString -> ByteString -> ByteString
Chunk ByteString
x ByteString
out) Deque
deque'
            Maybe (ByteString, Deque)
_ -> (ByteString -> ByteString
reverseChunks ByteString
out, Deque
deque)

        -- reverse a `ByteString`s chunks, keeping all internal `S.ByteString`s
        -- unchanged
        reverseChunks :: ByteString -> ByteString
reverseChunks = (ByteString -> ByteString -> ByteString)
-> ByteString -> ByteString -> ByteString
forall a. (a -> ByteString -> a) -> a -> ByteString -> a
foldlChunks ((ByteString -> ByteString -> ByteString)
-> ByteString -> ByteString -> ByteString
forall a b c. (a -> b -> c) -> b -> a -> c
flip ByteString -> ByteString -> ByteString
Chunk) ByteString
empty

        -- drop n elements from the rear of the accumulating `deque`
        dropEndBytes :: D.Deque -> Int64 -> D.Deque
        dropEndBytes :: Deque -> Int64 -> Deque
dropEndBytes Deque
deque Int64
n = case Deque -> Maybe (Deque, ByteString)
D.popRear Deque
deque of
            Maybe (Deque, ByteString)
Nothing                       -> Deque
deque
            Just (Deque
deque', ByteString
x) | ByteString -> Int64
forall {b}. Num b => ByteString -> b
len ByteString
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
n -> Deque -> Int64 -> Deque
dropEndBytes Deque
deque' (Int64
n Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
- ByteString -> Int64
forall {b}. Num b => ByteString -> b
len ByteString
x)
                             | Bool
otherwise  ->
                                ByteString -> Deque -> Deque
D.snoc (Int -> ByteString -> ByteString
S.dropEnd (Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
n) ByteString
x) Deque
deque'

        -- build a lazy ByteString from an accumulating `deque`
        fromDeque :: D.Deque -> ByteString
        fromDeque :: Deque -> ByteString
fromDeque Deque
deque =
            (ByteString -> ByteString -> ByteString)
-> ByteString -> [ByteString] -> ByteString
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
List.foldr ByteString -> ByteString -> ByteString
chunk ByteString
Empty (Deque -> [ByteString]
D.front Deque
deque) ByteString -> ByteString -> ByteString
`append`
            (ByteString -> ByteString -> ByteString)
-> ByteString -> [ByteString] -> ByteString
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl' ((ByteString -> ByteString -> ByteString)
-> ByteString -> ByteString -> ByteString
forall a b c. (a -> b -> c) -> b -> a -> c
flip ByteString -> ByteString -> ByteString
chunk) ByteString
Empty (Deque -> [ByteString]
D.rear Deque
deque)

-- | /O(n\/c)/ 'splitAt' @n xs@ is equivalent to @('take' n xs, 'drop' n xs)@.
splitAt :: Int64 -> ByteString -> (ByteString, ByteString)
splitAt :: Int64 -> ByteString -> (ByteString, ByteString)
splitAt Int64
i ByteString
cs0 | Int64
i Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int64
0 = (ByteString
Empty, ByteString
cs0)
splitAt Int64
i ByteString
cs0 = Int64 -> ByteString -> (ByteString, ByteString)
forall {a}.
Integral a =>
a -> ByteString -> (ByteString, ByteString)
splitAt' Int64
i ByteString
cs0
  where splitAt' :: a -> ByteString -> (ByteString, ByteString)
splitAt' a
0 ByteString
cs           = (ByteString
Empty, ByteString
cs)
        splitAt' a
_ ByteString
Empty        = (ByteString
Empty, ByteString
Empty)
        splitAt' a
n (Chunk ByteString
c ByteString
cs) =
          if a
n a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
S.length ByteString
c)
            then (ByteString -> ByteString -> ByteString
Chunk (Int -> ByteString -> ByteString
S.take (a -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
n) ByteString
c) ByteString
Empty
                 ,ByteString -> ByteString -> ByteString
Chunk (Int -> ByteString -> ByteString
S.drop (a -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
n) ByteString
c) ByteString
cs)
            else let (ByteString
cs', ByteString
cs'') = a -> ByteString -> (ByteString, ByteString)
splitAt' (a
n a -> a -> a
forall a. Num a => a -> a -> a
- Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
S.length ByteString
c)) ByteString
cs
                   in (ByteString -> ByteString -> ByteString
Chunk ByteString
c ByteString
cs', ByteString
cs'')


-- | Similar to 'Prelude.takeWhile',
-- returns the longest (possibly empty) prefix of elements
-- satisfying the predicate.
takeWhile :: (Word8 -> Bool) -> ByteString -> ByteString
takeWhile :: (Word8 -> Bool) -> ByteString -> ByteString
takeWhile Word8 -> Bool
f = ByteString -> ByteString
takeWhile'
  where takeWhile' :: ByteString -> ByteString
takeWhile' ByteString
Empty        = ByteString
Empty
        takeWhile' (Chunk ByteString
c ByteString
cs) =
          case (Word8 -> Bool) -> ByteString -> Int
S.findIndexOrLength (Bool -> Bool
not (Bool -> Bool) -> (Word8 -> Bool) -> Word8 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Bool
f) ByteString
c of
            Int
0                  -> ByteString
Empty
            Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< ByteString -> Int
S.length ByteString
c -> ByteString -> ByteString -> ByteString
Chunk (Int -> ByteString -> ByteString
S.take Int
n ByteString
c) ByteString
Empty
              | Bool
otherwise      -> ByteString -> ByteString -> ByteString
Chunk ByteString
c (ByteString -> ByteString
takeWhile' ByteString
cs)

-- | Returns the longest (possibly empty) suffix of elements
-- satisfying the predicate.
--
-- @'takeWhileEnd' p@ is equivalent to @'reverse' . 'takeWhile' p . 'reverse'@.
--
-- >>> {-# LANGUAGE OverloadedLists #-)
-- >>> takeWhileEnd even [1,2,3,4,6]
-- [4,6]
--
-- @since 0.11.2.0
takeWhileEnd :: (Word8 -> Bool) -> ByteString -> ByteString
takeWhileEnd :: (Word8 -> Bool) -> ByteString -> ByteString
takeWhileEnd Word8 -> Bool
f = ByteString -> ByteString
takeWhileEnd'
  where takeWhileEnd' :: ByteString -> ByteString
takeWhileEnd' ByteString
Empty = ByteString
Empty
        takeWhileEnd' ByteString
cs    =
            (Bool, ByteString) -> ByteString
forall a b. (a, b) -> b
snd ((Bool, ByteString) -> ByteString)
-> (Bool, ByteString) -> ByteString
forall a b. (a -> b) -> a -> b
$ (ByteString -> (Bool, ByteString) -> (Bool, ByteString))
-> (Bool, ByteString) -> ByteString -> (Bool, ByteString)
forall a. (ByteString -> a -> a) -> a -> ByteString -> a
foldrChunks ByteString -> (Bool, ByteString) -> (Bool, ByteString)
takeTuple (Bool
True,ByteString
Empty) ByteString
cs
        takeTuple :: ByteString -> (Bool, ByteString) -> (Bool, ByteString)
takeTuple ByteString
_ (Bool
False, ByteString
bs) = (Bool
False,ByteString
bs)
        takeTuple ByteString
c (Bool
True,ByteString
bs)   =
           case (Word8 -> Bool) -> ByteString -> ByteString
S.takeWhileEnd Word8 -> Bool
f ByteString
c of
                ByteString
c' | ByteString -> Int
S.length ByteString
c' Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString -> Int
S.length ByteString
c -> (Bool
True, ByteString -> ByteString -> ByteString
Chunk ByteString
c ByteString
bs)
                   | Bool
otherwise                 -> (Bool
False, ByteString -> ByteString
fromStrict ByteString
c' ByteString -> ByteString -> ByteString
`append` ByteString
bs)

-- | Similar to 'Prelude.dropWhile',
-- drops the longest (possibly empty) prefix of elements
-- satisfying the predicate and returns the remainder.
dropWhile :: (Word8 -> Bool) -> ByteString -> ByteString
dropWhile :: (Word8 -> Bool) -> ByteString -> ByteString
dropWhile Word8 -> Bool
f = ByteString -> ByteString
dropWhile'
  where dropWhile' :: ByteString -> ByteString
dropWhile' ByteString
Empty        = ByteString
Empty
        dropWhile' (Chunk ByteString
c ByteString
cs) =
          case (Word8 -> Bool) -> ByteString -> Int
S.findIndexOrLength (Bool -> Bool
not (Bool -> Bool) -> (Word8 -> Bool) -> Word8 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Bool
f) ByteString
c of
            Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< ByteString -> Int
S.length ByteString
c -> ByteString -> ByteString -> ByteString
Chunk (Int -> ByteString -> ByteString
S.drop Int
n ByteString
c) ByteString
cs
              | Bool
otherwise      -> ByteString -> ByteString
dropWhile' ByteString
cs

-- | Similar to 'Prelude.dropWhileEnd',
-- drops the longest (possibly empty) suffix of elements
-- satisfying the predicate and returns the remainder.
--
-- @'dropWhileEnd' p@ is equivalent to @'reverse' . 'dropWhile' p . 'reverse'@.
--
-- >>> {-# LANGUAGE OverloadedLists #-)
-- >>> dropWhileEnd even [1,2,3,4,6]
-- [1,2,3]
--
-- @since 0.11.2.0
dropWhileEnd :: (Word8 -> Bool) -> ByteString -> ByteString
dropWhileEnd :: (Word8 -> Bool) -> ByteString -> ByteString
dropWhileEnd Word8 -> Bool
f = [ByteString] -> ByteString -> ByteString
go []
  where go :: [ByteString] -> ByteString -> ByteString
go [ByteString]
acc (Chunk ByteString
c ByteString
cs)
            | Word8 -> Bool
f (HasCallStack => ByteString -> Word8
ByteString -> Word8
S.last ByteString
c) = [ByteString] -> ByteString -> ByteString
go (ByteString
c ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: [ByteString]
acc) ByteString
cs
            | Bool
otherwise    = (ByteString -> ByteString -> ByteString)
-> ByteString -> [ByteString] -> ByteString
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl ((ByteString -> ByteString -> ByteString)
-> ByteString -> ByteString -> ByteString
forall a b c. (a -> b -> c) -> b -> a -> c
flip ByteString -> ByteString -> ByteString
Chunk) ([ByteString] -> ByteString -> ByteString
go [] ByteString
cs) (ByteString
c ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: [ByteString]
acc)
        go [ByteString]
acc ByteString
Empty       = [ByteString] -> ByteString
dropEndBytes [ByteString]
acc
        dropEndBytes :: [ByteString] -> ByteString
dropEndBytes []         = ByteString
Empty
        dropEndBytes (ByteString
x : [ByteString]
xs)   =
            case (Word8 -> Bool) -> ByteString -> ByteString
S.dropWhileEnd Word8 -> Bool
f ByteString
x of
                 ByteString
x' | ByteString -> Bool
S.null ByteString
x' -> [ByteString] -> ByteString
dropEndBytes [ByteString]
xs
                    | Bool
otherwise -> (ByteString -> ByteString -> ByteString)
-> ByteString -> [ByteString] -> ByteString
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl' ((ByteString -> ByteString -> ByteString)
-> ByteString -> ByteString -> ByteString
forall a b c. (a -> b -> c) -> b -> a -> c
flip ByteString -> ByteString -> ByteString
Chunk) ByteString
Empty (ByteString
x' ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: [ByteString]
xs)

-- | Similar to 'Prelude.break',
-- returns the longest (possibly empty) prefix of elements which __do not__
-- satisfy the predicate and the remainder of the string.
--
-- 'break' @p@ is equivalent to @'span' (not . p)@ and to @('takeWhile' (not . p) &&& 'dropWhile' (not . p))@.
--
break :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
break :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
break Word8 -> Bool
f = ByteString -> (ByteString, ByteString)
break'
  where break' :: ByteString -> (ByteString, ByteString)
break' ByteString
Empty        = (ByteString
Empty, ByteString
Empty)
        break' (Chunk ByteString
c ByteString
cs) =
          case (Word8 -> Bool) -> ByteString -> Int
S.findIndexOrLength Word8 -> Bool
f ByteString
c of
            Int
0                  -> (ByteString
Empty, ByteString -> ByteString -> ByteString
Chunk ByteString
c ByteString
cs)
            Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< ByteString -> Int
S.length ByteString
c -> (ByteString -> ByteString -> ByteString
Chunk (Int -> ByteString -> ByteString
S.take Int
n ByteString
c) ByteString
Empty
                                  ,ByteString -> ByteString -> ByteString
Chunk (Int -> ByteString -> ByteString
S.drop Int
n ByteString
c) ByteString
cs)
              | Bool
otherwise      -> let (ByteString
cs', ByteString
cs'') = ByteString -> (ByteString, ByteString)
break' ByteString
cs
                                   in (ByteString -> ByteString -> ByteString
Chunk ByteString
c ByteString
cs', ByteString
cs'')


-- | Returns the longest (possibly empty) suffix of elements which __do not__
-- satisfy the predicate and the remainder of the string.
--
-- 'breakEnd' @p@ is equivalent to @'spanEnd' (not . p)@ and to @('takeWhileEnd' (not . p) &&& 'dropWhileEnd' (not . p))@.
--
-- @since 0.11.2.0
breakEnd :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
breakEnd :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
breakEnd  Word8 -> Bool
f = [ByteString] -> ByteString -> (ByteString, ByteString)
go []
  where go :: [ByteString] -> ByteString -> (ByteString, ByteString)
go [ByteString]
acc (Chunk ByteString
c ByteString
cs)
            | Word8 -> Bool
f (HasCallStack => ByteString -> Word8
ByteString -> Word8
S.last ByteString
c) = ((ByteString, ByteString)
 -> ByteString -> (ByteString, ByteString))
-> (ByteString, ByteString)
-> [ByteString]
-> (ByteString, ByteString)
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl ((ByteString
 -> (ByteString, ByteString) -> (ByteString, ByteString))
-> (ByteString, ByteString)
-> ByteString
-> (ByteString, ByteString)
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((ByteString
  -> (ByteString, ByteString) -> (ByteString, ByteString))
 -> (ByteString, ByteString)
 -> ByteString
 -> (ByteString, ByteString))
-> (ByteString
    -> (ByteString, ByteString) -> (ByteString, ByteString))
-> (ByteString, ByteString)
-> ByteString
-> (ByteString, ByteString)
forall a b. (a -> b) -> a -> b
$ (ByteString -> ByteString)
-> (ByteString, ByteString) -> (ByteString, ByteString)
forall a b c. (a -> b) -> (a, c) -> (b, c)
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
BF.first ((ByteString -> ByteString)
 -> (ByteString, ByteString) -> (ByteString, ByteString))
-> (ByteString -> ByteString -> ByteString)
-> ByteString
-> (ByteString, ByteString)
-> (ByteString, ByteString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString -> ByteString
Chunk) ([ByteString] -> ByteString -> (ByteString, ByteString)
go [] ByteString
cs) (ByteString
c ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: [ByteString]
acc)
            | Bool
otherwise = [ByteString] -> ByteString -> (ByteString, ByteString)
go (ByteString
c ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: [ByteString]
acc) ByteString
cs
        go [ByteString]
acc ByteString
Empty = [ByteString] -> (ByteString, ByteString)
dropEndBytes [ByteString]
acc
        dropEndBytes :: [ByteString] -> (ByteString, ByteString)
dropEndBytes [] = (ByteString
Empty, ByteString
Empty)
        dropEndBytes (ByteString
x : [ByteString]
xs) =
            case (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
S.breakEnd Word8 -> Bool
f ByteString
x of
                 (ByteString
x', ByteString
x'') | ByteString -> Bool
S.null ByteString
x' -> let (ByteString
y, ByteString
y') = [ByteString] -> (ByteString, ByteString)
dropEndBytes [ByteString]
xs
                                           in (ByteString
y, ByteString
y' ByteString -> ByteString -> ByteString
`append` ByteString -> ByteString
fromStrict ByteString
x)
                           | Bool
otherwise ->
                                ((ByteString, ByteString)
 -> ByteString -> (ByteString, ByteString))
-> (ByteString, ByteString)
-> [ByteString]
-> (ByteString, ByteString)
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl' ((ByteString
 -> (ByteString, ByteString) -> (ByteString, ByteString))
-> (ByteString, ByteString)
-> ByteString
-> (ByteString, ByteString)
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((ByteString
  -> (ByteString, ByteString) -> (ByteString, ByteString))
 -> (ByteString, ByteString)
 -> ByteString
 -> (ByteString, ByteString))
-> (ByteString
    -> (ByteString, ByteString) -> (ByteString, ByteString))
-> (ByteString, ByteString)
-> ByteString
-> (ByteString, ByteString)
forall a b. (a -> b) -> a -> b
$ (ByteString -> ByteString)
-> (ByteString, ByteString) -> (ByteString, ByteString)
forall a b c. (a -> b) -> (a, c) -> (b, c)
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
BF.first ((ByteString -> ByteString)
 -> (ByteString, ByteString) -> (ByteString, ByteString))
-> (ByteString -> ByteString -> ByteString)
-> ByteString
-> (ByteString, ByteString)
-> (ByteString, ByteString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString -> ByteString
Chunk) (ByteString -> ByteString
fromStrict ByteString
x', ByteString -> ByteString
fromStrict ByteString
x'') [ByteString]
xs


--
-- TODO
--
-- Add rules
--

{-
-- | 'breakByte' breaks its ByteString argument at the first occurrence
-- of the specified byte. It is more efficient than 'break' as it is
-- implemented with @memchr(3)@. I.e.
--
-- > break (==99) "abcd" == breakByte 99 "abcd" -- fromEnum 'c' == 99
--
breakByte :: Word8 -> ByteString -> (ByteString, ByteString)
breakByte c (LPS ps) = case (breakByte' ps) of (a,b) -> (LPS a, LPS b)
  where breakByte' []     = ([], [])
        breakByte' (x:xs) =
          case P.elemIndex c x of
            Just 0  -> ([], x : xs)
            Just n  -> (P.take n x : [], P.drop n x : xs)
            Nothing -> let (xs', xs'') = breakByte' xs
                        in (x : xs', xs'')

-- | 'spanByte' breaks its ByteString argument at the first
-- occurrence of a byte other than its argument. It is more efficient
-- than 'span (==)'
--
-- > span  (==99) "abcd" == spanByte 99 "abcd" -- fromEnum 'c' == 99
--
spanByte :: Word8 -> ByteString -> (ByteString, ByteString)
spanByte c (LPS ps) = case (spanByte' ps) of (a,b) -> (LPS a, LPS b)
  where spanByte' []     = ([], [])
        spanByte' (x:xs) =
          case P.spanByte c x of
            (x', x'') | P.null x'  -> ([], x : xs)
                      | P.null x'' -> let (xs', xs'') = spanByte' xs
                                       in (x : xs', xs'')
                      | otherwise  -> (x' : [], x'' : xs)
-}

-- | Similar to 'Prelude.span',
-- returns the longest (possibly empty) prefix of elements
-- satisfying the predicate and the remainder of the string.
--
-- 'span' @p@ is equivalent to @'break' (not . p)@ and to @('takeWhile' p &&& 'dropWhile' p)@.
--
span :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
span :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
span Word8 -> Bool
p = (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
break (Bool -> Bool
not (Bool -> Bool) -> (Word8 -> Bool) -> Word8 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Bool
p)

-- | Returns the longest (possibly empty) suffix of elements
-- satisfying the predicate and the remainder of the string.
--
-- 'spanEnd' @p@ is equivalent to @'breakEnd' (not . p)@ and to @('takeWhileEnd' p &&& 'dropWhileEnd' p)@.
--
-- We have
--
-- > spanEnd (not . isSpace) "x y z" == ("x y ", "z")
--
-- and
--
-- > spanEnd (not . isSpace) ps
-- >    ==
-- > let (x, y) = span (not . isSpace) (reverse ps) in (reverse y, reverse x)
--
-- @since 0.11.2.0
spanEnd :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
spanEnd :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
spanEnd Word8 -> Bool
p = (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
breakEnd (Bool -> Bool
not (Bool -> Bool) -> (Word8 -> Bool) -> Word8 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Bool
p)

-- | /O(n)/ Splits a 'ByteString' into components delimited by
-- separators, where the predicate returns True for a separator element.
-- The resulting components do not contain the separators.  Two adjacent
-- separators result in an empty component in the output.  eg.
--
-- > splitWith (==97) "aabbaca" == ["","","bb","c",""] -- fromEnum 'a' == 97
-- > splitWith undefined ""     == []                  -- and not [""]
--
splitWith :: (Word8 -> Bool) -> ByteString -> [ByteString]
splitWith :: (Word8 -> Bool) -> ByteString -> [ByteString]
splitWith Word8 -> Bool
_ ByteString
Empty          = []
splitWith Word8 -> Bool
p (Chunk ByteString
c0 ByteString
cs0) = [ByteString] -> [ByteString] -> ByteString -> [ByteString]
comb [] ((Word8 -> Bool) -> ByteString -> [ByteString]
S.splitWith Word8 -> Bool
p ByteString
c0) ByteString
cs0

  where comb :: [P.ByteString] -> [P.ByteString] -> ByteString -> [ByteString]
        comb :: [ByteString] -> [ByteString] -> ByteString -> [ByteString]
comb [ByteString]
acc [ByteString
s] ByteString
Empty        = [[ByteString] -> ByteString
revChunks (ByteString
sByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
:[ByteString]
acc)]
        comb [ByteString]
acc [ByteString
s] (Chunk ByteString
c ByteString
cs) = [ByteString] -> [ByteString] -> ByteString -> [ByteString]
comb (ByteString
sByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
:[ByteString]
acc) ((Word8 -> Bool) -> ByteString -> [ByteString]
S.splitWith Word8 -> Bool
p ByteString
c) ByteString
cs
        comb [ByteString]
acc (ByteString
s:[ByteString]
ss) ByteString
cs        = [ByteString] -> ByteString
revChunks (ByteString
sByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
:[ByteString]
acc) ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: [ByteString] -> [ByteString] -> ByteString -> [ByteString]
comb [] [ByteString]
ss ByteString
cs
{-# INLINE splitWith #-}

-- | /O(n)/ Break a 'ByteString' into pieces separated by the byte
-- argument, consuming the delimiter. I.e.
--
-- > split 10  "a\nb\nd\ne" == ["a","b","d","e"]   -- fromEnum '\n' == 10
-- > split 97  "aXaXaXa"    == ["","X","X","X",""] -- fromEnum 'a' == 97
-- > split 120 "x"          == ["",""]             -- fromEnum 'x' == 120
-- > split undefined ""     == []                  -- and not [""]
--
-- and
--
-- > intercalate [c] . split c == id
-- > split == splitWith . (==)
--
-- As for all splitting functions in this library, this function does
-- not copy the substrings, it just constructs new 'ByteString's that
-- are slices of the original.
--
split :: Word8 -> ByteString -> [ByteString]
split :: Word8 -> ByteString -> [ByteString]
split Word8
_ ByteString
Empty     = []
split Word8
w (Chunk ByteString
c0 ByteString
cs0) = [ByteString] -> [ByteString] -> ByteString -> [ByteString]
comb [] (Word8 -> ByteString -> [ByteString]
S.split Word8
w ByteString
c0) ByteString
cs0

  where comb :: [P.ByteString] -> [P.ByteString] -> ByteString -> [ByteString]
        comb :: [ByteString] -> [ByteString] -> ByteString -> [ByteString]
comb [ByteString]
acc [ByteString
s] ByteString
Empty        = [[ByteString] -> ByteString
revChunks (ByteString
sByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
:[ByteString]
acc)]
        comb [ByteString]
acc [ByteString
s] (Chunk ByteString
c ByteString
cs) = [ByteString] -> [ByteString] -> ByteString -> [ByteString]
comb (ByteString
sByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
:[ByteString]
acc) (Word8 -> ByteString -> [ByteString]
S.split Word8
w ByteString
c) ByteString
cs
        comb [ByteString]
acc (ByteString
s:[ByteString]
ss) ByteString
cs        = [ByteString] -> ByteString
revChunks (ByteString
sByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
:[ByteString]
acc) ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: [ByteString] -> [ByteString] -> ByteString -> [ByteString]
comb [] [ByteString]
ss ByteString
cs
{-# INLINE split #-}

-- | The 'group' function takes a ByteString and returns a list of
-- ByteStrings such that the concatenation of the result is equal to the
-- argument.  Moreover, each string in the result contains only equal
-- elements.  For example,
--
-- > group "Mississippi" = ["M","i","ss","i","ss","i","pp","i"]
--
-- It is a special case of 'groupBy', which allows the programmer to
-- supply their own equality test.
group :: ByteString -> [ByteString]
group :: ByteString -> [ByteString]
group = ByteString -> [ByteString]
go
  where
    go :: ByteString -> [ByteString]
go ByteString
Empty        = []
    go (Chunk ByteString
c ByteString
cs)
      | ByteString -> Int
S.length ByteString
c Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1  = [ByteString] -> Word8 -> ByteString -> [ByteString]
to [ByteString
c] (ByteString -> Word8
S.unsafeHead ByteString
c) ByteString
cs
      | Bool
otherwise        = [ByteString] -> Word8 -> ByteString -> [ByteString]
to [Int -> ByteString -> ByteString
S.unsafeTake Int
1 ByteString
c] (ByteString -> Word8
S.unsafeHead ByteString
c) (ByteString -> ByteString -> ByteString
Chunk (ByteString -> ByteString
S.unsafeTail ByteString
c) ByteString
cs)

    to :: [ByteString] -> Word8 -> ByteString -> [ByteString]
to [ByteString]
acc !Word8
_ ByteString
Empty        = [[ByteString] -> ByteString
revNonEmptyChunks [ByteString]
acc]
    to [ByteString]
acc !Word8
w (Chunk ByteString
c ByteString
cs) =
      case (Word8 -> Bool) -> ByteString -> Int
S.findIndexOrLength (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word8
w) ByteString
c of
        Int
0                    -> [ByteString] -> ByteString
revNonEmptyChunks [ByteString]
acc
                              ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: ByteString -> [ByteString]
go (ByteString -> ByteString -> ByteString
Chunk ByteString
c ByteString
cs)
        Int
n | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString -> Int
S.length ByteString
c  -> [ByteString] -> Word8 -> ByteString -> [ByteString]
to (Int -> ByteString -> ByteString
S.unsafeTake Int
n ByteString
c ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: [ByteString]
acc) Word8
w ByteString
cs
          | Bool
otherwise        -> [ByteString] -> ByteString
revNonEmptyChunks (Int -> ByteString -> ByteString
S.unsafeTake Int
n ByteString
c ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: [ByteString]
acc)
                              ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: ByteString -> [ByteString]
go (ByteString -> ByteString -> ByteString
Chunk (Int -> ByteString -> ByteString
S.unsafeDrop Int
n ByteString
c) ByteString
cs)

-- | The 'groupBy' function is the non-overloaded version of 'group'.
--
groupBy :: (Word8 -> Word8 -> Bool) -> ByteString -> [ByteString]
groupBy :: (Word8 -> Word8 -> Bool) -> ByteString -> [ByteString]
groupBy Word8 -> Word8 -> Bool
k = ByteString -> [ByteString]
go
  where
    go :: ByteString -> [ByteString]
go ByteString
Empty        = []
    go (Chunk ByteString
c ByteString
cs)
      | ByteString -> Int
S.length ByteString
c Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1  = [ByteString] -> Word8 -> ByteString -> [ByteString]
to [ByteString
c] (ByteString -> Word8
S.unsafeHead ByteString
c) ByteString
cs
      | Bool
otherwise        = [ByteString] -> Word8 -> ByteString -> [ByteString]
to [Int -> ByteString -> ByteString
S.unsafeTake Int
1 ByteString
c] (ByteString -> Word8
S.unsafeHead ByteString
c) (ByteString -> ByteString -> ByteString
Chunk (ByteString -> ByteString
S.unsafeTail ByteString
c) ByteString
cs)

    to :: [ByteString] -> Word8 -> ByteString -> [ByteString]
to [ByteString]
acc !Word8
_ ByteString
Empty        = [[ByteString] -> ByteString
revNonEmptyChunks [ByteString]
acc]
    to [ByteString]
acc !Word8
w (Chunk ByteString
c ByteString
cs) =
      case (Word8 -> Bool) -> ByteString -> Int
S.findIndexOrLength (Bool -> Bool
not (Bool -> Bool) -> (Word8 -> Bool) -> Word8 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Word8 -> Bool
k Word8
w) ByteString
c of
        Int
0                    -> [ByteString] -> ByteString
revNonEmptyChunks [ByteString]
acc
                              ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: ByteString -> [ByteString]
go (ByteString -> ByteString -> ByteString
Chunk ByteString
c ByteString
cs)
        Int
n | Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString -> Int
S.length ByteString
c  -> [ByteString] -> Word8 -> ByteString -> [ByteString]
to (Int -> ByteString -> ByteString
S.unsafeTake Int
n ByteString
c ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: [ByteString]
acc) Word8
w ByteString
cs
          | Bool
otherwise        -> [ByteString] -> ByteString
revNonEmptyChunks (Int -> ByteString -> ByteString
S.unsafeTake Int
n ByteString
c ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: [ByteString]
acc)
                              ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: ByteString -> [ByteString]
go (ByteString -> ByteString -> ByteString
Chunk (Int -> ByteString -> ByteString
S.unsafeDrop Int
n ByteString
c) ByteString
cs)

-- | /O(n)/ The 'intercalate' function takes a 'ByteString' and a list of
-- 'ByteString's and concatenates the list after interspersing the first
-- argument between each element of the list.
intercalate :: ByteString -> [ByteString] -> ByteString
intercalate :: ByteString -> [ByteString] -> ByteString
intercalate ByteString
s = [ByteString] -> ByteString
concat ([ByteString] -> ByteString)
-> ([ByteString] -> [ByteString]) -> [ByteString] -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
List.intersperse ByteString
s

-- ---------------------------------------------------------------------
-- Indexing ByteStrings

-- | /O(c)/ 'ByteString' index (subscript) operator, starting from 0.
--
-- This is a partial function, consider using 'indexMaybe' instead.
index :: HasCallStack => ByteString -> Int64 -> Word8
index :: HasCallStack => ByteString -> Int64 -> Word8
index ByteString
_  Int64
i | Int64
i Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< Int64
0  = String -> String -> Word8
forall a. HasCallStack => String -> String -> a
moduleError String
"index" (String
"negative index: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int64 -> String
forall a. Show a => a -> String
show Int64
i)
index ByteString
cs0 Int64
i         = ByteString -> Int64 -> Word8
forall {a}. (Show a, Integral a) => ByteString -> a -> Word8
index' ByteString
cs0 Int64
i
  where index' :: ByteString -> a -> Word8
index' ByteString
Empty     a
n = String -> String -> Word8
forall a. HasCallStack => String -> String -> a
moduleError String
"index" (String
"index too large: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
n)
        index' (Chunk ByteString
c ByteString
cs) a
n
          | a
n a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
S.length ByteString
c) =
              ByteString -> a -> Word8
index' ByteString
cs (a
n a -> a -> a
forall a. Num a => a -> a -> a
- Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
S.length ByteString
c))
          | Bool
otherwise       = ByteString -> Int -> Word8
S.unsafeIndex ByteString
c (a -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
n)

-- | /O(c)/ 'ByteString' index, starting from 0, that returns 'Just' if:
--
-- > 0 <= n < length bs
--
-- @since 0.11.0.0
indexMaybe :: ByteString -> Int64 -> Maybe Word8
indexMaybe :: ByteString -> Int64 -> Maybe Word8
indexMaybe ByteString
_ Int64
i | Int64
i Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< Int64
0 = Maybe Word8
forall a. Maybe a
Nothing
indexMaybe ByteString
cs0 Int64
i       = ByteString -> Int64 -> Maybe Word8
forall {a}. Integral a => ByteString -> a -> Maybe Word8
index' ByteString
cs0 Int64
i
  where index' :: ByteString -> a -> Maybe Word8
index' ByteString
Empty a
_ = Maybe Word8
forall a. Maybe a
Nothing
        index' (Chunk ByteString
c ByteString
cs) a
n
          | a
n a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
S.length ByteString
c) =
              ByteString -> a -> Maybe Word8
index' ByteString
cs (a
n a -> a -> a
forall a. Num a => a -> a -> a
- Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
S.length ByteString
c))
          | Bool
otherwise       = Word8 -> Maybe Word8
forall a. a -> Maybe a
Just (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! ByteString -> Int -> Word8
S.unsafeIndex ByteString
c (a -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
n)

-- | /O(1)/ 'ByteString' index, starting from 0, that returns 'Just' if:
--
-- > 0 <= n < length bs
--
-- @since 0.11.0.0
(!?) :: ByteString -> Int64 -> Maybe Word8
!? :: ByteString -> Int64 -> Maybe Word8
(!?) = ByteString -> Int64 -> Maybe Word8
indexMaybe
{-# INLINE (!?) #-}

-- | /O(n)/ The 'elemIndex' function returns the index of the first
-- element in the given 'ByteString' which is equal to the query
-- element, or 'Nothing' if there is no such element.
-- This implementation uses memchr(3).
elemIndex :: Word8 -> ByteString -> Maybe Int64
elemIndex :: Word8 -> ByteString -> Maybe Int64
elemIndex Word8
w = Int64 -> ByteString -> Maybe Int64
forall {a}. Num a => a -> ByteString -> Maybe a
elemIndex' Int64
0
  where elemIndex' :: a -> ByteString -> Maybe a
elemIndex' a
_ ByteString
Empty        = Maybe a
forall a. Maybe a
Nothing
        elemIndex' a
n (Chunk ByteString
c ByteString
cs) =
          case Word8 -> ByteString -> Maybe Int
S.elemIndex Word8
w ByteString
c of
            Maybe Int
Nothing -> a -> ByteString -> Maybe a
elemIndex' (a
n a -> a -> a
forall a. Num a => a -> a -> a
+ Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
S.length ByteString
c)) ByteString
cs
            Just Int
i  -> a -> Maybe a
forall a. a -> Maybe a
Just (a
n a -> a -> a
forall a. Num a => a -> a -> a
+ Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i)

-- | /O(n)/ The 'elemIndexEnd' function returns the last index of the
-- element in the given 'ByteString' which is equal to the query
-- element, or 'Nothing' if there is no such element. The following
-- holds:
--
-- > elemIndexEnd c xs = case elemIndex c (reverse xs) of
-- >   Nothing -> Nothing
-- >   Just i  -> Just (length xs - 1 - i)
--
-- @since 0.10.6.0
elemIndexEnd :: Word8 -> ByteString -> Maybe Int64
elemIndexEnd :: Word8 -> ByteString -> Maybe Int64
elemIndexEnd = (Word8 -> Bool) -> ByteString -> Maybe Int64
findIndexEnd ((Word8 -> Bool) -> ByteString -> Maybe Int64)
-> (Word8 -> Word8 -> Bool) -> Word8 -> ByteString -> Maybe Int64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
(==)
{-# INLINE elemIndexEnd #-}

-- | /O(n)/ The 'elemIndices' function extends 'elemIndex', by returning
-- the indices of all elements equal to the query element, in ascending order.
-- This implementation uses memchr(3).
elemIndices :: Word8 -> ByteString -> [Int64]
elemIndices :: Word8 -> ByteString -> [Int64]
elemIndices Word8
w = Int64 -> ByteString -> [Int64]
forall {t}. Num t => t -> ByteString -> [t]
elemIndices' Int64
0
  where elemIndices' :: t -> ByteString -> [t]
elemIndices' t
_ ByteString
Empty        = []
        elemIndices' t
n (Chunk ByteString
c ByteString
cs) = (Int -> t) -> [Int] -> [t]
forall a b. (a -> b) -> [a] -> [b]
List.map ((t -> t -> t
forall a. Num a => a -> a -> a
+t
n)(t -> t) -> (Int -> t) -> Int -> t
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Int -> t
forall a b. (Integral a, Num b) => a -> b
fromIntegral) (Word8 -> ByteString -> [Int]
S.elemIndices Word8
w ByteString
c)
                             [t] -> [t] -> [t]
forall a. [a] -> [a] -> [a]
++ t -> ByteString -> [t]
elemIndices' (t
n t -> t -> t
forall a. Num a => a -> a -> a
+ Int -> t
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
S.length ByteString
c)) ByteString
cs

-- | count returns the number of times its argument appears in the ByteString
--
-- > count = length . elemIndices
--
-- But more efficiently than using length on the intermediate list.
count :: Word8 -> ByteString -> Int64
count :: Word8 -> ByteString -> Int64
count Word8
w = (Int64 -> ByteString -> Int64) -> Int64 -> ByteString -> Int64
forall a. (a -> ByteString -> a) -> a -> ByteString -> a
foldlChunks (\Int64
n ByteString
c -> Int64
n Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+ Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8 -> ByteString -> Int
S.count Word8
w ByteString
c)) Int64
0

-- | The 'findIndex' function takes a predicate and a 'ByteString' and
-- returns the index of the first element in the ByteString
-- satisfying the predicate.
findIndex :: (Word8 -> Bool) -> ByteString -> Maybe Int64
findIndex :: (Word8 -> Bool) -> ByteString -> Maybe Int64
findIndex Word8 -> Bool
k = Int64 -> ByteString -> Maybe Int64
forall {a}. Num a => a -> ByteString -> Maybe a
findIndex' Int64
0
  where findIndex' :: a -> ByteString -> Maybe a
findIndex' a
_ ByteString
Empty        = Maybe a
forall a. Maybe a
Nothing
        findIndex' a
n (Chunk ByteString
c ByteString
cs) =
          case (Word8 -> Bool) -> ByteString -> Maybe Int
S.findIndex Word8 -> Bool
k ByteString
c of
            Maybe Int
Nothing -> a -> ByteString -> Maybe a
findIndex' (a
n a -> a -> a
forall a. Num a => a -> a -> a
+ Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
S.length ByteString
c)) ByteString
cs
            Just Int
i  -> a -> Maybe a
forall a. a -> Maybe a
Just (a
n a -> a -> a
forall a. Num a => a -> a -> a
+ Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i)
{-# INLINE findIndex #-}

-- | The 'findIndexEnd' function takes a predicate and a 'ByteString' and
-- returns the index of the last element in the ByteString
-- satisfying the predicate.
--
-- @since 0.10.12.0
findIndexEnd :: (Word8 -> Bool) -> ByteString -> Maybe Int64
findIndexEnd :: (Word8 -> Bool) -> ByteString -> Maybe Int64
findIndexEnd Word8 -> Bool
k = Int -> ByteString -> Maybe Int64
forall {a}. Num a => Int -> ByteString -> Maybe a
findIndexEnd' Int
0
  where
    findIndexEnd' :: Int -> ByteString -> Maybe a
findIndexEnd' Int
_ ByteString
Empty = Maybe a
forall a. Maybe a
Nothing
    findIndexEnd' Int
n (Chunk ByteString
c ByteString
cs) =
      let !n' :: Int
n' = Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ByteString -> Int
S.length ByteString
c
          !i :: Maybe a
i  = Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> a) -> (Int -> Int) -> Int -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+) (Int -> a) -> Maybe Int -> Maybe a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Word8 -> Bool) -> ByteString -> Maybe Int
S.findIndexEnd Word8 -> Bool
k ByteString
c
      in Int -> ByteString -> Maybe a
findIndexEnd' Int
n' ByteString
cs Maybe a -> Maybe a -> Maybe a
forall a. Maybe a -> Maybe a -> Maybe a
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
`mplus` Maybe a
i
{-# INLINE findIndexEnd #-}

-- | /O(n)/ The 'find' function takes a predicate and a ByteString,
-- and returns the first element in matching the predicate, or 'Nothing'
-- if there is no such element.
--
-- > find f p = case findIndex f p of Just n -> Just (p ! n) ; _ -> Nothing
--
find :: (Word8 -> Bool) -> ByteString -> Maybe Word8
find :: (Word8 -> Bool) -> ByteString -> Maybe Word8
find Word8 -> Bool
f = ByteString -> Maybe Word8
find'
  where find' :: ByteString -> Maybe Word8
find' ByteString
Empty        = Maybe Word8
forall a. Maybe a
Nothing
        find' (Chunk ByteString
c ByteString
cs) = case (Word8 -> Bool) -> ByteString -> Maybe Word8
S.find Word8 -> Bool
f ByteString
c of
            Maybe Word8
Nothing -> ByteString -> Maybe Word8
find' ByteString
cs
            Just Word8
w  -> Word8 -> Maybe Word8
forall a. a -> Maybe a
Just Word8
w
{-# INLINE find #-}

-- | The 'findIndices' function extends 'findIndex', by returning the
-- indices of all elements satisfying the predicate, in ascending order.
findIndices :: (Word8 -> Bool) -> ByteString -> [Int64]
findIndices :: (Word8 -> Bool) -> ByteString -> [Int64]
findIndices Word8 -> Bool
k = Int64 -> ByteString -> [Int64]
forall {t}. Num t => t -> ByteString -> [t]
findIndices' Int64
0
  where findIndices' :: t -> ByteString -> [t]
findIndices' t
_ ByteString
Empty        = []
        findIndices' t
n (Chunk ByteString
c ByteString
cs) = (Int -> t) -> [Int] -> [t]
forall a b. (a -> b) -> [a] -> [b]
List.map ((t -> t -> t
forall a. Num a => a -> a -> a
+t
n)(t -> t) -> (Int -> t) -> Int -> t
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Int -> t
forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Word8 -> Bool) -> ByteString -> [Int]
S.findIndices Word8 -> Bool
k ByteString
c)
                             [t] -> [t] -> [t]
forall a. [a] -> [a] -> [a]
++ t -> ByteString -> [t]
findIndices' (t
n t -> t -> t
forall a. Num a => a -> a -> a
+ Int -> t
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int
S.length ByteString
c)) ByteString
cs
{-# INLINE findIndices #-}

-- ---------------------------------------------------------------------
-- Searching ByteStrings

-- | /O(n)/ 'elem' is the 'ByteString' membership predicate.
elem :: Word8 -> ByteString -> Bool
elem :: Word8 -> ByteString -> Bool
elem Word8
w ByteString
cs = case Word8 -> ByteString -> Maybe Int64
elemIndex Word8
w ByteString
cs of Maybe Int64
Nothing -> Bool
False ; Maybe Int64
_ -> Bool
True

-- | /O(n)/ 'notElem' is the inverse of 'elem'
notElem :: Word8 -> ByteString -> Bool
notElem :: Word8 -> ByteString -> Bool
notElem Word8
w ByteString
cs = Bool -> Bool
not (Word8
w Word8 -> ByteString -> Bool
`elem` ByteString
cs)

-- | /O(n)/ 'filter', applied to a predicate and a ByteString,
-- returns a ByteString containing those characters that satisfy the
-- predicate.
filter :: (Word8 -> Bool) -> ByteString -> ByteString
filter :: (Word8 -> Bool) -> ByteString -> ByteString
filter Word8 -> Bool
p = ByteString -> ByteString
go
    where
        go :: ByteString -> ByteString
go ByteString
Empty        = ByteString
Empty
        go (Chunk ByteString
x ByteString
xs) = ByteString -> ByteString -> ByteString
chunk ((Word8 -> Bool) -> ByteString -> ByteString
S.filter Word8 -> Bool
p ByteString
x) (ByteString -> ByteString
go ByteString
xs)
{-# INLINE filter #-}

{-
-- | /O(n)/ and /O(n\/c) space/ A first order equivalent of /filter .
-- (==)/, for the common case of filtering a single byte. It is more
-- efficient to use /filterByte/ in this case.
--
-- > filterByte == filter . (==)
--
-- filterByte is around 10x faster, and uses much less space, than its
-- filter equivalent
filterByte :: Word8 -> ByteString -> ByteString
filterByte w ps = replicate (count w ps) w
{-# INLINE filterByte #-}

{-# RULES
"ByteString specialise filter (== x)" forall x.
  filter ((==) x) = filterByte x

"ByteString specialise filter (== x)" forall x.
 filter (== x) = filterByte x
  #-}
-}

{-
-- | /O(n)/ A first order equivalent of /filter . (\/=)/, for the common
-- case of filtering a single byte out of a list. It is more efficient
-- to use /filterNotByte/ in this case.
--
-- > filterNotByte == filter . (/=)
--
-- filterNotByte is around 2x faster than its filter equivalent.
filterNotByte :: Word8 -> ByteString -> ByteString
filterNotByte w (LPS xs) = LPS (filterMap (P.filterNotByte w) xs)
-}

-- | /O(n)/ The 'partition' function takes a predicate a ByteString and returns
-- the pair of ByteStrings with elements which do and do not satisfy the
-- predicate, respectively; i.e.,
--
-- > partition p bs == (filter p xs, filter (not . p) xs)
--
partition :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
partition :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
partition Word8 -> Bool
_ ByteString
Empty = (ByteString
Empty, ByteString
Empty)
partition Word8 -> Bool
p (Chunk ByteString
x ByteString
xs) = (ByteString -> ByteString -> ByteString
chunk ByteString
t ByteString
ts, ByteString -> ByteString -> ByteString
chunk ByteString
f ByteString
fs)
  where
    (ByteString
t,   ByteString
f) = (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
S.partition Word8 -> Bool
p ByteString
x
    (ByteString
ts, ByteString
fs) = (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
partition   Word8 -> Bool
p ByteString
xs

-- ---------------------------------------------------------------------
-- Searching for substrings

-- | /O(n)/ The 'isPrefixOf' function takes two ByteStrings and returns 'True'
-- iff the first is a prefix of the second.
isPrefixOf :: ByteString -> ByteString -> Bool
isPrefixOf :: ByteString -> ByteString -> Bool
isPrefixOf ByteString
Empty ByteString
_  = Bool
True
isPrefixOf ByteString
_ ByteString
Empty  = Bool
False
isPrefixOf (Chunk ByteString
x ByteString
xs) (Chunk ByteString
y ByteString
ys)
    | ByteString -> Int
S.length ByteString
x Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString -> Int
S.length ByteString
y = ByteString
x ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
y  Bool -> Bool -> Bool
&& ByteString -> ByteString -> Bool
isPrefixOf ByteString
xs ByteString
ys
    | ByteString -> Int
S.length ByteString
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<  ByteString -> Int
S.length ByteString
y = ByteString
x ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
yh Bool -> Bool -> Bool
&& ByteString -> ByteString -> Bool
isPrefixOf ByteString
xs (ByteString -> ByteString -> ByteString
Chunk ByteString
yt ByteString
ys)
    | Bool
otherwise                = ByteString
xh ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
y Bool -> Bool -> Bool
&& ByteString -> ByteString -> Bool
isPrefixOf (ByteString -> ByteString -> ByteString
Chunk ByteString
xt ByteString
xs) ByteString
ys
  where (ByteString
xh,ByteString
xt) = Int -> ByteString -> (ByteString, ByteString)
S.splitAt (ByteString -> Int
S.length ByteString
y) ByteString
x
        (ByteString
yh,ByteString
yt) = Int -> ByteString -> (ByteString, ByteString)
S.splitAt (ByteString -> Int
S.length ByteString
x) ByteString
y

-- | /O(n)/ The 'stripPrefix' function takes two ByteStrings and returns 'Just'
-- the remainder of the second iff the first is its prefix, and otherwise
-- 'Nothing'.
--
-- @since 0.10.8.0
stripPrefix :: ByteString -> ByteString -> Maybe ByteString
stripPrefix :: ByteString -> ByteString -> Maybe ByteString
stripPrefix ByteString
Empty ByteString
bs  = ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
bs
stripPrefix ByteString
_ ByteString
Empty  = Maybe ByteString
forall a. Maybe a
Nothing
stripPrefix (Chunk ByteString
x ByteString
xs) (Chunk ByteString
y ByteString
ys)
    | ByteString -> Int
S.length ByteString
x Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString -> Int
S.length ByteString
y = if ByteString
x ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
y then ByteString -> ByteString -> Maybe ByteString
stripPrefix ByteString
xs ByteString
ys else Maybe ByteString
forall a. Maybe a
Nothing
    | ByteString -> Int
S.length ByteString
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<  ByteString -> Int
S.length ByteString
y = do ByteString
yt <- ByteString -> ByteString -> Maybe ByteString
S.stripPrefix ByteString
x ByteString
y
                                    ByteString -> ByteString -> Maybe ByteString
stripPrefix ByteString
xs (ByteString -> ByteString -> ByteString
Chunk ByteString
yt ByteString
ys)
    | Bool
otherwise                = do ByteString
xt <- ByteString -> ByteString -> Maybe ByteString
S.stripPrefix ByteString
y ByteString
x
                                    ByteString -> ByteString -> Maybe ByteString
stripPrefix (ByteString -> ByteString -> ByteString
Chunk ByteString
xt ByteString
xs) ByteString
ys

-- | /O(n)/ The 'isSuffixOf' function takes two ByteStrings and returns 'True'
-- iff the first is a suffix of the second.
--
-- The following holds:
--
-- > isSuffixOf x y == reverse x `isPrefixOf` reverse y
--
isSuffixOf :: ByteString -> ByteString -> Bool
isSuffixOf :: ByteString -> ByteString -> Bool
isSuffixOf ByteString
x ByteString
y = ByteString -> ByteString
reverse ByteString
x ByteString -> ByteString -> Bool
`isPrefixOf` ByteString -> ByteString
reverse ByteString
y
--TODO: a better implementation

-- | /O(n)/ The 'stripSuffix' function takes two ByteStrings and returns 'Just'
-- the remainder of the second iff the first is its suffix, and otherwise
-- 'Nothing'.
stripSuffix :: ByteString -> ByteString -> Maybe ByteString
stripSuffix :: ByteString -> ByteString -> Maybe ByteString
stripSuffix ByteString
x ByteString
y = ByteString -> ByteString
reverse (ByteString -> ByteString) -> Maybe ByteString -> Maybe ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ByteString -> ByteString -> Maybe ByteString
stripPrefix (ByteString -> ByteString
reverse ByteString
x) (ByteString -> ByteString
reverse ByteString
y)
--TODO: a better implementation

-- ---------------------------------------------------------------------
-- Zipping

-- | /O(n)/ 'zip' takes two ByteStrings and returns a list of
-- corresponding pairs of bytes. If one input ByteString is short,
-- excess elements of the longer ByteString are discarded. This is
-- equivalent to a pair of 'unpack' operations.
zip :: ByteString -> ByteString -> [(Word8,Word8)]
zip :: ByteString -> ByteString -> [(Word8, Word8)]
zip = (Word8 -> Word8 -> (Word8, Word8))
-> ByteString -> ByteString -> [(Word8, Word8)]
forall a. (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a]
zipWith (,)

-- | 'zipWith' generalises 'zip' by zipping with the function given as
-- the first argument, instead of a tupling function.  For example,
-- @'zipWith' (+)@ is applied to two ByteStrings to produce the list of
-- corresponding sums.
zipWith :: (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a]
zipWith :: forall a. (Word8 -> Word8 -> a) -> ByteString -> ByteString -> [a]
zipWith Word8 -> Word8 -> a
_ ByteString
Empty     ByteString
_  = []
zipWith Word8 -> Word8 -> a
_ ByteString
_      ByteString
Empty = []
zipWith Word8 -> Word8 -> a
f (Chunk ByteString
a ByteString
as) (Chunk ByteString
b ByteString
bs) = ByteString -> ByteString -> ByteString -> ByteString -> [a]
go ByteString
a ByteString
as ByteString
b ByteString
bs
  where
    go :: ByteString -> ByteString -> ByteString -> ByteString -> [a]
go ByteString
x ByteString
xs ByteString
y ByteString
ys = Word8 -> Word8 -> a
f (ByteString -> Word8
S.unsafeHead ByteString
x) (ByteString -> Word8
S.unsafeHead ByteString
y)
                 a -> [a] -> [a]
forall a. a -> [a] -> [a]
: ByteString -> ByteString -> ByteString -> ByteString -> [a]
to (ByteString -> ByteString
S.unsafeTail ByteString
x) ByteString
xs (ByteString -> ByteString
S.unsafeTail ByteString
y) ByteString
ys

    to :: ByteString -> ByteString -> ByteString -> ByteString -> [a]
to ByteString
x ByteString
Empty         ByteString
_ ByteString
_             | ByteString -> Bool
S.null ByteString
x       = []
    to ByteString
_ ByteString
_             ByteString
y ByteString
Empty         | ByteString -> Bool
S.null ByteString
y       = []
    to ByteString
x ByteString
xs            ByteString
y ByteString
ys            | Bool -> Bool
not (ByteString -> Bool
S.null ByteString
x)
                                      Bool -> Bool -> Bool
&& Bool -> Bool
not (ByteString -> Bool
S.null ByteString
y) = ByteString -> ByteString -> ByteString -> ByteString -> [a]
go ByteString
x  ByteString
xs ByteString
y  ByteString
ys
    to ByteString
x ByteString
xs            ByteString
_ (Chunk ByteString
y' ByteString
ys) | Bool -> Bool
not (ByteString -> Bool
S.null ByteString
x) = ByteString -> ByteString -> ByteString -> ByteString -> [a]
go ByteString
x  ByteString
xs ByteString
y' ByteString
ys
    to ByteString
_ (Chunk ByteString
x' ByteString
xs) ByteString
y ByteString
ys            | Bool -> Bool
not (ByteString -> Bool
S.null ByteString
y) = ByteString -> ByteString -> ByteString -> ByteString -> [a]
go ByteString
x' ByteString
xs ByteString
y  ByteString
ys
    to ByteString
_ (Chunk ByteString
x' ByteString
xs) ByteString
_ (Chunk ByteString
y' ByteString
ys)                  = ByteString -> ByteString -> ByteString -> ByteString -> [a]
go ByteString
x' ByteString
xs ByteString
y' ByteString
ys

-- | A specialised version of `zipWith` for the common case of a
-- simultaneous map over two ByteStrings, to build a 3rd.
--
-- @since 0.11.1.0
packZipWith :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString -> ByteString
packZipWith :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString -> ByteString
packZipWith Word8 -> Word8 -> Word8
_ ByteString
Empty ByteString
_ = ByteString
Empty
packZipWith Word8 -> Word8 -> Word8
_ ByteString
_ ByteString
Empty = ByteString
Empty
packZipWith Word8 -> Word8 -> Word8
f (Chunk a :: ByteString
a@(S.BS ForeignPtr Word8
_ Int
al) ByteString
as) (Chunk b :: ByteString
b@(S.BS ForeignPtr Word8
_ Int
bl) ByteString
bs) = ByteString -> ByteString -> ByteString
Chunk ((Word8 -> Word8 -> Word8) -> ByteString -> ByteString -> ByteString
S.packZipWith Word8 -> Word8 -> Word8
f ByteString
a ByteString
b) (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$
    case Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Int
al Int
bl of
        Ordering
LT -> (Word8 -> Word8 -> Word8) -> ByteString -> ByteString -> ByteString
packZipWith Word8 -> Word8 -> Word8
f ByteString
as (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString -> ByteString
Chunk (Int -> ByteString -> ByteString
S.drop Int
al ByteString
b) ByteString
bs
        Ordering
EQ -> (Word8 -> Word8 -> Word8) -> ByteString -> ByteString -> ByteString
packZipWith Word8 -> Word8 -> Word8
f ByteString
as ByteString
bs
        Ordering
GT -> (Word8 -> Word8 -> Word8) -> ByteString -> ByteString -> ByteString
packZipWith Word8 -> Word8 -> Word8
f (ByteString -> ByteString -> ByteString
Chunk (Int -> ByteString -> ByteString
S.drop Int
bl ByteString
a) ByteString
as) ByteString
bs
{-# INLINE packZipWith #-}

-- | /O(n)/ 'unzip' transforms a list of pairs of bytes into a pair of
-- ByteStrings. Note that this performs two 'pack' operations.
unzip :: [(Word8,Word8)] -> (ByteString,ByteString)
unzip :: [(Word8, Word8)] -> (ByteString, ByteString)
unzip [(Word8, Word8)]
ls = ([Word8] -> ByteString
pack (((Word8, Word8) -> Word8) -> [(Word8, Word8)] -> [Word8]
forall a b. (a -> b) -> [a] -> [b]
List.map (Word8, Word8) -> Word8
forall a b. (a, b) -> a
fst [(Word8, Word8)]
ls), [Word8] -> ByteString
pack (((Word8, Word8) -> Word8) -> [(Word8, Word8)] -> [Word8]
forall a b. (a -> b) -> [a] -> [b]
List.map (Word8, Word8) -> Word8
forall a b. (a, b) -> b
snd [(Word8, Word8)]
ls))
{-# INLINE unzip #-}

-- ---------------------------------------------------------------------
-- Special lists

-- | Returns all initial segments of the given 'ByteString', shortest first.
inits :: ByteString -> [ByteString]
-- see Note [Avoid NonEmpty combinators] in Data.ByteString
inits :: ByteString -> [ByteString]
inits ByteString
bs = NonEmpty ByteString -> [ByteString]
forall a. NonEmpty a -> [a]
NE.toList (NonEmpty ByteString -> [ByteString])
-> NonEmpty ByteString -> [ByteString]
forall a b. (a -> b) -> a -> b
$! ByteString -> NonEmpty ByteString
initsNE ByteString
bs

-- | Returns all initial segments of the given 'ByteString', shortest first.
--
-- @since 0.11.4.0
initsNE :: ByteString -> NonEmpty ByteString
-- see Note [Avoid NonEmpty combinators] in Data.ByteString
initsNE :: ByteString -> NonEmpty ByteString
initsNE = (ByteString
Empty ByteString -> [ByteString] -> NonEmpty ByteString
forall a. a -> [a] -> NonEmpty a
:|) ([ByteString] -> NonEmpty ByteString)
-> (ByteString -> [ByteString])
-> ByteString
-> NonEmpty ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> ByteString) -> ByteString -> [ByteString]
inits' ByteString -> ByteString
forall a. a -> a
id
  where
    inits' :: (ByteString -> ByteString) -> ByteString -> [ByteString]
    -- inits' f bs === map f (tail (inits bs))
    inits' :: (ByteString -> ByteString) -> ByteString -> [ByteString]
inits' ByteString -> ByteString
_ ByteString
Empty = []
    inits' ByteString -> ByteString
f (Chunk c :: ByteString
c@(S.BS ForeignPtr Word8
x Int
len) ByteString
cs)
      = [ByteString -> ByteString
f (ForeignPtr Word8 -> Int -> ByteString
S.BS ForeignPtr Word8
x Int
n ByteString -> ByteString -> ByteString
`Chunk` ByteString
Empty) | Int
n <- [Int
1..Int
len]]
      [ByteString] -> [ByteString] -> [ByteString]
forall a. [a] -> [a] -> [a]
++ (ByteString -> ByteString) -> ByteString -> [ByteString]
inits' (ByteString -> ByteString
f (ByteString -> ByteString)
-> (ByteString -> ByteString) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString -> ByteString
Chunk ByteString
c) ByteString
cs

-- | /O(n)/ Returns all final segments of the given 'ByteString', longest first.
tails :: ByteString -> [ByteString]
-- see Note [Avoid NonEmpty combinators] in Data.ByteString
tails :: ByteString -> [ByteString]
tails ByteString
bs = NonEmpty ByteString -> [ByteString]
forall a. NonEmpty a -> [a]
NE.toList (NonEmpty ByteString -> [ByteString])
-> NonEmpty ByteString -> [ByteString]
forall a b. (a -> b) -> a -> b
$! ByteString -> NonEmpty ByteString
tailsNE ByteString
bs

-- | /O(n)/ Returns all final segments of the given 'ByteString', longest first.
--
-- @since 0.11.4.0
tailsNE :: ByteString -> NonEmpty ByteString
-- see Note [Avoid NonEmpty combinators] in Data.ByteString
tailsNE :: ByteString -> NonEmpty ByteString
tailsNE ByteString
bs = case ByteString -> Maybe (Word8, ByteString)
uncons ByteString
bs of
  Maybe (Word8, ByteString)
Nothing -> ByteString
Empty ByteString -> [ByteString] -> NonEmpty ByteString
forall a. a -> [a] -> NonEmpty a
:| []
  Just (Word8
_, ByteString
tl) -> ByteString
bs ByteString -> [ByteString] -> NonEmpty ByteString
forall a. a -> [a] -> NonEmpty a
:| ByteString -> [ByteString]
tails ByteString
tl


-- ---------------------------------------------------------------------
-- Low level constructors

-- | /O(n)/ Make a copy of the 'ByteString' with its own storage.
--   This is mainly useful to allow the rest of the data pointed
--   to by the 'ByteString' to be garbage collected, for example
--   if a large string has been read in, and only a small part of it
--   is needed in the rest of the program.
copy :: ByteString -> ByteString
copy :: ByteString -> ByteString
copy = (ByteString -> ByteString -> ByteString)
-> ByteString -> ByteString -> ByteString
forall a. (ByteString -> a -> a) -> a -> ByteString -> a
foldrChunks (ByteString -> ByteString -> ByteString
Chunk (ByteString -> ByteString -> ByteString)
-> (ByteString -> ByteString)
-> ByteString
-> ByteString
-> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
S.copy) ByteString
Empty
--TODO, we could coalese small blocks here
--FIXME: probably not strict enough, if we're doing this to avoid retaining
-- the parent blocks then we'd better copy strictly.

-- ---------------------------------------------------------------------

-- TODO defrag func that concatenates block together that are below a threshold
-- defrag :: ByteString -> ByteString

-- ---------------------------------------------------------------------
-- Lazy ByteString IO
--
-- Rule for when to close: is it expected to read the whole file?
-- If so, close when done.
--

-- | Read entire handle contents /lazily/ into a 'ByteString'. Chunks
-- are read on demand, in at most @k@-sized chunks. It does not block
-- waiting for a whole @k@-sized chunk, so if less than @k@ bytes are
-- available then they will be returned immediately as a smaller chunk.
--
-- The handle is closed on EOF.
--
hGetContentsN :: Int -> Handle -> IO ByteString
hGetContentsN :: Int -> Handle -> IO ByteString
hGetContentsN Int
k Handle
h = IO ByteString
lazyRead -- TODO close on exceptions
  where
    lazyRead :: IO ByteString
lazyRead = IO ByteString -> IO ByteString
forall a. IO a -> IO a
unsafeInterleaveIO IO ByteString
loop

    loop :: IO ByteString
loop = do
        ByteString
c <- Handle -> Int -> IO ByteString
S.hGetSome Handle
h Int
k -- only blocks if there is no data available
        if ByteString -> Bool
S.null ByteString
c
          then Handle -> IO ()
hClose Handle
h IO () -> IO ByteString -> IO ByteString
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
Empty
          else ByteString -> ByteString -> ByteString
Chunk ByteString
c (ByteString -> ByteString) -> IO ByteString -> IO ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO ByteString
lazyRead

-- | Read @n@ bytes into a 'ByteString', directly from the
-- specified 'Handle', in chunks of size @k@.
--
hGetN :: Int -> Handle -> Int -> IO ByteString
hGetN :: Int -> Handle -> Int -> IO ByteString
hGetN Int
k Handle
h Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 = Int -> IO ByteString
readChunks Int
n
  where
    readChunks :: Int -> IO ByteString
readChunks !Int
i = do
        ByteString
c <- Handle -> Int -> IO ByteString
S.hGet Handle
h (Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
k Int
i)
        case ByteString -> Int
S.length ByteString
c of
            Int
0 -> ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
Empty
            Int
m -> do ByteString
cs <- Int -> IO ByteString
readChunks (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
m)
                    ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> ByteString -> ByteString
Chunk ByteString
c ByteString
cs)

hGetN Int
_ Handle
_ Int
0 = ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
Empty
hGetN Int
_ Handle
h Int
n = Handle -> String -> Int -> IO ByteString
forall a. Handle -> String -> Int -> IO a
illegalBufferSize Handle
h String
"hGet" Int
n

-- | hGetNonBlockingN is similar to 'hGetContentsN', except that it will never block
-- waiting for data to become available, instead it returns only whatever data
-- is available. Chunks are read on demand, in @k@-sized chunks.
--
hGetNonBlockingN :: Int -> Handle -> Int -> IO ByteString
hGetNonBlockingN :: Int -> Handle -> Int -> IO ByteString
hGetNonBlockingN Int
k Handle
h Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0= Int -> IO ByteString
readChunks Int
n
  where
    readChunks :: Int -> IO ByteString
readChunks !Int
i = do
        ByteString
c <- Handle -> Int -> IO ByteString
S.hGetNonBlocking Handle
h (Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
k Int
i)
        case ByteString -> Int
S.length ByteString
c of
            Int
0 -> ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
Empty
            Int
m -> do ByteString
cs <- Int -> IO ByteString
readChunks (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
m)
                    ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> ByteString -> ByteString
Chunk ByteString
c ByteString
cs)

hGetNonBlockingN Int
_ Handle
_ Int
0 = ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
Empty
hGetNonBlockingN Int
_ Handle
h Int
n = Handle -> String -> Int -> IO ByteString
forall a. Handle -> String -> Int -> IO a
illegalBufferSize Handle
h String
"hGetNonBlocking" Int
n

illegalBufferSize :: Handle -> String -> Int -> IO a
illegalBufferSize :: forall a. Handle -> String -> Int -> IO a
illegalBufferSize Handle
handle String
fn Int
sz =
    IOError -> IO a
forall a. IOError -> IO a
ioError (IOErrorType -> String -> Maybe Handle -> Maybe String -> IOError
mkIOError IOErrorType
illegalOperationErrorType String
msg (Handle -> Maybe Handle
forall a. a -> Maybe a
Just Handle
handle) Maybe String
forall a. Maybe a
Nothing)
    --TODO: System.IO uses InvalidArgument here, but it's not exported :-(
    where
      msg :: String
msg = String
fn String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
": illegal ByteString size " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> Int -> String -> String
forall a. Show a => Int -> a -> String -> String
showsPrec Int
9 Int
sz []

-- | Read entire handle contents /lazily/ into a 'ByteString'. Chunks
-- are read on demand, using the default chunk size.
--
-- File handles are closed on EOF if all the file is read, or through
-- garbage collection otherwise.
--
hGetContents :: Handle -> IO ByteString
hGetContents :: Handle -> IO ByteString
hGetContents = Int -> Handle -> IO ByteString
hGetContentsN Int
defaultChunkSize

-- | Read @n@ bytes into a 'ByteString', directly from the specified 'Handle'.
--
hGet :: Handle -> Int -> IO ByteString
hGet :: Handle -> Int -> IO ByteString
hGet = Int -> Handle -> Int -> IO ByteString
hGetN Int
defaultChunkSize

-- | hGetNonBlocking is similar to 'hGet', except that it will never block
-- waiting for data to become available, instead it returns only whatever data
-- is available.  If there is no data available to be read, 'hGetNonBlocking'
-- returns 'empty'.
--
-- Note: on Windows and with Haskell implementation other than GHC, this
-- function does not work correctly; it behaves identically to 'hGet'.
--
hGetNonBlocking :: Handle -> Int -> IO ByteString
hGetNonBlocking :: Handle -> Int -> IO ByteString
hGetNonBlocking = Int -> Handle -> Int -> IO ByteString
hGetNonBlockingN Int
defaultChunkSize

-- | Read an entire file /lazily/ into a 'ByteString'.
--
-- The 'Handle' will be held open until EOF is encountered.
--
-- Note that this function's implementation relies on 'hGetContents'.
-- The reader is advised to read its documentation.
--
readFile :: FilePath -> IO ByteString
readFile :: String -> IO ByteString
readFile String
f = String -> IOMode -> IO Handle
openBinaryFile String
f IOMode
ReadMode IO Handle -> (Handle -> IO ByteString) -> IO ByteString
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Handle -> IO ByteString
hGetContents

modifyFile :: IOMode -> FilePath -> ByteString -> IO ()
modifyFile :: IOMode -> String -> ByteString -> IO ()
modifyFile IOMode
mode String
f ByteString
txt = String -> IOMode -> (Handle -> IO ()) -> IO ()
forall r. String -> IOMode -> (Handle -> IO r) -> IO r
withBinaryFile String
f IOMode
mode (Handle -> ByteString -> IO ()
`hPut` ByteString
txt)

-- | Write a 'ByteString' to a file.
--
writeFile :: FilePath -> ByteString -> IO ()
writeFile :: String -> ByteString -> IO ()
writeFile = IOMode -> String -> ByteString -> IO ()
modifyFile IOMode
WriteMode

-- | Append a 'ByteString' to a file.
--
appendFile :: FilePath -> ByteString -> IO ()
appendFile :: String -> ByteString -> IO ()
appendFile = IOMode -> String -> ByteString -> IO ()
modifyFile IOMode
AppendMode

-- | getContents. Equivalent to hGetContents stdin. Will read /lazily/
--
getContents :: IO ByteString
getContents :: IO ByteString
getContents = Handle -> IO ByteString
hGetContents Handle
stdin

-- | Outputs a 'ByteString' to the specified 'Handle'.
--
-- The chunks will be
-- written one at a time. Other threads might write to the 'Handle' in between,
-- and hence 'hPut' alone is not suitable for concurrent writes.
--
hPut :: Handle -> ByteString -> IO ()
hPut :: Handle -> ByteString -> IO ()
hPut Handle
h = (ByteString -> IO () -> IO ()) -> IO () -> ByteString -> IO ()
forall a. (ByteString -> a -> a) -> a -> ByteString -> a
foldrChunks (\ByteString
c IO ()
rest -> Handle -> ByteString -> IO ()
S.hPut Handle
h ByteString
c IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO ()
rest) (() -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ())

-- | Similar to 'hPut' except that it will never block. Instead it returns
-- any tail that did not get written. This tail may be 'empty' in the case that
-- the whole string was written, or the whole original string if nothing was
-- written. Partial writes are also possible.
--
-- Note: on Windows and with Haskell implementation other than GHC, this
-- function does not work correctly; it behaves identically to 'hPut'.
--
hPutNonBlocking :: Handle -> ByteString -> IO ByteString
hPutNonBlocking :: Handle -> ByteString -> IO ByteString
hPutNonBlocking Handle
_ ByteString
Empty           = ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
Empty
hPutNonBlocking Handle
h bs :: ByteString
bs@(Chunk ByteString
c ByteString
cs) = do
  ByteString
c' <- Handle -> ByteString -> IO ByteString
S.hPutNonBlocking Handle
h ByteString
c
  case ByteString -> Int
S.length ByteString
c' of
    Int
l' | Int
l' Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString -> Int
S.length ByteString
c -> Handle -> ByteString -> IO ByteString
hPutNonBlocking Handle
h ByteString
cs
    Int
0                     -> ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
bs
    Int
_                     -> ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> ByteString -> ByteString
Chunk ByteString
c' ByteString
cs)

-- | A synonym for 'hPut', for compatibility
--
hPutStr :: Handle -> ByteString -> IO ()
hPutStr :: Handle -> ByteString -> IO ()
hPutStr = Handle -> ByteString -> IO ()
hPut

-- | Write a ByteString to 'stdout'.
--
-- The chunks will be
-- written one at a time. Other threads might write to the 'stdout' in between,
-- and hence 'putStr' alone is not suitable for concurrent writes.
--
putStr :: ByteString -> IO ()
putStr :: ByteString -> IO ()
putStr = Handle -> ByteString -> IO ()
hPut Handle
stdout

-- | The interact function takes a function of type @ByteString -> ByteString@
-- as its argument. The entire input from the standard input device is passed
-- to this function as its argument, and the resulting string is output on the
-- standard output device.
--
interact :: (ByteString -> ByteString) -> IO ()
interact :: (ByteString -> ByteString) -> IO ()
interact ByteString -> ByteString
transformer = ByteString -> IO ()
putStr (ByteString -> IO ())
-> (ByteString -> ByteString) -> ByteString -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
transformer (ByteString -> IO ()) -> IO ByteString -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO ByteString
getContents

-- ---------------------------------------------------------------------
-- Internal utilities

-- Common up near identical calls to `error' to reduce the number
-- constant strings created when compiled:
errorEmptyList :: HasCallStack => String -> a
errorEmptyList :: forall a. HasCallStack => String -> a
errorEmptyList String
fun = String -> String -> a
forall a. HasCallStack => String -> String -> a
moduleError String
fun String
"empty ByteString"
{-# NOINLINE errorEmptyList #-}

moduleError :: HasCallStack => String -> String -> a
moduleError :: forall a. HasCallStack => String -> String -> a
moduleError String
fun String
msg = String -> a
forall a. HasCallStack => String -> a
error (String
"Data.ByteString.Lazy." String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
fun String -> String -> String
forall a. [a] -> [a] -> [a]
++ Char
':'Char -> String -> String
forall a. a -> [a] -> [a]
:Char
' 'Char -> String -> String
forall a. a -> [a] -> [a]
:String
msg)
{-# NOINLINE moduleError #-}


-- reverse a list of non-empty chunks into a lazy ByteString
revNonEmptyChunks :: [P.ByteString] -> ByteString
revNonEmptyChunks :: [ByteString] -> ByteString
revNonEmptyChunks = (ByteString -> ByteString -> ByteString)
-> ByteString -> [ByteString] -> ByteString
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl' ((ByteString -> ByteString -> ByteString)
-> ByteString -> ByteString -> ByteString
forall a b c. (a -> b -> c) -> b -> a -> c
flip ByteString -> ByteString -> ByteString
Chunk) ByteString
Empty

-- reverse a list of possibly-empty chunks into a lazy ByteString
revChunks :: [P.ByteString] -> ByteString
revChunks :: [ByteString] -> ByteString
revChunks = (ByteString -> ByteString -> ByteString)
-> ByteString -> [ByteString] -> ByteString
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl' ((ByteString -> ByteString -> ByteString)
-> ByteString -> ByteString -> ByteString
forall a b c. (a -> b -> c) -> b -> a -> c
flip ByteString -> ByteString -> ByteString
chunk) ByteString
Empty

-- $IOChunk
--
-- ⚠ Using lazy I\/O functions like 'readFile' or 'hGetContents'
-- means that the order of operations such as closing the file handle
-- is left at the discretion of the RTS.
-- Hence, the developer can face some issues when:
--
-- * The program reads a file and writes the same file. This means that the file
--   may be locked because the handler has not been released when 'writeFile' is executed.
-- * The program reads thousands of files, but due to lazy evaluation, the OS's file descriptor
--   limit is reached before the handlers can be released.
--
-- === Why?
--
-- Consider the following program:
--
-- > import qualified Data.ByteString.Lazy as BL
-- > main = do
-- >   _ <- BL.readFile "foo.txt"
-- >   BL.writeFile "foo.txt" mempty
--
-- Generally, in the 'IO' monad side effects happen
-- sequentially and in full. Therefore, one might reasonably expect that
-- reading the whole file via 'readFile' executes all three actions
-- (open the file handle, read its content, close the file handle) before
-- control moves to the following 'writeFile' action. This expectation holds
-- for the strict "Data.ByteString" API. However, the above lazy 'ByteString' variant
-- of the program fails with @openBinaryFile: resource busy (file is locked)@.
--
-- The reason for this is that "Data.ByteString.Lazy" is specifically designed
-- to handle large or unbounded streams of data incrementally, without requiring all the data
-- to be resident in memory at the same time. Incremental processing would not be possible
-- if 'readFile' were to follow the usual rules of 'IO': evaluating all side effects
-- would require reading the file in full and closing its handle before returning from 'readFile'. This is why
-- 'readFile' (and 'hGetContents' in general) is implemented
-- via 'unsafeInterleaveIO', which allows 'IO' side effects to be delayed and
-- interleaved with subsequent processing of the return value.
-- That's exactly what happens
-- in the example above: 'readFile' opens a file handle, but since the content
-- is not fully consumed, the file handle remains open, allowing the content to
-- read __on demand__ (never in this case, since the return value is ignored).
-- So when 'writeFile' is executed next, @foo.txt@ is still open for reading and
-- the RTS takes care to avoid simultaneously opening it for writing, instead
-- returning the error shown above.
--
-- === How to enforce the order of effects?
--
-- If the content is small enough to fit in memory,
-- consider using strict 'Data.ByteString.readFile',
-- potentially applying 'fromStrict' afterwards. E. g.,
--
-- > import qualified Data.ByteString as BS
-- > import qualified Data.ByteString.Lazy as BL
-- > main = do
-- >   _ <- BS.readFile "foo.txt"
-- >   BL.writeFile "foo.txt" mempty
--
-- If you are dealing with large or unbounded data streams,
-- consider reaching out for a specialised package, such as
-- <http://hackage.haskell.org/package/conduit conduit>,
-- <http://hackage.haskell.org/package/machines-bytestring machines-bytestring>,
-- <http://hackage.haskell.org/package/pipes-bytestring pipes-bytestring>,
-- <http://hackage.haskell.org/package/streaming-bytestring streaming-bytestring>,
-- <http://hackage.haskell.org/package/streamly-bytestring streamly-bytestring>,
-- etc.