HsHyperEstraier-0.2: Database/QDBM/Cabin/List.hsc
module Database.QDBM.Cabin.List
( List
, CBLIST
, wrapList
, withListPtr
, newList
, push
, length
, (!!)
, toList
, fromList
)
where
import qualified Data.ByteString as Strict (ByteString)
import qualified Data.ByteString.Char8 as C8 hiding (ByteString)
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 -> Strict.ByteString -> IO ()
push list value
= withListPtr list $ \ listPtr ->
C8.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 Strict.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 <- C8.packCStringLen (valPtr, fromIntegral valLen)
return $ Just value
toList :: List -> IO [Strict.ByteString]
toList list
= do len <- length list
mapM (list !!) [0..len] >>= return . catMaybes
fromList :: [Strict.ByteString] -> IO List
fromList values
= do list <- newList
mapM_ (push list) values
return list