summaryrefslogtreecommitdiff
path: root/libraries/base/Data/Array/Storable.hs
blob: 8c6fdf35b20e4cc318d22946dd00af27e1fc766c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
-----------------------------------------------------------------------------
-- |
-- Module      :  Data.Array.Storable
-- Copyright   :  (c) The University of Glasgow 2001
-- License     :  BSD-style (see the file libraries/core/LICENSE)
-- 
-- Maintainer  :  libraries@haskell.org
-- Stability   :  experimental
-- Portability :  non-portable
--
-- A storable array is an IO-mutable array which stores its
-- contents in a contiguous memory block living in the C
-- heap. Elements are stored according to the class Storable.
-- You can obtain the pointer to the array contents to manipulate
-- elements from languages like C.
--
-- It's similar to IOUArray but slower. Its advantage is that
-- it's compatible with C.
--
-----------------------------------------------------------------------------

module Data.Array.Storable (
    
    -- Array type:
    StorableArray, -- data StorableArray index element
                   --     -- index type must be in class Ix
                   --     -- element type must be in class Storable
    
    -- Module MArray provides the interface of storable arrays.
    -- They are instances of class MArray (with IO monad).
    module Data.Array.MArray,
    
    -- The pointer to the array contents is obtained by withStorableArray.
    -- The idea is similar to ForeignPtr (used internally here). The
    -- pointer should be used only during execution of the IO action
    -- retured by the function passed as argument to withStorableArray:
    withStorableArray, -- :: StorableArray i e -> (Ptr e -> IO a) -> IO a
    
    -- If you want to use it afterwards, ensure that you
    -- touchStorableArray after the last use of the pointer,
    -- so the array is not freed too early:
    touchStorableArray -- :: StorableArray i e -> IO ()
    )
    where

import Prelude

import Data.Array.Base
import Data.Array.MArray
import Foreign hiding (newArray)

data StorableArray i e = StorableArray !i !i !(ForeignPtr e)

instance HasBounds StorableArray where
    bounds (StorableArray l u _) = (l,u)

instance Storable e => MArray StorableArray e IO where

    newArray (l,u) init = do
        a <- mallocArray size
        sequence_ [pokeElemOff a i init | i <- [0..size-1]]
        fp <- newForeignPtr a (free a)
        return (StorableArray l u fp)
        where
        size = rangeSize (l,u)

    newArray_ (l,u) = do
        a  <- mallocArray (rangeSize (l,u))
        fp <- newForeignPtr a (free a)
        return (StorableArray l u fp)

    unsafeRead (StorableArray _ _ fp) i =
        withForeignPtr fp $ \a -> peekElemOff a i

    unsafeWrite (StorableArray _ _ fp) i e =
        withForeignPtr fp $ \a -> pokeElemOff a i e

withStorableArray :: StorableArray i e -> (Ptr e -> IO a) -> IO a
withStorableArray (StorableArray _ _ fp) f = withForeignPtr fp f

touchStorableArray :: StorableArray i e -> IO ()
touchStorableArray (StorableArray _ _ fp) = touchForeignPtr fp