1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Removed sdbm and it tests

This commit is contained in:
Hiroshi SHIBATA 2020-06-18 21:06:20 +09:00
parent adbdf11f94
commit 343ad9eff5
Notes: git 2020-06-19 08:27:13 +09:00
7 changed files with 0 additions and 3006 deletions

View file

@ -1,952 +0,0 @@
/*
* sdbm - ndbm work-alike hashed database library
* based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
* author: oz@nexus.yorku.ca
* status: public domain.
*
* core routines
*/
#include "ruby/ruby.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "sdbm.h"
/*
* sdbm - ndbm work-alike hashed database library
* tuning and portability constructs [not nearly enough]
* author: oz@nexus.yorku.ca
*/
#define BYTESIZ 8
#ifdef BSD42
#define SEEK_SET L_SET
#define memset(s,c,n) bzero((s), (n)) /* only when c is zero */
#define memcpy(s1,s2,n) bcopy((s2), (s1), (n))
#define memcmp(s1,s2,n) bcmp((s1),(s2),(n))
#endif
/*
* important tuning parms (hah)
*/
#ifndef SEEDUPS
#define SEEDUPS 1 /* always detect duplicates */
#endif
#ifndef BADMESS
#define BADMESS 1 /* generate a message for worst case:
cannot make room after SPLTMAX splits */
#endif
/*
* misc
*/
#ifdef DEBUG
#define debug(x) printf x
#else
#define debug(x)
#endif
#ifdef BIG_E
#define GET_SHORT(p, i) (((unsigned)((unsigned char *)(p))[(i)*2] << 8) + (((unsigned char *)(p))[(i)*2 + 1]))
#define PUT_SHORT(p, i, s) (((unsigned char *)(p))[(i)*2] = (unsigned char)((s) >> 8), ((unsigned char *)(p))[(i)*2 + 1] = (unsigned char)(s))
#else
#define GET_SHORT(p, i) ((p)[(i)])
#define PUT_SHORT(p, i, s) ((p)[(i)] = (s))
#endif
/*#include "pair.h"*/
static int fitpair proto((char *, int));
static void putpair proto((char *, datum, datum));
static datum getpair proto((char *, datum));
static int delpair proto((char *, datum));
static int chkpage proto((char *));
static datum getnkey proto((char *, int));
static void splpage proto((char *, char *, long));
#if SEEDUPS
static int duppair proto((char *, datum));
#endif
#include <stdio.h>
#include <stdlib.h>
#ifdef DOSISH
#include <io.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#ifdef BSD42
#include <sys/file.h>
#else
#include <fcntl.h>
/*#include <memory.h>*/
#endif
#ifndef O_BINARY
#define O_BINARY 0
#endif
#include <errno.h>
#ifndef EPERM
#define EPERM EACCES
#endif
#include <string.h>
#ifdef __STDC__
#include <stddef.h>
#endif
#ifndef NULL
#define NULL 0
#endif
/*
* externals
*/
#if !defined(__sun) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(errno)
extern int errno;
#endif
/*
* forward
*/
static int getdbit proto((DBM *, long));
static int setdbit proto((DBM *, long));
static int getpage proto((DBM *, long));
static datum getnext proto((DBM *));
static int makroom proto((DBM *, long, int));
/*
* useful macros
*/
#define bad(x) ((x).dptr == NULL || (x).dsize < 0)
#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
#define ioerr(db) ((db)->flags |= DBM_IOERR)
#define OFF_PAG(off) (long) (off) * PBLKSIZ
#define OFF_DIR(off) (long) (off) * DBLKSIZ
static long masks[] = {
000000000000L, 000000000001L, 000000000003L,
000000000007L, 000000000017L, 000000000037L,
000000000077L, 000000000177L, 000000000377L,
000000000777L, 000000001777L, 000000003777L,
000000007777L, 000000017777L, 000000037777L,
000000077777L, 000000177777L, 000000377777L,
000000777777L, 000001777777L, 000003777777L,
000007777777L, 000017777777L, 000037777777L,
000077777777L, 000177777777L, 000377777777L,
000777777777L, 001777777777L, 003777777777L,
007777777777L, 017777777777L
};
datum nullitem = {NULL, 0};
DBM *
sdbm_open(register char *file, register int flags, register int mode)
{
register DBM *db;
register char *dirname;
register char *pagname;
register size_t n;
if (file == NULL || !*file)
return errno = EINVAL, (DBM *) NULL;
/*
* need space for two separate filenames
*/
n = strlen(file) * 2 + strlen(DIRFEXT) + strlen(PAGFEXT) + 2;
if ((dirname = malloc(n)) == NULL)
return errno = ENOMEM, (DBM *) NULL;
/*
* build the file names
*/
dirname = strcat(strcpy(dirname, file), DIRFEXT);
pagname = strcpy(dirname + strlen(dirname) + 1, file);
pagname = strcat(pagname, PAGFEXT);
db = sdbm_prep(dirname, pagname, flags, mode);
free((char *) dirname);
return db;
}
static int
fd_set_cloexec(int fd)
{
/* MinGW don't have F_GETFD and FD_CLOEXEC. [ruby-core:40281] */
#ifdef F_GETFD
int flags, ret;
flags = fcntl(fd, F_GETFD); /* should not fail except EBADF. */
if (flags == -1) {
return -1;
}
if (2 < fd) {
if (!(flags & FD_CLOEXEC)) {
flags |= FD_CLOEXEC;
ret = fcntl(fd, F_SETFD, flags);
if (ret == -1) {
return -1;
}
}
}
#endif
return 0;
}
DBM *
sdbm_prep(char *dirname, char *pagname, int flags, int mode)
{
register DBM *db;
struct stat dstat;
if ((db = (DBM *) malloc(sizeof(DBM))) == NULL)
return errno = ENOMEM, (DBM *) NULL;
db->pagf = -1;
db->dirf = -1;
db->flags = 0;
db->hmask = 0;
db->blkptr = 0;
db->keyptr = 0;
/*
* adjust user flags so that WRONLY becomes RDWR,
* as required by this package. Also set our internal
* flag for RDONLY.
*/
if (flags & O_WRONLY)
flags = (flags & ~O_WRONLY) | O_RDWR;
if (flags & O_RDONLY)
db->flags = DBM_RDONLY;
/*
* open the files in sequence, and stat the dirfile.
* If we fail anywhere, undo everything, return NULL.
*/
flags |= O_BINARY;
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
if ((db->pagf = open(pagname, flags, mode)) == -1) goto err;
if (fd_set_cloexec(db->pagf) == -1) goto err;
if ((db->dirf = open(dirname, flags, mode)) == -1) goto err;
if (fd_set_cloexec(db->dirf) == -1) goto err;
/*
* need the dirfile size to establish max bit number.
*/
if (fstat(db->dirf, &dstat) == -1) goto err;
/*
* zero size: either a fresh database, or one with a single,
* unsplit data page: dirpage is all zeros.
*/
db->dirbno = (!dstat.st_size) ? 0 : -1;
db->pagbno = -1;
db->maxbno = dstat.st_size * (long) BYTESIZ;
(void) memset(db->pagbuf, 0, PBLKSIZ);
(void) memset(db->dirbuf, 0, DBLKSIZ);
/*
* success
*/
return db;
err:
if (db->pagf != -1)
(void) close(db->pagf);
if (db->dirf != -1)
(void) close(db->dirf);
free((char *) db);
return (DBM *) NULL;
}
void
sdbm_close(register DBM *db)
{
if (db == NULL)
errno = EINVAL;
else {
(void) close(db->dirf);
(void) close(db->pagf);
free((char *) db);
}
}
datum
sdbm_fetch(register DBM *db, datum key)
{
if (db == NULL || bad(key))
return errno = EINVAL, nullitem;
if (getpage(db, exhash(key)))
return getpair(db->pagbuf, key);
return ioerr(db), nullitem;
}
int
sdbm_delete(register DBM *db, datum key)
{
if (db == NULL || bad(key))
return errno = EINVAL, -1;
if (sdbm_rdonly(db))
return errno = EPERM, -1;
if (getpage(db, exhash(key))) {
if (!delpair(db->pagbuf, key))
return -1;
/*
* update the page file
*/
if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
|| write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
return ioerr(db), -1;
return 0;
}
return ioerr(db), -1;
}
int
sdbm_store(register DBM *db, datum key, datum val, int flags)
{
int need;
register long hash;
if (db == NULL || bad(key))
return errno = EINVAL, -1;
if (sdbm_rdonly(db))
return errno = EPERM, -1;
need = key.dsize + val.dsize;
/*
* is the pair too big (or too small) for this database ??
*/
if (need < 0 || need > PAIRMAX)
return errno = EINVAL, -1;
if (getpage(db, (hash = exhash(key)))) {
/*
* if we need to replace, delete the key/data pair
* first. If it is not there, ignore.
*/
if (flags == DBM_REPLACE)
(void) delpair(db->pagbuf, key);
#if SEEDUPS
else if (duppair(db->pagbuf, key))
return 1;
#endif
/*
* if we do not have enough room, we have to split.
*/
if (!fitpair(db->pagbuf, need))
if (!makroom(db, hash, need))
return ioerr(db), -1;
/*
* we have enough room or split is successful. insert the key,
* and update the page file.
*/
(void) putpair(db->pagbuf, key, val);
if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
|| write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
return ioerr(db), -1;
/*
* success
*/
return 0;
}
return ioerr(db), -1;
}
/*
* makroom - make room by splitting the overfull page
* this routine will attempt to make room for SPLTMAX times before
* giving up.
*/
static int
makroom(register DBM *db, long int hash, int need)
{
long newp;
char twin[PBLKSIZ];
#if defined _WIN32
char zer[PBLKSIZ];
long oldtail;
#endif
char *pag = db->pagbuf;
char *new = twin;
register int smax = SPLTMAX;
do {
/*
* split the current page
*/
(void) splpage(pag, new, db->hmask + 1);
/*
* address of the new page
*/
newp = (hash & db->hmask) | (db->hmask + 1);
debug(("newp: %ld\n", newp));
/*
* write delay, read avoidance/cache shuffle:
* select the page for incoming pair: if key is to go to the new page,
* write out the previous one, and copy the new one over, thus making
* it the current page. If not, simply write the new page, and we are
* still looking at the page of interest. current page is not updated
* here, as sdbm_store will do so, after it inserts the incoming pair.
*/
#if defined _WIN32
/*
* Fill hole with 0 if made it.
* (hole is NOT read as 0)
*/
oldtail = lseek(db->pagf, 0L, SEEK_END);
memset(zer, 0, PBLKSIZ);
while (OFF_PAG(newp) > oldtail) {
if (lseek(db->pagf, 0L, SEEK_END) < 0 ||
write(db->pagf, zer, PBLKSIZ) < 0) {
return 0;
}
oldtail += PBLKSIZ;
}
#endif
if (hash & (db->hmask + 1)) {
if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
|| write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
return 0;
db->pagbno = newp;
(void) memcpy(pag, new, PBLKSIZ);
}
else if (lseek(db->pagf, OFF_PAG(newp), SEEK_SET) < 0
|| write(db->pagf, new, PBLKSIZ) < 0)
return 0;
if (!setdbit(db, db->curbit))
return 0;
/*
* see if we have enough room now
*/
if (fitpair(pag, need))
return 1;
/*
* try again... update curbit and hmask as getpage would have
* done. because of our update of the current page, we do not
* need to read in anything. BUT we have to write the current
* [deferred] page out, as the window of failure is too great.
*/
db->curbit = 2 * db->curbit +
((hash & (db->hmask + 1)) ? 2 : 1);
db->hmask |= (db->hmask + 1);
if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
|| write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
return 0;
} while (--smax);
/*
* if we are here, this is real bad news. After SPLTMAX splits,
* we still cannot fit the key. say goodnight.
*/
#if BADMESS
(void) (write(2, "sdbm: cannot insert after SPLTMAX attempts.\n", 44) < 0);
#endif
return 0;
}
/*
* the following two routines will break if
* deletions aren't taken into account. (ndbm bug)
*/
datum
sdbm_firstkey(register DBM *db)
{
if (db == NULL)
return errno = EINVAL, nullitem;
/*
* start at page 0
*/
(void) memset(db->pagbuf, 0, PBLKSIZ);
if (lseek(db->pagf, OFF_PAG(0), SEEK_SET) < 0
|| read(db->pagf, db->pagbuf, PBLKSIZ) < 0)
return ioerr(db), nullitem;
db->pagbno = 0;
db->blkptr = 0;
db->keyptr = 0;
return getnext(db);
}
datum
sdbm_nextkey(register DBM *db)
{
if (db == NULL)
return errno = EINVAL, nullitem;
return getnext(db);
}
/*
* all important binary trie traversal
*/
static int
getpage(register DBM *db, register long int hash)
{
register int hbit;
register long dbit;
register long pagb;
dbit = 0;
hbit = 0;
while (dbit < db->maxbno && getdbit(db, dbit))
dbit = 2 * dbit + ((hash & ((long) 1 << hbit++)) ? 2 : 1);
debug(("dbit: %ld...", dbit));
db->curbit = dbit;
db->hmask = masks[hbit];
pagb = hash & db->hmask;
/*
* see if the block we need is already in memory.
* note: this lookaside cache has about 10% hit rate.
*/
if (pagb != db->pagbno) {
/*
* note: here, we assume a "hole" is read as 0s.
* if not, must zero pagbuf first.
*/
(void) memset(db->pagbuf, 0, PBLKSIZ);
if (lseek(db->pagf, OFF_PAG(pagb), SEEK_SET) < 0
|| read(db->pagf, db->pagbuf, PBLKSIZ) < 0)
return 0;
if (!chkpage(db->pagbuf)) {
return 0;
}
db->pagbno = pagb;
debug(("pag read: %ld\n", pagb));
}
return 1;
}
static int
getdbit(register DBM *db, register long int dbit)
{
register long c;
register long dirb;
c = dbit / BYTESIZ;
dirb = c / DBLKSIZ;
if (dirb != db->dirbno) {
if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
|| read(db->dirf, db->dirbuf, DBLKSIZ) < 0)
return 0;
db->dirbno = dirb;
debug(("dir read: %ld\n", dirb));
}
return db->dirbuf[c % DBLKSIZ] & (1 << (dbit % BYTESIZ));
}
static int
setdbit(register DBM *db, register long int dbit)
{
register long c;
register long dirb;
c = dbit / BYTESIZ;
dirb = c / DBLKSIZ;
if (dirb != db->dirbno) {
if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
|| read(db->dirf, db->dirbuf, DBLKSIZ) < 0)
return 0;
db->dirbno = dirb;
debug(("dir read: %ld\n", dirb));
}
db->dirbuf[c % DBLKSIZ] |= (1 << (dbit % BYTESIZ));
if (dbit >= db->maxbno)
db->maxbno += (long) DBLKSIZ * BYTESIZ;
if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
|| write(db->dirf, db->dirbuf, DBLKSIZ) < 0)
return 0;
return 1;
}
/*
* getnext - get the next key in the page, and if done with
* the page, try the next page in sequence
*/
static datum
getnext(register DBM *db)
{
datum key;
for (;;) {
db->keyptr++;
key = getnkey(db->pagbuf, db->keyptr);
if (key.dptr != NULL)
return key;
/*
* we either run out, or there is nothing on this page..
* try the next one... If we lost our position on the
* file, we will have to seek.
*/
db->keyptr = 0;
if (db->pagbno != db->blkptr++)
if (lseek(db->pagf, OFF_PAG(db->blkptr), SEEK_SET) < 0)
break;
db->pagbno = db->blkptr;
if (read(db->pagf, db->pagbuf, PBLKSIZ) <= 0)
break;
if (!chkpage(db->pagbuf)) {
break;
}
}
return ioerr(db), nullitem;
}
/* pair.c */
/*
* sdbm - ndbm work-alike hashed database library
* based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
* author: oz@nexus.yorku.ca
* status: public domain.
*
* page-level routines
*/
#ifndef BSD42
/*#include <memory.h>*/
#endif
#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
/*
* forward
*/
static int seepair proto((char *, int, char *, int));
/*
* page format:
* +------------------------------+
* ino | n | keyoff | datoff | keyoff |
* +------------+--------+--------+
* | datoff | - - - ----> |
* +--------+---------------------+
* | F R E E A R E A |
* +--------------+---------------+
* | <---- - - - | data |
* +--------+-----+----+----------+
* | key | data | key |
* +--------+----------+----------+
*
* calculating the offsets for free area: if the number
* of entries (ino[0]) is zero, the offset to the END of
* the free area is the block size. Otherwise, it is the
* nth (ino[ino[0]]) entry's offset.
*/
static int
fitpair(char *pag, int need)
{
register int n;
register int off;
register int free;
register short *ino = (short *) pag;
off = ((n = GET_SHORT(ino,0)) > 0) ? GET_SHORT(ino,n) : PBLKSIZ;
free = off - (n + 1) * (int)sizeof(short);
need += 2 * (int)sizeof(short);
debug(("free %d need %d\n", free, need));
return need <= free;
}
static void
putpair(char *pag, datum key, datum val)
{
register int n;
register int off;
register short *ino = (short *) pag;
off = ((n = GET_SHORT(ino,0)) > 0) ? GET_SHORT(ino,n) : PBLKSIZ;
/*
* enter the key first
*/
off -= key.dsize;
if (key.dsize)
(void) memcpy(pag + off, key.dptr, key.dsize);
PUT_SHORT(ino,n + 1,off);
/*
* now the data
*/
off -= val.dsize;
if (val.dsize)
(void) memcpy(pag + off, val.dptr, val.dsize);
PUT_SHORT(ino,n + 2,off);
/*
* adjust item count
*/
PUT_SHORT(ino,0,GET_SHORT(ino,0) + 2);
}
static datum
getpair(char *pag, datum key)
{
register int i;
register int n;
datum val;
register short *ino = (short *) pag;
if ((n = GET_SHORT(ino,0)) == 0)
return nullitem;
if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
return nullitem;
val.dptr = pag + GET_SHORT(ino,i + 1);
val.dsize = GET_SHORT(ino,i) - GET_SHORT(ino,i + 1);
return val;
}
#if SEEDUPS
static int
duppair(char *pag, datum key)
{
register short *ino = (short *) pag;
return GET_SHORT(ino,0) > 0 &&
seepair(pag, GET_SHORT(ino,0), key.dptr, key.dsize) > 0;
}
#endif
static datum
getnkey(char *pag, int num)
{
datum key;
register int off;
register short *ino = (short *) pag;
num = num * 2 - 1;
if (GET_SHORT(ino,0) == 0 || num > GET_SHORT(ino,0))
return nullitem;
off = (num > 1) ? GET_SHORT(ino,num - 1) : PBLKSIZ;
key.dptr = pag + GET_SHORT(ino,num);
key.dsize = off - GET_SHORT(ino,num);
return key;
}
static int
delpair(char *pag, datum key)
{
register int n;
register int i;
register short *ino = (short *) pag;
if ((n = GET_SHORT(ino,0)) == 0)
return 0;
if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
return 0;
/*
* found the key. if it is the last entry
* [i.e. i == n - 1] we just adjust the entry count.
* hard case: move all data down onto the deleted pair,
* shift offsets onto deleted offsets, and adjust them.
* [note: 0 < i < n]
*/
if (i < n - 1) {
register int m;
register char *dst = pag + (i == 1 ? PBLKSIZ : GET_SHORT(ino,i - 1));
register char *src = pag + GET_SHORT(ino,i + 1);
register ptrdiff_t zoo = dst - src;
debug(("free-up %"PRIdPTRDIFF" ", zoo));
/*
* shift data/keys down
*/
m = GET_SHORT(ino,i + 1) - GET_SHORT(ino,n);
#ifdef DUFF
#define MOVB *--dst = *--src
if (m > 0) {
register int loop = (m + 8 - 1) >> 3;
switch (m & (8 - 1)) {
case 0: do {
MOVB; case 7: MOVB;
case 6: MOVB; case 5: MOVB;
case 4: MOVB; case 3: MOVB;
case 2: MOVB; case 1: MOVB;
} while (--loop);
}
}
#else
#ifdef MEMMOVE
memmove(dst-m, src-m, m);
#else
while (m--)
*--dst = *--src;
#endif
#endif
/*
* adjust offset index up
*/
while (i < n - 1) {
PUT_SHORT(ino,i, GET_SHORT(ino,i + 2) + zoo);
i++;
}
}
PUT_SHORT(ino, 0, GET_SHORT(ino, 0) - 2);
return 1;
}
/*
* search for the key in the page.
* return offset index in the range 0 < i < n.
* return 0 if not found.
*/
static int
seepair(char *pag, register int n, register char *key, register int siz)
{
register int i;
register int off = PBLKSIZ;
register short *ino = (short *) pag;
for (i = 1; i < n; i += 2) {
if (siz == off - GET_SHORT(ino,i) &&
memcmp(key, pag + GET_SHORT(ino,i), siz) == 0)
return i;
off = GET_SHORT(ino,i + 1);
}
return 0;
}
static void
splpage(char *pag, char *new, long int sbit)
{
datum key;
datum val;
register int n;
register int off = PBLKSIZ;
char cur[PBLKSIZ];
register short *ino = (short *) cur;
(void) memcpy(cur, pag, PBLKSIZ);
(void) memset(pag, 0, PBLKSIZ);
(void) memset(new, 0, PBLKSIZ);
n = GET_SHORT(ino,0);
for (ino++; n > 0; ino += 2) {
key.dptr = cur + GET_SHORT(ino,0);
key.dsize = off - GET_SHORT(ino,0);
val.dptr = cur + GET_SHORT(ino,1);
val.dsize = GET_SHORT(ino,0) - GET_SHORT(ino,1);
/*
* select the page pointer (by looking at sbit) and insert
*/
(void) putpair((exhash(key) & sbit) ? new : pag, key, val);
off = GET_SHORT(ino,1);
n -= 2;
}
debug(("%d split %d/%d\n", ((short *) cur)[0] / 2,
((short *) new)[0] / 2,
((short *) pag)[0] / 2));
}
/*
* check page sanity:
* number of entries should be something
* reasonable, and all offsets in the index should be in order.
* this could be made more rigorous.
*/
static int
chkpage(char *pag)
{
register int n;
register int off;
register short *ino = (short *) pag;
if ((n = GET_SHORT(ino,0)) < 0 || n > PBLKSIZ / (int)sizeof(short))
return 0;
if (n > 0) {
off = PBLKSIZ;
for (ino++; n > 0; ino += 2) {
if (GET_SHORT(ino,0) > off || GET_SHORT(ino,1) > off ||
GET_SHORT(ino,1) > GET_SHORT(ino,0))
return 0;
off = GET_SHORT(ino,1);
n -= 2;
}
}
return 1;
}
/* hash.c */
/*
* sdbm - ndbm work-alike hashed database library
* based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
* author: oz@nexus.yorku.ca
* status: public domain. keep it that way.
*
* hashing routine
*/
/*
* polynomial conversion ignoring overflows
* [this seems to work remarkably well, in fact better
* then the ndbm hash function. Replace at your own risk]
* use: 65599 nice.
* 65587 even better.
*/
long
sdbm_hash(register char *str, register int len)
{
register unsigned long n = 0;
#ifdef DUFF
#define HASHC n = *str++ + 65599 * n
if (len > 0) {
register int loop = (len + 8 - 1) >> 3;
switch(len & (8 - 1)) {
case 0: do {
HASHC; case 7: HASHC;
case 6: HASHC; case 5: HASHC;
case 4: HASHC; case 3: HASHC;
case 2: HASHC; case 1: HASHC;
} while (--loop);
}
}
#else
while (len--)
n = ((*str++) & 255) + 65587L * n;
#endif
return n;
}

View file

@ -1,331 +0,0 @@
# AUTOGENERATED DEPENDENCIES START
_sdbm.o: $(RUBY_EXTCONF_H)
_sdbm.o: $(arch_hdrdir)/ruby/config.h
_sdbm.o: $(hdrdir)/ruby/internal/anyargs.h
_sdbm.o: $(hdrdir)/ruby/internal/arithmetic.h
_sdbm.o: $(hdrdir)/ruby/internal/arithmetic/char.h
_sdbm.o: $(hdrdir)/ruby/internal/arithmetic/double.h
_sdbm.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
_sdbm.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
_sdbm.o: $(hdrdir)/ruby/internal/arithmetic/int.h
_sdbm.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
_sdbm.o: $(hdrdir)/ruby/internal/arithmetic/long.h
_sdbm.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
_sdbm.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
_sdbm.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
_sdbm.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
_sdbm.o: $(hdrdir)/ruby/internal/arithmetic/short.h
_sdbm.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
_sdbm.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
_sdbm.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
_sdbm.o: $(hdrdir)/ruby/internal/assume.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/artificial.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/cold.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/const.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/constexpr.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/deprecated.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/error.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/forceinline.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/format.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/noalias.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/noexcept.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/noinline.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/nonnull.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/noreturn.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/pure.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/restrict.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/warning.h
_sdbm.o: $(hdrdir)/ruby/internal/attr/weakref.h
_sdbm.o: $(hdrdir)/ruby/internal/cast.h
_sdbm.o: $(hdrdir)/ruby/internal/compiler_is.h
_sdbm.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
_sdbm.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
_sdbm.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
_sdbm.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
_sdbm.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
_sdbm.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
_sdbm.o: $(hdrdir)/ruby/internal/compiler_since.h
_sdbm.o: $(hdrdir)/ruby/internal/config.h
_sdbm.o: $(hdrdir)/ruby/internal/constant_p.h
_sdbm.o: $(hdrdir)/ruby/internal/core.h
_sdbm.o: $(hdrdir)/ruby/internal/core/rarray.h
_sdbm.o: $(hdrdir)/ruby/internal/core/rbasic.h
_sdbm.o: $(hdrdir)/ruby/internal/core/rbignum.h
_sdbm.o: $(hdrdir)/ruby/internal/core/rclass.h
_sdbm.o: $(hdrdir)/ruby/internal/core/rdata.h
_sdbm.o: $(hdrdir)/ruby/internal/core/rfile.h
_sdbm.o: $(hdrdir)/ruby/internal/core/rhash.h
_sdbm.o: $(hdrdir)/ruby/internal/core/robject.h
_sdbm.o: $(hdrdir)/ruby/internal/core/rregexp.h
_sdbm.o: $(hdrdir)/ruby/internal/core/rstring.h
_sdbm.o: $(hdrdir)/ruby/internal/core/rstruct.h
_sdbm.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
_sdbm.o: $(hdrdir)/ruby/internal/ctype.h
_sdbm.o: $(hdrdir)/ruby/internal/dllexport.h
_sdbm.o: $(hdrdir)/ruby/internal/dosish.h
_sdbm.o: $(hdrdir)/ruby/internal/error.h
_sdbm.o: $(hdrdir)/ruby/internal/eval.h
_sdbm.o: $(hdrdir)/ruby/internal/event.h
_sdbm.o: $(hdrdir)/ruby/internal/fl_type.h
_sdbm.o: $(hdrdir)/ruby/internal/gc.h
_sdbm.o: $(hdrdir)/ruby/internal/glob.h
_sdbm.o: $(hdrdir)/ruby/internal/globals.h
_sdbm.o: $(hdrdir)/ruby/internal/has/attribute.h
_sdbm.o: $(hdrdir)/ruby/internal/has/builtin.h
_sdbm.o: $(hdrdir)/ruby/internal/has/c_attribute.h
_sdbm.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
_sdbm.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
_sdbm.o: $(hdrdir)/ruby/internal/has/extension.h
_sdbm.o: $(hdrdir)/ruby/internal/has/feature.h
_sdbm.o: $(hdrdir)/ruby/internal/has/warning.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/array.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/bignum.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/class.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/compar.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/complex.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/cont.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/dir.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/enum.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/enumerator.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/error.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/eval.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/file.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/gc.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/hash.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/io.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/load.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/marshal.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/numeric.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/object.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/parse.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/proc.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/process.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/random.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/range.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/rational.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/re.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/ruby.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/select.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/signal.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/sprintf.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/string.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/struct.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/thread.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/time.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/variable.h
_sdbm.o: $(hdrdir)/ruby/internal/intern/vm.h
_sdbm.o: $(hdrdir)/ruby/internal/interpreter.h
_sdbm.o: $(hdrdir)/ruby/internal/iterator.h
_sdbm.o: $(hdrdir)/ruby/internal/memory.h
_sdbm.o: $(hdrdir)/ruby/internal/method.h
_sdbm.o: $(hdrdir)/ruby/internal/module.h
_sdbm.o: $(hdrdir)/ruby/internal/newobj.h
_sdbm.o: $(hdrdir)/ruby/internal/rgengc.h
_sdbm.o: $(hdrdir)/ruby/internal/scan_args.h
_sdbm.o: $(hdrdir)/ruby/internal/special_consts.h
_sdbm.o: $(hdrdir)/ruby/internal/static_assert.h
_sdbm.o: $(hdrdir)/ruby/internal/stdalign.h
_sdbm.o: $(hdrdir)/ruby/internal/stdbool.h
_sdbm.o: $(hdrdir)/ruby/internal/symbol.h
_sdbm.o: $(hdrdir)/ruby/internal/token_paste.h
_sdbm.o: $(hdrdir)/ruby/internal/value.h
_sdbm.o: $(hdrdir)/ruby/internal/value_type.h
_sdbm.o: $(hdrdir)/ruby/internal/variable.h
_sdbm.o: $(hdrdir)/ruby/internal/warning_push.h
_sdbm.o: $(hdrdir)/ruby/internal/xmalloc.h
_sdbm.o: $(hdrdir)/ruby/assert.h
_sdbm.o: $(hdrdir)/ruby/backward.h
_sdbm.o: $(hdrdir)/ruby/backward/2/assume.h
_sdbm.o: $(hdrdir)/ruby/backward/2/attributes.h
_sdbm.o: $(hdrdir)/ruby/backward/2/bool.h
_sdbm.o: $(hdrdir)/ruby/backward/2/extern.h
_sdbm.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
_sdbm.o: $(hdrdir)/ruby/backward/2/inttypes.h
_sdbm.o: $(hdrdir)/ruby/backward/2/limits.h
_sdbm.o: $(hdrdir)/ruby/backward/2/long_long.h
_sdbm.o: $(hdrdir)/ruby/backward/2/r_cast.h
_sdbm.o: $(hdrdir)/ruby/backward/2/rmodule.h
_sdbm.o: $(hdrdir)/ruby/backward/2/stdalign.h
_sdbm.o: $(hdrdir)/ruby/backward/2/stdarg.h
_sdbm.o: $(hdrdir)/ruby/defines.h
_sdbm.o: $(hdrdir)/ruby/intern.h
_sdbm.o: $(hdrdir)/ruby/missing.h
_sdbm.o: $(hdrdir)/ruby/ruby.h
_sdbm.o: $(hdrdir)/ruby/st.h
_sdbm.o: $(hdrdir)/ruby/subst.h
_sdbm.o: _sdbm.c
_sdbm.o: sdbm.h
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
init.o: $(hdrdir)/ruby/internal/anyargs.h
init.o: $(hdrdir)/ruby/internal/arithmetic.h
init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
init.o: $(hdrdir)/ruby/internal/assume.h
init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
init.o: $(hdrdir)/ruby/internal/attr/artificial.h
init.o: $(hdrdir)/ruby/internal/attr/cold.h
init.o: $(hdrdir)/ruby/internal/attr/const.h
init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
init.o: $(hdrdir)/ruby/internal/attr/error.h
init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
init.o: $(hdrdir)/ruby/internal/attr/format.h
init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
init.o: $(hdrdir)/ruby/internal/attr/noalias.h
init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
init.o: $(hdrdir)/ruby/internal/attr/noinline.h
init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
init.o: $(hdrdir)/ruby/internal/attr/pure.h
init.o: $(hdrdir)/ruby/internal/attr/restrict.h
init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
init.o: $(hdrdir)/ruby/internal/attr/warning.h
init.o: $(hdrdir)/ruby/internal/attr/weakref.h
init.o: $(hdrdir)/ruby/internal/cast.h
init.o: $(hdrdir)/ruby/internal/compiler_is.h
init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
init.o: $(hdrdir)/ruby/internal/compiler_since.h
init.o: $(hdrdir)/ruby/internal/config.h
init.o: $(hdrdir)/ruby/internal/constant_p.h
init.o: $(hdrdir)/ruby/internal/core.h
init.o: $(hdrdir)/ruby/internal/core/rarray.h
init.o: $(hdrdir)/ruby/internal/core/rbasic.h
init.o: $(hdrdir)/ruby/internal/core/rbignum.h
init.o: $(hdrdir)/ruby/internal/core/rclass.h
init.o: $(hdrdir)/ruby/internal/core/rdata.h
init.o: $(hdrdir)/ruby/internal/core/rfile.h
init.o: $(hdrdir)/ruby/internal/core/rhash.h
init.o: $(hdrdir)/ruby/internal/core/robject.h
init.o: $(hdrdir)/ruby/internal/core/rregexp.h
init.o: $(hdrdir)/ruby/internal/core/rstring.h
init.o: $(hdrdir)/ruby/internal/core/rstruct.h
init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
init.o: $(hdrdir)/ruby/internal/ctype.h
init.o: $(hdrdir)/ruby/internal/dllexport.h
init.o: $(hdrdir)/ruby/internal/dosish.h
init.o: $(hdrdir)/ruby/internal/error.h
init.o: $(hdrdir)/ruby/internal/eval.h
init.o: $(hdrdir)/ruby/internal/event.h
init.o: $(hdrdir)/ruby/internal/fl_type.h
init.o: $(hdrdir)/ruby/internal/gc.h
init.o: $(hdrdir)/ruby/internal/glob.h
init.o: $(hdrdir)/ruby/internal/globals.h
init.o: $(hdrdir)/ruby/internal/has/attribute.h
init.o: $(hdrdir)/ruby/internal/has/builtin.h
init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
init.o: $(hdrdir)/ruby/internal/has/extension.h
init.o: $(hdrdir)/ruby/internal/has/feature.h
init.o: $(hdrdir)/ruby/internal/has/warning.h
init.o: $(hdrdir)/ruby/internal/intern/array.h
init.o: $(hdrdir)/ruby/internal/intern/bignum.h
init.o: $(hdrdir)/ruby/internal/intern/class.h
init.o: $(hdrdir)/ruby/internal/intern/compar.h
init.o: $(hdrdir)/ruby/internal/intern/complex.h
init.o: $(hdrdir)/ruby/internal/intern/cont.h
init.o: $(hdrdir)/ruby/internal/intern/dir.h
init.o: $(hdrdir)/ruby/internal/intern/enum.h
init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
init.o: $(hdrdir)/ruby/internal/intern/error.h
init.o: $(hdrdir)/ruby/internal/intern/eval.h
init.o: $(hdrdir)/ruby/internal/intern/file.h
init.o: $(hdrdir)/ruby/internal/intern/gc.h
init.o: $(hdrdir)/ruby/internal/intern/hash.h
init.o: $(hdrdir)/ruby/internal/intern/io.h
init.o: $(hdrdir)/ruby/internal/intern/load.h
init.o: $(hdrdir)/ruby/internal/intern/marshal.h
init.o: $(hdrdir)/ruby/internal/intern/numeric.h
init.o: $(hdrdir)/ruby/internal/intern/object.h
init.o: $(hdrdir)/ruby/internal/intern/parse.h
init.o: $(hdrdir)/ruby/internal/intern/proc.h
init.o: $(hdrdir)/ruby/internal/intern/process.h
init.o: $(hdrdir)/ruby/internal/intern/random.h
init.o: $(hdrdir)/ruby/internal/intern/range.h
init.o: $(hdrdir)/ruby/internal/intern/rational.h
init.o: $(hdrdir)/ruby/internal/intern/re.h
init.o: $(hdrdir)/ruby/internal/intern/ruby.h
init.o: $(hdrdir)/ruby/internal/intern/select.h
init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
init.o: $(hdrdir)/ruby/internal/intern/signal.h
init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
init.o: $(hdrdir)/ruby/internal/intern/string.h
init.o: $(hdrdir)/ruby/internal/intern/struct.h
init.o: $(hdrdir)/ruby/internal/intern/thread.h
init.o: $(hdrdir)/ruby/internal/intern/time.h
init.o: $(hdrdir)/ruby/internal/intern/variable.h
init.o: $(hdrdir)/ruby/internal/intern/vm.h
init.o: $(hdrdir)/ruby/internal/interpreter.h
init.o: $(hdrdir)/ruby/internal/iterator.h
init.o: $(hdrdir)/ruby/internal/memory.h
init.o: $(hdrdir)/ruby/internal/method.h
init.o: $(hdrdir)/ruby/internal/module.h
init.o: $(hdrdir)/ruby/internal/newobj.h
init.o: $(hdrdir)/ruby/internal/rgengc.h
init.o: $(hdrdir)/ruby/internal/scan_args.h
init.o: $(hdrdir)/ruby/internal/special_consts.h
init.o: $(hdrdir)/ruby/internal/static_assert.h
init.o: $(hdrdir)/ruby/internal/stdalign.h
init.o: $(hdrdir)/ruby/internal/stdbool.h
init.o: $(hdrdir)/ruby/internal/symbol.h
init.o: $(hdrdir)/ruby/internal/token_paste.h
init.o: $(hdrdir)/ruby/internal/value.h
init.o: $(hdrdir)/ruby/internal/value_type.h
init.o: $(hdrdir)/ruby/internal/variable.h
init.o: $(hdrdir)/ruby/internal/warning_push.h
init.o: $(hdrdir)/ruby/internal/xmalloc.h
init.o: $(hdrdir)/ruby/assert.h
init.o: $(hdrdir)/ruby/backward.h
init.o: $(hdrdir)/ruby/backward/2/assume.h
init.o: $(hdrdir)/ruby/backward/2/attributes.h
init.o: $(hdrdir)/ruby/backward/2/bool.h
init.o: $(hdrdir)/ruby/backward/2/extern.h
init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
init.o: $(hdrdir)/ruby/backward/2/inttypes.h
init.o: $(hdrdir)/ruby/backward/2/limits.h
init.o: $(hdrdir)/ruby/backward/2/long_long.h
init.o: $(hdrdir)/ruby/backward/2/r_cast.h
init.o: $(hdrdir)/ruby/backward/2/rmodule.h
init.o: $(hdrdir)/ruby/backward/2/stdalign.h
init.o: $(hdrdir)/ruby/backward/2/stdarg.h
init.o: $(hdrdir)/ruby/defines.h
init.o: $(hdrdir)/ruby/intern.h
init.o: $(hdrdir)/ruby/missing.h
init.o: $(hdrdir)/ruby/ruby.h
init.o: $(hdrdir)/ruby/st.h
init.o: $(hdrdir)/ruby/subst.h
init.o: init.c
init.o: sdbm.h
# AUTOGENERATED DEPENDENCIES END

View file

@ -1,5 +0,0 @@
# frozen_string_literal: false
require 'mkmf'
$defs << "-D""BADMESS=0"
create_makefile("sdbm")

File diff suppressed because it is too large Load diff

View file

@ -1,21 +0,0 @@
# frozen_string_literal: true
Gem::Specification.new do |s|
s.name = "sdbm"
s.version = '1.0.0'
s.summary = "Provides a simple file-based key-value store with String keys and values."
s.description = "Provides a simple file-based key-value store with String keys and values."
s.require_path = %w{lib}
s.files = %w{ext/sdbm/_sdbm.c ext/sdbm/extconf.rb ext/sdbm/init.c ext/sdbm/sdbm.h}
s.extensions = ["ext/sdbm/extconf.rb"]
s.required_ruby_version = ">= 2.3.0"
s.authors = ["Yukihiro Matsumoto"]
s.email = ["matz@ruby-lang.org"]
s.homepage = "https://github.com/ruby/sdbm"
s.license = "BSD-2-Clause"
s.add_development_dependency "test-unit"
s.add_development_dependency "rake-compiler"
end

View file

@ -1,86 +0,0 @@
/*
* sdbm - ndbm work-alike hashed database library
* based on Per-Ake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
* author: oz@nexus.yorku.ca
* status: public domain.
*/
#ifndef _SDBM_H_
#define _SDBM_H_
#include <stdio.h>
#define DBLKSIZ 4096
#define PBLKSIZ 1024
#define PAIRMAX 1008 /* arbitrary on PBLKSIZ-N */
#define SPLTMAX 10 /* maximum allowed splits */
/* for a single insertion */
#define DIRFEXT ".dir"
#define PAGFEXT ".pag"
typedef struct {
int dirf; /* directory file descriptor */
int pagf; /* page file descriptor */
int flags; /* status/error flags, see below */
int keyptr; /* current key for nextkey */
off_t maxbno; /* size of dirfile in bits */
long curbit; /* current bit number */
long hmask; /* current hash mask */
long blkptr; /* current block for nextkey */
long blkno; /* current page to read/write */
long pagbno; /* current page in pagbuf */
char pagbuf[PBLKSIZ]; /* page file block buffer */
long dirbno; /* current block in dirbuf */
char dirbuf[DBLKSIZ]; /* directory file block buffer */
} DBM;
#define DBM_RDONLY 0x1 /* data base open read-only */
#define DBM_IOERR 0x2 /* data base I/O error */
/*
* utility macros
*/
#define sdbm_rdonly(db) ((db)->flags & DBM_RDONLY)
#define sdbm_error(db) ((db)->flags & DBM_IOERR)
#define sdbm_clearerr(db) ((db)->flags &= ~DBM_IOERR) /* ouch */
#define sdbm_dirfno(db) ((db)->dirf)
#define sdbm_pagfno(db) ((db)->pagf)
typedef struct {
char *dptr;
int dsize;
} datum;
extern datum nullitem;
#if defined(__STDC__)
#define proto(p) p
#else
#define proto(p) ()
#endif
/*
* flags to sdbm_store
*/
#define DBM_INSERT 0
#define DBM_REPLACE 1
/*
* ndbm interface
*/
extern DBM *sdbm_open proto((char *, int, int));
extern void sdbm_close proto((DBM *));
extern datum sdbm_fetch proto((DBM *, datum));
extern int sdbm_delete proto((DBM *, datum));
extern int sdbm_store proto((DBM *, datum, datum, int));
extern datum sdbm_firstkey proto((DBM *));
extern datum sdbm_nextkey proto((DBM *));
/*
* other
*/
extern DBM *sdbm_prep proto((char *, char *, int, int));
extern long sdbm_hash proto((char *, int));
#endif /* _SDBM_H_ */

View file

@ -1,544 +0,0 @@
# frozen_string_literal: false
require 'test/unit'
require 'tmpdir'
begin
require 'sdbm'
rescue LoadError
end
class TestSDBM < Test::Unit::TestCase
def setup
@tmpdir = Dir.mktmpdir("tmptest_sdbm")
@prefix = "tmptest_sdbm_#{$$}"
@path = "#{@tmpdir}/#{@prefix}_"
assert_instance_of(SDBM, @sdbm = SDBM.new(@path))
end
def teardown
assert_nil(@sdbm.close)
ObjectSpace.each_object(SDBM) do |obj|
obj.close unless obj.closed?
end
FileUtils.remove_entry_secure @tmpdir
end
def check_size(expect, sdbm=@sdbm)
assert_equal(expect, sdbm.size)
n = 0
sdbm.each { n+=1 }
assert_equal(expect, n)
if expect == 0
assert_equal(true, sdbm.empty?)
else
assert_equal(false, sdbm.empty?)
end
end
def test_version
assert(! SDBM.const_defined?(:VERSION))
end
def test_s_new_has_no_block
# SDBM.new ignore the block
foo = true
assert_instance_of(SDBM, sdbm = SDBM.new("#{@tmpdir}/#{@prefix}") { foo = false })
assert_equal(foo, true)
assert_nil(sdbm.close)
end
def test_s_open_no_create
assert_nil(sdbm = SDBM.open("#{@tmpdir}/#{@prefix}", nil))
ensure
sdbm.close if sdbm
end
def test_s_open_with_block
assert_equal(SDBM.open("#{@tmpdir}/#{@prefix}") { :foo }, :foo)
end
=begin
# Is it guaranteed on many OS?
def test_s_open_lock_one_process
# locking on one process
assert_instance_of(SDBM, sdbm = SDBM.open("#{@tmpdir}/#{@prefix}", 0644))
assert_raise(Errno::EWOULDBLOCK) {
begin
SDBM.open("#{@tmpdir}/#{@prefix}", 0644)
rescue Errno::EAGAIN
raise Errno::EWOULDBLOCK
end
}
end
=end
def open_db_child(dbname, *opts)
opts = [0644, *opts].map(&:inspect).join(', ')
args = [EnvUtil.rubybin, "-rsdbm", <<-SRC, dbname]
STDOUT.sync = true
gdbm = SDBM.open(ARGV.shift, #{opts})
puts sdbm.class
gets
SRC
IO.popen(args, "r+") do |f|
dbclass = f.gets
assert_equal("SDBM", dbclass.chomp)
yield
end
end
def test_s_open_nolock
dbname = "#{@tmpdir}/#{@prefix}"
open_db_child(dbname, SDBM::NOLOCK) do
assert_no_exception(Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EACCES) {
SDBM.open(dbname, 0644) {|sdbm|
assert_instance_of(SDBM, sdbm)
}
}
end
p Dir.glob("#{@tmpdir}/#{@prefix}*") if $DEBUG
open_db_child(dbname) do
assert_no_exception(Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EACCES) {
# this test is failed on Cygwin98 (???)
SDBM.open(dbname, 0644, SDBM::NOLOCK) {|sdbm|
assert_instance_of(SDBM, sdbm)
}
}
end
end if defined? SDBM::NOLOCK # sdbm 1.8.0 specific
def test_s_open_error
skip "doesn't support to avoid read access by owner on Windows" if /mswin|mingw/ =~ RUBY_PLATFORM
skip "skipped because root can open anything" if Process.uid == 0
assert_instance_of(SDBM, sdbm = SDBM.open("#{@tmpdir}/#{@prefix}", 0))
assert_raise(Errno::EACCES) {
SDBM.open("#{@tmpdir}/#{@prefix}", 0)
}
sdbm.close
end
def test_close
assert_instance_of(SDBM, sdbm = SDBM.open("#{@tmpdir}/#{@prefix}"))
assert_nil(sdbm.close)
# closed SDBM file
assert_raise(SDBMError) { sdbm.close }
end
def test_aref
assert_equal('bar', @sdbm['foo'] = 'bar')
assert_equal('bar', @sdbm['foo'])
assert_nil(@sdbm['bar'])
end
def test_fetch
assert_equal('bar', @sdbm['foo']='bar')
assert_equal('bar', @sdbm.fetch('foo'))
# key not found
assert_raise(IndexError) {
@sdbm.fetch('bar')
}
# test for `ifnone' arg
assert_equal('baz', @sdbm.fetch('bar', 'baz'))
# test for `ifnone' block
assert_equal('foobar', @sdbm.fetch('bar') {|key| 'foo' + key })
end
def test_aset
num = 0
2.times {|i|
assert_equal('foo', @sdbm['foo'] = 'foo')
assert_equal('foo', @sdbm['foo'])
assert_equal('bar', @sdbm['foo'] = 'bar')
assert_equal('bar', @sdbm['foo'])
num += 1 if i == 0
assert_equal(num, @sdbm.size)
# assign nil
assert_equal('', @sdbm['bar'] = '')
assert_equal('', @sdbm['bar'])
num += 1 if i == 0
assert_equal(num, @sdbm.size)
# empty string
assert_equal('', @sdbm[''] = '')
assert_equal('', @sdbm[''])
num += 1 if i == 0
assert_equal(num, @sdbm.size)
# Integer
assert_equal('200', @sdbm['100'] = '200')
assert_equal('200', @sdbm['100'])
num += 1 if i == 0
assert_equal(num, @sdbm.size)
# Big key and value
assert_equal('y' * 100, @sdbm['x' * 100] = 'y' * 100)
assert_equal('y' * 100, @sdbm['x' * 100])
num += 1 if i == 0
assert_equal(num, @sdbm.size)
}
end
def test_key
assert_equal('bar', @sdbm['foo'] = 'bar')
assert_equal('foo', @sdbm.key('bar'))
assert_nil(@sdbm['bar'])
end
def test_values_at
keys = %w(foo bar baz)
values = %w(FOO BAR BAZ)
@sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
assert_equal(values.reverse, @sdbm.values_at(*keys.reverse))
end
def test_select_with_block
keys = %w(foo bar baz)
values = %w(FOO BAR BAZ)
@sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
ret = @sdbm.select {|k,v|
assert_equal(k.upcase, v)
k != "bar"
}
assert_equal([['baz', 'BAZ'], ['foo', 'FOO']],
ret.sort)
end
def test_length
num = 10
assert_equal(0, @sdbm.size)
num.times {|i|
i = i.to_s
@sdbm[i] = i
}
assert_equal(num, @sdbm.size)
@sdbm.shift
assert_equal(num - 1, @sdbm.size)
end
def test_empty?
assert_equal(true, @sdbm.empty?)
@sdbm['foo'] = 'FOO'
assert_equal(false, @sdbm.empty?)
end
def test_each_pair
n = 0
@sdbm.each_pair { n += 1 }
assert_equal(0, n)
keys = %w(foo bar baz)
values = %w(FOO BAR BAZ)
@sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
n = 0
ret = @sdbm.each_pair {|key, val|
assert_not_nil(i = keys.index(key))
assert_equal(val, values[i])
n += 1
}
assert_equal(keys.size, n)
assert_equal(@sdbm, ret)
end
def test_each_value
n = 0
@sdbm.each_value { n += 1 }
assert_equal(0, n)
keys = %w(foo bar baz)
values = %w(FOO BAR BAZ)
@sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
n = 0
ret = @sdbm.each_value {|val|
assert_not_nil(key = @sdbm.key(val))
assert_not_nil(i = keys.index(key))
assert_equal(val, values[i])
n += 1
}
assert_equal(keys.size, n)
assert_equal(@sdbm, ret)
end
def test_each_key
n = 0
@sdbm.each_key { n += 1 }
assert_equal(0, n)
keys = %w(foo bar baz)
values = %w(FOO BAR BAZ)
@sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
n = 0
ret = @sdbm.each_key {|key|
assert_not_nil(i = keys.index(key))
assert_equal(@sdbm[key], values[i])
n += 1
}
assert_equal(keys.size, n)
assert_equal(@sdbm, ret)
end
def test_keys
assert_equal([], @sdbm.keys)
keys = %w(foo bar baz)
values = %w(FOO BAR BAZ)
@sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
assert_equal(keys.sort, @sdbm.keys.sort)
assert_equal(values.sort, @sdbm.values.sort)
end
def test_values
test_keys
end
def test_shift
assert_nil(@sdbm.shift)
assert_equal(0, @sdbm.size)
keys = %w(foo bar baz)
values = %w(FOO BAR BAZ)
@sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
ret_keys = []
ret_values = []
while ret = @sdbm.shift
ret_keys.push ret[0]
ret_values.push ret[1]
assert_equal(keys.size - ret_keys.size, @sdbm.size)
end
assert_equal(keys.sort, ret_keys.sort)
assert_equal(values.sort, ret_values.sort)
end
def test_delete
keys = %w(foo bar baz)
values = %w(FOO BAR BAZ)
key = keys[1]
assert_nil(@sdbm.delete(key))
assert_equal(0, @sdbm.size)
@sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
assert_equal('BAR', @sdbm.delete(key))
assert_nil(@sdbm[key])
assert_equal(2, @sdbm.size)
assert_nil(@sdbm.delete(key))
end
def test_delete_with_block
key = 'no called block'
@sdbm[key] = 'foo'
assert_equal('foo', @sdbm.delete(key) {|k| k.replace 'called block'; :blockval})
assert_equal(0, @sdbm.size)
key = 'no called block'
assert_equal(:blockval, @sdbm.delete(key) {|k| k.replace 'called block'; :blockval})
assert_equal(0, @sdbm.size)
end
def test_delete_if
v = "0"
100.times {@sdbm[v] = v; v = v.next}
ret = @sdbm.delete_if {|key, val| key.to_i < 50}
assert_equal(@sdbm, ret)
check_size(50, @sdbm)
ret = @sdbm.delete_if {|key, val| key.to_i >= 50}
assert_equal(@sdbm, ret)
check_size(0, @sdbm)
# break
v = "0"
100.times {@sdbm[v] = v; v = v.next}
check_size(100, @sdbm)
n = 0;
@sdbm.delete_if {|key, val|
break if n > 50
n+=1
true
}
assert_equal(51, n)
check_size(49, @sdbm)
@sdbm.clear
# raise
v = "0"
100.times {@sdbm[v] = v; v = v.next}
check_size(100, @sdbm)
n = 0;
begin
@sdbm.delete_if {|key, val|
raise "runtime error" if n > 50
n+=1
true
}
rescue RuntimeError
end
assert_equal(51, n)
check_size(49, @sdbm)
end
def test_reject
v = "0"
100.times {@sdbm[v] = v; v = v.next}
hash = @sdbm.reject {|key, val| key.to_i < 50}
assert_instance_of(Hash, hash)
assert_equal(100, @sdbm.size)
assert_equal(50, hash.size)
hash.each_pair {|key,val|
assert_equal(false, key.to_i < 50)
assert_equal(key, val)
}
hash = @sdbm.reject {|key, val| key.to_i < 100}
assert_instance_of(Hash, hash)
assert_equal(true, hash.empty?)
end
def test_clear
v = "1"
100.times {v = v.next; @sdbm[v] = v}
assert_equal(@sdbm, @sdbm.clear)
# validate SDBM#size
i = 0
@sdbm.each { i += 1 }
assert_equal(@sdbm.size, i)
assert_equal(0, i)
end
def test_invert
v = "0"
100.times {@sdbm[v] = v; v = v.next}
hash = @sdbm.invert
assert_instance_of(Hash, hash)
assert_equal(100, hash.size)
hash.each_pair {|key, val|
assert_equal(key.to_i, val.to_i)
}
end
def test_update
hash = {}
v = "0"
100.times {v = v.next; hash[v] = v}
@sdbm["101"] = "101"
@sdbm.update hash
assert_equal(101, @sdbm.size)
@sdbm.each_pair {|key, val|
assert_equal(key.to_i, val.to_i)
}
end
def test_replace
hash = {}
v = "0"
100.times {v = v.next; hash[v] = v}
@sdbm["101"] = "101"
@sdbm.replace hash
assert_equal(100, @sdbm.size)
@sdbm.each_pair {|key, val|
assert_equal(key.to_i, val.to_i)
}
end
def test_haskey?
assert_equal('bar', @sdbm['foo']='bar')
assert_equal(true, @sdbm.has_key?('foo'))
assert_equal(false, @sdbm.has_key?('bar'))
end
def test_has_value?
assert_equal('bar', @sdbm['foo']='bar')
assert_equal(true, @sdbm.has_value?('bar'))
assert_equal(false, @sdbm.has_value?('foo'))
end
def test_to_a
v = "0"
100.times {v = v.next; @sdbm[v] = v}
ary = @sdbm.to_a
assert_instance_of(Array, ary)
assert_equal(100, ary.size)
ary.each {|key,val|
assert_equal(key.to_i, val.to_i)
}
end
def test_to_hash
v = "0"
100.times {v = v.next; @sdbm[v] = v}
hash = @sdbm.to_hash
assert_instance_of(Hash, hash)
assert_equal(100, hash.size)
hash.each {|key,val|
assert_equal(key.to_i, val.to_i)
}
end
def test_closed
assert_equal(false, @sdbm.closed?)
@sdbm.close
assert_equal(true, @sdbm.closed?)
@sdbm = SDBM.new(@path)
end
def test_readonly
skip "skipped because root can read anything" if /mswin|mingw/ !~ RUBY_PLATFORM && Process.uid == 0
@sdbm["bar"] = "baz"
@sdbm.close
File.chmod(0444, @path + ".dir")
File.chmod(0444, @path + ".pag")
@sdbm = SDBM.new(@path)
assert_raise(SDBMError) { @sdbm["bar"] = "foo" }
assert_raise(SDBMError) { @sdbm.delete("bar") }
assert_raise(SDBMError) { @sdbm.delete_if { true } }
assert_raise(SDBMError) { @sdbm.clear }
assert_nil(@sdbm.store("bar", nil))
end
def test_update2
obj = Object.new
def obj.each_pair
yield []
end
assert_raise(ArgumentError) { @sdbm.update(obj) }
end
end if defined? SDBM