2015-07-27 23:20:20 +00:00
|
|
|
#include <stdio.h>
|
2014-09-29 19:17:35 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "pool.h"
|
|
|
|
|
2015-07-03 00:03:07 +00:00
|
|
|
#define POOL_WIDTH 256
|
|
|
|
|
2015-08-20 21:27:39 +00:00
|
|
|
static int hash(const char *s) {
|
2015-07-03 00:03:07 +00:00
|
|
|
int h = 0;
|
|
|
|
for (; *s; s++) {
|
|
|
|
h = h * 37 + *s;
|
|
|
|
}
|
|
|
|
h = h & 0xFF;
|
|
|
|
return h;
|
|
|
|
}
|
|
|
|
|
2015-08-20 21:50:26 +00:00
|
|
|
struct pool_val *pool(struct pool *p, const char *s, int type) {
|
2015-07-03 00:03:07 +00:00
|
|
|
int h = hash(s);
|
|
|
|
struct pool_val **v = &(p->vals[h]);
|
2014-09-29 19:17:35 +00:00
|
|
|
|
|
|
|
while (*v != NULL) {
|
2015-07-03 00:03:07 +00:00
|
|
|
int cmp = strcmp(s, (*v)->s);
|
2014-09-29 19:17:35 +00:00
|
|
|
|
|
|
|
if (cmp == 0) {
|
|
|
|
cmp = type - (*v)->type;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cmp == 0) {
|
|
|
|
return *v;
|
|
|
|
} else if (cmp < 0) {
|
|
|
|
v = &((*v)->left);
|
|
|
|
} else {
|
|
|
|
v = &((*v)->right);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-19 20:26:47 +00:00
|
|
|
struct pool_val *nv = malloc(sizeof(struct pool_val));
|
|
|
|
if (nv == NULL) {
|
2015-07-27 23:20:20 +00:00
|
|
|
fprintf(stderr, "out of memory making string pool\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2015-10-19 20:26:47 +00:00
|
|
|
nv->left = NULL;
|
|
|
|
nv->right = NULL;
|
|
|
|
nv->next = NULL;
|
|
|
|
nv->s = s;
|
|
|
|
nv->type = type;
|
|
|
|
nv->n = p->n++;
|
2014-09-29 19:17:35 +00:00
|
|
|
|
|
|
|
if (p->tail != NULL) {
|
2015-10-19 20:26:47 +00:00
|
|
|
p->tail->next = nv;
|
2014-09-29 19:17:35 +00:00
|
|
|
}
|
2015-10-19 20:26:47 +00:00
|
|
|
p->tail = nv;
|
2014-09-29 19:17:35 +00:00
|
|
|
if (p->head == NULL) {
|
2015-10-19 20:26:47 +00:00
|
|
|
p->head = nv;
|
2014-09-29 19:17:35 +00:00
|
|
|
}
|
|
|
|
|
2015-10-19 20:26:47 +00:00
|
|
|
*v = nv;
|
2014-09-29 19:17:35 +00:00
|
|
|
return *v;
|
|
|
|
}
|
|
|
|
|
2015-08-20 21:27:39 +00:00
|
|
|
int is_pooled(struct pool *p, const char *s, int type) {
|
2015-07-03 00:03:07 +00:00
|
|
|
int h = hash(s);
|
|
|
|
struct pool_val **v = &(p->vals[h]);
|
2014-09-29 19:17:35 +00:00
|
|
|
|
|
|
|
while (*v != NULL) {
|
|
|
|
int cmp = strcmp(s, (*v)->s);
|
|
|
|
|
|
|
|
if (cmp == 0) {
|
|
|
|
cmp = type - (*v)->type;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cmp == 0) {
|
|
|
|
return 1;
|
|
|
|
} else if (cmp < 0) {
|
|
|
|
v = &((*v)->left);
|
|
|
|
} else {
|
|
|
|
v = &((*v)->right);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-10-01 17:33:22 +00:00
|
|
|
void pool_free1(struct pool *p, void (*func)(void *)) {
|
2014-09-29 19:17:35 +00:00
|
|
|
while (p->head != NULL) {
|
2014-10-01 17:33:22 +00:00
|
|
|
if (func != NULL) {
|
2015-08-20 21:50:26 +00:00
|
|
|
func((void *) p->head->s);
|
2014-10-01 17:33:22 +00:00
|
|
|
}
|
|
|
|
|
2014-09-29 19:17:35 +00:00
|
|
|
struct pool_val *next = p->head->next;
|
|
|
|
free(p->head);
|
|
|
|
p->head = next;
|
|
|
|
}
|
|
|
|
|
|
|
|
p->head = NULL;
|
|
|
|
p->tail = NULL;
|
2015-07-03 00:03:07 +00:00
|
|
|
|
|
|
|
free(p->vals);
|
2014-09-29 19:17:35 +00:00
|
|
|
p->vals = NULL;
|
|
|
|
}
|
|
|
|
|
2014-10-01 17:33:22 +00:00
|
|
|
void pool_free(struct pool *p) {
|
|
|
|
pool_free1(p, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pool_free_strings(struct pool *p) {
|
|
|
|
pool_free1(p, free);
|
|
|
|
}
|
|
|
|
|
2014-09-29 19:17:35 +00:00
|
|
|
void pool_init(struct pool *p, int n) {
|
|
|
|
p->n = n;
|
2015-07-03 00:03:07 +00:00
|
|
|
p->vals = calloc(POOL_WIDTH, sizeof(struct pool_val *));
|
2015-07-27 23:20:20 +00:00
|
|
|
if (p->vals == NULL) {
|
|
|
|
fprintf(stderr, "out of memory creating string pool\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2014-09-29 19:17:35 +00:00
|
|
|
p->head = NULL;
|
|
|
|
p->tail = NULL;
|
|
|
|
}
|