{-# LANGUAGE CPP, BangPatterns #-}
{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}
{-# OPTIONS_HADDOCK prune #-}
#if __GLASGOW_HASKELL__ >= 701
{-# LANGUAGE Trustworthy #-}
#endif

-- |
-- 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 (

        -- * The @ByteString@ type
        ByteString,             -- instances: Eq, Ord, Show, Read, Data, Typeable

        -- * Introducing and eliminating 'ByteString's
        empty,                  -- :: ByteString
        singleton,              -- :: Word8   -> ByteString
        pack,                   -- :: [Word8] -> ByteString
        unpack,                 -- :: ByteString -> [Word8]
        fromStrict,             -- :: Strict.ByteString -> ByteString
        toStrict,               -- :: ByteString -> Strict.ByteString
        fromChunks,             -- :: [Strict.ByteString] -> ByteString
        toChunks,               -- :: ByteString -> [Strict.ByteString]
        foldrChunks,            -- :: (S.ByteString -> a -> a) -> a -> ByteString -> a
        foldlChunks,            -- :: (a -> S.ByteString -> a) -> a -> ByteString -> a

        -- * Basic interface
        cons,                   -- :: Word8 -> ByteString -> ByteString
        cons',                  -- :: Word8 -> ByteString -> ByteString
        snoc,                   -- :: ByteString -> Word8 -> ByteString
        append,                 -- :: ByteString -> ByteString -> ByteString
        head,                   -- :: ByteString -> Word8
        uncons,                 -- :: ByteString -> Maybe (Word8, ByteString)
        unsnoc,                 -- :: ByteString -> Maybe (ByteString, Word8)
        last,                   -- :: ByteString -> Word8
        tail,                   -- :: ByteString -> ByteString
        init,                   -- :: ByteString -> ByteString
        null,                   -- :: ByteString -> Bool
        length,                 -- :: ByteString -> Int64

        -- * Transforming ByteStrings
        map,                    -- :: (Word8 -> Word8) -> ByteString -> ByteString
        reverse,                -- :: ByteString -> ByteString
        intersperse,            -- :: Word8 -> ByteString -> ByteString
        intercalate,            -- :: ByteString -> [ByteString] -> ByteString
        transpose,              -- :: [ByteString] -> [ByteString]

        -- * Reducing 'ByteString's (folds)
        foldl,                  -- :: (a -> Word8 -> a) -> a -> ByteString -> a
        foldl',                 -- :: (a -> Word8 -> a) -> a -> ByteString -> a
        foldl1,                 -- :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8
        foldl1',                -- :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8
        foldr,                  -- :: (Word8 -> a -> a) -> a -> ByteString -> a
        foldr1,                 -- :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8

        -- ** Special folds
        concat,                 -- :: [ByteString] -> ByteString
        concatMap,              -- :: (Word8 -> ByteString) -> ByteString -> ByteString
        any,                    -- :: (Word8 -> Bool) -> ByteString -> Bool
        all,                    -- :: (Word8 -> Bool) -> ByteString -> Bool
        maximum,                -- :: ByteString -> Word8
        minimum,                -- :: ByteString -> Word8

        -- * Building ByteStrings
        -- ** Scans
        scanl,                  -- :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString
--        scanl1,                 -- :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString
--        scanr,                  -- :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString
--        scanr1,                 -- :: (Word8 -> Word8 -> Word8) -> ByteString -> ByteString

        -- ** Accumulating maps
        mapAccumL,              -- :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)
        mapAccumR,              -- :: (acc -> Word8 -> (acc, Word8)) -> acc -> ByteString -> (acc, ByteString)

        -- ** Infinite ByteStrings
        repeat,                 -- :: Word8 -> ByteString
        replicate,              -- :: Int64 -> Word8 -> ByteString
        cycle,                  -- :: ByteString -> ByteString
        iterate,                -- :: (Word8 -> Word8) -> Word8 -> ByteString

        -- ** Unfolding ByteStrings
        unfoldr,                -- :: (a -> Maybe (Word8, a)) -> a -> ByteString

        -- * Substrings

        -- ** Breaking strings
        take,                   -- :: Int64 -> ByteString -> ByteString
        drop,                   -- :: Int64 -> ByteString -> ByteString
        splitAt,                -- :: Int64 -> ByteString -> (ByteString, ByteString)
        takeWhile,              -- :: (Word8 -> Bool) -> ByteString -> ByteString
        dropWhile,              -- :: (Word8 -> Bool) -> ByteString -> ByteString
        span,                   -- :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
        break,                  -- :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
        group,                  -- :: ByteString -> [ByteString]
        groupBy,                -- :: (Word8 -> Word8 -> Bool) -> ByteString -> [ByteString]
        inits,                  -- :: ByteString -> [ByteString]
        tails,                  -- :: ByteString -> [ByteString]
        stripPrefix,            -- :: ByteString -> ByteString -> Maybe ByteString
        stripSuffix,            -- :: ByteString -> ByteString -> Maybe ByteString

        -- ** Breaking into many substrings
        split,                  -- :: Word8 -> ByteString -> [ByteString]
        splitWith,              -- :: (Word8 -> Bool) -> ByteString -> [ByteString]

        -- * Predicates
        isPrefixOf,             -- :: ByteString -> ByteString -> Bool
        isSuffixOf,             -- :: ByteString -> ByteString -> Bool
--        isInfixOf,              -- :: ByteString -> ByteString -> Bool

        -- ** Search for arbitrary substrings
--        isSubstringOf,          -- :: ByteString -> ByteString -> Bool
--        findSubstring,          -- :: ByteString -> ByteString -> Maybe Int
--        findSubstrings,         -- :: ByteString -> ByteString -> [Int]

        -- * Searching ByteStrings

        -- ** Searching by equality
        elem,                   -- :: Word8 -> ByteString -> Bool
        notElem,                -- :: Word8 -> ByteString -> Bool

        -- ** Searching with a predicate
        find,                   -- :: (Word8 -> Bool) -> ByteString -> Maybe Word8
        filter,                 -- :: (Word8 -> Bool) -> ByteString -> ByteString
        partition,              -- :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)

        -- * Indexing ByteStrings
        index,                  -- :: ByteString -> Int64 -> Word8
        elemIndex,              -- :: Word8 -> ByteString -> Maybe Int64
        elemIndexEnd,           -- :: Word8 -> ByteString -> Maybe Int64
        elemIndices,            -- :: Word8 -> ByteString -> [Int64]
        findIndex,              -- :: (Word8 -> Bool) -> ByteString -> Maybe Int64
        findIndices,            -- :: (Word8 -> Bool) -> ByteString -> [Int64]
        count,                  -- :: Word8 -> ByteString -> Int64

        -- * Zipping and unzipping ByteStrings
        zip,                    -- :: ByteString -> ByteString -> [(Word8,Word8)]
        zipWith,                -- :: (Word8 -> Word8 -> c) -> ByteString -> ByteString -> [c]
        unzip,                  -- :: [(Word8,Word8)] -> (ByteString,ByteString)

        -- * Ordered ByteStrings
--        sort,                   -- :: ByteString -> ByteString

        -- * Low level conversions
        -- ** Copying ByteStrings
        copy,                   -- :: ByteString -> ByteString
--        defrag,                -- :: ByteString -> ByteString

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

        -- ** Standard input and output
        getContents,            -- :: IO ByteString
        putStr,                 -- :: ByteString -> IO ()
        putStrLn,               -- :: ByteString -> IO ()
        interact,               -- :: (ByteString -> ByteString) -> IO ()

        -- ** Files
        readFile,               -- :: FilePath -> IO ByteString
        writeFile,              -- :: FilePath -> ByteString -> IO ()
        appendFile,             -- :: FilePath -> ByteString -> IO ()

        -- ** I\/O with Handles
        hGetContents,           -- :: Handle -> IO ByteString
        hGet,                   -- :: Handle -> Int -> IO ByteString
        hGetNonBlocking,        -- :: Handle -> Int -> IO ByteString
        hPut,                   -- :: Handle -> ByteString -> IO ()
        hPutNonBlocking,        -- :: Handle -> ByteString -> IO ByteString
        hPutStr,                -- :: Handle -> ByteString -> IO ()

  ) where

import Prelude hiding
    (reverse,head,tail,last,init,null,length,map,lines,foldl,foldr,unlines
    ,concat,any,take,drop,splitAt,takeWhile,dropWhile,span,break,elem,filter,maximum
    ,minimum,all,concatMap,foldl1,foldr1,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 L  -- L for list/lazy
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 as S
import qualified Data.ByteString.Unsafe as S
import Data.ByteString.Lazy.Internal

#if !(MIN_VERSION_base(4,8,0))
import Control.Applicative      ((<$>))
import Data.Monoid              (Monoid(..))
#endif
import Control.Monad            (mplus)
import Data.Word                (Word8)
import Data.Int                 (Int64)
import System.IO                (Handle,openBinaryFile,stdin,stdout,withBinaryFile,IOMode(..)
                                ,hClose)
import System.IO.Error          (mkIOError, illegalOperationErrorType)
import System.IO.Unsafe

import Foreign.ForeignPtr       (withForeignPtr)
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]
cs = (ByteString -> ByteString -> ByteString)
-> ByteString -> [ByteString] -> ByteString
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
L.foldr ByteString -> ByteString -> ByteString
chunk ByteString
Empty [ByteString]
cs

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

-- |/O(1)/ Convert a strict 'ByteString' into a lazy 'ByteString'.
fromStrict :: P.ByteString -> ByteString
fromStrict :: ByteString -> ByteString
fromStrict ByteString
bs | ByteString -> Bool
S.null ByteString
bs = ByteString
Empty
              | Bool
otherwise = ByteString -> ByteString -> ByteString
Chunk ByteString
bs ByteString
Empty

-- |/O(n)/ Convert a lazy 'ByteString' into a strict 'ByteString'.
--
-- Note that this is an /expensive/ operation that forces the whole lazy
-- ByteString into memory and then copies all the data. If possible, try to
-- avoid converting back and forth between strict and lazy bytestrings.
--
toStrict :: ByteString -> S.ByteString
toStrict :: ByteString -> ByteString
toStrict = \ByteString
cs -> ByteString -> ByteString -> ByteString
goLen0 ByteString
cs ByteString
cs
    -- We pass the original [ByteString] (bss0) through as an argument through
    -- goLen0, goLen1, and goLen since we will need it again in goCopy. Passing
    -- it as an explicit argument avoids capturing it in these functions'
    -- closures which would result in unnecessary closure allocation.
  where
    -- It's still possible that the result is empty
    goLen0 :: ByteString -> ByteString -> ByteString
goLen0 ByteString
_   ByteString
Empty                   = ByteString
S.empty
    goLen0 ByteString
cs0 (Chunk ByteString
c ByteString
cs) | ByteString -> Bool
S.null ByteString
c = ByteString -> ByteString -> ByteString
goLen0 ByteString
cs0 ByteString
cs
    goLen0 ByteString
cs0 (Chunk ByteString
c ByteString
cs)            = ByteString -> ByteString -> ByteString -> ByteString
goLen1 ByteString
cs0 ByteString
c ByteString
cs

    -- It's still possible that the result is a single chunk
    goLen1 :: ByteString -> ByteString -> ByteString -> ByteString
goLen1 ByteString
_   ByteString
bs ByteString
Empty                = ByteString
bs
    goLen1 ByteString
cs0 ByteString
bs (Chunk ByteString
c ByteString
cs)
      | ByteString -> Bool
S.null ByteString
c                   = ByteString -> ByteString -> ByteString -> ByteString
goLen1 ByteString
cs0 ByteString
bs ByteString
cs
      | Bool
otherwise                  =
        ByteString -> Int -> ByteString -> ByteString
goLen ByteString
cs0 (String -> Int -> Int -> Int
S.checkedAdd String
"Lazy.concat" (ByteString -> Int
S.length ByteString
bs) (ByteString -> Int
S.length ByteString
c)) ByteString
cs

    -- General case, just find the total length we'll need
    goLen :: ByteString -> Int -> ByteString -> ByteString
goLen ByteString
cs0 !Int
total (Chunk ByteString
c ByteString
cs)      = ByteString -> Int -> ByteString -> ByteString
goLen ByteString
cs0 Int
total' ByteString
cs
      where
        total' :: Int
total' = String -> Int -> Int -> Int
S.checkedAdd String
"Lazy.concat" Int
total (ByteString -> Int
S.length ByteString
c)
    goLen ByteString
cs0 Int
total ByteString
Empty =
      Int -> (Ptr Word8 -> IO ()) -> ByteString
S.unsafeCreate Int
total ((Ptr Word8 -> IO ()) -> ByteString)
-> (Ptr Word8 -> IO ()) -> ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
ptr -> ByteString -> Ptr Word8 -> IO ()
goCopy ByteString
cs0 Ptr Word8
ptr

    -- Copy the data
    goCopy :: ByteString -> Ptr Word8 -> IO ()
goCopy ByteString
Empty                        !Ptr Word8
_   = () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
    goCopy (Chunk (S.PS ForeignPtr Word8
_  Int
_   Int
0  ) ByteString
cs) !Ptr Word8
ptr = ByteString -> Ptr Word8 -> IO ()
goCopy ByteString
cs Ptr Word8
ptr
    goCopy (Chunk (S.PS ForeignPtr Word8
fp Int
off Int
len) ByteString
cs) !Ptr Word8
ptr = do
      ForeignPtr Word8 -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
fp ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p -> do
        Ptr Word8 -> Ptr Word8 -> Int -> IO ()
S.memcpy Ptr Word8
ptr (Ptr Word8
p Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
off) Int
len
        ByteString -> Ptr Word8 -> IO ()
goCopy ByteString
cs (Ptr Word8
ptr Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
len)
-- See the comment on Data.ByteString.Internal.concat for some background on
-- this implementation.

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

{-
-- | /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(n\/c)/ 'length' returns the length of a ByteString as an 'Int64'
length :: ByteString -> Int64
length :: ByteString -> Int64
length ByteString
cs = (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 ByteString
cs
{-# INLINE length #-}

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

-- | /O(1)/ 'cons' is analogous to '(:)' for lists.
--
cons :: Word8 -> ByteString -> ByteString
cons :: Word8 -> ByteString -> ByteString
cons Word8
c ByteString
cs = ByteString -> ByteString -> ByteString
Chunk (Word8 -> ByteString
S.singleton Word8
c) ByteString
cs
{-# 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.
head :: ByteString -> Word8
head :: ByteString -> Word8
head ByteString
Empty       = String -> Word8
forall a. 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)
    = (Word8, ByteString) -> Maybe (Word8, ByteString)
forall a. a -> Maybe a
Just (ByteString -> Word8
S.unsafeHead ByteString
c,
            if ByteString -> Int
S.length ByteString
c Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 then ByteString
cs else 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.
tail :: ByteString -> ByteString
tail :: ByteString -> ByteString
tail ByteString
Empty          = String -> ByteString
forall a. 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.
last :: ByteString -> Word8
last :: ByteString -> Word8
last ByteString
Empty          = String -> Word8
forall a. 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)/ Return all the elements of a 'ByteString' except the last one.
init :: ByteString -> ByteString
init :: ByteString -> ByteString
init ByteString
Empty          = String -> ByteString
forall a. 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 (ByteString -> ByteString
init (ByteString -> ByteString -> ByteString
Chunk ByteString
c ByteString
cs), 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
s = ByteString -> ByteString
go ByteString
s
    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
cs0 = ByteString -> ByteString -> ByteString
rev ByteString
Empty ByteString
cs0
  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.PS ForeignPtr Word8
fp Int
o Int
l) =
          Int -> (Ptr Word8 -> IO ()) -> ByteString
S.unsafeCreate (Int
2Int -> Int -> Int
forall a. Num a => a -> a -> a
*Int
l) ((Ptr Word8 -> IO ()) -> ByteString)
-> (Ptr Word8 -> IO ()) -> ByteString
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
withForeignPtr 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 -> CULong -> 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 Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
o) (Int -> CULong
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]
L.map (\[Word8]
ss -> ByteString -> ByteString -> ByteString
Chunk ([Word8] -> ByteString
S.pack [Word8]
ss) ByteString
Empty)
                      ([[Word8]] -> [[Word8]]
forall a. [[a]] -> [[a]]
L.transpose ((ByteString -> [Word8]) -> [ByteString] -> [[Word8]]
forall a b. (a -> b) -> [a] -> [b]
L.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 :: (a -> Word8 -> a) -> a -> ByteString -> a
foldl a -> Word8 -> a
f a
z = a -> ByteString -> a
go a
z
  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' :: (a -> Word8 -> a) -> a -> ByteString -> a
foldl' a -> Word8 -> a
f a
z = a -> ByteString -> a
go a
z
  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 :: (Word8 -> a -> a) -> a -> ByteString -> a
foldr Word8 -> a -> a
k a
z = (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)) a
z
{-# INLINE foldr #-}

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

-- | 'foldl1'' is like 'foldl1', but strict in the accumulator.
foldl1' :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8
foldl1' :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8
foldl1' Word8 -> Word8 -> Word8
_ ByteString
Empty        = String -> Word8
forall a. String -> a
errorEmptyList String
"foldl1'"
foldl1' Word8 -> Word8 -> Word8
f (Chunk ByteString
c ByteString
cs) = (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> Word8
forall a. (a -> Word8 -> a) -> a -> ByteString -> a
foldl' Word8 -> Word8 -> Word8
f (ByteString -> Word8
S.unsafeHead ByteString
c) (ByteString -> ByteString -> ByteString
Chunk (ByteString -> ByteString
S.unsafeTail ByteString
c) ByteString
cs)

-- | 'foldr1' is a variant of 'foldr' that has no starting value argument,
-- and thus must be applied to non-empty 'ByteString's
foldr1 :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8
foldr1 :: (Word8 -> Word8 -> Word8) -> ByteString -> Word8
foldr1 Word8 -> Word8 -> Word8
_ ByteString
Empty          = String -> Word8
forall a. 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         = (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
cs = (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 ByteString
cs
{-# INLINE any #-}
-- todo fuse

-- | /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
cs = (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 ByteString
cs
{-# INLINE all #-}
-- todo fuse

-- | /O(n)/ 'maximum' returns the maximum value from a 'ByteString'
maximum :: ByteString -> Word8
maximum :: ByteString -> Word8
maximum ByteString
Empty        = String -> Word8
forall a. 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` ByteString -> Word8
S.maximum ByteString
c')
                                   (ByteString -> Word8
S.maximum ByteString
c) ByteString
cs
{-# INLINE maximum #-}

-- | /O(n)/ 'minimum' returns the minimum value from a 'ByteString'
minimum :: ByteString -> Word8
minimum :: ByteString -> Word8
minimum ByteString
Empty        = String -> Word8
forall a. 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` ByteString -> Word8
S.minimum ByteString
c')
                                     (ByteString -> Word8
S.minimum ByteString
c) ByteString
cs
{-# INLINE minimum #-}

-- | 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 :: (acc -> Word8 -> (acc, Word8))
-> acc -> ByteString -> (acc, ByteString)
mapAccumL acc -> Word8 -> (acc, Word8)
f acc
s0 = acc -> ByteString -> (acc, ByteString)
go acc
s0
  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 :: (acc -> Word8 -> (acc, Word8))
-> acc -> ByteString -> (acc, ByteString)
mapAccumR acc -> Word8 -> (acc, Word8)
f acc
s0 = acc -> ByteString -> (acc, ByteString)
go acc
s0
  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. This function will fuse.
--
-- > scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]
--
-- Note that
--
-- > last (scanl f z xs) == foldl f z xs.
scanl :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString
scanl :: (Word8 -> Word8 -> Word8) -> Word8 -> ByteString -> ByteString
scanl Word8 -> Word8 -> Word8
f Word8
z = (Word8, ByteString) -> ByteString
forall a b. (a, b) -> b
snd ((Word8, ByteString) -> ByteString)
-> (ByteString -> (Word8, ByteString)) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Word8, ByteString) -> Word8 -> (Word8, ByteString))
-> (Word8, ByteString) -> ByteString -> (Word8, ByteString)
forall a. (a -> Word8 -> a) -> a -> ByteString -> a
foldl (Word8, ByteString) -> Word8 -> (Word8, ByteString)
k (Word8
z,Word8 -> ByteString
singleton Word8
z)
 where
    k :: (Word8, ByteString) -> Word8 -> (Word8, ByteString)
k (Word8
c,ByteString
acc) Word8
a = let n :: Word8
n = Word8 -> Word8 -> Word8
f Word8
c Word8
a in (Word8
n, ByteString
acc ByteString -> Word8 -> ByteString
`snoc` Word8
n)
{-# INLINE scanl #-}

-- ---------------------------------------------------------------------
-- 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 :: ByteString -> ByteString
cycle :: ByteString -> ByteString
cycle ByteString
Empty = String -> ByteString
forall a. 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 :: (a -> Maybe (Word8, a)) -> a -> ByteString
unfoldr a -> Maybe (Word8, a)
f a
z = Int -> a -> ByteString
unfoldChunk Int
32 a
z
  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(n\/c)/ 'drop' @n xs@ returns the suffix of @xs@ after the first @n@
-- elements, or @[]@ 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\/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'')


-- | 'takeWhile', applied to a predicate @p@ and a ByteString @xs@,
-- returns the longest prefix (possibly empty) of @xs@ of elements that
-- satisfy @p@.
takeWhile :: (Word8 -> Bool) -> ByteString -> ByteString
takeWhile :: (Word8 -> Bool) -> ByteString -> ByteString
takeWhile Word8 -> Bool
f ByteString
cs0 = ByteString -> ByteString
takeWhile' ByteString
cs0
  where takeWhile' :: ByteString -> ByteString
takeWhile' ByteString
Empty        = ByteString
Empty
        takeWhile' (Chunk ByteString
c ByteString
cs) =
          case (Word8 -> Bool) -> ByteString -> Int
findIndexOrEnd (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)

-- | 'dropWhile' @p xs@ returns the suffix remaining after 'takeWhile' @p xs@.
dropWhile :: (Word8 -> Bool) -> ByteString -> ByteString
dropWhile :: (Word8 -> Bool) -> ByteString -> ByteString
dropWhile Word8 -> Bool
f ByteString
cs0 = ByteString -> ByteString
dropWhile' ByteString
cs0
  where dropWhile' :: ByteString -> ByteString
dropWhile' ByteString
Empty        = ByteString
Empty
        dropWhile' (Chunk ByteString
c ByteString
cs) =
          case (Word8 -> Bool) -> ByteString -> Int
findIndexOrEnd (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

-- | 'break' @p@ is equivalent to @'span' ('not' . p)@.
break :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
break :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
break Word8 -> Bool
f ByteString
cs0 = ByteString -> (ByteString, ByteString)
break' ByteString
cs0
  where break' :: ByteString -> (ByteString, ByteString)
break' ByteString
Empty        = (ByteString
Empty, ByteString
Empty)
        break' (Chunk ByteString
c ByteString
cs) =
          case (Word8 -> Bool) -> ByteString -> Int
findIndexOrEnd 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'')

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

{-
-- | 'breakByte' breaks its ByteString argument at the first occurence
-- of the specified byte. It is more efficient than 'break' as it is
-- implemented with @memchr(3)@. I.e.
--
-- > break (=='c') "abcd" == breakByte 'c' "abcd"
--
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
-- occurence of a byte other than its argument. It is more efficient
-- than 'span (==)'
--
-- > span  (=='c') "abcd" == spanByte 'c' "abcd"
--
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)
-}

-- | 'span' @p xs@ breaks the ByteString into two segments. It is
-- equivalent to @('takeWhile' p xs, 'dropWhile' p xs)@
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)

-- | /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 (=='a') "aabbaca" == ["","","bb","c",""]
-- > splitWith (=='a') []        == []
--
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) ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: []
        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 '\n' "a\nb\nd\ne" == ["a","b","d","e"]
-- > split 'a'  "aXaXaXa"    == ["","X","X","X",""]
-- > split 'x'  "x"          == ["",""]
--
-- 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 'ByteStrings' 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) ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: []
        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 sublist 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 ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: []
    to [ByteString]
acc !Word8
w (Chunk ByteString
c ByteString
cs) =
      case (Word8 -> Bool) -> ByteString -> Int
findIndexOrEnd (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 ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: []
    to [ByteString]
acc !Word8
w (Chunk ByteString
c ByteString
cs) =
      case (Word8 -> Bool) -> ByteString -> Int
findIndexOrEnd (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]
L.intersperse ByteString
s

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

-- | /O(c)/ 'ByteString' index (subscript) operator, starting from 0.
index :: ByteString -> Int64 -> Word8
index :: 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. 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. 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(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 ByteString
cs0 = Int64 -> ByteString -> Maybe Int64
forall a. Num a => a -> ByteString -> Maybe a
elemIndex' Int64
0 ByteString
cs0
  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 ==
-- > (-) (length xs - 1) `fmap` elemIndex c (reverse xs)
--
-- @since 0.10.6.0
elemIndexEnd :: Word8 -> ByteString -> Maybe Int64
elemIndexEnd :: Word8 -> ByteString -> Maybe Int64
elemIndexEnd Word8
w = Int -> ByteString -> Maybe Int64
forall a. Num a => Int -> ByteString -> Maybe a
elemIndexEnd' Int
0
  where
    elemIndexEnd' :: Int -> ByteString -> Maybe a
elemIndexEnd' Int
_ ByteString
Empty = Maybe a
forall a. Maybe a
Nothing
    elemIndexEnd' 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) -> Maybe Int -> Maybe a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (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
+)) (Maybe Int -> Maybe a) -> Maybe Int -> Maybe a
forall a b. (a -> b) -> a -> b
$ Word8 -> ByteString -> Maybe Int
S.elemIndexEnd Word8
w ByteString
c
      in Int -> ByteString -> Maybe a
elemIndexEnd' Int
n' ByteString
cs Maybe a -> Maybe a -> Maybe a
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
`mplus` Maybe a
i

-- | /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 ByteString
cs0 = Int64 -> ByteString -> [Int64]
forall a. Num a => a -> ByteString -> [a]
elemIndices' Int64
0 ByteString
cs0
  where elemIndices' :: a -> ByteString -> [a]
elemIndices' a
_ ByteString
Empty        = []
        elemIndices' a
n (Chunk ByteString
c ByteString
cs) = (Int -> a) -> [Int] -> [a]
forall a b. (a -> b) -> [a] -> [b]
L.map ((a -> a -> a
forall a. Num a => a -> a -> a
+a
n)(a -> a) -> (Int -> a) -> Int -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral) (Word8 -> ByteString -> [Int]
S.elemIndices Word8
w ByteString
c)
                             [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ a -> ByteString -> [a]
elemIndices' (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

-- | 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 ByteString
cs = (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 ByteString
cs

-- | 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 ByteString
cs0 = Int64 -> ByteString -> Maybe Int64
forall a. Num a => a -> ByteString -> Maybe a
findIndex' Int64
0 ByteString
cs0
  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 #-}

-- | /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
cs0 = ByteString -> Maybe Word8
find' ByteString
cs0
  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 ByteString
cs0 = Int64 -> ByteString -> [Int64]
forall a. Num a => a -> ByteString -> [a]
findIndices' Int64
0 ByteString
cs0
  where findIndices' :: a -> ByteString -> [a]
findIndices' a
_ ByteString
Empty        = []
        findIndices' a
n (Chunk ByteString
c ByteString
cs) = (Int -> a) -> [Int] -> [a]
forall a b. (a -> b) -> [a] -> [b]
L.map ((a -> a -> a
forall a. Num a => a -> a -> a
+a
n)(a -> a) -> (Int -> a) -> Int -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral) ((Word8 -> Bool) -> ByteString -> [Int]
S.findIndices Word8 -> Bool
k ByteString
c)
                             [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ a -> ByteString -> [a]
findIndices' (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

-- ---------------------------------------------------------------------
-- 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 -> ByteString -> Bool
elem Word8
w 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
s = ByteString -> ByteString
go ByteString
s
    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 :: (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

-- | /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]
L.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]
L.map (Word8, Word8) -> Word8
forall a b. (a, b) -> b
snd [(Word8, Word8)]
ls))
{-# INLINE unzip #-}

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

-- | /O(n)/ Return all initial segments of the given 'ByteString', shortest first.
inits :: ByteString -> [ByteString]
inits :: ByteString -> [ByteString]
inits = (ByteString
Empty ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
:) ([ByteString] -> [ByteString])
-> (ByteString -> [ByteString]) -> ByteString -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
inits'
  where inits' :: ByteString -> [ByteString]
inits' ByteString
Empty        = []
        inits' (Chunk ByteString
c ByteString
cs) = (ByteString -> ByteString) -> [ByteString] -> [ByteString]
forall a b. (a -> b) -> [a] -> [b]
L.map (ByteString -> ByteString -> ByteString
`Chunk` ByteString
Empty) ([ByteString] -> [ByteString]
forall a. [a] -> [a]
L.tail (ByteString -> [ByteString]
S.inits ByteString
c))
                           [ByteString] -> [ByteString] -> [ByteString]
forall a. [a] -> [a] -> [a]
++ (ByteString -> ByteString) -> [ByteString] -> [ByteString]
forall a b. (a -> b) -> [a] -> [b]
L.map (ByteString -> ByteString -> ByteString
Chunk ByteString
c) (ByteString -> [ByteString]
inits' ByteString
cs)

-- | /O(n)/ Return all final segments of the given 'ByteString', longest first.
tails :: ByteString -> [ByteString]
tails :: ByteString -> [ByteString]
tails ByteString
Empty         = ByteString
Empty ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: []
tails cs :: ByteString
cs@(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 ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: ByteString -> [ByteString]
tails ByteString
cs'
  | Bool
otherwise       = ByteString
cs ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: ByteString -> [ByteString]
tails (ByteString -> ByteString -> ByteString
Chunk (ByteString -> ByteString
S.unsafeTail ByteString
c) ByteString
cs')

-- ---------------------------------------------------------------------
-- 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
cs = (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 ByteString
cs
--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.
--
-- Note: the 'Handle' should be placed in binary mode with
-- 'System.IO.hSetBinaryMode' for 'hGetContentsN' to
-- work correctly.
--
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 (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ByteString -> IO ByteString
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
Empty
          else do ByteString
cs <- IO ByteString
lazyRead
                  ByteString -> IO ByteString
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> ByteString -> ByteString
Chunk ByteString
c ByteString
cs)

-- | 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 (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 (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 (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 (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 (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 (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 :: 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.
--
-- Once EOF is encountered, the Handle is closed.
--
-- Note: the 'Handle' should be placed in binary mode with
-- 'System.IO.hSetBinaryMode' for 'hGetContents' to
-- work correctly.
--
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.
--
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 (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' between the
-- writes, and hence 'hPut' alone might not be suitable for concurrent writes.
--
hPut :: Handle -> ByteString -> IO ()
hPut :: Handle -> ByteString -> IO ()
hPut Handle
h ByteString
cs = (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 (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO ()
rest) (() -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()) ByteString
cs

-- | 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 (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 (m :: * -> *) a. Monad m => a -> m a
return ByteString
bs
    Int
_                     -> ByteString -> IO ByteString
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
putStr :: ByteString -> IO ()
putStr :: ByteString -> IO ()
putStr = Handle -> ByteString -> IO ()
hPut Handle
stdout

-- | Write a ByteString to stdout, appending a newline byte
--
putStrLn :: ByteString -> IO ()
putStrLn :: ByteString -> IO ()
putStrLn ByteString
ps = Handle -> ByteString -> IO ()
hPut Handle
stdout ByteString
ps IO () -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Handle -> ByteString -> IO ()
hPut Handle
stdout (Word8 -> ByteString
singleton Word8
0x0a)

{-# DEPRECATED putStrLn
    "Use Data.ByteString.Lazy.Char8.putStrLn instead. (Functions that rely on ASCII encodings belong in Data.ByteString.Lazy.Char8)"
  #-}

-- | 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 :: String -> a
errorEmptyList :: String -> a
errorEmptyList String
fun = String -> String -> a
forall a. String -> String -> a
moduleError String
fun String
"empty ByteString"
{-# NOINLINE errorEmptyList #-}

moduleError :: String -> String -> a
moduleError :: 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]
cs = (ByteString -> ByteString -> ByteString)
-> ByteString -> [ByteString] -> ByteString
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
L.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]
cs

-- reverse a list of possibly-empty chunks into a lazy ByteString
revChunks :: [P.ByteString] -> ByteString
revChunks :: [ByteString] -> ByteString
revChunks [ByteString]
cs = (ByteString -> ByteString -> ByteString)
-> ByteString -> [ByteString] -> ByteString
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
L.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]
cs

-- | 'findIndexOrEnd' is a variant of findIndex, that returns the length
-- of the string if no element is found, rather than Nothing.
findIndexOrEnd :: (Word8 -> Bool) -> P.ByteString -> Int
findIndexOrEnd :: (Word8 -> Bool) -> ByteString -> Int
findIndexOrEnd Word8 -> Bool
k (S.PS ForeignPtr Word8
x Int
s Int
l) =
    IO Int -> Int
forall a. IO a -> a
S.accursedUnutterablePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$
      ForeignPtr Word8 -> (Ptr Word8 -> IO Int) -> IO Int
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
x ((Ptr Word8 -> IO Int) -> IO Int)
-> (Ptr Word8 -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
f -> Ptr Word8 -> Int -> IO Int
go (Ptr Word8
f Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
s) Int
0
  where
    go :: Ptr Word8 -> Int -> IO Int
go !Ptr Word8
ptr !Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
l    = Int -> IO Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
l
               | Bool
otherwise = do Word8
w <- Ptr Word8 -> IO Word8
forall a. Storable a => Ptr a -> IO a
peek Ptr Word8
ptr
                                if Word8 -> Bool
k Word8
w
                                  then Int -> IO Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
n
                                  else Ptr Word8 -> Int -> IO Int
go (Ptr Word8
ptr Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
1) (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
{-# INLINE findIndexOrEnd #-}