{-# LANGUAGE BangPatterns             #-}
{-# LANGUAGE CPP                      #-}
{-# LANGUAGE DeriveDataTypeable       #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE LambdaCase               #-}
{-# LANGUAGE MagicHash                #-}
{-# LANGUAGE MultiWayIf               #-}
{-# LANGUAGE RankNTypes               #-}
{-# LANGUAGE ScopedTypeVariables      #-}
{-# LANGUAGE TemplateHaskellQuotes    #-}
{-# LANGUAGE TupleSections            #-}
{-# LANGUAGE TypeFamilies             #-}
{-# LANGUAGE UnboxedTuples            #-}
{-# LANGUAGE UnliftedFFITypes         #-}
{-# LANGUAGE Unsafe                   #-}

{-# OPTIONS_GHC -fno-warn-name-shadowing -fexpose-all-unfoldings #-}
{-# OPTIONS_HADDOCK not-home #-}

-- Not all architectures are forgiving of unaligned accesses; whitelist ones
-- which are known not to trap (either to the kernel for emulation, or crash).
#if defined(i386_HOST_ARCH) || defined(x86_64_HOST_ARCH) \
    || ((defined(arm_HOST_ARCH) || defined(aarch64_HOST_ARCH)) \
        && defined(__ARM_FEATURE_UNALIGNED)) \
    || defined(powerpc_HOST_ARCH) || defined(powerpc64_HOST_ARCH) \
    || defined(powerpc64le_HOST_ARCH)
#define SAFE_UNALIGNED 1
#endif

-- |
-- Module      : Data.ByteString.Short.Internal
-- Copyright   : (c) Duncan Coutts 2012-2013, Julian Ospald 2022
-- License     : BSD-style
--
-- Maintainer  : hasufell@posteo.de
-- Stability   : stable
-- Portability : ghc only
--
-- Internal representation of ShortByteString
--
module Data.ByteString.Short.Internal (

    -- * The @ShortByteString@ type and representation
    ShortByteString(..),

    -- * Introducing and eliminating 'ShortByteString's
    empty,
    singleton,
    pack,
    unpack,
    fromShort,
    toShort,

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

    -- * Transforming ShortByteStrings
    map,
    reverse,
    intercalate,

    -- * Reducing 'ShortByteString's (folds)
    foldl,
    foldl',
    foldl1,
    foldl1',

    foldr,
    foldr',
    foldr1,
    foldr1',

    -- ** Special folds
    all,
    any,
    concat,

    -- ** Generating and unfolding ByteStrings
    replicate,
    unfoldr,
    unfoldrN,

    -- * Substrings

    -- ** Breaking strings
    take,
    takeEnd,
    takeWhileEnd,
    takeWhile,
    drop,
    dropEnd,
    dropWhile,
    dropWhileEnd,
    breakEnd,
    break,
    span,
    spanEnd,
    splitAt,
    split,
    splitWith,
    stripSuffix,
    stripPrefix,

    -- * Predicates
    isInfixOf,
    isPrefixOf,
    isSuffixOf,

    -- ** Search for arbitrary substrings
    breakSubstring,

    -- * Searching ShortByteStrings

    -- ** Searching by equality
    elem,

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

    -- * Indexing ShortByteStrings
    index,
    indexMaybe,
    (!?),
    elemIndex,
    elemIndices,
    count,
    findIndex,
    findIndices,

    -- * Low level operations
    createFromPtr,
    copyToPtr,

    -- ** Encoding validation
    isValidUtf8,

    -- * Low level conversions
    -- ** Packing 'Foreign.C.String.CString's and pointers
    packCString,
    packCStringLen,

    -- ** Using ShortByteStrings as 'Foreign.C.String.CString's
    useAsCString,
    useAsCStringLen,
  ) where

import Data.ByteString.Internal
  ( ByteString(..)
  , accursedUnutterablePerformIO
  , checkedAdd
  )

import Data.Bits
  ( FiniteBits (finiteBitSize)
  , shiftL
#if MIN_VERSION_base(4,12,0) && defined(SAFE_UNALIGNED)
  , shiftR
#endif
  , (.&.)
  , (.|.)
  )
import Data.Data
  ( Data(..)
  , mkNoRepType
  )
import Data.Monoid
  ( Monoid(..) )
import Data.Semigroup
  ( Semigroup((<>)) )
import Data.String
  ( IsString(..) )
import Data.Typeable
  ( Typeable )
import Control.Applicative
  ( pure )
import Control.DeepSeq
  ( NFData(..) )
import Control.Exception
  ( assert )
import Control.Monad
  ( (>>) )
import Foreign.C.String
  ( CString
  , CStringLen
  )
import Foreign.C.Types
  ( CSize(..)
  , CInt(..)
  , CPtrdiff(..)
  )
import Foreign.ForeignPtr
  ( touchForeignPtr )
import Foreign.ForeignPtr.Unsafe
  ( unsafeForeignPtrToPtr )
import Foreign.Marshal.Alloc
  ( allocaBytes )
import Foreign.Storable
  ( pokeByteOff )
import GHC.Exts
  ( Int(I#), Int#, Ptr(Ptr), Addr#, Char(C#)
  , State#, RealWorld
  , ByteArray#, MutableByteArray#
  , newByteArray#
  , newPinnedByteArray#
  , byteArrayContents#
  , unsafeCoerce#
  , copyMutableByteArray#
#if MIN_VERSION_base(4,10,0)
  , isByteArrayPinned#
  , isTrue#
#endif
#if MIN_VERSION_base(4,11,0)
  , compareByteArrays#
#endif
  , sizeofByteArray#
  , indexWord8Array#, indexCharArray#
  , writeWord8Array#
  , unsafeFreezeByteArray#
#if MIN_VERSION_base(4,12,0) && defined(SAFE_UNALIGNED)
  ,writeWord64Array#
  ,indexWord8ArrayAsWord64#
#endif
  , setByteArray#
  , sizeofByteArray#
  , indexWord8Array#, indexCharArray#
  , writeWord8Array#
  , unsafeFreezeByteArray#
  , touch# )
import GHC.IO
import GHC.ForeignPtr
  ( ForeignPtr(ForeignPtr)
  , ForeignPtrContents(PlainPtr)
  )
import GHC.ST
  ( ST(ST)
  , runST
  )
import GHC.Stack.Types
  ( HasCallStack )
import GHC.Word
import Prelude
  ( Eq(..), Ord(..), Ordering(..), Read(..), Show(..)
  , ($), ($!), error, (++), (.), (||)
  , String, userError
  , Bool(..), (&&), otherwise
  , (+), (-), fromIntegral
  , (*)
  , (^)
  , (<$>)
  , return
  , Maybe(..)
  , not
  , snd
  )

import qualified Data.ByteString.Internal as BS

import qualified Data.Foldable as Foldable
import qualified Data.List as List
import qualified GHC.Exts
import qualified Language.Haskell.TH.Lib as TH
import qualified Language.Haskell.TH.Syntax as TH

-- | A compact representation of a 'Word8' vector.
--
-- It has a lower memory overhead than a 'ByteString' and does not
-- contribute to heap fragmentation. It can be converted to or from a
-- 'ByteString' (at the cost of copying the string data). It supports very few
-- other operations.
--
-- It is suitable for use as an internal representation for code that needs
-- to keep many short strings in memory, but it /should not/ be used as an
-- interchange type. That is, it should not generally be used in public APIs.
-- The 'ByteString' type is usually more suitable for use in interfaces; it is
-- more flexible and it supports a wide range of operations.
--
data ShortByteString = SBS ByteArray#
    deriving Typeable

-- | @since 0.11.2.0
instance TH.Lift ShortByteString where
#if MIN_VERSION_template_haskell(2,16,0)
  lift :: forall (m :: * -> *). Quote m => ShortByteString -> m Exp
lift ShortByteString
sbs = [| unsafePackLenLiteral |]
    m Exp -> m Exp -> m Exp
forall (m :: * -> *). Quote m => m Exp -> m Exp -> m Exp
`TH.appE` Lit -> m Exp
forall (m :: * -> *). Quote m => Lit -> m Exp
TH.litE (Integer -> Lit
TH.integerL (Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len))
    m Exp -> m Exp -> m Exp
forall (m :: * -> *). Quote m => m Exp -> m Exp -> m Exp
`TH.appE` Lit -> m Exp
forall (m :: * -> *). Quote m => Lit -> m Exp
TH.litE (Bytes -> Lit
TH.BytesPrimL (Bytes -> Lit) -> Bytes -> Lit
forall a b. (a -> b) -> a -> b
$ ForeignPtr Word8 -> Word -> Word -> Bytes
TH.Bytes ForeignPtr Word8
ptr Word
0 (Int -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len))
    where
      BS ForeignPtr Word8
ptr Int
len = ShortByteString -> ByteString
fromShort ShortByteString
sbs
#else
  lift sbs = [| unsafePackLenLiteral |]
    `TH.appE` TH.litE (TH.integerL (fromIntegral len))
    `TH.appE` TH.litE (TH.StringPrimL $ BS.unpackBytes bs)
    where
      bs@(BS _ len) = fromShort sbs
#endif

#if MIN_VERSION_template_haskell(2,17,0)
  liftTyped :: forall (m :: * -> *).
Quote m =>
ShortByteString -> Code m ShortByteString
liftTyped = m Exp -> Code m ShortByteString
forall a (m :: * -> *). Quote m => m Exp -> Code m a
TH.unsafeCodeCoerce (m Exp -> Code m ShortByteString)
-> (ShortByteString -> m Exp)
-> ShortByteString
-> Code m ShortByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> m Exp
forall t (m :: * -> *). (Lift t, Quote m) => t -> m Exp
TH.lift
#elif MIN_VERSION_template_haskell(2,16,0)
  liftTyped = TH.unsafeTExpCoerce . TH.lift
#endif

-- The ByteArray# representation is always word sized and aligned but with a
-- known byte length. Our representation choice for ShortByteString is to leave
-- the 0--3 trailing bytes undefined. This means we can use word-sized writes,
-- but we have to be careful with reads, see equateBytes and compareBytes below.


instance Eq ShortByteString where
    == :: ShortByteString -> ShortByteString -> Bool
(==)    = ShortByteString -> ShortByteString -> Bool
equateBytes

instance Ord ShortByteString where
    compare :: ShortByteString -> ShortByteString -> Ordering
compare = ShortByteString -> ShortByteString -> Ordering
compareBytes

instance Semigroup ShortByteString where
    <> :: ShortByteString -> ShortByteString -> ShortByteString
(<>)    = ShortByteString -> ShortByteString -> ShortByteString
append

instance Monoid ShortByteString where
    mempty :: ShortByteString
mempty  = ShortByteString
empty
    mappend :: ShortByteString -> ShortByteString -> ShortByteString
mappend = ShortByteString -> ShortByteString -> ShortByteString
forall a. Semigroup a => a -> a -> a
(<>)
    mconcat :: [ShortByteString] -> ShortByteString
mconcat = [ShortByteString] -> ShortByteString
concat

instance NFData ShortByteString where
    rnf :: ShortByteString -> ()
rnf SBS{} = ()

instance Show ShortByteString where
    showsPrec :: Int -> ShortByteString -> ShowS
showsPrec Int
p ShortByteString
ps String
r = Int -> String -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
p (ShortByteString -> String
unpackChars ShortByteString
ps) String
r

instance Read ShortByteString where
    readsPrec :: Int -> ReadS ShortByteString
readsPrec Int
p String
str = [ (String -> ShortByteString
packChars String
x, String
y) | (String
x, String
y) <- Int -> ReadS String
forall a. Read a => Int -> ReadS a
readsPrec Int
p String
str ]

-- | @since 0.10.12.0
instance GHC.Exts.IsList ShortByteString where
  type Item ShortByteString = Word8
  fromList :: [Item ShortByteString] -> ShortByteString
fromList = [Word8] -> ShortByteString
[Item ShortByteString] -> ShortByteString
packBytes
  toList :: ShortByteString -> [Item ShortByteString]
toList   = ShortByteString -> [Word8]
ShortByteString -> [Item ShortByteString]
unpackBytes

-- | Beware: 'fromString' truncates multi-byte characters to octets.
-- e.g. "枯朶に烏のとまりけり秋の暮" becomes �6k�nh~�Q��n�
instance IsString ShortByteString where
    fromString :: String -> ShortByteString
fromString = String -> ShortByteString
packChars

instance Data ShortByteString where
  gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ShortByteString -> c ShortByteString
gfoldl forall d b. Data d => c (d -> b) -> d -> c b
f forall g. g -> c g
z ShortByteString
txt = ([Word8] -> ShortByteString) -> c ([Word8] -> ShortByteString)
forall g. g -> c g
z [Word8] -> ShortByteString
packBytes c ([Word8] -> ShortByteString) -> [Word8] -> c ShortByteString
forall d b. Data d => c (d -> b) -> d -> c b
`f` ShortByteString -> [Word8]
unpackBytes ShortByteString
txt
  toConstr :: ShortByteString -> Constr
toConstr ShortByteString
_     = String -> Constr
forall a. HasCallStack => String -> a
error String
"Data.ByteString.Short.ShortByteString.toConstr"
  gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ShortByteString
gunfold forall b r. Data b => c (b -> r) -> c r
_ forall r. r -> c r
_    = String -> Constr -> c ShortByteString
forall a. HasCallStack => String -> a
error String
"Data.ByteString.Short.ShortByteString.gunfold"
  dataTypeOf :: ShortByteString -> DataType
dataTypeOf ShortByteString
_   = String -> DataType
mkNoRepType String
"Data.ByteString.Short.ShortByteString"

------------------------------------------------------------------------
-- Simple operations

-- | /O(1)/. The empty 'ShortByteString'.
empty :: ShortByteString
empty :: ShortByteString
empty = Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create Int
0 (\MBA s
_ -> () -> ST s ()
forall (m :: * -> *) a. Monad m => a -> m a
return ())

-- | /O(1)/ The length of a 'ShortByteString'.
length :: ShortByteString -> Int
length :: ShortByteString -> Int
length (SBS ByteArray#
barr#) = Int# -> Int
I# (ByteArray# -> Int#
sizeofByteArray# ByteArray#
barr#)

-- | /O(1)/ Test whether a 'ShortByteString' is empty.
null :: ShortByteString -> Bool
null :: ShortByteString -> Bool
null ShortByteString
sbs = ShortByteString -> Int
length ShortByteString
sbs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0

-- | /O(1)/ 'ShortByteString' index (subscript) operator, starting from 0.
index :: HasCallStack => ShortByteString -> Int -> Word8
index :: HasCallStack => ShortByteString -> Int -> Word8
index ShortByteString
sbs Int
i
  | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< ShortByteString -> Int
length ShortByteString
sbs = ShortByteString -> Int -> Word8
unsafeIndex ShortByteString
sbs Int
i
  | Bool
otherwise                = ShortByteString -> Int -> Word8
forall a. HasCallStack => ShortByteString -> Int -> a
indexError ShortByteString
sbs Int
i

-- | /O(1)/ 'ShortByteString' index, starting from 0, that returns 'Just' if:
--
-- > 0 <= n < length bs
--
-- @since 0.11.0.0
indexMaybe :: ShortByteString -> Int -> Maybe Word8
indexMaybe :: ShortByteString -> Int -> Maybe Word8
indexMaybe ShortByteString
sbs Int
i
  | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< ShortByteString -> Int
length ShortByteString
sbs = Word8 -> Maybe Word8
forall a. a -> Maybe a
Just (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! ShortByteString -> Int -> Word8
unsafeIndex ShortByteString
sbs Int
i
  | Bool
otherwise                = Maybe Word8
forall a. Maybe a
Nothing
{-# INLINE indexMaybe #-}

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

unsafeIndex :: ShortByteString -> Int -> Word8
unsafeIndex :: ShortByteString -> Int -> Word8
unsafeIndex ShortByteString
sbs = BA -> Int -> Word8
indexWord8Array (ShortByteString -> BA
asBA ShortByteString
sbs)

indexError :: HasCallStack => ShortByteString -> Int -> a
indexError :: forall a. HasCallStack => ShortByteString -> Int -> a
indexError ShortByteString
sbs Int
i =
  String -> String -> a
forall a. HasCallStack => String -> String -> a
moduleError String
"index" (String -> a) -> String -> a
forall a b. (a -> b) -> a -> b
$ String
"error in array index: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
i
                        String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" not in range [0.." String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show (ShortByteString -> Int
length ShortByteString
sbs) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"]"

-- | @since 0.11.2.0
unsafePackLenLiteral :: Int -> Addr# -> ShortByteString
unsafePackLenLiteral :: Int -> Addr# -> ShortByteString
unsafePackLenLiteral Int
len Addr#
addr# =
    IO ShortByteString -> ShortByteString
forall a. IO a -> a
accursedUnutterablePerformIO (IO ShortByteString -> ShortByteString)
-> IO ShortByteString -> ShortByteString
forall a b. (a -> b) -> a -> b
$ Ptr Any -> Int -> IO ShortByteString
forall a. Ptr a -> Int -> IO ShortByteString
createFromPtr (Addr# -> Ptr Any
forall a. Addr# -> Ptr a
Ptr Addr#
addr#) Int
len

------------------------------------------------------------------------
-- Internal utils

asBA :: ShortByteString -> BA
asBA :: ShortByteString -> BA
asBA (SBS ByteArray#
ba#) = ByteArray# -> BA
BA# ByteArray#
ba#

create :: Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create :: Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create Int
len forall s. MBA s -> ST s ()
fill =
    (forall s. ST s ShortByteString) -> ShortByteString
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s ShortByteString) -> ShortByteString)
-> (forall s. ST s ShortByteString) -> ShortByteString
forall a b. (a -> b) -> a -> b
$ do
      MBA s
mba <- Int -> ST s (MBA s)
forall s. Int -> ST s (MBA s)
newByteArray Int
len
      MBA s -> ST s ()
forall s. MBA s -> ST s ()
fill MBA s
mba
      BA# ByteArray#
ba# <- MBA s -> ST s BA
forall s. MBA s -> ST s BA
unsafeFreezeByteArray MBA s
mba
      ShortByteString -> ST s ShortByteString
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteArray# -> ShortByteString
SBS ByteArray#
ba#)
{-# INLINE create #-}

-- | Given the maximum size needed and a function to make the contents
-- of a ShortByteString, createAndTrim makes the 'ShortByteString'.
-- The generating function is required to return the actual final size
-- (<= the maximum size) and the result value. The resulting byte array
-- is realloced to this size.
createAndTrim :: Int -> (forall s. MBA s -> ST s (Int, a)) -> (ShortByteString, a)
createAndTrim :: forall a.
Int -> (forall s. MBA s -> ST s (Int, a)) -> (ShortByteString, a)
createAndTrim Int
l forall s. MBA s -> ST s (Int, a)
fill =
    (forall s. ST s (ShortByteString, a)) -> (ShortByteString, a)
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s (ShortByteString, a)) -> (ShortByteString, a))
-> (forall s. ST s (ShortByteString, a)) -> (ShortByteString, a)
forall a b. (a -> b) -> a -> b
$ do
      MBA s
mba <- Int -> ST s (MBA s)
forall s. Int -> ST s (MBA s)
newByteArray Int
l
      (Int
l', a
res) <- MBA s -> ST s (Int, a)
forall s. MBA s -> ST s (Int, a)
fill MBA s
mba
      if Bool -> Bool -> Bool
forall a. HasCallStack => Bool -> a -> a
assert (Int
l' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
l) (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Int
l' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
l
          then do
            BA# ByteArray#
ba# <- MBA s -> ST s BA
forall s. MBA s -> ST s BA
unsafeFreezeByteArray MBA s
mba
            (ShortByteString, a) -> ST s (ShortByteString, a)
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteArray# -> ShortByteString
SBS ByteArray#
ba#, a
res)
          else do
            MBA s
mba2 <- Int -> ST s (MBA s)
forall s. Int -> ST s (MBA s)
newByteArray Int
l'
            MBA s -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. MBA s -> Int -> MBA s -> Int -> Int -> ST s ()
copyMutableByteArray MBA s
mba Int
0 MBA s
mba2 Int
0 Int
l'
            BA# ByteArray#
ba# <- MBA s -> ST s BA
forall s. MBA s -> ST s BA
unsafeFreezeByteArray MBA s
mba2
            (ShortByteString, a) -> ST s (ShortByteString, a)
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteArray# -> ShortByteString
SBS ByteArray#
ba#, a
res)
{-# INLINE createAndTrim #-}

createAndTrim' :: Int -> (forall s. MBA s -> ST s Int) -> ShortByteString
createAndTrim' :: Int -> (forall s. MBA s -> ST s Int) -> ShortByteString
createAndTrim' Int
l forall s. MBA s -> ST s Int
fill =
    (forall s. ST s ShortByteString) -> ShortByteString
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s ShortByteString) -> ShortByteString)
-> (forall s. ST s ShortByteString) -> ShortByteString
forall a b. (a -> b) -> a -> b
$ do
      MBA s
mba <- Int -> ST s (MBA s)
forall s. Int -> ST s (MBA s)
newByteArray Int
l
      Int
l' <- MBA s -> ST s Int
forall s. MBA s -> ST s Int
fill MBA s
mba
      if Bool -> Bool -> Bool
forall a. HasCallStack => Bool -> a -> a
assert (Int
l' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
l) (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Int
l' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
l
          then do
            BA# ByteArray#
ba# <- MBA s -> ST s BA
forall s. MBA s -> ST s BA
unsafeFreezeByteArray MBA s
mba
            ShortByteString -> ST s ShortByteString
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteArray# -> ShortByteString
SBS ByteArray#
ba#)
          else do
            MBA s
mba2 <- Int -> ST s (MBA s)
forall s. Int -> ST s (MBA s)
newByteArray Int
l'
            MBA s -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. MBA s -> Int -> MBA s -> Int -> Int -> ST s ()
copyMutableByteArray MBA s
mba Int
0 MBA s
mba2 Int
0 Int
l'
            BA# ByteArray#
ba# <- MBA s -> ST s BA
forall s. MBA s -> ST s BA
unsafeFreezeByteArray MBA s
mba2
            ShortByteString -> ST s ShortByteString
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteArray# -> ShortByteString
SBS ByteArray#
ba#)
{-# INLINE createAndTrim' #-}

createAndTrim'' :: Int -> (forall s. MBA s -> MBA s -> ST s (Int, Int)) -> (ShortByteString, ShortByteString)
createAndTrim'' :: Int
-> (forall s. MBA s -> MBA s -> ST s (Int, Int))
-> (ShortByteString, ShortByteString)
createAndTrim'' Int
l forall s. MBA s -> MBA s -> ST s (Int, Int)
fill =
    (forall s. ST s (ShortByteString, ShortByteString))
-> (ShortByteString, ShortByteString)
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s (ShortByteString, ShortByteString))
 -> (ShortByteString, ShortByteString))
-> (forall s. ST s (ShortByteString, ShortByteString))
-> (ShortByteString, ShortByteString)
forall a b. (a -> b) -> a -> b
$ do
      MBA s
mba1 <- Int -> ST s (MBA s)
forall s. Int -> ST s (MBA s)
newByteArray Int
l
      MBA s
mba2 <- Int -> ST s (MBA s)
forall s. Int -> ST s (MBA s)
newByteArray Int
l
      (Int
l1, Int
l2) <- MBA s -> MBA s -> ST s (Int, Int)
forall s. MBA s -> MBA s -> ST s (Int, Int)
fill MBA s
mba1 MBA s
mba2
      ShortByteString
sbs1 <- Int -> MBA s -> ST s ShortByteString
forall s. Int -> MBA s -> ST s ShortByteString
freeze' Int
l1 MBA s
mba1
      ShortByteString
sbs2 <- Int -> MBA s -> ST s ShortByteString
forall s. Int -> MBA s -> ST s ShortByteString
freeze' Int
l2 MBA s
mba2
      (ShortByteString, ShortByteString)
-> ST s (ShortByteString, ShortByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ShortByteString
sbs1, ShortByteString
sbs2)
  where
    freeze' :: Int -> MBA s -> ST s ShortByteString
    freeze' :: forall s. Int -> MBA s -> ST s ShortByteString
freeze' Int
l' MBA s
mba =
      if Bool -> Bool -> Bool
forall a. HasCallStack => Bool -> a -> a
assert (Int
l' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
l) (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Int
l' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
l
          then do
            BA# ByteArray#
ba# <- MBA s -> ST s BA
forall s. MBA s -> ST s BA
unsafeFreezeByteArray MBA s
mba
            ShortByteString -> ST s ShortByteString
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteArray# -> ShortByteString
SBS ByteArray#
ba#)
          else do
            MBA s
mba2 <- Int -> ST s (MBA s)
forall s. Int -> ST s (MBA s)
newByteArray Int
l'
            MBA s -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. MBA s -> Int -> MBA s -> Int -> Int -> ST s ()
copyMutableByteArray MBA s
mba Int
0 MBA s
mba2 Int
0 Int
l'
            BA# ByteArray#
ba# <- MBA s -> ST s BA
forall s. MBA s -> ST s BA
unsafeFreezeByteArray MBA s
mba2
            ShortByteString -> ST s ShortByteString
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteArray# -> ShortByteString
SBS ByteArray#
ba#)
{-# INLINE createAndTrim'' #-}

isPinned :: ByteArray# -> Bool
#if MIN_VERSION_base(4,10,0)
isPinned :: ByteArray# -> Bool
isPinned ByteArray#
ba# = Int# -> Bool
isTrue# (ByteArray# -> Int#
isByteArrayPinned# ByteArray#
ba#)
#else
isPinned _ = False
#endif

------------------------------------------------------------------------
-- Conversion to and from ByteString

-- | /O(n)/. Convert a 'ByteString' into a 'ShortByteString'.
--
-- This makes a copy, so does not retain the input string.
--
toShort :: ByteString -> ShortByteString
toShort :: ByteString -> ShortByteString
toShort !ByteString
bs = IO ShortByteString -> ShortByteString
forall a. IO a -> a
unsafeDupablePerformIO (ByteString -> IO ShortByteString
toShortIO ByteString
bs)

toShortIO :: ByteString -> IO ShortByteString
toShortIO :: ByteString -> IO ShortByteString
toShortIO (BS ForeignPtr Word8
fptr Int
len) = do
    MBA RealWorld
mba <- ST RealWorld (MBA RealWorld) -> IO (MBA RealWorld)
forall a. ST RealWorld a -> IO a
stToIO (Int -> ST RealWorld (MBA RealWorld)
forall s. Int -> ST s (MBA s)
newByteArray Int
len)
    let ptr :: Ptr Word8
ptr = ForeignPtr Word8 -> Ptr Word8
forall a. ForeignPtr a -> Ptr a
unsafeForeignPtrToPtr ForeignPtr Word8
fptr
    ST RealWorld () -> IO ()
forall a. ST RealWorld a -> IO a
stToIO (Ptr Word8 -> MBA RealWorld -> Int -> Int -> ST RealWorld ()
forall a. Ptr a -> MBA RealWorld -> Int -> Int -> ST RealWorld ()
copyAddrToByteArray Ptr Word8
ptr MBA RealWorld
mba Int
0 Int
len)
    ForeignPtr Word8 -> IO ()
forall a. ForeignPtr a -> IO ()
touchForeignPtr ForeignPtr Word8
fptr
    BA# ByteArray#
ba# <- ST RealWorld BA -> IO BA
forall a. ST RealWorld a -> IO a
stToIO (MBA RealWorld -> ST RealWorld BA
forall s. MBA s -> ST s BA
unsafeFreezeByteArray MBA RealWorld
mba)
    ShortByteString -> IO ShortByteString
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteArray# -> ShortByteString
SBS ByteArray#
ba#)

-- | /O(n)/. Convert a 'ShortByteString' into a 'ByteString'.
--
fromShort :: ShortByteString -> ByteString
fromShort :: ShortByteString -> ByteString
fromShort (SBS ByteArray#
b#)
  | ByteArray# -> Bool
isPinned ByteArray#
b# = ForeignPtr Word8 -> Int -> ByteString
BS ForeignPtr Word8
fp Int
len
  where
    addr# :: Addr#
addr# = ByteArray# -> Addr#
byteArrayContents# ByteArray#
b#
    fp :: ForeignPtr Word8
fp = Addr# -> ForeignPtrContents -> ForeignPtr Word8
forall a. Addr# -> ForeignPtrContents -> ForeignPtr a
ForeignPtr Addr#
addr# (MutableByteArray# RealWorld -> ForeignPtrContents
PlainPtr (ByteArray# -> MutableByteArray# RealWorld
unsafeCoerce# ByteArray#
b#))
    len :: Int
len = Int# -> Int
I# (ByteArray# -> Int#
sizeofByteArray# ByteArray#
b#)
fromShort !ShortByteString
sbs = IO ByteString -> ByteString
forall a. IO a -> a
unsafeDupablePerformIO (ShortByteString -> IO ByteString
fromShortIO ShortByteString
sbs)

fromShortIO :: ShortByteString -> IO ByteString
fromShortIO :: ShortByteString -> IO ByteString
fromShortIO ShortByteString
sbs = do
    let len :: Int
len = ShortByteString -> Int
length ShortByteString
sbs
    mba :: MBA RealWorld
mba@(MBA# MutableByteArray# RealWorld
mba#) <- ST RealWorld (MBA RealWorld) -> IO (MBA RealWorld)
forall a. ST RealWorld a -> IO a
stToIO (Int -> ST RealWorld (MBA RealWorld)
forall s. Int -> ST s (MBA s)
newPinnedByteArray Int
len)
    ST RealWorld () -> IO ()
forall a. ST RealWorld a -> IO a
stToIO (BA -> Int -> MBA RealWorld -> Int -> Int -> ST RealWorld ()
forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (ShortByteString -> BA
asBA ShortByteString
sbs) Int
0 MBA RealWorld
mba Int
0 Int
len)
    let fp :: ForeignPtr Word8
fp = Addr# -> ForeignPtrContents -> ForeignPtr Word8
forall a. Addr# -> ForeignPtrContents -> ForeignPtr a
ForeignPtr (ByteArray# -> Addr#
byteArrayContents# (MutableByteArray# RealWorld -> ByteArray#
unsafeCoerce# MutableByteArray# RealWorld
mba#))
                        (MutableByteArray# RealWorld -> ForeignPtrContents
PlainPtr MutableByteArray# RealWorld
mba#)
    ByteString -> IO ByteString
forall (m :: * -> *) a. Monad m => a -> m a
return (ForeignPtr Word8 -> Int -> ByteString
BS ForeignPtr Word8
fp Int
len)

-- | /O(1)/ Convert a 'Word8' into a 'ShortByteString'
--
-- @since 0.11.3.0
singleton :: Word8 -> ShortByteString
singleton :: Word8 -> ShortByteString
singleton = \Word8
w -> Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create Int
1 (\MBA s
mba -> MBA s -> Int -> Word8 -> ST s ()
forall s. MBA s -> Int -> Word8 -> ST s ()
writeWord8Array MBA s
mba Int
0 Word8
w)

------------------------------------------------------------------------
-- Packing and unpacking from lists

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

-- | /O(n)/. Convert a 'ShortByteString' into a list.
unpack :: ShortByteString -> [Word8]
unpack :: ShortByteString -> [Word8]
unpack = ShortByteString -> [Word8]
unpackBytes

packChars :: [Char] -> ShortByteString
packChars :: String -> ShortByteString
packChars = \String
cs -> Int -> [Word8] -> ShortByteString
packLenBytes (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
List.length String
cs) ((Char -> Word8) -> String -> [Word8]
forall a b. (a -> b) -> [a] -> [b]
List.map Char -> Word8
BS.c2w String
cs)

packBytes :: [Word8] -> ShortByteString
packBytes :: [Word8] -> ShortByteString
packBytes = \[Word8]
ws -> Int -> [Word8] -> ShortByteString
packLenBytes ([Word8] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
List.length [Word8]
ws) [Word8]
ws

packLenBytes :: Int -> [Word8] -> ShortByteString
packLenBytes :: Int -> [Word8] -> ShortByteString
packLenBytes Int
len [Word8]
ws0 =
    Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create Int
len (\MBA s
mba -> MBA s -> Int -> [Word8] -> ST s ()
forall s. MBA s -> Int -> [Word8] -> ST s ()
go MBA s
mba Int
0 [Word8]
ws0)
  where
    go :: MBA s -> Int -> [Word8] -> ST s ()
    go :: forall s. MBA s -> Int -> [Word8] -> ST s ()
go !MBA s
_   !Int
_ []     = () -> ST s ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
    go !MBA s
mba !Int
i (Word8
w:[Word8]
ws) = do
      MBA s -> Int -> Word8 -> ST s ()
forall s. MBA s -> Int -> Word8 -> ST s ()
writeWord8Array MBA s
mba Int
i Word8
w
      MBA s -> Int -> [Word8] -> ST s ()
forall s. MBA s -> Int -> [Word8] -> ST s ()
go MBA s
mba (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) [Word8]
ws

-- Unpacking bytestrings into lists effeciently is a tradeoff: on the one hand
-- we would like to write a tight loop that just blats the list into memory, on
-- the other hand we want it to be unpacked lazily so we don't end up with a
-- massive list data structure in memory.
--
-- Our strategy is to combine both: we will unpack lazily in reasonable sized
-- chunks, where each chunk is unpacked strictly.
--
-- unpackChars does the lazy loop, while unpackAppendBytes and
-- unpackAppendChars do the chunks strictly.

unpackChars :: ShortByteString -> [Char]
unpackChars :: ShortByteString -> String
unpackChars ShortByteString
sbs = ShortByteString -> ShowS
unpackAppendCharsLazy ShortByteString
sbs []

unpackBytes :: ShortByteString -> [Word8]
unpackBytes :: ShortByteString -> [Word8]
unpackBytes ShortByteString
sbs = ShortByteString -> [Word8] -> [Word8]
unpackAppendBytesLazy ShortByteString
sbs []

-- Why 100 bytes you ask? Because on a 64bit machine the list we allocate
-- takes just shy of 4k which seems like a reasonable amount.
-- (5 words per list element, 8 bytes per word, 100 elements = 4000 bytes)

unpackAppendCharsLazy :: ShortByteString -> [Char] -> [Char]
unpackAppendCharsLazy :: ShortByteString -> ShowS
unpackAppendCharsLazy ShortByteString
sbs = Int -> Int -> ShowS
go Int
0 (ShortByteString -> Int
length ShortByteString
sbs)
  where
    sz :: Int
sz = Int
100

    go :: Int -> Int -> ShowS
go Int
off Int
len String
cs
      | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
sz = ShortByteString -> Int -> Int -> ShowS
unpackAppendCharsStrict ShortByteString
sbs Int
off Int
len String
cs
      | Bool
otherwise = ShortByteString -> Int -> Int -> ShowS
unpackAppendCharsStrict ShortByteString
sbs Int
off Int
sz  String
remainder
                      where remainder :: String
remainder = Int -> Int -> ShowS
go (Int
offInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
sz) (Int
lenInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
sz) String
cs

unpackAppendBytesLazy :: ShortByteString -> [Word8] -> [Word8]
unpackAppendBytesLazy :: ShortByteString -> [Word8] -> [Word8]
unpackAppendBytesLazy ShortByteString
sbs = Int -> Int -> [Word8] -> [Word8]
go Int
0 (ShortByteString -> Int
length ShortByteString
sbs)
  where
    sz :: Int
sz = Int
100

    go :: Int -> Int -> [Word8] -> [Word8]
go Int
off Int
len [Word8]
ws
      | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
sz = ShortByteString -> Int -> Int -> [Word8] -> [Word8]
unpackAppendBytesStrict ShortByteString
sbs Int
off Int
len [Word8]
ws
      | Bool
otherwise = ShortByteString -> Int -> Int -> [Word8] -> [Word8]
unpackAppendBytesStrict ShortByteString
sbs Int
off Int
sz  [Word8]
remainder
                      where remainder :: [Word8]
remainder = Int -> Int -> [Word8] -> [Word8]
go (Int
offInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
sz) (Int
lenInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
sz) [Word8]
ws

-- For these unpack functions, since we're unpacking the whole list strictly we
-- build up the result list in an accumulator. This means we have to build up
-- the list starting at the end. So our traversal starts at the end of the
-- buffer and loops down until we hit the sentinal:

unpackAppendCharsStrict :: ShortByteString -> Int -> Int -> [Char] -> [Char]
unpackAppendCharsStrict :: ShortByteString -> Int -> Int -> ShowS
unpackAppendCharsStrict !ShortByteString
sbs Int
off Int
len = Int -> Int -> ShowS
go (Int
offInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) (Int
offInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
len)
  where
    go :: Int -> Int -> ShowS
go !Int
sentinal !Int
i !String
acc
      | Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
sentinal = String
acc
      | Bool
otherwise     = let !c :: Char
c = BA -> Int -> Char
indexCharArray (ShortByteString -> BA
asBA ShortByteString
sbs) Int
i
                        in Int -> Int -> ShowS
go Int
sentinal (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) (Char
cChar -> ShowS
forall a. a -> [a] -> [a]
:String
acc)

unpackAppendBytesStrict :: ShortByteString -> Int -> Int -> [Word8] -> [Word8]
unpackAppendBytesStrict :: ShortByteString -> Int -> Int -> [Word8] -> [Word8]
unpackAppendBytesStrict !ShortByteString
sbs Int
off Int
len = Int -> Int -> [Word8] -> [Word8]
go (Int
offInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) (Int
offInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
len)
  where
    go :: Int -> Int -> [Word8] -> [Word8]
go !Int
sentinal !Int
i ![Word8]
acc
      | Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
sentinal = [Word8]
acc
      | Bool
otherwise     = let !w :: Word8
w = BA -> Int -> Word8
indexWord8Array (ShortByteString -> BA
asBA ShortByteString
sbs) Int
i
                         in Int -> Int -> [Word8] -> [Word8]
go Int
sentinal (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) (Word8
wWord8 -> [Word8] -> [Word8]
forall a. a -> [a] -> [a]
:[Word8]
acc)


------------------------------------------------------------------------
-- Eq and Ord implementations

equateBytes :: ShortByteString -> ShortByteString -> Bool
equateBytes :: ShortByteString -> ShortByteString -> Bool
equateBytes ShortByteString
sbs1 ShortByteString
sbs2 =
    let !len1 :: Int
len1 = ShortByteString -> Int
length ShortByteString
sbs1
        !len2 :: Int
len2 = ShortByteString -> Int
length ShortByteString
sbs2
     in Int
len1 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
len2
     Bool -> Bool -> Bool
&& Int
0 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== BA -> BA -> Int -> Int
compareByteArrays (ShortByteString -> BA
asBA ShortByteString
sbs1) (ShortByteString -> BA
asBA ShortByteString
sbs2) Int
len1

compareBytes :: ShortByteString -> ShortByteString -> Ordering
compareBytes :: ShortByteString -> ShortByteString -> Ordering
compareBytes ShortByteString
sbs1 ShortByteString
sbs2 =
    let !len1 :: Int
len1 = ShortByteString -> Int
length ShortByteString
sbs1
        !len2 :: Int
len2 = ShortByteString -> Int
length ShortByteString
sbs2
        !len :: Int
len  = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
len1 Int
len2
     in case BA -> BA -> Int -> Int
compareByteArrays (ShortByteString -> BA
asBA ShortByteString
sbs1) (ShortByteString -> BA
asBA ShortByteString
sbs2) Int
len of
          Int
i | Int
i    Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0    -> Ordering
LT
            | Int
i    Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0    -> Ordering
GT
            | Int
len2 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
len1 -> Ordering
LT
            | Int
len2 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
len1 -> Ordering
GT
            | Bool
otherwise   -> Ordering
EQ


------------------------------------------------------------------------
-- Appending and concatenation

append :: ShortByteString -> ShortByteString -> ShortByteString
append :: ShortByteString -> ShortByteString -> ShortByteString
append ShortByteString
src1 ShortByteString
src2 =
  let !len1 :: Int
len1 = ShortByteString -> Int
length ShortByteString
src1
      !len2 :: Int
len2 = ShortByteString -> Int
length ShortByteString
src2
   in Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create (Int
len1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
len2) ((forall s. MBA s -> ST s ()) -> ShortByteString)
-> (forall s. MBA s -> ST s ()) -> ShortByteString
forall a b. (a -> b) -> a -> b
$ \MBA s
dst -> do
        BA -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (ShortByteString -> BA
asBA ShortByteString
src1) Int
0 MBA s
dst Int
0    Int
len1
        BA -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (ShortByteString -> BA
asBA ShortByteString
src2) Int
0 MBA s
dst Int
len1 Int
len2

concat :: [ShortByteString] -> ShortByteString
concat :: [ShortByteString] -> ShortByteString
concat = \[ShortByteString]
sbss ->
    Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create (Int -> [ShortByteString] -> Int
totalLen Int
0 [ShortByteString]
sbss) (\MBA s
dst -> MBA s -> Int -> [ShortByteString] -> ST s ()
forall s. MBA s -> Int -> [ShortByteString] -> ST s ()
copy MBA s
dst Int
0 [ShortByteString]
sbss)
  where
    totalLen :: Int -> [ShortByteString] -> Int
totalLen !Int
acc []          = Int
acc
    totalLen !Int
acc (ShortByteString
sbs: [ShortByteString]
sbss) = Int -> [ShortByteString] -> Int
totalLen (Int
acc Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ShortByteString -> Int
length ShortByteString
sbs) [ShortByteString]
sbss

    copy :: MBA s -> Int -> [ShortByteString] -> ST s ()
    copy :: forall s. MBA s -> Int -> [ShortByteString] -> ST s ()
copy !MBA s
_   !Int
_   []                           = () -> ST s ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
    copy !MBA s
dst !Int
off (ShortByteString
src : [ShortByteString]
sbss) = do
      let !len :: Int
len = ShortByteString -> Int
length ShortByteString
src
      BA -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (ShortByteString -> BA
asBA ShortByteString
src) Int
0 MBA s
dst Int
off Int
len
      MBA s -> Int -> [ShortByteString] -> ST s ()
forall s. MBA s -> Int -> [ShortByteString] -> ST s ()
copy MBA s
dst (Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
len) [ShortByteString]
sbss

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

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

-- | /O(n)/ Append a byte to the end of a 'ShortByteString'
--
-- Note: copies the entire byte array
--
-- @since 0.11.3.0
snoc :: ShortByteString -> Word8 -> ShortByteString
snoc :: ShortByteString -> Word8 -> ShortByteString
snoc = \ShortByteString
sbs Word8
c -> let l :: Int
l  = ShortByteString -> Int
length ShortByteString
sbs
                     nl :: Int
nl = Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
  in Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create Int
nl ((forall s. MBA s -> ST s ()) -> ShortByteString)
-> (forall s. MBA s -> ST s ()) -> ShortByteString
forall a b. (a -> b) -> a -> b
$ \MBA s
mba -> do
      BA -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (ShortByteString -> BA
asBA ShortByteString
sbs) Int
0 MBA s
mba Int
0 Int
l
      MBA s -> Int -> Word8 -> ST s ()
forall s. MBA s -> Int -> Word8 -> ST s ()
writeWord8Array MBA s
mba Int
l Word8
c

-- | /O(n)/ 'cons' is analogous to (:) for lists.
--
-- Note: copies the entire byte array
--
-- @since 0.11.3.0
cons :: Word8 -> ShortByteString -> ShortByteString
cons :: Word8 -> ShortByteString -> ShortByteString
cons Word8
c = \ShortByteString
sbs -> let l :: Int
l  = ShortByteString -> Int
length ShortByteString
sbs
                     nl :: Int
nl = Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
  in Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create Int
nl ((forall s. MBA s -> ST s ()) -> ShortByteString)
-> (forall s. MBA s -> ST s ()) -> ShortByteString
forall a b. (a -> b) -> a -> b
$ \MBA s
mba -> do
      MBA s -> Int -> Word8 -> ST s ()
forall s. MBA s -> Int -> Word8 -> ST s ()
writeWord8Array MBA s
mba Int
0 Word8
c
      BA -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (ShortByteString -> BA
asBA ShortByteString
sbs) Int
0 MBA s
mba Int
1 Int
l

-- | /O(1)/ Extract the last element of a ShortByteString, which must be finite and non-empty.
-- An exception will be thrown in the case of an empty ShortByteString.
--
-- This is a partial function, consider using 'unsnoc' instead.
--
-- @since 0.11.3.0
last :: HasCallStack => ShortByteString -> Word8
last :: HasCallStack => ShortByteString -> Word8
last = \ShortByteString
sbs -> case ShortByteString -> Bool
null ShortByteString
sbs of
  Bool
True -> String -> Word8
forall a. HasCallStack => String -> a
errorEmptySBS String
"last"
  Bool
False -> BA -> Int -> Word8
indexWord8Array (ShortByteString -> BA
asBA ShortByteString
sbs) (ShortByteString -> Int
length ShortByteString
sbs Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)

-- | /O(n)/ Extract the elements after the head of a ShortByteString, which must be non-empty.
-- An exception will be thrown in the case of an empty ShortByteString.
--
-- This is a partial function, consider using 'uncons' instead.
--
-- Note: copies the entire byte array
--
-- @since 0.11.3.0
tail :: HasCallStack => ShortByteString -> ShortByteString
tail :: HasCallStack => ShortByteString -> ShortByteString
tail = \ShortByteString
sbs ->
  let l :: Int
l  = ShortByteString -> Int
length ShortByteString
sbs
      nl :: Int
nl = Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
  in case ShortByteString -> Bool
null ShortByteString
sbs of
      Bool
True -> String -> ShortByteString
forall a. HasCallStack => String -> a
errorEmptySBS String
"tail"
      Bool
False -> Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create Int
nl ((forall s. MBA s -> ST s ()) -> ShortByteString)
-> (forall s. MBA s -> ST s ()) -> ShortByteString
forall a b. (a -> b) -> a -> b
$ \MBA s
mba -> BA -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (ShortByteString -> BA
asBA ShortByteString
sbs) Int
1 MBA s
mba Int
0 Int
nl

-- | /O(n)/ Extract the head and tail of a ByteString, returning Nothing
-- if it is empty.
--
-- @since 0.11.3.0
uncons :: ShortByteString -> Maybe (Word8, ShortByteString)
uncons :: ShortByteString -> Maybe (Word8, ShortByteString)
uncons = \ShortByteString
sbs ->
  let l :: Int
l  = ShortByteString -> Int
length ShortByteString
sbs
      nl :: Int
nl = Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
  in if | Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 -> Maybe (Word8, ShortByteString)
forall a. Maybe a
Nothing
        | Bool
otherwise -> let h :: Word8
h = BA -> Int -> Word8
indexWord8Array (ShortByteString -> BA
asBA ShortByteString
sbs) Int
0
                           t :: ShortByteString
t = Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create Int
nl ((forall s. MBA s -> ST s ()) -> ShortByteString)
-> (forall s. MBA s -> ST s ()) -> ShortByteString
forall a b. (a -> b) -> a -> b
$ \MBA s
mba -> BA -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (ShortByteString -> BA
asBA ShortByteString
sbs) Int
1 MBA s
mba Int
0 Int
nl
                       in (Word8, ShortByteString) -> Maybe (Word8, ShortByteString)
forall a. a -> Maybe a
Just (Word8
h, ShortByteString
t)

-- | /O(1)/ Extract the first element of a ShortByteString, which must be non-empty.
-- An exception will be thrown in the case of an empty ShortByteString.
--
-- This is a partial function, consider using 'uncons' instead.
--
-- @since 0.11.3.0
head :: HasCallStack => ShortByteString -> Word8
head :: HasCallStack => ShortByteString -> Word8
head = \ShortByteString
sbs -> case ShortByteString -> Bool
null ShortByteString
sbs of
  Bool
True -> String -> Word8
forall a. HasCallStack => String -> a
errorEmptySBS String
"head"
  Bool
False -> BA -> Int -> Word8
indexWord8Array (ShortByteString -> BA
asBA ShortByteString
sbs) Int
0

-- | /O(n)/ Return all the elements of a 'ShortByteString' except the last one.
-- An exception will be thrown in the case of an empty ShortByteString.
--
-- This is a partial function, consider using 'unsnoc' instead.
--
-- Note: copies the entire byte array
--
-- @since 0.11.3.0
init :: HasCallStack => ShortByteString -> ShortByteString
init :: HasCallStack => ShortByteString -> ShortByteString
init = \ShortByteString
sbs ->
  let l :: Int
l  = ShortByteString -> Int
length ShortByteString
sbs
      nl :: Int
nl = Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
  in case ShortByteString -> Bool
null ShortByteString
sbs of
      Bool
True -> String -> ShortByteString
forall a. HasCallStack => String -> a
errorEmptySBS String
"init"
      Bool
False -> Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create Int
nl ((forall s. MBA s -> ST s ()) -> ShortByteString)
-> (forall s. MBA s -> ST s ()) -> ShortByteString
forall a b. (a -> b) -> a -> b
$ \MBA s
mba -> BA -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (ShortByteString -> BA
asBA ShortByteString
sbs) Int
0 MBA s
mba Int
0 Int
nl

-- | /O(n)/ Extract the 'init' and 'last' of a ByteString, returning Nothing
-- if it is empty.
--
-- @since 0.11.3.0
unsnoc :: ShortByteString -> Maybe (ShortByteString, Word8)
unsnoc :: ShortByteString -> Maybe (ShortByteString, Word8)
unsnoc = \ShortByteString
sbs ->
  let l :: Int
l  = ShortByteString -> Int
length ShortByteString
sbs
      nl :: Int
nl = Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
  in if | Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 -> Maybe (ShortByteString, Word8)
forall a. Maybe a
Nothing
        | Bool
otherwise -> let l' :: Word8
l' = BA -> Int -> Word8
indexWord8Array (ShortByteString -> BA
asBA ShortByteString
sbs) (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
                           i :: ShortByteString
i  = Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create Int
nl ((forall s. MBA s -> ST s ()) -> ShortByteString)
-> (forall s. MBA s -> ST s ()) -> ShortByteString
forall a b. (a -> b) -> a -> b
$ \MBA s
mba -> BA -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (ShortByteString -> BA
asBA ShortByteString
sbs) Int
0 MBA s
mba Int
0 Int
nl
                       in (ShortByteString, Word8) -> Maybe (ShortByteString, Word8)
forall a. a -> Maybe a
Just (ShortByteString
i, Word8
l')


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

-- | /O(n)/ 'map' @f xs@ is the ShortByteString obtained by applying @f@ to each
-- element of @xs@.
--
-- @since 0.11.3.0
map :: (Word8 -> Word8) -> ShortByteString -> ShortByteString
map :: (Word8 -> Word8) -> ShortByteString -> ShortByteString
map Word8 -> Word8
f = \ShortByteString
sbs ->
    let l :: Int
l  = ShortByteString -> Int
length ShortByteString
sbs
        ba :: BA
ba = ShortByteString -> BA
asBA ShortByteString
sbs
    in Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create Int
l (\MBA s
mba -> BA -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> MBA s -> Int -> Int -> ST s ()
go BA
ba MBA s
mba Int
0 Int
l)
  where
    go :: BA -> MBA s -> Int -> Int -> ST s ()
    go :: forall s. BA -> MBA s -> Int -> Int -> ST s ()
go !BA
ba !MBA s
mba !Int
i !Int
l
      | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
l = () -> ST s ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
      | Bool
otherwise = do
          let w :: Word8
w = BA -> Int -> Word8
indexWord8Array BA
ba Int
i
          MBA s -> Int -> Word8 -> ST s ()
forall s. MBA s -> Int -> Word8 -> ST s ()
writeWord8Array MBA s
mba Int
i (Word8 -> Word8
f Word8
w)
          BA -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> MBA s -> Int -> Int -> ST s ()
go BA
ba MBA s
mba (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Int
l


-- | /O(n)/ 'reverse' @xs@ efficiently returns the elements of @xs@ in reverse order.
--
-- @since 0.11.3.0
reverse :: ShortByteString -> ShortByteString
reverse :: ShortByteString -> ShortByteString
reverse = \ShortByteString
sbs ->
    let l :: Int
l  = ShortByteString -> Int
length ShortByteString
sbs
        ba :: BA
ba = ShortByteString -> BA
asBA ShortByteString
sbs
-- https://gitlab.haskell.org/ghc/ghc/-/issues/21015
#if MIN_VERSION_base(4,12,0) && defined(SAFE_UNALIGNED)
    in Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create Int
l (\MBA s
mba -> BA -> MBA s -> Int -> ST s ()
forall s. BA -> MBA s -> Int -> ST s ()
go BA
ba MBA s
mba Int
l)
  where
    go :: forall s. BA -> MBA s -> Int -> ST s ()
    go :: forall s. BA -> MBA s -> Int -> ST s ()
go !BA
ba !MBA s
mba !Int
l = do
      -- this is equivalent to: (q, r) = l `quotRem` 8
      let q :: Int
q = Int
l Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`shiftR` Int
3
          r :: Int
r = Int
l Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. Int
7
      Int
i' <- Int -> Int -> ST s Int
goWord8Chunk Int
0 Int
r
      Int -> Int -> Int -> ST s ()
goWord64Chunk Int
i' Int
0 Int
q
     where

      goWord64Chunk :: Int -> Int -> Int -> ST s ()
      goWord64Chunk :: Int -> Int -> Int -> ST s ()
goWord64Chunk !Int
off !Int
i' !Int
cl = Int -> ST s ()
loop Int
i'
       where
        loop :: Int -> ST s ()
        loop :: Int -> ST s ()
loop !Int
i
          | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
cl = () -> ST s ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
          | Bool
otherwise = do
              let w :: Word64
w = BA -> Int -> Word64
indexWord8ArrayAsWord64 BA
ba (Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
8))
              MBA s -> Int -> Word64 -> ST s ()
forall s. MBA s -> Int -> Word64 -> ST s ()
writeWord64Array MBA s
mba (Int
cl Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
i) (Word64 -> Word64
byteSwap64 Word64
w)
              Int -> ST s ()
loop (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)

      goWord8Chunk :: Int -> Int -> ST s Int
      goWord8Chunk :: Int -> Int -> ST s Int
goWord8Chunk !Int
i' !Int
cl = Int -> ST s Int
loop Int
i'
       where
        loop :: Int -> ST s Int
        loop :: Int -> ST s Int
loop !Int
i
          | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
cl = Int -> ST s Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
i
          | Bool
otherwise = do
              let w :: Word8
w = BA -> Int -> Word8
indexWord8Array BA
ba Int
i
              MBA s -> Int -> Word8 -> ST s ()
forall s. MBA s -> Int -> Word8 -> ST s ()
writeWord8Array MBA s
mba (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
i) Word8
w
              Int -> ST s Int
loop (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
#else
    in create l (\mba -> go ba mba 0 l)
   where
    go :: BA -> MBA s -> Int -> Int -> ST s ()
    go !ba !mba !i !l
      | i >= l = return ()
      | otherwise = do
          let w = indexWord8Array ba i
          writeWord8Array mba (l - 1 - i) w
          go ba mba (i+1) l
#endif


-- | /O(n)/ The 'intercalate' function takes a 'ShortByteString' and a list of
-- 'ShortByteString's and concatenates the list after interspersing the first
-- argument between each element of the list.
--
-- @since 0.11.3.0
intercalate :: ShortByteString -> [ShortByteString] -> ShortByteString
intercalate :: ShortByteString -> [ShortByteString] -> ShortByteString
intercalate ShortByteString
sep = \case
                    []      -> ShortByteString
empty
                    [ShortByteString
x]     -> ShortByteString
x -- This branch exists for laziness, not speed
                    (ShortByteString
sbs:[ShortByteString]
t) -> let !totalLen :: Int
totalLen = (Int -> ShortByteString -> Int) -> Int -> [ShortByteString] -> Int
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl' (\Int
acc ShortByteString
chunk -> Int
acc Int -> Int -> Int
+! ShortByteString -> Int
length ShortByteString
sep Int -> Int -> Int
+! ShortByteString -> Int
length ShortByteString
chunk) (ShortByteString -> Int
length ShortByteString
sbs) [ShortByteString]
t
                               in Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create Int
totalLen (\MBA s
mba ->
                                      let !l :: Int
l = ShortByteString -> Int
length ShortByteString
sbs
                                      in BA -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (ShortByteString -> BA
asBA ShortByteString
sbs) Int
0 MBA s
mba Int
0 Int
l ST s () -> ST s () -> ST s ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> MBA s -> Int -> [ShortByteString] -> ST s ()
forall s. MBA s -> Int -> [ShortByteString] -> ST s ()
go MBA s
mba Int
l [ShortByteString]
t)
 where
  ba :: BA
ba  = ShortByteString -> BA
asBA ShortByteString
sep
  lba :: Int
lba = ShortByteString -> Int
length ShortByteString
sep

  go :: MBA s -> Int -> [ShortByteString] -> ST s ()
  go :: forall s. MBA s -> Int -> [ShortByteString] -> ST s ()
go MBA s
_ Int
_ [] = () -> ST s ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
  go MBA s
mba !Int
off (ShortByteString
chunk:[ShortByteString]
chunks) = do
    let lc :: Int
lc = ShortByteString -> Int
length ShortByteString
chunk
    BA -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray BA
ba Int
0 MBA s
mba Int
off Int
lba
    BA -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (ShortByteString -> BA
asBA ShortByteString
chunk) Int
0 MBA s
mba (Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
lba) Int
lc
    MBA s -> Int -> [ShortByteString] -> ST s ()
forall s. MBA s -> Int -> [ShortByteString] -> ST s ()
go MBA s
mba (Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
lc Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
lba) [ShortByteString]
chunks
  +! :: Int -> Int -> Int
(+!) = String -> Int -> Int -> Int
checkedAdd String
"Short.intercalate"


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

-- | 'foldl', applied to a binary operator, a starting value (typically
-- the left-identity of the operator), and a ShortByteString, reduces the
-- ShortByteString using the binary operator, from left to right.
--
-- @since 0.11.3.0
foldl :: (a -> Word8 -> a) -> a -> ShortByteString -> a
foldl :: forall a. (a -> Word8 -> a) -> a -> ShortByteString -> a
foldl a -> Word8 -> a
f a
v = (a -> Word8 -> a) -> a -> [Word8] -> a
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl a -> Word8 -> a
f a
v ([Word8] -> a)
-> (ShortByteString -> [Word8]) -> ShortByteString -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> [Word8]
unpack

-- | 'foldl'' is like 'foldl', but strict in the accumulator.
--
-- @since 0.11.3.0
foldl' :: (a -> Word8 -> a) -> a -> ShortByteString -> a
foldl' :: forall a. (a -> Word8 -> a) -> a -> ShortByteString -> a
foldl' a -> Word8 -> a
f a
v = (a -> Word8 -> a) -> a -> [Word8] -> a
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl' a -> Word8 -> a
f a
v ([Word8] -> a)
-> (ShortByteString -> [Word8]) -> ShortByteString -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> [Word8]
unpack

-- | 'foldr', applied to a binary operator, a starting value
-- (typically the right-identity of the operator), and a ShortByteString,
-- reduces the ShortByteString using the binary operator, from right to left.
--
-- @since 0.11.3.0
foldr :: (Word8 -> a -> a) -> a -> ShortByteString -> a
foldr :: forall a. (Word8 -> a -> a) -> a -> ShortByteString -> a
foldr Word8 -> a -> a
f a
v = (Word8 -> a -> a) -> a -> [Word8] -> a
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
List.foldr Word8 -> a -> a
f a
v ([Word8] -> a)
-> (ShortByteString -> [Word8]) -> ShortByteString -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> [Word8]
unpack

-- | 'foldr'' is like 'foldr', but strict in the accumulator.
--
-- @since 0.11.3.0
foldr' :: (Word8 -> a -> a) -> a -> ShortByteString -> a
foldr' :: forall a. (Word8 -> a -> a) -> a -> ShortByteString -> a
foldr' Word8 -> a -> a
k a
v = (Word8 -> a -> a) -> a -> [Word8] -> a
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
Foldable.foldr' Word8 -> a -> a
k a
v ([Word8] -> a)
-> (ShortByteString -> [Word8]) -> ShortByteString -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> [Word8]
unpack

-- | 'foldl1' is a variant of 'foldl' that has no starting value
-- argument, and thus must be applied to non-empty 'ShortByteString's.
-- An exception will be thrown in the case of an empty ShortByteString.
--
-- @since 0.11.3.0
foldl1 :: HasCallStack => (Word8 -> Word8 -> Word8) -> ShortByteString -> Word8
foldl1 :: HasCallStack =>
(Word8 -> Word8 -> Word8) -> ShortByteString -> Word8
foldl1 Word8 -> Word8 -> Word8
k = (Word8 -> Word8 -> Word8) -> [Word8] -> Word8
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
List.foldl1 Word8 -> Word8 -> Word8
k ([Word8] -> Word8)
-> (ShortByteString -> [Word8]) -> ShortByteString -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> [Word8]
unpack

-- | 'foldl1'' is like 'foldl1', but strict in the accumulator.
-- An exception will be thrown in the case of an empty ShortByteString.
--
-- @since 0.11.3.0
foldl1' :: HasCallStack => (Word8 -> Word8 -> Word8) -> ShortByteString -> Word8
foldl1' :: HasCallStack =>
(Word8 -> Word8 -> Word8) -> ShortByteString -> Word8
foldl1' Word8 -> Word8 -> Word8
k = (Word8 -> Word8 -> Word8) -> [Word8] -> Word8
forall a. (a -> a -> a) -> [a] -> a
List.foldl1' Word8 -> Word8 -> Word8
k ([Word8] -> Word8)
-> (ShortByteString -> [Word8]) -> ShortByteString -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> [Word8]
unpack

-- | 'foldr1' is a variant of 'foldr' that has no starting value argument,
-- and thus must be applied to non-empty 'ShortByteString's
-- An exception will be thrown in the case of an empty ShortByteString.
--
-- @since 0.11.3.0
foldr1 :: HasCallStack => (Word8 -> Word8 -> Word8) -> ShortByteString -> Word8
foldr1 :: HasCallStack =>
(Word8 -> Word8 -> Word8) -> ShortByteString -> Word8
foldr1 Word8 -> Word8 -> Word8
k = (Word8 -> Word8 -> Word8) -> [Word8] -> Word8
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
List.foldr1 Word8 -> Word8 -> Word8
k ([Word8] -> Word8)
-> (ShortByteString -> [Word8]) -> ShortByteString -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> [Word8]
unpack

-- | 'foldr1'' is a variant of 'foldr1', but is strict in the
-- accumulator.
--
-- @since 0.11.3.0
foldr1' :: HasCallStack => (Word8 -> Word8 -> Word8) -> ShortByteString -> Word8
foldr1' :: HasCallStack =>
(Word8 -> Word8 -> Word8) -> ShortByteString -> Word8
foldr1' Word8 -> Word8 -> Word8
k = \ShortByteString
sbs -> if ShortByteString -> Bool
null ShortByteString
sbs then String -> Word8
forall a. HasCallStack => String -> a
errorEmptySBS String
"foldr1'" else (Word8 -> Word8 -> Word8) -> Word8 -> ShortByteString -> Word8
forall a. (Word8 -> a -> a) -> a -> ShortByteString -> a
foldr' Word8 -> Word8 -> Word8
k (HasCallStack => ShortByteString -> Word8
ShortByteString -> Word8
last ShortByteString
sbs) (HasCallStack => ShortByteString -> ShortByteString
ShortByteString -> ShortByteString
init ShortByteString
sbs)



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

-- | /O(n)/ Applied to a predicate and a 'ShortByteString', 'all' determines
-- if all elements of the 'ShortByteString' satisfy the predicate.
--
-- @since 0.11.3.0
all :: (Word8 -> Bool) -> ShortByteString -> Bool
all :: (Word8 -> Bool) -> ShortByteString -> Bool
all Word8 -> Bool
k = \ShortByteString
sbs ->
  let l :: Int
l  = ShortByteString -> Int
length ShortByteString
sbs
      ba :: BA
ba = ShortByteString -> BA
asBA ShortByteString
sbs
      w :: Int -> Word8
w  = BA -> Int -> Word8
indexWord8Array BA
ba
      go :: Int -> Bool
go !Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
l    = Bool
True
            | Bool
otherwise = Word8 -> Bool
k (Int -> Word8
w Int
n) Bool -> Bool -> Bool
&& Int -> Bool
go (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
  in Int -> Bool
go Int
0


-- | /O(n)/ Applied to a predicate and a ByteString, 'any' determines if
-- any element of the 'ByteString' satisfies the predicate.
--
-- @since 0.11.3.0
any :: (Word8 -> Bool) -> ShortByteString -> Bool
any :: (Word8 -> Bool) -> ShortByteString -> Bool
any Word8 -> Bool
k = \ShortByteString
sbs ->
  let l :: Int
l  = ShortByteString -> Int
length ShortByteString
sbs
      ba :: BA
ba = ShortByteString -> BA
asBA ShortByteString
sbs
      w :: Int -> Word8
w  = BA -> Int -> Word8
indexWord8Array BA
ba
      go :: Int -> Bool
go !Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
l    = Bool
False
            | Bool
otherwise = Word8 -> Bool
k (Int -> Word8
w Int
n) Bool -> Bool -> Bool
|| Int -> Bool
go (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
  in Int -> Bool
go Int
0



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

-- | /O(n)/ 'take' @n@, applied to a ShortByteString @xs@, returns the prefix
-- of @xs@ of length @n@, or @xs@ itself if @n > 'length' xs@.
--
-- Note: copies the entire byte array
--
-- @since 0.11.3.0
take :: Int -> ShortByteString -> ShortByteString
take :: Int -> ShortByteString -> ShortByteString
take = \Int
n -> \ShortByteString
sbs -> let sl :: Int
sl = ShortByteString -> Int
length ShortByteString
sbs
                     in if | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
sl   -> ShortByteString
sbs
                           | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0    -> ShortByteString
empty
                           | Bool
otherwise ->
                               Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create Int
n ((forall s. MBA s -> ST s ()) -> ShortByteString)
-> (forall s. MBA s -> ST s ()) -> ShortByteString
forall a b. (a -> b) -> a -> b
$ \MBA s
mba -> BA -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (ShortByteString -> BA
asBA ShortByteString
sbs) Int
0 MBA s
mba Int
0 Int
n

-- | Similar to 'Prelude.takeWhile',
-- returns the longest (possibly empty) prefix of elements
-- satisfying the predicate.
--
-- @since 0.11.3.0
takeWhile :: (Word8 -> Bool) -> ShortByteString -> ShortByteString
takeWhile :: (Word8 -> Bool) -> ShortByteString -> ShortByteString
takeWhile Word8 -> Bool
f = \ShortByteString
sbs -> Int -> ShortByteString -> ShortByteString
take ((Word8 -> Bool) -> ShortByteString -> Int
findIndexOrLength (Bool -> Bool
not (Bool -> Bool) -> (Word8 -> Bool) -> Word8 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Bool
f) ShortByteString
sbs) ShortByteString
sbs

-- | /O(n)/ @'takeEnd' n xs@ is equivalent to @'drop' ('length' xs - n) xs@.
-- Takes @n@ elements from end of bytestring.
--
-- >>> takeEnd 3 "abcdefg"
-- "efg"
-- >>> takeEnd 0 "abcdefg"
-- ""
-- >>> takeEnd 4 "abc"
-- "abc"
--
-- @since 0.11.3.0
takeEnd :: Int -> ShortByteString -> ShortByteString
takeEnd :: Int -> ShortByteString -> ShortByteString
takeEnd Int
n = \ShortByteString
sbs -> let sl :: Int
sl = ShortByteString -> Int
length ShortByteString
sbs
                    in if | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
sl   -> ShortByteString
sbs
                          | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0    -> ShortByteString
empty
                          | Bool
otherwise -> Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create Int
n ((forall s. MBA s -> ST s ()) -> ShortByteString)
-> (forall s. MBA s -> ST s ()) -> ShortByteString
forall a b. (a -> b) -> a -> b
$ \MBA s
mba -> BA -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (ShortByteString -> BA
asBA ShortByteString
sbs) (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 (Int
sl Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n)) MBA s
mba Int
0 Int
n


-- | Returns the longest (possibly empty) suffix of elements
-- satisfying the predicate.
--
-- @'takeWhileEnd' p@ is equivalent to @'reverse' . 'takeWhile' p . 'reverse'@.
--
-- @since 0.11.3.0
takeWhileEnd :: (Word8 -> Bool) -> ShortByteString -> ShortByteString
takeWhileEnd :: (Word8 -> Bool) -> ShortByteString -> ShortByteString
takeWhileEnd Word8 -> Bool
f = \ShortByteString
sbs -> Int -> ShortByteString -> ShortByteString
drop ((Word8 -> Bool) -> ShortByteString -> Int
findFromEndUntil (Bool -> Bool
not (Bool -> Bool) -> (Word8 -> Bool) -> Word8 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Bool
f) ShortByteString
sbs) ShortByteString
sbs

-- | /O(n)/ 'drop' @n@ @xs@ returns the suffix of @xs@ after the first n elements, or @[]@ if @n > 'length' xs@.
--
-- Note: copies the entire byte array
--
-- @since 0.11.3.0
drop :: Int -> ShortByteString -> ShortByteString
drop :: Int -> ShortByteString -> ShortByteString
drop = \Int
n -> \ShortByteString
sbs ->
  let len :: Int
len = ShortByteString -> Int
length ShortByteString
sbs
  in if | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0    -> ShortByteString
sbs
        | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
len  -> ShortByteString
empty
        | Bool
otherwise ->
            let newLen :: Int
newLen = Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n
            in Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create Int
newLen ((forall s. MBA s -> ST s ()) -> ShortByteString)
-> (forall s. MBA s -> ST s ()) -> ShortByteString
forall a b. (a -> b) -> a -> b
$ \MBA s
mba -> BA -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (ShortByteString -> BA
asBA ShortByteString
sbs) Int
n MBA s
mba Int
0 Int
newLen

-- | /O(n)/ @'dropEnd' n xs@ is equivalent to @'take' ('length' xs - n) xs@.
-- Drops @n@ elements from end of bytestring.
--
-- >>> dropEnd 3 "abcdefg"
-- "abcd"
-- >>> dropEnd 0 "abcdefg"
-- "abcdefg"
-- >>> dropEnd 4 "abc"
-- ""
--
-- @since 0.11.3.0
dropEnd :: Int -> ShortByteString -> ShortByteString
dropEnd :: Int -> ShortByteString -> ShortByteString
dropEnd Int
n = \ShortByteString
sbs -> let sl :: Int
sl = ShortByteString -> Int
length ShortByteString
sbs
                        nl :: Int
nl = Int
sl Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n
                    in if | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
sl   -> ShortByteString
empty
                          | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0    -> ShortByteString
sbs
                          | Bool
otherwise -> Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create Int
nl ((forall s. MBA s -> ST s ()) -> ShortByteString)
-> (forall s. MBA s -> ST s ()) -> ShortByteString
forall a b. (a -> b) -> a -> b
$ \MBA s
mba -> BA -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (ShortByteString -> BA
asBA ShortByteString
sbs) Int
0 MBA s
mba Int
0 Int
nl

-- | Similar to 'Prelude.dropWhile',
-- drops the longest (possibly empty) prefix of elements
-- satisfying the predicate and returns the remainder.
--
-- Note: copies the entire byte array
--
-- @since 0.11.3.0
dropWhile :: (Word8 -> Bool) -> ShortByteString -> ShortByteString
dropWhile :: (Word8 -> Bool) -> ShortByteString -> ShortByteString
dropWhile Word8 -> Bool
f = \ShortByteString
sbs -> Int -> ShortByteString -> ShortByteString
drop ((Word8 -> Bool) -> ShortByteString -> Int
findIndexOrLength (Bool -> Bool
not (Bool -> Bool) -> (Word8 -> Bool) -> Word8 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Bool
f) ShortByteString
sbs) ShortByteString
sbs

-- | Similar to 'Prelude.dropWhileEnd',
-- drops the longest (possibly empty) suffix of elements
-- satisfying the predicate and returns the remainder.
--
-- @'dropWhileEnd' p@ is equivalent to @'reverse' . 'dropWhile' p . 'reverse'@.
--
-- @since 0.11.3.0
dropWhileEnd :: (Word8 -> Bool) -> ShortByteString -> ShortByteString
dropWhileEnd :: (Word8 -> Bool) -> ShortByteString -> ShortByteString
dropWhileEnd Word8 -> Bool
f = \ShortByteString
sbs -> Int -> ShortByteString -> ShortByteString
take ((Word8 -> Bool) -> ShortByteString -> Int
findFromEndUntil (Bool -> Bool
not (Bool -> Bool) -> (Word8 -> Bool) -> Word8 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Bool
f) ShortByteString
sbs) ShortByteString
sbs

-- | Returns the longest (possibly empty) suffix of elements which __do not__
-- satisfy the predicate and the remainder of the string.
--
-- 'breakEnd' @p@ is equivalent to @'spanEnd' (not . p)@ and to @('takeWhileEnd' (not . p) &&& 'dropWhileEnd' (not . p))@.
--
-- @since 0.11.3.0
breakEnd :: (Word8 -> Bool) -> ShortByteString -> (ShortByteString, ShortByteString)
breakEnd :: (Word8 -> Bool)
-> ShortByteString -> (ShortByteString, ShortByteString)
breakEnd Word8 -> Bool
p = \ShortByteString
sbs -> Int -> ShortByteString -> (ShortByteString, ShortByteString)
splitAt ((Word8 -> Bool) -> ShortByteString -> Int
findFromEndUntil Word8 -> Bool
p ShortByteString
sbs) ShortByteString
sbs

-- | Similar to 'Prelude.break',
-- returns the longest (possibly empty) prefix of elements which __do not__
-- satisfy the predicate and the remainder of the string.
--
-- 'break' @p@ is equivalent to @'span' (not . p)@ and to @('takeWhile' (not . p) &&& 'dropWhile' (not . p))@.
--
-- @since 0.11.3.0
break :: (Word8 -> Bool) -> ShortByteString -> (ShortByteString, ShortByteString)
break :: (Word8 -> Bool)
-> ShortByteString -> (ShortByteString, ShortByteString)
break = \Word8 -> Bool
p -> \ShortByteString
sbs -> case (Word8 -> Bool) -> ShortByteString -> Int
findIndexOrLength Word8 -> Bool
p ShortByteString
sbs of Int
n -> (Int -> ShortByteString -> ShortByteString
take Int
n ShortByteString
sbs, Int -> ShortByteString -> ShortByteString
drop Int
n ShortByteString
sbs)

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

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

-- | /O(n)/ 'splitAt' @n sbs@ is equivalent to @('take' n sbs, 'drop' n sbs)@.
--
-- Note: copies the substrings
--
-- @since 0.11.3.0
splitAt :: Int -> ShortByteString -> (ShortByteString, ShortByteString)
splitAt :: Int -> ShortByteString -> (ShortByteString, ShortByteString)
splitAt Int
n = \ShortByteString
sbs -> if
  | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 -> (ShortByteString
empty, ShortByteString
sbs)
  | Bool
otherwise ->
      let slen :: Int
slen = ShortByteString -> Int
length ShortByteString
sbs
      in if | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= ShortByteString -> Int
length ShortByteString
sbs -> (ShortByteString
sbs, ShortByteString
empty)
            | Bool
otherwise ->
                let llen :: Int
llen = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
slen (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 Int
n)
                    rlen :: Int
rlen = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 (Int
slen Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 Int
n)
                    lsbs :: ShortByteString
lsbs = Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create Int
llen ((forall s. MBA s -> ST s ()) -> ShortByteString)
-> (forall s. MBA s -> ST s ()) -> ShortByteString
forall a b. (a -> b) -> a -> b
$ \MBA s
mba -> BA -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (ShortByteString -> BA
asBA ShortByteString
sbs) Int
0 MBA s
mba Int
0 Int
llen
                    rsbs :: ShortByteString
rsbs = Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create Int
rlen ((forall s. MBA s -> ST s ()) -> ShortByteString)
-> (forall s. MBA s -> ST s ()) -> ShortByteString
forall a b. (a -> b) -> a -> b
$ \MBA s
mba -> BA -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (ShortByteString -> BA
asBA ShortByteString
sbs) Int
n MBA s
mba Int
0 Int
rlen
                in (ShortByteString
lsbs, ShortByteString
rsbs)

-- | /O(n)/ Break a 'ShortByteString' into pieces separated by the byte
-- argument, consuming the delimiter. I.e.
--
-- > split 10  "a\nb\nd\ne" == ["a","b","d","e"]   -- fromEnum '\n' == 10
-- > split 97  "aXaXaXa"    == ["","X","X","X",""] -- fromEnum 'a' == 97
-- > split 120 "x"          == ["",""]             -- fromEnum 'x' == 120
-- > split undefined ""     == []                  -- and not [""]
--
-- and
--
-- > intercalate [c] . split c == id
-- > split == splitWith . (==)
--
-- Note: copies the substrings
--
-- @since 0.11.3.0
split :: Word8 -> ShortByteString -> [ShortByteString]
split :: Word8 -> ShortByteString -> [ShortByteString]
split Word8
w = (Word8 -> Bool) -> ShortByteString -> [ShortByteString]
splitWith (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
w)


-- | /O(n)/ Splits a 'ShortByteString' into components delimited by
-- separators, where the predicate returns True for a separator element.
-- The resulting components do not contain the separators.  Two adjacent
-- separators result in an empty component in the output.  eg.
--
-- > splitWith (==97) "aabbaca" == ["","","bb","c",""] -- fromEnum 'a' == 97
-- > splitWith undefined ""     == []                  -- and not [""]
--
-- @since 0.11.3.0
splitWith :: (Word8 -> Bool) -> ShortByteString -> [ShortByteString]
splitWith :: (Word8 -> Bool) -> ShortByteString -> [ShortByteString]
splitWith Word8 -> Bool
p = \ShortByteString
sbs -> if
  | ShortByteString -> Bool
null ShortByteString
sbs  -> []
  | Bool
otherwise -> ShortByteString -> [ShortByteString]
go ShortByteString
sbs
  where
    go :: ShortByteString -> [ShortByteString]
go ShortByteString
sbs'
      | ShortByteString -> Bool
null ShortByteString
sbs' = [ShortByteString
empty]
      | Bool
otherwise =
          case (Word8 -> Bool)
-> ShortByteString -> (ShortByteString, ShortByteString)
break Word8 -> Bool
p ShortByteString
sbs' of
            (ShortByteString
a, ShortByteString
b)
              | ShortByteString -> Bool
null ShortByteString
b    -> [ShortByteString
a]
              | Bool
otherwise -> ShortByteString
a ShortByteString -> [ShortByteString] -> [ShortByteString]
forall a. a -> [a] -> [a]
: ShortByteString -> [ShortByteString]
go (HasCallStack => ShortByteString -> ShortByteString
ShortByteString -> ShortByteString
tail ShortByteString
b)


-- | /O(n)/ The 'stripSuffix' function takes two ShortByteStrings and returns 'Just'
-- the remainder of the second iff the first is its suffix, and otherwise
-- 'Nothing'.
--
-- @since 0.11.3.0
stripSuffix :: ShortByteString -> ShortByteString -> Maybe ShortByteString
stripSuffix :: ShortByteString -> ShortByteString -> Maybe ShortByteString
stripSuffix ShortByteString
sbs1 = \ShortByteString
sbs2 -> do
  let l1 :: Int
l1 = ShortByteString -> Int
length ShortByteString
sbs1
      l2 :: Int
l2 = ShortByteString -> Int
length ShortByteString
sbs2
  if | ShortByteString -> ShortByteString -> Bool
isSuffixOf ShortByteString
sbs1 ShortByteString
sbs2 ->
         if ShortByteString -> Bool
null ShortByteString
sbs1
         then ShortByteString -> Maybe ShortByteString
forall a. a -> Maybe a
Just ShortByteString
sbs2
         else ShortByteString -> Maybe ShortByteString
forall a. a -> Maybe a
Just (ShortByteString -> Maybe ShortByteString)
-> ShortByteString -> Maybe ShortByteString
forall a b. (a -> b) -> a -> b
$! Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create (Int
l2 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
l1) ((forall s. MBA s -> ST s ()) -> ShortByteString)
-> (forall s. MBA s -> ST s ()) -> ShortByteString
forall a b. (a -> b) -> a -> b
$ \MBA s
dst -> do
                BA -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (ShortByteString -> BA
asBA ShortByteString
sbs2) Int
0 MBA s
dst Int
0 (Int
l2 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
l1)
     | Bool
otherwise -> Maybe ShortByteString
forall a. Maybe a
Nothing

-- | /O(n)/ The 'stripPrefix' function takes two ShortByteStrings and returns 'Just'
-- the remainder of the second iff the first is its prefix, and otherwise
-- 'Nothing'.
--
-- @since 0.11.3.0
stripPrefix :: ShortByteString -> ShortByteString -> Maybe ShortByteString
stripPrefix :: ShortByteString -> ShortByteString -> Maybe ShortByteString
stripPrefix ShortByteString
sbs1 = \ShortByteString
sbs2 -> do
  let l1 :: Int
l1 = ShortByteString -> Int
length ShortByteString
sbs1
      l2 :: Int
l2 = ShortByteString -> Int
length ShortByteString
sbs2
  if | ShortByteString -> ShortByteString -> Bool
isPrefixOf ShortByteString
sbs1 ShortByteString
sbs2 ->
         if ShortByteString -> Bool
null ShortByteString
sbs1
         then ShortByteString -> Maybe ShortByteString
forall a. a -> Maybe a
Just ShortByteString
sbs2
         else ShortByteString -> Maybe ShortByteString
forall a. a -> Maybe a
Just (ShortByteString -> Maybe ShortByteString)
-> ShortByteString -> Maybe ShortByteString
forall a b. (a -> b) -> a -> b
$! Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create (Int
l2 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
l1) ((forall s. MBA s -> ST s ()) -> ShortByteString)
-> (forall s. MBA s -> ST s ()) -> ShortByteString
forall a b. (a -> b) -> a -> b
$ \MBA s
dst -> do
                BA -> Int -> MBA s -> Int -> Int -> ST s ()
forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (ShortByteString -> BA
asBA ShortByteString
sbs2) Int
l1 MBA s
dst Int
0 (Int
l2 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
l1)
     | Bool
otherwise -> Maybe ShortByteString
forall a. Maybe a
Nothing


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


-- | /O(n)/ 'replicate' @n x@ is a ByteString of length @n@ with @x@
-- the value of every element. The following holds:
--
-- > replicate w c = unfoldr w (\u -> Just (u,u)) c
--
-- @since 0.11.3.0
replicate :: Int -> Word8 -> ShortByteString
replicate :: Int -> Word8 -> ShortByteString
replicate Int
w Word8
c
    | Int
w Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0    = ShortByteString
empty
    | Bool
otherwise = Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create Int
w (\MBA s
mba -> MBA s -> Int -> Int -> Int -> ST s ()
forall s. MBA s -> Int -> Int -> Int -> ST s ()
setByteArray MBA s
mba Int
0 Int
w (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
c))


-- | /O(n)/, where /n/ is the length of the result.  The 'unfoldr'
-- function is analogous to the List \'unfoldr\'.  'unfoldr' builds a
-- ShortByteString from a seed value.  The function takes the element and
-- returns 'Nothing' if it is done producing the ShortByteString or returns
-- 'Just' @(a,b)@, in which case, @a@ is the next byte in the string,
-- and @b@ is the seed value for further production.
--
-- This function is not efficient/safe. It will build a list of @[Word8]@
-- and run the generator until it returns `Nothing`, otherwise recurse infinitely,
-- then finally create a 'ShortByteString'.
--
-- If you know the maximum length, consider using 'unfoldrN'.
--
-- Examples:
--
-- >    unfoldr (\x -> if x <= 5 then Just (x, x + 1) else Nothing) 0
-- > == pack [0, 1, 2, 3, 4, 5]
--
-- @since 0.11.3.0
unfoldr :: (a -> Maybe (Word8, a)) -> a -> ShortByteString
unfoldr :: forall a. (a -> Maybe (Word8, a)) -> a -> ShortByteString
unfoldr a -> Maybe (Word8, a)
f = \a
x0 -> [Word8] -> ShortByteString
packBytesRev ([Word8] -> ShortByteString) -> [Word8] -> ShortByteString
forall a b. (a -> b) -> a -> b
$ a -> [Word8] -> [Word8]
go a
x0 []
 where
   go :: a -> [Word8] -> [Word8]
go a
x [Word8]
words' = case a -> Maybe (Word8, a)
f a
x of
                    Maybe (Word8, a)
Nothing      -> [Word8]
words'
                    Just (Word8
w, a
x') -> a -> [Word8] -> [Word8]
go a
x' (Word8
wWord8 -> [Word8] -> [Word8]
forall a. a -> [a] -> [a]
:[Word8]
words')

-- | /O(n)/ Like 'unfoldr', 'unfoldrN' builds a ShortByteString from a seed
-- value.  However, the length of the result is limited by the first
-- argument to 'unfoldrN'.  This function is more efficient than 'unfoldr'
-- when the maximum length of the result is known.
--
-- The following equation relates 'unfoldrN' and 'unfoldr':
--
-- > fst (unfoldrN n f s) == take n (unfoldr f s)
--
-- @since 0.11.3.0
unfoldrN :: forall a. Int -> (a -> Maybe (Word8, a)) -> a -> (ShortByteString, Maybe a)
unfoldrN :: forall a.
Int -> (a -> Maybe (Word8, a)) -> a -> (ShortByteString, Maybe a)
unfoldrN Int
i a -> Maybe (Word8, a)
f = \a
x0 ->
  if | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0     -> (ShortByteString
empty, a -> Maybe a
forall a. a -> Maybe a
Just a
x0)
     | Bool
otherwise -> Int
-> (forall s. MBA s -> ST s (Int, Maybe a))
-> (ShortByteString, Maybe a)
forall a.
Int -> (forall s. MBA s -> ST s (Int, a)) -> (ShortByteString, a)
createAndTrim Int
i ((forall s. MBA s -> ST s (Int, Maybe a))
 -> (ShortByteString, Maybe a))
-> (forall s. MBA s -> ST s (Int, Maybe a))
-> (ShortByteString, Maybe a)
forall a b. (a -> b) -> a -> b
$ \MBA s
mba -> MBA s -> a -> Int -> ST s (Int, Maybe a)
forall s. MBA s -> a -> Int -> ST s (Int, Maybe a)
go MBA s
mba a
x0 Int
0

  where
    go :: forall s. MBA s -> a -> Int -> ST s (Int, Maybe a)
    go :: forall s. MBA s -> a -> Int -> ST s (Int, Maybe a)
go !MBA s
mba !a
x !Int
n = a -> Int -> ST s (Int, Maybe a)
go' a
x Int
n
      where
        go' :: a -> Int -> ST s (Int, Maybe a)
        go' :: a -> Int -> ST s (Int, Maybe a)
go' !a
x' !Int
n'
          | Int
n' Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
i   = (Int, Maybe a) -> ST s (Int, Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
n', a -> Maybe a
forall a. a -> Maybe a
Just a
x')
          | Bool
otherwise = case a -> Maybe (Word8, a)
f a
x' of
                          Maybe (Word8, a)
Nothing       -> (Int, Maybe a) -> ST s (Int, Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
n', Maybe a
forall a. Maybe a
Nothing)
                          Just (Word8
w, a
x'') -> do
                                             MBA s -> Int -> Word8 -> ST s ()
forall s. MBA s -> Int -> Word8 -> ST s ()
writeWord8Array MBA s
mba Int
n' Word8
w
                                             a -> Int -> ST s (Int, Maybe a)
go' a
x'' (Int
n'Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)



-- --------------------------------------------------------------------
-- Predicates

-- | Check whether one string is a substring of another.
--
-- @since 0.11.3.0
isInfixOf :: ShortByteString -> ShortByteString -> Bool
isInfixOf :: ShortByteString -> ShortByteString -> Bool
isInfixOf ShortByteString
sbs = \ShortByteString
s -> ShortByteString -> Bool
null ShortByteString
sbs Bool -> Bool -> Bool
|| Bool -> Bool
not (ShortByteString -> Bool
null (ShortByteString -> Bool) -> ShortByteString -> Bool
forall a b. (a -> b) -> a -> b
$ (ShortByteString, ShortByteString) -> ShortByteString
forall a b. (a, b) -> b
snd ((ShortByteString, ShortByteString) -> ShortByteString)
-> (ShortByteString, ShortByteString) -> ShortByteString
forall a b. (a -> b) -> a -> b
$ ((ShortByteString
 -> ShortByteString -> (ShortByteString, ShortByteString))
-> ShortByteString
-> ShortByteString
-> (ShortByteString, ShortByteString)
forall a. a -> a
GHC.Exts.inline ShortByteString
-> ShortByteString -> (ShortByteString, ShortByteString)
breakSubstring) ShortByteString
sbs ShortByteString
s)

-- |/O(n)/ The 'isPrefixOf' function takes two ShortByteStrings and returns 'True'
--
-- @since 0.11.3.0
isPrefixOf :: ShortByteString -> ShortByteString -> Bool
isPrefixOf :: ShortByteString -> ShortByteString -> Bool
isPrefixOf ShortByteString
sbs1 = \ShortByteString
sbs2 -> do
  let l1 :: Int
l1 = ShortByteString -> Int
length ShortByteString
sbs1
      l2 :: Int
l2 = ShortByteString -> Int
length ShortByteString
sbs2
  if | Int
l1 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0   -> Bool
True
     | Int
l2 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
l1   -> Bool
False
     | Bool
otherwise ->
         let i :: Int
i = BA -> Int -> BA -> Int -> Int -> Int
compareByteArraysOff (ShortByteString -> BA
asBA ShortByteString
sbs1) Int
0 (ShortByteString -> BA
asBA ShortByteString
sbs2) Int
0 Int
l1
         in Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0

-- | /O(n)/ The 'isSuffixOf' function takes two ShortByteStrings and returns 'True'
-- iff the first is a suffix of the second.
--
-- The following holds:
--
-- > isSuffixOf x y == reverse x `isPrefixOf` reverse y
--
-- @since 0.11.3.0
isSuffixOf :: ShortByteString -> ShortByteString -> Bool
isSuffixOf :: ShortByteString -> ShortByteString -> Bool
isSuffixOf ShortByteString
sbs1 = \ShortByteString
sbs2 -> do
  let l1 :: Int
l1 = ShortByteString -> Int
length ShortByteString
sbs1
      l2 :: Int
l2 = ShortByteString -> Int
length ShortByteString
sbs2
  if | Int
l1 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0   -> Bool
True
     | Int
l2 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
l1   -> Bool
False
     | Bool
otherwise ->
         let i :: Int
i = BA -> Int -> BA -> Int -> Int -> Int
compareByteArraysOff (ShortByteString -> BA
asBA ShortByteString
sbs1) Int
0 (ShortByteString -> BA
asBA ShortByteString
sbs2) (Int
l2 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
l1) Int
l1
         in Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0

-- | Break a string on a substring, returning a pair of the part of the
-- string prior to the match, and the rest of the string.
--
-- The following relationships hold:
--
-- > break (== c) l == breakSubstring (singleton c) l
--
-- For example, to tokenise a string, dropping delimiters:
--
-- > tokenise x y = h : if null t then [] else tokenise x (drop (length x) t)
-- >     where (h,t) = breakSubstring x y
--
-- To skip to the first occurence of a string:
--
-- > snd (breakSubstring x y)
--
-- To take the parts of a string before a delimiter:
--
-- > fst (breakSubstring x y)
--
-- Note that calling `breakSubstring x` does some preprocessing work, so
-- you should avoid unnecessarily duplicating breakSubstring calls with the same
-- pattern.
--
-- @since 0.11.3.0
breakSubstring :: ShortByteString -- ^ String to search for
               -> ShortByteString -- ^ String to search in
               -> (ShortByteString, ShortByteString) -- ^ Head and tail of string broken at substring
breakSubstring :: ShortByteString
-> ShortByteString -> (ShortByteString, ShortByteString)
breakSubstring ShortByteString
pat =
  case Int
lp of
    Int
0 -> (ShortByteString
empty,)
    Int
1 -> Word8 -> ShortByteString -> (ShortByteString, ShortByteString)
breakByte (HasCallStack => ShortByteString -> Word8
ShortByteString -> Word8
head ShortByteString
pat)
    Int
_ -> if Int
lp Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
8 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Word -> Int
forall b. FiniteBits b => b -> Int
finiteBitSize (Word
0 :: Word)
             then ShortByteString -> (ShortByteString, ShortByteString)
shift
             else ShortByteString -> (ShortByteString, ShortByteString)
karpRabin
  where
    lp :: Int
lp = ShortByteString -> Int
length ShortByteString
pat
    karpRabin :: ShortByteString -> (ShortByteString, ShortByteString)
    karpRabin :: ShortByteString -> (ShortByteString, ShortByteString)
karpRabin ShortByteString
src
        | ShortByteString -> Int
length ShortByteString
src Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
lp = (ShortByteString
src,ShortByteString
empty)
        | Bool
otherwise       = Word32 -> Int -> (ShortByteString, ShortByteString)
search (ShortByteString -> Word32
rollingHash (ShortByteString -> Word32) -> ShortByteString -> Word32
forall a b. (a -> b) -> a -> b
$ Int -> ShortByteString -> ShortByteString
take Int
lp ShortByteString
src) Int
lp
      where
        k :: Word32
k           = Word32
2891336453 :: Word32
        rollingHash :: ShortByteString -> Word32
rollingHash = (Word32 -> Word8 -> Word32) -> Word32 -> ShortByteString -> Word32
forall a. (a -> Word8 -> a) -> a -> ShortByteString -> a
foldl' (\Word32
h Word8
b -> Word32
h Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
* Word32
k Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b) Word32
0
        hp :: Word32
hp          = ShortByteString -> Word32
rollingHash ShortByteString
pat
        m :: Word32
m           = Word32
k Word32 -> Int -> Word32
forall a b. (Num a, Integral b) => a -> b -> a
^ Int
lp
        get :: Int -> Word32
get = Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8 -> Word32) -> (Int -> Word8) -> Int -> Word32
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> Int -> Word8
unsafeIndex ShortByteString
src
        search :: Word32 -> Int -> (ShortByteString, ShortByteString)
search !Word32
hs !Int
i
            | Word32
hp Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
== Word32
hs Bool -> Bool -> Bool
&& ShortByteString
pat ShortByteString -> ShortByteString -> Bool
forall a. Eq a => a -> a -> Bool
== Int -> ShortByteString -> ShortByteString
take Int
lp ShortByteString
b = (ShortByteString, ShortByteString)
u
            | ShortByteString -> Int
length ShortByteString
src Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
i              = (ShortByteString
src, ShortByteString
empty) -- not found
            | Bool
otherwise                    = Word32 -> Int -> (ShortByteString, ShortByteString)
search Word32
hs' (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
          where
            u :: (ShortByteString, ShortByteString)
u@(ShortByteString
_, ShortByteString
b) = Int -> ShortByteString -> (ShortByteString, ShortByteString)
splitAt (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
lp) ShortByteString
src
            hs' :: Word32
hs' = Word32
hs Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
* Word32
k Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+
                  Int -> Word32
get Int
i Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
-
                  Word32
m Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
* Int -> Word32
get (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
lp)
    {-# INLINE karpRabin #-}

    shift :: ShortByteString -> (ShortByteString, ShortByteString)
    shift :: ShortByteString -> (ShortByteString, ShortByteString)
shift !ShortByteString
src
        | ShortByteString -> Int
length ShortByteString
src Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
lp = (ShortByteString
src, ShortByteString
empty)
        | Bool
otherwise       = Word -> Int -> (ShortByteString, ShortByteString)
search (ShortByteString -> Word
intoWord (ShortByteString -> Word) -> ShortByteString -> Word
forall a b. (a -> b) -> a -> b
$ Int -> ShortByteString -> ShortByteString
take Int
lp ShortByteString
src) Int
lp
      where
        intoWord :: ShortByteString -> Word
        intoWord :: ShortByteString -> Word
intoWord = (Word -> Word8 -> Word) -> Word -> ShortByteString -> Word
forall a. (a -> Word8 -> a) -> a -> ShortByteString -> a
foldl' (\Word
w Word8
b -> (Word
w Word -> Int -> Word
forall a. Bits a => a -> Int -> a
`shiftL` Int
8) Word -> Word -> Word
forall a. Bits a => a -> a -> a
.|. Word8 -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b) Word
0

        wp :: Word
wp    = ShortByteString -> Word
intoWord ShortByteString
pat
        mask' :: Word
mask' = (Word
1 Word -> Int -> Word
forall a. Bits a => a -> Int -> a
`shiftL` (Int
8 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
lp)) Word -> Word -> Word
forall a. Num a => a -> a -> a
- Word
1
        search :: Word -> Int -> (ShortByteString, ShortByteString)
search !Word
w !Int
i
            | Word
w Word -> Word -> Bool
forall a. Eq a => a -> a -> Bool
== Word
wp         = Int -> ShortByteString -> (ShortByteString, ShortByteString)
splitAt (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
lp) ShortByteString
src
            | ShortByteString -> Int
length ShortByteString
src Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
i = (ShortByteString
src, ShortByteString
empty)
            | Bool
otherwise       = Word -> Int -> (ShortByteString, ShortByteString)
search Word
w' (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
          where
            b :: Word
b  = Word8 -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ShortByteString -> Int -> Word8
unsafeIndex ShortByteString
src Int
i)
            w' :: Word
w' = Word
mask' Word -> Word -> Word
forall a. Bits a => a -> a -> a
.&. ((Word
w Word -> Int -> Word
forall a. Bits a => a -> Int -> a
`shiftL` Int
8) Word -> Word -> Word
forall a. Bits a => a -> a -> a
.|. Word
b)
    {-# INLINE shift #-}


-- --------------------------------------------------------------------
-- Searching ShortByteString

-- | /O(n)/ 'elem' is the 'ShortByteString' membership predicate.
--
-- @since 0.11.3.0
elem :: Word8 -> ShortByteString -> Bool
elem :: Word8 -> ShortByteString -> Bool
elem Word8
c = \ShortByteString
sbs -> case Word8 -> ShortByteString -> Maybe Int
elemIndex Word8
c ShortByteString
sbs of Maybe Int
Nothing -> Bool
False ; Maybe Int
_ -> Bool
True

-- | /O(n)/ 'filter', applied to a predicate and a ByteString,
-- returns a ByteString containing those characters that satisfy the
-- predicate.
--
-- @since 0.11.3.0
filter :: (Word8 -> Bool) -> ShortByteString -> ShortByteString
filter :: (Word8 -> Bool) -> ShortByteString -> ShortByteString
filter Word8 -> Bool
k = \ShortByteString
sbs -> let l :: Int
l = ShortByteString -> Int
length ShortByteString
sbs
                   in if | Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0    -> ShortByteString
sbs
                         | Bool
otherwise -> Int -> (forall s. MBA s -> ST s Int) -> ShortByteString
createAndTrim' Int
l ((forall s. MBA s -> ST s Int) -> ShortByteString)
-> (forall s. MBA s -> ST s Int) -> ShortByteString
forall a b. (a -> b) -> a -> b
$ \MBA s
mba -> MBA s -> BA -> Int -> ST s Int
forall s. MBA s -> BA -> Int -> ST s Int
go MBA s
mba (ShortByteString -> BA
asBA ShortByteString
sbs) Int
l
  where
    go :: forall s. MBA s -- mutable output bytestring
       -> BA              -- input bytestring
       -> Int             -- length of input bytestring
       -> ST s Int
    go :: forall s. MBA s -> BA -> Int -> ST s Int
go !MBA s
mba BA
ba !Int
l = Int -> Int -> ST s Int
go' Int
0 Int
0
      where
        go' :: Int -- bytes read
            -> Int -- bytes written
            -> ST s Int
        go' :: Int -> Int -> ST s Int
go' !Int
br !Int
bw
          | Int
br Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
l   = Int -> ST s Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
bw
          | Bool
otherwise = do
              let w :: Word8
w = BA -> Int -> Word8
indexWord8Array BA
ba Int
br
              if Word8 -> Bool
k Word8
w
              then do
                MBA s -> Int -> Word8 -> ST s ()
forall s. MBA s -> Int -> Word8 -> ST s ()
writeWord8Array MBA s
mba Int
bw Word8
w
                Int -> Int -> ST s Int
go' (Int
brInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) (Int
bwInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
              else
                Int -> Int -> ST s Int
go' (Int
brInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Int
bw

-- | /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
--
-- @since 0.11.3.0
find :: (Word8 -> Bool) -> ShortByteString -> Maybe Word8
find :: (Word8 -> Bool) -> ShortByteString -> Maybe Word8
find Word8 -> Bool
f = \ShortByteString
sbs -> case (Word8 -> Bool) -> ShortByteString -> Maybe Int
findIndex Word8 -> Bool
f ShortByteString
sbs of
                    Just Int
n -> Word8 -> Maybe Word8
forall a. a -> Maybe a
Just (ShortByteString
sbs HasCallStack => ShortByteString -> Int -> Word8
ShortByteString -> Int -> Word8
`index` Int
n)
                    Maybe Int
_      -> Maybe Word8
forall a. Maybe a
Nothing

-- | /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 sbs, filter (not . p) sbs)
--
-- @since 0.11.3.0
partition :: (Word8 -> Bool) -> ShortByteString -> (ShortByteString, ShortByteString)
partition :: (Word8 -> Bool)
-> ShortByteString -> (ShortByteString, ShortByteString)
partition Word8 -> Bool
k = \ShortByteString
sbs -> let l :: Int
l = ShortByteString -> Int
length ShortByteString
sbs
                   in if | Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0    -> (ShortByteString
sbs, ShortByteString
sbs)
                         | Bool
otherwise -> Int
-> (forall s. MBA s -> MBA s -> ST s (Int, Int))
-> (ShortByteString, ShortByteString)
createAndTrim'' Int
l ((forall s. MBA s -> MBA s -> ST s (Int, Int))
 -> (ShortByteString, ShortByteString))
-> (forall s. MBA s -> MBA s -> ST s (Int, Int))
-> (ShortByteString, ShortByteString)
forall a b. (a -> b) -> a -> b
$ \MBA s
mba1 MBA s
mba2 -> MBA s -> MBA s -> BA -> Int -> ST s (Int, Int)
forall s. MBA s -> MBA s -> BA -> Int -> ST s (Int, Int)
go MBA s
mba1 MBA s
mba2 (ShortByteString -> BA
asBA ShortByteString
sbs) Int
l
  where
    go :: forall s.
          MBA s           -- mutable output bytestring1
       -> MBA s           -- mutable output bytestring2
       -> BA              -- input bytestring
       -> Int             -- length of input bytestring
       -> ST s (Int, Int) -- (length mba1, length mba2)
    go :: forall s. MBA s -> MBA s -> BA -> Int -> ST s (Int, Int)
go !MBA s
mba1 !MBA s
mba2 BA
ba !Int
l = Int -> Int -> ST s (Int, Int)
go' Int
0 Int
0
      where
        go' :: Int -- bytes read
            -> Int -- bytes written to bytestring 1
            -> ST s (Int, Int) -- (length mba1, length mba2)
        go' :: Int -> Int -> ST s (Int, Int)
go' !Int
br !Int
bw1
          | Int
br Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
l   = (Int, Int) -> ST s (Int, Int)
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
bw1, Int
br Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
bw1)
          | Bool
otherwise = do
              let w :: Word8
w = BA -> Int -> Word8
indexWord8Array BA
ba Int
br
              if Word8 -> Bool
k Word8
w
              then do
                MBA s -> Int -> Word8 -> ST s ()
forall s. MBA s -> Int -> Word8 -> ST s ()
writeWord8Array MBA s
mba1 Int
bw1 Word8
w
                Int -> Int -> ST s (Int, Int)
go' (Int
brInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) (Int
bw1Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
              else do
                MBA s -> Int -> Word8 -> ST s ()
forall s. MBA s -> Int -> Word8 -> ST s ()
writeWord8Array MBA s
mba2 (Int
br Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
bw1) Word8
w
                Int -> Int -> ST s (Int, Int)
go' (Int
brInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Int
bw1


-- --------------------------------------------------------------------
-- Indexing ShortByteString

-- | /O(n)/ The 'elemIndex' function returns the index of the first
-- element in the given 'ShortByteString' which is equal to the query
-- element, or 'Nothing' if there is no such element.
--
-- @since 0.11.3.0
elemIndex :: Word8 -> ShortByteString -> Maybe Int
elemIndex :: Word8 -> ShortByteString -> Maybe Int
elemIndex Word8
c = \sbs :: ShortByteString
sbs@(SBS ByteArray#
ba#) -> do
    let l :: Int
l = ShortByteString -> Int
length ShortByteString
sbs
    IO (Maybe Int) -> Maybe Int
forall a. IO a -> a
accursedUnutterablePerformIO (IO (Maybe Int) -> Maybe Int) -> IO (Maybe Int) -> Maybe Int
forall a b. (a -> b) -> a -> b
$ do
      !CPtrdiff
s <- ByteArray# -> Word8 -> CSize -> IO CPtrdiff
c_elem_index ByteArray#
ba# Word8
c (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
l)
      Maybe Int -> IO (Maybe Int)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe Int -> IO (Maybe Int)) -> Maybe Int -> IO (Maybe Int)
forall a b. (a -> b) -> a -> b
$! if CPtrdiff
s CPtrdiff -> CPtrdiff -> Bool
forall a. Ord a => a -> a -> Bool
< CPtrdiff
0 then Maybe Int
forall a. Maybe a
Nothing else Int -> Maybe Int
forall a. a -> Maybe a
Just (CPtrdiff -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CPtrdiff
s)


-- | /O(n)/ The 'elemIndices' function extends 'elemIndex', by returning
-- the indices of all elements equal to the query element, in ascending order.
--
-- @since 0.11.3.0
elemIndices :: Word8 -> ShortByteString -> [Int]
elemIndices :: Word8 -> ShortByteString -> [Int]
elemIndices Word8
k = (Word8 -> Bool) -> ShortByteString -> [Int]
findIndices (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
==Word8
k)

-- | count returns the number of times its argument appears in the ShortByteString
--
-- @since 0.11.3.0
count :: Word8 -> ShortByteString -> Int
count :: Word8 -> ShortByteString -> Int
count Word8
w = \sbs :: ShortByteString
sbs@(SBS ByteArray#
ba#) -> IO Int -> Int
forall a. IO a -> a
accursedUnutterablePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$
    CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CSize -> Int) -> IO CSize -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ByteArray# -> CSize -> Word8 -> IO CSize
c_count ByteArray#
ba# (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> CSize) -> Int -> CSize
forall a b. (a -> b) -> a -> b
$ ShortByteString -> Int
length ShortByteString
sbs) Word8
w

-- | /O(n)/ The 'findIndex' function takes a predicate and a 'ShortByteString' and
-- returns the index of the first element in the ByteString
-- satisfying the predicate.
--
-- @since 0.11.3.0
findIndex :: (Word8 -> Bool) -> ShortByteString -> Maybe Int
findIndex :: (Word8 -> Bool) -> ShortByteString -> Maybe Int
findIndex Word8 -> Bool
k = \ShortByteString
sbs ->
  let l :: Int
l  = ShortByteString -> Int
length ShortByteString
sbs
      ba :: BA
ba = ShortByteString -> BA
asBA ShortByteString
sbs
      w :: Int -> Word8
w  = BA -> Int -> Word8
indexWord8Array BA
ba
      go :: Int -> Maybe Int
go !Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
l    = Maybe Int
forall a. Maybe a
Nothing
            | Word8 -> Bool
k (Int -> Word8
w Int
n)   = Int -> Maybe Int
forall a. a -> Maybe a
Just Int
n
            | Bool
otherwise = Int -> Maybe Int
go (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
  in Int -> Maybe Int
go Int
0


-- | /O(n)/ The 'findIndices' function extends 'findIndex', by returning the
-- indices of all elements satisfying the predicate, in ascending order.
--
-- @since 0.11.3.0
findIndices :: (Word8 -> Bool) -> ShortByteString -> [Int]
findIndices :: (Word8 -> Bool) -> ShortByteString -> [Int]
findIndices Word8 -> Bool
k = \ShortByteString
sbs ->
  let l :: Int
l  = ShortByteString -> Int
length ShortByteString
sbs
      ba :: BA
ba = ShortByteString -> BA
asBA ShortByteString
sbs
      w :: Int -> Word8
w  = BA -> Int -> Word8
indexWord8Array BA
ba
      go :: Int -> [Int]
go !Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
l    = []
            | Word8 -> Bool
k (Int -> Word8
w Int
n)   = Int
n Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: Int -> [Int]
go (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
            | Bool
otherwise = Int -> [Int]
go (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
  in Int -> [Int]
go Int
0



------------------------------------------------------------------------
-- Exported low level operations

copyToPtr :: ShortByteString  -- ^ source data
          -> Int              -- ^ offset into source
          -> Ptr a            -- ^ destination
          -> Int              -- ^ number of bytes to copy
          -> IO ()
copyToPtr :: forall a. ShortByteString -> Int -> Ptr a -> Int -> IO ()
copyToPtr ShortByteString
src Int
off Ptr a
dst Int
len =
    ST RealWorld () -> IO ()
forall a. ST RealWorld a -> IO a
stToIO (ST RealWorld () -> IO ()) -> ST RealWorld () -> IO ()
forall a b. (a -> b) -> a -> b
$
      BA -> Int -> Ptr a -> Int -> ST RealWorld ()
forall a. BA -> Int -> Ptr a -> Int -> ST RealWorld ()
copyByteArrayToAddr (ShortByteString -> BA
asBA ShortByteString
src) Int
off Ptr a
dst Int
len

createFromPtr :: Ptr a   -- ^ source data
              -> Int     -- ^ number of bytes to copy
              -> IO ShortByteString
createFromPtr :: forall a. Ptr a -> Int -> IO ShortByteString
createFromPtr !Ptr a
ptr Int
len =
    ST RealWorld ShortByteString -> IO ShortByteString
forall a. ST RealWorld a -> IO a
stToIO (ST RealWorld ShortByteString -> IO ShortByteString)
-> ST RealWorld ShortByteString -> IO ShortByteString
forall a b. (a -> b) -> a -> b
$ do
      MBA RealWorld
mba <- Int -> ST RealWorld (MBA RealWorld)
forall s. Int -> ST s (MBA s)
newByteArray Int
len
      Ptr a -> MBA RealWorld -> Int -> Int -> ST RealWorld ()
forall a. Ptr a -> MBA RealWorld -> Int -> Int -> ST RealWorld ()
copyAddrToByteArray Ptr a
ptr MBA RealWorld
mba Int
0 Int
len
      BA# ByteArray#
ba# <- MBA RealWorld -> ST RealWorld BA
forall s. MBA s -> ST s BA
unsafeFreezeByteArray MBA RealWorld
mba
      ShortByteString -> ST RealWorld ShortByteString
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteArray# -> ShortByteString
SBS ByteArray#
ba#)


------------------------------------------------------------------------
-- Primop wrappers

data BA    = BA# ByteArray#
data MBA s = MBA# (MutableByteArray# s)

indexCharArray :: BA -> Int -> Char
indexCharArray :: BA -> Int -> Char
indexCharArray (BA# ByteArray#
ba#) (I# Int#
i#) = Char# -> Char
C# (ByteArray# -> Int# -> Char#
indexCharArray# ByteArray#
ba# Int#
i#)

indexWord8Array :: BA -> Int -> Word8
indexWord8Array :: BA -> Int -> Word8
indexWord8Array (BA# ByteArray#
ba#) (I# Int#
i#) = Word8# -> Word8
W8# (ByteArray# -> Int# -> Word8#
indexWord8Array# ByteArray#
ba# Int#
i#)

#if MIN_VERSION_base(4,12,0) && defined(SAFE_UNALIGNED)
indexWord8ArrayAsWord64 :: BA -> Int -> Word64
indexWord8ArrayAsWord64 :: BA -> Int -> Word64
indexWord8ArrayAsWord64 (BA# ByteArray#
ba#) (I# Int#
i#) = Word# -> Word64
W64# (ByteArray# -> Int# -> Word#
indexWord8ArrayAsWord64# ByteArray#
ba# Int#
i#)
#endif

newByteArray :: Int -> ST s (MBA s)
newByteArray :: forall s. Int -> ST s (MBA s)
newByteArray (I# Int#
len#) =
    STRep s (MBA s) -> ST s (MBA s)
forall s a. STRep s a -> ST s a
ST (STRep s (MBA s) -> ST s (MBA s))
-> STRep s (MBA s) -> ST s (MBA s)
forall a b. (a -> b) -> a -> b
$ \State# s
s -> case Int# -> State# s -> (# State# s, MutableByteArray# s #)
forall d. Int# -> State# d -> (# State# d, MutableByteArray# d #)
newByteArray# Int#
len# State# s
s of
                 (# State# s
s, MutableByteArray# s
mba# #) -> (# State# s
s, MutableByteArray# s -> MBA s
forall s. MutableByteArray# s -> MBA s
MBA# MutableByteArray# s
mba# #)

newPinnedByteArray :: Int -> ST s (MBA s)
newPinnedByteArray :: forall s. Int -> ST s (MBA s)
newPinnedByteArray (I# Int#
len#) =
    STRep s (MBA s) -> ST s (MBA s)
forall s a. STRep s a -> ST s a
ST (STRep s (MBA s) -> ST s (MBA s))
-> STRep s (MBA s) -> ST s (MBA s)
forall a b. (a -> b) -> a -> b
$ \State# s
s -> case Int# -> State# s -> (# State# s, MutableByteArray# s #)
forall d. Int# -> State# d -> (# State# d, MutableByteArray# d #)
newPinnedByteArray# Int#
len# State# s
s of
                 (# State# s
s, MutableByteArray# s
mba# #) -> (# State# s
s, MutableByteArray# s -> MBA s
forall s. MutableByteArray# s -> MBA s
MBA# MutableByteArray# s
mba# #)

unsafeFreezeByteArray :: MBA s -> ST s BA
unsafeFreezeByteArray :: forall s. MBA s -> ST s BA
unsafeFreezeByteArray (MBA# MutableByteArray# s
mba#) =
    STRep s BA -> ST s BA
forall s a. STRep s a -> ST s a
ST (STRep s BA -> ST s BA) -> STRep s BA -> ST s BA
forall a b. (a -> b) -> a -> b
$ \State# s
s -> case MutableByteArray# s -> State# s -> (# State# s, ByteArray# #)
forall d.
MutableByteArray# d -> State# d -> (# State# d, ByteArray# #)
unsafeFreezeByteArray# MutableByteArray# s
mba# State# s
s of
                 (# State# s
s, ByteArray#
ba# #) -> (# State# s
s, ByteArray# -> BA
BA# ByteArray#
ba# #)

writeWord8Array :: MBA s -> Int -> Word8 -> ST s ()
writeWord8Array :: forall s. MBA s -> Int -> Word8 -> ST s ()
writeWord8Array (MBA# MutableByteArray# s
mba#) (I# Int#
i#) (W8# Word8#
w#) =
  STRep s () -> ST s ()
forall s a. STRep s a -> ST s a
ST (STRep s () -> ST s ()) -> STRep s () -> ST s ()
forall a b. (a -> b) -> a -> b
$ \State# s
s -> case MutableByteArray# s -> Int# -> Word8# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word8# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# Int#
i# Word8#
w# State# s
s of
               State# s
s -> (# State# s
s, () #)

#if MIN_VERSION_base(4,12,0) && defined(SAFE_UNALIGNED)
writeWord64Array :: MBA s -> Int -> Word64 -> ST s ()
writeWord64Array :: forall s. MBA s -> Int -> Word64 -> ST s ()
writeWord64Array (MBA# MutableByteArray# s
mba#) (I# Int#
i#) (W64# Word#
w#) =
  STRep s () -> ST s ()
forall s a. STRep s a -> ST s a
ST (STRep s () -> ST s ()) -> STRep s () -> ST s ()
forall a b. (a -> b) -> a -> b
$ \State# s
s -> case MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord64Array# MutableByteArray# s
mba# Int#
i# Word#
w# State# s
s of
               State# s
s -> (# State# s
s, () #)
#endif

copyAddrToByteArray :: Ptr a -> MBA RealWorld -> Int -> Int -> ST RealWorld ()
copyAddrToByteArray :: forall a. Ptr a -> MBA RealWorld -> Int -> Int -> ST RealWorld ()
copyAddrToByteArray (Ptr Addr#
src#) (MBA# MutableByteArray# RealWorld
dst#) (I# Int#
dst_off#) (I# Int#
len#) =
    STRep RealWorld () -> ST RealWorld ()
forall s a. STRep s a -> ST s a
ST (STRep RealWorld () -> ST RealWorld ())
-> STRep RealWorld () -> ST RealWorld ()
forall a b. (a -> b) -> a -> b
$ \State# RealWorld
s -> case Addr#
-> MutableByteArray# RealWorld
-> Int#
-> Int#
-> State# RealWorld
-> State# RealWorld
copyAddrToByteArray# Addr#
src# MutableByteArray# RealWorld
dst# Int#
dst_off# Int#
len# State# RealWorld
s of
                 State# RealWorld
s -> (# State# RealWorld
s, () #)

copyByteArrayToAddr :: BA -> Int -> Ptr a -> Int -> ST RealWorld ()
copyByteArrayToAddr :: forall a. BA -> Int -> Ptr a -> Int -> ST RealWorld ()
copyByteArrayToAddr (BA# ByteArray#
src#) (I# Int#
src_off#) (Ptr Addr#
dst#) (I# Int#
len#) =
    STRep RealWorld () -> ST RealWorld ()
forall s a. STRep s a -> ST s a
ST (STRep RealWorld () -> ST RealWorld ())
-> STRep RealWorld () -> ST RealWorld ()
forall a b. (a -> b) -> a -> b
$ \State# RealWorld
s -> case ByteArray#
-> Int# -> Addr# -> Int# -> State# RealWorld -> State# RealWorld
copyByteArrayToAddr# ByteArray#
src# Int#
src_off# Addr#
dst# Int#
len# State# RealWorld
s of
                 State# RealWorld
s -> (# State# RealWorld
s, () #)

copyByteArray :: BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray :: forall s. BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (BA# ByteArray#
src#) (I# Int#
src_off#) (MBA# MutableByteArray# s
dst#) (I# Int#
dst_off#) (I# Int#
len#) =
    STRep s () -> ST s ()
forall s a. STRep s a -> ST s a
ST (STRep s () -> ST s ()) -> STRep s () -> ST s ()
forall a b. (a -> b) -> a -> b
$ \State# s
s -> case ByteArray#
-> Int#
-> MutableByteArray# s
-> Int#
-> Int#
-> State# s
-> State# s
forall s.
ByteArray#
-> Int#
-> MutableByteArray# s
-> Int#
-> Int#
-> State# s
-> State# s
copyByteArray# ByteArray#
src# Int#
src_off# MutableByteArray# s
dst# Int#
dst_off# Int#
len# State# s
s of
                 State# s
s -> (# State# s
s, () #)

setByteArray :: MBA s -> Int -> Int -> Int -> ST s ()
setByteArray :: forall s. MBA s -> Int -> Int -> Int -> ST s ()
setByteArray (MBA# MutableByteArray# s
dst#) (I# Int#
off#) (I# Int#
len#) (I# Int#
c#) =
    STRep s () -> ST s ()
forall s a. STRep s a -> ST s a
ST (STRep s () -> ST s ()) -> STRep s () -> ST s ()
forall a b. (a -> b) -> a -> b
$ \State# s
s -> case MutableByteArray# s -> Int# -> Int# -> Int# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Int# -> Int# -> State# d -> State# d
setByteArray# MutableByteArray# s
dst# Int#
off# Int#
len# Int#
c# State# s
s of
                 State# s
s -> (# State# s
s, () #)

copyMutableByteArray :: MBA s -> Int -> MBA s -> Int -> Int -> ST s ()
copyMutableByteArray :: forall s. MBA s -> Int -> MBA s -> Int -> Int -> ST s ()
copyMutableByteArray (MBA# MutableByteArray# s
src#) (I# Int#
src_off#) (MBA# MutableByteArray# s
dst#) (I# Int#
dst_off#) (I# Int#
len#) =
    STRep s () -> ST s ()
forall s a. STRep s a -> ST s a
ST (STRep s () -> ST s ()) -> STRep s () -> ST s ()
forall a b. (a -> b) -> a -> b
$ \State# s
s -> case MutableByteArray# s
-> Int#
-> MutableByteArray# s
-> Int#
-> Int#
-> State# s
-> State# s
forall d.
MutableByteArray# d
-> Int#
-> MutableByteArray# d
-> Int#
-> Int#
-> State# d
-> State# d
copyMutableByteArray# MutableByteArray# s
src# Int#
src_off# MutableByteArray# s
dst# Int#
dst_off# Int#
len# State# s
s of
                 State# s
s -> (# State# s
s, () #)


------------------------------------------------------------------------
-- FFI imports
--
compareByteArrays :: BA -> BA -> Int -> Int
compareByteArrays :: BA -> BA -> Int -> Int
compareByteArrays BA
ba1 BA
ba2 = BA -> Int -> BA -> Int -> Int -> Int
compareByteArraysOff BA
ba1 Int
0 BA
ba2 Int
0

compareByteArraysOff :: BA  -- ^ array 1
                     -> Int -- ^ offset for array 1
                     -> BA  -- ^ array 2
                     -> Int -- ^ offset for array 2
                     -> Int -- ^ length to compare
                     -> Int -- ^ like memcmp
#if MIN_VERSION_base(4,11,0)
compareByteArraysOff :: BA -> Int -> BA -> Int -> Int -> Int
compareByteArraysOff (BA# ByteArray#
ba1#) (I# Int#
ba1off#) (BA# ByteArray#
ba2#) (I# Int#
ba2off#) (I# Int#
len#) =
  Int# -> Int
I# (ByteArray# -> Int# -> ByteArray# -> Int# -> Int# -> Int#
compareByteArrays#  ByteArray#
ba1# Int#
ba1off# ByteArray#
ba2# Int#
ba2off# Int#
len#)
#else
compareByteArraysOff (BA# ba1#) ba1off (BA# ba2#) ba2off len =
  assert (ba1off + len <= (I# (sizeofByteArray# ba1#)))
  $ assert (ba2off + len <= (I# (sizeofByteArray# ba2#)))
  $ fromIntegral $ accursedUnutterablePerformIO $
    c_memcmp_ByteArray ba1#
                       ba1off
                       ba2#
                       ba2off
                       (fromIntegral len)


foreign import ccall unsafe "static sbs_memcmp_off"
  c_memcmp_ByteArray :: ByteArray# -> Int -> ByteArray# -> Int -> CSize -> IO CInt
#endif

foreign import ccall unsafe "static sbs_elem_index"
    c_elem_index :: ByteArray# -> Word8 -> CSize -> IO CPtrdiff

foreign import ccall unsafe "static fpstring.h fps_count" c_count
    :: ByteArray# -> CSize -> Word8 -> IO CSize


------------------------------------------------------------------------
-- Primop replacements

copyAddrToByteArray# :: Addr#
                     -> MutableByteArray# RealWorld -> Int#
                     -> Int#
                     -> State# RealWorld -> State# RealWorld

copyByteArrayToAddr# :: ByteArray# -> Int#
                     -> Addr#
                     -> Int#
                     -> State# RealWorld -> State# RealWorld

copyByteArray#       :: ByteArray# -> Int#
                     -> MutableByteArray# s -> Int#
                     -> Int#
                     -> State# s -> State# s

copyAddrToByteArray# :: Addr#
-> MutableByteArray# RealWorld
-> Int#
-> Int#
-> State# RealWorld
-> State# RealWorld
copyAddrToByteArray# = Addr#
-> MutableByteArray# RealWorld
-> Int#
-> Int#
-> State# RealWorld
-> State# RealWorld
forall d.
Addr#
-> MutableByteArray# d -> Int# -> Int# -> State# d -> State# d
GHC.Exts.copyAddrToByteArray#
copyByteArrayToAddr# :: ByteArray#
-> Int# -> Addr# -> Int# -> State# RealWorld -> State# RealWorld
copyByteArrayToAddr# = ByteArray#
-> Int# -> Addr# -> Int# -> State# RealWorld -> State# RealWorld
forall d.
ByteArray# -> Int# -> Addr# -> Int# -> State# d -> State# d
GHC.Exts.copyByteArrayToAddr#
copyByteArray# :: forall s.
ByteArray#
-> Int#
-> MutableByteArray# s
-> Int#
-> Int#
-> State# s
-> State# s
copyByteArray# = ByteArray#
-> Int#
-> MutableByteArray# s
-> Int#
-> Int#
-> State# s
-> State# s
forall s.
ByteArray#
-> Int#
-> MutableByteArray# s
-> Int#
-> Int#
-> State# s
-> State# s
GHC.Exts.copyByteArray#

-- | /O(n)./ Construct a new @ShortByteString@ from a @CString@. The
-- resulting @ShortByteString@ is an immutable copy of the original
-- @CString@, and is managed on the Haskell heap. The original
-- @CString@ must be null terminated.
--
-- @since 0.10.10.0
packCString :: CString -> IO ShortByteString
packCString :: CString -> IO ShortByteString
packCString CString
cstr = do
  CSize
len <- CString -> IO CSize
BS.c_strlen CString
cstr
  CStringLen -> IO ShortByteString
packCStringLen (CString
cstr, CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
len)

-- | /O(n)./ Construct a new @ShortByteString@ from a @CStringLen@. The
-- resulting @ShortByteString@ is an immutable copy of the original @CStringLen@.
-- The @ShortByteString@ is a normal Haskell value and will be managed on the
-- Haskell heap.
--
-- @since 0.10.10.0
packCStringLen :: CStringLen -> IO ShortByteString
packCStringLen :: CStringLen -> IO ShortByteString
packCStringLen (CString
cstr, Int
len) | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 = CString -> Int -> IO ShortByteString
forall a. Ptr a -> Int -> IO ShortByteString
createFromPtr CString
cstr Int
len
packCStringLen (CString
_, Int
len) =
  String -> String -> IO ShortByteString
forall a. HasCallStack => String -> String -> IO a
moduleErrorIO String
"packCStringLen" (String
"negative length: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
len)

-- | /O(n) construction./ Use a @ShortByteString@ with a function requiring a
-- null-terminated @CString@.  The @CString@ is a copy and will be freed
-- automatically; it must not be stored or used after the
-- subcomputation finishes.
--
-- @since 0.10.10.0
useAsCString :: ShortByteString -> (CString -> IO a) -> IO a
useAsCString :: forall a. ShortByteString -> (CString -> IO a) -> IO a
useAsCString ShortByteString
sbs CString -> IO a
action =
  Int -> (CString -> IO a) -> IO a
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes (Int
lInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) ((CString -> IO a) -> IO a) -> (CString -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \CString
buf -> do
      ShortByteString -> Int -> CString -> Int -> IO ()
forall a. ShortByteString -> Int -> Ptr a -> Int -> IO ()
copyToPtr ShortByteString
sbs Int
0 CString
buf (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
l)
      CString -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff CString
buf Int
l (Word8
0::Word8)
      CString -> IO a
action CString
buf
  where l :: Int
l = ShortByteString -> Int
length ShortByteString
sbs

-- | /O(n) construction./ Use a @ShortByteString@ with a function requiring a @CStringLen@.
-- As for @useAsCString@ this function makes a copy of the original @ShortByteString@.
-- It must not be stored or used after the subcomputation finishes.
--
-- @since 0.10.10.0
useAsCStringLen :: ShortByteString -> (CStringLen -> IO a) -> IO a
useAsCStringLen :: forall a. ShortByteString -> (CStringLen -> IO a) -> IO a
useAsCStringLen ShortByteString
sbs CStringLen -> IO a
action =
  Int -> (CString -> IO a) -> IO a
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes Int
l ((CString -> IO a) -> IO a) -> (CString -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \CString
buf -> do
      ShortByteString -> Int -> CString -> Int -> IO ()
forall a. ShortByteString -> Int -> Ptr a -> Int -> IO ()
copyToPtr ShortByteString
sbs Int
0 CString
buf (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
l)
      CStringLen -> IO a
action (CString
buf, Int
l)
  where l :: Int
l = ShortByteString -> Int
length ShortByteString
sbs

-- | /O(n)/ Check whether a 'ShortByteString' represents valid UTF-8.
--
-- @since 0.11.3.0
isValidUtf8 :: ShortByteString -> Bool
isValidUtf8 :: ShortByteString -> Bool
isValidUtf8 sbs :: ShortByteString
sbs@(SBS ByteArray#
ba#) = IO Bool -> Bool
forall a. IO a -> a
accursedUnutterablePerformIO (IO Bool -> Bool) -> IO Bool -> Bool
forall a b. (a -> b) -> a -> b
$ do
  let n :: Int
n = ShortByteString -> Int
length ShortByteString
sbs
  -- Use a safe FFI call for large inputs to avoid GC synchronization pauses
  -- in multithreaded contexts.
  -- This specific limit was chosen based on results of a simple benchmark, see:
  -- https://github.com/haskell/bytestring/issues/451#issuecomment-991879338
  -- When changing this function, also consider changing the related function:
  -- Data.ByteString.isValidUtf8
  CInt
i <- if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
1000000 Bool -> Bool -> Bool
|| Bool -> Bool
not (ByteArray# -> Bool
isPinned ByteArray#
ba#)
     then ByteArray# -> CSize -> IO CInt
cIsValidUtf8 ByteArray#
ba# (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n)
     else ByteArray# -> CSize -> IO CInt
cIsValidUtf8Safe ByteArray#
ba# (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n)
  STRep RealWorld () -> IO ()
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO (\State# RealWorld
s -> (# ByteArray# -> State# RealWorld -> State# RealWorld
touch# ByteArray#
ba# State# RealWorld
s, () #))
  Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ CInt
i CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
0

-- We import bytestring_is_valid_utf8 both unsafe and safe. For small inputs
-- we can use the unsafe version to get a bit more performance, but for large
-- inputs the safe version should be used to avoid GC synchronization pauses
-- in multithreaded contexts.

foreign import ccall unsafe "bytestring_is_valid_utf8" cIsValidUtf8
  :: ByteArray# -> CSize -> IO CInt

foreign import ccall safe "bytestring_is_valid_utf8" cIsValidUtf8Safe
  :: ByteArray# -> CSize -> IO CInt

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

moduleErrorIO :: HasCallStack => String -> String -> IO a
moduleErrorIO :: forall a. HasCallStack => String -> String -> IO a
moduleErrorIO String
fun String
msg = IOError -> IO a
forall e a. Exception e => e -> IO a
throwIO (IOError -> IO a) -> (String -> IOError) -> String -> IO a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> IOError
userError (String -> IO a) -> String -> IO a
forall a b. (a -> b) -> a -> b
$ String -> ShowS
moduleErrorMsg String
fun String
msg
{-# NOINLINE moduleErrorIO #-}

moduleErrorMsg :: String -> String -> String
moduleErrorMsg :: String -> ShowS
moduleErrorMsg String
fun String
msg = String
"Data.ByteString.Short." String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
fun String -> ShowS
forall a. [a] -> [a] -> [a]
++ Char
':'Char -> ShowS
forall a. a -> [a] -> [a]
:Char
' 'Char -> ShowS
forall a. a -> [a] -> [a]
:String
msg


-- Find from the end of the string using predicate.
--
-- Return '0' if the predicate returns false for the entire ShortByteString.
findFromEndUntil :: (Word8 -> Bool) -> ShortByteString -> Int
findFromEndUntil :: (Word8 -> Bool) -> ShortByteString -> Int
findFromEndUntil Word8 -> Bool
k ShortByteString
sbs = Int -> Int
go (ShortByteString -> Int
length ShortByteString
sbs Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
  where
    ba :: BA
ba = ShortByteString -> BA
asBA ShortByteString
sbs
    go :: Int -> Int
go !Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0                    = Int
0
          | Word8 -> Bool
k (BA -> Int -> Word8
indexWord8Array BA
ba Int
n) = Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
          | Bool
otherwise                = Int -> Int
go (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)

findIndexOrLength :: (Word8 -> Bool) -> ShortByteString -> Int
findIndexOrLength :: (Word8 -> Bool) -> ShortByteString -> Int
findIndexOrLength Word8 -> Bool
k ShortByteString
sbs = Int -> Int
go Int
0
  where
    l :: Int
l = ShortByteString -> Int
length ShortByteString
sbs
    ba :: BA
ba = ShortByteString -> BA
asBA ShortByteString
sbs
    go :: Int -> Int
go !Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
l                   = Int
l
          | Word8 -> Bool
k (BA -> Int -> Word8
indexWord8Array BA
ba Int
n) = Int
n
          | Bool
otherwise                = Int -> Int
go (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)


packBytesRev :: [Word8] -> ShortByteString
packBytesRev :: [Word8] -> ShortByteString
packBytesRev [Word8]
cs = Int -> [Word8] -> ShortByteString
packLenBytesRev ([Word8] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
List.length [Word8]
cs) [Word8]
cs

packLenBytesRev :: Int -> [Word8] -> ShortByteString
packLenBytesRev :: Int -> [Word8] -> ShortByteString
packLenBytesRev Int
len [Word8]
ws0 =
    Int -> (forall s. MBA s -> ST s ()) -> ShortByteString
create Int
len (\MBA s
mba -> MBA s -> Int -> [Word8] -> ST s ()
forall s. MBA s -> Int -> [Word8] -> ST s ()
go MBA s
mba Int
len [Word8]
ws0)
  where
    go :: MBA s -> Int -> [Word8] -> ST s ()
    go :: forall s. MBA s -> Int -> [Word8] -> ST s ()
go !MBA s
_   !Int
_ []     = () -> ST s ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
    go !MBA s
mba !Int
i (Word8
w:[Word8]
ws) = do
      MBA s -> Int -> Word8 -> ST s ()
forall s. MBA s -> Int -> Word8 -> ST s ()
writeWord8Array MBA s
mba (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Word8
w
      MBA s -> Int -> [Word8] -> ST s ()
forall s. MBA s -> Int -> [Word8] -> ST s ()
go MBA s
mba (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) [Word8]
ws


breakByte :: Word8 -> ShortByteString -> (ShortByteString, ShortByteString)
breakByte :: Word8 -> ShortByteString -> (ShortByteString, ShortByteString)
breakByte Word8
c ShortByteString
sbs = case Word8 -> ShortByteString -> Maybe Int
elemIndex Word8
c ShortByteString
sbs of
    Maybe Int
Nothing -> (ShortByteString
sbs, ShortByteString
empty)
    Just Int
n  -> (Int -> ShortByteString -> ShortByteString
take Int
n ShortByteString
sbs, Int -> ShortByteString -> ShortByteString
drop Int
n ShortByteString
sbs)

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

moduleError :: HasCallStack => String -> String -> a
moduleError :: forall a. HasCallStack => String -> String -> a
moduleError String
fun String
msg = String -> a
forall a. HasCallStack => String -> a
error (String -> ShowS
moduleErrorMsg String
fun String
msg)
{-# NOINLINE moduleError #-}