You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

namespace.c 2.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #include "vm/vm.h"
  2. static const l2_word tombstone = ~(l2_word)0;
  3. static struct l2_vm_namespace *set(struct l2_vm_namespace *ns, l2_word key, l2_word val);
  4. static struct l2_vm_namespace *alloc(size_t size, l2_word mask) {
  5. struct l2_vm_namespace *ns = calloc(
  6. 1, sizeof(struct l2_vm_namespace) + sizeof(l2_word) * size * 2);
  7. ns->size = size;
  8. ns->mask = mask;
  9. return ns;
  10. }
  11. static struct l2_vm_namespace *grow(struct l2_vm_namespace *ns) {
  12. struct l2_vm_namespace *newns = alloc(ns->size * 2, (ns->mask << 1) | ns->mask);
  13. for (size_t i = 0; i < ns->size; ++i) {
  14. l2_word key = ns->data[i];
  15. if (key == 0 || key == tombstone) {
  16. continue;
  17. }
  18. l2_word val = ns->data[ns->size + i];
  19. for (l2_word i = 0; ; ++i) {
  20. l2_word hash = (key + i) & newns->mask;
  21. if (newns->data[hash] == 0) {
  22. newns->data[hash] = key;
  23. newns->data[newns->size + hash] = val;
  24. newns->len += 1;
  25. break;
  26. }
  27. }
  28. }
  29. free(ns);
  30. return newns;
  31. }
  32. static void del(struct l2_vm_namespace *ns, l2_word key) {
  33. if (ns == NULL) {
  34. return;
  35. }
  36. for (l2_word i = 0; ; ++i) {
  37. l2_word hash = (key + i) & ns->mask;
  38. l2_word k = ns->data[hash];
  39. if (k == 0) {
  40. return;
  41. } else if (k == key) {
  42. ns->data[hash] = tombstone;
  43. return;
  44. }
  45. }
  46. }
  47. static struct l2_vm_namespace *set(struct l2_vm_namespace *ns, l2_word key, l2_word val) {
  48. if (ns == NULL) {
  49. ns = alloc(16, 0x0f);
  50. } else if (ns->len >= ns->size / 2) {
  51. ns = grow(ns);
  52. }
  53. for (l2_word i = 0; ; ++i) {
  54. l2_word hash = (key + i) & ns->mask;
  55. l2_word k = ns->data[hash];
  56. if (k == tombstone) {
  57. ns->data[hash] = key;
  58. ns->data[ns->size + hash] = val;
  59. break;
  60. } else if (k == key) {
  61. ns->data[ns->size + hash] = val;
  62. break;
  63. } else if (k == 0) {
  64. ns->len += 1;
  65. ns->data[hash] = key;
  66. ns->data[ns->size + hash] = val;
  67. break;
  68. }
  69. }
  70. return ns;
  71. }
  72. static l2_word get(struct l2_vm_namespace *ns, l2_word key) {
  73. if (ns == NULL) {
  74. return 0;
  75. }
  76. for (l2_word i = 0; ; ++i) {
  77. l2_word hash = (key + i) & ns->mask;
  78. l2_word k = ns->data[hash];
  79. if (k == 0) {
  80. return 0;
  81. } else if (k == key) {
  82. return ns->data[ns->size + hash];
  83. }
  84. }
  85. }
  86. void l2_vm_namespace_set(struct l2_vm_value *ns, l2_word key, l2_word val) {
  87. if (val == 0) {
  88. del(ns->data, key);
  89. } else {
  90. ns->data = set(ns->data, key, val);
  91. }
  92. }
  93. l2_word l2_vm_namespace_get(struct l2_vm_value *ns, l2_word key) {
  94. return get(ns->data, key);
  95. }