1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
|
/* text-tree.c
*
* Storage of reference counted text strings
* used by keyvals.c to store the key/value strings
*/
#define _GNU_SOURCE
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include "text-tree.h"
struct tree_context *tree_ctx = NULL;
int text_compare(const void *pa, const void *pb, void *rb_param)
{
struct text_node *a = (struct text_node *)pa;
struct text_node *b = (struct text_node *)pb;
rb_param = NULL;
return strcmp(a->str, b->str);
}
struct tree_context *text_init(void)
{
struct tree_context *context;
struct rb_table *table = rb_create (text_compare, NULL, NULL);
assert(table);
context = calloc(1, sizeof(*context));
assert(context);
context->table = table;
tree_ctx = context;
return context;
}
void text_free(void *pa, void *rb_param)
{
struct text_node *a = (struct text_node *)pa;
rb_param = NULL;
free(a->str);
free(a);
}
const char *text_get(struct tree_context *context, const char *text)
{
struct text_node *node, *dupe;
node = malloc(sizeof(*node));
assert(node);
node->str = strdup(text);
assert(node->str);
node->ref = 0;
dupe = rb_insert(context->table, (void *)node);
if (dupe) {
free(node->str);
free(node);
dupe->ref++;
return dupe->str;
} else {
node->ref++;
return node->str;
}
}
void text_release(struct tree_context *context, const char *text)
{
struct text_node *node, find;
find.str = (char *)text;
find.ref = 0;
node = rb_find(context->table, (void *)&find);
if (!node) {
fprintf(stderr, "failed to find '%s'\n", text);
return;
}
node->ref--;
if (!node->ref) {
rb_delete (context->table, &find);
free(node->str);
free(node);
}
}
void text_exit(void)
{
struct tree_context *context = tree_ctx;
rb_destroy(context->table, text_free);
free(context);
tree_ctx = NULL;
}
#if 0
int main(int argc, char **argv)
{
struct tree_context *ctx = text_init();
printf("%1$p %1$s\n", text_get(ctx, "Hello"));
printf("%1$p %1$s\n", text_get(ctx, "Hello"));
printf("%1$p %1$s\n", text_get(ctx, "World"));
text_release(ctx,"Hello");
text_release(ctx,"Hello");
text_release(ctx,"World");
text_release(ctx,"Hello");
text_exit(ctx);
return 0;
}
#endif
|