symtable.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. * symtable.c -- part of ZilUtils/ZilAsm
  3. *
  4. * Copyright (C) 2016 Jason Self <j@jxself.org>
  5. *
  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.
  10. *
  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.
  15. *
  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/>
  18. *
  19. * SPDX-License-Identifier: AGPL-3.0-or-later
  20. */
  21. #include <string.h>
  22. #include <stdlib.h>
  23. #include <assert.h>
  24. #include "symtable.h"
  25. #define FIELD_SIZE(Typ,Field) (sizeof(((Typ*)0)->Field))
  26. Symtable* symtable_create(unsigned elems_count, unsigned name_size, unsigned elem_size)
  27. {
  28. size_t n = elems_count * (name_size + elem_size) + sizeof(Symtable) - FIELD_SIZE(Symtable, contents);
  29. Symtable *p = malloc(n);
  30. assert(p);
  31. bzero(p, n);
  32. p->elems_count = elems_count;
  33. p->name_size = name_size;
  34. p->elem_size = elem_size;
  35. return p;
  36. }
  37. void symtable_destroy(Symtable *p)
  38. {
  39. assert(p);
  40. free(p);
  41. }
  42. static unsigned name2pos(const Symtable *p, const char *name, unsigned namelen)
  43. {
  44. assert(p);
  45. unsigned key = 0;
  46. while(namelen--)
  47. key = ((key << 1) | (*name++));
  48. return key % p->elems_count;
  49. }
  50. static char *getsym(const Symtable *p, unsigned pos)
  51. {
  52. //assert(p); //already checked by caller
  53. //assert(pos < p->elems_count);
  54. return ((char*)p) + sizeof(Symtable) - FIELD_SIZE(Symtable, contents) + (pos * p->elem_size);
  55. }
  56. void* symtable_lookup2(const Symtable *p, const char *name, unsigned namelen)
  57. {
  58. assert(p);
  59. assert(name);
  60. assert(namelen > 0);
  61. assert(namelen < p->name_size);
  62. unsigned start = name2pos(p, name, namelen);
  63. unsigned pos = start;
  64. do {
  65. char *s = getsym(p, pos);
  66. if (!*s)
  67. return NULL;
  68. if (!memcmp(name, s, namelen))
  69. return s + p->name_size;
  70. if (++pos >= p->elems_count)
  71. pos = 0;
  72. } while(pos != start);
  73. return NULL;
  74. }
  75. void* symtable_lookup(const Symtable *p, const char *name)
  76. {
  77. assert(name);
  78. return symtable_lookup2(p, name, strlen(name));
  79. }
  80. void* symtable_add(Symtable *p, const char *name, void *contents)
  81. {
  82. assert(name);
  83. return symtable_add2(p, name, strlen(name), contents);
  84. }
  85. void* symtable_add2(Symtable *p, const char *name, unsigned namelen, void *contents)
  86. {
  87. assert(p);
  88. assert(name);
  89. assert(namelen > 0 && namelen < p->name_size);
  90. assert(contents);
  91. unsigned start = name2pos(p, name, namelen);
  92. unsigned pos = start;
  93. do {
  94. char *s = getsym(p, pos);
  95. if (!*s) {
  96. memcpy(s, name, namelen + 1);
  97. s[namelen] = '\0';
  98. memcpy(s + p->name_size, contents, p->elem_size);
  99. return s + p->name_size;
  100. }
  101. if (!memcmp(name, s, namelen) && s[namelen] == '\0') {
  102. /* TODO!! report error */
  103. return NULL; /* ..already added */
  104. }
  105. if (++pos >= p->elems_count)
  106. pos = 0;
  107. } while(pos != start);
  108. /* TODO!! report overflow */
  109. return NULL;
  110. /* TODO!!! */
  111. }
  112. static int sortfunc(const void *a, const void *b)
  113. {
  114. const char *s1 = a;
  115. const char *s2 = b;
  116. if (!*s1 && !*s2) return 0;
  117. if (!*s1) return 1;
  118. if (!*s2) return -1;
  119. return strcmp(s1, s2);
  120. }
  121. void symtable_sort(Symtable *p)
  122. {
  123. assert(p);
  124. qsort(getsym(p, 0), p->elems_count, p->elem_size + p->name_size, sortfunc);
  125. }
  126. /* END */