root / trunk / src / dot / proxy / atom.c

Revision 7618, 8.1 kB (checked in by BradNeuberg, 22 months ago)

Local and remote SVN repositories somehow became out of sync and corrupted -- re-adding these in

Line 
1/*
2Copyright (c) 2003-2006 by Juliusz Chroboczek
3
4Permission is hereby granted, free of charge, to any person obtaining a copy
5of this software and associated documentation files (the "Software"), to deal
6in the Software without restriction, including without limitation the rights
7to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8copies of the Software, and to permit persons to whom the Software is
9furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20THE SOFTWARE.
21*/
22
23#include "polipo.h"
24
25static AtomPtr *atomHashTable;
26int used_atoms;
27
28void
29initAtoms()
30{
31    atomHashTable = calloc((1 << LOG2_ATOM_HASH_TABLE_SIZE),
32                           sizeof(AtomPtr));
33
34    if(atomHashTable == NULL) {
35        do_log(L_ERROR, "Couldn't allocate atom hash table.\n");
36        exit(1);
37    }
38    used_atoms = 0;
39}
40
41AtomPtr
42internAtomN(const char *string, int n)
43{
44    AtomPtr atom;
45    int h;
46
47    if(n < 0 || n >= (1 << (8 * sizeof(unsigned short))))
48        return NULL;
49
50    h = hash(0, string, n, LOG2_ATOM_HASH_TABLE_SIZE);
51    atom = atomHashTable[h];
52    while(atom) {
53        if(atom->length == n &&
54           (n == 0 || memcmp(atom->string, string, n) == 0))
55            break;
56        atom = atom->next;
57    }
58
59    if(!atom) {
60        atom = malloc(sizeof(AtomRec) - 1 + n + 1);
61        if(atom == NULL) {
62            return NULL;
63        }
64        atom->refcount = 0;
65        atom->length = n;
66        /* Atoms are used both for binary data and strings.  To make
67           their use as strings more convenient, atoms are always
68           NUL-terminated. */
69        memcpy(atom->string, string, n);
70        atom->string[n] = '\0';
71        atom->next = atomHashTable[h];
72        atomHashTable[h] = atom;
73        used_atoms++;
74    }
75    do_log(D_ATOM_REFCOUNT, "A 0x%lx %d++\n",
76           (unsigned long)atom, atom->refcount);
77    atom->refcount++;
78    return atom;
79}
80
81AtomPtr
82internAtom(const char *string)
83{
84    return internAtomN(string, strlen(string));
85}
86
87AtomPtr
88atomCat(AtomPtr atom, const char *string)
89{
90    char buf[128];
91    char *s = buf;
92    AtomPtr newAtom;
93    int n = strlen(string);
94    if(atom->length + n > 128) {
95        s = malloc(atom->length + n + 1);
96        if(s == NULL)
97            return NULL;
98    }
99    memcpy(s, atom->string, atom->length);
100    memcpy(s + atom->length, string, n);
101    newAtom = internAtomN(s, atom->length + n);
102    if(s != buf) free(s);
103    return newAtom;
104}
105
106int
107atomSplit(AtomPtr atom, char c, AtomPtr *return1, AtomPtr *return2)
108{
109    char *p;
110    AtomPtr atom1, atom2;
111    p = memchr(atom->string, c, atom->length);
112    if(p == NULL)
113        return 0;
114    atom1 = internAtomN(atom->string, p - atom->string);
115    if(atom1 == NULL)
116        return -ENOMEM;
117    atom2 = internAtomN(p + 1, atom->length - (p + 1 - atom->string));
118    if(atom2 == NULL) {
119        releaseAtom(atom1);
120        return -ENOMEM;
121    }
122    *return1 = atom1;
123    *return2 = atom2;
124    return 1;
125}
126
127AtomPtr
128internAtomLowerN(const char *string, int n)
129{
130    char *s;
131    char buf[100];
132    AtomPtr atom;
133
134    if(n < 0 || n >= 50000)
135        return NULL;
136
137    if(n < 100) {
138        s = buf;
139    } else {
140        s = malloc(n);
141        if(s == NULL)
142            return NULL;
143    }
144
145    lwrcpy(s, string, n);
146    atom = internAtomN(s, n);
147    if(s != buf) free(s);
148    return atom;
149}
150
151AtomPtr
152retainAtom(AtomPtr atom)
153{
154    if(atom == NULL)
155        return NULL;
156
157    do_log(D_ATOM_REFCOUNT, "A 0x%lx %d++\n",
158           (unsigned long)atom, atom->refcount);
159    assert(atom->refcount >= 1 && atom->refcount < 50000);
160    atom->refcount++;
161    return atom;
162}
163
164void
165releaseAtom(AtomPtr atom)
166{
167    if(atom == NULL)
168        return;
169
170    do_log(D_ATOM_REFCOUNT, "A 0x%lx %d--\n",
171           (unsigned long)atom, atom->refcount);
172    assert(atom->refcount >= 1 && atom->refcount < 50000);
173
174    atom->refcount--;
175
176    if(atom->refcount == 0) {
177        int h = hash(0, atom->string, atom->length, LOG2_ATOM_HASH_TABLE_SIZE);
178        assert(atomHashTable[h] != NULL);
179
180        if(atom == atomHashTable[h]) {
181            atomHashTable[h] = atom->next;
182            free(atom);
183        } else {
184            AtomPtr previous = atomHashTable[h];
185            while(previous->next) {
186                if(previous->next == atom)
187                    break;
188                previous = previous->next;
189            }
190            assert(previous->next != NULL);
191            previous->next = atom->next;
192            free(atom);
193        }
194        used_atoms--;
195    }
196}
197
198AtomPtr
199internAtomF(const char *format, ...)
200{
201    char *s;
202    char buf[150];
203    int n;
204    va_list args;
205    AtomPtr atom = NULL;
206
207    va_start(args, format);
208    n = vsnprintf(buf, 150, format, args);
209    va_end(args);
210    if(n >= 0 && n < 150) {
211        atom = internAtomN(buf, n);
212    } else {
213        va_start(args, format);
214        s = vsprintf_a(format, args);
215        va_end(args);
216        if(s != NULL) {
217            atom = internAtom(s);
218            free(s);
219        }
220    }
221    return atom;
222}
223
224static AtomPtr
225internAtomErrorV(int e, const char *f, va_list args)
226{
227   
228    char *es = pstrerror(e);
229    AtomPtr atom;
230    char *s1, *s2;
231    int n, rc;
232
233    if(f) {
234        s1 = vsprintf_a(f, args);
235        if(s1 == NULL)
236            return NULL;
237        n = strlen(s1);
238    } else {
239        s1 = NULL;
240        n = 0;
241    }
242
243    s2 = malloc(n + 70);
244    if(s2 == NULL) {
245        free(s1);
246        return NULL;
247    }
248    if(s1) {
249        strcpy(s2, s1);
250        free(s1);
251    }
252
253    rc = snprintf(s2 + n, 69, f ? ": %s" : "%s", es);
254    if(rc < 0 || rc >= 69) {
255        free(s2);
256        return NULL;
257    }
258
259    atom = internAtomN(s2, n + rc);
260    free(s2);
261    return atom;
262}
263
264AtomPtr
265internAtomError(int e, const char *f, ...)
266{
267    AtomPtr atom;
268    va_list args;
269    va_start(args, f);
270    atom = internAtomErrorV(e, f, args);
271    va_end(args);
272    return atom;
273}
274
275char *
276atomString(AtomPtr atom)
277{
278    if(atom)
279        return atom->string;
280    else
281        return "(null)";
282}
283
284AtomListPtr
285makeAtomList(AtomPtr *atoms, int n)
286{
287    AtomListPtr list;
288    list = malloc(sizeof(AtomListRec));
289    if(list == NULL) return NULL;
290    list->length = 0;
291    list->size = 0;
292    list->list = NULL;
293    if(n > 0) {
294        int i;
295        list->list = malloc(n * sizeof(AtomPtr));
296        if(list->list == NULL) {
297            free(list);
298            return NULL;
299        }
300        list->size = n;
301        for(i = 0; i < n; i++)
302            list->list[i] = atoms[i];
303        list->length = n;
304    }
305    return list;
306}
307
308void
309destroyAtomList(AtomListPtr list)
310{
311    int i;
312    if(list->list) {
313        for(i = 0; i < list->length; i++)
314            releaseAtom(list->list[i]);
315        list->length = 0;
316        free(list->list);
317        list->list = NULL;
318        list->size = 0;
319    }
320    assert(list->size == 0);
321    free(list);
322}
323
324int
325atomListMember(AtomPtr atom, AtomListPtr list)
326{
327    int i;
328    for(i = 0; i < list->length; i++) {
329        if(atom == list->list[i])
330            return 1;
331    }
332    return 0;
333}
334
335void
336atomListCons(AtomPtr atom, AtomListPtr list)
337{
338    if(list->list == NULL) {
339        assert(list->size == 0);
340        list->list = malloc(5 * sizeof(AtomPtr));
341        if(list->list == NULL) {
342            do_log(L_ERROR, "Couldn't allocate AtomList\n");
343            return;
344        }
345        list->size = 5;
346    }
347    if(list->size <= list->length) {
348        AtomPtr *new_list;
349        int n = (2 * list->length + 1);
350        new_list = realloc(list->list, n * sizeof(AtomPtr));
351        if(new_list == NULL) {
352            do_log(L_ERROR, "Couldn't realloc AtomList\n");
353            return;
354        }
355        list->list = new_list;
356        list->size = n;
357    }
358    list->list[list->length] = atom;
359    list->length++;
360}
Note: See TracBrowser for help on using the browser.