packages feed

gegl-0.0.0.1: src/GEGL/FFI/Tuple.hsc

{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ForeignFunctionInterface #-}
module GEGL.FFI.Tuple where

import qualified Language.C.Inline as C
import qualified Language.C.Types as C
import qualified Language.C.Inline.Context as C

import qualified Data.Map as Map

import Foreign
import Foreign.C.Types
import Foreign.C.String
import Foreign.Ptr
import GHC.Ptr as G

import qualified Language.Haskell.TH as TH

#def typedef struct {void * node; char * pad;} producer;
#def typedef struct {int length; void * data; char ** names;} nodeWithPad;
#def typedef struct {int length; float * data;} tupleFloat;
#def typedef struct {int length; double * data;} tupleDouble;

C.include "Tuple.h"

data Producer = Producer
  { prodNode :: Ptr ()
  , prodPad  :: CString
  }

instance Storable Producer where
  sizeOf    (Producer _ _) = (#size producer)
  alignment (Producer _ _) = alignment (undefined :: CDouble)
  peek ptr = do
    node <- (#peek producer, node) ptr
    pad  <- (#peek producer, pad) ptr
    return $ Producer node pad
  poke _ = error "poke undefined for Produer"

data NodeWithPad =
  NodeWithPad
    { nwpLength :: CInt
    , nwpData   :: Ptr (Ptr ())
    , nwpNames  :: Ptr CString
    }

instance Storable NodeWithPad where
  sizeOf    (NodeWithPad _ _ _) = (#size tupleFloat)
  alignment (NodeWithPad _ _ _) = alignment (undefined :: CDouble)
  peek ptr = do
    length <- (#peek nodeWithPad, length) ptr
    tdata  <- (#peek nodeWithPad, data) ptr
    names  <- (#peek nodeWithPad, names) ptr
    return $ NodeWithPad length tdata names
  poke ptr (NodeWithPad{..}) = do
    (#poke nodeWithPad, length) ptr nwpLength
    (#poke nodeWithPad, data)   ptr nwpData
    (#poke nodeWithPad, names)  ptr nwpNames

data TupleFloat =
  TupleFloat
    { tupleFloatLength :: CInt
    , tupleFloatData   :: Ptr CFloat
    }

instance Storable TupleFloat where
  sizeOf    (TupleFloat _ _) = (#size tupleFloat)
  alignment (TupleFloat _ _) = alignment (undefined :: CDouble)
  peek ptr = do
    length <- (#peek tupleFloat, length) ptr
    tdata  <- (#peek tupleFloat, data) ptr
    return $ TupleFloat length tdata
  poke ptr (TupleFloat{..}) = do
    (#poke tupleFloat, length) ptr tupleFloatLength
    (#poke tupleFloat, data)   ptr tupleFloatData

data TupleDouble =
  TupleDouble
    { tupleDoubleLength :: CInt
    , tupleDoubleData   :: Ptr CDouble
    }

instance Storable TupleDouble where
  sizeOf    (TupleDouble _ _) = (#size tupleDouble)
  alignment (TupleDouble _ _) = alignment (undefined :: CDouble)
  peek ptr = do
    length <- (#peek tupleDouble, length) ptr
    tdata  <- (#peek tupleDouble, data) ptr
    return $ TupleDouble length tdata
  poke ptr (TupleDouble{..}) = do
    (#poke tupleDouble, length) ptr tupleDoubleLength
    (#poke tupleDouble, data)   ptr tupleDoubleData

tupleCtx :: C.Context
tupleCtx = mempty
  { C.ctxTypesTable = tupleTypes
  }

tupleTypes :: Map.Map C.TypeSpecifier TH.TypeQ
tupleTypes = Map.fromList
  [ (C.TypeName "tupleFloat",  [t|TupleFloat|])
  , (C.TypeName "tupleDouble", [t|TupleDouble|])
  , (C.TypeName "nodeWithPad",   [t|NodeWithPad|])
  , (C.TypeName "producer",   [t|Producer|])
  ]