packages feed

HsHyperEstraier-0.2: Database/QDBM/Cabin/List.hs

{-# OPTIONS_GHC -optc-D__GLASGOW_HASKELL__=606 #-}
{-# LINE 1 "Database/QDBM/Cabin/List.hsc" #-}
module Database.QDBM.Cabin.List
{-# LINE 2 "Database/QDBM/Cabin/List.hsc" #-}
    ( List
    , CBLIST

    , wrapList
    , withListPtr

    , newList
    , push
    , length
    , (!!)

    , toList
    , fromList
    )
    where

import qualified Data.ByteString as BS
import           Data.ByteString.Base
import           Data.Maybe
import           Foreign.C.Types
import           Foreign.ForeignPtr
import           Foreign.Ptr
import           Foreign.Storable
import           Foreign.Marshal.Alloc
import           Prelude hiding (length, (!!))


infixl 9 !!


newtype List = List (ForeignPtr CBLIST)
data CBLIST


foreign import ccall unsafe "cabin.h cblistopen"
        _open :: IO (Ptr CBLIST)

foreign import ccall unsafe "cabin.h &cblistclose"
        _close :: FunPtr (Ptr CBLIST -> IO ())

foreign import ccall unsafe "cabin.h cblistnum"
        _num :: Ptr CBLIST -> IO CInt

foreign import ccall unsafe "cabin.h cblistval"
        _val :: Ptr CBLIST -> CInt -> Ptr CInt -> IO (Ptr CChar)

foreign import ccall unsafe "cabin.h cblistpush"
        _push :: Ptr CBLIST -> Ptr CChar -> CInt -> IO ()


wrapList :: Ptr CBLIST -> IO List
wrapList listPtr = newForeignPtr _close listPtr >>= return . List


withListPtr :: List -> (Ptr CBLIST -> IO a) -> IO a
withListPtr (List list) = withForeignPtr list


newList :: IO List
newList = _open >>= wrapList


push :: List -> ByteString -> IO ()
push list value
    = withListPtr        list  $ \ listPtr              ->
      BS.useAsCStringLen value $ \ (valuePtr, valueLen) ->
      _push listPtr valuePtr (fromIntegral valueLen)


length :: List -> IO Int
length list
    = withListPtr list $ \ listPtr ->
      _num listPtr >>= return . fromIntegral


(!!) :: List -> Int -> IO (Maybe ByteString)
list !! index
    = withListPtr list $ \ listPtr   ->
      alloca           $ \ valLenPtr ->
      do valPtr <- _val listPtr (fromIntegral index) valLenPtr
         if valPtr == nullPtr then
             return Nothing
           else
             do valLen <- peek valLenPtr
                value  <- BS.copyCStringLen (valPtr, fromIntegral valLen)
                return $ Just value


toList :: List -> IO [ByteString]
toList list
    = do len <- length list
         mapM (list !!) [0..len] >>= return . catMaybes


fromList :: [ByteString] -> IO List
fromList values
    = do list <- newList
         mapM_ (push list) values
         return list