1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#![allow(non_camel_case_types)]
#![allow(dead_code)]

extern crate libc;

use libc::{c_int, c_uchar, c_uint, c_void};

#[repr(C)]
pub struct cdb {
    // File descriptor
    pub cdb_fd: c_int,

    // Datafile size
    cdb_fsize: c_uint,

    // End of data ptr
    cdb_dend: c_uint,

    // mmap'ed file memory
    cdb_mem: *const c_uchar,

    // Found data
    cdb_vpos: c_uint,
    cdb_vlen: c_uint,

    // Found key
    cdb_kpos: c_uint,
    cdb_klen: c_uint,
}

// Macros defined in C
impl cdb {
    #[inline]
    pub fn cdb_datapos(&self) -> c_uint {
        self.cdb_vpos
    }

    #[inline]
    pub fn cdb_datalen(&self) -> c_uint {
        self.cdb_vlen
    }

    #[inline]
    pub fn cdb_keypos(&self) -> c_uint {
        self.cdb_kpos
    }

    #[inline]
    pub fn cdb_keylen(&self) -> c_uint {
        self.cdb_klen
    }
}

#[repr(C)]
pub struct cdb_find {
    cdb_cdbp: *mut cdb,
    cdb_hval: c_uint,
    cdb_htp: *const c_uchar,
    cdb_htab: *const c_uchar,
    cdb_htend: *const c_uchar,
    cdb_httodo: c_uint,
    cdb_key: *const c_void,
    cdb_klen: c_uint,
}

#[repr(C)]
pub struct cdb_make {
    // File descriptor
    pub cdb_fd: c_int,

    // Data position so far
    cdb_dpos: c_uint,

    // Record count so far
    cdb_rcnt: c_uint,

    // Write buffer
    cdb_buf: [c_uchar; 4096],

    // Current buf position
    cdb_bpos: *mut c_uchar,

    // List of arrays of record infos
    // OLD: cdb_rl*
    cdb_rec: [*mut c_void; 256],
}

/**
 * `CdbPutMode` represents the different behaviours that will be used when
 * inserting a key into a database where the key already exists.
 */
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum CdbPutMode {
    /**
     * No duplicate checking will be performed.  This is the same as just
     * calling `CdbCreator.add()`.
     */
    Add      = 0,

    /**
     * If the key already exists in the database, it will be removed prior
     * to adding the new value.  This can be quite slow if the file is
     * large, due to having to copy data around.
     */
    Replace  = 1,

    /**
     * Insert the key into the database only if the key does not already
     * exist.  Note that since a simple query of the database only returns
     * the first key, this is really only useful to save space in the
     * database.
     */
    Insert   = 2,

    /**
     * Add the key to the database unconditionally, but also check if it
     * already existed.
     *
     * TODO: what return value does put give?
     */
    Warn     = 3,

    /**
     * If the key already exists in the database, zero it out before adding
     * this key/value pair.  See the comments on `CdbCreator.remove()` for some
     * caveats regarding zeroing out keys in the database.
     */
    Replace0 = 4,
}

#[repr(C)]
pub enum CdbFindMode {
    Find   = 0,     // == CDB_PUT_ADD
    Remove = 1,     // == CDB_PUT_REPLACE
    Fill0  = 4,     // == CDB_PUT_REPLACE0
}

extern "C" {
    pub fn cdb_init(cdbp: *mut cdb, fd: c_int) -> c_int;
    pub fn cdb_free(cdbp: *mut cdb);
    pub fn cdb_read(cdbp: *const cdb, buf: *mut c_void, len: c_uint, pos: c_uint) -> c_int;
    pub fn cdb_get(cdbp: *const cdb, len: c_uint, pos: c_uint) -> *const c_void;

    pub fn cdb_find(cdbp: *mut cdb, key: *const c_void, klen: c_uint) -> c_int;
    pub fn cdb_findinit(cdbfp: *mut cdb_find, cdb: *mut cdb, key: *const c_void, klen: c_uint) -> c_int;
    pub fn cdb_findnext(cdbfp: *mut cdb_find) -> c_int;

    pub fn cdb_make_start(cdbmp: *mut cdb_make, fd: c_int) -> c_int;
    pub fn cdb_make_add(cdbmp: *mut cdb_make, key: *const c_void, klen: c_uint, val: *const c_void, vlen: c_uint) -> c_int;
    pub fn cdb_make_exists(cdbmp: *mut cdb_make, key: *const c_void, klen: c_uint) -> c_int;
    pub fn cdb_make_find(cdbmp: *mut cdb_make, key: *const c_void, klen: c_uint, mode: CdbFindMode) -> c_int;
    pub fn cdb_make_put(cdbmp: *mut cdb_make, key: *const c_void, klen: c_uint, val: *const c_void, vlen: c_uint, mode: CdbPutMode) -> c_int;
    pub fn cdb_make_finish(cdbmp: *mut cdb_make) -> c_int;

    pub fn cdb_seqnext(cptr: *mut c_uint, cdbp: *mut cdb) -> c_int;
}

// A C macro
pub unsafe fn cdb_seqinit(cptr: *mut c_uint, _cdbp: *mut cdb) {
    *cptr = 2048;
}