module Data.Grib (
GribIO
, runGribIO
, runGribIO_
, GribEnv
, getDouble
, getLong
, getString
, getValues
, setDouble
, setLong
, setString
, setValues
, getFilename
, getIndex
, getHandle
, liftIO
) where
import Control.Monad ( void )
import Control.Monad.IO.Class ( liftIO )
import Control.Monad.Trans.Reader ( ReaderT, ask, runReaderT )
import Foreign ( allocaArray, allocaBytes )
import Control.Applicative
import Prelude
import Data.Grib.Raw
handles :: FilePath -> IO [GribHandle]
handles path = withBinaryCFile path ReadMode go
where go file = gribHandleNewFromFile defaultGribContext file >>=
maybe (return []) (\h' -> (h' :) <$> go file)
data GribEnv = GribEnv
{ filename :: FilePath
, index :: Int
, handle :: GribHandle
}
envs :: FilePath -> IO [GribEnv]
envs path = fmap (zipWith3 GribEnv (repeat path) [0..]) (handles path)
type GribIO = ReaderT GribEnv IO
runGribIO :: FilePath
-> GribIO a
-> IO [a]
runGribIO path m = envs path >>= mapM (runReaderT m)
runGribIO_ :: FilePath -> GribIO a -> IO ()
runGribIO_ path m = envs path >>= mapM_ (runReaderT m)
getFilename :: GribIO FilePath
getFilename = fmap filename ask
getIndex :: GribIO Int
getIndex = fmap index ask
getHandle :: GribIO GribHandle
getHandle = fmap handle ask
getDouble :: Key -> GribIO Double
getDouble key = getHandle >>= liftIO . flip gribGetDouble key
getLong :: Key -> GribIO Int
getLong key = getHandle >>= liftIO . flip gribGetLong key
getString :: Key -> GribIO String
getString key = getHandle >>= \h -> do
n <- liftIO . gribGetLength h $ key
liftIO . allocaBytes n $ \bufr -> gribGetString h key bufr n
getValues :: GribIO [Double]
getValues = getHandle >>= \h -> do
n <- liftIO . gribGetSize h $ key
liftIO . allocaArray n $ \array -> gribGetDoubleArray h key array n
where key = "values"
setGeneric :: (GribHandle -> Key -> a -> IO b) -> Key -> a -> GribIO b
setGeneric setter key value = getHandle >>= \h -> liftIO $ setter h key value
setDouble :: Key -> Double -> GribIO ()
setDouble = setGeneric gribSetDouble
setLong :: Key -> Int -> GribIO ()
setLong = setGeneric gribSetLong
setString :: Key -> String -> GribIO ()
setString key value = void $ setGeneric gribSetString key value
setValues :: [Double] -> GribIO ()
setValues = setGeneric gribSetDoubleArray "values"