06528b2b4ec1cc0d89ca9bd584720cdfad913217
[packages/random.git] / Foreign / Marshal / Utils.hs
1 {-# OPTIONS -fno-implicit-prelude #-}
2 -----------------------------------------------------------------------------
3 -- |
4 -- Module : Foreign.Marshal.Utils
5 -- Copyright : (c) The FFI task force 2001
6 -- License : BSD-style (see the file libraries/base/LICENSE)
7 --
8 -- Maintainer : ffi@haskell.org
9 -- Stability : provisional
10 -- Portability : portable
11 --
12 -- Utilities for primitive marshaling
13 --
14 -----------------------------------------------------------------------------
15
16 module Foreign.Marshal.Utils (
17 -- * General marshalling utilities
18
19 -- ** Combined allocation and marshalling
20 --
21 with, -- :: Storable a => a -> (Ptr a -> IO b) -> IO b
22 new, -- :: Storable a => a -> IO (Ptr a)
23
24 -- ** Marshalling of Boolean values (non-zero corresponds to 'True')
25 --
26 fromBool, -- :: Num a => Bool -> a
27 toBool, -- :: Num a => a -> Bool
28
29 -- ** Marshalling of Maybe values
30 --
31 maybeNew, -- :: ( a -> IO (Ptr a))
32 -- -> (Maybe a -> IO (Ptr a))
33 maybeWith, -- :: ( a -> (Ptr b -> IO c) -> IO c)
34 -- -> (Maybe a -> (Ptr b -> IO c) -> IO c)
35 maybePeek, -- :: (Ptr a -> IO b )
36 -- -> (Ptr a -> IO (Maybe b))
37
38 -- ** Marshalling lists of storable objects
39 --
40 withMany, -- :: (a -> (b -> res) -> res) -> [a] -> ([b] -> res) -> res
41
42 -- ** Haskellish interface to memcpy and memmove
43 -- | (argument order: destination, source)
44 --
45 copyBytes, -- :: Ptr a -> Ptr a -> Int -> IO ()
46 moveBytes, -- :: Ptr a -> Ptr a -> Int -> IO ()
47
48 -- ** DEPRECATED FUNCTIONS (don\'t use; they may disappear at any time)
49 --
50 withObject -- :: Storable a => a -> (Ptr a -> IO b) -> IO b
51 ) where
52
53 import Data.Maybe
54 import Foreign.Ptr ( Ptr, nullPtr )
55 import Foreign.Storable ( Storable(poke) )
56 import Foreign.C.Types ( CSize, CInt(..) )
57 import Foreign.Marshal.Alloc ( malloc, alloca )
58
59 #ifdef __GLASGOW_HASKELL__
60 import GHC.IOBase
61 import GHC.Real ( fromIntegral )
62 import GHC.Num
63 import GHC.Base
64 #endif
65
66 -- combined allocation and marshalling
67 -- -----------------------------------
68
69 -- |Allocate storage for a value and marshal it into this storage
70 --
71 new :: Storable a => a -> IO (Ptr a)
72 new val =
73 do
74 ptr <- malloc
75 poke ptr val
76 return ptr
77
78 -- |Allocate temporary storage for a value and marshal it into this storage
79 --
80 -- * see the life time constraints imposed by 'alloca'
81 --
82 with :: Storable a => a -> (Ptr a -> IO b) -> IO b
83 with val f =
84 alloca $ \ptr -> do
85 poke ptr val
86 res <- f ptr
87 return res
88
89 -- old DEPRECATED name (don't use; may disappear at any time)
90 --
91 withObject :: Storable a => a -> (Ptr a -> IO b) -> IO b
92 {-# DEPRECATED withObject "use `with' instead" #-}
93 withObject = with
94
95
96 -- marshalling of Boolean values (non-zero corresponds to 'True')
97 -- -----------------------------
98
99 -- |Convert a Haskell 'Bool' to its numeric representation
100 --
101 fromBool :: Num a => Bool -> a
102 fromBool False = 0
103 fromBool True = 1
104
105 -- |Convert a Boolean in numeric representation to a Haskell value
106 --
107 toBool :: Num a => a -> Bool
108 toBool = (/= 0)
109
110
111 -- marshalling of Maybe values
112 -- ---------------------------
113
114 -- |Allocate storage and marshall a storable value wrapped into a 'Maybe'
115 --
116 -- * the 'nullPtr' is used to represent 'Nothing'
117 --
118 maybeNew :: ( a -> IO (Ptr a))
119 -> (Maybe a -> IO (Ptr a))
120 maybeNew = maybe (return nullPtr)
121
122 -- |Converts a @withXXX@ combinator into one marshalling a value wrapped into a
123 -- 'Maybe'
124 --
125 maybeWith :: ( a -> (Ptr b -> IO c) -> IO c)
126 -> (Maybe a -> (Ptr b -> IO c) -> IO c)
127 maybeWith = maybe ($ nullPtr)
128
129 -- |Convert a peek combinator into a one returning 'Nothing' if applied to a
130 -- 'nullPtr'
131 --
132 maybePeek :: (Ptr a -> IO b) -> Ptr a -> IO (Maybe b)
133 maybePeek peek ptr | ptr == nullPtr = return Nothing
134 | otherwise = do a <- peek ptr; return (Just a)
135
136
137 -- marshalling lists of storable objects
138 -- -------------------------------------
139
140 -- |Replicates a @withXXX@ combinator over a list of objects, yielding a list of
141 -- marshalled objects
142 --
143 withMany :: (a -> (b -> res) -> res) -- withXXX combinator for one object
144 -> [a] -- storable objects
145 -> ([b] -> res) -- action on list of marshalled obj.s
146 -> res
147 withMany _ [] f = f []
148 withMany withFoo (x:xs) f = withFoo x $ \x' ->
149 withMany withFoo xs (\xs' -> f (x':xs'))
150
151
152 -- Haskellish interface to memcpy and memmove
153 -- ------------------------------------------
154
155 -- |Copies the given number of bytes from the second area (source) into the
156 -- first (destination); the copied areas may /not/ overlap
157 --
158 copyBytes :: Ptr a -> Ptr a -> Int -> IO ()
159 copyBytes dest src size = memcpy dest src (fromIntegral size)
160
161 -- |Copies the given number of elements from the second area (source) into the
162 -- first (destination); the copied areas /may/ overlap
163 --
164 moveBytes :: Ptr a -> Ptr a -> Int -> IO ()
165 moveBytes dest src size = memmove dest src (fromIntegral size)
166
167
168 -- auxilliary routines
169 -- -------------------
170
171 -- |Basic C routines needed for memory copying
172 --
173 foreign import ccall unsafe "string.h" memcpy :: Ptr a -> Ptr a -> CSize -> IO ()
174 foreign import ccall unsafe "string.h" memmove :: Ptr a -> Ptr a -> CSize -> IO ()