packages feed

croaring-ffi-1.0: src/Data/Bitmap/Roaring/FFI/Bitmap64/Iterator.hsc

{-# LANGUAGE CApiFFI #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE NoFieldSelectors #-}

{-| Raw bindings to the iterator part of @roaring/roaring64.h@.
The opaque @roaring64_iterator_t@ iterates over a 64-bit bitmap.

Iterators live on the C heap.
Release each one with 'free'.

An iterator points into its bitmap.
The bitmap must outlive the iterator, and any change to the bitmap invalidates the iterator.
-}
module Data.Bitmap.Roaring.FFI.Bitmap64.Iterator
  ( Iterator (..)
  , create
  , createLast
  , with
  , withLast
  , reinit
  , reinitLast
  , copy
  , free
  , finalizerFree
  , hasValue
  , value
  , advance
  , previous
  , moveEqualOrLarger
  , read
  , readBackward
  , Range (..)
  , readRanges
  , readPrevRanges
  ) where

#include <roaring/roaring64.h>

import Prelude hiding (read)

import Data.Bitmap.Roaring.FFI.Bitmap64 (Bitmap64 (..))
import Data.Bitmap.Roaring.FFI.NullHandle qualified as NullHandle
import Data.Word (Word64)
import Foreign.C.Types (CSize (..))
import Foreign.ForeignPtr (FinalizerPtr)
import Foreign.Ptr (Ptr)
import Foreign.Storable (Storable (..))

-- | @roaring64_iterator_t@
newtype Iterator = Iterator (Ptr Iterator)
  deriving (Eq, Ord, Show, Storable)

-- | @roaring64_iterator_create@: positioned at the smallest value. NULL on allocation failure.
foreign import capi unsafe "roaring/roaring64.h roaring64_iterator_create"
  create :: Bitmap64 -> IO Iterator

-- | @roaring64_iterator_create_last@: NULL on allocation failure.
foreign import capi unsafe "roaring/roaring64.h roaring64_iterator_create_last"
  createLast :: Bitmap64 -> IO Iterator

-- | @roaring64_iterator_reinit@: repositions at the smallest value of the given bitmap, without allocating.
foreign import capi unsafe "roaring/roaring64.h roaring64_iterator_reinit"
  reinit :: Bitmap64 -> Iterator -> IO ()

-- | @roaring64_iterator_reinit_last@: without allocating.
foreign import capi unsafe "roaring/roaring64.h roaring64_iterator_reinit_last"
  reinitLast :: Bitmap64 -> Iterator -> IO ()

-- | @roaring64_iterator_copy@: NULL on allocation failure.
foreign import capi unsafe "roaring/roaring64.h roaring64_iterator_copy"
  copy :: Iterator -> IO Iterator

-- | @roaring64_iterator_free@
foreign import capi unsafe "roaring/roaring64.h roaring64_iterator_free"
  free :: Iterator -> IO ()

-- | @&roaring64_iterator_free@
foreign import capi unsafe "roaring/roaring64.h &roaring64_iterator_free"
  finalizerFree :: FinalizerPtr Iterator

{- | An iterator at the smallest value ('create'), freed when the action ends.

Throws t'NullHandle.NullHandle' if 'create' returns NULL.
The bitmap must not be modified while the action runs, and the iterator must not escape the action.
-}
with :: Bitmap64 -> (Iterator -> IO a) -> IO a
with bitmap = NullHandle.bracket "Data.Bitmap.Roaring.FFI.Bitmap64.Iterator.with" free $ create bitmap
{-# INLINE with #-}

-- | Like 'with', but from the largest value. The same rules apply.
withLast :: Bitmap64 -> (Iterator -> IO a) -> IO a
withLast bitmap = NullHandle.bracket "Data.Bitmap.Roaring.FFI.Bitmap64.Iterator.withLast" free $ createLast bitmap
{-# INLINE withLast #-}

-- | @roaring64_iterator_has_value@
foreign import capi unsafe "roaring/roaring64.h roaring64_iterator_has_value"
  hasValue :: Iterator -> IO Bool

-- | @roaring64_iterator_value@: meaningful only while 'hasValue' is 'True'.
foreign import capi unsafe "roaring/roaring64.h roaring64_iterator_value"
  value :: Iterator -> IO Word64

-- | @roaring64_iterator_advance@: returns 'hasValue'. Do not call it again after 'False'.
foreign import capi unsafe "roaring/roaring64.h roaring64_iterator_advance"
  advance :: Iterator -> IO Bool

-- | @roaring64_iterator_previous@: returns 'hasValue'. Do not call it again after 'False'.
foreign import capi unsafe "roaring/roaring64.h roaring64_iterator_previous"
  previous :: Iterator -> IO Bool

-- | @roaring64_iterator_move_equalorlarger@: returns 'hasValue'.
foreign import capi unsafe "roaring/roaring64.h roaring64_iterator_move_equalorlarger"
  moveEqualOrLarger :: Iterator -> Word64 -> IO Bool

-- | @roaring64_iterator_read@: returns how many values it wrote. Fewer than asked means the iterator is exhausted.
foreign import capi safe "roaring/roaring64.h roaring64_iterator_read"
  read :: Iterator -> Ptr Word64 -> Word64 -> IO Word64

-- | @roaring64_iterator_read_backward@
foreign import capi safe "roaring/roaring64.h roaring64_iterator_read_backward"
  readBackward :: Iterator -> Ptr Word64 -> Word64 -> IO Word64

-- | @roaring64_range_closed_t@: a maximal run of consecutive values @[min, max]@.
data Range = Range
  { min :: Word64
  , max :: Word64
  }
  deriving (Eq, Ord, Show)

instance Storable Range where
  sizeOf _ = #{size roaring64_range_closed_t}
  {-# INLINE sizeOf #-}
  alignment _ = #{alignment roaring64_range_closed_t}
  {-# INLINE alignment #-}
  peek ptr =
    Range
      <$> #{peek roaring64_range_closed_t, min} ptr
      <*> #{peek roaring64_range_closed_t, max} ptr
  {-# INLINE peek #-}
  poke ptr range = do
    #{poke roaring64_range_closed_t, min} ptr range.min
    #{poke roaring64_range_closed_t, max} ptr range.max
  {-# INLINE poke #-}

-- | @roaring64_iterator_read_ranges@
foreign import capi safe "roaring/roaring64.h roaring64_iterator_read_ranges"
  readRanges :: Iterator -> Ptr Range -> CSize -> IO CSize

-- | @roaring64_iterator_read_prev_ranges@
foreign import capi safe "roaring/roaring64.h roaring64_iterator_read_prev_ranges"
  readPrevRanges :: Iterator -> Ptr Range -> CSize -> IO CSize