Complete.Org: Mailing Lists: Archives: freeciv-dev: May 2005:
[Freeciv-Dev] (PR#11779) [PATCH] New genlist code: registry section hash
Home

[Freeciv-Dev] (PR#11779) [PATCH] New genlist code: registry section hash

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: per@xxxxxxxxxxx
Subject: [Freeciv-Dev] (PR#11779) [PATCH] New genlist code: registry section hashtable
From: "Vasco Alexandre da Silva Costa" <vasc@xxxxxxxxxxxxxx>
Date: Sat, 7 May 2005 08:55:05 -0700
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=11779 >

> [per - Sat Jan 22 19:59:31 2005]:
> 
> Now that the API change has been done, the new genlist code itself is a
> rather small patch. Here it is.
> 
> But before I commit this, I want to make section lookups in registry.c
> into a hashtable lookup instead of a genlist search.

And here is a patch which does just that.

Index: utility/registry.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/utility/registry.c,v
retrieving revision 1.69
diff -u -u -r1.69 registry.c
--- utility/registry.c  22 Jan 2005 19:45:45 -0000      1.69
+++ utility/registry.c  7 May 2005 15:49:32 -0000
@@ -236,6 +236,14 @@
 section_file_insert_internal(struct section_file *my_section_file, 
                             char *fullpath);
 
+/* Only need use these explicitly on section_files constructed,
+   not for ones generated by section_file_load:
+*/
+static bool secfilehash_hashash(struct section_file *file);
+static void secfilehash_build(struct section_file *file,
+                             bool allow_duplicates);
+static void secfilehash_free(struct section_file *file);
+
 /**************************************************************************
   Return the filename the sectionfile was loaded as, or "(anonymous)"
   if this sectionfile was created rather than loaded from file.
@@ -258,6 +266,7 @@
 {
   file->filename = NULL;
   file->sections = section_list_new();
+  file->hash_sections = hash_new(hash_fval_string, hash_fcmp_string);
   file->num_entries = 0;
   file->hashd = NULL;
   file->sb = sbuf_new();
@@ -279,6 +288,10 @@
   section_list_free(file->sections);
   file->sections = NULL;
 
+  /* free the sections hash data: */
+  hash_free(file->hash_sections);
+  file->hash_sections = NULL;
+
   /* free the hash data: */
   if(secfilehash_hashash(file)) {
     secfilehash_free(file);
@@ -295,6 +308,26 @@
 }
 
 /**************************************************************************
+...
+**************************************************************************/
+static struct section*
+section_file_append_section(struct section_file *sf, const char *sec_name)
+{
+  struct section *psection;
+
+  psection = sbuf_malloc(sf->sb, sizeof(*psection));
+  psection->name = sbuf_strdup(sf->sb, sec_name);
+  psection->entries = entry_list_new();
+  section_list_append(sf->sections, psection);
+
+  if (!hash_insert(sf->hash_sections, psection->name, psection)) {
+    freelog(LOG_ERROR, "Section \"%s\" name collision", sec_name);
+  }
+
+  return psection;
+}
+
+/**************************************************************************
   Print log messages for any entries in the file which have
   not been looked up -- ie, unused or unrecognised entries.
   To mark an entry as used without actually doing anything with it,
@@ -359,20 +392,7 @@
 static struct section *find_section_by_name(struct section_file *sf,
                                            const char *name)
 {
-  /*
-   * Search backwards since on insertion the requested section is most
-   * likely at the end (on lookup it doesn't matter).
-   *
-   * Nonetheless this is slow if there are lots of sections.  We could have
-   * a hash on section names to speed it up.
-   */
-  section_list_iterate_rev(sf->sections, psection) {
-    if (strcmp(psection->name, name) == 0) {
-      return psection;
-    }
-  } section_list_iterate_rev_end;
-
-  return NULL;
+  return hash_lookup_data(sf->hash_sections, name);
 }      
 
 /**************************************************************************
@@ -432,10 +452,7 @@
       */
       psection = find_section_by_name(sf, tok);
       if (!psection) {
-       psection = sbuf_malloc(sb, sizeof(struct section));
-       psection->name = sbuf_strdup(sb, tok);
-       psection->entries = entry_list_new();
-       section_list_append(sf->sections, psection);
+       psection = section_file_append_section(sf, tok);
       }
       (void) inf_token_required(inf, INF_TOK_EOL);
       continue;
@@ -1254,7 +1271,6 @@
   return NULL;
 }
 
-
 /**************************************************************************
  The caller should ensure that "fullpath" should not refer to an entry
  which already exists in "my_section_file".  (Actually, in some cases
@@ -1301,11 +1317,8 @@
     return pentry;
   }
 
-  psection = sbuf_malloc(sb, sizeof(struct section));
-  psection->name = sbuf_strdup(sb, sec_name);
-  psection->entries = entry_list_new();
-  section_list_append(my_section_file->sections, psection);
-  
+  psection = section_file_append_section(my_section_file, sec_name);
+
   pentry = sbuf_malloc(sb, sizeof(struct entry));
   pentry->name = sbuf_strdup(sb, ent_name);
   entry_list_append(psection->entries, pentry);
@@ -1317,7 +1330,7 @@
 /**************************************************************************
  Return 0 if the section_file has not been setup for hashing.
 **************************************************************************/
-bool secfilehash_hashash(struct section_file *file)
+static bool secfilehash_hashash(struct section_file *file)
 {
   return (file->hashd && hash_num_buckets(file->hashd->htbl) != 0);
 }
@@ -1375,7 +1388,7 @@
  all entries must have unique names; in this case for duplicates
  the hash ref will be to the _last_ entry.
 **************************************************************************/
-void secfilehash_build(struct section_file *file, bool allow_duplicates)
+static void secfilehash_build(struct section_file *file, bool allow_duplicates)
 {
   struct hash_data *hashd;
   char buf[256];
@@ -1407,7 +1420,7 @@
 /**************************************************************************
  Free the memory allocated for the hash table.
 **************************************************************************/
-void secfilehash_free(struct section_file *file)
+static void secfilehash_free(struct section_file *file)
 {
   secfilehash_check(file);
   hash_free(file->hashd->htbl);
Index: utility/registry.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/utility/registry.h,v
retrieving revision 1.25
diff -u -u -r1.25 registry.h
--- utility/registry.h  22 Jul 2004 19:04:33 -0000      1.25
+++ utility/registry.h  7 May 2005 15:49:32 -0000
@@ -24,6 +24,7 @@
   char *filename;
   int num_entries;
   struct section_list *sections;
+  struct hash_table *hash_sections;
   struct hash_data *hashd;
   struct sbuffer *sb;
 };
@@ -113,11 +114,4 @@
 char **secfile_get_section_entries(struct section_file *my_section_file,
                                   const char *section, int *num);
 
-/* Only need use these explicitly on section_files constructed,
-   not for ones generated by section_file_load:
-*/
-bool secfilehash_hashash(struct section_file *file);
-void secfilehash_build(struct section_file *file, bool allow_duplicates);
-void secfilehash_free(struct section_file *file);
-
 #endif  /* FC__REGISTRY_H */

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#11779) [PATCH] New genlist code: registry section hashtable, Vasco Alexandre da Silva Costa <=