Add copyAddr and moveAddr and deprecate memcpyAddr
[darcs-mirrors/primitive.git] / Data / Primitive / Addr.hs
1 {-# LANGUAGE MagicHash, UnboxedTuples #-}
2
3 -- |
4 -- Module : Data.Primitive.Addr
5 -- Copyright : (c) Roman Leshchinskiy 2009-2010
6 -- License : BSD-style
7 --
8 -- Maintainer : Roman Leshchinskiy <rl@cse.unsw.edu.au>
9 -- Portability : non-portable
10 --
11 -- Primitive operations on machine addresses
12 --
13
14 module Data.Primitive.Addr (
15 Addr(..),
16
17 nullAddr, plusAddr, minusAddr, remAddr,
18 indexOffAddr, readOffAddr, writeOffAddr,
19 copyAddr, moveAddr, memcpyAddr
20 ) where
21
22 import Control.Monad.Primitive
23 import Data.Primitive.Types
24
25 import GHC.Base ( Int(..) )
26 import GHC.Prim
27
28 import GHC.Ptr
29 import Foreign.Marshal.Utils
30
31
32 -- | The null address
33 nullAddr :: Addr
34 nullAddr = Addr nullAddr#
35
36 infixl 6 `plusAddr`, `minusAddr`
37 infixl 7 `remAddr`
38
39 -- | Offset an address by the given number of bytes
40 plusAddr :: Addr -> Int -> Addr
41 plusAddr (Addr a#) (I# i#) = Addr (plusAddr# a# i#)
42
43 -- | Distance in bytes between two addresses. The result is only valid if the
44 -- difference fits in an 'Int'.
45 minusAddr :: Addr -> Addr -> Int
46 minusAddr (Addr a#) (Addr b#) = I# (minusAddr# a# b#)
47
48 -- | The remainder of the address and the integer.
49 remAddr :: Addr -> Int -> Int
50 remAddr (Addr a#) (I# i#) = I# (remAddr# a# i#)
51
52 -- | Read a value from a memory position given by an address and an offset.
53 -- The memory block the address refers to must be immutable. The offset is in
54 -- elements of type @a@ rather than in bytes.
55 indexOffAddr :: Prim a => Addr -> Int -> a
56 {-# INLINE indexOffAddr #-}
57 indexOffAddr (Addr addr#) (I# i#) = indexOffAddr# addr# i#
58
59 -- | Read a value from a memory position given by an address and an offset.
60 -- The offset is in elements of type @a@ rather than in bytes.
61 readOffAddr :: (Prim a, PrimMonad m) => Addr -> Int -> m a
62 {-# INLINE readOffAddr #-}
63 readOffAddr (Addr addr#) (I# i#) = primitive (readOffAddr# addr# i#)
64
65 -- | Write a value to a memory position given by an address and an offset.
66 -- The offset is in elements of type @a@ rather than in bytes.
67 writeOffAddr :: (Prim a, PrimMonad m) => Addr -> Int -> a -> m ()
68 {-# INLINE writeOffAddr #-}
69 writeOffAddr (Addr addr#) (I# i#) x = primitive_ (writeOffAddr# addr# i# x)
70
71 -- | Copy the given number of bytes from the second 'Addr' to the first. The
72 -- areas may not overlap.
73 copyAddr :: PrimMonad m => Addr -- ^ destination address
74 -> Addr -- ^ source address
75 -> Int -- ^ number of bytes
76 -> m ()
77 {-# INLINE copyAddr #-}
78 copyAddr (Addr dst#) (Addr src#) n
79 = unsafePrimToPrim $ copyBytes (Ptr dst#) (Ptr src#) n
80
81 -- | Copy the given number of bytes from the second 'Addr' to the first. The
82 -- areas may overlap.
83 moveAddr :: PrimMonad m => Addr -- ^ destination address
84 -> Addr -- ^ source address
85 -> Int -- ^ number of bytes
86 -> m ()
87 {-# INLINE moveAddr #-}
88 moveAddr (Addr dst#) (Addr src#) n
89 = unsafePrimToPrim $ moveBytes (Ptr dst#) (Ptr src#) n
90
91 memcpyAddr :: PrimMonad m => Addr -> Addr -> Int -> m ()
92 {-# INLINE memcpyAddr #-}
93 {-# DEPRECATED memcpyAddr "Use copyAddr instead" #-}
94 memcpyAddr = copyAddr
95