php-src/ext/dba/libcdb/cdb.c

195 lines
4.0 KiB
C
Raw Normal View History

/*
+----------------------------------------------------------------------+
2014-09-19 16:33:14 +00:00
| PHP Version 7 |
+----------------------------------------------------------------------+
2015-01-15 15:27:30 +00:00
| Copyright (c) 1997-2015 The PHP Group |
+----------------------------------------------------------------------+
2006-01-01 12:51:34 +00:00
| 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: |
2006-01-01 12:51:34 +00:00
| 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$ */
/* 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 */
2014-12-13 22:06:14 +00:00
static int cdb_match(struct cdb *c, char *key, unsigned int len, uint32 pos)
{
char buf[32];
unsigned int n;
while (len > 0) {
n = sizeof(buf);
2015-01-03 09:22:58 +00:00
if (n > len)
n = len;
2015-01-03 09:22:58 +00:00
if (cdb_read(c, buf, n, pos) == -1)
return -1;
2015-01-03 09:22:58 +00:00
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;
2007-04-14 11:15:13 +00:00
const unsigned char * b = (unsigned char *)buf;
h = CDB_HASHSTART;
2003-02-26 22:03:55 +00:00
while (len--) {
2006-11-03 19:00:46 +00:00
h = ( h + (h << 5)) ^ (*b++);
}
return h;
}
/* }}} */
/* {{{ cdb_free */
2014-12-13 22:06:14 +00:00
void cdb_free(struct cdb *c)
{
}
/* }}} */
/* {{{ cdb_findstart */
2014-12-13 22:06:14 +00:00
void cdb_findstart(struct cdb *c)
{
c->loop = 0;
}
/* }}} */
/* {{{ cdb_init */
2014-12-13 22:06:14 +00:00
void cdb_init(struct cdb *c, php_stream *fp)
{
2014-12-13 22:06:14 +00:00
cdb_free(c);
cdb_findstart(c);
c->fp = fp;
}
/* }}} */
/* {{{ cdb_read */
2014-12-13 22:06:14 +00:00
int cdb_read(struct cdb *c, char *buf, unsigned int len, uint32 pos)
{
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));
2015-01-03 09:22:58 +00:00
if (r == -1)
return -1;
if (r == 0) {
errno = EPROTO;
return -1;
}
buf += r;
len -= r;
}
return 0;
}
/* }}} */
/* {{{ cdb_findnext */
2014-12-13 22:06:14 +00:00
int cdb_findnext(struct cdb *c, char *key, unsigned int len)
{
char buf[8];
uint32 pos;
uint32 u;
if (!c->loop) {
u = cdb_hash(key, len);
2015-01-03 09:22:58 +00:00
if (cdb_read(c, buf, 8, (u << 3) & 2047) == -1)
return -1;
uint32_unpack(buf + 4,&c->hslots);
2015-01-03 09:22:58 +00:00
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) {
2015-01-03 09:22:58 +00:00
if (cdb_read(c, buf, 8, c->kpos) == -1)
return -1;
uint32_unpack(buf + 4, &pos);
2015-01-03 09:22:58 +00:00
if (!pos)
return 0;
c->loop += 1;
c->kpos += 8;
2015-01-03 09:22:58 +00:00
if (c->kpos == c->hpos + (c->hslots << 3))
c->kpos = c->hpos;
uint32_unpack(buf, &u);
if (u == c->khash) {
2015-01-03 09:22:58 +00:00
if (cdb_read(c, buf, 8, pos) == -1)
return -1;
uint32_unpack(buf, &u);
if (u == len)
2014-12-13 22:06:14 +00:00
switch(cdb_match(c, key, len, pos + 8)) {
case -1:
return -1;
case 1:
uint32_unpack(buf + 4, &c->dlen);
c->dpos = pos + 8 + len;
return 1;
}
}
}
return 0;
}
/* }}} */
/* {{{ cdb_find */
2014-12-13 22:06:14 +00:00
int cdb_find(struct cdb *c, char *key, unsigned int len)
{
2014-12-13 22:06:14 +00:00
cdb_findstart(c);
return cdb_findnext(c, key, len);
}
/* }}} */
/* {{{ cdb_version */
2015-01-03 09:22:58 +00:00
char *cdb_version()
{
return "0.75, $Id$";
}
/* }}} */