diff options
Diffstat (limited to 'ext/dba/libcdb/cdb.c')
-rw-r--r-- | ext/dba/libcdb/cdb.c | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/ext/dba/libcdb/cdb.c b/ext/dba/libcdb/cdb.c new file mode 100644 index 0000000..2b101f8 --- /dev/null +++ b/ext/dba/libcdb/cdb.c @@ -0,0 +1,194 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2013 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Marcus Boerger <helly@php.net> | + +----------------------------------------------------------------------+ + */ + +/* $Id: bc4ee08831fe552aab0f3fdce506f7b734dde461 $ */ + +/* incorporated from D.J.Bernstein's cdb-0.75 (http://cr.yp.to/cdb.html)*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" + +#include <sys/types.h> +#include <sys/stat.h> +#ifndef PHP_WIN32 +#include <sys/mman.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <string.h> +#include <errno.h> +#include "cdb.h" + +#ifndef EPROTO +# define EPROTO -15 /* cdb 0.75's default for PROTOless systems */ +#endif + +/* {{{ cdb_match */ +static int cdb_match(struct cdb *c, char *key, unsigned int len, uint32 pos TSRMLS_DC) +{ + char buf[32]; + unsigned int n; + + while (len > 0) { + n = sizeof(buf); + if (n > len) + n = len; + if (cdb_read(c, buf, n, pos TSRMLS_CC) == -1) + return -1; + if (memcmp(buf, key, n)) + return 0; + pos += n; + key += n; + len -= n; + } + return 1; +} +/* }}} */ + +/* {{{ cdb_hash */ +uint32 cdb_hash(char *buf, unsigned int len) +{ + uint32 h; + const unsigned char * b = (unsigned char *)buf; + + h = CDB_HASHSTART; + while (len--) { + h = ( h + (h << 5)) ^ (*b++); + } + return h; +} +/* }}} */ + +/* {{{ cdb_free */ +void cdb_free(struct cdb *c TSRMLS_DC) +{ +} +/* }}} */ + +/* {{{ cdb_findstart */ +void cdb_findstart(struct cdb *c TSRMLS_DC) +{ + c->loop = 0; +} +/* }}} */ + +/* {{{ cdb_init */ +void cdb_init(struct cdb *c, php_stream *fp TSRMLS_DC) +{ + cdb_free(c TSRMLS_CC); + cdb_findstart(c TSRMLS_CC); + c->fp = fp; +} +/* }}} */ + +/* {{{ cdb_read */ +int cdb_read(struct cdb *c, char *buf, unsigned int len, uint32 pos TSRMLS_DC) +{ + if (php_stream_seek(c->fp, pos, SEEK_SET) == -1) { + errno = EPROTO; + return -1; + } + while (len > 0) { + int r; + do { + r = php_stream_read(c->fp, buf, len); + } while ((r == -1) && (errno == EINTR)); + if (r == -1) + return -1; + if (r == 0) { + errno = EPROTO; + return -1; + } + buf += r; + len -= r; + } + return 0; +} +/* }}} */ + +/* {{{ cdb_findnext */ +int cdb_findnext(struct cdb *c, char *key, unsigned int len TSRMLS_DC) +{ + char buf[8]; + uint32 pos; + uint32 u; + + if (!c->loop) { + u = cdb_hash(key, len); + if (cdb_read(c, buf, 8, (u << 3) & 2047 TSRMLS_CC) == -1) + return -1; + uint32_unpack(buf + 4,&c->hslots); + if (!c->hslots) + return 0; + uint32_unpack(buf, &c->hpos); + c->khash = u; + u >>= 8; + u %= c->hslots; + u <<= 3; + c->kpos = c->hpos + u; + } + + while (c->loop < c->hslots) { + if (cdb_read(c, buf, 8, c->kpos TSRMLS_CC) == -1) + return -1; + uint32_unpack(buf + 4, &pos); + if (!pos) + return 0; + c->loop += 1; + c->kpos += 8; + if (c->kpos == c->hpos + (c->hslots << 3)) + c->kpos = c->hpos; + uint32_unpack(buf, &u); + if (u == c->khash) { + if (cdb_read(c, buf, 8, pos TSRMLS_CC) == -1) + return -1; + uint32_unpack(buf, &u); + if (u == len) + switch(cdb_match(c, key, len, pos + 8 TSRMLS_CC)) { + case -1: + return -1; + case 1: + uint32_unpack(buf + 4, &c->dlen); + c->dpos = pos + 8 + len; + return 1; + } + } + } + + return 0; +} +/* }}} */ + +/* {{{ cdb_find */ +int cdb_find(struct cdb *c, char *key, unsigned int len TSRMLS_DC) +{ + cdb_findstart(c TSRMLS_CC); + return cdb_findnext(c, key, len TSRMLS_CC); +} +/* }}} */ + +/* {{{ cdb_version */ +char *cdb_version() +{ + return "0.75, $Id: bc4ee08831fe552aab0f3fdce506f7b734dde461 $"; +} +/* }}} */ |