    {-# LANGUAGE CPP #-}
    {-# LANGUAGE MagicHash #-}
    {-# LANGUAGE ScopedTypeVariables #-}
    {-# LANGUAGE TypeApplications #-}

    -- |
    -- Module      : Data.Primitive.Ptr
    -- Copyright   : (c) Roman Leshchinskiy 2009-2012
    -- License     : BSD-style
    --
    -- Maintainer  : Roman Leshchinskiy <rl@cse.unsw.edu.au>
    -- Portability : non-portable
    --
    -- Primitive operations on machine addresses.
    --
    -- @since 0.6.4.0

    module Data.Primitive.Ptr (
      -- * Types
      Ptr(..),

      -- * Address arithmetic
      nullPtr, advancePtr, subtractPtr,

      -- * Element access
      indexOffPtr, readOffPtr, writeOffPtr,

      -- * Block operations
      copyPtr, movePtr, setPtr

      , copyPtrToMutablePrimArray
      , copyPtrToMutableByteArray
    ) where

    import Control.Monad.Primitive
    import Data.Primitive.Types
    import Data.Primitive.PrimArray (copyPtrToMutablePrimArray)
    import Data.Primitive.ByteArray (copyPtrToMutableByteArray)

    import Data.Proxy
    import GHC.Exts
    import GHC.Ptr
    import Foreign.Marshal.Utils

    -- | Offset a pointer by the given number of elements.
    advancePtr :: forall a. Prim a => Ptr a -> Int -> Ptr a
    {-# INLINE advancePtr #-}
    advancePtr :: forall a. Prim a => Ptr a -> Int -> Ptr a
    advancePtr (Ptr Addr#
    a#) (I# Int#
    i#) = Addr# -> Ptr a
    forall a. Addr# -> Ptr a
    Ptr (Addr# -> Int# -> Addr#
    plusAddr# Addr#
    a# (Int#
    i# Int# -> Int# -> Int#
    *# Proxy a -> Int#
    forall a. Prim a => Proxy a -> Int#
    sizeOfType# (Proxy a
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy a)))

    -- | Subtract a pointer from another pointer. The result represents
    -- the number of elements of type @a@ that fit in the contiguous
    -- memory range bounded by these two pointers.
    subtractPtr :: forall a. Prim a => Ptr a -> Ptr a -> Int
    {-# INLINE subtractPtr #-}
    subtractPtr :: forall a. Prim a => Ptr a -> Ptr a -> Int
    subtractPtr (Ptr Addr#
    a#) (Ptr Addr#
    b#) = Int# -> Int
    I# (Int# -> Int# -> Int#
    quotInt# (Addr# -> Addr# -> Int#
    minusAddr# Addr#
    a# Addr#
    b#) (Proxy a -> Int#
    forall a. Prim a => Proxy a -> Int#
    sizeOfType# (Proxy a
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy a)))

    -- | Read a value from a memory position given by a pointer and an offset.
    -- The memory block the address refers to must be immutable. The offset is in
    -- elements of type @a@ rather than in bytes.
    indexOffPtr :: Prim a => Ptr a -> Int -> a
    {-# INLINE indexOffPtr #-}
    indexOffPtr :: forall a. Prim a => Ptr a -> Int -> a
    indexOffPtr (Ptr Addr#
    addr#) (I# Int#
    i#) = Addr# -> Int# -> a
    forall a. Prim a => Addr# -> Int# -> a
    indexOffAddr# Addr#
    addr# Int#
    i#

    -- | Read a value from a memory position given by an address and an offset.
    -- The offset is in elements of type @a@ rather than in bytes.
    readOffPtr :: (Prim a, PrimMonad m) => Ptr a -> Int -> m a
    {-# INLINE readOffPtr #-}
    readOffPtr :: forall a (m :: * -> *).
    (Prim a, PrimMonad m) =>
    Ptr a -> Int -> m a
    readOffPtr (Ptr Addr#
    addr#) (I# Int#
    i#) = (State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
    forall a.
    (State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
    forall (m :: * -> *) a.
    PrimMonad m =>
    (State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
    primitive (Addr#
    -> Int# -> State# (PrimState m) -> (# State# (PrimState m), a #)
    forall s. Addr# -> Int# -> State# s -> (# State# s, a #)
    forall a s.
    Prim a =>
    Addr# -> Int# -> State# s -> (# State# s, a #)
    readOffAddr# Addr#
    addr# Int#
    i#)

    -- | Write a value to a memory position given by an address and an offset.
    -- The offset is in elements of type @a@ rather than in bytes.
    writeOffPtr :: (Prim a, PrimMonad m) => Ptr a -> Int -> a -> m ()
    {-# INLINE writeOffPtr #-}
    writeOffPtr :: forall a (m :: * -> *).
    (Prim a, PrimMonad m) =>
    Ptr a -> Int -> a -> m ()
    writeOffPtr (Ptr Addr#
    addr#) (I# Int#
    i#) a
    x = (State# (PrimState m) -> State# (PrimState m)) -> m ()
    forall (m :: * -> *).
    PrimMonad m =>
    (State# (PrimState m) -> State# (PrimState m)) -> m ()
    primitive_ (Addr# -> Int# -> a -> State# (PrimState m) -> State# (PrimState m)
    forall s. Addr# -> Int# -> a -> State# s -> State# s
    forall a s. Prim a => Addr# -> Int# -> a -> State# s -> State# s
    writeOffAddr# Addr#
    addr# Int#
    i# a
    x)

    -- | Copy the given number of elements from the second 'Ptr' to the first. The
    -- areas may not overlap.
    copyPtr :: forall m a. (PrimMonad m, Prim a)
      => Ptr a -- ^ destination pointer
      -> Ptr a -- ^ source pointer
      -> Int -- ^ number of elements
      -> m ()
    {-# INLINE copyPtr #-}
    copyPtr :: forall (m :: * -> *) a.
    (PrimMonad m, Prim a) =>
    Ptr a -> Ptr a -> Int -> m ()
    copyPtr (Ptr Addr#
    dst#) (Ptr Addr#
    src#) Int
    n
      = IO () -> m ()
    forall (m1 :: * -> *) (m2 :: * -> *) a.
    (PrimBase m1, PrimMonad m2) =>
    m1 a -> m2 a
    unsafePrimToPrim (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ Ptr (ZonkAny 1) -> Ptr (ZonkAny 1) -> Int -> IO ()
    forall a. Ptr a -> Ptr a -> Int -> IO ()
    copyBytes (Addr# -> Ptr (ZonkAny 1)
    forall a. Addr# -> Ptr a
    Ptr Addr#
    dst#) (Addr# -> Ptr (ZonkAny 1)
    forall a. Addr# -> Ptr a
    Ptr Addr#
    src#) (Int
    n Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * forall a. Prim a => Int
    sizeOfType @a)

    -- | Copy the given number of elements from the second 'Ptr' to the first. The
    -- areas may overlap.
    movePtr :: forall m a. (PrimMonad m, Prim a)
      => Ptr a -- ^ destination pointer
      -> Ptr a -- ^ source pointer
      -> Int -- ^ number of elements
      -> m ()
    {-# INLINE movePtr #-}
    movePtr :: forall (m :: * -> *) a.
    (PrimMonad m, Prim a) =>
    Ptr a -> Ptr a -> Int -> m ()
    movePtr (Ptr Addr#
    dst#) (Ptr Addr#
    src#) Int
    n
      = IO () -> m ()
    forall (m1 :: * -> *) (m2 :: * -> *) a.
    (PrimBase m1, PrimMonad m2) =>
    m1 a -> m2 a
    unsafePrimToPrim (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ Ptr (ZonkAny 0) -> Ptr (ZonkAny 0) -> Int -> IO ()
    forall a. Ptr a -> Ptr a -> Int -> IO ()
    moveBytes (Addr# -> Ptr (ZonkAny 0)
    forall a. Addr# -> Ptr a
    Ptr Addr#
    dst#) (Addr# -> Ptr (ZonkAny 0)
    forall a. Addr# -> Ptr a
    Ptr Addr#
    src#) (Int
    n Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * forall a. Prim a => Int
    sizeOfType @a)

    -- | Fill a memory block with the given value. The length is in
    -- elements of type @a@ rather than in bytes.
    setPtr :: (Prim a, PrimMonad m) => Ptr a -> Int -> a -> m ()
    {-# INLINE setPtr #-}
    setPtr :: forall a (m :: * -> *).
    (Prim a, PrimMonad m) =>
    Ptr a -> Int -> a -> m ()
    setPtr (Ptr Addr#
    addr#) (I# Int#
    n#) a
    x = (State# (PrimState m) -> State# (PrimState m)) -> m ()
    forall (m :: * -> *).
    PrimMonad m =>
    (State# (PrimState m) -> State# (PrimState m)) -> m ()
    primitive_ (Addr#
    -> Int#
    -> Int#
    -> a
    -> State# (PrimState m)
    -> State# (PrimState m)
    forall s. Addr# -> Int# -> Int# -> a -> State# s -> State# s
    forall a s.
    Prim a =>
    Addr# -> Int# -> Int# -> a -> State# s -> State# s
    setOffAddr# Addr#
    addr# Int#
    0# Int#
    n# a
    x)