[project @ 2001-06-28 14:15:04 by simonmar]
[ghc-base.git] / Foreign / Marshal / Alloc.hs
1 {-# OPTIONS -fno-implicit-prelude #-}
2 -----------------------------------------------------------------------------
3 -- 
4 -- Module      :  Foreign.Marshal.Alloc
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: Alloc.hs,v 1.1 2001/06/28 14:15:03 simonmar Exp $
13 --
14 -- Marshalling support: basic routines for memory allocation
15 --
16 -----------------------------------------------------------------------------
17
18 module Foreign.Marshal.Alloc (
19   malloc,       -- :: Storable a =>        IO (Ptr a)
20   mallocBytes,  -- ::               Int -> IO (Ptr a)
21
22   alloca,       -- :: Storable a =>        (Ptr a -> IO b) -> IO b
23   allocaBytes,  -- ::               Int -> (Ptr a -> IO b) -> IO b
24
25   reallocBytes, -- :: Ptr a -> Int -> IO (Ptr a)
26
27   free          -- :: Ptr a -> IO ()
28 ) where
29
30 import Data.Maybe
31 import Foreign.Ptr              ( Ptr, nullPtr )
32 import Foreign.C.TypesISO       ( CSize )
33
34 #ifdef __GLASGOW_HASKELL__
35 import GHC.Exception    ( bracket )
36 import GHC.Storable     ( Storable(sizeOf) )
37 import GHC.IOBase
38 import GHC.Real
39 import GHC.Err
40 import GHC.Base
41 #endif
42
43
44 -- exported functions
45 -- ------------------
46
47 -- allocate space for storable type
48 --
49 malloc :: Storable a => IO (Ptr a)
50 malloc  = doMalloc undefined
51   where
52     doMalloc       :: Storable a => a -> IO (Ptr a)
53     doMalloc dummy  = mallocBytes (sizeOf dummy)
54
55 -- allocate given number of bytes of storage
56 --
57 mallocBytes      :: Int -> IO (Ptr a)
58 mallocBytes size  = failWhenNULL "malloc" (_malloc (fromIntegral size))
59
60 -- temporarily allocate space for a storable type
61 --
62 -- * the pointer passed as an argument to the function must *not* escape from
63 --   this function; in other words, in `alloca f' the allocated storage must
64 --   not be used after `f' returns
65 --
66 alloca :: Storable a => (Ptr a -> IO b) -> IO b
67 alloca  = doAlloca undefined
68   where
69     doAlloca       :: Storable a => a -> (Ptr a -> IO b) -> IO b
70     doAlloca dummy  = allocaBytes (sizeOf dummy)
71
72 -- temporarily allocate the given number of bytes of storage
73 --
74 -- * the pointer passed as an argument to the function must *not* escape from
75 --   this function; in other words, in `allocaBytes n f' the allocated storage
76 --   must not be used after `f' returns
77 --
78 allocaBytes      :: Int -> (Ptr a -> IO b) -> IO b
79 allocaBytes size  = bracket (mallocBytes size) free
80
81 -- adjust a malloc'ed storage area to the given size
82 --
83 reallocBytes          :: Ptr a -> Int -> IO (Ptr a)
84 reallocBytes ptr size  = 
85   failWhenNULL "realloc" (_realloc ptr (fromIntegral size))
86
87 -- free malloc'ed storage
88 --
89 free :: Ptr a -> IO ()
90 free  = _free
91
92
93 -- auxilliary routines
94 -- -------------------
95
96 -- asserts that the pointer returned from the action in the second argument is
97 -- non-null
98 --
99 failWhenNULL :: String -> IO (Ptr a) -> IO (Ptr a)
100 failWhenNULL name f = do
101    addr <- f
102    if addr == nullPtr
103 #ifdef __GLASGOW_HASKELL__
104       then ioException (IOError Nothing ResourceExhausted name 
105                                         "out of memory" Nothing)
106 #else
107       then ioError (userError (name++": out of memory"))
108 #endif
109       else return addr
110
111 -- basic C routines needed for memory allocation
112 --
113 foreign import "malloc"  unsafe _malloc  ::          CSize -> IO (Ptr a)
114 foreign import "realloc" unsafe _realloc :: Ptr a -> CSize -> IO (Ptr a)
115 foreign import "free"    unsafe _free    :: Ptr a -> IO ()