]> git.decadent.org.uk Git - ion3.git/blob - libtu/stringstore.c
e47c902050a0051b23fc574aa6e83e8d024043e4
[ion3.git] / libtu / stringstore.c
1 /*
2  * libtu/stringstore.c
3  *
4  * Copyright (c) Tuomo Valkonen 2004-2007. 
5  *
6  * You may distribute and modify this library under the terms of either
7  * the Clarified Artistic License or the GNU LGPL, version 2.1 or later.
8  */
9
10 #include <stdlib.h>
11 #include <string.h>
12
13 #include "misc.h"
14 #include "output.h"
15 #include "rb.h"
16 #include "stringstore.h"
17
18
19 static Rb_node stringstore=NULL;
20
21
22 const char *stringstore_get(StringId id)
23 {
24     return (id==STRINGID_NONE
25             ? NULL
26             : (const char*)(((Rb_node)id)->k.key));
27 }
28
29
30 typedef struct{
31     const char *key;
32     uint len;
33 } D;
34
35 static int cmp(const void *d_, const char *nodekey)
36 {
37     D *d=(D*)d_;
38     
39     int res=strncmp(d->key, nodekey, d->len);
40     
41     return (res!=0 
42             ? res 
43             : (nodekey[d->len]=='\0' ? 0 : 1));
44 }
45
46
47 StringId stringstore_find_n(const char *str, uint l)
48 {
49     Rb_node node;
50     int found=0;
51     D d;
52     
53     if(stringstore==NULL)
54         return STRINGID_NONE;
55     
56     d.key=str;
57     d.len=l;
58     
59     node=rb_find_gkey_n(stringstore, &d, (Rb_compfn*)cmp, &found);
60     
61     if(!found)
62         return STRINGID_NONE;
63     
64     return (StringId)node;
65 }
66
67
68 StringId stringstore_find(const char *str)
69 {
70     return stringstore_find_n(str, strlen(str));
71 }
72
73
74 StringId stringstore_alloc_n(const char *str, uint l)
75 {
76     Rb_node node=(Rb_node)stringstore_find_n(str, l);
77     char *s;
78     
79     if(node!=NULL){
80         node->v.ival++;
81         return node;
82     }
83     
84     if(stringstore==NULL){
85         stringstore=make_rb();
86         if(stringstore==NULL)
87             return STRINGID_NONE;
88     }
89     
90     s=scopyn(str, l);
91     
92     if(s==NULL)
93         return STRINGID_NONE;
94     
95     node=rb_insert(stringstore, s, NULL);
96     
97     if(node==NULL)
98         return STRINGID_NONE;
99     
100     node->v.ival=1;
101         
102     return (StringId)node;
103 }
104
105
106 StringId stringstore_alloc(const char *str)
107 {
108     if(str==NULL)
109         return STRINGID_NONE;
110     
111     return stringstore_alloc_n(str, strlen(str));
112 }
113
114
115 void stringstore_free(StringId id)
116 {
117     Rb_node node=(Rb_node)id;
118     
119     if(node==NULL)
120         return;
121     
122     if(node->v.ival<=0){
123         warn("Stringstore reference count corrupted.");
124         return;
125     }
126     
127     node->v.ival--;
128     
129     if(node->v.ival==0){
130         char *s=(char*)(node->k.key);
131         rb_delete_node(node);
132         free(s);
133     }
134 }
135
136
137 void stringstore_ref(StringId id)
138 {
139     Rb_node node=(Rb_node)id;
140     
141     if(node!=NULL)
142         node->v.ival++;
143 }
144