mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-12-22 12:12:35 +03:00
Improve the message loading API to return error codes.
Returning an error instead of simply calling die allows more robust error handling. Secondly initialisation may continue even if the messages have not been loaded which is more friendly than simply dropping dead with no communication to the user.
This commit is contained in:
parent
808783c2eb
commit
94ab63319f
151
utils/messages.c
151
utils/messages.c
@ -17,8 +17,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* Localised message support (implementation).
|
||||
/**
|
||||
* \file
|
||||
* Localised message support implementation.
|
||||
*
|
||||
* Native language messages are loaded from a file and stored hashed by key for
|
||||
* fast access.
|
||||
@ -37,7 +38,7 @@
|
||||
#include "utils/utils.h"
|
||||
#include "utils/hashtable.h"
|
||||
|
||||
/** We store the messages in a fixed-size hash table. */
|
||||
/** Messages are stored in a fixed-size hash table. */
|
||||
#define HASH_SIZE 101
|
||||
|
||||
/** The hash table used to store the standard Messages file for the old API */
|
||||
@ -47,32 +48,38 @@ static struct hash_table *messages_hash = NULL;
|
||||
* Read keys and values from messages file.
|
||||
*
|
||||
* \param path pathname of messages file
|
||||
* \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.
|
||||
* \param ctx reference of hash table to merge with.
|
||||
* \return NSERROR_OK on sucess and ctx updated or error code on faliure.
|
||||
*/
|
||||
|
||||
struct hash_table *messages_load_ctx(const char *path, struct hash_table *ctx)
|
||||
static nserror messages_load_ctx(const char *path, struct hash_table **ctx)
|
||||
{
|
||||
char s[400];
|
||||
gzFile fp;
|
||||
char s[400]; /* line buffer */
|
||||
gzFile fp; /* compressed file handle */
|
||||
struct hash_table *nctx; /* new context */
|
||||
|
||||
assert(path != NULL);
|
||||
|
||||
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 = gzopen(path, "r");
|
||||
if (!fp) {
|
||||
snprintf(s, sizeof s, "Unable to open messages file "
|
||||
"\"%.100s\": %s", path, strerror(errno));
|
||||
s[sizeof s - 1] = 0;
|
||||
LOG(("%s", s));
|
||||
hash_destroy(ctx);
|
||||
return NULL;
|
||||
LOG(("Unable to open messages file \"%.100s\": %s",
|
||||
path, strerror(errno)));
|
||||
|
||||
return NSERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (*ctx == NULL) {
|
||||
nctx = hash_create(HASH_SIZE);
|
||||
} else {
|
||||
/**
|
||||
* \note The passed hash is not copied here so this
|
||||
* updates in place.
|
||||
*/
|
||||
nctx = *ctx;
|
||||
}
|
||||
if (nctx == NULL) {
|
||||
LOG(("Unable to create hash table for messages file %s", path));
|
||||
gzclose(fp);
|
||||
return NSERROR_NOMEM;
|
||||
}
|
||||
|
||||
while (gzgets(fp, s, sizeof s)) {
|
||||
@ -88,52 +95,24 @@ struct hash_table *messages_load_ctx(const char *path, struct hash_table *ctx)
|
||||
*colon = 0; /* terminate key */
|
||||
value = colon + 1;
|
||||
|
||||
if (hash_add(ctx, s, value) == false) {
|
||||
if (hash_add(nctx, s, value) == false) {
|
||||
LOG(("Unable to add %s:%s to hash table of %s",
|
||||
s, value, path));
|
||||
gzclose(fp);
|
||||
hash_destroy(ctx);
|
||||
return NULL;
|
||||
if (*ctx == NULL) {
|
||||
hash_destroy(nctx);
|
||||
}
|
||||
return NSERROR_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
gzclose(fp);
|
||||
|
||||
return ctx;
|
||||
*ctx = nctx;
|
||||
|
||||
return NSERROR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read keys and values from messages file into the standard Messages hash.
|
||||
*
|
||||
* \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.
|
||||
*/
|
||||
|
||||
void messages_load(const char *path)
|
||||
{
|
||||
struct hash_table *m;
|
||||
char s[400];
|
||||
|
||||
if (path == NULL)
|
||||
return;
|
||||
|
||||
LOG(("Loading Messages from '%s'", path));
|
||||
|
||||
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, sizeof s,
|
||||
"Unable to open Messages file '%s'.", path);
|
||||
die(s);
|
||||
}
|
||||
|
||||
messages_hash = m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fast lookup of a message by key.
|
||||
@ -142,22 +121,42 @@ void messages_load(const char *path)
|
||||
* \param ctx context of messages file to look up in
|
||||
* \return value of message, or key if not found
|
||||
*/
|
||||
|
||||
const char *messages_get_ctx(const char *key, struct hash_table *ctx)
|
||||
static const char *
|
||||
messages_get_ctx(const char *key, struct hash_table *ctx)
|
||||
{
|
||||
const char *r;
|
||||
const char *r = NULL;
|
||||
|
||||
assert(key != NULL);
|
||||
|
||||
/* If we're called with no context, it's nicer to return the
|
||||
* key rather than explode - this allows attempts to get messages
|
||||
* before messages_hash is set up to fail gracefully, for example */
|
||||
if (ctx == NULL)
|
||||
return key;
|
||||
/* allow attempts to retrieve messages before context is set up. */
|
||||
if (ctx != NULL) {
|
||||
r = hash_get(ctx, key);
|
||||
}
|
||||
|
||||
r = hash_get(ctx, key);
|
||||
/* If called with no context or unable to retrive a value
|
||||
* return the key.
|
||||
*/
|
||||
if (r == NULL) {
|
||||
r = key;
|
||||
}
|
||||
|
||||
return r ? r : key;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* exported interface documented in messages.h */
|
||||
nserror messages_load(const char *path)
|
||||
{
|
||||
nserror err;
|
||||
|
||||
if (path == NULL) {
|
||||
err = NSERROR_BAD_PARAMETER;
|
||||
} else {
|
||||
LOG(("Loading Messages from '%s'", path));
|
||||
|
||||
err = messages_load_ctx(path, &messages_hash);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* exported interface documented in messages.h */
|
||||
@ -189,26 +188,14 @@ char *messages_get_buff(const char *key, ...)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* exported function documented in utils/messages.h */
|
||||
const char *messages_get(const char *key)
|
||||
{
|
||||
return messages_get_ctx(key, messages_hash);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* lookup of a message by errorcode from the standard Messages hash.
|
||||
*
|
||||
* \param code errorcode of message
|
||||
* \return message text
|
||||
*/
|
||||
|
||||
/* exported function documented in utils/messages.h */
|
||||
const char *messages_get_errorcode(nserror code)
|
||||
{
|
||||
switch (code) {
|
||||
|
@ -36,9 +36,23 @@
|
||||
#include "utils/errors.h"
|
||||
#include "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);
|
||||
/**
|
||||
* Read keys and values from messages file into the standard Messages hash.
|
||||
*
|
||||
* The messages are merged with any previously loaded messages. Any keys which
|
||||
* are present already are replaced with the new value.
|
||||
*
|
||||
* \param path pathname of messages file.
|
||||
* \return NSERROR_OK on success or error code on faliure.
|
||||
*/
|
||||
nserror messages_load(const char *path);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
const char *messages_get(const char *key);
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user