    {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, RoleAnnotations #-}
    {-# 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)
    -- Both parameters have class-based invariants. See also #9220.
    type role StorableArray nominal nominal

    instance Storable e => MArray StorableArray e IO where
        getBounds :: forall i. Ix i => StorableArray i e -> IO (i, i)
    getBounds (StorableArray i
    l i
    u Int
    _ ForeignPtr e
    _) = (i, i) -> IO (i, i)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (i
    l,i
    u)

        getNumElements :: forall i. Ix i => StorableArray i e -> IO Int
    getNumElements (StorableArray i
    _l i
    _u Int
    n ForeignPtr e
    _) = Int -> IO Int
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Int
    n

        newArray :: forall i. Ix i => (i, i) -> e -> IO (StorableArray i e)
    newArray (i
    l,i
    u) e
    initialValue = do
            ForeignPtr e
    fp <- Int -> IO (ForeignPtr e)
    forall a. Storable a => Int -> IO (ForeignPtr a)
    mallocForeignPtrArray Int
    size
            ForeignPtr e -> (Ptr e -> IO ()) -> IO ()
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr e
    fp ((Ptr e -> IO ()) -> IO ()) -> (Ptr e -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr e
    a ->
                [IO ()] -> IO ()
    forall (t :: * -> *) (m :: * -> *) a.
    (Foldable t, Monad m) =>
    t (m a) -> m ()
    sequence_ [Ptr e -> Int -> e -> IO ()
    forall a. Storable a => Ptr a -> Int -> a -> IO ()
    pokeElemOff Ptr e
    a Int
    i e
    initialValue | Int
    i <- [Int
    0..Int
    sizeInt -> Int -> Int
    forall a. Num a => a -> a -> a
    -Int
    1]]
            StorableArray i e -> IO (StorableArray i e)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (i -> i -> Int -> ForeignPtr e -> StorableArray i e
    forall i e. i -> i -> Int -> ForeignPtr e -> StorableArray i e
    StorableArray i
    l i
    u Int
    size ForeignPtr e
    fp)
            where
            size :: Int
    size = (i, i) -> Int
    forall a. Ix a => (a, a) -> Int
    rangeSize (i
    l,i
    u)

        unsafeNewArray_ :: forall i. Ix i => (i, i) -> IO (StorableArray i e)
    unsafeNewArray_ (i
    l,i
    u) = do
            let n :: Int
    n = (i, i) -> Int
    forall a. Ix a => (a, a) -> Int
    rangeSize (i
    l,i
    u)
            ForeignPtr e
    fp <- Int -> IO (ForeignPtr e)
    forall a. Storable a => Int -> IO (ForeignPtr a)
    mallocForeignPtrArray Int
    n
            StorableArray i e -> IO (StorableArray i e)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (i -> i -> Int -> ForeignPtr e -> StorableArray i e
    forall i e. i -> i -> Int -> ForeignPtr e -> StorableArray i e
    StorableArray i
    l i
    u Int
    n ForeignPtr e
    fp)

        newArray_ :: forall i. Ix i => (i, i) -> IO (StorableArray i e)
    newArray_ = (i, i) -> IO (StorableArray i e)
    forall i. Ix i => (i, i) -> IO (StorableArray i e)
    forall (a :: * -> * -> *) e (m :: * -> *) i.
    (MArray a e m, Ix i) =>
    (i, i) -> m (a i e)
    unsafeNewArray_

        unsafeRead :: forall i. Ix i => StorableArray i e -> Int -> IO e
    unsafeRead (StorableArray i
    _ i
    _ Int
    _ ForeignPtr e
    fp) Int
    i =
            ForeignPtr e -> (Ptr e -> IO e) -> IO e
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr e
    fp ((Ptr e -> IO e) -> IO e) -> (Ptr e -> IO e) -> IO e
    forall a b. (a -> b) -> a -> b
    $ \Ptr e
    a -> Ptr e -> Int -> IO e
    forall a. Storable a => Ptr a -> Int -> IO a
    peekElemOff Ptr e
    a Int
    i

        unsafeWrite :: forall i. Ix i => StorableArray i e -> Int -> e -> IO ()
    unsafeWrite (StorableArray i
    _ i
    _ Int
    _ ForeignPtr e
    fp) Int
    i e
    e =
            ForeignPtr e -> (Ptr e -> IO ()) -> IO ()
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr e
    fp ((Ptr e -> IO ()) -> IO ()) -> (Ptr e -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr e
    a -> Ptr e -> Int -> e -> IO ()
    forall a. Storable a => Ptr a -> Int -> a -> IO ()
    pokeElemOff Ptr e
    a Int
    i e
    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 :: forall i e a. StorableArray i e -> (Ptr e -> IO a) -> IO a
    withStorableArray (StorableArray i
    _ i
    _ Int
    _ ForeignPtr e
    fp) Ptr e -> IO a
    f = ForeignPtr e -> (Ptr e -> IO a) -> IO a
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr e
    fp Ptr e -> IO a
    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 :: forall i e. StorableArray i e -> IO ()
    touchStorableArray (StorableArray i
    _ i
    _ Int
    _ ForeignPtr e
    fp) = ForeignPtr e -> IO ()
    forall a. ForeignPtr a -> IO ()
    touchForeignPtr ForeignPtr e
    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 :: forall i e.
    Ix i =>
    ForeignPtr e -> (i, i) -> IO (StorableArray i e)
    unsafeForeignPtrToStorableArray ForeignPtr e
    p (i
    l,i
    u) =
       StorableArray i e -> IO (StorableArray i e)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (i -> i -> Int -> ForeignPtr e -> StorableArray i e
    forall i e. i -> i -> Int -> ForeignPtr e -> StorableArray i e
    StorableArray i
    l i
    u ((i, i) -> Int
    forall a. Ix a => (a, a) -> Int
    rangeSize (i
    l,i
    u)) ForeignPtr e
    p)