From: Bruno Haible Date: Tue, 20 Nov 2001 14:47:05 +0000 (+0000) Subject: Add an optional hash table to each message list. X-Git-Tag: v0.11~283 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2bc823ea6f3c93b1437638a44e14c53d7a7747aa;p=thirdparty%2Fgettext.git Add an optional hash table to each message list. --- diff --git a/src/ChangeLog b/src/ChangeLog index 78310cfda..36b1d1ab4 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,36 @@ +2001-11-17 Bruno Haible + + * message.h: Include hash.h. + (message_list_ty): Add use_hashtable, htable fields. + (message_list_alloc): Add 'use_hashtable' argument. + (msgdomain_alloc): Likewise. + (msgdomain_list_ty): Add use_hashtable field. + (msgdomain_list_alloc): Add 'use_hashtable' argument. + * message.c: Include hash.h. + (message_list_alloc): Add 'use_hashtable' argument. + (message_list_free): Delete the hash table if present. + (message_list_append): If a hash table is in use, verify no duplicates. + (message_list_prepend): Likewise. + (message_list_remove_if_not): Remove hash table after removal. + (message_list_search): Use hash table if present. + (msgdomain_alloc): Add 'use_hashtable' argument. + (msgdomain_list_alloc): Add 'use_hashtable' argument. + (msgdomain_list_sublist): Use 'use_hashtable'. + * msgcmp.c (compare): Update. + (compare_constructor): Allocate a message list with hash table. + * msgfmt.c (new_domain): Allocate a message list with hash table. + Remove impossible error message. + * msgl-cat.c (catenate_msgdomain_list): Allocate message lists with + hash table. + * msgmerge.c (merge): Update. + * msgunfmt.c (main): Update. + * read-po.c (readall_constructor): Allocate a message list with hash + table if and only if duplicates will lead to an error message. + * xgettext.c (main): Allocate a message list with hash table, to + speed up insertion. + (exclude_directive_message): Allocate a message list with hash table, + to speed up exclusion test. + 2001-11-17 Bruno Haible * message.h (msgdomain_list_sublist): Change last argument to bool. diff --git a/src/message.c b/src/message.c index 7202c5384..08dbfafc4 100644 --- a/src/message.c +++ b/src/message.c @@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "fstrcmp.h" +#include "hash.h" #include "xmalloc.h" #include "strstr.h" #include "system.h" @@ -425,7 +426,8 @@ message_merge (def, ref) message_list_ty * -message_list_alloc () +message_list_alloc (use_hashtable) + bool use_hashtable; { message_list_ty *mlp; @@ -433,6 +435,8 @@ message_list_alloc () mlp->nitems = 0; mlp->nitems_max = 0; mlp->item = NULL; + if ((mlp->use_hashtable = use_hashtable)) + init_hash (&mlp->htable, 10); return mlp; } @@ -447,6 +451,8 @@ message_list_free (mlp) message_free (mlp->item[j]); if (mlp->item) free (mlp->item); + if (mlp->use_hashtable) + delete_hash (&mlp->htable); free (mlp); } @@ -465,6 +471,12 @@ message_list_append (mlp, mp) mlp->item = xrealloc (mlp->item, nbytes); } mlp->item[mlp->nitems++] = mp; + + if (mlp->use_hashtable) + if (insert_entry (&mlp->htable, mp->msgid, strlen (mp->msgid) + 1, mp)) + /* A message list has duplicates, although it was allocated with the + assertion that it wouldn't have duplicates. It is a bug. */ + abort (); } @@ -487,6 +499,12 @@ message_list_prepend (mlp, mp) mlp->item[j] = mlp->item[j - 1]; mlp->item[0] = mp; mlp->nitems++; + + if (mlp->use_hashtable) + if (insert_entry (&mlp->htable, mp->msgid, strlen (mp->msgid) + 1, mp)) + /* A message list has duplicates, although it was allocated with the + assertion that it wouldn't have duplicates. It is a bug. */ + abort (); } @@ -504,6 +522,13 @@ message_list_delete_nth (mlp, n) for (j = n + 1; j < mlp->nitems; ++j) mlp->item[j - 1] = mlp->item[j]; mlp->nitems--; + + if (mlp->use_hashtable) + { + /* Our simple-minded hash tables don't support removal. */ + delete_hash (&mlp->htable); + mlp->use_hashtable = false; + } } #endif @@ -518,6 +543,12 @@ message_list_remove_if_not (mlp, predicate) for (j = 0, i = 0; j < mlp->nitems; j++) if (predicate (mlp->item[j])) mlp->item[i++] = mlp->item[j]; + if (mlp->use_hashtable && i < mlp->nitems) + { + /* Our simple-minded hash tables don't support removal. */ + delete_hash (&mlp->htable); + mlp->use_hashtable = false; + } mlp->nitems = i; } @@ -527,17 +558,29 @@ message_list_search (mlp, msgid) message_list_ty *mlp; const char *msgid; { - size_t j; - - for (j = 0; j < mlp->nitems; ++j) + if (mlp->use_hashtable) { message_ty *mp; - mp = mlp->item[j]; - if (strcmp (msgid, mp->msgid) == 0) + if (find_entry (&mlp->htable, msgid, strlen (msgid) + 1, (void **) &mp)) + return NULL; + else return mp; } - return NULL; + else + { + size_t j; + + for (j = 0; j < mlp->nitems; ++j) + { + message_ty *mp; + + mp = mlp->item[j]; + if (strcmp (msgid, mp->msgid) == 0) + return mp; + } + return NULL; + } } @@ -699,14 +742,15 @@ message_list_list_search_fuzzy (mllp, msgid) msgdomain_ty* -msgdomain_alloc (domain) +msgdomain_alloc (domain, use_hashtable) const char *domain; + bool use_hashtable; { msgdomain_ty *mdp; mdp = (msgdomain_ty *) xmalloc (sizeof (msgdomain_ty)); mdp->domain = domain; - mdp->messages = message_list_alloc (); + mdp->messages = message_list_alloc (use_hashtable); return mdp; } @@ -721,7 +765,8 @@ msgdomain_free (mdp) msgdomain_list_ty * -msgdomain_list_alloc () +msgdomain_list_alloc (use_hashtable) + bool use_hashtable; { msgdomain_list_ty *mdlp; @@ -732,7 +777,8 @@ msgdomain_list_alloc () mdlp->nitems_max = 1; mdlp->item = (msgdomain_ty **) xmalloc (mdlp->nitems_max * sizeof (msgdomain_ty *)); - mdlp->item[0] = msgdomain_alloc (MESSAGE_DOMAIN_DEFAULT); + mdlp->item[0] = msgdomain_alloc (MESSAGE_DOMAIN_DEFAULT, use_hashtable); + mdlp->use_hashtable = use_hashtable; return mdlp; } @@ -798,7 +844,7 @@ msgdomain_list_sublist (mdlp, domain, create) if (create) { - msgdomain_ty *mdp = msgdomain_alloc (domain); + msgdomain_ty *mdp = msgdomain_alloc (domain, mdlp->use_hashtable); msgdomain_list_append (mdlp, mdp); return mdp->messages; } diff --git a/src/message.h b/src/message.h index 0571e99cc..7e794ec33 100644 --- a/src/message.h +++ b/src/message.h @@ -22,6 +22,7 @@ #include "str-list.h" #include "pos.h" +#include "hash.h" #include @@ -159,10 +160,16 @@ struct message_list_ty message_ty **item; size_t nitems; size_t nitems_max; + bool use_hashtable; + hash_table htable; /* Table mapping msgid to 'message_ty *'. */ }; +/* Create a fresh message list. + If USE_HASHTABLE is true, a hash table will be used to speed up + message_list_search(). USE_HASHTABLE can only be set to true if it is + known that the message list will not contain duplicate msgids. */ extern message_list_ty * - message_list_alloc PARAMS ((void)); + message_list_alloc PARAMS ((bool use_hashtable)); extern void message_list_free PARAMS ((message_list_ty *mlp)); extern void @@ -216,7 +223,7 @@ struct msgdomain_ty }; extern msgdomain_ty * - msgdomain_alloc PARAMS ((const char *domain)); + msgdomain_alloc PARAMS ((const char *domain, bool use_hashtable)); extern void msgdomain_free PARAMS ((msgdomain_ty *mdp)); @@ -227,10 +234,11 @@ struct msgdomain_list_ty msgdomain_ty **item; size_t nitems; size_t nitems_max; + bool use_hashtable; }; extern msgdomain_list_ty * - msgdomain_list_alloc PARAMS ((void)); + msgdomain_list_alloc PARAMS ((bool use_hashtable)); extern void msgdomain_list_free PARAMS ((msgdomain_list_ty *mdlp)); extern void diff --git a/src/msgcmp.c b/src/msgcmp.c index ab08fbcd2..621eea512 100644 --- a/src/msgcmp.c +++ b/src/msgcmp.c @@ -282,7 +282,7 @@ compare (fn1, fn2) the xgettext program. */ ref = grammar (fn2); - empty_list = message_list_alloc (); + empty_list = message_list_alloc (false); /* Every entry in the xgettext generated file must be matched by a (single) entry in the human created file. */ @@ -367,7 +367,7 @@ compare_constructor (that) { compare_class_ty *this = (compare_class_ty *) that; - this->mdlp = msgdomain_list_alloc (); + this->mdlp = msgdomain_list_alloc (true); this->domain = MESSAGE_DOMAIN_DEFAULT; this->mlp = msgdomain_list_sublist (this->mdlp, this->domain, true); } diff --git a/src/msgfmt.c b/src/msgfmt.c index f88adc41a..8698d9bf2 100644 --- a/src/msgfmt.c +++ b/src/msgfmt.c @@ -597,9 +597,8 @@ new_domain (name, file_name) struct msg_domain *domain; domain = (struct msg_domain *) xmalloc (sizeof (struct msg_domain)); - domain->mlp = message_list_alloc (); - if (init_hash (&domain->symbol_tab, 100) != 0) - error (EXIT_FAILURE, errno, _("while creating hash table")); + domain->mlp = message_list_alloc (true); + init_hash (&domain->symbol_tab, 100); domain->domain_name = name; domain->file_name = file_name; domain->next = NULL; diff --git a/src/msgl-cat.c b/src/msgl-cat.c index 6d6cfd4cb..5baced9e9 100644 --- a/src/msgl-cat.c +++ b/src/msgl-cat.c @@ -269,7 +269,7 @@ domain \"%s\" in input file `%s' doesn't contain a header entry with a charset s If for a message, there is at least one non-fuzzy, non-empty translation, use only the non-fuzzy, non-empty translations. Otherwise use the fuzzy or empty translations as well. */ - total_mdlp = msgdomain_list_alloc (); + total_mdlp = msgdomain_list_alloc (true); for (n = 0; n < nfiles; n++) { msgdomain_list_ty *mdlp = mdlps[n]; diff --git a/src/msgmerge.c b/src/msgmerge.c index 672ca125d..35bac2223 100644 --- a/src/msgmerge.c +++ b/src/msgmerge.c @@ -606,7 +606,7 @@ merge (fn1, fn2, defp) message_list_list_append (definitions, NULL); if (compendiums) message_list_list_append_list (definitions, compendiums); - empty_list = message_list_alloc (); + empty_list = message_list_alloc (false); /* This is the references file, created by groping the sources with the xgettext program. */ @@ -621,7 +621,7 @@ merge (fn1, fn2, defp) message_list_prepend (ref->item[k]->messages, refheader); } - result = msgdomain_list_alloc (); + result = msgdomain_list_alloc (false); processed = 0; /* Every reference must be matched with its definition. */ diff --git a/src/msgunfmt.c b/src/msgunfmt.c index 0d95d0033..6c7f9ca36 100644 --- a/src/msgunfmt.c +++ b/src/msgunfmt.c @@ -227,7 +227,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ { message_list_ty *mlp; - mlp = message_list_alloc (); + mlp = message_list_alloc (false); if (optind < argc) { do @@ -237,7 +237,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ else read_mo_file (mlp, "-"); - result = msgdomain_list_alloc (); + result = msgdomain_list_alloc (false); result->item[0]->messages = mlp; } diff --git a/src/read-po.c b/src/read-po.c index 891947bc9..b5a2702e7 100644 --- a/src/read-po.c +++ b/src/read-po.c @@ -102,7 +102,7 @@ readall_constructor (that) readall_class_ty *this = (readall_class_ty *) that; size_t i; - this->mdlp = msgdomain_list_alloc (); + this->mdlp = msgdomain_list_alloc (!allow_duplicates); this->domain = MESSAGE_DOMAIN_DEFAULT; this->mlp = msgdomain_list_sublist (this->mdlp, this->domain, true); this->comment = NULL; diff --git a/src/xgettext.c b/src/xgettext.c index 053ec32e6..2f4e7afb0 100644 --- a/src/xgettext.c +++ b/src/xgettext.c @@ -424,7 +424,7 @@ xgettext cannot work without keywords to look for")); string_list_append_unique (file_list, argv[cnt]); /* Allocate a message list to remember all the messages. */ - mdlp = msgdomain_list_alloc (); + mdlp = msgdomain_list_alloc (true); /* Generate a header, so that we know how and when this PO file was created. */ @@ -622,7 +622,7 @@ exclude_directive_message (pop, msgid, msgid_pos, msgid_plural, /* See if this message ID has been seen before. */ if (exclude == NULL) - exclude = message_list_alloc (); + exclude = message_list_alloc (true); mp = message_list_search (exclude, msgid); if (mp != NULL) free (msgid);