[project @ 2005-10-13 11:09:50 by ross]
[haskell-directory.git] / Data / Array / Storable.hs
1 -----------------------------------------------------------------------------
2 -- |
3 -- Module      :  Data.Array.Storable
4 -- Copyright   :  (c) The University of Glasgow 2001
5 -- License     :  BSD-style (see the file libraries/base/LICENSE)
6 -- 
7 -- Maintainer  :  libraries@haskell.org
8 -- Stability   :  experimental
9 -- Portability :  non-portable (uses Data.Array.MArray)
10 --
11 -- A storable array is an IO-mutable array which stores its
12 -- contents in a contiguous memory block living in the C
13 -- heap. Elements are stored according to the class 'Storable'.
14 -- You can obtain the pointer to the array contents to manipulate
15 -- elements from languages like C.
16 --
17 -- It is similar to 'Data.Array.IO.IOUArray' but slower.
18 -- Its advantage is that it's compatible with C.
19 --
20 -----------------------------------------------------------------------------
21
22 module Data.Array.Storable (
23     
24     -- * Arrays of 'Storable' things.
25     StorableArray, -- data StorableArray index element
26                    --     -- index type must be in class Ix
27                    --     -- element type must be in class Storable
28     
29     -- * Overloaded mutable array interface
30     -- | Module "Data.Array.MArray" provides the interface of storable arrays.
31     -- They are instances of class 'MArray' (with the 'IO' monad).
32     module Data.Array.MArray,
33     
34     -- * Accessing the pointer to the array contents
35     withStorableArray, -- :: StorableArray i e -> (Ptr e -> IO a) -> IO a
36     
37     touchStorableArray, -- :: StorableArray i e -> IO ()
38
39     unsafeForeignPtrToStorableArray
40     )
41     where
42
43 import Prelude
44
45 import Data.Array.Base
46 import Data.Array.MArray
47 import Foreign hiding (newArray)
48
49 -- |The array type
50 data StorableArray i e = StorableArray !i !i !(ForeignPtr e)
51
52 instance HasBounds StorableArray where
53     bounds (StorableArray l u _) = (l,u)
54
55 instance Storable e => MArray StorableArray e IO where
56
57     newArray (l,u) init = do
58         fp <- mallocForeignPtrArray size
59         withForeignPtr fp $ \a ->
60             sequence_ [pokeElemOff a i init | i <- [0..size-1]]
61         return (StorableArray l u fp)
62         where
63         size = rangeSize (l,u)
64
65     newArray_ (l,u) = do
66         fp <- mallocForeignPtrArray (rangeSize (l,u))
67         return (StorableArray l u fp)
68
69     unsafeRead (StorableArray _ _ fp) i =
70         withForeignPtr fp $ \a -> peekElemOff a i
71
72     unsafeWrite (StorableArray _ _ fp) i e =
73         withForeignPtr fp $ \a -> pokeElemOff a i e
74
75 -- |The pointer to the array contents is obtained by 'withStorableArray'.
76 -- The idea is similar to 'ForeignPtr' (used internally here).
77 -- The pointer should be used only during execution of the 'IO' action
78 -- retured by the function passed as argument to 'withStorableArray'.
79 withStorableArray :: StorableArray i e -> (Ptr e -> IO a) -> IO a
80 withStorableArray (StorableArray _ _ fp) f = withForeignPtr fp f
81
82 -- |If you want to use it afterwards, ensure that you
83 -- 'touchStorableArray' after the last use of the pointer,
84 -- so the array is not freed too early.
85 touchStorableArray :: StorableArray i e -> IO ()
86 touchStorableArray (StorableArray _ _ fp) = touchForeignPtr fp
87
88 -- |Construct a 'StorableArray' from an arbitrary 'ForeignPtr'.  It is
89 -- the caller's responsibility to ensure that the 'ForeignPtr' points to
90 -- an area of memory sufficient for the specified bounds.
91 unsafeForeignPtrToStorableArray 
92    :: ForeignPtr e -> (i,i) -> IO (StorableArray i e)
93 unsafeForeignPtrToStorableArray p (l,u) =
94    return (StorableArray l u p)