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 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
/*
* libtu/stringstore.c
*
* Copyright (c) Tuomo Valkonen 2004-2007.
*
* You may distribute and modify this library under the terms of either
* the Clarified Artistic License or the GNU LGPL, version 2.1 or later.
*/
#include <stdlib.h>
#include <string.h>
#include "misc.h"
#include "output.h"
#include "rb.h"
#include "stringstore.h"
static Rb_node stringstore=NULL;
const char *stringstore_get(StringId id)
{
return (id==STRINGID_NONE
? NULL
: (const char*)(((Rb_node)id)->k.key));
}
typedef struct{
const char *key;
uint len;
} D;
static int cmp(const void *d_, const char *nodekey)
{
D *d=(D*)d_;
int res=strncmp(d->key, nodekey, d->len);
return (res!=0
? res
: (nodekey[d->len]=='\0' ? 0 : -1));
}
StringId stringstore_find_n(const char *str, uint l)
{
Rb_node node;
int found=0;
D d;
if(stringstore==NULL)
return STRINGID_NONE;
d.key=str;
d.len=l;
node=rb_find_gkey_n(stringstore, &d, (Rb_compfn*)cmp, &found);
if(!found)
return STRINGID_NONE;
return (StringId)node;
}
StringId stringstore_find(const char *str)
{
return stringstore_find_n(str, strlen(str));
}
StringId stringstore_alloc_n(const char *str, uint l)
{
Rb_node node=(Rb_node)stringstore_find_n(str, l);
char *s;
if(node!=NULL){
node->v.ival++;
return node;
}
if(stringstore==NULL){
stringstore=make_rb();
if(stringstore==NULL)
return STRINGID_NONE;
}
s=scopyn(str, l);
if(s==NULL)
return STRINGID_NONE;
node=rb_insert(stringstore, s, NULL);
if(node==NULL)
return STRINGID_NONE;
node->v.ival=1;
return (StringId)node;
}
StringId stringstore_alloc(const char *str)
{
if(str==NULL)
return STRINGID_NONE;
return stringstore_alloc_n(str, strlen(str));
}
void stringstore_free(StringId id)
{
Rb_node node=(Rb_node)id;
if(node==NULL)
return;
if(node->v.ival<=0){
warn("Stringstore reference count corrupted.");
return;
}
node->v.ival--;
if(node->v.ival==0){
char *s=(char*)(node->k.key);
rb_delete_node(node);
free(s);
}
}
void stringstore_ref(StringId id)
{
Rb_node node=(Rb_node)id;
if(node!=NULL)
node->v.ival++;
}
void stringstore_deinit(void) {
if(stringstore!=NULL){
Rb_node node;
while ((node=rb_first(stringstore))!=rb_nil(stringstore)) {
node->v.ival = 1;
stringstore_free((StringId)node);
}
}
}
|