c88fb5107820ac0194f71e8431a0c3e2fa717cda
[ghc-base.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 )
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 #ifdef __NHC__
67 import NHC.FFI                  ( CInt(..) )
68 #endif
69
70 -- combined allocation and marshalling
71 -- -----------------------------------
72
73 -- |Allocate storage for a value and marshal it into this storage
74 --
75 new     :: Storable a => a -> IO (Ptr a)
76 new val  = 
77   do 
78     ptr <- malloc
79     poke ptr val
80     return ptr
81
82 -- |Allocate temporary storage for a value and marshal it into this storage
83 --
84 -- * see the life time constraints imposed by 'alloca'
85 --
86 with       :: Storable a => a -> (Ptr a -> IO b) -> IO b
87 with val f  =
88   alloca $ \ptr -> do
89     poke ptr val
90     res <- f ptr
91     return res
92
93 -- old DEPRECATED name (don't use; may disappear at any time)
94 --
95 withObject :: Storable a => a -> (Ptr a -> IO b) -> IO b
96 {-# DEPRECATED withObject "use `with' instead" #-}
97 withObject  = with
98
99
100 -- marshalling of Boolean values (non-zero corresponds to 'True')
101 -- -----------------------------
102
103 -- |Convert a Haskell 'Bool' to its numeric representation
104 --
105 fromBool       :: Num a => Bool -> a
106 fromBool False  = 0
107 fromBool True   = 1
108
109 -- |Convert a Boolean in numeric representation to a Haskell value
110 --
111 toBool :: Num a => a -> Bool
112 toBool  = (/= 0)
113
114
115 -- marshalling of Maybe values
116 -- ---------------------------
117
118 -- |Allocate storage and marshall a storable value wrapped into a 'Maybe'
119 --
120 -- * the 'nullPtr' is used to represent 'Nothing'
121 --
122 maybeNew :: (      a -> IO (Ptr a))
123          -> (Maybe a -> IO (Ptr a))
124 maybeNew  = maybe (return nullPtr)
125
126 -- |Converts a @withXXX@ combinator into one marshalling a value wrapped into a
127 -- 'Maybe'
128 --
129 maybeWith :: (      a -> (Ptr b -> IO c) -> IO c) 
130           -> (Maybe a -> (Ptr b -> IO c) -> IO c)
131 maybeWith  = maybe ($ nullPtr)
132
133 -- |Convert a peek combinator into a one returning 'Nothing' if applied to a
134 -- 'nullPtr' 
135 --
136 maybePeek                           :: (Ptr a -> IO b) -> Ptr a -> IO (Maybe b)
137 maybePeek peek ptr | ptr == nullPtr  = return Nothing
138                    | otherwise       = do a <- peek ptr; return (Just a)
139
140
141 -- marshalling lists of storable objects
142 -- -------------------------------------
143
144 -- |Replicates a @withXXX@ combinator over a list of objects, yielding a list of
145 -- marshalled objects
146 --
147 withMany :: (a -> (b -> res) -> res)  -- withXXX combinator for one object
148          -> [a]                       -- storable objects
149          -> ([b] -> res)              -- action on list of marshalled obj.s
150          -> res
151 withMany _       []     f = f []
152 withMany withFoo (x:xs) f = withFoo x $ \x' ->
153                               withMany withFoo xs (\xs' -> f (x':xs'))
154
155
156 -- Haskellish interface to memcpy and memmove
157 -- ------------------------------------------
158
159 -- |Copies the given number of bytes from the second area (source) into the
160 -- first (destination); the copied areas may /not/ overlap
161 --
162 copyBytes               :: Ptr a -> Ptr a -> Int -> IO ()
163 copyBytes dest src size  = memcpy dest src (fromIntegral size)
164
165 -- |Copies the given number of elements from the second area (source) into the
166 -- first (destination); the copied areas /may/ overlap
167 --
168 moveBytes               :: Ptr a -> Ptr a -> Int -> IO ()
169 moveBytes dest src size  = memmove dest src (fromIntegral size)
170
171
172 -- auxilliary routines
173 -- -------------------
174
175 -- |Basic C routines needed for memory copying
176 --
177 foreign import ccall unsafe "string.h" memcpy  :: Ptr a -> Ptr a -> CSize -> IO ()
178 foreign import ccall unsafe "string.h" memmove :: Ptr a -> Ptr a -> CSize -> IO ()