txlyre 1 day ago
parent
commit
29b432f048
4 changed files with 136 additions and 189 deletions
  1. 1 0
      .gitignore
  2. 107 37
      qirt.c
  3. 28 15
      qirt.h
  4. 0 137
      std.qi

+ 1 - 0
.gitignore

@@ -2,3 +2,4 @@
 *.o
 *.a
 qistd.c
+.vscode

+ 107 - 37
qirt.c

@@ -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,

+ 28 - 15
qirt.h

@@ -44,6 +44,16 @@ struct _qi_list_t
 #define qi_list_first(list) ((list)->data[0])
 #define qi_list_last(list) ((list)->data[(list)->length - 1])
 
+typedef struct _qi_linkedlist_t qi_linkedlist_t;
+
+struct _qi_linkedlist_t
+{
+  uint64_t i;
+
+  qi_linkedlist_t *prev;
+  qi_linkedlist_t *next;
+};
+
 typedef struct _qi_table_t qi_table_t;
 typedef struct _qi_table_entry_t qi_table_entry_t;
 
@@ -51,6 +61,7 @@ struct _qi_table_entry_t
 {
   char *key;
   void *value;
+  qi_linkedlist_t *lln;
 
   qi_bool is_deleted;
 };
@@ -58,6 +69,8 @@ struct _qi_table_entry_t
 struct _qi_table_t
 {
   qi_table_entry_t *entries;
+  qi_linkedlist_t *llh;
+  qi_linkedlist_t *llc;
 
   qi_size_t used;
   qi_size_t capacity;
@@ -67,21 +80,21 @@ struct _qi_table_t
 
 #define qi_table_length(table) ((table)->used)
 #define qi_table_empty(table) ((table)->used == 0)
-#define qi_table_iterate(table, code)                 \
-  {                                                   \
-    if (!qi_table_empty(table))                       \
-    {                                                 \
-      qi_size_t i = 0;                                \
-      while (i < (table)->capacity)                   \
-      {                                               \
-        qi_table_entry_t entry = (table)->entries[i]; \
-        if (entry.key && !entry.is_deleted)           \
-        {                                             \
-          code;                                       \
-        }                                             \
-        i++;                                          \
-      }                                               \
-    }                                                 \
+#define qi_table_iterate(table, code)                      \
+  {                                                        \
+    if (!qi_table_empty(table))                            \
+    {                                                      \
+      qi_linkedlist_t *lln = (table)->llh;                 \
+      while (lln != NULL)                                  \
+      {                                                    \
+        qi_table_entry_t entry = (table)->entries[lln->i]; \
+        if (entry.key && !entry.is_deleted)                \
+        {                                                  \
+          code;                                            \
+        }                                                  \
+        lln = lln->next;                                   \
+      }                                                    \
+    }                                                      \
   }
 
 typedef struct

+ 0 - 137
std.qi

@@ -639,140 +639,3 @@ class ListIterator {
 
     __end(this): this.i >= this.z
 }
-class OrderedTable {
-    __data__ = nil
-
-    constructor (this, v=nil) {
-        this.__data__ = []
-
-        if v !is nil {
-            if type(v) is "list" {
-              for var pair of v
-                this[str(pair[0])] = pair[1]
-            } else {   
-              v = table(v)
-
-              for var k of v
-                this[k] = v
-            }
-        }
-    }
-
-    __type (this): "orderedtable"
-    
-    stringify (this, tempstack=[]) {
-        if this in tempstack
-            return "OrderedTable({...})"
-
-        tempstack.push(this)
-
-        var buf = "OrderedTable({"
-        var f = true
-
-        for var [k, v] of this.__data__ {
-            if f
-                f = false
-            else buf += ", "
-
-            k = k.replace(`\`, `\\`).replace(`"`, `\"`)
-
-            if type(v) is "orderedtable"
-                v = v.stringify(tempstack)
-            
-            buf += f`"${k}": ${v}`
-        }
-
-        buf += "})"
-
-        return buf
-    }
-
-    __str (this) {
-        return this.stringify([])
-    }
-
-    keys (this) {
-        let keys = []
-
-        for var [k, _] of this.__data__
-            keys.push(k)
-
-        return keys
-    }
-
-    values (this) {
-        let values = []
-
-        for var [_, v] of this.__data__
-            values.push(v)
-
-        return values
-    }
-
-    delete (this, k) {
-        del this[k]
-    }
-
-    copy (this) {
-        return OrderedTable(this.__data__)
-    }
-
-    get (this, k, d=nil) {
-        k = str(k)
-
-        for var [ok, v] of this.__data__
-            if ok == k
-                return v
-
-        return d
-    }
-
-    __iter (this): ListIterator(this.keys())
-    __len (this): len(this.__data__)
-
-    __in (this, k) {
-        k = str(k)
-
-        for var [ok, _] of this.__data__
-            if ok == k
-                return true
-
-        return false
-    }
-
-    __del (this, k) {
-        k = str(k)
-
-        for var [i, ok] of zip(range(len(this)), this.keys())
-            if ok == k {
-                del this.__data__[i]
-
-                return
-            }
-
-        throw KeyError(k)
-    }
-
-    __index (this, k) {
-        k = str(k)
-
-        for var [ok, v] of this.__data__
-            if ok == k
-                return v
-
-        throw KeyError(k)
-    }
-
-    __index_set (this, k, v) {
-        k = str(k)
-
-        for var [i, ok] of zip(range(len(this)), this.keys())
-            if ok == k {
-                this.__data__[i] = (ok, v)
-
-                return
-            }
-
-        this.__data__.push((k, v))
-    }
-}