Cleanup
This commit is contained in:
@@ -0,0 +1,237 @@
|
||||
|
||||
#include "iron_map.h"
|
||||
#include "iron_gc.h"
|
||||
#include "iron_string.h"
|
||||
|
||||
static size_t hash(const char *k) {
|
||||
// fnv1a
|
||||
size_t hash = 0x811c9dc5;
|
||||
while (*k) {
|
||||
hash ^= (unsigned char) *k++;
|
||||
hash *= 0x01000193;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
static size_t index_set(any_map_t *m, char *k) {
|
||||
size_t i = hash(k) & (m->keys->capacity - 1); // % m->keys->capacity
|
||||
while (true) {
|
||||
if (m->keys->buffer[i] == NULL) {
|
||||
m->keys->length++;
|
||||
break;
|
||||
}
|
||||
if (string_equals(k, m->keys->buffer[i])) {
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
if (i > m->keys->capacity - 1) {
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static size_t index_get(char_ptr_array_t *keys, char *k) {
|
||||
if (k == NULL || keys->capacity == 0) {
|
||||
return -1;
|
||||
}
|
||||
size_t i = hash(k) & (keys->capacity - 1);
|
||||
while (!string_equals(k, keys->buffer[i])) {
|
||||
if (keys->buffer[i] == NULL) {
|
||||
return -1;
|
||||
}
|
||||
++i;
|
||||
if (i > keys->capacity - 1) {
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static void resize(any_map_t *m, int elem_size) {
|
||||
if (m->keys->length < m->keys->capacity * 0.5) {
|
||||
return;
|
||||
}
|
||||
|
||||
int cap = m->keys->capacity == 0 ? 16 : m->keys->capacity * 2;
|
||||
any_map_t *tmp = any_map_create();
|
||||
tmp->keys->capacity = cap;
|
||||
tmp->keys->buffer = gc_realloc(tmp->keys->buffer, cap * sizeof(void *));
|
||||
tmp->values->capacity = cap;
|
||||
tmp->values->buffer = gc_realloc(tmp->values->buffer, cap * elem_size);
|
||||
if (elem_size < 8) {
|
||||
gc_leaf(tmp->values->buffer);
|
||||
}
|
||||
|
||||
any_array_t *old_keys = map_keys(m);
|
||||
for (int i = 0; i < old_keys->length; ++i) {
|
||||
char *k = old_keys->buffer[i];
|
||||
size_t j = index_set(tmp, k);
|
||||
tmp->keys->buffer[j] = k;
|
||||
if (elem_size == 8) {
|
||||
void **buf = tmp->values->buffer;
|
||||
buf[j] = any_map_get(m, k);
|
||||
}
|
||||
else {
|
||||
int32_t *buf = tmp->values->buffer;
|
||||
buf[j] = i32_map_get(m, k);
|
||||
}
|
||||
}
|
||||
|
||||
m->keys = tmp->keys;
|
||||
m->values = tmp->values;
|
||||
}
|
||||
|
||||
void i32_map_set(i32_map_t *m, char *k, int v) {
|
||||
resize(m, 4);
|
||||
size_t i = index_set(m, k);
|
||||
m->keys->buffer[i] = k;
|
||||
m->values->buffer[i] = v;
|
||||
}
|
||||
|
||||
void f32_map_set(f32_map_t *m, char *k, float v) {
|
||||
resize(m, 4);
|
||||
size_t i = index_set(m, k);
|
||||
m->keys->buffer[i] = k;
|
||||
m->values->buffer[i] = v;
|
||||
}
|
||||
|
||||
void any_map_set(any_map_t *m, char *k, void *v) {
|
||||
resize(m, 8);
|
||||
size_t i = index_set(m, k);
|
||||
m->keys->buffer[i] = k;
|
||||
m->values->buffer[i] = v;
|
||||
}
|
||||
|
||||
int32_t i32_map_get(i32_map_t *m, char *k) {
|
||||
size_t i = index_get(m->keys, k);
|
||||
return i == -1 ? -1 : m->values->buffer[i];
|
||||
}
|
||||
|
||||
float f32_map_get(f32_map_t *m, char *k) {
|
||||
size_t i = index_get(m->keys, k);
|
||||
return i == -1 ? -1.0 : m->values->buffer[i];
|
||||
}
|
||||
|
||||
void *any_map_get(any_map_t *m, char *k) {
|
||||
size_t i = index_get(m->keys, k);
|
||||
return i == -1 ? NULL : m->values->buffer[i];
|
||||
}
|
||||
|
||||
static int next_pos(any_map_t *m, int i) {
|
||||
return i == m->keys->capacity - 1 ? 0 : i + 1;
|
||||
}
|
||||
|
||||
void map_delete(any_map_t *m, char *k) {
|
||||
size_t i = index_get(m->keys, k);
|
||||
if (i != -1) {
|
||||
m->keys->buffer[i] = NULL;
|
||||
m->values->buffer[i] = NULL;
|
||||
m->keys->length--;
|
||||
|
||||
int next = next_pos(m, i);
|
||||
while (m->keys->buffer[next] != NULL && next != i) {
|
||||
int j = index_set(m, m->keys->buffer[next]);
|
||||
if (j != next) {
|
||||
m->keys->buffer[j] = m->keys->buffer[next];
|
||||
m->values->buffer[j] = m->values->buffer[next];
|
||||
m->keys->buffer[next] = NULL;
|
||||
m->values->buffer[next] = NULL;
|
||||
}
|
||||
next = next_pos(m, next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
any_array_t *map_keys(any_map_t *m) {
|
||||
char_ptr_array_t *keys = gc_alloc(sizeof(char_ptr_array_t));
|
||||
char_ptr_array_resize(keys, m->keys->length);
|
||||
for (int i = 0; i < m->keys->capacity; ++i) {
|
||||
if (m->keys->buffer[i] != NULL) {
|
||||
char_ptr_array_push(keys, m->keys->buffer[i]);
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
i32_map_t *i32_map_create() {
|
||||
i32_map_t *r = gc_alloc(sizeof(i32_map_t));
|
||||
r->keys = gc_alloc(sizeof(char_ptr_array_t));
|
||||
r->values = gc_alloc(sizeof(i32_array_t));
|
||||
return r;
|
||||
}
|
||||
|
||||
any_map_t *any_map_create() {
|
||||
any_map_t *r = gc_alloc(sizeof(any_map_t));
|
||||
r->keys = gc_alloc(sizeof(char_ptr_array_t));
|
||||
r->values = gc_alloc(sizeof(any_array_t));
|
||||
return r;
|
||||
}
|
||||
|
||||
// imap
|
||||
|
||||
void i32_imap_set(i32_imap_t *m, int k, int v) {
|
||||
int i = i32_array_index_of(m->keys, k);
|
||||
if (i == -1) {
|
||||
i32_array_push(m->keys, k);
|
||||
i32_array_push(m->values, v);
|
||||
}
|
||||
else {
|
||||
m->keys->buffer[i] = k;
|
||||
m->values->buffer[i] = v;
|
||||
}
|
||||
}
|
||||
|
||||
void any_imap_set(any_imap_t *m, int k, void *v) {
|
||||
int i = i32_array_index_of(m->keys, k);
|
||||
if (i == -1) {
|
||||
i32_array_push(m->keys, k);
|
||||
any_array_push(m->values, v);
|
||||
}
|
||||
else {
|
||||
m->keys->buffer[i] = k;
|
||||
m->values->buffer[i] = v;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t i32_imap_get(i32_imap_t *m, int k) {
|
||||
int i = i32_array_index_of(m->keys, k);
|
||||
if (i > -1) {
|
||||
return m->values->buffer[i];
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *any_imap_get(any_imap_t *m, int k) {
|
||||
int i = i32_array_index_of(m->keys, k);
|
||||
if (i > -1) {
|
||||
return m->values->buffer[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void imap_delete(any_imap_t *m, int k) {
|
||||
int i = i32_array_index_of(m->keys, k);
|
||||
if (i > -1) {
|
||||
array_splice(m->keys, i, 1);
|
||||
array_splice(m->values, i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
i32_array_t *imap_keys(any_imap_t *m) {
|
||||
return m->keys;
|
||||
}
|
||||
|
||||
i32_imap_t *i32_imap_create() {
|
||||
i32_imap_t *r = gc_alloc(sizeof(i32_imap_t));
|
||||
r->keys = gc_alloc(sizeof(i32_array_t));
|
||||
r->values = gc_alloc(sizeof(i32_array_t));
|
||||
return r;
|
||||
}
|
||||
|
||||
any_imap_t *any_imap_create() {
|
||||
any_imap_t *r = gc_alloc(sizeof(any_imap_t));
|
||||
r->keys = gc_alloc(sizeof(i32_array_t));
|
||||
r->values = gc_alloc(sizeof(any_array_t));
|
||||
return r;
|
||||
}
|
||||
Reference in New Issue
Block a user