packages feed

hdf5-lite (empty) → 0.1.0.0

raw patch · 11 files changed

+873/−0 lines, 11 filesdep +QuickCheckdep +basedep +containerssetup-changed

Dependencies added: QuickCheck, base, containers, exceptions, ghc-prim, hdf5-lite, hspec, inline-c, primitive, template-haskell, text, vector

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Marco Zocca (c) 2018++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Marco Zocca nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,32 @@+# hdf5-lite++[![Build Status](https://travis-ci.org/ocramz/hdf5-lite.png)](https://travis-ci.org/ocramz/hdf5-lite)++Bindings to the HDF5 "lite" interface: https://support.hdfgroup.org/HDF5/doc/HL/RM_H5LT.html++## Warning++Experimental, partly tested and incomplete, not meant for production use.++++## Dependencies++- The HDF5 library headers must be correctly installed at `/usr/local/hdf5/include`. In particular, the file `/usr/local/hdf5/include/hdf5_hl.h` must be present++- The `stack` build tool++- The `c2hs` tool (in case you don't have it, `stack install c2hs`)++## Installation++- `make`+  - generates the Haskell types by running `c2hs`. This is necessary since HDF5 may be configured to use specific numerical precisions etc.+  - runs `stack build`+++++## Credits++Inspiration : [`hnetcdf`](https://hackage.haskell.org/package/hnetcdf) 
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ hdf5-lite.cabal view
@@ -0,0 +1,51 @@+name:                hdf5-lite+version:             0.1.0.0+synopsis:            Bindings to the HDF5 "lite" interface+description:         This library wraps the simplified ("lite") interface to the HDF5 data format.+homepage:            https://github.com/ocramz/hdf5-lite+license:             BSD3+license-file:        LICENSE+author:              Marco Zocca+maintainer:          zocca.marco gmail+copyright:           2018 Marco Zocca+category:            Data+build-type:          Simple+extra-source-files:  README.md+cabal-version:       >=1.10+tested-with:         GHC == 8.2.2++library+  default-language:    Haskell2010+  ghc-options:         -Wall+  hs-source-dirs:      src+  include-dirs:        /usr/local/hdf5/include+  exposed-modules:     Data.HDF5.Lite+  other-modules:       Data.HDF5.Lite.Internal+                       Data.HDF5.Internal.Exceptions+                       Data.HDF5.Internal.Types+                       Data.HDF5.Store+  build-depends:       base >= 4.7 && < 5+                     , containers+                     , exceptions+                     , ghc-prim+                     , inline-c+                     , primitive+                     , text+                     , template-haskell+                     , vector+                     -- , bytestring++test-suite spec+  default-language:    Haskell2010+  ghc-options:         -Wall+  type:                exitcode-stdio-1.0+  hs-source-dirs:      test+  main-is:             Spec.hs+  build-depends:       base+                     , hdf5-lite+                     , hspec+                     , QuickCheck++source-repository head+  type:     git+  location: https://github.com/ocramz/hdf5-lite
+ src/Data/HDF5/Internal/Exceptions.hs view
@@ -0,0 +1,27 @@+{-# language DeriveGeneric #-}+module Data.HDF5.Internal.Exceptions where++import GHC.Generics++import Control.Monad+import Control.Monad.Catch++import Data.HDF5.Internal.Types (Herr, Htri)++data HDF5Exception = HDF5Exception Herr deriving (Eq, Show, Generic)+instance Exception HDF5Exception+++throwH :: MonadThrow m => m Herr -> m ()+throwH io = do+  ec <- io+  when (ec < 0) $ throwM (HDF5Exception ec)+++throwTri :: MonadThrow m => m Htri -> m Bool+throwTri io = do+  ec <- io+  if+    ec > 0+    then return True+    else if ec == 0 then return False else throwM (HDF5Exception ec)
+ src/Data/HDF5/Internal/Types.chs view
@@ -0,0 +1,53 @@+{-# language CPP, DeriveAnyClass #-}+module Data.HDF5.Internal.Types where++import Foreign.Storable++#include <H5Tpublic.h>+#include <hdf5_hl.h>++-- | HDF5 integer error codes+type Herr = {#type herr_t#} ++-- | HDF Type of atoms to return to users+type Hid = {#type hid_t#} ++-- | HDF5 file object sizes (64 bits by default i.e. an unsigned CLLong)+type Hsize = {#type hsize_t #} ++-- | HDF5 "ternary" Boolean type. Functions that return `htri_t' return zero (false), positive (true), or negative (failure).+type Htri = {#type htri_t #}++++-- | HDF5 native datatypes : https://support.hdfgroup.org/HDF5/doc/RM/PredefDTypes.html+  +-- type HNativeDouble = {#type H5T_NATIVE_DOUBLE #}++++-- /* These are the various classes of datatypes */+-- /* If this goes over 16 types (0-15), the file format will need to change) */+-- typedef enum H5T_class_t {+--     H5T_NO_CLASS         = -1,  /*error                                      */+--     H5T_INTEGER          = 0,   /*integer types                              */+--     H5T_FLOAT            = 1,   /*floating-point types                       */+--     H5T_TIME             = 2,   /*date and time types                        */+--     H5T_STRING           = 3,   /*character string types                     */+--     H5T_BITFIELD         = 4,   /*bit field types                            */+--     H5T_OPAQUE           = 5,   /*opaque types                               */+--     H5T_COMPOUND         = 6,   /*compound types                             */+--     H5T_REFERENCE        = 7,   /*reference types                            */+--     H5T_ENUM		 = 8,	/*enumeration types                          */+--     H5T_VLEN		 = 9,	/*Variable-Length types                      */+--     H5T_ARRAY	         = 10,	/*Array types                                */++--     H5T_NCLASSES                /*this must be last                          */+-- } H5T_class_t;++{#enum H5T_class_t {underscoreToCase} deriving (Eq, Storable) #}++++-- | flags+
+ src/Data/HDF5/Internal/Types.hs view
@@ -0,0 +1,146 @@+-- GENERATED by C->Haskell Compiler, version 0.28.1 Switcheroo, 1 April 2016 (Haskell)+-- Edit the ORIGNAL .chs file instead!+++{-# LINE 1 "src/Data/HDF5/Internal/Types.chs" #-}+{-# language CPP, DeriveAnyClass #-}+module Data.HDF5.Internal.Types where+import qualified Foreign.C.Types as C2HSImp++++import Foreign.Storable+++++-- | HDF5 integer error codes+type Herr = (C2HSImp.CInt) ++-- | HDF Type of atoms to return to users+type Hid = (C2HSImp.CLLong) ++-- | HDF5 file object sizes (64 bits by default i.e. an unsigned CLLong)+type Hsize = (C2HSImp.CULLong) ++-- | HDF5 "ternary" Boolean type. Functions that return `htri_t' return zero (false), positive (true), or negative (failure).+type Htri = (C2HSImp.CInt)+{-# LINE 19 "src/Data/HDF5/Internal/Types.chs" #-}+++++-- | HDF5 native datatypes : https://support.hdfgroup.org/HDF5/doc/RM/PredefDTypes.html+  +-- type HNativeDouble = {#type H5T_NATIVE_DOUBLE #}++++-- /* These are the various classes of datatypes */+-- /* If this goes over 16 types (0-15), the file format will need to change) */+-- typedef enum H5T_class_t {+--     H5T_NO_CLASS         = -1,  /*error                                      */+--     H5T_INTEGER          = 0,   /*integer types                              */+--     H5T_FLOAT            = 1,   /*floating-point types                       */+--     H5T_TIME             = 2,   /*date and time types                        */+--     H5T_STRING           = 3,   /*character string types                     */+--     H5T_BITFIELD         = 4,   /*bit field types                            */+--     H5T_OPAQUE           = 5,   /*opaque types                               */+--     H5T_COMPOUND         = 6,   /*compound types                             */+--     H5T_REFERENCE        = 7,   /*reference types                            */+--     H5T_ENUM		 = 8,	/*enumeration types                          */+--     H5T_VLEN		 = 9,	/*Variable-Length types                      */+--     H5T_ARRAY	         = 10,	/*Array types                                */++--     H5T_NCLASSES                /*this must be last                          */+-- } H5T_class_t;++data H5T_class_t = H5tNoClass+                 | H5tInteger+                 | H5tFloat+                 | H5tTime+                 | H5tString+                 | H5tBitfield+                 | H5tOpaque+                 | H5tCompound+                 | H5tReference+                 | H5tEnum+                 | H5tVlen+                 | H5tArray+                 | H5tNclasses+  deriving (Eq,Storable)+instance Enum H5T_class_t where+  succ H5tNoClass = H5tInteger+  succ H5tInteger = H5tFloat+  succ H5tFloat = H5tTime+  succ H5tTime = H5tString+  succ H5tString = H5tBitfield+  succ H5tBitfield = H5tOpaque+  succ H5tOpaque = H5tCompound+  succ H5tCompound = H5tReference+  succ H5tReference = H5tEnum+  succ H5tEnum = H5tVlen+  succ H5tVlen = H5tArray+  succ H5tArray = H5tNclasses+  succ H5tNclasses = error "H5T_class_t.succ: H5tNclasses has no successor"++  pred H5tInteger = H5tNoClass+  pred H5tFloat = H5tInteger+  pred H5tTime = H5tFloat+  pred H5tString = H5tTime+  pred H5tBitfield = H5tString+  pred H5tOpaque = H5tBitfield+  pred H5tCompound = H5tOpaque+  pred H5tReference = H5tCompound+  pred H5tEnum = H5tReference+  pred H5tVlen = H5tEnum+  pred H5tArray = H5tVlen+  pred H5tNclasses = H5tArray+  pred H5tNoClass = error "H5T_class_t.pred: H5tNoClass has no predecessor"++  enumFromTo from to = go from+    where+      end = fromEnum to+      go v = case compare (fromEnum v) end of+                 LT -> v : go (succ v)+                 EQ -> [v]+                 GT -> []++  enumFrom from = enumFromTo from H5tNclasses++  fromEnum H5tNoClass = (-1)+  fromEnum H5tInteger = 0+  fromEnum H5tFloat = 1+  fromEnum H5tTime = 2+  fromEnum H5tString = 3+  fromEnum H5tBitfield = 4+  fromEnum H5tOpaque = 5+  fromEnum H5tCompound = 6+  fromEnum H5tReference = 7+  fromEnum H5tEnum = 8+  fromEnum H5tVlen = 9+  fromEnum H5tArray = 10+  fromEnum H5tNclasses = 11++  toEnum (-1) = H5tNoClass+  toEnum 0 = H5tInteger+  toEnum 1 = H5tFloat+  toEnum 2 = H5tTime+  toEnum 3 = H5tString+  toEnum 4 = H5tBitfield+  toEnum 5 = H5tOpaque+  toEnum 6 = H5tCompound+  toEnum 7 = H5tReference+  toEnum 8 = H5tEnum+  toEnum 9 = H5tVlen+  toEnum 10 = H5tArray+  toEnum 11 = H5tNclasses+  toEnum unmatched = error ("H5T_class_t.toEnum: Cannot match " ++ show unmatched)++{-# LINE 48 "src/Data/HDF5/Internal/Types.chs" #-}+++++-- | flags+
+ src/Data/HDF5/Lite.hs view
@@ -0,0 +1,451 @@+{-# language OverloadedStrings, QuasiQuotes, TemplateHaskell #-}+{-# language TypeFamilies #-}+{- |+Module      : Data.HDF5.Lite+Copyright   : (c) Marco Zocca, 2018+License     : GPL-3+Maintainer  : zocca.marco gmail+Stability   : experimental+Portability : POSIX+= Introduction++This module exposes the main interface to @hdf5-lite@.++-}+module Data.HDF5.Lite (+  -- * File API+  withFile+  , withFileCreate+  , FileOpenMode(..)  +  -- -- * Dataspace API+  -- , withDataspace+  -- * Dataset API+  , StorableDataset(..)+  -- -- ** Create+  -- , makeDatasetFloat+  -- , makeDatasetDouble+  -- -- ** Read+  -- , readDatasetFloat+  -- , readDatasetDouble+  -- ** Information+  , getDatasetInfo+  -- * HDF5 Types+  , Hid, Hsize, Herr, H5T_class_t+  -- * Exceptions+  , HDF5Exception+                      ) where++import Data.Functor ((<$>))++import Control.Monad.Catch (throwM, MonadThrow(..))+import Control.Exception (Exception(..), bracket)++import Foreign.C.String (CString, peekCString, withCString)+import Foreign.C.Types (CInt, CChar, CDouble, CFloat, CSize)+-- import Foreign.Marshal.Alloc (alloca)+import Foreign.Marshal.Array (withArray, peekArray, lengthArray0)+import Foreign.ForeignPtr (ForeignPtr(..), mallocForeignPtr)+import Foreign.Ptr (Ptr)+import Foreign.Storable++import GHC.Prim++import qualified Language.C.Inline as C++import qualified Data.Vector as V+import qualified Data.Vector.Unboxed as VU+import qualified Data.Vector.Storable as VS (Vector(..), unsafeWith, unsafeFromForeignPtr0, unsafeToForeignPtr0, fromList)+import qualified Data.Vector.Storable.Mutable as VM++import Data.HDF5.Internal.Types (Herr, Hid, Hsize, H5T_class_t)+import qualified Data.HDF5.Lite.Internal as H+import Data.HDF5.Internal.Exceptions+import Data.HDF5.Store++C.context H.hdf5ctx++C.include "<hdf5.h>"+C.include "<hdf5_hl.h>"+++  ++-- | HDF5 Lite API reference: https://support.hdfgroup.org/HDF5/doc/HL/RM_H5LT.html++-- hid_t H5Fcreate( const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id )+-- Purpose:+--     Creates an HDF5 file.+-- Description:+--     H5Fcreate is the primary function for creating HDF5 files; it creates a new HDF5 file with the specified name and property lists and specifies whether an existing file of same name should be overwritten.+--     The name parameter specifies the name of the new file.+--     The flags parameter specifies whether an existing file is to be overwritten. It should be set to either H5F_ACC_TRUNC to overwrite an existing file or H5F_ACC_EXCL, instructing the function to fail if the file already exists.+--     New files are always created in read-write mode, so the read-write and read-only flags, H5F_ACC_RDWR and H5F_ACC_RDONLY, respectively, are not relevant in this function. Further note that a specification of H5F_ACC_RDONLY will be ignored; the file will be created in read-write mode, regardless.+--     More complex behaviors of file creation and access are controlled through the file creation and file access property lists, fcpl_id and fapl_id, respectively. The value of H5P_DEFAULT for any property list value indicates that the library should use the default values for that appropriate property list.+--     The return value is a file identifier for the newly-created file; this file identifier should be closed by calling H5Fclose when it is no longer needed. +fcreate :: String -> IO Hid+fcreate name = withCString name $ \name_ ->+  [C.exp| hid_t{ H5Fcreate( $(const char* name_), H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT)}|]++++-- * File operations (H5F)+-- NB: each HDF5 physical file (e.g. "/usr/data/dataset0.h5" ) specifies a whole internal filesystem, the elements of which are what we call "files" here++-- hid_t H5Fopen( const char *name, unsigned flags, hid_t fapl_id )+-- Purpose:+--     Opens an existing HDF5 file.+-- Description:+--     H5Fopen is the primary function for accessing existing HDF5 files. This function opens the named file in the specified access mode and with the specified access property list.+--     Note that H5Fopen does not create a file if it does not already exist; see H5Fcreate.+--     The name parameter specifies the name of the file to be opened.+--     The fapl_id parameter specifies the file access property list. Use of H5P_DEFAULT specifies that default I/O access properties are to be used+--     The flags parameter specifies whether the file will be opened in read-write or read-only mode, H5F_ACC_RDWR or H5F_ACC_RDONLY, respectively. More complex behaviors of file access are controlled through the file-access property list.+--     The return value is a file identifier for the open file; this file identifier should be closed by calling H5Fclose when it is no longer needed. +++-- hid_t H5Fopen( const char *name, unsigned flags, hid_t fapl_id )+fopenReadOnly :: String -> IO Hid+fopenReadOnly name = withCString name $ \name_ -> +  [C.exp| hid_t{ H5Fopen( $(const char* name_), H5F_ACC_RDONLY, H5P_DEFAULT )}|]++fopenRW :: String -> IO Hid+fopenRW name = withCString name $ \name_ ->+  [C.exp| hid_t{ H5Fopen( $(const char* name_), H5F_ACC_RDWR, H5P_DEFAULT )}|]++-- | File access mode+data FileOpenMode = ReadOnly | ReadWrite deriving (Eq, Show)++-- | Open a file+fopen :: String -> FileOpenMode -> IO Hid+fopen name mode =+  case mode of ReadOnly -> fopenReadOnly name+               ReadWrite -> fopenRW name+++-- herr_t H5Fclose( hid_t file_id )+-- Purpose:+--     Terminates access to an HDF5 file.+-- Description:+--     H5Fclose terminates access to an HDF5 file by flushing all data to storage and terminating access to the file through file_id.+--     If this is the last file identifier open for the file and no other access identifier is open (e.g., a dataset identifier, group identifier, or shared datatype identifier), the file will be fully closed and access will end.+--     Delayed close:+--     Note the following deviation from the above-described behavior. If H5Fclose is called for a file but one or more objects within the file remain open, those objects will remain accessible until they are individually closed. Thus, if the dataset data_sample is open when H5Fclose is called for the file containing it, data_sample will remain open and accessible (including writable) until it is explicitely closed. The file will be automatically closed once all objects in the file have been closed.+--     Be warned, however, that there are circumstances where it is not possible to delay closing a file. For example, an MPI-IO file close is a collective call; all of the processes that opened the file must close it collectively. The file cannot be closed at some time in the future by each process in an independent fashion. Another example is that an application using an AFS token-based file access privilage may destroy its AFS token after H5Fclose has returned successfully. This would make any future access to the file, or any object within it, illegal.+--     In such situations, applications must close all open objects in a file before calling H5Fclose. It is generally recommended to do so in all cases.+-- Parameters:+--     hid_t file_id     	IN: Identifier of a file to terminate access to.+fclose :: Hid -> IO Herr+fclose fid = [C.exp| herr_t{ H5Fclose( $(hid_t fid))}|]+++-- | File memory bracket, preexisting file+withFile :: String -> FileOpenMode -> (Hid -> IO c) -> IO c+withFile name mode = bracket (fopen name mode) fclose+++-- | File memory bracket+withFileCreate :: String -> (Hid -> IO c) -> IO c+withFileCreate name = bracket (fcreate name) fclose+++++-- * Dataspace (H5S)+++-- hid_t H5Screate_simple( int rank, const hsize_t * current_dims, const hsize_t * maximum_dims )+-- Purpose:+--     Creates a new simple dataspace and opens it for access.+-- Description:+--     H5Screate_simple creates a new simple dataspace and opens it for access, returning a dataspace identifier.+--     rank is the number of dimensions used in the dataspace.+--     current_dims is a one-dimensional array of size rank specifying the size of each dimension of the dataset. maximum_dims is an array of the same size specifying the upper limit on the size of each dimension.+--     Any element of current_dims can be 0 (zero). Note that no data can be written to a dataset if the size of any dimension of its current dataspace is 0. This is sometimes a useful initial state for a dataset.+--     maximum_dims may be the null pointer, in which case the upper limit is the same as current_dims. Otherwise, no element of maximum_dims should be smaller than the corresponding element of current_dims.+--     If an element of maximum_dims is H5S_UNLIMITED, the maximum size of the corresponding dimension is unlimited.+--     Any dataset with an unlimited dimension must also be chunked; see H5Pset_chunk. Similarly, a dataset must be chunked if current_dims does not equal maximum_dims.+--     The dataspace identifier returned from this function must be released with H5Sclose or resource leaks will occur.+-- Parameters:+--     int rank 	IN: Number of dimensions of dataspace.+--     const hsize_t * current_dims 	IN: Array specifying the size of each dimension.+--     const hsize_t * maximum_dims     	IN: Array specifying the maximum size of each dimension.+screateSimple :: CInt -> [Hsize] -> IO Hid+screateSimple rank dims =+  withArray dims $ \dims_ -> +  [C.exp| hid_t{+      H5Screate_simple( $(int rank), $(hsize_t* dims_), NULL)+               }|]++sclose :: Hid -> IO Herr+sclose hid = [C.exp| herr_t{ H5Sclose( $(hid_t hid)) }|]++-- | Memory bracket for dataspaces+withDataspace :: CInt -> [Hsize] -> (Hid -> IO c) -> IO c+withDataspace rank dims = bracket (screateSimple rank dims) sclose+++++-- * Dataset (H5D)++-- herr_t H5LTmake_dataset_double ( hid_t loc_id, const char *dset_name, int rank, const hsize_t *dims, const double *buffer )+-- Purpose:+--     Creates and writes a dataset.  +-- Description:+--     H5LTmake_dataset creates and writes a dataset named dset_name attached to the object specified by the identifier loc_id.+--     The dataset’s datatype will be native floating-point double, H5T_NATIVE_DOUBLE. +-- Parameters:+-- hid_t loc_id+--     IN: Identifier of the file or group to create the dataset within. +-- const char *dset_name+--     IN: The name of the dataset to create. +-- int rank+--     IN: Number of dimensions of dataspace. +-- const hsize_t * dims+--     IN: An array of the size of each dimension. +-- const double * buffer+--     IN: Buffer with data to be written to the dataset.+-- Returns:+--     Returns a non-negative value if successful; otherwise returns a negative value.+makeDatasetDouble' :: Hid -> Ptr CChar -> CInt -> Ptr Hsize -> Ptr C.CDouble -> IO Herr+makeDatasetDouble' loc name rank dims bp =+  [C.exp| herr_t{+        H5LTmake_dataset_double( $(hid_t loc), $(const char* name), $(int rank), $(const hsize_t* dims), $(double* bp) ) } |]  +++makeDatasetDouble+  :: Hid -> String -> [Hsize] -> VS.Vector C.CDouble -> IO ()+makeDatasetDouble loc name dims buffer =+  withMakeDataset loc name dims buffer makeDatasetDouble'+++-- float++makeDatasetFloat' :: Hid -> Ptr CChar -> CInt -> Ptr Hsize -> Ptr CFloat -> IO Herr+makeDatasetFloat' loc name rank dims bp =+  [C.exp| herr_t{+        H5LTmake_dataset_float( $(hid_t loc), $(const char* name), $(int rank), $(const hsize_t* dims), $(float* bp) ) } |]++makeDatasetFloat+  :: Hid -> String -> [Hsize] -> VS.Vector CFloat -> IO ()+makeDatasetFloat loc name dims buffer =+  withMakeDataset loc name dims buffer makeDatasetFloat'++-- int++makeDatasetInt'+  :: Hid -> Ptr CChar -> CInt -> Ptr Hsize -> Ptr CInt -> IO Herr+makeDatasetInt' loc name rank dims bp =+  [C.exp| herr_t{+        H5LTmake_dataset_int( $(hid_t loc), $(const char* name), $(int rank), $(const hsize_t* dims), $(int* bp) ) } |]++makeDatasetInt+  :: Hid -> String -> [Hsize] -> VS.Vector CInt -> IO ()+makeDatasetInt loc name dims bp =+  withMakeDataset loc name dims bp makeDatasetInt'+  ++-- | Helper function for dataset creation+withMakeDataset :: (Num t1, Storable a1, Storable a2) =>+     t2+     -> String+     -> [a1]+     -> VS.Vector a2+     -> (t2 -> CString -> t1 -> Ptr a1 -> Ptr a2 -> IO Herr)+     -> IO ()+withMakeDataset loc name dims buffer io =+    let+    rank = fromIntegral $ length dims+  in +    withCString name $ \name_ ->+    withArray dims $ \dims_ -> +    VS.unsafeWith buffer $ \ bp_ -> throwH (io loc name_ rank dims_ bp_)++instance StorableDataset CFloat where+  makeDataset = makeDatasetFloat+  readDataset = readDatasetFloat++instance StorableDataset CDouble where+  makeDataset = makeDatasetDouble+  readDataset = readDatasetDouble+++-- herr_t H5LTmake_dataset_char ( hid_t loc_id, const char *dset_name, int rank, const hsize_t *dims, const char *buffer )+++-- | Close a dataset and release its resources+dclose :: Hid -> IO Herr+dclose did = [C.exp| herr_t{ H5Dclose( $(hid_t did)) } |]++++-- herr_t H5LTread_dataset_double ( hid_t loc_id, const char *dset_name, double *buffer  +-- Purpose:+--     Reads a dataset from disk. +-- Description:+--     H5LTread_dataset reads a dataset named dset_name attached to the object specified by the identifier loc_id. The HDF5 datatype is H5T_NATIVE_DOUBLE. +-- Parameters:+-- hid_t loc_id+--     IN: Identifier of the file or group to read the dataset within. +-- const char *dset_name+--     IN: The name of the dataset to read. +-- double * buffer+--     OUT: Buffer with data.+++readDatasetDouble' loc name_ bp =+  [C.exp|herr_t{+      H5LTread( $(hid_t loc), $(const char* name_), $(double* bp) )+               }|]++readDatasetDouble :: Hid -> String -> IO (VS.Vector CDouble)+readDatasetDouble loc name = withReadDataset loc name (undefined :: CDouble) readDatasetDouble'  ++++readDatasetFloat' loc name_ bp =+  [C.exp|herr_t{+      H5LTread( $(hid_t loc), $(const char* name_), $(float* bp) )+               }|]++readDatasetFloat :: Hid -> String -> IO (VS.Vector CFloat)+readDatasetFloat loc name = withReadDataset loc name (undefined :: CFloat) readDatasetFloat'  +++withReadDataset+  :: (Storable a, Eq a) =>+     t+     -> String+     -> a+     -> (t -> CString -> Ptr a -> IO Herr)+     -> IO (VS.Vector a)+withReadDataset loc name x io =+  fst <$> withCString name ( \name_ ->+  peekVS x $ \bp -> throwH (io loc name_ bp))++++++++-- herr_t H5LTget_attribute_ndims( hid_t loc_id, const char *obj_name, const char *attr_name,  int *rank )+-- Purpose:+--     Gets the dimensionality of an attribute. +-- Description:+--     H5LTget_attribute_ndims gets the dimensionality of an attribute named attr_name that is attached to the object specified by the name obj_name. +-- Parameters:+-- hid_t loc_id+--     IN: Identifier of the object ( dataset or group) to read the attribute from. +-- const char *obj_name+--     IN: The name of the object that the attribute is attached to. +-- const char *attr_name+--     IN: The attribute name. +-- int * rank+--     OUT: The dimensionality of the attribute. ++++++++-- herr_t H5LTget_dataset_info ( hid_t loc_id, const char *dset_name, hsize_t *dims, H5T_class_t *class_id, size_t *type_size )+-- Purpose:+--     Gets information about a dataset.  +-- Description:+--     H5LTget_dataset_info gets information about a dataset named dset_name exists attached to the object loc_id.+-- Parameters:+-- hid_t loc_id+--     IN: Identifier of the object to locate the dataset within. +-- const char *dset_name+--     IN: The dataset name. +-- hsize_t * dims+--     OUT: The dimensions of the dataset.+-- H5T_class_t * class_id+--     OUT: The class identifier. To a list of the HDF5 class types please refer to the Datatype Interface API help.+-- size_t * type_size+--     OUT: The size of the datatype in bytes.+getDatasetInfo :: Hid -> String -> IO ([Hsize], H5T_class_t, CSize)+getDatasetInfo loc name = do +  (sizes, (clid, szt)) <- peekArrayPtr (undefined :: Hsize) $ \dims -> +      withPtr2 $ \ clid szt ->+        withCString name $ \name_ ->                    +        [C.exp| herr_t{+        H5LTget_dataset_info ( $(hid_t loc), $(const char *name_), $(hsize_t *dims), $(H5T_class_t *clid), $(size_t *szt) )+                  }|]+  return (sizes, clid, szt)        ++    ++++++-- * HDF5 image operations+-- The HDF5 Image API defines a standard storage for HDF5 datasets that are intended to be interpreted as images. The specification for this API is presented in another document: HDF5 Image and Palette Specification. This version of the API is primarily concerned with two dimensional raster data similar to HDF4 Raster Images. The HDF5 image API uses the Lite HDF5 API. ++-- herr_t H5IMread_image ( hid_t loc_id, const char *dset_name, unsigned char *buffer ) +-- Purpose:+--     Reads image data from disk. +-- Description:+--     H5IMread_image reads a dataset named dset_name attached to the file or group specified by the identifier loc_id. +-- Parameters:+--     hid_t loc_id 	IN: Identifier of the file or group to read the dataset from.+--     const char *dset_name 	IN: The name of the dataset.+--     unsigned char *buffer     	OUT: Buffer with data to store the image.+-- Returns:+--     Returns a non-negative value if successful; otherwise returns a negative value.++-- readImage locId name = undefined+++++-- * Helpers+++++class Sized v where+  type SizedData v :: * +  dat :: v -> SizedData v+  size :: v -> [Hsize]+  rank :: v -> CInt++-- data Sized v = Sized { szDat :: v, szDims :: [Hsize] } deriving (Eq, Show)+++++withPtr2+  :: (Storable a, Storable b) =>+     (Ptr a -> Ptr b -> IO Herr) -> IO (a, b)+withPtr2 io = do+  (a, (b, _)) <- C.withPtr $ \a -> C.withPtr $ \b -> throwH (io a b)+  return (a, b)++withPtr3+  :: (Storable a, Storable b, Storable c) =>+     (Ptr a -> Ptr b -> Ptr c -> IO Herr) -> IO (a, b, c)+withPtr3 io = do+  (a, (b, (c, _))) <- C.withPtr $ \a -> C.withPtr $ \b -> C.withPtr $ \c -> throwH (io a b c)+  return (a, b, c)++++peekArrayPtr :: (Storable a, Eq a) => a -> (Ptr a -> IO b) -> IO ([a], b)+peekArrayPtr x io =+  snd <$> C.withPtr ( \p -> do+    e <- io p                         +    n <- lengthArray0 x p+    z <- peekArray n p+    return (z, e)+            )++peekVS :: (Storable a, Eq a) =>+     a -> (Ptr a -> IO b) -> IO (VS.Vector a, b)+peekVS x io = do+  (arr, e) <- peekArrayPtr x io+  return (VS.fromList arr, e)+  
+ src/Data/HDF5/Lite/Internal.hs view
@@ -0,0 +1,38 @@+{-# language OverloadedStrings, QuasiQuotes, TemplateHaskell #-}+module Data.HDF5.Lite.Internal where++import           Data.Monoid ((<>), mempty)+import qualified Data.Map as M++import           Foreign.C.Types+import           Foreign.Ptr (Ptr)+import           Foreign.Storable (Storable(..))+import qualified Language.Haskell.TH as TH++import           Language.C.Inline as C+import           Language.C.Inline.Context+import qualified Language.C.Types as C++import Data.HDF5.Internal.Types+++C.include "<hdf5_hl.h>"++++-- | inline-c context+hdf5ctx :: Context+hdf5ctx = baseCtx <> funCtx <> vecCtx <> bsCtx <> ctx+  where+    ctx = mempty { ctxTypesTable = hdf5TypesTable }++-- | HDF5 types table for inline-c+hdf5TypesTable :: M.Map C.TypeSpecifier TH.TypeQ+hdf5TypesTable = M.fromList [+    (C.TypeName "herr_t", [t| Herr |])+  , (C.TypeName "hid_t", [t| Hid |])+  , (C.TypeName "hsize_t", [t| Hsize |])+  , (C.TypeName "htri_t", [t| Htri |])+  , (C.TypeName "H5T_class_t", [t| H5T_class_t |])+                            ]+
+ src/Data/HDF5/Store.hs view
@@ -0,0 +1,42 @@+module Data.HDF5.Store where++import qualified Data.Vector.Storable as VS+import Foreign.C.Types (CInt, CChar, CDouble, CFloat, CSize)+import Foreign.Storable++import Data.HDF5.Internal.Types (Herr, Hid, Hsize, H5T_class_t)++class Storable a => StorableDataset a where+  -- | Allocate and write a dataset+  makeDataset :: Hid  -- ^ Identifier+    -> String    -- ^ Dataset name+    -> [Hsize]   -- ^ Dimensions+    -> VS.Vector a -- ^ Dataset contents+    -> IO ()+  -- | Read a dataset+  readDataset :: Hid -- ^ Identifier+    -> String        -- ^ Dataset name+    -> IO (VS.Vector a)+++++++-- from https://github.com/ian-ross/hnetcdf/blob/master/Data/NetCDF/Store.hs++-- -- | Class representing containers suitable for storing values read+-- -- from NetCDF variables.  Just has methods to convert back and forth+-- -- between the store and a foreign pointer, and to perform simple+-- -- mapping over the store.  The NcStoreExtraCon associated+-- -- constraint-kinded type is used to track extra class constraints on+-- -- elements needed for some store types.+-- class NcStore s where+--   type NcStoreExtraCon s a :: Constraint+--   type NcStoreExtraCon s a = ()+--   toForeignPtr :: (Storable e, NcStoreExtraCon s e) =>+--                   s e -> ForeignPtr e+--   fromForeignPtr :: (Storable e, NcStoreExtraCon s e) =>+--                     ForeignPtr e -> [Int] -> s e+--   smap :: (Storable a, Storable b, NcStoreExtraCon s a, NcStoreExtraCon s b) =>+-- (a -> b) -> s a -> s b
+ test/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}