File: stringstore.c

package info (click to toggle)
notion 4.0.2%2Bdfsg-6
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 4,676 kB
  • sloc: ansic: 47,508; sh: 2,096; makefile: 603; perl: 270
file content (153 lines) | stat: -rw-r--r-- 2,619 bytes parent folder | download | duplicates (4)
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);
        }
    }
}