From 8d7172fd17e7b49f236ab97848872f2c91d800da Mon Sep 17 00:00:00 2001 From: Rob Kendrick Date: Mon, 21 Aug 2006 22:07:10 +0000 Subject: Make Messages file parsing and searching use new re-usable hash table library svn path=/trunk/netsurf/; revision=2879 --- utils/messages.c | 138 +++++++++++++++++++++++-------------------------------- utils/messages.h | 10 ++-- 2 files changed, 65 insertions(+), 83 deletions(-) (limited to 'utils') diff --git a/utils/messages.c b/utils/messages.c index 05aae858f..a40c2b3bf 100644 --- a/utils/messages.c +++ b/utils/messages.c @@ -3,6 +3,7 @@ * Licensed under the GNU General Public License, * http://www.opensource.org/licenses/gpl-license * Copyright 2004 James Bursa + * Copyright 2006 Rob Kendrick */ /** \file @@ -15,46 +16,38 @@ #include #include #include +#include #include #include "netsurf/utils/log.h" #include "netsurf/utils/messages.h" #include "netsurf/utils/utils.h" +#include "netsurf/utils/hashtable.h" /** We store the messages in a fixed-size hash table. */ #define HASH_SIZE 101 -/** Maximum length of a key. */ -#define MAX_KEY_LENGTH 24 - -/** Entry in the messages hash table. */ -struct messages_entry { - struct messages_entry *next; /**< Next entry in this hash chain. */ - char key[MAX_KEY_LENGTH]; - char value[1]; -}; - -/** Localised messages hash table. */ -static struct messages_entry *messages_table[HASH_SIZE]; - - -static unsigned int messages_hash(const char *s); - +/** The hash table used to store the standard Messages file for the old API */ +static struct hash_table *messages_hash = NULL; /** * Read keys and values from messages file. * * \param path pathname of messages file - * - * The messages are merged with any previously loaded messages. Any keys which - * are present already are replaced with the new value. - * - * Exits through die() in case of error. + * \param ctx struct hash_table to merge with, or NULL for a new one. + * \return struct hash_table containing the context or NULL in case of error. */ -void messages_load(const char *path) +struct hash_table *messages_load_ctx(const char *path, struct hash_table *ctx) { char s[400]; FILE *fp; + + ctx = (ctx != NULL) ? ctx : hash_create(HASH_SIZE); + + if (ctx == NULL) { + LOG(("Unable to create hash table for messages file %s", path)); + return NULL; + } fp = fopen(path, "r"); if (!fp) { @@ -62,14 +55,11 @@ void messages_load(const char *path) "\"%.100s\": %s", path, strerror(errno)); s[sizeof s - 1] = 0; LOG(("%s", s)); - die(s); + return NULL; } while (fgets(s, sizeof s, fp)) { char *colon, *value; - unsigned int slot; - struct messages_entry *entry; - size_t length; if (s[0] == 0 || s[0] == '#') continue; @@ -80,82 +70,70 @@ void messages_load(const char *path) continue; *colon = 0; /* terminate key */ value = colon + 1; - length = strlen(value); - - entry = malloc(sizeof *entry + length + 1); - if (!entry) { - snprintf(s, sizeof s, "Not enough memory to load " - "messages file \"%.100s\".", path); - s[sizeof s - 1] = 0; - LOG(("%s", s)); - die(s); + + if (hash_add(ctx, s, value) == false) { + LOG(("Unable to add %s:%s to hash table of %s", + s, value, path)); + fclose(fp); + return NULL; } - strncpy(entry->key, s, MAX_KEY_LENGTH); - strcpy(entry->value, value); - slot = messages_hash(entry->key); - entry->next = messages_table[slot]; - messages_table[slot] = entry; } fclose(fp); + + return ctx; } - /** - * Fast lookup of a message by key. + * Read keys and values from messages file into the standard Messages hash. * - * \param key key of message - * \return value of message, or key if not found + * \param path pathname of messages file + * + * The messages are merged with any previously loaded messages. Any keys which + * are present already are replaced with the new value. + * + * Exits through die() in case of error. */ -const char *messages_get(const char *key) +void messages_load(const char *path) { - struct messages_entry *entry; - - for (entry = messages_table[messages_hash(key)]; - entry && strcasecmp(entry->key, key) != 0; - entry = entry->next) - ; - if (!entry) - return key; - return entry->value; + struct hash_table *m; + char s[400]; + + m = messages_load_ctx(path, messages_hash); + if (m == NULL) { + LOG(("Unable to open Messages file '%s'. Possible reason: %s", + path, strerror(errno))); + snprintf(s, 400, "Unable to open Messages file '%s'.", path); + die(s); + } + + messages_hash = m; } - /** - * Hash function for keys. + * Fast lookup of a message by key. + * + * \param key key of message + * \param ctx context of messages file to look up in + * \return value of message, or key if not found */ -/* This is Fowler Noll Vo - a very fast and simple hash ideal for short - * strings. See http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash for more - * details. - */ -unsigned int messages_hash(const char *s) +const char *messages_get_ctx(const char *key, struct hash_table *ctx) { - unsigned int z = 0x01000193, i; - - if (s == NULL) - return 0; - - for (i = 0; i != MAX_KEY_LENGTH && s[i]; i++) { - z *= 0x01000193; - z ^= (s[i] & 0x1f); /* lower 5 bits, case insensitive */ - } + const char *r = hash_get(ctx, key); - return z % HASH_SIZE; + return r ? r : key; } - /** - * Dump set of loaded messages. + * Fast lookup of a message by key from the standard Messages hash. + * + * \param key key of message + * \return value of message, or key if not found */ -void messages_dump(void) +const char *messages_get(const char *key) { - unsigned int i; - for (i = 0; i != HASH_SIZE; i++) { - struct messages_entry *entry; - for (entry = messages_table[i]; entry; entry = entry->next) - printf("%.20s:%s\n", entry->key, entry->value); - } + return messages_get_ctx(key, messages_hash); } diff --git a/utils/messages.h b/utils/messages.h index 4ca079293..6f9dfb763 100644 --- a/utils/messages.h +++ b/utils/messages.h @@ -14,15 +14,19 @@ * messages_load() to read the file into memory. To lookup a key, use * messages_get("key"). * - * Only the first MAX_KEY_LENGTH (currently 24) characters of the key are - * significant. + * It can also load additional messages files into different contexts and allow + * you to look up values in it independantly from the standard shared Messages + * file table. Use the _ctx versions of the functions to do this. */ #ifndef _NETSURF_UTILS_MESSAGES_H_ #define _NETSURF_UTILS_MESSAGES_H_ +#include "netsurf/utils/hashtable.h" + void messages_load(const char *path); +struct hash_table *messages_load_ctx(const char *path, struct hash_table *ctx); +const char *messages_get_ctx(const char *key, struct hash_table *ctx); const char *messages_get(const char *key); -void messages_dump(void); #endif -- cgit v1.2.3