Fix various deprecation warnings
[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 => ByteArray -- ^ source array
150 -> Int -- ^ offset into source array
151 -> MutableByteArray (PrimState m)
152 -- ^ destination array
153 -> Int -- ^ offset into destination array
154 -> Int -- ^ number of bytes to copy
155 -> m ()
156 {-# INLINE copyByteArray #-}
157 copyByteArray (ByteArray src#) soff (MutableByteArray dst#) doff 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 -- ^ source array
171 -> Int -- ^ offset into source array
172 -> MutableByteArray (PrimState m)
173 -- ^ destination array
174 -> Int -- ^ offset into destination array
175 -> Int -- ^ number of bytes to copy
176 -> m ()
177 {-# INLINE copyMutableByteArray #-}
178 copyMutableByteArray (MutableByteArray src#) soff
179 (MutableByteArray dst#) doff 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 -- ^ source array
193 -> Int -- ^ offset into source array
194 -> MutableByteArray (PrimState m)
195 -- ^ destination array
196 -> Int -- ^ offset into destination array
197 -> Int -- ^ number of bytes to copy
198 -> m ()
199 {-# INLINE moveByteArray #-}
200 moveByteArray (MutableByteArray src#) soff
201 (MutableByteArray dst#) doff 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 c sz
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 (NOTE: arguments are flipped)" #-}
226 {-# INLINE memcpyByteArray #-}
227 memcpyByteArray dst doff src soff sz
228 = copyMutableByteArray src soff dst doff sz
229
230 memcpyByteArray'
231 :: PrimMonad m => MutableByteArray (PrimState m) -> Int
232 -> ByteArray -> Int
233 -> Int -> m ()
234 {-# DEPRECATED memcpyByteArray' "Use copyByteArray instead (NOTE: arguments are flipped)" #-}
235 {-# INLINE memcpyByteArray' #-}
236 memcpyByteArray' dst doff src soff sz
237 = copyByteArray src soff dst doff sz
238
239 memmoveByteArray
240 :: PrimMonad m => MutableByteArray (PrimState m) -> Int
241 -> MutableByteArray (PrimState m) -> Int
242 -> Int -> m ()
243 {-# DEPRECATED memmoveByteArray "Use moveByteArray instead (NOTE: arguments are flipped)" #-}
244 {-# INLINE memmoveByteArray #-}
245 memmoveByteArray dst doff src soff sz
246 = moveByteArray src soff dst doff sz
247
248 memsetByteArray
249 :: PrimMonad m => MutableByteArray (PrimState m) -> Int -> Word8
250 -> Int -> m ()
251 {-# DEPRECATED memsetByteArray "Use fillByteArray instead (NOTE: arguments are flipped)" #-}
252 {-# INLINE memsetByteArray #-}
253 memsetByteArray dst off x sz = fillByteArray dst off sz x
254
255
256 foreign import ccall unsafe "primitive-memops.h memcpy_off"
257 memcpy_mba :: MutableByteArray# s -> CInt
258 -> MutableByteArray# s -> CInt
259 -> CSize -> IO ()
260
261 foreign import ccall unsafe "primitive-memops.h memcpy_off"
262 memcpy_ba :: MutableByteArray# s -> CInt
263 -> ByteArray# -> CInt
264 -> CSize -> IO ()
265
266 foreign import ccall unsafe "primitive-memops.h memmove_off"
267 memmove_mba :: MutableByteArray# s -> CInt
268 -> MutableByteArray# s -> CInt
269 -> CSize -> IO ()
270
271 foreign import ccall unsafe "primitive-memops.h memset_off"
272 memset_mba :: MutableByteArray# s -> CInt -> CInt -> CSize -> IO ()
273
274 instance Data ByteArray where
275 toConstr _ = error "toConstr"
276 gunfold _ _ = error "gunfold"
277 dataTypeOf _ = mkNoRepType "Data.Primitive.ByteArray.ByteArray"
278
279 instance Typeable s => Data (MutableByteArray s) where
280 toConstr _ = error "toConstr"
281 gunfold _ _ = error "gunfold"
282 dataTypeOf _ = mkNoRepType "Data.Primitive.ByteArray.MutableByteArray"
283