hgrib-0.2.0.0: src/Data/Grib/Raw/Iterator.chs
{- |
Module : Data.Grib.Raw.Iterator
Copyright : (c) Mattias Jakobsson 2015
License : GPL-3
Maintainer : mjakob422@gmail.com
Stability : unstable
Portability : portable
Iterate on latitude, longitude, values.
Most of the documentation herein was copied from the official
documentation of
<https://software.ecmwf.int/wiki/display/GRIB/Module+Index grib_api>.
-}
module Data.Grib.Raw.Iterator
( -- *The GRIB Iterator
GribIterator(..)
, gribIteratorNew
, gribIteratorNext
, gribIteratorPrevious
, gribIteratorHasNext
, gribIteratorReset
, gribIteratorDelete
, withGribIterator
) where
import Control.Exception ( bracket )
import Foreign ( alloca )
{#import Data.Grib.Raw.Handle #}
import Data.Grib.Raw.Marshal
#include <grib_api.h>
-- typedef struct grib_iterator grib_iterator;
--
-- If the grib_handle used to create a grib_iterator has been freed
-- (garbage collected), deleting the iterator leads to undefined
-- behavior since a reference to the handle is used to access the
-- grib_context that in turn is used to free the memory. Because of
-- this, we can't use a foreign pointer here.
--
-- |Grib iterator, structure supporting a geographic iteration of
-- values on a grib message.
{#pointer *grib_iterator as GribIterator newtype #} deriving (Eq, Show)
-- grib_iterator* grib_iterator_new(grib_handle* h, unsigned long flags,
-- int* error);
--
-- |Create a new iterator from a handle, using current geometry and
-- values.
--
-- The returned iterator needs to be manually deleted with
-- 'gribIteratorDelete'. However, due to the reason given in that
-- function, 'withGribIterator' should be preferred over this
-- function.
{#fun unsafe grib_iterator_new as ^ {
`GribHandle'
-- ^the handle from which the iterator will be created
, `Int'
-- ^flags for future use (ignored)
, alloca- `CInt' checkStatusPtr*-
} -> `GribIterator'
-- ^an IO action that will return the new iterator
#}
-- int grib_iterator_next(grib_iterator *i, double* lat, double* lon,
-- double* value);
--
-- |Get the next value from an iterator.
--
-- This function returns a tuple @(status, latitude, longitude,
-- value)@, where @status@ is @True@ if successful and @False@ if no
-- more data is available.
{#fun unsafe grib_iterator_next as ^ {
`GribIterator'
, alloca- `Double' peekReal*
, alloca- `Double' peekReal*
, alloca- `Double' peekReal*
} -> `Bool' #}
-- int grib_iterator_previous(grib_iterator *i, double* lat, double* lon,
-- double* value);
--
-- |Like 'gribIteratorNext', but return the previous value instead.
{#fun unsafe grib_iterator_previous as ^ {
`GribIterator'
, alloca- `Double' peekReal*
, alloca- `Double' peekReal*
, alloca- `Double' peekReal*
} -> `Bool' #}
-- int grib_iterator_has_next(grib_iterator *i);
--
-- |Test procedure for values in an iterator.
{#fun unsafe grib_iterator_has_next as ^ { `GribIterator' } -> `Bool' #}
-- int grib_iterator_reset(grib_iterator *i);
--
-- |Reset the iterator.
{#fun unsafe grib_iterator_reset as ^ {
`GribIterator'
} -> `()' checkStatus*- #}
-- int grib_iterator_delete(grib_iterator *i);
--
-- |Frees an iterator from memory.
--
-- If the 'GribHandle' used to create the iterator has been garbage
-- collected by the time this function is called, the behavior is
-- undefined. Because of this, 'withGribIterator' should be preferred
-- over directly using 'gribIteratorNew' and this function.
{#fun unsafe grib_iterator_delete as ^ {
`GribIterator'
} -> `()' checkStatus*- #}
-- |Safely create, use and delete a 'GribIterator'.
--
-- This function should be preferred over directly using
-- 'gribIteratorNew' and 'gribIteratorDelete'.
withGribIterator :: GribHandle
-- ^the handle from which the iterator will be created
-> Int
-- ^flags for future use (ignored)
-> (GribIterator -> IO a)
-- ^a function that will be called with the newly
-- created iterator
-> IO a
-- ^the result of the above function
withGribIterator h flags = bracket before after
where before = gribIteratorNew h flags
after iter = withGribHandle h $ \_ -> gribIteratorDelete iter