]> de.git.xonotic.org Git - voretournament/voretournament.git/blobdiff - misc/mediasource/extra/fteqcc-src/hash.c
fteqcc source
[voretournament/voretournament.git] / misc / mediasource / extra / fteqcc-src / hash.c
diff --git a/misc/mediasource/extra/fteqcc-src/hash.c b/misc/mediasource/extra/fteqcc-src/hash.c
new file mode 100644 (file)
index 0000000..2b7b912
--- /dev/null
@@ -0,0 +1,272 @@
+#include "hash.h"
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef _WIN32
+#ifndef stricmp 
+#define stricmp strcasecmp
+#endif
+#endif
+
+// hash init assumes we get clean memory
+void Hash_InitTable(hashtable_t *table, int numbucks, void *mem)
+{
+       table->numbuckets = numbucks;
+       table->bucket = (bucket_t **)mem;
+}
+
+int Hash_Key(const char *name, int modulus)
+{      //fixme: optimize.
+       unsigned int key;
+       for (key=0;*name; name++)
+               key += ((key<<3) + (key>>28) + *name);
+               
+       return (int)(key%modulus);
+}
+int Hash_KeyInsensative(const char *name, int modulus)
+{      //fixme: optimize.
+       unsigned int key;
+       for (key=0;*name; name++)
+       {
+               if (*name >= 'A' && *name <= 'Z')
+                       key += ((key<<3) + (key>>28) + (*name-'A'+'a'));
+               else
+                       key += ((key<<3) + (key>>28) + *name);
+       }
+               
+       return (int)(key%modulus);
+}
+
+void *Hash_Get(hashtable_t *table, const char *name)
+{
+       int bucknum = Hash_Key(name, table->numbuckets);
+       bucket_t *buck;
+
+       buck = table->bucket[bucknum];
+
+       while(buck)
+       {
+               if (!STRCMP(name, buck->key.string))
+                       return buck->data;
+
+               buck = buck->next;
+       }
+       return NULL;
+}
+void *Hash_GetInsensative(hashtable_t *table, const char *name)
+{
+       int bucknum = Hash_KeyInsensative(name, table->numbuckets);
+       bucket_t *buck;
+
+       buck = table->bucket[bucknum];
+
+       while(buck)
+       {
+               if (!stricmp(name, buck->key.string))
+                       return buck->data;
+
+               buck = buck->next;
+       }
+       return NULL;
+}
+void *Hash_GetKey(hashtable_t *table, int key)
+{
+       int bucknum = key%table->numbuckets;
+       bucket_t *buck;
+
+       buck = table->bucket[bucknum];
+
+       while(buck)
+       {
+               if (buck->key.value == key)
+                       return buck->data;
+
+               buck = buck->next;
+       }
+       return NULL;
+}
+void *Hash_GetNext(hashtable_t *table, char *name, void *old)
+{
+       int bucknum = Hash_Key(name, table->numbuckets);
+       bucket_t *buck;
+
+       buck = table->bucket[bucknum];
+
+       while(buck)
+       {
+               if (!STRCMP(name, buck->key.string))
+               {
+                       if (buck->data == old)  //found the old one
+                               break;
+               }
+
+               buck = buck->next;
+       }
+       if (!buck)
+               return NULL;
+
+       buck = buck->next;//don't return old
+       while(buck)
+       {
+               if (!STRCMP(name, buck->key.string))
+                       return buck->data;
+
+               buck = buck->next;
+       }
+       return NULL;
+}
+void *Hash_GetNextInsensative(hashtable_t *table, char *name, void *old)
+{
+       int bucknum = Hash_KeyInsensative(name, table->numbuckets);
+       bucket_t *buck;
+
+       buck = table->bucket[bucknum];
+
+       while(buck)
+       {
+               if (!STRCMP(name, buck->key.string))
+               {
+                       if (buck->data == old)  //found the old one
+                               break;
+               }
+
+               buck = buck->next;
+       }
+       if (!buck)
+               return NULL;
+
+       buck = buck->next;//don't return old
+       while(buck)
+       {
+               if (!STRCMP(name, buck->key.string))
+                       return buck->data;
+
+               buck = buck->next;
+       }
+       return NULL;
+}
+
+
+void *Hash_Add(hashtable_t *table, char *name, void *data, bucket_t *buck)
+{
+       int bucknum = Hash_Key(name, table->numbuckets);
+
+       buck->data = data;
+       buck->key.string = name;
+       buck->next = table->bucket[bucknum];
+       table->bucket[bucknum] = buck;
+
+       return buck;
+}
+void *Hash_AddInsensative(hashtable_t *table, char *name, void *data, bucket_t *buck)
+{
+       int bucknum = Hash_KeyInsensative(name, table->numbuckets);
+
+       buck->data = data;
+       buck->key.string = name;
+       buck->next = table->bucket[bucknum];
+       table->bucket[bucknum] = buck;
+
+       return buck;
+}
+void *Hash_AddKey(hashtable_t *table, int key, void *data, bucket_t *buck)
+{
+       int bucknum = key%table->numbuckets;
+
+       buck->data = data;
+       buck->key.value = key;
+       buck->next = table->bucket[bucknum];
+       table->bucket[bucknum] = buck;
+
+       return buck;
+}
+
+void Hash_Remove(hashtable_t *table, char *name)
+{
+       int bucknum = Hash_Key(name, table->numbuckets);
+       bucket_t *buck; 
+
+       buck = table->bucket[bucknum];
+       if(!buck)
+               return;
+
+       if (!STRCMP(name, buck->key.string))
+       {
+               table->bucket[bucknum] = buck->next;
+               return;
+       }
+
+
+       while(buck->next)
+       {
+               if (!STRCMP(name, buck->next->key.string))
+               {
+                       buck->next = buck->next->next;
+                       return;
+               }
+
+               buck = buck->next;
+       }
+       return;
+}
+
+void Hash_RemoveData(hashtable_t *table, char *name, void *data)
+{
+       int bucknum = Hash_Key(name, table->numbuckets);
+       bucket_t *buck; 
+
+       buck = table->bucket[bucknum];
+       if(!buck)
+               return;
+
+       if (buck->data == data)
+               if (!STRCMP(name, buck->key.string))
+               {
+                       table->bucket[bucknum] = buck->next;
+                       return;
+               }
+
+
+       while(buck->next)
+       {
+               if (buck->next->data == data)
+                       if (!STRCMP(name, buck->next->key.string))
+                       {
+                               buck->next = buck->next->next;
+                               return;
+                       }
+
+               buck = buck->next;
+       }
+       return;
+}
+
+
+void Hash_RemoveKey(hashtable_t *table, int key)
+{
+       int bucknum = key%table->numbuckets;
+       bucket_t *buck; 
+
+       buck = table->bucket[bucknum];
+       if(!buck)
+               return;
+
+       if (buck->key.value == key)
+       {
+               table->bucket[bucknum] = buck->next;
+               return;
+       }
+
+
+       while(buck->next)
+       {
+               if (buck->next->key.value == key)
+               {
+                       buck->next = buck->next->next;
+                       return;
+               }
+
+               buck = buck->next;
+       }
+       return;
+}