    {-# LINE 1 "Database/TokyoCabinet/TDB/C.hsc" #-}
    {-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}
    {-# LINE 2 "Database/TokyoCabinet/TDB/C.hsc" #-}
    module Database.TokyoCabinet.TDB.C where

    import Data.Int
    import Data.Word
    import Data.Bits

    import Foreign.Ptr
    import Foreign.ForeignPtr
    import Foreign.C.Types
    import Foreign.C.String

    import Database.TokyoCabinet.Map.C
    import Database.TokyoCabinet.List.C

    {-# LINE 17 "Database/TokyoCabinet/TDB/C.hsc" #-}

    -- | Represents open mode
    data OpenMode =
        OREADER | -- ^ read only mode
        OWRITER | -- ^ write mode
        OCREAT  | -- ^ if this value is included in open mode list, `open
                  -- function' creates a new database if not exist.
        OTRUNC  | -- ^ creates a new database regardless if one exists
        ONOLCK  | -- ^ open the database file without file locking
        OLCKNB  | -- ^ open the database file with locking performed
                  -- without blocking.
        OTSYNC    -- ^ every transaction synchronizes updated contents
                  -- with the device
        deriving (Eq, Ord, Show)

    data TuningOption =
        TLARGE   |
        TDEFLATE |
        TBZIP    |
        TTCBS    |
        TEXCODEC
        deriving (Eq, Ord, Show)

    -- | Represents the index type
    data IndexType =
        ITLEXICAL | -- ^ for lexical string
        ITDECIMAL | -- ^ for decimal string
        ITOPT     | -- ^ the index is optimized
        ITVOID    | -- ^ the index is removed
        ITKEEP IndexType -- ^ if the index exists, setindex function merely returns failure
        deriving (Eq, Ord, Show)

    openModeToCInt :: OpenMode -> CInt
    openModeToCInt OREADER = 1
    {-# LINE 51 "Database/TokyoCabinet/TDB/C.hsc" #-}
    openModeToCInt OWRITER = 2
    {-# LINE 52 "Database/TokyoCabinet/TDB/C.hsc" #-}
    openModeToCInt OCREAT  = 4
    {-# LINE 53 "Database/TokyoCabinet/TDB/C.hsc" #-}
    openModeToCInt OTRUNC  = 8
    {-# LINE 54 "Database/TokyoCabinet/TDB/C.hsc" #-}
    openModeToCInt ONOLCK  = 16
    {-# LINE 55 "Database/TokyoCabinet/TDB/C.hsc" #-}
    openModeToCInt OLCKNB  = 32
    {-# LINE 56 "Database/TokyoCabinet/TDB/C.hsc" #-}
    openModeToCInt OTSYNC  = 64
    {-# LINE 57 "Database/TokyoCabinet/TDB/C.hsc" #-}

    tuningOptionToWord8 :: TuningOption -> Word8
    tuningOptionToWord8 TLARGE   = 1
    {-# LINE 60 "Database/TokyoCabinet/TDB/C.hsc" #-}
    tuningOptionToWord8 TDEFLATE = 2
    {-# LINE 61 "Database/TokyoCabinet/TDB/C.hsc" #-}
    tuningOptionToWord8 TBZIP    = 4
    {-# LINE 62 "Database/TokyoCabinet/TDB/C.hsc" #-}
    tuningOptionToWord8 TTCBS    = 8
    {-# LINE 63 "Database/TokyoCabinet/TDB/C.hsc" #-}
    tuningOptionToWord8 TEXCODEC = 16
    {-# LINE 64 "Database/TokyoCabinet/TDB/C.hsc" #-}

    indexTypeToCInt :: IndexType -> CInt
    indexTypeToCInt ITLEXICAL = 0
    {-# LINE 67 "Database/TokyoCabinet/TDB/C.hsc" #-}
    indexTypeToCInt ITDECIMAL = 1
    {-# LINE 68 "Database/TokyoCabinet/TDB/C.hsc" #-}
    indexTypeToCInt ITOPT     = 9998
    {-# LINE 69 "Database/TokyoCabinet/TDB/C.hsc" #-}
    indexTypeToCInt ITVOID    = 9999
    {-# LINE 70 "Database/TokyoCabinet/TDB/C.hsc" #-}
    indexTypeToCInt (ITKEEP ixt) = (16777216) .|. (indexTypeToCInt ixt)
    {-# LINE 71 "Database/TokyoCabinet/TDB/C.hsc" #-}

    combineOpenMode :: [OpenMode] -> CInt
    combineOpenMode = foldr ((.|.) . openModeToCInt) 0

    combineTuningOption :: [TuningOption] -> Word8
    combineTuningOption = foldr ((.|.) . tuningOptionToWord8) 0

    data TDB = TDB { unTCTDB :: !(ForeignPtr TDB') }

    data TDB'

    foreign import ccall safe "tctdbnew"
      c_tctdbnew :: IO (Ptr TDB')

    foreign import ccall safe "tctdbdel"
      c_tctdbdel :: Ptr TDB' -> IO ()

    foreign import ccall safe "&tctdbdel"
      tctdbFinalizer :: FunPtr (Ptr TDB' -> IO ())

    foreign import ccall safe "tctdbecode"
      c_tctdbecode :: Ptr TDB' -> IO CInt

    foreign import ccall safe "tctdbsetmutex"
      c_tctdbsetmutex :: Ptr TDB' -> IO Bool

    foreign import ccall safe "tctdbtune"
      c_tctdbtune :: Ptr TDB' -> Int64 -> Int8 -> Int8 -> Word8 -> IO Bool

    foreign import ccall safe "tctdbsetcache"
      c_tctdbsetcache :: Ptr TDB' -> Int32 -> Int32 -> Int32 -> IO Bool

    foreign import ccall safe "tctdbsetxmsiz"
      c_tctdbsetxmsiz :: Ptr TDB' -> Int64 -> IO Bool

    foreign import ccall safe "tctdbopen"
      c_tctdbopen :: Ptr TDB' -> CString -> CInt -> IO Bool

    foreign import ccall safe "tctdbclose"
      c_tctdbclose :: Ptr TDB' -> IO Bool

    foreign import ccall safe "tctdbput"
      c_tctdbput :: Ptr TDB' -> Ptr Word8 -> CInt -> Ptr MAP -> IO Bool

    foreign import ccall safe "tctdbput2"
      c_tctdbput2 :: Ptr TDB' -> Ptr Word8 -> CInt -> Ptr Word8 -> CInt -> IO Bool

    foreign import ccall safe "tctdbput3"
      c_tctdbput3 :: Ptr TDB' -> CString -> CString -> IO Bool

    foreign import ccall safe "tctdbputkeep"
      c_tctdbputkeep :: Ptr TDB' -> Ptr Word8 -> CInt -> Ptr MAP -> IO Bool

    foreign import ccall safe "tctdbputkeep2"
      c_tctdbputkeep2 :: Ptr TDB' -> Ptr Word8 -> CInt -> Ptr Word8 -> CInt -> IO Bool

    foreign import ccall safe "tctdbputkeep3"
      c_tctdbputkeep3 :: Ptr TDB' -> CString -> CString -> IO Bool

    foreign import ccall safe "tctdbputcat"
      c_tctdbputcat :: Ptr TDB' -> Ptr Word8 -> CInt -> Ptr MAP -> IO Bool

    foreign import ccall safe "tctdbputcat2"
      c_tctdbputcat2 :: Ptr TDB' -> Ptr Word8 -> CInt -> Ptr Word8 -> CInt -> IO Bool

    foreign import ccall safe "tctdbputcat3"
      c_tctdbputcat3 :: Ptr TDB' -> CString -> CString -> IO Bool

    foreign import ccall safe "tctdbout"
      c_tctdbout :: Ptr TDB' -> Ptr Word8 -> CInt -> IO Bool

    foreign import ccall safe "tctdbout2"
      c_tctdbout2 :: Ptr TDB' -> CString -> IO Bool

    foreign import ccall safe "tctdbget"
      c_tctdbget :: Ptr TDB' -> Ptr Word8 -> CInt -> IO (Ptr MAP)

    foreign import ccall safe "tctdbget2"
      c_tctdbget2 :: Ptr TDB' -> Ptr Word8 -> CInt -> Ptr CInt -> IO (Ptr Word8)

    foreign import ccall safe "tctdbget3"
      c_tctdbget3 :: Ptr TDB' -> CString -> IO CString

    foreign import ccall safe "tctdbvsiz"
      c_tctdbvsiz :: Ptr TDB' -> Ptr Word8 -> CInt -> IO CInt

    foreign import ccall safe "tctdbvsiz2"
      c_tctdbvsiz2 :: Ptr TDB' -> CString -> IO CInt

    foreign import ccall safe "tctdbiterinit"
      c_tctdbiterinit :: Ptr TDB' -> IO Bool

    foreign import ccall safe "tctdbiternext"
      c_tctdbiternext :: Ptr TDB' -> Ptr CInt -> IO (Ptr Word8)

    foreign import ccall safe "tctdbiternext2"
      c_tctdbiternext2 :: Ptr TDB' -> IO CString

    foreign import ccall safe "tctdbfwmkeys"
      c_tctdbfwmkeys :: Ptr TDB' -> Ptr Word8 -> CInt -> CInt -> IO (Ptr LIST)

    foreign import ccall safe "tctdbfwmkeys2"
      c_tctdbfwmkeys2 :: Ptr TDB' -> CString -> CInt -> IO (Ptr LIST)

    foreign import ccall safe "tctdbaddint"
      c_tctdbaddint :: Ptr TDB' -> Ptr Word8 -> CInt -> CInt -> IO CInt

    foreign import ccall safe "tctdbadddouble"
      c_tctdbadddouble :: Ptr TDB' -> Ptr Word8 -> CInt -> CDouble -> IO CDouble

    foreign import ccall safe "tctdbsync"
      c_tctdbsync :: Ptr TDB' -> IO Bool

    foreign import ccall safe "tctdboptimize"
      c_tctdboptimize :: Ptr TDB' -> Int64 -> Int8 -> Int8 -> Word8 -> IO Bool

    foreign import ccall safe "tctdbvanish"
      c_tctdbvanish :: Ptr TDB' -> IO Bool

    foreign import ccall safe "tctdbcopy"
      c_tctdbcopy :: Ptr TDB' -> CString -> IO Bool

    foreign import ccall safe "tctdbtranbegin"
      c_tctdbtranbegin :: Ptr TDB' -> IO Bool

    foreign import ccall safe "tctdbtrancommit"
      c_tctdbtrancommit :: Ptr TDB' -> IO Bool

    foreign import ccall safe "tctdbtranabort"
      c_tctdbtranabort :: Ptr TDB' -> IO Bool

    foreign import ccall safe "tctdbpath"
      c_tctdbpath :: Ptr TDB' -> IO CString

    foreign import ccall safe "tctdbrnum"
      c_tctdbrnum :: Ptr TDB' -> IO Word64

    foreign import ccall safe "tctdbfsiz"
      c_tctdbfsiz :: Ptr TDB' -> IO Word64

    foreign import ccall safe "tctdbsetindex"
      c_tctdbsetindex :: Ptr TDB' -> CString -> CInt -> IO Bool

    foreign import ccall safe "tctdbgenuid"
      c_tctdbgenuid :: Ptr TDB' -> IO Int64