File: Storable.hs

package info (click to toggle)
haskell-foundation 0.0.30-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 932 kB
  • sloc: haskell: 9,124; ansic: 570; makefile: 7
file content (266 lines) | stat: -rw-r--r-- 9,671 bytes parent folder | download | duplicates (2)
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