1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
|
-- |
-- Module : Foundation.Class.Storable
-- License : BSD-style
-- Maintainer : Haskell Foundation
-- Stability : experimental
-- Portability : portable
--
-- <https://github.com/haskell-foundation/issues/111>
--
--
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE CPP #-}
module Foundation.Class.Storable
( Storable(..)
, StorableFixed(..)
-- * Ptr
, Ptr, plusPtr, castPtr
-- * offset based helper
, peekOff, pokeOff
-- * Collection
, peekArray
, peekArrayEndedBy
, pokeArray
, pokeArrayEndedBy
) where
#include "MachDeps.h"
import Foreign.Ptr (castPtr)
import qualified Foreign.Ptr
import qualified Foreign.Storable (peek, poke)
import Basement.Compat.Base
import Basement.Compat.C.Types (CChar, CUChar)
import Basement.Types.OffsetSize
import Basement.Types.Word128 (Word128(..))
import Basement.Types.Word256 (Word256(..))
import Foundation.Collection
import Foundation.Collection.Buildable (builderLift)
import Basement.PrimType
import Basement.Endianness
import Foundation.Numerical
-- | Storable type of self determined size.
--
class Storable a where
peek :: Ptr a -> IO a
poke :: Ptr a -> a -> IO ()
-- | Extending the Storable type class to the types that can be sequenced
-- in a structure.
--
class Storable a => StorableFixed a where
size :: proxy a -> CountOf Word8
alignment :: proxy a -> CountOf Word8
plusPtr :: StorableFixed a => Ptr a -> CountOf a -> Ptr a
plusPtr ptr (CountOf num) = ptr `Foreign.Ptr.plusPtr` (num * (size ptr `align` alignment ptr))
where
align (CountOf sz) (CountOf a) = sz + (sz `mod` a)
-- | like `peek` but at a given offset.
peekOff :: StorableFixed a => Ptr a -> Offset a -> IO a
peekOff ptr off = peek (ptr `plusPtr` offsetAsSize off)
-- | like `poke` but at a given offset.
pokeOff :: StorableFixed a => Ptr a -> Offset a -> a -> IO ()
pokeOff ptr off = poke (ptr `plusPtr` offsetAsSize off)
peekArray :: (Buildable col, StorableFixed (Element col))
=> CountOf (Element col) -> Ptr (Element col) -> IO col
peekArray (CountOf s) p = build_ 64 . builder 0 $ p
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 p = build_ 64 . builder 0 $ p
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 (sizeAsOffset $ 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 Word128 where
peek (Ptr addr) = primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0)
instance Storable (BE Word128) where
peek (Ptr addr) = BE <$> primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0) . unBE
instance Storable (LE Word128) where
peek (Ptr addr) = LE <$> primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0) . unLE
instance Storable Word256 where
peek (Ptr addr) = primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0)
instance Storable (BE Word256) where
peek (Ptr addr) = BE <$> primAddrRead addr (Offset 0)
poke (Ptr addr) = primAddrWrite addr (Offset 0) . unBE
instance Storable (LE Word256) 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 = const SIZEOF_CHAR
alignment = const ALIGNMENT_CHAR
instance StorableFixed CUChar where
size = const SIZEOF_WORD8
alignment = const ALIGNMENT_WORD8
instance StorableFixed Char where
size = const SIZEOF_HSCHAR
alignment = const ALIGNMENT_HSCHAR
instance StorableFixed Double where
size = const SIZEOF_HSDOUBLE
alignment = const ALIGNMENT_HSDOUBLE
instance StorableFixed Float where
size = const SIZEOF_HSFLOAT
alignment = const ALIGNMENT_HSFLOAT
instance StorableFixed Int8 where
size = const SIZEOF_INT8
alignment = const ALIGNMENT_INT8
instance StorableFixed Int16 where
size = const SIZEOF_INT16
alignment = const ALIGNMENT_INT16
instance StorableFixed Int32 where
size = const SIZEOF_INT32
alignment = const ALIGNMENT_INT32
instance StorableFixed Int64 where
size = const SIZEOF_INT64
alignment = const ALIGNMENT_INT64
instance StorableFixed Word8 where
size = const SIZEOF_WORD8
alignment = const ALIGNMENT_WORD8
instance StorableFixed Word16 where
size = const SIZEOF_WORD16
alignment = const ALIGNMENT_WORD16
instance StorableFixed (BE Word16) where
size = const SIZEOF_WORD16
alignment = const ALIGNMENT_WORD16
instance StorableFixed (LE Word16) where
size = const SIZEOF_WORD16
alignment = const ALIGNMENT_WORD16
instance StorableFixed Word32 where
size = const SIZEOF_WORD32
alignment = const ALIGNMENT_WORD32
instance StorableFixed (BE Word32) where
size = const SIZEOF_WORD32
alignment = const ALIGNMENT_WORD32
instance StorableFixed (LE Word32) where
size = const SIZEOF_WORD32
alignment = const ALIGNMENT_WORD32
instance StorableFixed Word64 where
size = const SIZEOF_WORD64
alignment = const ALIGNMENT_WORD64
instance StorableFixed (BE Word64) where
size = const SIZEOF_WORD64
alignment = const ALIGNMENT_WORD64
instance StorableFixed (LE Word64) where
size = const SIZEOF_WORD64
alignment = const ALIGNMENT_WORD64
instance StorableFixed Word128 where
size = const 16
alignment = const 16
instance StorableFixed (BE Word128) where
size = const 16
alignment = const 16
instance StorableFixed (LE Word128) where
size = const 16
alignment = const 16
instance StorableFixed Word256 where
size = const 32
alignment = const 32
instance StorableFixed (BE Word256) where
size = const 32
alignment = const 32
instance StorableFixed (LE Word256) where
size = const 32
alignment = const 32
instance StorableFixed (Ptr a) where
size = const SIZEOF_HSPTR
alignment = const ALIGNMENT_HSPTR
|