87881b6b3d883b780f81b5d7818213abe57973f4
[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/core/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   withObject,    -- :: Storable a => a -> (Ptr a -> IO b) -> IO b
22   {- FIXME: should be `with' -}
23   new,           -- :: Storable a => a -> IO (Ptr a)
24
25   -- ** Marshalling of Boolean values (non-zero corresponds to 'True')
26   --
27   fromBool,      -- :: Num a => Bool -> a
28   toBool,        -- :: Num a => a -> Bool
29
30   -- ** Marshalling of Maybe values
31   --
32   maybeNew,      -- :: (      a -> IO (Ptr a))
33                  -- -> (Maybe a -> IO (Ptr a))
34   maybeWith,     -- :: (      a -> (Ptr b -> IO c) -> IO c)
35                  -- -> (Maybe a -> (Ptr b -> IO c) -> IO c)
36   maybePeek,     -- :: (Ptr a -> IO        b )
37                  -- -> (Ptr a -> IO (Maybe b))
38
39   -- ** Marshalling lists of storable objects
40   --
41   withMany,      -- :: (a -> (b -> res) -> res) -> [a] -> ([b] -> res) -> res
42
43   -- ** Haskellish interface to memcpy and memmove
44
45   -- | (argument order: destination, source)
46   copyBytes,     -- :: Ptr a -> Ptr a -> Int -> IO ()
47   moveBytes      -- :: Ptr a -> Ptr a -> Int -> IO ()
48 ) where
49
50 import Data.Maybe
51
52 #ifdef __GLASGOW_HASKELL__
53 import Foreign.Ptr              ( Ptr, nullPtr )
54 import GHC.Storable             ( Storable(poke) )
55 import Foreign.C.TypesISO       ( CSize )
56 import Foreign.Marshal.Alloc    ( malloc, alloca )
57 import GHC.IOBase
58 import GHC.Real                 ( fromIntegral )
59 import GHC.Num
60 import GHC.Base
61 #endif
62
63 -- combined allocation and marshalling
64 -- -----------------------------------
65
66 -- |Allocate storage for a value and marshal it into this storage
67 --
68 new     :: Storable a => a -> IO (Ptr a)
69 new val  = 
70   do 
71     ptr <- malloc
72     poke ptr val
73     return ptr
74
75 -- |Allocate temporary storage for a value and marshal it into this storage
76 --
77 -- * see the life time constraints imposed by 'alloca'
78 --
79 {- FIXME: should be called `with' -}
80 withObject       :: Storable a => a -> (Ptr a -> IO b) -> IO b
81 withObject val f  =
82   alloca $ \ptr -> do
83     poke ptr val
84     res <- f ptr
85     return res
86
87
88 -- marshalling of Boolean values (non-zero corresponds to 'True')
89 -- -----------------------------
90
91 -- |Convert a Haskell 'Bool' to its numeric representation
92 --
93 fromBool       :: Num a => Bool -> a
94 fromBool False  = 0
95 fromBool True   = 1
96
97 -- |Convert a Boolean in numeric representation to a Haskell value
98 --
99 toBool :: Num a => a -> Bool
100 toBool  = (/= 0)
101
102
103 -- marshalling of Maybe values
104 -- ---------------------------
105
106 -- |Allocate storage and marshall a storable value wrapped into a 'Maybe'
107 --
108 -- * the 'nullPtr' is used to represent 'Nothing'
109 --
110 maybeNew :: (      a -> IO (Ptr a))
111          -> (Maybe a -> IO (Ptr a))
112 maybeNew  = maybe (return nullPtr)
113
114 -- |Converts a @withXXX@ combinator into one marshalling a value wrapped into a
115 -- 'Maybe'
116 --
117 maybeWith :: (      a -> (Ptr b -> IO c) -> IO c) 
118           -> (Maybe a -> (Ptr b -> IO c) -> IO c)
119 maybeWith  = maybe ($ nullPtr)
120
121 -- |Convert a peek combinator into a one returning 'Nothing' if applied to a
122 -- 'nullPtr' 
123 --
124 maybePeek                           :: (Ptr a -> IO b) -> Ptr a -> IO (Maybe b)
125 maybePeek peek ptr | ptr == nullPtr  = return Nothing
126                    | otherwise       = do a <- peek ptr; return (Just a)
127
128
129 -- marshalling lists of storable objects
130 -- -------------------------------------
131
132 -- |Replicates a @withXXX@ combinator over a list of objects, yielding a list of
133 -- marshalled objects
134 --
135 withMany :: (a -> (b -> res) -> res)  -- withXXX combinator for one object
136          -> [a]                       -- storable objects
137          -> ([b] -> res)              -- action on list of marshalled obj.s
138          -> res
139 withMany _       []     f = f []
140 withMany withFoo (x:xs) f = withFoo x $ \x' ->
141                               withMany withFoo xs (\xs' -> f (x':xs'))
142
143
144 -- Haskellish interface to memcpy and memmove
145 -- ------------------------------------------
146
147 -- |Copies the given number of bytes from the second area (source) into the
148 -- first (destination); the copied areas may /not/ overlap
149 --
150 copyBytes               :: Ptr a -> Ptr a -> Int -> IO ()
151 copyBytes dest src size  = memcpy dest src (fromIntegral size)
152
153 -- |Copies the given number of elements from the second area (source) into the
154 -- first (destination); the copied areas /may/ overlap
155 --
156 moveBytes               :: Ptr a -> Ptr a -> Int -> IO ()
157 moveBytes dest src size  = memmove dest src (fromIntegral size)
158
159
160 -- auxilliary routines
161 -- -------------------
162
163 -- |Basic C routines needed for memory copying
164 --
165 foreign import ccall unsafe memcpy  :: Ptr a -> Ptr a -> CSize -> IO ()
166 foreign import ccall unsafe memmove :: Ptr a -> Ptr a -> CSize -> IO ()