packages feed

tokyocabinet-haskell-0.0.1: Database/TokyoCabinet/Internal.hs

module Database.TokyoCabinet.Internal where

import Database.TokyoCabinet.List.C
import Database.TokyoCabinet.Storable

import Foreign.Ptr
import Foreign.ForeignPtr
import Foreign.C.Types
import Foreign.C.String
import Foreign.Storable (peek)
import Foreign.Marshal (alloca)
import Foreign.Marshal.Utils (maybePeek)

import Data.Word

peekTCListAndFree :: (Storable a) => Ptr LIST -> IO [a]
peekTCListAndFree list = do
  vals <- peekTCList' list []
  c_tclistdel list
  return vals
 where
   peekTCList' tclist acc = 
       alloca $ \sizbuf ->
           do val <- c_tclistpop tclist sizbuf
              siz <- peek sizbuf
              if val == nullPtr
                then return acc
                else do elm <- peekPtrLen (val, siz)
                        peekTCList' tclist (elm:acc)

type Lifter ptr tcdb = Ptr ptr -> tcdb
type UnLifter tcdb fptr = tcdb -> ForeignPtr fptr
type Combiner mode c_mode = [mode] -> c_mode
type Caster a b = a -> b
type Checker a = a -> Bool

type FunOpen p c_mode = Ptr p -> CString -> c_mode -> IO Bool
type FunPath p = Ptr p -> IO CString
type FunCopy p = Ptr p -> CString -> IO Bool
type FunPut  p = Ptr p -> Ptr Word8 -> CInt -> Ptr Word8 -> CInt -> IO Bool
type FunGet  p = Ptr p -> Ptr Word8 -> CInt -> Ptr CInt -> IO (Ptr Word8)
type FunOut  p = Ptr p -> Ptr Word8 -> CInt -> IO Bool
type FunAdd  p n = Ptr p -> Ptr Word8 -> CInt -> n -> IO n
type FunFwm  p = Ptr p -> Ptr Word8 -> CInt -> CInt -> IO (Ptr LIST)
type FunVsiz p =  Ptr p -> Ptr Word8 -> CInt -> IO CInt

openHelper :: FunOpen p c_mode -> UnLifter tcdb p
           -> Combiner mode c_mode -> tcdb -> String -> [mode] -> IO Bool
openHelper opener unlifter combiner tcdb name modes =
    withForeignPtr (unlifter tcdb) $ \db ->
        withCString name $ \c_name ->
            opener db c_name (combiner modes)

pathHelper :: FunPath p -> UnLifter tcdb p -> tcdb -> IO (Maybe String)
pathHelper c_path unlifter tcdb =
    withForeignPtr (unlifter tcdb) $ \db ->
        c_path db >>= (maybePeek peekCString)

copyHelper :: FunCopy p -> UnLifter tcdb p -> tcdb -> String -> IO Bool
copyHelper c_copy unlifter tcdb fpath =
    withForeignPtr (unlifter tcdb) $ \db -> withCString fpath (c_copy db)

putHelper :: (Storable a, Storable b) =>
             FunPut p -> UnLifter tcdb p -> tcdb -> a -> b -> IO Bool
putHelper c_put unlifter tcdb key val =
    withForeignPtr (unlifter tcdb) $ \db ->
        withPtrLen key $ \(kbuf, ksize) ->
        withPtrLen val $ \(vbuf, vsize) -> c_put db kbuf ksize vbuf vsize

getHelper :: (Storable a, Storable b) =>
             FunGet p -> UnLifter tcdb p -> tcdb -> a -> IO (Maybe b)
getHelper c_get unlifter tcdb key =
    withForeignPtr (unlifter tcdb) $ \db ->
        withPtrLen key $ \(kbuf, ksiz) ->
            alloca $ \sizbuf -> do
              vbuf <- c_get db kbuf ksiz sizbuf
              flip maybePeek vbuf $ \vp ->
                  do siz <- peek sizbuf
                     peekPtrLen (vp, siz)

outHelper :: (Storable a) =>
             FunOut p -> UnLifter tcdb p -> tcdb -> a -> IO Bool
outHelper c_out unlifter tcdb key =
    withForeignPtr (unlifter tcdb) $ \db ->
        withPtrLen key $ \(kbuf, ksize) -> c_out db kbuf ksize

addHelper :: (Storable a) =>
             FunAdd p n -> UnLifter tcdb p
                        -> Caster hv n -> Caster n hv -> Checker n
                        -> tcdb -> a -> hv -> IO (Maybe hv)
addHelper c_add unlifter cast_in cast_out check tcdb key num =
    withForeignPtr (unlifter tcdb) $ \db ->
        withPtrLen key $ \(kbuf, ksiz) -> do
            sumval <- c_add db kbuf ksiz (cast_in num)
            return $ if check sumval
                       then Nothing
                       else Just $ cast_out sumval


fwmHelper :: (Storable a, Storable b) =>
             FunFwm p -> UnLifter tcdb p -> tcdb -> a -> Int -> IO [b]
fwmHelper c_fwm unlifter tcdb key maxn = 
    withForeignPtr (unlifter tcdb) $ \db ->
        withPtrLen key $ \(kbuf, ksiz) ->
            c_fwm db kbuf ksiz (fromIntegral maxn) >>= peekTCListAndFree

vsizHelper :: (Storable a) =>
              FunVsiz p -> UnLifter tcdb p -> tcdb -> a -> IO (Maybe Int)
vsizHelper c_vsiz unlifter tcdb key =
    withForeignPtr (unlifter tcdb) $ \db ->
        withPtrLen key $ \(kbuf, ksiz) -> do
          vsize <- c_vsiz db kbuf ksiz
          return $ if vsize == -1
                     then Nothing
                     else Just (fromIntegral vsize)