rnd-20030426-2-src
[rocksndiamonds.git] / src / libgame / setup.c
index 940d6bad827d9fab1639f101e65d0505839bd7c3..47bc9b4732f24e24e7ee38a3d367ed9acc6bfd49 100644 (file)
@@ -1040,6 +1040,18 @@ char *getFormattedSetupEntry(char *token, char *value)
   return entry;
 }
 
   return entry;
 }
 
+SetupFileList *newSetupFileList(char *token, char *value)
+{
+  SetupFileList *new = checked_malloc(sizeof(SetupFileList));
+
+  new->token = getStringCopy(token);
+  new->value = getStringCopy(value);
+
+  new->next = NULL;
+
+  return new;
+}
+
 void freeSetupFileList(SetupFileList *list)
 {
   if (list == NULL)
 void freeSetupFileList(SetupFileList *list)
 {
   if (list == NULL)
@@ -1054,19 +1066,7 @@ void freeSetupFileList(SetupFileList *list)
   free(list);
 }
 
   free(list);
 }
 
-SetupFileList *newSetupFileList(char *token, char *value)
-{
-  SetupFileList *new = checked_malloc(sizeof(SetupFileList));
-
-  new->token = getStringCopy(token);
-  new->value = getStringCopy(value);
-
-  new->next = NULL;
-
-  return new;
-}
-
-char *getTokenValue(SetupFileList *list, char *token)
+char *getListEntry(SetupFileList *list, char *token)
 {
   if (list == NULL)
     return NULL;
 {
   if (list == NULL)
     return NULL;
@@ -1074,10 +1074,10 @@ char *getTokenValue(SetupFileList *list, char *token)
   if (strcmp(list->token, token) == 0)
     return list->value;
   else
   if (strcmp(list->token, token) == 0)
     return list->value;
   else
-    return getTokenValue(list->next, token);
+    return getListEntry(list->next, token);
 }
 
 }
 
-void setTokenValue(SetupFileList *list, char *token, char *value)
+void setListEntry(SetupFileList *list, char *token, char *value)
 {
   if (list == NULL)
     return;
 {
   if (list == NULL)
     return;
@@ -1092,7 +1092,7 @@ void setTokenValue(SetupFileList *list, char *token, char *value)
   else if (list->next == NULL)
     list->next = newSetupFileList(token, value);
   else
   else if (list->next == NULL)
     list->next = newSetupFileList(token, value);
   else
-    setTokenValue(list->next, token, value);
+    setListEntry(list->next, token, value);
 }
 
 #ifdef DEBUG
 }
 
 #ifdef DEBUG
@@ -1125,11 +1125,19 @@ static unsigned int get_hash_from_key(void *key)
   /*
     djb2
 
   /*
     djb2
 
-    this algorithm (k=33) was first reported by dan bernstein many years ago in
-    comp.lang.c. another version of this algorithm (now favored by bernstein)
-    uses xor: hash(i) = hash(i - 1) * 33 ^ str[i]; the magic of number 33 (why
+    This algorithm (k=33) was first reported by Dan Bernstein many years ago in
+    'comp.lang.c'. Another version of this algorithm (now favored by Bernstein)
+    uses XOR: hash(i) = hash(i - 1) * 33 ^ str[i]; the magic of number 33 (why
     it works better than many other constants, prime or not) has never been
     adequately explained.
     it works better than many other constants, prime or not) has never been
     adequately explained.
+
+    If you just want to have a good hash function, and cannot wait, djb2
+    is one of the best string hash functions i know. It has excellent
+    distribution and speed on many different sets of keys and table sizes.
+    You are not likely to do better with one of the "well known" functions
+    such as PJW, K&R, etc.
+
+    Ozan (oz) Yigit [http://www.cs.yorku.ca/~oz/hash.html]
   */
 
   char *str = (char *)key;
   */
 
   char *str = (char *)key;
@@ -1147,15 +1155,6 @@ static int keys_are_equal(void *key1, void *key2)
   return (strcmp((char *)key1, (char *)key2) == 0);
 }
 
   return (strcmp((char *)key1, (char *)key2) == 0);
 }
 
-void freeSetupFileHash(SetupFileHash *hash)
-{
-  if (hash == NULL)
-    return;
-
-  hashtable_destroy(hash, 1);  /* 1 == also free values */
-  free(hash);
-}
-
 SetupFileHash *newSetupFileHash()
 {
   SetupFileHash *new_hash =
 SetupFileHash *newSetupFileHash()
 {
   SetupFileHash *new_hash =
@@ -1164,6 +1163,14 @@ SetupFileHash *newSetupFileHash()
   return new_hash;
 }
 
   return new_hash;
 }
 
+void freeSetupFileHash(SetupFileHash *hash)
+{
+  if (hash == NULL)
+    return;
+
+  hashtable_destroy(hash, 1);  /* 1 == also free values stored in hash */
+}
+
 char *getHashEntry(SetupFileHash *hash, char *token)
 {
   if (hash == NULL)
 char *getHashEntry(SetupFileHash *hash, char *token)
 {
   if (hash == NULL)
@@ -1191,26 +1198,6 @@ void setHashEntry(SetupFileHash *hash, char *token, char *value)
 #ifdef DEBUG
 static void printSetupFileHash(SetupFileHash *hash)
 {
 #ifdef DEBUG
 static void printSetupFileHash(SetupFileHash *hash)
 {
-#if 0
-  if (hash == NULL)
-    return;
-
-  /* iterator constructor only returns valid iterator for non-empty hash */
-  if (hash != NULL && hashtable_count(hash) > 0)
-  {
-    struct hashtable_itr *itr = hashtable_iterator(hash);
-
-    do
-    {
-      printf("token: '%s'\n", (char *)hashtable_iterator_key(itr));
-      printf("value: '%s'\n", (char *)hashtable_iterator_value(itr));
-    }
-    while (hashtable_iterator_advance(itr));
-
-    free(itr);
-  }
-#endif
-
   BEGIN_HASH_ITERATION(hash, itr)
   {
     printf("token: '%s'\n", HASH_ITERATION_TOKEN(itr));
   BEGIN_HASH_ITERATION(hash, itr)
   {
     printf("token: '%s'\n", HASH_ITERATION_TOKEN(itr));
@@ -1221,14 +1208,19 @@ static void printSetupFileHash(SetupFileHash *hash)
 #endif
 #endif
 
 #endif
 #endif
 
-SetupFileHash *loadSetupFileHash(char *filename)
+static void *loadSetupFileData(char *filename, boolean use_hash)
 {
   int line_len;
   char line[MAX_LINE_LEN];
   char *token, *value, *line_ptr;
 {
   int line_len;
   char line[MAX_LINE_LEN];
   char *token, *value, *line_ptr;
-  SetupFileHash *setup_file_hash = newSetupFileHash();
+  void *setup_file_data;
   FILE *file;
 
   FILE *file;
 
+  if (use_hash)
+    setup_file_data = newSetupFileHash();
+  else
+    setup_file_data = newSetupFileList("", "");
+
   if (!(file = fopen(filename, MODE_READ)))
   {
     Error(ERR_WARN, "cannot open configuration file '%s'", filename);
   if (!(file = fopen(filename, MODE_READ)))
   {
     Error(ERR_WARN, "cannot open configuration file '%s'", filename);
@@ -1288,15 +1280,46 @@ SetupFileHash *loadSetupFileHash(char *filename)
        break;
 
     if (*token && *value)
        break;
 
     if (*token && *value)
-      setHashEntry(setup_file_hash, token, value);
+    {
+      if (use_hash)
+       setHashEntry((SetupFileHash *)setup_file_data, token, value);
+      else
+       setListEntry((SetupFileList *)setup_file_data, token, value);
+    }
   }
 
   fclose(file);
 
   }
 
   fclose(file);
 
-  if (hashtable_count(setup_file_hash) == 0)
-    Error(ERR_WARN, "configuration file '%s' is empty", filename);
+  if (use_hash)
+  {
+    if (hashtable_count((SetupFileHash *)setup_file_data) == 0)
+      Error(ERR_WARN, "configuration file '%s' is empty", filename);
+  }
+  else
+  {
+    SetupFileList *setup_file_list = (SetupFileList *)setup_file_data;
+    SetupFileList *first_valid_list_entry = setup_file_list->next;
+
+    /* free empty list header */
+    setup_file_list->next = NULL;
+    freeSetupFileList(setup_file_list);
+    setup_file_data = first_valid_list_entry;
 
 
-  return setup_file_hash;
+    if (first_valid_list_entry == NULL)
+      Error(ERR_WARN, "configuration file '%s' is empty", filename);
+  }
+
+  return setup_file_data;
+}
+
+SetupFileList *loadSetupFileList(char *filename)
+{
+  return (SetupFileList *)loadSetupFileData(filename, FALSE);
+}
+
+SetupFileHash *loadSetupFileHash(char *filename)
+{
+  return (SetupFileHash *)loadSetupFileData(filename, TRUE);
 }
 
 void checkSetupFileHashIdentifier(SetupFileHash *setup_file_hash,
 }
 
 void checkSetupFileHashIdentifier(SetupFileHash *setup_file_hash,