{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-} {-# OPTIONS_HADDOCK hide #-} ----------------------------------------------------------------------------- -- | -- Module : Data.Array.Storable.Internals -- Copyright : (c) The University of Glasgow 2011 -- License : BSD-style (see the file libraries/base/LICENSE) -- -- Maintainer : libraries@haskell.org -- Stability : experimental -- Portability : non-portable (uses Data.Array.MArray) -- -- Actual implementation of "Data.Array.Storable". -- -- /Since: 0.4.0.0/ ----------------------------------------------------------------------------- module Data.Array.Storable.Internals ( StorableArray(..), withStorableArray, touchStorableArray, unsafeForeignPtrToStorableArray, ) where import Data.Array.Base import Data.Array.MArray import Foreign hiding (newArray) -- |The array type data StorableArray i e = StorableArray !i !i Int !(ForeignPtr e) instance Storable e => MArray StorableArray e IO where getBounds (StorableArray l u _ _) = return (l,u) getNumElements (StorableArray _l _u n _) = return n newArray (l,u) initialValue = do fp <- mallocForeignPtrArray size withForeignPtr fp $ \a -> sequence_ [pokeElemOff a i initialValue | i <- [0..size-1]] return (StorableArray l u size fp) where size = rangeSize (l,u) unsafeNewArray_ (l,u) = do let n = rangeSize (l,u) fp <- mallocForeignPtrArray n return (StorableArray l u n fp) newArray_ = unsafeNewArray_ unsafeRead (StorableArray _ _ _ fp) i = withForeignPtr fp $ \a -> peekElemOff a i unsafeWrite (StorableArray _ _ _ fp) i e = withForeignPtr fp $ \a -> pokeElemOff a i e -- |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 withStorableArray (StorableArray _ _ _ fp) f = withForeignPtr fp f -- |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 () touchStorableArray (StorableArray _ _ _ fp) = touchForeignPtr fp -- |Construct a 'StorableArray' from an arbitrary 'ForeignPtr'. It is -- the caller's responsibility to ensure that the 'ForeignPtr' points to -- an area of memory sufficient for the specified bounds. unsafeForeignPtrToStorableArray :: Ix i => ForeignPtr e -> (i,i) -> IO (StorableArray i e) unsafeForeignPtrToStorableArray p (l,u) = return (StorableArray l u (rangeSize (l,u)) p)