LyogYXV0aG9yOiBEYW5pZWwgSGlsc3QgKi8gCgovKj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSoKICogICAgSEFTSCBUQUJMRSBJTVBMRU1FTlRBVElPTiAgICAqCiAqPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ki8KCiNpbmNsdWRlICZxdW90O2hhc2guaCZxdW90OwoKc3RhdGljIHZvaWQgKgp4bWFsbG9jIChzaXplX3Qgc2l6KQp7Cgl2b2lkICpuID0gbWFsbG9jIChzaXopOwoJaWYgKCFuKSB7CgkJcGVycm9yICgmcXVvdDttYWxsb2MmcXVvdDspOwoJCWV4aXQgKEVYSVRfRkFJTFVSRSk7Cgl9CglyZXR1cm4gbjsKfQoKdm9pZAppbml0X2xpc3QgKHN0cnVjdCBsaXN0ICpsKQp7CglsLSZndDtmaXJzdCA9IGwtJmd0O2xhc3QgPSBOVUxMOwoJbC0mZ3Q7c2l6ID0gMDsKfQoKaW50CmFkZF9ub2RlIChzdHJ1Y3QgbGlzdCAqbCwgY29uc3QgY2hhciAqaywgY29uc3QgY2hhciAqdikKewoJc3RydWN0IG5vZGUgKm47CglpZiAoIWwgfHwgIWsgfHwgIXYpIHsKCQlmcHJpbnRmIChzdGRlcnIsICZxdW90O2FkZF9ub2RlOiBpbnZhbGlkIHBhcmFldGVyXG4mcXVvdDspOwoJCXJldHVybiAtMTsKCX0KCQoJbiA9IHhtYWxsb2MgKHNpemVvZiAoc3RydWN0IG5vZGUpKTsKCW4tJmd0O25leHQgPSBOVUxMOwoJbi0mZ3Q7ayA9IHhtYWxsb2MgKHN0cmxlbiAoaykgKyAxKTsKCW4tJmd0O3YgPSB4bWFsbG9jIChzdHJsZW4gKHYpICsgMSk7CgltZW1jcHkgKG4tJmd0O2ssIGssIHN0cmxlbiAoaykgKyAxKTsKCW1lbWNweSAobi0mZ3Q7diwgdiwgc3RybGVuICh2KSArIDEpOwoJaWYgKGwtJmd0O3NpeiA9PSAwKSB7CgkJbC0mZ3Q7Zmlyc3QgPSBsLSZndDtsYXN0ID0gbjsKCX0gZWxzZSB7CgkJbC0mZ3Q7bGFzdC0mZ3Q7bmV4dCA9IG47CgkJbC0mZ3Q7bGFzdCA9IG47Cgl9IAoJbC0mZ3Q7c2l6Kys7CglyZXR1cm4gMDsKfQoKaW50CmRlbF9ub2RlIChzdHJ1Y3QgbGlzdCAqbCwgc3RydWN0IG5vZGUgKm4sIHN0cnVjdCBub2RlICpwcmlvcikKewoJaWYgKCFsIHx8ICFuIHx8ICFwcmlvcikgewoJCWZwcmludGYgKHN0ZGVyciwgJnF1b3Q7ZGVsX25vZGU6IGludmFsaWQgcGFyYW1ldGVyXG4mcXVvdDspOwoJCXJldHVybiAtMTsKCX0gZWxzZSBpZiAoIWwtJmd0O3NpeikgewoJCXJldHVybiAxOwoJfSBlbHNlIGlmIChsLSZndDtmaXJzdCA9PSBuKSB7CgkJbC0mZ3Q7Zmlyc3QgPSBsLSZndDtmaXJzdC0mZ3Q7bmV4dDsKCX0gZWxzZSBpZiAobC0mZ3Q7bGFzdCA9PSBuKSB7CgkJbC0mZ3Q7bGFzdCA9IHByaW9yOwoJCWwtJmd0O2xhc3QtJmd0O25leHQgPSBOVUxMOwoJfSBlbHNlIHsKCQlwcmlvci0mZ3Q7bmV4dCA9IG4tJmd0O25leHQ7Cgl9CQkKCWZyZWUgKG4tJmd0O2spOwoJZnJlZSAobi0mZ3Q7dik7CglmcmVlIChuKTsKCWwtJmd0O3Npei0tOwoJcmV0dXJuIDA7Cn0KCmludApmcmVlX2xpc3QgKHN0cnVjdCBsaXN0ICpsKQp7CglpZiAoIWwpIHsKCQlmcHJpbnRmIChzdGRlcnIsICZxdW90O2ZyZWVfbGlzdDogaW52YWxpZCBwYXJhbWV0ZXJzXG4mcXVvdDspOwoJCXJldHVybiAtMTsKCX0KCXdoaWxlICghZGVsX25vZGUgKGwsIGwtJmd0O2ZpcnN0LCBOVUxMKSkKCQk7CglyZXR1cm4gMDsKfQoKc3RydWN0IG5vZGUgKioKc2VhcmNoX25vZGUgKHN0cnVjdCBsaXN0ICpsLCBjb25zdCBjaGFyICprKQp7CglzdHJ1Y3Qgbm9kZSAqKm4gPSB4bWFsbG9jIChzaXplb2YgKHN0cnVjdCBub2RlKSAqIDIpOwoJaWYgKCFsKSB7CgkJZnByaW50ZiAoc3RkZXJyLCAmcXVvdDtzZWFyY2hfbm9kZTogSW52YWxpZCBwYXJhbWV0ZXJcbiZxdW90Oyk7CgkJZXhpdCAoRVhJVF9GQUlMVVJFKTsKCX0KCW5bMF0gPSBsLSZndDtmaXJzdDsKCW5bMV0gPSBOVUxMOyAvKiBwcmlvciBub2RlICovOwoJZm9yICg7IG5bMF07IG5bMV0gPSBuWzBdLCBuWzBdID0gblswXS0mZ3Q7bmV4dCkgewoJCWlmICghc3RyY21wIChuWzBdLSZndDtrLCBrKSkKCQkJcmV0dXJuIG47Cgl9CglyZXR1cm4gTlVMTDsKfQoKCmNoYXIgKgpzZXJpYV9ub2RlIChzdHJ1Y3Qgbm9kZSAqbikKewoJY2hhciAqc2VyLCAqcDsKCWludCBsZW47CglsZW4gPSBzdHJsZW4gKG4tJmd0O2spICsgc3RybGVuIChuLSZndDt2KSArIDI7IC8qIGtleT12YWx1ZVwwKi8KCXNlciA9IHhtYWxsb2MgKGxlbik7CglzdHJuY3B5IChzZXIsIG4tJmd0O2ssIHN0cmxlbiAobi0mZ3Q7aykgKyAxKTsKCXN0cm5jYXQgKHNlciwgJnF1b3Q7PSZxdW90OywgMik7CglzdHJuY2F0IChzZXIsIG4tJmd0O3YsIHN0cmxlbiAobi0mZ3Q7dikgKyAxKTsgCglyZXR1cm4gc2VyOwp9IAoKc3RydWN0IG5vZGUgKgp1bnNlcmlhX25vZGUgKGNvbnN0IGNoYXIgKnNlcikKewoJc3RydWN0IG5vZGUgKm47CgljaGFyICplcTsKCWVxID0gc3RyY2hyIChzZXIsICc9Jyk7CglpZiAoIWVxKSB7CgkJZnByaW50ZiAoc3RkZXJyLCAmcXVvdDt1bnNlcmlhX25vZGU6IEJhZCBwYWlyIGZvcm1hdFxuJnF1b3Q7KTsKCQlleGl0IChFWElUX0ZBSUxVUkUpOwoJfQoJKmVxKysgPSAnXDAnOwoJbiA9IHhtYWxsb2MgKHNpemVvZiAoc3RydWN0IG5vZGUpKTsJCgluLSZndDtrID0geG1hbGxvYyAoc3RybGVuIChzZXIpICsgMSk7CQoJbi0mZ3Q7diA9IHhtYWxsb2MgKHN0cmxlbiAoZXEpICsgMSk7CglzdHJuY3B5IChuLSZndDtrLCBzZXIsIHN0cmxlbiAoc2VyKSArIDEpOwoJc3RybmNweSAobi0mZ3Q7diwgZXEsIHN0cmxlbiAoZXEpICsgMSk7CglyZXR1cm4gbjsKfQoKaW50Cmhhc2hfaW5pdCAoc3RydWN0IGhhc2ggKmgsIGludCBzaXopCnsKCWludCBpOwoJaWYgKCFoIHx8IHNpeiAmbHQ7PSAwKSB7CgkJZnByaW50ZiAoc3RkZXJyLCAmcXVvdDtoYXNoX2luaXQ6IGludmFsaWQgcGFyYW1ldGVyc1xuJnF1b3Q7KTsKCQlleGl0IChFWElUX0ZBSUxVUkUpOwoJfQoJaC0mZ3Q7c2l6ID0gc2l6OwoJaC0mZ3Q7dmVjID0geG1hbGxvYyAoc2l6ICogc2l6ZW9mIChzdHJ1Y3QgbGlzdCkpOwoJZm9yIChpID0gMDsgaSAmbHQ7IGgtJmd0O3NpejsgaSsrKSB7CgkJaW5pdF9saXN0ICgmYW1wO2gtJmd0O3ZlY1tpXSk7Cgl9CglyZXR1cm4gMDsJCn0KCnVuc2lnbmVkCmhhc2hpbmcgKGNvbnN0IGNoYXIgKmspCnsKCXVuc2lnbmVkIGhhc2ggPSAwOwoJZm9yICg7ICprOyBrKyspIAoJCWhhc2ggKz0gKmsgLSAnQSc7CglyZXR1cm4gaGFzaDsKfQkKCQppbnQKaGFzaF9zZXQgKHN0cnVjdCBoYXNoICpoLCBjb25zdCBjaGFyICprLCBjb25zdCBjaGFyICp2KQp7Cgl1bnNpZ25lZCBpbmR4OwoJc3RydWN0IG5vZGUgKipuOwoJaWYgKCFoIHx8ICFrIHx8ICF2KSB7CgkJZnByaW50ZiAoc3RkZXJyLCAmcXVvdDtoYXNoX3NldDogaW52YWxpZCBwYXJhbWV0ZXJzXG4mcXVvdDspOwoJCWV4aXQgKEVYSVRfRkFJTFVSRSk7Cgl9CglpbmR4ID0gaGFzaGluZyAoaykgJSBoLSZndDtzaXo7CgluID0gc2VhcmNoX25vZGUgKCZhbXA7aC0mZ3Q7dmVjW2luZHhdLCBrKTsKCWlmICghbikgewoJCWFkZF9ub2RlICgmYW1wO2gtJmd0O3ZlY1tpbmR4XSwgaywgdik7Cgl9IGVsc2UgewoJCWZyZWUgKG5bMF0tJmd0O3YpOwoJCW5bMF0tJmd0O3YgPSBtYWxsb2MgKHN0cmxlbiAodikgKyAxKTsKCQlzdHJuY3B5IChuWzBdLSZndDt2LCB2LCBzdHJsZW4gKHYpICsgMSk7Cgl9CglmcmVlIChuKTsKCXJldHVybiAwOwp9CgpjaGFyICoKaGFzaF9nZXQgKHN0cnVjdCBoYXNoICpoLCBjb25zdCBjaGFyICprKQp7Cgl1bnNpZ25lZCBpbmR4OwoJc3RydWN0IG5vZGUgKipuOwoJY2hhciAqdjsKCWlmICghaCB8fCAhaykgewoJCWZwcmludGYgKHN0ZGVyciwgJnF1b3Q7aGFzaF9nZXQ6IGludmFsaWQgcGFyYW1ldGVyc1xuJnF1b3Q7KTsKCQlleGl0IChFWElUX0ZBSUxVUkUpOwoJfQoJaW5keCA9IGhhc2hpbmcgKGspICUgaC0mZ3Q7c2l6OwoJbiA9IHNlYXJjaF9ub2RlICgmYW1wO2gtJmd0O3ZlY1tpbmR4XSwgayk7CglpZiAoIW4pIHsKCQlyZXR1cm4gTlVMTDsKCX0gZWxzZSB7CgkJdiA9IHN0cmR1cCAoblswXS0mZ3Q7dik7CgkJZnJlZSAobik7CgkJcmV0dXJuIHY7Cgl9CglmcmVlIChuKTsKCXJldHVybiBOVUxMOwp9CgppbnQKaGFzaF9zYXZlIChzdHJ1Y3QgaGFzaCAqaCwgY29uc3QgY2hhciAqZmlsZSkKewoJRklMRSAqZnA7CglpbnQgaTsKCWNoYXIgKmJ1ZjsKCXN0cnVjdCBub2RlICpuOwoJaWYgKCFoIHx8ICFmaWxlKSB7CgkJZnByaW50ZiAoc3RkZXJyLCAmcXVvdDtoYXNoX3NhdmU6IEludmFsaWQgcGFyYW1ldGVyc1xuJnF1b3Q7KTsKCQlleGl0IChFWElUX0ZBSUxVUkUpOwoJfQoJCglpZiAoIShmcCA9IGZvcGVuIChmaWxlLCAmcXVvdDt3JnF1b3Q7KSkpIHsKCQlwZXJyb3IgKCZxdW90O2ZvcGVuJnF1b3Q7KTsKCQlleGl0IChFWElUX0ZBSUxVUkUpOwoJfQoKCWZvciAoaSA9IDA7IGkgJmx0OyBoLSZndDtzaXo7IGkrKykgewoJCWZvciAobiA9IGgtJmd0O3ZlY1tpXS5maXJzdDsgbjsgbiA9IG4tJmd0O25leHQpIHsKCQkJYnVmID0gc2VyaWFfbm9kZSAobik7CgkJCWZ3cml0ZSAoYnVmLCBzdHJsZW4gKGJ1ZiksIDEsIGZwKTsKCQkJZnB1dGMgKCdcbicsIGZwKTsKCQkJZnJlZSAoYnVmKTsKCQl9Cgl9CglmY2xvc2UgKGZwKTsKCXJldHVybiAwOwp9CgppbnQKaGFzaF9sb2FkIChzdHJ1Y3QgaGFzaCAqaCwgY29uc3QgY2hhciAqZmlsZSkKewoJaW50IGksIGxlbjsgCglzdHJ1Y3Qgbm9kZSAqbjsKCUZJTEUgKmZwOwoJY2hhciBidWZbMHg0MDBdOwoJY2hhciBlcTsKCWlmICghaCB8fCAhZmlsZSkgewoJCWZwcmludGYgKHN0ZGVyciwgJnF1b3Q7aGFzaF9sb2FkOiBpbnZhbGlkIHBhcmFtZXRlcnNcbiZxdW90Oyk7CgkJZXhpdCAoRVhJVF9GQUlMVVJFKTsKCX0KCglpZiAoIShmcCA9IGZvcGVuIChmaWxlLCAmcXVvdDtyJnF1b3Q7KSkpIHsKCQlwZXJyb3IgKCZxdW90O2ZvcGVuJnF1b3Q7KTsKCQlleGl0IChFWElUX0ZBSUxVUkUpOwoJfQoKCXdoaWxlIChmZ2V0cyAoYnVmLCAweDQwMCwgZnApKSB7CgkJYnVmW3N0cmxlbiAoYnVmKSAtIDFdID0gJ1wwJzsgIC8qIGNob3AgdGhlIGZnZXRzIG5ldyBsaW5lICovCgkJbiA9IHVuc2VyaWFfbm9kZSAoYnVmKTsKCQloYXNoX3NldCAoaCwgbi0mZ3Q7aywgbi0mZ3Q7dik7CgkJZnJlZSAobik7Cgl9CglmY2xvc2UgKGZwKTsKfQoKCnZvaWQKaGFzaF9kYmcgKHN0cnVjdCBoYXNoICpoKQp7CglpbnQgaTsKCXN0cnVjdCBub2RlICpuOwoJZm9yIChpID0gMDsgaSAmbHQ7IGgtJmd0O3NpejsgaSsrKSB7CgkJcHJpbnRmICgmcXVvdDsmZ3Q7Jmd0OyAlMDVkICZndDsmZ3Q7XG4mcXVvdDssIGkpOwoJCWlmICghaC0mZ3Q7dmVjW2ldLnNpeikgewoJCQlwdXRzICgmcXVvdDtFTVBUWSBMSVNUJnF1b3Q7KTsKCQl9IGVsc2UgewoJCQlmb3IgKG4gPSBoLSZndDt2ZWNbaV0uZmlyc3Q7IG47IG4gPSBuLSZndDtuZXh0KSB7CgkJCQlwcmludGYgKCZxdW90O25vZGUoICUxMHAgKSBuZXh0KCAlMTBwICkgJXMgPSZndDsgJXNcbiZxdW90Oywgbiwgbi0mZ3Q7bmV4dCwgbi0mZ3Q7aywgbi0mZ3Q7dik7CgkJCX0KCQl9CgkJcHJpbnRmICgmcXVvdDsmbHQ7Jmx0OyAlMDVkICZsdDsmbHQ7XG4mcXVvdDssIGkpOwoJfQp9Cgo=
/* author: Daniel Hilst */
/*=================================*
* HASH TABLE IMPLEMENTATION *
*=================================*/
#include "hash.h"
static void *
xmalloc (size_t siz)
{
void *n = malloc (siz);
if (!n) {
perror ("malloc");
exit (EXIT_FAILURE);
}
return n;
}
void
init_list (struct list *l)
{
l->first = l->last = NULL;
l->siz = 0;
}
int
add_node (struct list *l, const char *k, const char *v)
{
struct node *n;
if (!l || !k || !v) {
fprintf (stderr, "add_node: invalid paraeter\n");
return -1;
}
n = xmalloc (sizeof (struct node));
n->next = NULL;
n->k = xmalloc (strlen (k) + 1);
n->v = xmalloc (strlen (v) + 1);
memcpy (n->k, k, strlen (k) + 1);
memcpy (n->v, v, strlen (v) + 1);
if (l->siz == 0) {
l->first = l->last = n;
} else {
l->last->next = n;
l->last = n;
}
l->siz++;
return 0;
}
int
del_node (struct list *l, struct node *n, struct node *prior)
{
if (!l || !n || !prior) {
fprintf (stderr, "del_node: invalid parameter\n");
return -1;
} else if (!l->siz) {
return 1;
} else if (l->first == n) {
l->first = l->first->next;
} else if (l->last == n) {
l->last = prior;
l->last->next = NULL;
} else {
prior->next = n->next;
}
free (n->k);
free (n->v);
free (n);
l->siz--;
return 0;
}
int
free_list (struct list *l)
{
if (!l) {
fprintf (stderr, "free_list: invalid parameters\n");
return -1;
}
while (!del_node (l, l->first, NULL))
;
return 0;
}
struct node **
search_node (struct list *l, const char *k)
{
struct node **n = xmalloc (sizeof (struct node) * 2);
if (!l) {
fprintf (stderr, "search_node: Invalid parameter\n");
exit (EXIT_FAILURE);
}
n[0] = l->first;
n[1] = NULL; /* prior node */;
for (; n[0]; n[1] = n[0], n[0] = n[0]->next) {
if (!strcmp (n[0]->k, k))
return n;
}
return NULL;
}
char *
seria_node (struct node *n)
{
char *ser, *p;
int len;
len = strlen (n->k) + strlen (n->v) + 2; /* key=value\0*/
ser = xmalloc (len);
strncpy (ser, n->k, strlen (n->k) + 1);
strncat (ser, "=", 2);
strncat (ser, n->v, strlen (n->v) + 1);
return ser;
}
struct node *
unseria_node (const char *ser)
{
struct node *n;
char *eq;
eq = strchr (ser, '=');
if (!eq) {
fprintf (stderr, "unseria_node: Bad pair format\n");
exit (EXIT_FAILURE);
}
*eq++ = '\0';
n = xmalloc (sizeof (struct node));
n->k = xmalloc (strlen (ser) + 1);
n->v = xmalloc (strlen (eq) + 1);
strncpy (n->k, ser, strlen (ser) + 1);
strncpy (n->v, eq, strlen (eq) + 1);
return n;
}
int
hash_init (struct hash *h, int siz)
{
int i;
if (!h || siz <= 0) {
fprintf (stderr, "hash_init: invalid parameters\n");
exit (EXIT_FAILURE);
}
h->siz = siz;
h->vec = xmalloc (siz * sizeof (struct list));
for (i = 0; i < h->siz; i++) {
init_list (&h->vec[i]);
}
return 0;
}
unsigned
hashing (const char *k)
{
unsigned hash = 0;
for (; *k; k++)
hash += *k - 'A';
return hash;
}
int
hash_set (struct hash *h, const char *k, const char *v)
{
unsigned indx;
struct node **n;
if (!h || !k || !v) {
fprintf (stderr, "hash_set: invalid parameters\n");
exit (EXIT_FAILURE);
}
indx = hashing (k) % h->siz;
n = search_node (&h->vec[indx], k);
if (!n) {
add_node (&h->vec[indx], k, v);
} else {
free (n[0]->v);
n[0]->v = malloc (strlen (v) + 1);
strncpy (n[0]->v, v, strlen (v) + 1);
}
free (n);
return 0;
}
char *
hash_get (struct hash *h, const char *k)
{
unsigned indx;
struct node **n;
char *v;
if (!h || !k) {
fprintf (stderr, "hash_get: invalid parameters\n");
exit (EXIT_FAILURE);
}
indx = hashing (k) % h->siz;
n = search_node (&h->vec[indx], k);
if (!n) {
return NULL;
} else {
v = strdup (n[0]->v);
free (n);
return v;
}
free (n);
return NULL;
}
int
hash_save (struct hash *h, const char *file)
{
FILE *fp;
int i;
char *buf;
struct node *n;
if (!h || !file) {
fprintf (stderr, "hash_save: Invalid parameters\n");
exit (EXIT_FAILURE);
}
if (!(fp = fopen (file, "w"))) {
perror ("fopen");
exit (EXIT_FAILURE);
}
for (i = 0; i < h->siz; i++) {
for (n = h->vec[i].first; n; n = n->next) {
buf = seria_node (n);
fwrite (buf, strlen (buf), 1, fp);
fputc ('\n', fp);
free (buf);
}
}
fclose (fp);
return 0;
}
int
hash_load (struct hash *h, const char *file)
{
int i, len;
struct node *n;
FILE *fp;
char buf[0x400];
char eq;
if (!h || !file) {
fprintf (stderr, "hash_load: invalid parameters\n");
exit (EXIT_FAILURE);
}
if (!(fp = fopen (file, "r"))) {
perror ("fopen");
exit (EXIT_FAILURE);
}
while (fgets (buf, 0x400, fp)) {
buf[strlen (buf) - 1] = '\0'; /* chop the fgets new line */
n = unseria_node (buf);
hash_set (h, n->k, n->v);
free (n);
}
fclose (fp);
}
void
hash_dbg (struct hash *h)
{
int i;
struct node *n;
for (i = 0; i < h->siz; i++) {
printf (">> %05d >>\n", i);
if (!h->vec[i].siz) {
puts ("EMPTY LIST");
} else {
for (n = h->vec[i].first; n; n = n->next) {
printf ("node( %10p ) next( %10p ) %s => %s\n", n, n->next, n->k, n->v);
}
}
printf ("<< %05d <<\n", i);
}
}