diff --git a/infobot.c b/infobot.c new file mode 100644 index 0000000..6fc6823 --- /dev/null +++ b/infobot.c @@ -0,0 +1,142 @@ +#include +#include +#include + +/* Why I am using stdio.h + * By Neale Pickett + * November, 2012 + * + * I am not as clever as the people who maintain libc. + * + * THE END + */ + +/* Some things I use for debugging */ +#ifdef NODUMP +# define DUMPf(fmt, args...) +#else +# define DUMPf(fmt, args...) fprintf(stderr, "%s:%s:%d " fmt "\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#endif +#define DUMP() DUMPf("") +#define DUMP_u(v) DUMPf("%s = %u", #v, v) +#define DUMP_d(v) DUMPf("%s = %d", #v, v) +#define DUMP_x(v) DUMPf("%s = 0x%x", #v, v) +#define DUMP_s(v) DUMPf("%s = %s", #v, v) +#define DUMP_c(v) DUMPf("%s = %c", #v, v) +#define DUMP_p(v) DUMPf("%s = %p", #v, v) + + +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; +} + +int +usage() +{ + fprintf(stderr, "Usage: infobot\n"); + + return 0; +} + +uint32_t +read_u32(FILE *f) +{ + uint8_t d[4]; + + fread(d, 4, 1, f); + return ((d[0]<< 0) | + (d[1] << 8) | + (d[2] << 16) | + (d[3] << 24)); +} + + +int +bufcmp(char *a, size_t alen, char *b, size_t blen) +{ + if (alen == blen) { + return memcmp(a, b, blen); + } else { + return alen - blen; + } +} + +int +lookup(FILE *f, char *key) +{ + size_t keylen = strlen(key); + uint32_t h = hash(key, keylen); + uint32_t p, plen; + uint32_t i; + + /* Read pointer */ + fseek(f, (h % 256) * 8, SEEK_SET); + p = read_u32(f); + plen = read_u32(f); + + /* Read hash table entries */ + for (i = (h / 256) % plen; i < plen; i += 1) { + uint32_t hashval; + uint32_t entry_pos; + uint32_t klen; + uint32_t dlen; + + fseek(f, p + (i * 8), SEEK_SET); + hashval = read_u32(f); + entry_pos = read_u32(f); + if (entry_pos == 0) { + break; + } + if (hashval != h) { + continue; + } + + fseek(f, entry_pos, SEEK_SET); + klen = read_u32(f); + dlen = read_u32(f); + + if (klen == keylen) { + uint32_t i; + + for (i = 0; i < klen; i += 1) { + int c = fgetc(f); + + if (c != key[i]) { + break; + } + } + + if (i < klen) { + continue; + } + + for (i = 0; i < dlen; i += 1) { + int c = fgetc(f); + + putchar(c); + } + } + } + + return 0; +} + + + +int +main(int argc, char *argv[]) +{ + if (1 == argc) { + return usage(); + } + + return lookup(stdin, argv[1]); +}