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/>
19 * SPDX-License-Identifier: AGPL-3.0-or-later
28 #define FIELD_SIZE(Typ,Field) (sizeof(((Typ*)0)->Field))
30 Symtable* symtable_create(unsigned elems_count, unsigned name_size, unsigned elem_size)
32 size_t n = elems_count * (name_size + elem_size) + sizeof(Symtable) - FIELD_SIZE(Symtable, contents);
33 Symtable *p = malloc(n);
36 p->elems_count = elems_count;
37 p->name_size = name_size;
38 p->elem_size = elem_size;
42 void symtable_destroy(Symtable *p)
48 static unsigned name2pos(const Symtable *p, const char *name, unsigned namelen)
53 key = ((key << 1) | (*name++));
54 return key % p->elems_count;
57 static char *getsym(const Symtable *p, unsigned pos)
59 //assert(p); //already checked by caller
60 //assert(pos < p->elems_count);
61 return ((char*)p) + sizeof(Symtable) - FIELD_SIZE(Symtable, contents) + (pos * p->elem_size);
64 void* symtable_lookup2(const Symtable *p, const char *name, unsigned namelen)
69 assert(namelen < p->name_size);
71 unsigned start = name2pos(p, name, namelen);
75 char *s = getsym(p, pos);
78 if (!memcmp(name, s, namelen))
79 return s + p->name_size;
80 if (++pos >= p->elems_count)
82 } while(pos != start);
87 void* symtable_lookup(const Symtable *p, const char *name)
90 return symtable_lookup2(p, name, strlen(name));
93 void* symtable_add(Symtable *p, const char *name, void *contents)
96 return symtable_add2(p, name, strlen(name), contents);
99 void* symtable_add2(Symtable *p, const char *name, unsigned namelen, void *contents)
103 assert(namelen > 0 && namelen < p->name_size);
106 unsigned start = name2pos(p, name, namelen);
107 unsigned pos = start;
110 char *s = getsym(p, pos);
112 memcpy(s, name, namelen + 1);
114 memcpy(s + p->name_size, contents, p->elem_size);
115 return s + p->name_size;
117 if (!memcmp(name, s, namelen) && s[namelen] == '\0') {
118 /* TODO!! report error */
119 return NULL; /* ..already added */
121 if (++pos >= p->elems_count)
123 } while(pos != start);
125 /* TODO!! report overflow */
130 static int sortfunc(const void *a, const void *b)
134 if (!*s1 && !*s2) return 0;
137 return strcmp(s1, s2);
140 void symtable_sort(Symtable *p)
143 qsort(getsym(p, 0), p->elems_count, p->elem_size + p->name_size, sortfunc);