codec-0.1: Examples/Foreign.hsc
module Examples.Foreign where
#include "time.h"
#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)
import Foreign
import Foreign.C
import Data.Codec
import Foreign.Codec
data TM = TM
{ seconds :: Int
, minutes :: Int
, hours :: Int
, monthDay :: Int
, month :: Int
, year :: Int
, weekDay :: Int
, yearDay :: Int
, daylightSavingTime :: Bool
} deriving Show
genFields ''TM
-- convenience macro that enforces the correct codec type for a field
#define hsc_numField(s, f) \
hsc_printf("field (%ld) . codecFor (undefined :: ", offsetof(s, f)); \
hsc_type(typeof(((s*)0)->f)); \
hsc_printf(")");
cTimeCodec :: ForeignCodec TM
cTimeCodec =
TM
$>> f_seconds >-< (#numField struct tm, tm_sec) cast
>>> f_minutes >-< (#numField struct tm, tm_min) cast
>>> f_hours >-< (#numField struct tm, tm_hour) cast
>>> f_monthDay >-< (#numField struct tm, tm_mday) cast
>>> f_month >-< (#numField struct tm, tm_mon) cast
>>> f_year >-< (#numField struct tm, tm_year) cast
>>> f_weekDay >-< (#numField struct tm, tm_wday) cast
>>> f_yearDay >-< (#numField struct tm, tm_yday) cast
>>> f_daylightSavingTime >-< (#numField struct tm, tm_yday) cBool
instance Storable TM where
sizeOf _ = #{size struct tm}
alignment _ = #{alignment struct tm}
peek = peekWith cTimeCodec
poke = pokeWith cTimeCodec
foreign import ccall "time.h strftime" strftime
:: CString -> CInt -> CString -> Ptr TM -> IO CSize
formatTM :: String -> TM -> IO String
formatTM fmt tm
= allocaBytes maxSize $ \str -> do
_ <- withCString fmt $ \cfmt ->
with tm $ \tmp ->
strftime str (fromIntegral maxSize) cfmt tmp
peekCString str
where
maxSize = 512
testTime :: TM
testTime = TM
{ seconds = 42
, minutes = 49
, hours = 13
, monthDay = 4
, month = 4
, year = 115
, weekDay = 0
, yearDay = 0
, daylightSavingTime = False
}