forked from osm2pgsql-dev/osm2pgsql
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtext-tree.c
111 lines (95 loc) · 2.35 KB
/
text-tree.c
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