|
Packit |
c1c4f9 |
-- |
|
|
Packit |
c1c4f9 |
-- Module : Data.ByteArray.Types
|
|
Packit |
c1c4f9 |
-- License : BSD-style
|
|
Packit |
c1c4f9 |
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
|
|
Packit |
c1c4f9 |
-- Stability : stable
|
|
Packit |
c1c4f9 |
-- Portability : Good
|
|
Packit |
c1c4f9 |
--
|
|
Packit |
c1c4f9 |
{-# LANGUAGE CPP #-}
|
|
Packit |
c1c4f9 |
{-# LANGUAGE BangPatterns #-}
|
|
Packit |
c1c4f9 |
module Data.ByteArray.Types
|
|
Packit |
c1c4f9 |
( ByteArrayAccess(..)
|
|
Packit |
c1c4f9 |
, ByteArray(..)
|
|
Packit |
c1c4f9 |
) where
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
import Foreign.Ptr
|
|
Packit |
c1c4f9 |
import Data.Monoid
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
#ifdef WITH_BYTESTRING_SUPPORT
|
|
Packit |
c1c4f9 |
import qualified Data.ByteString as Bytestring (length)
|
|
Packit |
c1c4f9 |
import qualified Data.ByteString.Internal as Bytestring
|
|
Packit |
c1c4f9 |
import Foreign.ForeignPtr (withForeignPtr)
|
|
Packit |
c1c4f9 |
#endif
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
#ifdef WITH_FOUNDATION_SUPPORT
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
#if MIN_VERSION_foundation(0,0,14) && MIN_VERSION_basement(0,0,0)
|
|
Packit |
c1c4f9 |
# define NO_LEGACY_FOUNDATION_SUPPORT
|
|
Packit |
c1c4f9 |
#else
|
|
Packit |
c1c4f9 |
# define LEGACY_FOUNDATION_SUPPORT
|
|
Packit |
c1c4f9 |
#endif
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
import Data.Proxy (Proxy(..))
|
|
Packit |
c1c4f9 |
import Data.Word (Word8)
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
import qualified Basement.Types.OffsetSize as Base
|
|
Packit |
c1c4f9 |
import qualified Basement.UArray as Base
|
|
Packit |
c1c4f9 |
import qualified Basement.String as Base (String, toBytes, Encoding(UTF8))
|
|
Packit |
c1c4f9 |
import qualified Basement.PrimType as Base (primSizeInBytes)
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
#ifdef LEGACY_FOUNDATION_SUPPORT
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
import qualified Foundation as F
|
|
Packit |
c1c4f9 |
import qualified Foundation.Collection as F
|
|
Packit |
c1c4f9 |
import qualified Foundation.String as F (toBytes, Encoding(UTF8))
|
|
Packit |
c1c4f9 |
import qualified Foundation.Array.Internal as F
|
|
Packit |
c1c4f9 |
import qualified Foundation.Primitive as F (primSizeInBytes)
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
#endif
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
#endif
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
-- | Class to Access size properties and data of a ByteArray
|
|
Packit |
c1c4f9 |
class ByteArrayAccess ba where
|
|
Packit |
c1c4f9 |
-- | Return the length in bytes of a bytearray
|
|
Packit |
c1c4f9 |
length :: ba -> Int
|
|
Packit |
c1c4f9 |
-- | Allow to use using a pointer
|
|
Packit |
c1c4f9 |
withByteArray :: ba -> (Ptr p -> IO a) -> IO a
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
-- | Class to allocate new ByteArray of specific size
|
|
Packit |
c1c4f9 |
class (Eq ba, Ord ba, Monoid ba, ByteArrayAccess ba) => ByteArray ba where
|
|
Packit |
c1c4f9 |
-- | allocate `n` bytes and perform the given operation
|
|
Packit |
c1c4f9 |
allocRet :: Int
|
|
Packit |
c1c4f9 |
-- ^ number of bytes to allocate. i.e. might not match the
|
|
Packit |
c1c4f9 |
-- size of the given type `ba`.
|
|
Packit |
c1c4f9 |
-> (Ptr p -> IO a)
|
|
Packit |
c1c4f9 |
-> IO (a, ba)
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
#ifdef WITH_BYTESTRING_SUPPORT
|
|
Packit |
c1c4f9 |
instance ByteArrayAccess Bytestring.ByteString where
|
|
Packit |
c1c4f9 |
length = Bytestring.length
|
|
Packit |
c1c4f9 |
withByteArray (Bytestring.PS fptr off _) f = withForeignPtr fptr $ \ptr -> f $! (ptr `plusPtr` off)
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
instance ByteArray Bytestring.ByteString where
|
|
Packit |
c1c4f9 |
allocRet sz f = do
|
|
Packit |
c1c4f9 |
fptr <- Bytestring.mallocByteString sz
|
|
Packit |
c1c4f9 |
r <- withForeignPtr fptr (f . castPtr)
|
|
Packit |
c1c4f9 |
return (r, Bytestring.PS fptr 0 sz)
|
|
Packit |
c1c4f9 |
#endif
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
#ifdef WITH_FOUNDATION_SUPPORT
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
baseUarrayRecastW8 :: Base.PrimType ty => Base.UArray ty -> Base.UArray Word8
|
|
Packit |
c1c4f9 |
baseUarrayRecastW8 = Base.recast
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
instance Base.PrimType ty => ByteArrayAccess (Base.UArray ty) where
|
|
Packit |
c1c4f9 |
length a = let Base.CountOf i = Base.length (baseUarrayRecastW8 a) in i
|
|
Packit |
c1c4f9 |
withByteArray a f = Base.withPtr (baseUarrayRecastW8 a) (f . castPtr)
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
instance ByteArrayAccess Base.String where
|
|
Packit |
c1c4f9 |
length str = let Base.CountOf i = Base.length bytes in i
|
|
Packit |
c1c4f9 |
where
|
|
Packit |
c1c4f9 |
-- the Foundation's length return a number of elements not a number of
|
|
Packit |
c1c4f9 |
-- bytes. For @ByteArrayAccess@, because we are using an @Int@, we
|
|
Packit |
c1c4f9 |
-- didn't see that we were returning the wrong @CountOf@.
|
|
Packit |
c1c4f9 |
bytes = Base.toBytes Base.UTF8 str
|
|
Packit |
c1c4f9 |
withByteArray s f = withByteArray (Base.toBytes Base.UTF8 s) f
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
instance (Ord ty, Base.PrimType ty) => ByteArray (Base.UArray ty) where
|
|
Packit |
c1c4f9 |
allocRet sz f = do
|
|
Packit |
c1c4f9 |
mba <- Base.new $ sizeRecastBytes sz Proxy
|
|
Packit |
c1c4f9 |
a <- Base.withMutablePtr mba (f . castPtr)
|
|
Packit |
c1c4f9 |
ba <- Base.unsafeFreeze mba
|
|
Packit |
c1c4f9 |
return (a, ba)
|
|
Packit |
c1c4f9 |
where
|
|
Packit |
c1c4f9 |
sizeRecastBytes :: Base.PrimType ty => Int -> Proxy ty -> Base.CountOf ty
|
|
Packit |
c1c4f9 |
sizeRecastBytes w p = Base.CountOf $
|
|
Packit |
c1c4f9 |
let (q,r) = w `Prelude.quotRem` szTy
|
|
Packit |
c1c4f9 |
in q + (if r == 0 then 0 else 1)
|
|
Packit |
c1c4f9 |
where !(Base.CountOf szTy) = Base.primSizeInBytes p
|
|
Packit |
c1c4f9 |
{-# INLINE [1] sizeRecastBytes #-}
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
#ifdef LEGACY_FOUNDATION_SUPPORT
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
uarrayRecastW8 :: F.PrimType ty => F.UArray ty -> F.UArray Word8
|
|
Packit |
c1c4f9 |
uarrayRecastW8 = F.recast
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
instance F.PrimType ty => ByteArrayAccess (F.UArray ty) where
|
|
Packit |
c1c4f9 |
#if MIN_VERSION_foundation(0,0,10)
|
|
Packit |
c1c4f9 |
length a = let F.CountOf i = F.length (uarrayRecastW8 a) in i
|
|
Packit |
c1c4f9 |
#else
|
|
Packit |
c1c4f9 |
length = F.length . uarrayRecastW8
|
|
Packit |
c1c4f9 |
#endif
|
|
Packit |
c1c4f9 |
withByteArray a f = F.withPtr (uarrayRecastW8 a) (f . castPtr)
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
instance ByteArrayAccess F.String where
|
|
Packit |
c1c4f9 |
#if MIN_VERSION_foundation(0,0,10)
|
|
Packit |
c1c4f9 |
length str = let F.CountOf i = F.length bytes in i
|
|
Packit |
c1c4f9 |
#else
|
|
Packit |
c1c4f9 |
length str = F.length bytes
|
|
Packit |
c1c4f9 |
#endif
|
|
Packit |
c1c4f9 |
where
|
|
Packit |
c1c4f9 |
-- the Foundation's length return a number of elements not a number of
|
|
Packit |
c1c4f9 |
-- bytes. For @ByteArrayAccess@, because we are using an @Int@, we
|
|
Packit |
c1c4f9 |
-- didn't see that we were returning the wrong @CountOf@.
|
|
Packit |
c1c4f9 |
bytes = F.toBytes F.UTF8 str
|
|
Packit |
c1c4f9 |
withByteArray s f = withByteArray (F.toBytes F.UTF8 s) f
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
instance (Ord ty, F.PrimType ty) => ByteArray (F.UArray ty) where
|
|
Packit |
c1c4f9 |
allocRet sz f = do
|
|
Packit |
c1c4f9 |
mba <- F.new $ sizeRecastBytes sz Proxy
|
|
Packit |
c1c4f9 |
a <- F.withMutablePtr mba (f . castPtr)
|
|
Packit |
c1c4f9 |
ba <- F.unsafeFreeze mba
|
|
Packit |
c1c4f9 |
return (a, ba)
|
|
Packit |
c1c4f9 |
where
|
|
Packit |
c1c4f9 |
#if MIN_VERSION_foundation(0,0,10)
|
|
Packit |
c1c4f9 |
sizeRecastBytes :: F.PrimType ty => Int -> Proxy ty -> F.CountOf ty
|
|
Packit |
c1c4f9 |
sizeRecastBytes w p = F.CountOf $
|
|
Packit |
c1c4f9 |
let (q,r) = w `Prelude.quotRem` szTy
|
|
Packit |
c1c4f9 |
in q + (if r == 0 then 0 else 1)
|
|
Packit |
c1c4f9 |
where !(F.CountOf szTy) = F.primSizeInBytes p
|
|
Packit |
c1c4f9 |
{-# INLINE [1] sizeRecastBytes #-}
|
|
Packit |
c1c4f9 |
#else
|
|
Packit |
c1c4f9 |
sizeRecastBytes :: F.PrimType ty => Int -> Proxy ty -> F.Size ty
|
|
Packit |
c1c4f9 |
sizeRecastBytes w p = F.Size $
|
|
Packit |
c1c4f9 |
let (q,r) = w `Prelude.quotRem` szTy
|
|
Packit |
c1c4f9 |
in q + (if r == 0 then 0 else 1)
|
|
Packit |
c1c4f9 |
where !(F.Size szTy) = F.primSizeInBytes p
|
|
Packit |
c1c4f9 |
{-# INLINE [1] sizeRecastBytes #-}
|
|
Packit |
c1c4f9 |
#endif
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
#endif
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
|
|
Packit |
c1c4f9 |
#endif
|