|
|
@@ -28,7 +28,7 @@ void *qi_malloc_atomic(qi_size_t size)
|
|
|
|
|
|
if (!ptr)
|
|
|
abort();
|
|
|
-
|
|
|
+
|
|
|
memset(ptr, 0, size);
|
|
|
|
|
|
return ptr;
|
|
|
@@ -37,10 +37,10 @@ void *qi_malloc_atomic(qi_size_t size)
|
|
|
static void *qi_malloc_uncollectable(size_t size)
|
|
|
{
|
|
|
void *ptr = malloc(size);
|
|
|
-
|
|
|
+
|
|
|
if (!ptr)
|
|
|
abort();
|
|
|
-
|
|
|
+
|
|
|
memset(ptr, 0, size);
|
|
|
|
|
|
return ptr;
|
|
|
@@ -49,10 +49,10 @@ static void *qi_malloc_uncollectable(size_t size)
|
|
|
static void *qi_malloc_root(size_t size)
|
|
|
{
|
|
|
void *ptr = GC_malloc_uncollectable(size);
|
|
|
-
|
|
|
+
|
|
|
if (!ptr)
|
|
|
abort();
|
|
|
-
|
|
|
+
|
|
|
memset(ptr, 0, size);
|
|
|
|
|
|
return ptr;
|
|
|
@@ -82,12 +82,12 @@ char *qi_strdup(const char *s)
|
|
|
{
|
|
|
qi_size_t z = strlen(s) + 1;
|
|
|
char *ptr = GC_MALLOC_ATOMIC(sizeof(char) * z);
|
|
|
-
|
|
|
+
|
|
|
if (!ptr)
|
|
|
abort();
|
|
|
-
|
|
|
+
|
|
|
ptr[z - 1] = 0;
|
|
|
-
|
|
|
+
|
|
|
strcpy(ptr, s);
|
|
|
|
|
|
return ptr;
|
|
|
@@ -304,6 +304,49 @@ static qi_table_t *qi_table_make_root(void)
|
|
|
return table;
|
|
|
}
|
|
|
|
|
|
+static qi_linkedlist_t *qi_linkedlist_push(qi_linkedlist_t *prev, uint64_t i)
|
|
|
+{
|
|
|
+ qi_linkedlist_t *ll = qi_malloc(sizeof(qi_linkedlist_t));
|
|
|
+
|
|
|
+ ll->i = i;
|
|
|
+ ll->next = NULL;
|
|
|
+
|
|
|
+ if (prev == NULL)
|
|
|
+ {
|
|
|
+ ll->prev = NULL;
|
|
|
+
|
|
|
+ return ll;
|
|
|
+ }
|
|
|
+
|
|
|
+ prev->next = ll;
|
|
|
+ ll->prev = prev;
|
|
|
+
|
|
|
+ return ll;
|
|
|
+}
|
|
|
+
|
|
|
+static qi_linkedlist_t *qi_linkedlist_delete(qi_linkedlist_t *ll)
|
|
|
+{
|
|
|
+ ll->prev->next = ll->next;
|
|
|
+ ll->next->prev = ll->prev;
|
|
|
+
|
|
|
+ qi_free(ll);
|
|
|
+}
|
|
|
+
|
|
|
+static qi_linkedlist_t *qi_linkedlist_destroy(qi_linkedlist_t *ll)
|
|
|
+{
|
|
|
+ qi_linkedlist_t *lln = ll;
|
|
|
+
|
|
|
+ qi_linkedlist_t *temp;
|
|
|
+ while (lln != NULL)
|
|
|
+ {
|
|
|
+ temp = lln->next;
|
|
|
+
|
|
|
+ qi_free(lln);
|
|
|
+
|
|
|
+ lln = temp;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static uint64_t MM86128(void *key, const int len, uint32_t seed)
|
|
|
{
|
|
|
#define ROTL32(x, r) ((x << r) | (x >> (32 - r)))
|
|
|
@@ -438,12 +481,14 @@ static uint64_t MM86128(void *key, const int len, uint32_t seed)
|
|
|
|
|
|
static uint32_t QI_HASH_SEED = 0;
|
|
|
|
|
|
+#define mm86128h(s) (MM86128((s), strlen((s)), QI_HASH_SEED))
|
|
|
+
|
|
|
void *qi_table_get(qi_table_t *table, char *key)
|
|
|
{
|
|
|
if (qi_table_empty(table))
|
|
|
return NULL;
|
|
|
|
|
|
- uint64_t hash = MM86128(key, strlen(key), QI_HASH_SEED);
|
|
|
+ uint64_t hash = mm86128h(key);
|
|
|
qi_size_t index = hash % table->capacity;
|
|
|
|
|
|
qi_size_t i = index;
|
|
|
@@ -471,7 +516,7 @@ qi_bool qi_table_has(qi_table_t *table, char *key)
|
|
|
if (qi_table_empty(table))
|
|
|
return false;
|
|
|
|
|
|
- uint64_t hash = MM86128(key, strlen(key), QI_HASH_SEED);
|
|
|
+ uint64_t hash = mm86128h(key);
|
|
|
qi_size_t index = hash % table->capacity;
|
|
|
|
|
|
qi_size_t i = index;
|
|
|
@@ -495,10 +540,10 @@ qi_bool qi_table_has(qi_table_t *table, char *key)
|
|
|
}
|
|
|
|
|
|
static void qi_table_entry_set(qi_table_entry_t *entries, char *key,
|
|
|
- void *value, qi_size_t capacity,
|
|
|
- qi_size_t *used)
|
|
|
+ void *value, qi_linkedlist_t **llh, qi_linkedlist_t **llc,
|
|
|
+ qi_size_t capacity, qi_size_t *used)
|
|
|
{
|
|
|
- uint64_t hash = MM86128(key, strlen(key), QI_HASH_SEED);
|
|
|
+ uint64_t hash = mm86128h(key);
|
|
|
qi_size_t index = hash % capacity;
|
|
|
|
|
|
qi_size_t i = index;
|
|
|
@@ -515,6 +560,14 @@ static void qi_table_entry_set(qi_table_entry_t *entries, char *key,
|
|
|
(*used)++;
|
|
|
|
|
|
entries[i].is_deleted = false;
|
|
|
+
|
|
|
+ qi_linkedlist_t *lln = qi_linkedlist_push(*llc, i);
|
|
|
+ if (!*llh)
|
|
|
+ *llh = lln;
|
|
|
+
|
|
|
+ *llc = lln;
|
|
|
+
|
|
|
+ entries[i].lln = lln;
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
@@ -537,6 +590,17 @@ static void qi_table_entry_set(qi_table_entry_t *entries, char *key,
|
|
|
entries[i].key = key;
|
|
|
entries[i].value = value;
|
|
|
entries[i].is_deleted = false;
|
|
|
+
|
|
|
+ if (!entries[i].lln)
|
|
|
+ {
|
|
|
+ qi_linkedlist_t *lln = qi_linkedlist_push(*llc, i);
|
|
|
+ if (!*llh)
|
|
|
+ *llh = lln;
|
|
|
+
|
|
|
+ *llc = lln;
|
|
|
+
|
|
|
+ entries[i].lln = lln;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
qi_table_t *qi_table_set(qi_table_t *table, char *key, void *value)
|
|
|
@@ -545,22 +609,23 @@ qi_table_t *qi_table_set(qi_table_t *table, char *key, void *value)
|
|
|
{
|
|
|
qi_size_t capacity = table->capacity + QI_TABLE_MIN_CAP;
|
|
|
qi_table_entry_t *entries = qi_calloc(capacity, sizeof(qi_table_entry_t));
|
|
|
+ qi_linkedlist_t *llh = NULL;
|
|
|
+ qi_linkedlist_t *llc = NULL;
|
|
|
|
|
|
- for (qi_size_t i = 0; i < table->capacity; i++)
|
|
|
- {
|
|
|
- qi_table_entry_t entry = table->entries[i];
|
|
|
-
|
|
|
- if (entry.key && !entry.is_deleted)
|
|
|
- qi_table_entry_set(entries, entry.key, entry.value, capacity, NULL);
|
|
|
- }
|
|
|
+ qi_table_iterate(table, {
|
|
|
+ qi_table_entry_set(entries, entry.key, entry.value, &llh, &llc, capacity, NULL);
|
|
|
+ });
|
|
|
|
|
|
qi_free(table->entries);
|
|
|
+ qi_linkedlist_destroy(table->llh);
|
|
|
|
|
|
table->entries = entries;
|
|
|
+ table->llh = llh;
|
|
|
+ table->llc = llc;
|
|
|
table->capacity = capacity;
|
|
|
}
|
|
|
|
|
|
- qi_table_entry_set(table->entries, key, value, table->capacity, &table->used);
|
|
|
+ qi_table_entry_set(table->entries, key, value, &table->llh, &table->llc, table->capacity, &table->used);
|
|
|
|
|
|
return table;
|
|
|
}
|
|
|
@@ -576,7 +641,7 @@ qi_list_t *qi_table_keys(qi_table_t *table)
|
|
|
|
|
|
qi_bool qi_table_delete(qi_table_t *table, char *key)
|
|
|
{
|
|
|
- uint64_t hash = MM86128(key, strlen(key), QI_HASH_SEED);
|
|
|
+ uint64_t hash = mm86128h(key);
|
|
|
qi_size_t index = hash % table->capacity;
|
|
|
|
|
|
qi_size_t i = index;
|
|
|
@@ -589,6 +654,10 @@ qi_bool qi_table_delete(qi_table_t *table, char *key)
|
|
|
table->entries[i].value = NULL;
|
|
|
table->entries[i].is_deleted = true;
|
|
|
|
|
|
+ qi_linkedlist_delete(table->entries[i].lln);
|
|
|
+
|
|
|
+ table->entries[i].lln = NULL;
|
|
|
+
|
|
|
table->used--;
|
|
|
|
|
|
if (table->capacity > QI_TABLE_MIN_CAP &&
|
|
|
@@ -597,18 +666,19 @@ qi_bool qi_table_delete(qi_table_t *table, char *key)
|
|
|
qi_size_t capacity = table->capacity - QI_TABLE_MIN_CAP;
|
|
|
qi_table_entry_t *entries =
|
|
|
qi_calloc(capacity, sizeof(qi_table_entry_t));
|
|
|
+ qi_linkedlist_t *llh = NULL;
|
|
|
+ qi_linkedlist_t *llc = NULL;
|
|
|
|
|
|
- for (qi_size_t i = 0; i < table->capacity; i++)
|
|
|
- {
|
|
|
- qi_table_entry_t entry = table->entries[i];
|
|
|
-
|
|
|
- if (entry.key && !entry.is_deleted)
|
|
|
- qi_table_entry_set(entries, entry.key, entry.value, capacity, NULL);
|
|
|
- }
|
|
|
+ qi_table_iterate(table, {
|
|
|
+ qi_table_entry_set(entries, entry.key, entry.value, &llh, &llc, capacity, NULL);
|
|
|
+ });
|
|
|
|
|
|
qi_free(table->entries);
|
|
|
+ qi_linkedlist_destroy(table->llh);
|
|
|
|
|
|
table->entries = entries;
|
|
|
+ table->llh = llh;
|
|
|
+ table->llc = llc;
|
|
|
table->capacity = capacity;
|
|
|
}
|
|
|
|
|
|
@@ -685,7 +755,7 @@ void qi_buffer_format(qi_buffer_t *buf, const char *fmt, ...)
|
|
|
va_end(largs);
|
|
|
|
|
|
qi_buffer_append_str(buf, str);
|
|
|
-
|
|
|
+
|
|
|
qi_free(str);
|
|
|
}
|
|
|
|
|
|
@@ -718,18 +788,18 @@ char *qi_buffer_read(qi_buffer_t *buf)
|
|
|
char *qi_buffer_get(qi_buffer_t *buf)
|
|
|
{
|
|
|
char *str = qi_buffer_read(buf);
|
|
|
-
|
|
|
+
|
|
|
qi_free(buf);
|
|
|
-
|
|
|
+
|
|
|
return str;
|
|
|
}
|
|
|
|
|
|
void qi_buffer_destroy(qi_buffer_t *buf)
|
|
|
{
|
|
|
- if (buf->str)
|
|
|
- qi_free(buf->str);
|
|
|
-
|
|
|
- qi_free(buf);
|
|
|
+ if (buf->str)
|
|
|
+ qi_free(buf->str);
|
|
|
+
|
|
|
+ qi_free(buf);
|
|
|
}
|
|
|
|
|
|
void _qi_add_defer(qi_state_t *state, qi_ssize_t index, qi_defer_t defer,
|
|
|
@@ -2274,7 +2344,7 @@ qi_value_t *qi_cast(qi_state_t *state, qi_type_t type, qi_value_t *value)
|
|
|
if (byte->type != QI_NUMBER)
|
|
|
{
|
|
|
qi_mutex_unlock(value->mutex);
|
|
|
-
|
|
|
+
|
|
|
qi_free(temp);
|
|
|
|
|
|
qi_typeerror(state,
|