hgrib-0.2.0.0: src/Data/Grib/Raw/Index.chs
{- |
Module : Data.Grib.Raw.Index
Copyright : (c) Mattias Jakobsson 2015
License : GPL-3
Maintainer : mjakob422@gmail.com
Stability : unstable
Portability : portable
The grib_index is the structure giving indexed access to messages in a
file.
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.Index
( -- *The GRIB Index
GribIndex(..)
, gribIndexNewFromFile
, gribIndexNew
, gribIndexAddFile
, gribIndexWrite
, gribIndexRead
, withGribIndex
-- **Get values from the index
, gribIndexGetSize
, gribIndexGetLong
, gribIndexGetDouble
, gribIndexGetString
-- **Select values from the index
, gribIndexSelectLong
, gribIndexSelectDouble
, gribIndexSelectString
-- **Other functions
, gribHandleNewFromIndex
) where
import Foreign ( Ptr, alloca )
import Foreign.C ( CDouble, CLong, CSize, CString, peekCString, withCString )
{#import Data.Grib.Raw.Context #}
{#import Data.Grib.Raw.Handle #}
import Data.Grib.Raw.Marshal
#include <grib_api.h>
{#typedef size_t CSize #}
-- typedef struct grib_index grib_index;
--
-- |Index structure to access messages in a file.
{#pointer *grib_index as GribIndex
foreign finalizer grib_index_delete as gribIndexFinalizer
newtype #}
-- grib_index* grib_index_new_from_file(grib_context* c, char* filename,
-- const char* keys, int *err);
--
-- |Create a new index from a file.
--
-- The file is indexed with the keys in argument.
{#fun unsafe grib_index_new_from_file as ^ {
`GribContext'
-- ^context
, withCString* `FilePath'
-- ^name of the file of messages to be indexed
, withJoinedCString* `[Key]'
-- ^a list of keys for the index. The type of the key can be
-- explicitly declared appending :l for long, :d for double, :s
-- for string to the key name. If the type is not declared
-- explicitly, the native type is assumed
, alloca- `CInt' checkStatusPtr*-
} -> `GribIndex'
-- ^an IO action that will return the new index
#}
-- grib_index* grib_index_new(grib_context* c, const char* keys, int *err);
--
-- |Create a new index based on a set of keys.
{#fun unsafe grib_index_new as ^ {
`GribContext'
-- ^context
, withJoinedCString* `[Key]'
-- ^a list of keys for the index. The type of the key can be
-- explicitly declared appending :l for long, :d for double, :s
-- for string to the key name. If the type is not declared
-- explicitly, the native type is assumed
, alloca- `CInt' checkStatusPtr*-
} -> `GribIndex'
-- ^an IO action that will return the new index
#}
-- int grib_index_add_file(grib_index *index, const char *filename);
--
-- |Indexes the file given in argument in the index given in argument.
{#fun unsafe grib_index_add_file as ^ {
`GribIndex'
, withCString* `FilePath'
} -> `()' checkStatus*- #}
-- int grib_index_write(grib_index *index, const char *filename);
--
-- |Write the index and its messages to file.
{#fun unsafe grib_index_write as ^ {
`GribIndex'
, withCString* `FilePath'
} -> `()' checkStatus*- #}
-- grib_index* grib_index_read(grib_context* c, const char* filename, int *err);
--
-- |Read messages and their index from a file.
{#fun unsafe grib_index_read as ^ {
`GribContext'
, withCString* `FilePath'
, alloca- `CInt' checkStatusPtr*-
} -> `GribIndex' #}
-- int grib_index_get_size(grib_index* index, const char* key, size_t* size);
--
-- |Get the number of distinct values of the key in argument contained
-- in the index.
--
-- The key must belong to the index.
{#fun unsafe grib_index_get_size as ^ {
`GribIndex'
, withCString* `Key'
, alloca- `Int' peekIntegral*
} -> `()' checkStatus*- #}
-- int grib_index_get_long(grib_index* index, const char* key, long* values,
-- size_t *size);
--
-- This function is not macro expanded since an output marshaller
-- would want to return another data type than the corresponding input
-- marshaller accepts.
--
-- |Get the distinct values of the key in argument contained in the index.
--
-- This function is used when the type of the key was explicitly
-- defined as long or when the native type of the key is long.
--
-- This function takes the address of an array that is used to
-- retrieve the values. It could potentially be re-used between
-- multiple calls.
gribIndexGetLong :: GribIndex -- ^an index created from a file. The
-- index must have been created with
-- the key in argument.
-> Key -- ^key for which the values are
-- returned
-> Ptr CLong -- ^array of values. The array must be
-- allocated before entering this
-- function and its size must be enough
-- to contain all the values.
-> Int -- ^size of the values array
-> IO [Int] -- ^an IO action that will return the
-- data in a list
gribIndexGetLong idx key ls n = withGribIndex idx $ \idx' ->
fmap (map fromIntegral) $ getArray (cCall idx') key ls n
where cCall = {#call unsafe grib_index_get_long #}
-- int grib_index_get_double(grib_index* index, const char* key,
-- double* values, size_t *size);
--
-- This function is not macro expanded since an output marshaller
-- would want to return another data type than the corresponding input
-- marshaller accepts.
--
-- |Get the distinct values of the key in argument contained in the index.
--
-- This function is used when the type of the key was explicitly
-- defined as double or when the native type of the key is double.
--
-- This function takes the address of an array that is used to
-- retrieve the values. It could potentially be re-used between
-- multiple calls.
gribIndexGetDouble :: GribIndex -- ^an index created from a
-- file. The index must have been
-- created with the key in
-- argument.
-> Key -- ^key for which the values are
-- returned
-> Ptr CDouble -- ^array of values. The array must
-- be allocated before entering
-- this function and its size must
-- be enough to contain all the
-- values.
-> Int -- ^size of the values array
-> IO [Double] -- ^an IO action that will return
-- the data in a list
gribIndexGetDouble idx key ds n = withGribIndex idx $ \idx' ->
fmap (map realToFrac) $ getArray (cCall idx') key ds n
where cCall = {#call unsafe grib_index_get_double #}
-- int grib_index_get_string(grib_index* index, const char* key, char** values,
-- size_t *size);
--
-- This function is not macro expanded since an output marshaller
-- would want to return another data type than the corresponding input
-- marshaller accepts.
--
-- |Get the distinct values of the key in argument contained in the
-- index.
--
-- This function is used when the type of the key was explicitly
-- defined as string or when the native type of the key is string.
--
-- This function takes the address of an array that is used to
-- retrieve the values. It could potentially be re-used between
-- multiple calls.
--
-- __WARNING!__ This function seem to leak memory unless the returned
-- strings in values are eventually freed with the grib context's
-- free_mem function.
gribIndexGetString :: GribIndex -- ^an index created from a
-- file. The index must have been
-- created with the key in
-- argument.
-> Key -- ^key for which the values are
-- returned
-> Ptr CString -- ^array of values. The array must
-- be allocated before entering
-- this function and its size must
-- be enough to contain all the
-- values.
-> Int -- ^size of the values array
-> IO [String] -- ^an IO action that will return
-- the data in a list
gribIndexGetString idx key ss n = withGribIndex idx $ \idx' ->
getArray (cCall idx') key ss n >>= mapM peekCString
where cCall = {#call unsafe grib_index_get_string #}
-- int grib_index_select_long(grib_index* index, const char* key, long value);
--
-- |Select the message subset with key==value.
--
-- The index must have been created with the key in argument. The
-- value is a long. The key must have been created with long type or
-- have long as native type if the type was not explicitly defined in
-- the index creation.
{#fun unsafe grib_index_select_long as ^ {
`GribIndex'
, withCString* `Key'
, `Int'
} -> `()' checkStatus*- #}
-- int grib_index_select_double(grib_index* index, const char* key,
-- double value);
--
-- |Select the message subset with key==value.
--
-- The index must have been created with the key in argument. The
-- value is a double. The key must have been created with double type
-- or have double as native type if the type was not explicitly
-- defined in the index creation.
{#fun unsafe grib_index_select_double as ^ {
`GribIndex'
, withCString* `Key'
, `Double'
} -> `()' checkStatus*- #}
-- int grib_index_select_string(grib_index* index, const char* key,
-- char* value);
--
-- |Select the message subset with key==value.
--
-- The index must have been created with the key in argument. The
-- value is a string. The key must have been created with string type
-- or have string as native type if the type was not explicitly
-- defined in the index creation.
{#fun unsafe grib_index_select_string as ^ {
`GribIndex'
, withCString* `Key'
, `String'
} -> `()' checkStatus*- #}
-- grib_handle* grib_handle_new_from_index(grib_index* index,int *err);
--
-- |Create a new handle from an index after having selected the key values.
--
-- All the keys belonging to the index must be selected before calling
-- this function. Successive calls to this function will return all
-- the handles compatible with the constraints defined selecting the
-- values of the index keys.
--
-- This operation may fail with:
--
-- * @isGribException GribEndOfIndex@ when no more handles are
-- available from the index.
{#fun unsafe grib_handle_new_from_index as ^ {
`GribIndex'
, alloca- `CInt' checkStatusPtr*-
} -> `GribHandle' #}