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)
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 (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;
else if (list->next == NULL)
list->next = newSetupFileList(token, value);
else
- setTokenValue(list->next, token, value);
+ setListEntry(list->next, token, value);
}
#ifdef DEBUG
/*
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.
+
+ 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;
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 =
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)
#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));
#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;
- SetupFileHash *setup_file_hash = newSetupFileHash();
+ void *setup_file_data;
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);
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);
- 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;
+
+ if (first_valid_list_entry == NULL)
+ Error(ERR_WARN, "configuration file '%s' is empty", filename);
+ }
+
+ return setup_file_data;
+}
- return setup_file_hash;
+SetupFileList *loadSetupFileList(char *filename)
+{
+ return (SetupFileList *)loadSetupFileData(filename, FALSE);
+}
+
+SetupFileHash *loadSetupFileHash(char *filename)
+{
+ return (SetupFileHash *)loadSetupFileData(filename, TRUE);
}
void checkSetupFileHashIdentifier(SetupFileHash *setup_file_hash,
levelnum_value = atoi(levelnum_str);
+#if 0
if (levelnum_value < leveldir_current->first_level)
{
Error(ERR_WARN, "additional level %d found", levelnum_value);
Error(ERR_WARN, "additional level %d found", levelnum_value);
leveldir_current->last_level = levelnum_value;
}
+#endif
}
}