585fb388f9c910c3bdd3cbcfdfe487670cea4dbd
[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,
21 sizeofByteArray, sizeofMutableByteArray, sameMutableByteArray,
22 byteArrayContents,
23
24 memcpyByteArray, memcpyByteArray', memmoveByteArray, memsetByteArray
25 ) where
26
27 import Control.Monad.Primitive
28 import Data.Primitive.Types
29
30 import Foreign.C.Types
31 import Data.Word ( Word8 )
32 import GHC.Base ( Int(..) )
33 import GHC.Prim
34
35 import Data.Typeable ( Typeable )
36 import Data.Data ( Data(..), mkNorepType )
37
38 -- | Byte arrays
39 data ByteArray = ByteArray ByteArray# deriving ( Typeable )
40
41 -- | Mutable byte arrays associated with a primitive state token
42 data MutableByteArray s = MutableByteArray (MutableByteArray# s)
43 deriving( Typeable )
44
45 -- | Create a new mutable byte array of the specified size.
46 newByteArray :: PrimMonad m => Int -> m (MutableByteArray (PrimState m))
47 {-# INLINE newByteArray #-}
48 newByteArray (I# n#)
49 = primitive (\s# -> case newByteArray# n# s# of
50 (# s'#, arr# #) -> (# s'#, MutableByteArray arr# #))
51
52 -- | Create a /pinned/ byte array of the specified size. The garbage collector
53 -- is guaranteed not to move it.
54 newPinnedByteArray :: PrimMonad m => Int -> m (MutableByteArray (PrimState m))
55 {-# INLINE newPinnedByteArray #-}
56 newPinnedByteArray (I# n#)
57 = primitive (\s# -> case newPinnedByteArray# n# s# of
58 (# s'#, arr# #) -> (# s'#, MutableByteArray arr# #))
59
60 -- | Create a /pinned/ byte array of the specified size and with the give
61 -- alignment. The garbage collector is guaranteed not to move it.
62 newAlignedPinnedByteArray
63 :: PrimMonad m => Int -> Int -> m (MutableByteArray (PrimState m))
64 {-# INLINE newAlignedPinnedByteArray #-}
65 newAlignedPinnedByteArray (I# n#) (I# k#)
66 = primitive (\s# -> case newAlignedPinnedByteArray# n# k# s# of
67 (# s'#, arr# #) -> (# s'#, MutableByteArray arr# #))
68
69 -- | Yield a pointer to the array's data. This operation is only safe on
70 -- /pinned/ byte arrays allocated by 'newPinnedByteArray' or
71 -- 'newAlignedPinnedByteArray'.
72 byteArrayContents :: ByteArray -> Addr
73 {-# INLINE byteArrayContents #-}
74 byteArrayContents (ByteArray arr#) = Addr (byteArrayContents# arr#)
75
76 -- | Check if the two arrays refer to the same memory block.
77 sameMutableByteArray :: MutableByteArray s -> MutableByteArray s -> Bool
78 {-# INLINE sameMutableByteArray #-}
79 sameMutableByteArray (MutableByteArray arr#) (MutableByteArray brr#)
80 = sameMutableByteArray# arr# brr#
81
82 -- | Convert a mutable byte array to an immutable one without copying. The
83 -- array should not be modified after the conversion.
84 unsafeFreezeByteArray
85 :: PrimMonad m => MutableByteArray (PrimState m) -> m ByteArray
86 {-# INLINE unsafeFreezeByteArray #-}
87 unsafeFreezeByteArray (MutableByteArray arr#)
88 = primitive (\s# -> case unsafeFreezeByteArray# arr# s# of
89 (# s'#, arr'# #) -> (# s'#, ByteArray arr'# #))
90
91 -- | Size of the byte array.
92 sizeofByteArray :: ByteArray -> Int
93 {-# INLINE sizeofByteArray #-}
94 sizeofByteArray (ByteArray arr#) = I# (sizeofByteArray# arr#)
95
96 -- | Size of the mutable byte array.
97 sizeofMutableByteArray :: MutableByteArray s -> Int
98 {-# INLINE sizeofMutableByteArray #-}
99 sizeofMutableByteArray (MutableByteArray arr#) = I# (sizeofMutableByteArray# arr#)
100
101 -- | Read a primitive value from the byte array. The offset is given in
102 -- elements of type @a@ rather than in bytes.
103 indexByteArray :: Prim a => ByteArray -> Int -> a
104 {-# INLINE indexByteArray #-}
105 indexByteArray (ByteArray arr#) (I# i#) = indexByteArray# arr# i#
106
107 -- | Read a primitive value from the byte array. The offset is given in
108 -- elements of type @a@ rather than in bytes.
109 readByteArray
110 :: (Prim a, PrimMonad m) => MutableByteArray (PrimState m) -> Int -> m a
111 {-# INLINE readByteArray #-}
112 readByteArray (MutableByteArray arr#) (I# i#)
113 = primitive (readByteArray# arr# i#)
114
115 -- | Write a primitive value to the byte array. The offset is given in
116 -- elements of type @a@ rather than in bytes.
117 writeByteArray
118 :: (Prim a, PrimMonad m) => MutableByteArray (PrimState m) -> Int -> a -> m ()
119 {-# INLINE writeByteArray #-}
120 writeByteArray (MutableByteArray arr#) (I# i#) x
121 = primitive_ (writeByteArray# arr# i# x)
122
123 memcpyByteArray
124 :: PrimMonad m => MutableByteArray (PrimState m) -> Int
125 -> MutableByteArray (PrimState m) -> Int
126 -> Int -> m ()
127 {-# INLINE memcpyByteArray #-}
128 memcpyByteArray (MutableByteArray dst#) doff
129 (MutableByteArray src#) soff sz
130 = unsafePrimToPrim
131 $ memcpy_mba dst# (fromIntegral doff) src# (fromIntegral soff)
132 (fromIntegral sz)
133
134 memcpyByteArray'
135 :: PrimMonad m => MutableByteArray (PrimState m) -> Int
136 -> ByteArray -> Int
137 -> Int -> m ()
138 {-# INLINE memcpyByteArray' #-}
139 memcpyByteArray' (MutableByteArray dst#) doff
140 (ByteArray src#) soff sz
141 = unsafePrimToPrim
142 $ memcpy_ba dst# (fromIntegral doff) src# (fromIntegral soff)
143 (fromIntegral sz)
144
145 memmoveByteArray
146 :: PrimMonad m => MutableByteArray (PrimState m) -> Int
147 -> MutableByteArray (PrimState m) -> Int
148 -> Int -> m ()
149 {-# INLINE memmoveByteArray #-}
150 memmoveByteArray (MutableByteArray dst#) doff
151 (MutableByteArray src#) soff sz
152 = unsafePrimToPrim
153 $ memmove_mba dst# (fromIntegral doff) src# (fromIntegral soff)
154 (fromIntegral sz)
155
156 memsetByteArray
157 :: PrimMonad m => MutableByteArray (PrimState m) -> Int -> Word8
158 -> Int -> m ()
159 {-# INLINE memsetByteArray #-}
160 memsetByteArray (MutableByteArray dst#) doff c sz
161 = unsafePrimToPrim
162 $ memset_mba dst# (fromIntegral doff) (fromIntegral c) (fromIntegral sz)
163
164
165
166 foreign import ccall unsafe "memops.h memcpy_off"
167 memcpy_mba :: MutableByteArray# s -> CInt
168 -> MutableByteArray# s -> CInt
169 -> CSize -> IO ()
170
171 foreign import ccall unsafe "memops.h memcpy_off"
172 memcpy_ba :: MutableByteArray# s -> CInt
173 -> ByteArray# -> CInt
174 -> CSize -> IO ()
175
176 foreign import ccall unsafe "memops.h memmove_off"
177 memmove_mba :: MutableByteArray# s -> CInt
178 -> MutableByteArray# s -> CInt
179 -> CSize -> IO ()
180
181 foreign import ccall unsafe "memops.h memset_off"
182 memset_mba :: MutableByteArray# s -> CInt -> CInt -> CSize -> IO ()
183
184 instance Data ByteArray where
185 toConstr _ = error "toConstr"
186 gunfold _ _ = error "gunfold"
187 dataTypeOf _ = mkNorepType "Data.Primitive.ByteArray.ByteArray"
188
189 instance Typeable s => Data (MutableByteArray s) where
190 toConstr _ = error "toConstr"
191 gunfold _ _ = error "gunfold"
192 dataTypeOf _ = mkNorepType "Data.Primitive.ByteArray.MutableByteArray"
193