fixed argument order to fillByteArray to comply with documentation
[darcs-mirrors/primitive.git] / Data / Primitive / ByteArray.hs
1 {-# LANGUAGE MagicHash, UnboxedTuples, ForeignFunctionInterface,
2 UnliftedFFITypes, DeriveDataTypeable #-}
3
4 -- |
5 -- Module : Data.Primitive.ByteArray
6 -- Copyright : (c) Roman Leshchinskiy 2009-2010
7 -- License : BSD-style
8 --
9 -- Maintainer : Roman Leshchinskiy <rl@cse.unsw.edu.au>
10 -- Portability : non-portable
11 --
12 -- Primitive operations on ByteArrays
13 --
14
15 module Data.Primitive.ByteArray (
16 ByteArray(..), MutableByteArray(..), ByteArray#, MutableByteArray#,
17
18 newByteArray, newPinnedByteArray, newAlignedPinnedByteArray,
19 readByteArray, writeByteArray, indexByteArray,
20 unsafeFreezeByteArray, unsafeThawByteArray,
21 sizeofByteArray, sizeofMutableByteArray, sameMutableByteArray,
22 byteArrayContents, mutableByteArrayContents,
23 copyByteArray, copyMutableByteArray, moveByteArray, fillByteArray,
24
25 -- * Deprecated operations
26 memcpyByteArray, memcpyByteArray', memmoveByteArray, memsetByteArray
27 ) where
28
29 import Control.Monad.Primitive
30 import Data.Primitive.Types
31
32 import Foreign.C.Types
33 import Data.Word ( Word8 )
34 import GHC.Base ( Int(..) )
35 import GHC.Prim
36
37 import Data.Typeable ( Typeable )
38 import Data.Data ( Data(..) )
39 import Data.Primitive.Internal.Compat ( mkNoRepType )
40
41 -- | Byte arrays
42 data ByteArray = ByteArray ByteArray# deriving ( Typeable )
43
44 -- | Mutable byte arrays associated with a primitive state token
45 data MutableByteArray s = MutableByteArray (MutableByteArray# s)
46 deriving( Typeable )
47
48 -- | Create a new mutable byte array of the specified size.
49 newByteArray :: PrimMonad m => Int -> m (MutableByteArray (PrimState m))
50 {-# INLINE newByteArray #-}
51 newByteArray (I# n#)
52 = primitive (\s# -> case newByteArray# n# s# of
53 (# s'#, arr# #) -> (# s'#, MutableByteArray arr# #))
54
55 -- | Create a /pinned/ byte array of the specified size. The garbage collector
56 -- is guaranteed not to move it.
57 newPinnedByteArray :: PrimMonad m => Int -> m (MutableByteArray (PrimState m))
58 {-# INLINE newPinnedByteArray #-}
59 newPinnedByteArray (I# n#)
60 = primitive (\s# -> case newPinnedByteArray# n# s# of
61 (# s'#, arr# #) -> (# s'#, MutableByteArray arr# #))
62
63 -- | Create a /pinned/ byte array of the specified size and with the give
64 -- alignment. The garbage collector is guaranteed not to move it.
65 newAlignedPinnedByteArray
66 :: PrimMonad m => Int -> Int -> m (MutableByteArray (PrimState m))
67 {-# INLINE newAlignedPinnedByteArray #-}
68 newAlignedPinnedByteArray (I# n#) (I# k#)
69 = primitive (\s# -> case newAlignedPinnedByteArray# n# k# s# of
70 (# s'#, arr# #) -> (# s'#, MutableByteArray arr# #))
71
72 -- | Yield a pointer to the array's data. This operation is only safe on
73 -- /pinned/ byte arrays allocated by 'newPinnedByteArray' or
74 -- 'newAlignedPinnedByteArray'.
75 byteArrayContents :: ByteArray -> Addr
76 {-# INLINE byteArrayContents #-}
77 byteArrayContents (ByteArray arr#) = Addr (byteArrayContents# arr#)
78
79 -- | Yield a pointer to the array's data. This operation is only safe on
80 -- /pinned/ byte arrays allocated by 'newPinnedByteArray' or
81 -- 'newAlignedPinnedByteArray'.
82 mutableByteArrayContents :: MutableByteArray s -> Addr
83 {-# INLINE mutableByteArrayContents #-}
84 mutableByteArrayContents (MutableByteArray arr#)
85 = Addr (byteArrayContents# (unsafeCoerce# arr#))
86
87 -- | Check if the two arrays refer to the same memory block.
88 sameMutableByteArray :: MutableByteArray s -> MutableByteArray s -> Bool
89 {-# INLINE sameMutableByteArray #-}
90 sameMutableByteArray (MutableByteArray arr#) (MutableByteArray brr#)
91 = sameMutableByteArray# arr# brr#
92
93 -- | Convert a mutable byte array to an immutable one without copying. The
94 -- array should not be modified after the conversion.
95 unsafeFreezeByteArray
96 :: PrimMonad m => MutableByteArray (PrimState m) -> m ByteArray
97 {-# INLINE unsafeFreezeByteArray #-}
98 unsafeFreezeByteArray (MutableByteArray arr#)
99 = primitive (\s# -> case unsafeFreezeByteArray# arr# s# of
100 (# s'#, arr'# #) -> (# s'#, ByteArray arr'# #))
101
102 -- | Convert an immutable byte array to a mutable one without copying. The
103 -- original array should not be used after the conversion.
104 unsafeThawByteArray
105 :: PrimMonad m => ByteArray -> m (MutableByteArray (PrimState m))
106 {-# INLINE unsafeThawByteArray #-}
107 unsafeThawByteArray (ByteArray arr#)
108 = primitive (\s# -> (# s#, MutableByteArray (unsafeCoerce# arr#) #))
109
110 -- | Size of the byte array.
111 sizeofByteArray :: ByteArray -> Int
112 {-# INLINE sizeofByteArray #-}
113 sizeofByteArray (ByteArray arr#) = I# (sizeofByteArray# arr#)
114
115 -- | Size of the mutable byte array.
116 sizeofMutableByteArray :: MutableByteArray s -> Int
117 {-# INLINE sizeofMutableByteArray #-}
118 sizeofMutableByteArray (MutableByteArray arr#) = I# (sizeofMutableByteArray# arr#)
119
120 -- | Read a primitive value from the byte array. The offset is given in
121 -- elements of type @a@ rather than in bytes.
122 indexByteArray :: Prim a => ByteArray -> Int -> a
123 {-# INLINE indexByteArray #-}
124 indexByteArray (ByteArray arr#) (I# i#) = indexByteArray# arr# i#
125
126 -- | Read a primitive value from the byte array. The offset is given in
127 -- elements of type @a@ rather than in bytes.
128 readByteArray
129 :: (Prim a, PrimMonad m) => MutableByteArray (PrimState m) -> Int -> m a
130 {-# INLINE readByteArray #-}
131 readByteArray (MutableByteArray arr#) (I# i#)
132 = primitive (readByteArray# arr# i#)
133
134 -- | Write a primitive value to the byte array. The offset is given in
135 -- elements of type @a@ rather than in bytes.
136 writeByteArray
137 :: (Prim a, PrimMonad m) => MutableByteArray (PrimState m) -> Int -> a -> m ()
138 {-# INLINE writeByteArray #-}
139 writeByteArray (MutableByteArray arr#) (I# i#) x
140 = primitive_ (writeByteArray# arr# i# x)
141
142 #if __GLASGOW_HASKELL__ >= 702
143 i# :: Int -> Int#
144 i# (I# n#) = n#
145 #endif
146
147 -- | Copy a slice of an immutable byte array to a mutable byte array.
148 copyByteArray
149 :: PrimMonad m => MutableByteArray (PrimState m)
150 -- ^ destination array
151 -> Int -- ^ offset into destination array
152 -> ByteArray -- ^ source array
153 -> Int -- ^ offset into source array
154 -> Int -- ^ number of bytes to copy
155 -> m ()
156 {-# INLINE copyByteArray #-}
157 copyByteArray (MutableByteArray dst#) doff (ByteArray src#) soff sz
158 #if __GLASGOW_HASKELL__ >= 702
159 = primitive_ (copyByteArray# src# (i# soff) dst# (i# doff) (i# sz))
160 #else
161 = unsafePrimToPrim
162 $ memcpy_ba dst# (fromIntegral doff) src# (fromIntegral soff)
163 (fromIntegral sz)
164 #endif
165
166 -- | Copy a slice of a mutable byte array into another array. The two slices
167 -- may not overlap.
168 copyMutableByteArray
169 :: PrimMonad m => MutableByteArray (PrimState m)
170 -- ^ destination array
171 -> Int -- ^ offset into destination array
172 -> MutableByteArray (PrimState m)
173 -- ^ source array
174 -> Int -- ^ offset into source array
175 -> Int -- ^ number of bytes to copy
176 -> m ()
177 {-# INLINE copyMutableByteArray #-}
178 copyMutableByteArray (MutableByteArray dst#) doff
179 (MutableByteArray src#) soff sz
180 #if __GLASGOW_HASKELL__ >= 702
181 = primitive_ (copyMutableByteArray# src# (i# soff) dst# (i# doff) (i# sz))
182 #else
183 = unsafePrimToPrim
184 $ memcpy_mba dst# (fromIntegral doff) src# (fromIntegral soff)
185 (fromIntegral sz)
186 #endif
187
188 -- | Copy a slice of a mutable byte array into another, potentially
189 -- overlapping array.
190 moveByteArray
191 :: PrimMonad m => MutableByteArray (PrimState m)
192 -- ^ destination array
193 -> Int -- ^ offset into destination array
194 -> MutableByteArray (PrimState m)
195 -- ^ source array
196 -> Int -- ^ offset into source array
197 -> Int -- ^ number of bytes to copy
198 -> m ()
199 {-# INLINE moveByteArray #-}
200 moveByteArray (MutableByteArray dst#) doff
201 (MutableByteArray src#) soff sz
202 = unsafePrimToPrim
203 $ memmove_mba dst# (fromIntegral doff) src# (fromIntegral soff)
204 (fromIntegral sz)
205
206 -- | Fill a slice of a mutable byte array with a value.
207 fillByteArray
208 :: PrimMonad m => MutableByteArray (PrimState m)
209 -- ^ array to fill
210 -> Int -- ^ offset into array
211 -> Int -- ^ number of bytes to fill
212 -> Word8 -- ^ value to fill with
213 -> m ()
214 {-# INLINE fillByteArray #-}
215 fillByteArray (MutableByteArray dst#) doff sz c
216 = unsafePrimToPrim
217 $ memset_mba dst# (fromIntegral doff) (fromIntegral c) (fromIntegral sz)
218
219
220
221 memcpyByteArray
222 :: PrimMonad m => MutableByteArray (PrimState m) -> Int
223 -> MutableByteArray (PrimState m) -> Int
224 -> Int -> m ()
225 {-# DEPRECATED memcpyByteArray "Use copyMutableByteArray instead" #-}
226 {-# INLINE memcpyByteArray #-}
227 memcpyByteArray = copyMutableByteArray
228
229 memcpyByteArray'
230 :: PrimMonad m => MutableByteArray (PrimState m) -> Int
231 -> ByteArray -> Int
232 -> Int -> m ()
233 {-# DEPRECATED memcpyByteArray' "Use copyByteArray instead" #-}
234 {-# INLINE memcpyByteArray' #-}
235 memcpyByteArray' = copyByteArray
236
237 memmoveByteArray
238 :: PrimMonad m => MutableByteArray (PrimState m) -> Int
239 -> MutableByteArray (PrimState m) -> Int
240 -> Int -> m ()
241 {-# DEPRECATED memmoveByteArray "Use moveByteArray instead" #-}
242 {-# INLINE memmoveByteArray #-}
243 memmoveByteArray = moveByteArray
244
245 memsetByteArray
246 :: PrimMonad m => MutableByteArray (PrimState m) -> Int -> Word8
247 -> Int -> m ()
248 {-# DEPRECATED memsetByteArray "Use fillByteArray instead (WARNING: order of arguments is different)" #-}
249 {-# INLINE memsetByteArray #-}
250 memsetByteArray dst off x sz = fillByteArray dst off sz x
251
252
253 foreign import ccall unsafe "primitive-memops.h memcpy_off"
254 memcpy_mba :: MutableByteArray# s -> CInt
255 -> MutableByteArray# s -> CInt
256 -> CSize -> IO ()
257
258 foreign import ccall unsafe "primitive-memops.h memcpy_off"
259 memcpy_ba :: MutableByteArray# s -> CInt
260 -> ByteArray# -> CInt
261 -> CSize -> IO ()
262
263 foreign import ccall unsafe "primitive-memops.h memmove_off"
264 memmove_mba :: MutableByteArray# s -> CInt
265 -> MutableByteArray# s -> CInt
266 -> CSize -> IO ()
267
268 foreign import ccall unsafe "primitive-memops.h memset_off"
269 memset_mba :: MutableByteArray# s -> CInt -> CInt -> CSize -> IO ()
270
271 instance Data ByteArray where
272 toConstr _ = error "toConstr"
273 gunfold _ _ = error "gunfold"
274 dataTypeOf _ = mkNoRepType "Data.Primitive.ByteArray.ByteArray"
275
276 instance Typeable s => Data (MutableByteArray s) where
277 toConstr _ = error "toConstr"
278 gunfold _ _ = error "gunfold"
279 dataTypeOf _ = mkNoRepType "Data.Primitive.ByteArray.MutableByteArray"
280