tinycdb-python

1. create shared library for tinycdb (libcdb) in codeblocks.

2. create Komodo edit proiect for tinycdb-python (http://code.google.com/p/tinycdb-python/)

(3. Another python-cdb project: http://code.google.com/p/python-pure-cdb/)

tinycdb.py

# coding: utf-8

'''

python bind for tinycdb

author: zhaoweikid

date: 2009-12-14

site: http://code.google.com/p/tinycdb-python

'''

import os, sys

import ctypes

from ctypes import *

from ctypes.util import find_library

if sys.platform == 'win32':

    cdblib = cdll.LoadLibrary("libcdb.dll")

else:

    cdblib = cdll.LoadLibrary("/home/barnix/cpp/tinycdb/cdblib_so/bin/Release/libcdblib_so.so")

CDB_PUT_ADD = 0

CDB_FIND = CDB_PUT_ADD

CDB_PUT_REPLACE = 1

CDB_FIND_REMOVE = CDB_PUT_REPLACE

CDB_PUT_INSERT = 2

CDB_PUT_WARN = 3

CDB_PUT_REPLACE0 = 4

CDB_FIND_FILL0 = CDB_PUT_REPLACE0

class cdb (Structure):

    _fields_ = [('cdb_fd', c_int),

                ('cdb_fsize', c_uint),

                ('cdb_dend', c_uint),

                ('cdb_men', c_char_p),

                ('cdb_vpos', c_uint),

                ('cdb_vlen', c_uint),

                ('cdb_kpos', c_uint),

                ('cdb_klen', c_uint)]

class cdb_rec (Structure):

    _fields_ = [('hval', c_uint),

                ('rpos', c_uint)]

class cdb_rl (Structure):

    pass

cdb_rl._fields_ = [('next', POINTER(cdb_rl)),

                ('cnt', c_uint),

                ('rec', cdb_rec * 254)]

class cdb_find (Structure):

    _fields_ = [('cdb_cdbp', POINTER(cdb)),

                ('cdb_hval', c_uint),

                ('cdb_htp', c_char_p),

                ('cdb_htab', c_char_p),

                ('cdb_htend', c_char_p),

                ('cdb_httodo', c_uint),

                ('cdb_key', c_void_p),

                ('cdb_klen', c_uint)]

class cdb_make (Structure):

    _fields_ = [('cdb_fd', c_int),

                ('cdb_dpos', c_uint),

                ('cdb_cdb_rcnt', c_uint),

                ('cdb_cdb_buf', c_ubyte * 4096),

                ('cdb_bpos', POINTER(c_ubyte)),

                ('cdb_rec', POINTER(cdb_rl) * 256)]

cdblib.cdb_make_start.argtypes = [POINTER(cdb_make), c_int]

cdblib.cdb_make_add.argtypes = [POINTER(cdb_make), c_void_p, c_uint, c_void_p, c_uint]

cdblib.cdb_make_put.argtypes = [POINTER(cdb_make), c_void_p, c_uint, c_void_p, c_uint, c_uint]

cdblib.cdb_make_exists.argtypes = [POINTER(cdb_make), c_void_p, c_uint]

cdblib.cdb_make_finish.argtypes = [POINTER(cdb_make)]

cdblib.cdb_findinit.argtypes = [POINTER(cdb_find), POINTER(cdb), c_void_p, c_uint]

cdblib.cdb_findnext.argtypes = [POINTER(cdb_find)]

cdblib.cdb_seqnext.argtypes = [c_uint, POINTER(cdb)]

cdblib.cdb_seek.argtypes  = [c_int, c_void_p, c_uint, POINTER(c_uint)]

cdblib.cdb_bread.argtypes = [c_int, c_void_p, c_int]

cdblib.cdb_init.argtypes = [POINTER(cdb), c_int]

cdblib.cdb_free.argtypes = [POINTER(cdb)]

cdblib.cdb_read.argtypes = [POINTER(cdb), c_void_p, c_uint, c_uint]

cdblib.cdb_get.argtypes  = [POINTER(cdb), c_uint, c_uint]

cdblib.cdb_find.argtypes = [POINTER(cdb), c_void_p, c_uint]

cdblib.cdb_hash.argtypes = [c_void_p, c_uint]

cdblib.cdb_unpack.argtypes = [POINTER(c_ubyte)]

cdblib.cdb_pack.argtypes = [c_uint, POINTER(c_ubyte)]

def cdb_datapos(c):

    return c.cdb_vpos

def cdb_datalen(c):

    return c.cdb_vlen

def cdb_keypos(c):

    return c.cdb_kpos

def cdb_keylen(c):

    return c.cdb_klen

def cdb_fileno(c):

    return c.cdb_fd

class CDB:

    def __init_(self):

        pass

class Maker:

    def __init__(self, filename):

        self.cdbm = cdb_make()

        self.file = open(filename, 'w')

        self.fd = self.file.fileno()

        cdblib.cdb_make_start(self.cdbm, self.fd)

    def add(self, key, val):

        cdblib.cdb_make_add(self.cdbm, key, len(key), val, len(val))

    def put(self, key, val, flags):

        cdblib.cdb_make_put(self.cdbm, key, len(key), val, len(val), flags)

    def __setitem__(self, key, val):

        cdblib.cdb_make_add(self.cdbm, key, len(key), val, len(val))

    def finish(self):

        cdblib.cdb_make_finish(self.cdbm)

    def close(self):

        self.finish()

class Finder:

    def __init__(self, filename):

        self.file = open(filename, 'r')

        self.fd = self.file.fileno()

        self.cdb = cdb()

        cdblib.cdb_init(self.cdb, self.fd)

    def __getitem__(self, key):

        ret = self.find(key)

        if ret is None:

            raise IndexError, 'not found ' + key

        return ret

    def find(self, key):

        ret = cdblib.cdb_find(self.cdb, key, len(key))

        if ret > 0:

            vpos = cdb_datapos(self.cdb)

            vlen = cdb_datalen(self.cdb)

            buf = (c_char * vlen)()

            val = cast(buf, c_void_p)

            cdblib.cdb_read(self.cdb, val, vlen, vpos)

            return buf.value

        else:

            return None

    def findall(self, key):

        retv = []

        finder = cdb_find()

        cdblib.cdb_findinit(finder, self.cdb, key, len(key))

        while cdblib.cdb_findnext(finder) > 0:

            vpos = cdb_datapos(self.cdb)

            vlen = cdb_datalen(self.cdb)

            buf = (c_char * vlen)()

            val = cast(buf, c_void_p)

            cdblib.cdb_read(self.cdb, val, vlen, vpos)

            retv.append(buf.value)

        return retv

    def seek(self, key):

        vlen = c_uint()

        ret = cdblib.cdb_seek(self.fd, key, len(key), vlen)

        if ret > 0:

            buf = (c_char * vlen.value)()

            val = cast(buf, c_void_p)

            cdblib.cdb_bread(self.fd, val, vlen.value)

            return buf.value

        else:

            return None

    def close(self):

        cdblib.cdb_free(self.cdb)

        self.file.close()

def test_make():

    m = Maker('test.db')

    for i in xrange(1, 100000):

        #m.add('zhaoweikid' + str(i%5000), 'testinfoiiiiiiiiiiiiiiiii'+str(i))

        m['zhaoweikid' + str(i%5000)] = 'testinfoiiiiiiiiiiiiiiiii'+str(i)

    #m.finish()

    m.close()

def test_find():

    import time, random

    f = Finder('test.db')

    print 'seek:', f.seek('zhaoweikid0')

    start = time.time()

    for i in xrange(1, 100):

        #a = f.find('zhaoweikid' + str(random.randint(0,100)))

        a = f['zhaoweikid' + str(random.randint(0,100))]

    end = time.time()

    print 'find time:', end-start, a

    start = time.time()

    for i in xrange(1, 100):

        a = f.findall('zhaoweikid2')

    end = time.time()

    print 'findall time:', end-start

    start = time.time()

    try:

        a = f['zzzzzz']

    except Exception, e:

        end = time.time()

        print 'find zzzzzz error:',

        print e

    else:

        end = time.time()

    print 'find time:', end-start

    f.close()

if __name__ == '__main__':

    test_make()

    test_find()