-- |
-- Module      : Data.ByteArray.Methods
-- License     : BSD-style
-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
-- Stability   : stable
-- Portability : Good
--
{-# LANGUAGE CPP #-}
{-# LANGUAGE BangPatterns #-}
module Data.ByteArray.Methods
    ( alloc
    , allocAndFreeze
    , create
    , unsafeCreate
    , pack
    , unpack
    , uncons
    , empty
    , singleton
    , cons
    , snoc
    , null
    , replicate
    , zero
    , copy
    , take
    , drop
    , span
    , reverse
    , convert
    , copyRet
    , copyAndFreeze
    , splitAt
    , xor
    , index
    , eq
    , constEq
    , any
    , all
    , append
    , concat
    ) where

import           Data.ByteArray.Types
import           Data.Memory.Internal.Compat
import           Data.Memory.Internal.Imports hiding (empty)
import           Data.Memory.PtrMethods
import           Data.Monoid
import           Foreign.Storable
import           Foreign.Ptr

import           Prelude hiding (length, take, drop, span, reverse, concat, replicate, splitAt, null, pred, last, any, all)
import qualified Prelude

#if defined(WITH_BYTESTRING_SUPPORT) && defined(WITH_BASEMENT_SUPPORT)
import qualified Data.ByteString as SPE (ByteString)
import qualified Basement.UArray as SPE (UArray)
import qualified Basement.Block  as SPE (Block)
#endif

-- | Allocate a new bytearray of specific size, and run the initializer on this memory
alloc :: ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
alloc :: forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
alloc Int
n Ptr p -> IO ()
f
    | Int
n forall a. Ord a => a -> a -> Bool
< Int
0     = forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
alloc Int
0 Ptr p -> IO ()
f
    | Bool
otherwise = forall a b. (a, b) -> b
snd forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` forall ba p a. ByteArray ba => Int -> (Ptr p -> IO a) -> IO (a, ba)
allocRet Int
n Ptr p -> IO ()
f
{-# INLINE alloc #-}

-- | Allocate a new bytearray of specific size, and run the initializer on this memory
create :: ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
create :: forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
create Int
n Ptr p -> IO ()
f = forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
alloc Int
n Ptr p -> IO ()
f

-- | similar to 'alloc' but hide the allocation and initializer in a pure context
allocAndFreeze :: ByteArray a => Int -> (Ptr p -> IO ()) -> a
allocAndFreeze :: forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
allocAndFreeze Int
sz Ptr p -> IO ()
f = forall a. IO a -> a
unsafeDoIO (forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
alloc Int
sz Ptr p -> IO ()
f)
{-# NOINLINE allocAndFreeze #-}

-- | similar to 'create' but hide the allocation and initializer in a pure context
unsafeCreate :: ByteArray a => Int -> (Ptr p -> IO ()) -> a
unsafeCreate :: forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
unsafeCreate Int
sz Ptr p -> IO ()
f = forall a. IO a -> a
unsafeDoIO (forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
alloc Int
sz Ptr p -> IO ()
f)
{-# NOINLINE unsafeCreate #-}

inlineUnsafeCreate :: ByteArray a => Int -> (Ptr p -> IO ()) -> a
inlineUnsafeCreate :: forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
inlineUnsafeCreate !Int
sz Ptr p -> IO ()
f = forall a. IO a -> a
unsafeDoIO (forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
alloc Int
sz Ptr p -> IO ()
f)
{-# INLINE inlineUnsafeCreate #-}

-- | Create an empty byte array
empty :: ByteArray a => a
empty :: forall a. ByteArray a => a
empty = forall a. IO a -> a
unsafeDoIO (forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
alloc Int
0 forall a b. (a -> b) -> a -> b
$ \Ptr Any
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return ())

-- | Check if a byte array is empty
null :: ByteArrayAccess a => a -> Bool
null :: forall a. ByteArrayAccess a => a -> Bool
null a
b = forall ba. ByteArrayAccess ba => ba -> Int
length a
b forall a. Eq a => a -> a -> Bool
== Int
0

-- | Pack a list of bytes into a bytearray
pack :: ByteArray a => [Word8] -> a
pack :: forall a. ByteArray a => [Word8] -> a
pack [Word8]
l = forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
inlineUnsafeCreate (forall (t :: * -> *) a. Foldable t => t a -> Int
Prelude.length [Word8]
l) (forall {b}. Storable b => [b] -> Ptr b -> IO ()
fill [Word8]
l)
  where fill :: [b] -> Ptr b -> IO ()
fill []     Ptr b
_  = forall (m :: * -> *) a. Monad m => a -> m a
return ()
        fill (b
x:[b]
xs) !Ptr b
p = forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr b
p b
x forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [b] -> Ptr b -> IO ()
fill [b]
xs (Ptr b
p forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
1)
        {-# INLINE fill #-}
{-# NOINLINE pack #-}

-- | Un-pack a bytearray into a list of bytes
unpack :: ByteArrayAccess a => a -> [Word8]
unpack :: forall a. ByteArrayAccess a => a -> [Word8]
unpack a
bs = forall {a}. Storable a => Int -> [a]
loop Int
0
  where !len :: Int
len = forall ba. ByteArrayAccess ba => ba -> Int
length a
bs
        loop :: Int -> [a]
loop Int
i
            | Int
i forall a. Eq a => a -> a -> Bool
== Int
len  = []
            | Bool
otherwise =
                let !v :: a
v = forall a. IO a -> a
unsafeDoIO forall a b. (a -> b) -> a -> b
$ forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray a
bs (\Ptr Any
p -> forall a b. Storable a => Ptr b -> Int -> IO a
peekByteOff Ptr Any
p Int
i)
                 in a
v forall a. a -> [a] -> [a]
: Int -> [a]
loop (Int
iforall a. Num a => a -> a -> a
+Int
1)

-- | returns the first byte, and the remaining bytearray if the bytearray is not null
uncons :: ByteArray a => a -> Maybe (Word8, a)
uncons :: forall a. ByteArray a => a -> Maybe (Word8, a)
uncons a
a
    | forall a. ByteArrayAccess a => a -> Bool
null a
a    = forall a. Maybe a
Nothing
    | Bool
otherwise = forall a. a -> Maybe a
Just (forall a. ByteArrayAccess a => a -> Int -> Word8
index a
a Int
0, forall bs. ByteArray bs => Int -> bs -> bs
drop Int
1 a
a)

-- | Create a byte array from a single byte
singleton :: ByteArray a => Word8 -> a
singleton :: forall a. ByteArray a => Word8 -> a
singleton Word8
b = forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
unsafeCreate Int
1 (\Ptr Any
p -> forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff Ptr Any
p Int
0 Word8
b)

-- | prepend a single byte to a byte array
cons :: ByteArray a => Word8 -> a -> a
cons :: forall a. ByteArray a => Word8 -> a -> a
cons Word8
b a
ba = forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
unsafeCreate (Int
len forall a. Num a => a -> a -> a
+ Int
1) forall a b. (a -> b) -> a -> b
$ \Ptr Any
d -> forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray a
ba forall a b. (a -> b) -> a -> b
$ \Ptr Word8
s -> do
    forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff Ptr Any
d Int
0 Word8
b
    Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memCopy (Ptr Any
d forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
1) Ptr Word8
s Int
len
  where len :: Int
len = forall ba. ByteArrayAccess ba => ba -> Int
length a
ba

-- | append a single byte to a byte array
snoc :: ByteArray a =>  a -> Word8 -> a
snoc :: forall a. ByteArray a => a -> Word8 -> a
snoc a
ba Word8
b = forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
unsafeCreate (Int
len forall a. Num a => a -> a -> a
+ Int
1) forall a b. (a -> b) -> a -> b
$ \Ptr Word8
d -> forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray a
ba forall a b. (a -> b) -> a -> b
$ \Ptr Word8
s -> do
    Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memCopy Ptr Word8
d Ptr Word8
s Int
len
    forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff Ptr Word8
d Int
len Word8
b
  where len :: Int
len = forall ba. ByteArrayAccess ba => ba -> Int
length a
ba

-- | Create a xor of bytes between a and b.
--
-- the returns byte array is the size of the smallest input.
xor :: (ByteArrayAccess a, ByteArrayAccess b, ByteArray c) => a -> b -> c
xor :: forall a b c.
(ByteArrayAccess a, ByteArrayAccess b, ByteArray c) =>
a -> b -> c
xor a
a b
b =
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
unsafeCreate Int
n forall a b. (a -> b) -> a -> b
$ \Ptr Word8
pc ->
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray a
a  forall a b. (a -> b) -> a -> b
$ \Ptr Word8
pa ->
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray b
b  forall a b. (a -> b) -> a -> b
$ \Ptr Word8
pb ->
        Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memXor Ptr Word8
pc Ptr Word8
pa Ptr Word8
pb Int
n
  where
        n :: Int
n  = forall a. Ord a => a -> a -> a
min Int
la Int
lb
        la :: Int
la = forall ba. ByteArrayAccess ba => ba -> Int
length a
a
        lb :: Int
lb = forall ba. ByteArrayAccess ba => ba -> Int
length b
b

-- | return a specific byte indexed by a number from 0 in a bytearray
--
-- unsafe, no bound checking are done
index :: ByteArrayAccess a => a -> Int -> Word8
index :: forall a. ByteArrayAccess a => a -> Int -> Word8
index a
b Int
i = forall a. IO a -> a
unsafeDoIO forall a b. (a -> b) -> a -> b
$ forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray a
b forall a b. (a -> b) -> a -> b
$ \Ptr Any
p -> forall a. Storable a => Ptr a -> IO a
peek (Ptr Any
p forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
i)

-- | Split a bytearray at a specific length in two bytearray
splitAt :: ByteArray bs => Int -> bs -> (bs, bs)
splitAt :: forall bs. ByteArray bs => Int -> bs -> (bs, bs)
splitAt Int
n bs
bs
    | Int
n forall a. Ord a => a -> a -> Bool
<= Int
0    = (forall a. ByteArray a => a
empty, bs
bs)
    | Int
n forall a. Ord a => a -> a -> Bool
>= Int
len  = (bs
bs, forall a. ByteArray a => a
empty)
    | Bool
otherwise = forall a. IO a -> a
unsafeDoIO forall a b. (a -> b) -> a -> b
$ do
        forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray bs
bs forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p -> do
            bs
b1 <- forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
alloc Int
n forall a b. (a -> b) -> a -> b
$ \Ptr Word8
r -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memCopy Ptr Word8
r Ptr Word8
p Int
n
            bs
b2 <- forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
alloc (Int
len forall a. Num a => a -> a -> a
- Int
n) forall a b. (a -> b) -> a -> b
$ \Ptr Word8
r -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memCopy Ptr Word8
r (Ptr Word8
p forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
n) (Int
len forall a. Num a => a -> a -> a
- Int
n)
            forall (m :: * -> *) a. Monad m => a -> m a
return (bs
b1, bs
b2)
  where len :: Int
len = forall ba. ByteArrayAccess ba => ba -> Int
length bs
bs

-- | Take the first @n@ byte of a bytearray
take :: ByteArray bs => Int -> bs -> bs
take :: forall bs. ByteArray bs => Int -> bs -> bs
take Int
n bs
bs
    | Int
n forall a. Ord a => a -> a -> Bool
<= Int
0    = forall a. ByteArray a => a
empty
    | Bool
otherwise = forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
unsafeCreate Int
m forall a b. (a -> b) -> a -> b
$ \Ptr Word8
d -> forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray bs
bs forall a b. (a -> b) -> a -> b
$ \Ptr Word8
s -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memCopy Ptr Word8
d Ptr Word8
s Int
m
  where
    !m :: Int
m   = forall a. Ord a => a -> a -> a
min Int
len Int
n
    !len :: Int
len = forall ba. ByteArrayAccess ba => ba -> Int
length bs
bs

-- | drop the first @n@ byte of a bytearray
drop :: ByteArray bs => Int -> bs -> bs
drop :: forall bs. ByteArray bs => Int -> bs -> bs
drop Int
n bs
bs
    | Int
n forall a. Ord a => a -> a -> Bool
<= Int
0    = bs
bs
    | Int
nb forall a. Eq a => a -> a -> Bool
== Int
0   = forall a. ByteArray a => a
empty
    | Bool
otherwise = forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
unsafeCreate Int
nb forall a b. (a -> b) -> a -> b
$ \Ptr Word8
d -> forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray bs
bs forall a b. (a -> b) -> a -> b
$ \Ptr Any
s -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memCopy Ptr Word8
d (Ptr Any
s forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
ofs) Int
nb
  where
    ofs :: Int
ofs = forall a. Ord a => a -> a -> a
min Int
len Int
n
    nb :: Int
nb  = Int
len forall a. Num a => a -> a -> a
- Int
ofs
    len :: Int
len = forall ba. ByteArrayAccess ba => ba -> Int
length bs
bs

-- | Split a bytearray at the point where @pred@ becomes invalid
span :: ByteArray bs => (Word8 -> Bool) -> bs -> (bs, bs)
span :: forall bs. ByteArray bs => (Word8 -> Bool) -> bs -> (bs, bs)
span Word8 -> Bool
pred bs
bs
    | forall a. ByteArrayAccess a => a -> Bool
null bs
bs   = (bs
bs, bs
bs)
    | Bool
otherwise = let n :: Int
n = Int -> Int
loop Int
0 in (forall bs. ByteArray bs => Int -> bs -> bs
take Int
n bs
bs, forall bs. ByteArray bs => Int -> bs -> bs
drop Int
n bs
bs)
  where loop :: Int -> Int
loop !Int
i
            | Int
i forall a. Ord a => a -> a -> Bool
>= Int
len          = Int
len
            | Word8 -> Bool
pred (forall a. ByteArrayAccess a => a -> Int -> Word8
index bs
bs Int
i) = Int -> Int
loop (Int
iforall a. Num a => a -> a -> a
+Int
1)
            | Bool
otherwise         = Int
i
        len :: Int
len = forall ba. ByteArrayAccess ba => ba -> Int
length bs
bs

-- | Reverse a bytearray
reverse :: ByteArray bs => bs -> bs
reverse :: forall bs. ByteArray bs => bs -> bs
reverse bs
bs = forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
unsafeCreate Int
n forall a b. (a -> b) -> a -> b
$ \Ptr Word8
d -> forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray bs
bs forall a b. (a -> b) -> a -> b
$ \Ptr Word8
s -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memReverse Ptr Word8
d Ptr Word8
s Int
n
  where n :: Int
n = forall ba. ByteArrayAccess ba => ba -> Int
length bs
bs

-- | Concatenate bytearray into a larger bytearray
concat :: (ByteArrayAccess bin, ByteArray bout) => [bin] -> bout
concat :: forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
[bin] -> bout
concat [bin]
l = forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
unsafeCreate Int
retLen (forall {ba} {b}. ByteArrayAccess ba => [ba] -> Ptr b -> IO ()
loopCopy [bin]
l)
  where
    retLen :: Int
retLen = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map forall ba. ByteArrayAccess ba => ba -> Int
length [bin]
l

    loopCopy :: [ba] -> Ptr b -> IO ()
loopCopy []     Ptr b
_   = forall (m :: * -> *) a. Monad m => a -> m a
return ()
    loopCopy (ba
x:[ba]
xs) Ptr b
dst = do
        forall ba p. ByteArrayAccess ba => ba -> Ptr p -> IO ()
copyByteArrayToPtr ba
x Ptr b
dst
        [ba] -> Ptr b -> IO ()
loopCopy [ba]
xs (Ptr b
dst forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
chunkLen)
      where
        !chunkLen :: Int
chunkLen = forall ba. ByteArrayAccess ba => ba -> Int
length ba
x

-- | append one bytearray to the other
append :: ByteArray bs => bs -> bs -> bs
append :: forall bs. ByteArray bs => bs -> bs -> bs
append = forall a. Monoid a => a -> a -> a
mappend

-- | Duplicate a bytearray into another bytearray, and run an initializer on it
copy :: (ByteArrayAccess bs1, ByteArray bs2) => bs1 -> (Ptr p -> IO ()) -> IO bs2
copy :: forall bs1 bs2 p.
(ByteArrayAccess bs1, ByteArray bs2) =>
bs1 -> (Ptr p -> IO ()) -> IO bs2
copy bs1
bs Ptr p -> IO ()
f =
    forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
alloc (forall ba. ByteArrayAccess ba => ba -> Int
length bs1
bs) forall a b. (a -> b) -> a -> b
$ \Ptr Any
d -> do
        forall ba p. ByteArrayAccess ba => ba -> Ptr p -> IO ()
copyByteArrayToPtr bs1
bs Ptr Any
d
        Ptr p -> IO ()
f (forall a b. Ptr a -> Ptr b
castPtr Ptr Any
d)

-- | Similar to 'copy' but also provide a way to return a value from the initializer
copyRet :: (ByteArrayAccess bs1, ByteArray bs2) => bs1 -> (Ptr p -> IO a) -> IO (a, bs2)
copyRet :: forall bs1 bs2 p a.
(ByteArrayAccess bs1, ByteArray bs2) =>
bs1 -> (Ptr p -> IO a) -> IO (a, bs2)
copyRet bs1
bs Ptr p -> IO a
f =
    forall ba p a. ByteArray ba => Int -> (Ptr p -> IO a) -> IO (a, ba)
allocRet (forall ba. ByteArrayAccess ba => ba -> Int
length bs1
bs) forall a b. (a -> b) -> a -> b
$ \Ptr Any
d -> do
        forall ba p. ByteArrayAccess ba => ba -> Ptr p -> IO ()
copyByteArrayToPtr bs1
bs Ptr Any
d
        Ptr p -> IO a
f (forall a b. Ptr a -> Ptr b
castPtr Ptr Any
d)

-- | Similiar to 'copy' but expect the resulting bytearray in a pure context
copyAndFreeze :: (ByteArrayAccess bs1, ByteArray bs2) => bs1 -> (Ptr p -> IO ()) -> bs2
copyAndFreeze :: forall bs1 bs2 p.
(ByteArrayAccess bs1, ByteArray bs2) =>
bs1 -> (Ptr p -> IO ()) -> bs2
copyAndFreeze bs1
bs Ptr p -> IO ()
f =
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
inlineUnsafeCreate (forall ba. ByteArrayAccess ba => ba -> Int
length bs1
bs) forall a b. (a -> b) -> a -> b
$ \Ptr Any
d -> do
        forall ba p. ByteArrayAccess ba => ba -> Ptr p -> IO ()
copyByteArrayToPtr bs1
bs Ptr Any
d
        Ptr p -> IO ()
f (forall a b. Ptr a -> Ptr b
castPtr Ptr Any
d)
{-# NOINLINE copyAndFreeze #-}

-- | Create a bytearray of a specific size containing a repeated byte value
replicate :: ByteArray ba => Int -> Word8 -> ba
replicate :: forall ba. ByteArray ba => Int -> Word8 -> ba
replicate Int
0 Word8
_ = forall a. ByteArray a => a
empty
replicate Int
n Word8
b
    | Int
n forall a. Ord a => a -> a -> Bool
< Int
0     = forall a. ByteArray a => a
empty
    | Bool
otherwise = forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
inlineUnsafeCreate Int
n forall a b. (a -> b) -> a -> b
$ \Ptr Word8
ptr -> Ptr Word8 -> Word8 -> Int -> IO ()
memSet Ptr Word8
ptr Word8
b Int
n
{-# NOINLINE replicate #-}

-- | Create a bytearray of a specific size initialized to 0
zero :: ByteArray ba => Int -> ba
zero :: forall ba. ByteArray ba => Int -> ba
zero Int
0 = forall a. ByteArray a => a
empty
zero Int
n
    | Int
n forall a. Ord a => a -> a -> Bool
< Int
0     = forall a. ByteArray a => a
empty
    | Bool
otherwise = forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
unsafeCreate Int
n forall a b. (a -> b) -> a -> b
$ \Ptr Word8
ptr -> Ptr Word8 -> Word8 -> Int -> IO ()
memSet Ptr Word8
ptr Word8
0 Int
n
{-# NOINLINE zero #-}

-- | Check if two bytearray are equals
--
-- This is not constant time, as soon some byte differs the function will
-- returns. use 'constEq' in sensitive context where timing matters.
eq :: (ByteArrayAccess bs1, ByteArrayAccess bs2) => bs1 -> bs2 -> Bool
eq :: forall bs1 bs2.
(ByteArrayAccess bs1, ByteArrayAccess bs2) =>
bs1 -> bs2 -> Bool
eq bs1
b1 bs2
b2
    | Int
l1 forall a. Eq a => a -> a -> Bool
/= Int
l2  = Bool
False
    | Bool
otherwise = forall a. IO a -> a
unsafeDoIO forall a b. (a -> b) -> a -> b
$ forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray bs1
b1 forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p1 -> forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray bs2
b2 forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p2 -> Ptr Word8 -> Ptr Word8 -> Int -> IO Bool
memEqual Ptr Word8
p1 Ptr Word8
p2 Int
l1
  where
    l1 :: Int
l1 = forall ba. ByteArrayAccess ba => ba -> Int
length bs1
b1
    l2 :: Int
l2 = forall ba. ByteArrayAccess ba => ba -> Int
length bs2
b2

-- | A constant time equality test for 2 ByteArrayAccess values.
--
-- If values are of 2 different sizes, the function will abort early
-- without comparing any bytes.
--
-- compared to == , this function will go over all the bytes
-- present before yielding a result even when knowing the
-- overall result early in the processing.
constEq :: (ByteArrayAccess bs1, ByteArrayAccess bs2) => bs1 -> bs2 -> Bool
constEq :: forall bs1 bs2.
(ByteArrayAccess bs1, ByteArrayAccess bs2) =>
bs1 -> bs2 -> Bool
constEq bs1
b1 bs2
b2
    | Int
l1 forall a. Eq a => a -> a -> Bool
/= Int
l2  = Bool
False
    | Bool
otherwise = forall a. IO a -> a
unsafeDoIO forall a b. (a -> b) -> a -> b
$ forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray bs1
b1 forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p1 -> forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray bs2
b2 forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p2 -> Ptr Word8 -> Ptr Word8 -> Int -> IO Bool
memConstEqual Ptr Word8
p1 Ptr Word8
p2 Int
l1
  where
    !l1 :: Int
l1 = forall ba. ByteArrayAccess ba => ba -> Int
length bs1
b1
    !l2 :: Int
l2 = forall ba. ByteArrayAccess ba => ba -> Int
length bs2
b2

-- | Check if any element of a byte array satisfies a predicate
any :: (ByteArrayAccess ba) => (Word8 -> Bool) -> ba -> Bool
any :: forall ba. ByteArrayAccess ba => (Word8 -> Bool) -> ba -> Bool
any Word8 -> Bool
f ba
b
    | forall a. ByteArrayAccess a => a -> Bool
null ba
b    = Bool
False
    | Bool
otherwise = forall a. IO a -> a
unsafeDoIO forall a b. (a -> b) -> a -> b
$ forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray ba
b forall a b. (a -> b) -> a -> b
$ \Ptr Any
p -> forall {b}. Ptr b -> Int -> IO Bool
loop Ptr Any
p Int
0
  where
    len :: Int
len = forall ba. ByteArrayAccess ba => ba -> Int
length ba
b
    loop :: Ptr b -> Int -> IO Bool
loop Ptr b
p Int
i
        | Int
i forall a. Eq a => a -> a -> Bool
== Int
len  = forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
        | Bool
otherwise = do
            Word8
w <- forall a b. Storable a => Ptr b -> Int -> IO a
peekByteOff Ptr b
p Int
i
            if Word8 -> Bool
f Word8
w then forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True else Ptr b -> Int -> IO Bool
loop Ptr b
p (Int
iforall a. Num a => a -> a -> a
+Int
1)

-- | Check if all elements of a byte array satisfy a predicate
all :: (ByteArrayAccess ba) => (Word8 -> Bool) -> ba -> Bool
all :: forall ba. ByteArrayAccess ba => (Word8 -> Bool) -> ba -> Bool
all Word8 -> Bool
f ba
b = Bool -> Bool
not (forall ba. ByteArrayAccess ba => (Word8 -> Bool) -> ba -> Bool
any (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Bool
f) ba
b)

-- | Convert a bytearray to another type of bytearray
convert :: (ByteArrayAccess bin, ByteArray bout) => bin -> bout
convert :: forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
convert bin
bs = forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
inlineUnsafeCreate (forall ba. ByteArrayAccess ba => ba -> Int
length bin
bs) (forall ba p. ByteArrayAccess ba => ba -> Ptr p -> IO ()
copyByteArrayToPtr bin
bs)
#if defined(WITH_BYTESTRING_SUPPORT) && defined(WITH_BASEMENT_SUPPORT)
{-# SPECIALIZE convert :: SPE.ByteString -> SPE.UArray Word8 #-}
{-# SPECIALIZE convert :: SPE.UArray Word8 -> SPE.ByteString #-}
{-# SPECIALIZE convert :: SPE.ByteString -> SPE.Block Word8 #-}
{-# SPECIALIZE convert :: SPE.Block Word8 -> SPE.ByteString #-}
#endif