Use hashtable for macro definitions in the preprocessor, this speeds up the search...
authorDale Weiler <killfieldengine@gmail.com>
Wed, 17 Apr 2013 10:51:33 +0000 (10:51 +0000)
committerDale Weiler <killfieldengine@gmail.com>
Wed, 17 Apr 2013 10:51:33 +0000 (10:51 +0000)
ftepp.c
gmqcc.h
util.c

diff --git a/ftepp.c b/ftepp.c
index a9500c41dc35de235fe18e1fa9ceefd98dee36b5..320afc8182874580f98202f16d5aace610caf5b2 100644 (file)
--- a/ftepp.c
+++ b/ftepp.c
@@ -25,6 +25,7 @@
 #include "gmqcc.h"
 #include "lexer.h"
 
+#define HT_MACROS 1024
 typedef struct {
     bool on;
     bool was_on;
@@ -62,7 +63,8 @@ typedef struct ftepp_s {
 
     bool         output_on;
     ppcondition *conditions;
-    ppmacro    **macros;
+    /*ppmacro    **macros;*/
+    ht           macros; /* hashtable<string, ppmacro*> */
 
     char        *output_string;
 
@@ -261,6 +263,7 @@ static ftepp_t* ftepp_new()
     ftepp = (ftepp_t*)mem_a(sizeof(*ftepp));
     memset(ftepp, 0, sizeof(*ftepp));
 
+    ftepp->macros    = util_htnew(HT_MACROS);
     ftepp->output_on = true;
 
     return ftepp;
@@ -273,15 +276,21 @@ static void ftepp_flush_do(ftepp_t *self)
 
 static void ftepp_delete(ftepp_t *self)
 {
-    size_t i;
     ftepp_flush_do(self);
     if (self->itemname)
         mem_d(self->itemname);
     if (self->includename)
         vec_free(self->includename);
+
+    /*
     for (i = 0; i < vec_size(self->macros); ++i)
         ppmacro_delete(self->macros[i]);
+
     vec_free(self->macros);
+*/
+
+    util_htrem(self->macros, (void (*)(void*))&ppmacro_delete);
+
     vec_free(self->conditions);
     if (self->lex)
         lex_close(self->lex);
@@ -310,23 +319,12 @@ static void ftepp_update_output_condition(ftepp_t *ftepp)
 
 static ppmacro* ftepp_macro_find(ftepp_t *ftepp, const char *name)
 {
-    size_t i;
-    for (i = 0; i < vec_size(ftepp->macros); ++i) {
-        if (!strcmp(name, ftepp->macros[i]->name))
-            return ftepp->macros[i];
-    }
-    return NULL;
+    return util_htget(ftepp->macros, name);
 }
 
 static void ftepp_macro_delete(ftepp_t *ftepp, const char *name)
 {
-    size_t i;
-    for (i = 0; i < vec_size(ftepp->macros); ++i) {
-        if (!strcmp(name, ftepp->macros[i]->name)) {
-            vec_remove(ftepp->macros, i, 1);
-            return;
-        }
-    }
+    util_htrm(ftepp->macros, name, NULL);
 }
 
 static GMQCC_INLINE int ftepp_next(ftepp_t *ftepp)
@@ -516,8 +514,12 @@ static bool ftepp_define(ftepp_t *ftepp)
         return false;
     }
 
+#if 0
     if (ftepp->output_on)
         vec_push(ftepp->macros, macro);
+#endif
+    if (ftepp->output_on)
+        util_htset(ftepp->macros, macro->name, (void*)macro);
     else {
         ppmacro_delete(macro);
     }
@@ -1832,7 +1834,8 @@ void ftepp_add_define(ftepp_t *ftepp, const char *source, const char *name)
     lex_ctx ctx = { "__builtin__", 0 };
     ctx.file = source;
     macro = ppmacro_new(ctx, name);
-    vec_push(ftepp->macros, macro);
+    /*vec_push(ftepp->macros, macro);*/
+    util_htset(ftepp->macros, name, macro);
 }
 
 const char *ftepp_get(ftepp_t *ftepp)
diff --git a/gmqcc.h b/gmqcc.h
index 297f73589dfdb9807831044837ebf623beab05f8..42e771459303cc7be78cb564abd28b7d5d73273e 100644 (file)
--- a/gmqcc.h
+++ b/gmqcc.h
@@ -417,10 +417,13 @@ typedef struct hash_set_t {
  * util_htdel(foo);
  */
 hash_table_t *util_htnew (size_t size);
+void          util_htrem (hash_table_t *ht, void (*callback)(void *data));
 void          util_htset (hash_table_t *ht, const char *key, void *value);
 void          util_htdel (hash_table_t *ht);
 size_t        util_hthash(hash_table_t *ht, const char *key);
 void          util_htseth(hash_table_t *ht, const char *key, size_t hash, void *value);
+void          util_htrmh (hash_table_t *ht, const char *key, size_t bin, void (*cb)(void*));
+void          util_htrm  (hash_table_t *ht, const char *key, void (*cb)(void*));
 
 void         *util_htget (hash_table_t *ht, const char *key);
 void         *util_htgeth(hash_table_t *ht, const char *key, size_t hash);
diff --git a/util.c b/util.c
index 59be9bfd7c706ab6c4b83b418a22bd6e6dfee504..712a9eaa40db597b81e33935a202c0685e9ecf72 100644 (file)
--- a/util.c
+++ b/util.c
@@ -601,7 +601,7 @@ void *code_util_str_htgeth(hash_table_t *ht, const char *key, size_t bin) {
  * Free all allocated data in a hashtable, this is quite the amount
  * of work.
  */
-void util_htdel(hash_table_t *ht) {
+void util_htrem(hash_table_t *ht, void (*callback)(void *data)) {
     size_t i = 0;
     for (; i < ht->size; i++) {
         hash_node_t *n = ht->table[i];
@@ -611,6 +611,8 @@ void util_htdel(hash_table_t *ht) {
         while (n) {
             if (n->key)
                 mem_d(n->key);
+            if (callback)
+                callback(n->value);
             p = n;
             n = n->next;
             mem_d(p);
@@ -622,6 +624,33 @@ void util_htdel(hash_table_t *ht) {
     mem_d(ht);
 }
 
+void util_htrmh(hash_table_t *ht, const char *key, size_t bin, void (*cb)(void*)) {
+    hash_node_t **pair = &ht->table[bin];
+    hash_node_t *tmp;
+
+    while (*pair && (*pair)->key && strcmp(key, (*pair)->key) > 0)
+        pair = &(*pair)->next;
+
+    tmp = *pair;
+    if (!tmp || !tmp->key || strcmp(key, tmp->key) != 0)
+        return;
+
+    if (cb)
+        (*cb)(tmp->value);
+
+    *pair = tmp->next;
+    mem_d(tmp->key);
+    mem_d(tmp);
+}
+
+void util_htrm(hash_table_t *ht, const char *key, void (*cb)(void*)) {
+    util_htrmh(ht, key, util_hthash(ht, key), cb);
+}
+
+void util_htdel(hash_table_t *ht) {
+    util_htrem(ht, NULL);
+}
+
 /*
  * A basic implementation of a hash-set.  Unlike a hashtable, a hash
  * set doesn't maintain key-value pairs.  It simply maintains a key