]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Add an optional hash table to each message list.
authorBruno Haible <bruno@clisp.org>
Tue, 20 Nov 2001 14:47:05 +0000 (14:47 +0000)
committerBruno Haible <bruno@clisp.org>
Sun, 21 Jun 2009 21:22:27 +0000 (23:22 +0200)
src/ChangeLog
src/message.c
src/message.h
src/msgcmp.c
src/msgfmt.c
src/msgl-cat.c
src/msgmerge.c
src/msgunfmt.c
src/read-po.c
src/xgettext.c

index 78310cfda9dcd897e9cc44d0c3a84a9dc287f94c..36b1d1ab41e666d2ca3e1b0804a421577c8e48d5 100644 (file)
@@ -1,3 +1,36 @@
+2001-11-17  Bruno Haible  <haible@clisp.cons.org>
+
+       * 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  <haible@clisp.cons.org>
 
        * message.h (msgdomain_list_sublist): Change last argument to bool.
index 7202c5384551b9a6d68724ebe795677804127c40..08dbfafc420a2f50887bf06a1ece0173bee6334c 100644 (file)
@@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include <string.h>
 
 #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;
     }
index 0571e99cc1580ad7301327702a5219763da02928..7e794ec33725df38732eee3e88ca1da46b461588 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "str-list.h"
 #include "pos.h"
+#include "hash.h"
 
 #include <stdbool.h>
 
@@ -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
index ab08fbcd286d7fc9ab693f43756f63a484b17962..621eea5120078b42042560d797542e56ffffd5c7 100644 (file)
@@ -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);
 }
index f88adc41aa0bda68c18ae76f474815430297f940..8698d9bf213381242b9279a49d6f7aaef41456f9 100644 (file)
@@ -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;
index 6d6cfd4cb182b7ff8dcfa57a34a3a5119bc8f6b5..5baced9e9fb7d328b5ff664491c9b37b0e4a6ed2 100644 (file)
@@ -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];
index 672ca125d4c447cb0bb91d3d05e9c5ab16ec6b80..35bac222320a6214d71859d2c79a580ffe6e9e14 100644 (file)
@@ -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. */
index 0d95d00335b8cef72e108421c67b5bf092c2b38a..6c7f9ca366b3ab93112eb3542dab246ddf8e47f4 100644 (file)
@@ -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;
     }
 
index 891947bc9d70aa97bf880925fecd2cf0b9531e78..b5a2702e703da5ff3b32db9155b186114b5cf5e5 100644 (file)
@@ -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;
index 053ec32e658ecf14bafca58190b1101e5f4ebd90..2f4e7afb08a645d95f3b2af460fadc0b8085d57e 100644 (file)
@@ -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);