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