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