added move to front optimization
[swftools.git] / lib / q.c
diff --git a/lib/q.c b/lib/q.c
index 8c67d06..9bdcdf0 100644 (file)
--- a/lib/q.c
+++ b/lib/q.c
@@ -393,10 +393,12 @@ unsigned int crc32_add_byte(unsigned int checksum, unsigned char b)
 }
 unsigned int crc32_add_string(unsigned int checksum, const char*s)
 {
+    if(!crc32)
+        crc32_init();
     if(!s)
         return checksum;
     while(*s) {
-        checksum = crc32_add_byte(checksum, *s);
+        checksum = checksum>>8 ^ crc32[(*s^checksum)&0xff];
         s++;
     }
     return checksum;
@@ -800,11 +802,10 @@ int dict_count(dict_t*h)
     return h->num;
 }
 
-void dict_do_lookup(dict_t*h, const void*key, void***match)
+static inline dictentry_t* dict_do_lookup(dict_t*h, const void*key)
 {
     if(!h->num) {
-        *match = 0;
-        return;
+        return 0;
     }
     
     unsigned int ohash = h->key_type->hash(key);
@@ -813,8 +814,7 @@ void dict_do_lookup(dict_t*h, const void*key, void***match)
     /* check first entry for match */
     dictentry_t*e = h->slots[hash];
     if(e && h->key_type->equals(e->key, key)) {
-        *match = &e->data;
-        return;
+        return e;
     } else if(e) {
         e = e->next;
     }
@@ -830,31 +830,40 @@ void dict_do_lookup(dict_t*h, const void*key, void***match)
         dict_expand(h, newsize);
         hash = ohash % h->hashsize;
         e = h->slots[hash];
+        if(e && h->key_type->equals(e->key, key)) {
+            // omit move to front
+            return e;
+        } else if(e) {
+            e = e->next;
+        }
     }
 
     /* check subsequent entries for a match */
+    dictentry_t*last = h->slots[hash];
     while(e) {
         if(h->key_type->equals(e->key, key)) {
-            *match = &e->data;
-            return;
+            /* move to front- makes a difference of about 10% in most applications */
+            last->next = e->next;
+            e->next = h->slots[hash];
+            h->slots[hash] = e;
+            return e;
         }
+        last=e;
         e = e->next;
     }
-    *match = 0;
+    return 0;
 }
 void* dict_lookup(dict_t*h, const void*key)
 {
-    void**data = 0;
-    dict_do_lookup(h, key, &data);
-    if(data)
-        return *data;
+    dictentry_t*e = dict_do_lookup(h, key);
+    if(e)
+        return e->data;
     return 0;
 }
 char dict_contains(dict_t*h, const void*key)
 {
-    void**data = 0;
-    dict_do_lookup(h, key, &data);
-    return !!data;
+    dictentry_t*e = dict_do_lookup(h, key);
+    return !!e;
 }
 
 char dict_del(dict_t*h, const void*key)
@@ -1122,6 +1131,20 @@ int list_length_(void*_list)
         return 0;
     return l->info[0].size;
 }
+void list_concat_(void*_l1, void*_l2)
+{
+    commonlist_t**l1 = (commonlist_t**)_l1;
+    commonlist_t**l2 = (commonlist_t**)_l2;
+
+    if(!*l1) {
+        *l1 = *l2;
+    } else if(*l2) {
+        (*l1)->info[0].last->next = *l2;
+        (*l1)->info[0].last = (*l2)->info[0].last;
+        (*l1)->info[0].size += (*l2)->info[0].size;
+    }
+    *l2 = 0;
+}
 void list_append_(void*_list, void*entry)
 {
     commonlist_t**list = (commonlist_t**)_list;