mirror of https://github.com/nealey/irc-bot
Working cdbm(ake) program
This commit is contained in:
parent
3b6dd727e8
commit
47bf8f7fbd
|
@ -0,0 +1,131 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h> // XXX: remove if malloc() is gone
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
hash(char *s, size_t len)
|
||||||
|
{
|
||||||
|
uint32_t h = 5381;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i += 1) {
|
||||||
|
h = ((h << 5) + h) ^ s[i];
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
write_u32le(FILE *f, uint32_t val)
|
||||||
|
{
|
||||||
|
fputc((val >> 0) & 0xff, f);
|
||||||
|
fputc((val >> 8) & 0xff, f);
|
||||||
|
fputc((val >> 16) & 0xff, f);
|
||||||
|
fputc((val >> 24) & 0xff, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct record {
|
||||||
|
uint32_t hashval;
|
||||||
|
uint32_t offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct record *records[256] = {0};
|
||||||
|
uint32_t nrecords[256] = {0};
|
||||||
|
FILE *f = fopen("a.cdb", "wb");
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
// Start writing records
|
||||||
|
fseek(f, 256*4*2, SEEK_SET);
|
||||||
|
|
||||||
|
while (! feof(stdin)) {
|
||||||
|
int ret;
|
||||||
|
char key[4098];
|
||||||
|
char val[4098];
|
||||||
|
uint32_t keylen;
|
||||||
|
uint32_t vallen;
|
||||||
|
|
||||||
|
// Read a record
|
||||||
|
ret = scanf("+%u,%u:", &keylen, &vallen);
|
||||||
|
if (ret == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((keylen > sizeof(key)) || (vallen > sizeof(val))) {
|
||||||
|
fprintf(stderr, "error: my buffers are too puny (%d,%d)\n", keylen, vallen);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
fread(key, 1, keylen, stdin);
|
||||||
|
getchar();
|
||||||
|
getchar();
|
||||||
|
fread(val, 1, vallen, stdin);
|
||||||
|
getchar();
|
||||||
|
|
||||||
|
// Comupute hash of key
|
||||||
|
{
|
||||||
|
long where = ftell(f);
|
||||||
|
uint32_t hashval = hash(key, keylen);
|
||||||
|
uint32_t n;
|
||||||
|
|
||||||
|
idx = hashval % 256;
|
||||||
|
n = nrecords[idx];
|
||||||
|
nrecords[idx] += 1;
|
||||||
|
records[idx] = (struct record *)realloc(records[idx], nrecords[idx] * sizeof(struct record));
|
||||||
|
if (NULL == records[idx]) {
|
||||||
|
perror("realloc records");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
records[idx][n].hashval = hashval;
|
||||||
|
records[idx][n].offset = (uint32_t)where;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write it out
|
||||||
|
write_u32le(f, keylen);
|
||||||
|
write_u32le(f, vallen);
|
||||||
|
fwrite(key, 1, keylen, f);
|
||||||
|
fwrite(val, 1, vallen, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write out tables
|
||||||
|
for (idx = 0; idx < 256; idx += 1) {
|
||||||
|
uint32_t r;
|
||||||
|
long offset;
|
||||||
|
uint32_t tlen = nrecords[idx] * 2;
|
||||||
|
uint32_t *buf;
|
||||||
|
|
||||||
|
// Pointer
|
||||||
|
offset = ftell(f);
|
||||||
|
fseek(f, idx * 8, SEEK_SET);
|
||||||
|
write_u32le(f, (uint32_t)offset);
|
||||||
|
write_u32le(f, tlen);
|
||||||
|
fseek(f, offset, SEEK_SET);
|
||||||
|
|
||||||
|
// Build table in memory
|
||||||
|
buf = (uint32_t *)calloc(tlen * 2, sizeof(uint32_t));
|
||||||
|
if (! buf) {
|
||||||
|
perror("Allocating hash table");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
for (r = 0; r < nrecords[idx]; r += 1) {
|
||||||
|
uint32_t slot = (records[idx][r].hashval / 256) % tlen;
|
||||||
|
|
||||||
|
while (buf[slot * 2] > 0) {
|
||||||
|
slot = (slot + 1) % tlen;
|
||||||
|
}
|
||||||
|
buf[slot*2 + 0] = records[idx][r].hashval;
|
||||||
|
buf[slot*2 + 1] = records[idx][r].offset;
|
||||||
|
}
|
||||||
|
// Write it out
|
||||||
|
for (r = 0; r < tlen; r += 1) {
|
||||||
|
write_u32le(f, buf[r*2 + 0]);
|
||||||
|
write_u32le(f, buf[r*2 + 1]);
|
||||||
|
}
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue