mirror of
https://github.com/php/php-src.git
synced 2024-10-20 07:53:58 +00:00
195 lines
4.2 KiB
C
195 lines
4.2 KiB
C
/*
|
|
+----------------------------------------------------------------------+
|
|
| PHP Version 5 |
|
|
+----------------------------------------------------------------------+
|
|
| Copyright (c) 1997-2007 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$ */
|
|
|
|
/* 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 = 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, $Revision$";
|
|
}
|
|
/* }}} */
|