{-# LANGUAGE GeneralizedNewtypeDeriving #-} module Bindings.HDF5.PropertyList.DCPL ( module Bindings.HDF5.PropertyList.OCPL , DCPL , DatasetCreationPropertyList , Layout(..) , setLayout , getLayout , setChunk , getChunk , setExternal , getExternalCount , getExternalN , getExternal , setSZip , setShuffle , setNBit , ScaleType(..) , setScaleOffset , setFillValue , getFillValue , FillValueDefaultType(..) , fillValueDefined , AllocTime(..) , setAllocTime , getAllocTime , FillTime(..) , setFillTime , getFillTime ) where import Bindings.HDF5.Core import Bindings.HDF5.Error import Bindings.HDF5.PropertyList import Bindings.HDF5.PropertyList.OCPL import Bindings.HDF5.Datatype.Internal import Bindings.HDF5.Raw.H5D import Bindings.HDF5.Raw.H5P import Bindings.HDF5.Raw.H5Z import qualified Data.ByteString as BS import qualified Data.ByteString.Unsafe as BS import Data.List import Foreign import Foreign.C import Foreign.Ptr.Conventions import System.Posix.Types newtype DCPL = DCPL OCPL deriving (Eq, HId, FromHId, HDFResultType, PropertyListOrClass, ObjectCreationPropertyList) instance PropertyList DCPL where staticPlistClass = Tagged datasetCreate class ObjectCreationPropertyList t => DatasetCreationPropertyList t where instance DatasetCreationPropertyList DCPL data Layout = CompactLayout | ContiguousLayout | ChunkedLayout deriving (Eq, Ord, Bounded, Enum, Read, Show) layoutCode :: Layout -> H5D_layout_t layoutCode CompactLayout = h5d_COMPACT layoutCode ContiguousLayout = h5d_CONTIGUOUS layoutCode ChunkedLayout = h5d_CHUNKED layout :: H5D_layout_t -> Layout layout c | c == h5d_COMPACT = CompactLayout | c == h5d_CONTIGUOUS = ContiguousLayout | c == h5d_CHUNKED = ChunkedLayout | otherwise = error ("unknown H5D_layout_t: " ++ show c) setLayout :: DatasetCreationPropertyList t => t -> Layout -> IO () setLayout plist l = withErrorCheck_ $ h5p_set_layout (hid plist) (layoutCode l) getLayout :: DatasetCreationPropertyList t => t -> IO Layout getLayout plist = fmap layout $ withErrorWhen (\(H5D_layout_t c) -> c < 0) $ h5p_get_layout (hid plist) setChunk :: DatasetCreationPropertyList t => t -> [HSize] -> IO () setChunk plist chunkSizes = withErrorCheck_ $ withInList (map hSize chunkSizes) $ \cchunkSizes -> h5p_set_chunk (hid plist) n cchunkSizes where n = genericLength chunkSizes getChunk :: DatasetCreationPropertyList t => t -> IO [HSize] getChunk plist = do n <- withErrorWhen (< 0) $ h5p_get_chunk (hid plist) 0 (OutArray nullPtr) fmap (map HSize) $ withOutList_ (fromIntegral n) $ \buf -> withErrorWhen_ (< 0) $ h5p_get_chunk (hid plist) n buf setExternal :: DatasetCreationPropertyList t => t -> BS.ByteString -> COff -> HSize -> IO () setExternal plist name offset size = withErrorCheck_ $ BS.useAsCString name $ \cname -> h5p_set_external (hid plist) cname offset (hSize size) getExternalCount :: DatasetCreationPropertyList t => t -> IO CInt getExternalCount plist = withErrorWhen (< 0) $ h5p_get_external_count (hid plist) getExternalN :: DatasetCreationPropertyList t => t -> CUInt -> CSize -> IO (BS.ByteString, COff, HSize) getExternalN plist idx name_size = do let sz = fromIntegral name_size name1 <- mallocBytes sz (offset, size) <- withOut $ \offset -> withOut_ $ \size -> withErrorCheck_ $ h5p_get_external (hid plist) idx name_size (OutArray name1) offset size -- TODO: this will leak memory if an exception is thrown name2 <- BS.unsafePackCStringLen (name1, sz) return (BS.takeWhile (0 /=) name2, offset, HSize size) getExternal :: DatasetCreationPropertyList t => t -> CUInt -> IO (BS.ByteString, COff, HSize) getExternal plist idx = loop 255 where loop sz = do result@(name, _, _) <- getExternalN plist idx sz if BS.length name < fromIntegral sz then return result else do let sz' = 2*sz + 1 if sz' > sz then loop sz' else fail "getExternal: name_size overflow, this is almost certainly a programming error in getExternal" setSZip :: DatasetCreationPropertyList t => t -> CUInt -> CUInt -> IO () setSZip plist options_mask pixels_per_block = withErrorCheck_ $ h5p_set_szip (hid plist) options_mask pixels_per_block setShuffle :: DatasetCreationPropertyList t => t -> IO () setShuffle plist = withErrorCheck_ $ h5p_set_shuffle (hid plist) setNBit :: DatasetCreationPropertyList t => t -> IO () setNBit plist = withErrorCheck_ $ h5p_set_nbit (hid plist) data ScaleType = FloatDScale | FloatEScale | IntScale deriving (Eq, Ord, Bounded, Enum, Read, Show) scaleTypeCode :: ScaleType -> H5Z_SO_scale_type_t scaleTypeCode FloatDScale = h5z_SO_FLOAT_DSCALE scaleTypeCode FloatEScale = h5z_SO_FLOAT_ESCALE scaleTypeCode IntScale = h5z_SO_INT setScaleOffset :: DatasetCreationPropertyList t => t -> ScaleType -> CInt -> IO () setScaleOffset plist scale_type scale_factor = withErrorCheck_ $ h5p_set_scaleoffset (hid plist) (scaleTypeCode scale_type) scale_factor setFillValue :: (DatasetCreationPropertyList t, NativeType a) => t -> a -> IO () setFillValue plist value = withErrorCheck_ $ withIn value $ \ivalue -> h5p_set_fill_value (hid plist) (hdfTypeOf1 ivalue) ivalue getFillValue :: (DatasetCreationPropertyList t, NativeType a) => t -> IO a getFillValue plist = withOut_ $ \value -> withErrorCheck_ $ h5p_get_fill_value (hid plist) (hdfTypeOf1 value) value data FillValueDefaultType = Undefined | DefaultFillValue | UserDefined deriving (Eq, Ord, Bounded, Enum, Read, Show) fillValueDefaultType :: H5D_fill_value_t -> FillValueDefaultType fillValueDefaultType c | c == h5d_FILL_VALUE_UNDEFINED = Undefined | c == h5d_FILL_VALUE_DEFAULT = DefaultFillValue | c == h5d_FILL_VALUE_USER_DEFINED = UserDefined | c == h5d_FILL_VALUE_ERROR = error "fillValueDefined: h5d_FILL_VALUE_ERROR" | otherwise = error ("fillValueDefined: unknown H5D_fill_value_t " ++ show c) fillValueDefined :: DatasetCreationPropertyList t => t -> IO FillValueDefaultType fillValueDefined plist = fmap fillValueDefaultType $ withOut_ $ \status -> withErrorCheck_ $ h5p_fill_value_defined (hid plist) status data AllocTime = DefaultAllocTime | Early | Late | Incr -- ...emental? deriving (Eq, Ord, Bounded, Enum, Read, Show) allocTimeCode :: AllocTime -> H5D_alloc_time_t allocTimeCode DefaultAllocTime = h5d_ALLOC_TIME_DEFAULT allocTimeCode Early = h5d_ALLOC_TIME_EARLY allocTimeCode Late = h5d_ALLOC_TIME_LATE allocTimeCode Incr = h5d_ALLOC_TIME_INCR allocTime :: H5D_alloc_time_t -> AllocTime allocTime c | c == h5d_ALLOC_TIME_DEFAULT = DefaultAllocTime | c == h5d_ALLOC_TIME_EARLY = Early | c == h5d_ALLOC_TIME_LATE = Late | c == h5d_ALLOC_TIME_INCR = Incr | c == h5d_ALLOC_TIME_ERROR = error "h5d_ALLOC_TIME_ERROR" | otherwise = error ("unknown H5D_alloc_time_t " ++ show c) setAllocTime :: DatasetCreationPropertyList t => t -> AllocTime -> IO () setAllocTime plist alloc_time = withErrorCheck_ $ h5p_set_alloc_time (hid plist) (allocTimeCode alloc_time) getAllocTime :: DatasetCreationPropertyList t => t -> IO AllocTime getAllocTime plist = fmap allocTime $ withOut_ $ \alloc_time -> withErrorCheck_ $ h5p_get_alloc_time (hid plist) alloc_time data FillTime = Alloc | Never | IfSet deriving (Eq, Ord, Bounded, Enum, Read, Show) fillTimeCode :: FillTime -> H5D_fill_time_t fillTimeCode Alloc = h5d_FILL_TIME_ALLOC fillTimeCode Never = h5d_FILL_TIME_NEVER fillTimeCode IfSet = h5d_FILL_TIME_IFSET fillTime :: H5D_fill_time_t -> FillTime fillTime c | c == h5d_FILL_TIME_ALLOC = Alloc | c == h5d_FILL_TIME_NEVER = Never | c == h5d_FILL_TIME_IFSET = IfSet | otherwise = error "unknown h5d_FILL_TIME value" setFillTime :: DatasetCreationPropertyList t => t -> FillTime -> IO () setFillTime plist fill_time = withErrorCheck_ $ h5p_set_fill_time (hid plist) (fillTimeCode fill_time) getFillTime :: DatasetCreationPropertyList t => t -> IO FillTime getFillTime plist = fmap fillTime $ withOut_ $ \fill_time -> withErrorCheck_ $ h5p_get_fill_time (hid plist) fill_time