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 #include "refString.h"
30 #include "nedit_malloc.h"
31 #include <string.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34
35 #define RCS_SIZE 0x10000
36
37 struct rcs;
38
39 struct rcs_stats
40 {
41 int talloc, tshar, tgiveup, tbytes, tbyteshared;
42 };
43
44 struct rcs
45 {
46 struct rcs *next;
47 char *string;
48 int usage;
49 };
50
51 static struct rcs *Rcs[
RCS_SIZE];
52 static struct rcs_stats RcsStats;
53
54 static unsigned const DJB2_SEED = 5381u;
55
56 static unsigned djb2s(
char const* key,
unsigned hash)
57 {
58 char c;
59 while (!!(c = *key++))
60 hash = ((hash <<
5) + hash) ^ c;
61 return hash;
62 }
63
64
65 unsigned StringHashAddr(
const char *key)
66 {
67 return djb2s(key,
DJB2_SEED);
68 }
69
70
71 unsigned StringsHashAddr(
const char** keys)
72 {
73 unsigned hash =
DJB2_SEED;
74 char const* key;
75 while (!!(key = *keys++))
76 hash = djb2s(key, hash);
77 return hash;
78 }
79
80
81
82
83
84
85
86
87 const char *RefStringDup(
const char *str)
88 {
89 unsigned bucket;
90 size_t len;
91 struct rcs *rp;
92 char *newstr;
93
94 if (str ==
NULL)
95 return NULL;
96
97 len = strlen(str);
98
99 RcsStats.talloc++;
100
101
102 bucket = StringHashAddr(str) %
RCS_SIZE;
103 rp = Rcs[bucket];
104 for (; rp; rp = rp->next)
105 if (!strcmp(str, rp->string))
break;
106
107 newstr =
NULL;
108 if (rp)
109 {
110 rp->usage++;
111 newstr = rp->string;
112
113 RcsStats.tshar++;
114 RcsStats.tbyteshared += len;
115 }
116 else
117 {
118 rp = NEditNew(
struct rcs);
119 rp->usage =
1;
120 rp->next = Rcs[bucket];
121 Rcs[bucket] = rp;
122
123 rp->string = (
char*) NEditMalloc(len +
1);
124 memcpy(rp->string, str, len +
1);
125
126 newstr = rp->string;
127 }
128
129 RcsStats.tbytes += len;
130 return newstr;
131 }
132
133
134
135
136
137
138 void RefStringFree(
const char *rcs_str)
139 {
140 int bucket;
141 struct rcs *rp;
142 struct rcs *prev =
NULL;
143
144 if (rcs_str ==
NULL)
145 return;
146
147 bucket = StringHashAddr(rcs_str) %
RCS_SIZE;
148
149
150 for (rp = Rcs[bucket]; rp; rp = rp->next)
151 {
152 if (rcs_str == rp->string)
153 break;
154 prev = rp;
155 }
156
157 if (rp)
158 {
159 rp->usage--;
160
161 if (rp->usage <
0)
162 {
163 fprintf(stderr,
"XNEdit: internal error deallocating shared string.");
164 return;
165 }
166
167 if (rp->usage ==
0)
168 {
169 NEditFree(rp->string);
170 if (prev)
171 prev->next = rp->next;
172 else
173 Rcs[bucket] = rp->next;
174 NEditFree(rp);
175 }
176 }
177 else
178 {
179 fprintf(stderr,
"XNEdit: attempt to free a non-shared string.");
180 return;
181 }
182 }
183
184