module Foundation.Class.Storable
( Storable(..)
, StorableFixed(..)
, Ptr, plusPtr, castPtr
, peekOff, pokeOff
, peekArray
, peekArrayEndedBy
, pokeArray
, pokeArrayEndedBy
) where
import GHC.Types (Double, Float)
import Foreign.Ptr (castPtr)
import qualified Foreign.Ptr
import qualified Foreign.Storable (peek, poke, sizeOf, alignment)
import Foreign.C.Types (CChar, CUChar)
import Foundation.Internal.Base
import Foundation.Primitive.Types.OffsetSize
import Foundation.Internal.Proxy
import Foundation.Collection
import Foundation.Collection.Buildable (builderLift)
import Foundation.Primitive.Types
import Foundation.Primitive.Endianness
import Foundation.Numerical
toProxy :: proxy ty -> Proxy ty
toProxy _ = Proxy
class Storable a where
peek :: Ptr a -> IO a
poke :: Ptr a -> a -> IO ()
class Storable a => StorableFixed a where
size :: proxy a -> Size Word8
alignment :: proxy a -> Size Word8
plusPtr :: StorableFixed a => Ptr a -> Size a -> Ptr a
plusPtr ptr (Size num) = ptr `Foreign.Ptr.plusPtr` (num * (size ptr `align` alignment ptr))
where
align (Size sz) (Size a) = sz + (sz `mod` a)
peekOff :: StorableFixed a => Ptr a -> Offset a -> IO a
peekOff ptr off = peek (ptr `plusPtr` offsetAsSize off)
pokeOff :: StorableFixed a => Ptr a -> Offset a -> a -> IO ()
pokeOff ptr off = poke (ptr `plusPtr` offsetAsSize off)
peekArray :: (Buildable col, StorableFixed (Element col))
=> Size (Element col) -> Ptr (Element col) -> IO col
peekArray (Size s) = build 64 . builder 0
where
builder off ptr
| off == s = return ()
| otherwise = do
v <- builderLift (peekOff ptr (Offset off))
append v
builder (off + 1) ptr
peekArrayEndedBy :: (Buildable col, StorableFixed (Element col), Eq (Element col), Show (Element col))
=> Element col -> Ptr (Element col) -> IO col
peekArrayEndedBy term = build 64 . builder 0
where
builder off ptr = do
v <- builderLift $ peekOff ptr off
if term == v
then return ()
else append v >> builder (off + (Offset 1)) ptr
pokeArray :: (Sequential col, StorableFixed (Element col))
=> Ptr (Element col) -> col -> IO ()
pokeArray ptr arr =
forM_ (z [0..] arr) $ \(i, e) ->
pokeOff ptr (Offset i) e
where
z :: (Sequential col, Collection col) => [Int] -> col -> [(Int, Element col)]
z = zip
pokeArrayEndedBy :: (Sequential col, StorableFixed (Element col))
=> Element col -> Ptr (Element col) -> col -> IO ()
pokeArrayEndedBy term ptr col = do
pokeArray ptr col
pokeOff ptr (Offset $ length col) term
instance Storable CChar where
peek (Ptr addr) = primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0)
instance Storable CUChar where
peek (Ptr addr) = primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0)
instance Storable Char where
peek (Ptr addr) = primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0)
instance Storable Double where
peek (Ptr addr) = primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0)
instance Storable Float where
peek (Ptr addr) = primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0)
instance Storable Int8 where
peek (Ptr addr) = primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0)
instance Storable Int16 where
peek (Ptr addr) = primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0)
instance Storable Int32 where
peek (Ptr addr) = primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0)
instance Storable Int64 where
peek (Ptr addr) = primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0)
instance Storable Word8 where
peek (Ptr addr) = primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0)
instance Storable Word16 where
peek (Ptr addr) = primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0)
instance Storable (BE Word16) where
peek (Ptr addr) = BE <$> primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0) . unBE
instance Storable (LE Word16) where
peek (Ptr addr) = LE <$> primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0) . unLE
instance Storable Word32 where
peek (Ptr addr) = primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0)
instance Storable (BE Word32) where
peek (Ptr addr) = BE <$> primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0) . unBE
instance Storable (LE Word32) where
peek (Ptr addr) = LE <$> primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0) . unLE
instance Storable Word64 where
peek (Ptr addr) = primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0)
instance Storable (BE Word64) where
peek (Ptr addr) = BE <$> primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0) . unBE
instance Storable (LE Word64) where
peek (Ptr addr) = LE <$> primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0) . unLE
instance Storable (Ptr a) where
peek = Foreign.Storable.peek
poke = Foreign.Storable.poke
instance StorableFixed CChar where
size = primSizeInBytes . toProxy
alignment = primSizeInBytes . toProxy
instance StorableFixed CUChar where
size = primSizeInBytes . toProxy
alignment = primSizeInBytes . toProxy
instance StorableFixed Char where
size = primSizeInBytes . toProxy
alignment = primSizeInBytes . toProxy
instance StorableFixed Double where
size = primSizeInBytes . toProxy
alignment = primSizeInBytes . toProxy
instance StorableFixed Float where
size = primSizeInBytes . toProxy
alignment = primSizeInBytes . toProxy
instance StorableFixed Int8 where
size = primSizeInBytes . toProxy
alignment = primSizeInBytes . toProxy
instance StorableFixed Int16 where
size = primSizeInBytes . toProxy
alignment = primSizeInBytes . toProxy
instance StorableFixed Int32 where
size = primSizeInBytes . toProxy
alignment = primSizeInBytes . toProxy
instance StorableFixed Int64 where
size = primSizeInBytes . toProxy
alignment = primSizeInBytes . toProxy
instance StorableFixed Word8 where
size = primSizeInBytes . toProxy
alignment = primSizeInBytes . toProxy
instance StorableFixed Word16 where
size = primSizeInBytes . toProxy
alignment = primSizeInBytes . toProxy
instance StorableFixed (BE Word16) where
size = primSizeInBytes . toProxy
alignment = primSizeInBytes . toProxy
instance StorableFixed (LE Word16) where
size = primSizeInBytes . toProxy
alignment = primSizeInBytes . toProxy
instance StorableFixed Word32 where
size = primSizeInBytes . toProxy
alignment = primSizeInBytes . toProxy
instance StorableFixed (BE Word32) where
size = primSizeInBytes . toProxy
alignment = primSizeInBytes . toProxy
instance StorableFixed (LE Word32) where
size = primSizeInBytes . toProxy
alignment = primSizeInBytes . toProxy
instance StorableFixed Word64 where
size = primSizeInBytes . toProxy
alignment = primSizeInBytes . toProxy
instance StorableFixed (BE Word64) where
size = primSizeInBytes . toProxy
alignment = primSizeInBytes . toProxy
instance StorableFixed (LE Word64) where
size = primSizeInBytes . toProxy
alignment = primSizeInBytes . toProxy
instance StorableFixed (Ptr a) where
size = Size . Foreign.Storable.sizeOf . toUndefined
alignment = Size . Foreign.Storable.alignment . toUndefined
toUndefined :: proxy a -> a
toUndefined _ = undefined