HsHyperEstraier-0.3.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 = fmap List (newForeignPtr _close listPtr)
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 ->
fmap fromIntegral (_num listPtr)
(!!) :: 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
fmap catMaybes (mapM (list !!) [0..len])
fromList :: [Strict.ByteString] -> IO List
fromList values
= do list <- newList
mapM_ (push list) values
return list