2 * symtable.c -- part of ZilUtils/ZilAsm
4 * Copyright (C) 2016 Jason Self <j@jxself.org>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as
8 * published by the Free Software Foundation, either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>
26 #define FIELD_SIZE(Typ,Field) (sizeof(((Typ*)0)->Field))
28 Symtable* symtable_create(unsigned elems_count, unsigned name_size, unsigned elem_size)
30 size_t n = elems_count * (name_size + elem_size) + sizeof(Symtable) - FIELD_SIZE(Symtable, contents);
31 Symtable *p = malloc(n);
34 p->elems_count = elems_count;
35 p->name_size = name_size;
36 p->elem_size = elem_size;
40 void symtable_destroy(Symtable *p)
46 static unsigned name2pos(const Symtable *p, const char *name, unsigned namelen)
51 key = ((key << 1) | (*name++));
52 return key % p->elems_count;
55 static char *getsym(const Symtable *p, unsigned pos)
57 //assert(p); //already checked by caller
58 //assert(pos < p->elems_count);
59 return ((char*)p) + sizeof(Symtable) - FIELD_SIZE(Symtable, contents) + (pos * p->elem_size);
62 void* symtable_lookup2(const Symtable *p, const char *name, unsigned namelen)
67 assert(namelen < p->name_size);
69 unsigned start = name2pos(p, name, namelen);
73 char *s = getsym(p, pos);
76 if (!memcmp(name, s, namelen))
77 return s + p->name_size;
78 if (++pos >= p->elems_count)
80 } while(pos != start);
85 void* symtable_lookup(const Symtable *p, const char *name)
88 return symtable_lookup2(p, name, strlen(name));
91 void* symtable_add(Symtable *p, const char *name, void *contents)
94 return symtable_add2(p, name, strlen(name), contents);
97 void* symtable_add2(Symtable *p, const char *name, unsigned namelen, void *contents)
101 assert(namelen > 0 && namelen < p->name_size);
104 unsigned start = name2pos(p, name, namelen);
105 unsigned pos = start;
108 char *s = getsym(p, pos);
110 memcpy(s, name, namelen + 1);
112 memcpy(s + p->name_size, contents, p->elem_size);
113 return s + p->name_size;
115 if (!memcmp(name, s, namelen) && s[namelen] == '\0') {
116 /* TODO!! report error */
117 return NULL; /* ..already added */
119 if (++pos >= p->elems_count)
121 } while(pos != start);
123 /* TODO!! report overflow */
128 static int sortfunc(const void *a, const void *b)
132 if (!*s1 && !*s2) return 0;
135 return strcmp(s1, s2);
138 void symtable_sort(Symtable *p)
141 qsort(getsym(p, 0), p->elems_count, p->elem_size + p->name_size, sortfunc);