content: module Foreign.Marshal.Array (
    mallocArray, mallocArray0,
    allocaArray, allocaArray0,
    reallocArray, reallocArray0,
    callocArray, callocArray0,
    peekArray, peekArray0,
    pokeArray, pokeArray0,
    newArray, newArray0,
    withArray, withArray0,
    withArrayLen, withArrayLen0,
    copyArray, moveArray,
    lengthArray0,
    advancePtr,
  ) where
  
  import qualified Prelude(); import MiniPrelude
  import Foreign.Ptr
  import Foreign.Storable
  import Foreign.Marshal.Alloc
  import Foreign.Marshal.Utils (copyBytes, moveBytes)
  
  mallocArray :: forall a . Storable a => Int -> IO (Ptr a)
  mallocArray size = mallocBytes (size * sizeOf (error "mallocArray" :: a))
  
  mallocArray0 :: forall a . Storable a => Int -> IO (Ptr a)
  mallocArray0 size  = mallocArray (size + 1)
  
  allocaArray :: forall a b. (Storable a) => Int -> (Ptr a -> IO b) -> IO b
  allocaArray n = allocaBytes (n * sizeOf (error "allocaArray" :: a))
  
  allocaArray0 :: forall a b. (Storable a) => Int -> (Ptr a -> IO b) -> IO b
  allocaArray0 n = allocaArray (n + 1)
  
  reallocArray :: forall a . Storable a => Ptr a -> Int -> IO (Ptr a)
  reallocArray p n = reallocBytes p (n * sizeOf (error "reallocArray" :: a))
  
  reallocArray0 :: forall a . Storable a => Ptr a -> Int -> IO (Ptr a)
  reallocArray0 p n = reallocArray p (n + 1)
  
  callocArray :: forall a . Storable a => Int -> IO (Ptr a)
  callocArray size = callocBytes (size * sizeOf (error "callocArray" :: a))
  
  callocArray0 :: forall a . Storable a => Int -> IO (Ptr a)
  callocArray0 size  = callocArray (size + 1)
  
  peekArray :: forall a . Storable a => Int -> Ptr a -> IO [a]
  peekArray size ptr | size <= 0 = return []
                     | otherwise = f (size-1) []
    where
      f n acc | n < 0 = return acc
      f n acc = do e <- peekElemOff ptr n; f (n-1) (e:acc)
  
  peekArray0 :: forall a . (Storable a, Eq a) => a -> Ptr a -> IO [a]
  peekArray0 marker ptr  = do
    size <- lengthArray0 marker ptr
    peekArray size ptr
  
  pokeArray :: forall a . Storable a => Ptr a -> [a] -> IO ()
  pokeArray ptr vals0 = go vals0 0
    where go [] _         = return ()
          go (val:vals) n = do { pokeElemOff ptr n val; go vals (n + 1) }
  
  pokeArray0 :: forall a . Storable a => a -> Ptr a -> [a] -> IO ()
  pokeArray0 marker ptr vals0 = go vals0 0
    where go []         n = pokeElemOff ptr n marker
          go (val:vals) n = do { pokeElemOff ptr n val; go vals (n + 1) }
  
  newArray :: forall a . Storable a => [a] -> IO (Ptr a)
  newArray vals  = do
    ptr <- mallocArray (length vals)
    pokeArray ptr vals
    return ptr
  
  newArray0 :: forall a . Storable a => a -> [a] -> IO (Ptr a)
  newArray0 marker vals  = do
    ptr <- mallocArray0 (length vals)
    pokeArray0 marker ptr vals
    return ptr
  
  lengthArray0 :: forall a . (Storable a, Eq a) => a -> Ptr a -> IO Int
  lengthArray0 marker ptr = loop 0
    where
      loop i = do
          val <- peekElemOff ptr i
          if val == marker then return i else loop (i+1)
  
  withArray :: forall a b . Storable a => [a] -> (Ptr a -> IO b) -> IO b
  withArray vals f = withArrayLen vals (const f)
  
  withArray0 :: forall a b . Storable a => a -> [a] -> (Ptr a -> IO b) -> IO b
  withArray0 marker vals f = withArrayLen0 marker vals (const f)
  
  withArrayLen :: forall a b . Storable a => [a] -> (Int -> Ptr a -> IO b) -> IO b
  withArrayLen vals f =
    allocaArray len $ \ptr -> do
      pokeArray ptr vals
      f len ptr
    where
      len = length vals
  
  withArrayLen0 :: forall a b . Storable a => a -> [a] -> (Int -> Ptr a -> IO b) -> IO b
  withArrayLen0 marker vals f =
    allocaArray0 len $ \ptr -> do
      pokeArray0 marker ptr vals
      f len ptr
    where
      len = length vals
  
  
  advancePtr :: forall a. (Storable a) => Ptr a -> Int -> Ptr a
  advancePtr p n = plusPtr p (n * sizeOf (error "advancePtr" :: a))
  
  copyArray :: forall a. Storable a => Ptr a -> Ptr a -> Int -> IO ()
  copyArray dest src n = copyBytes dest src (n * sizeOf (error "copyArray" :: a))
  
  moveArray :: forall a. Storable a => Ptr a -> Ptr a -> Int -> IO ()
  moveArray dest src n = moveBytes dest src (n * sizeOf (error "moveArray" :: a))
  