Re: Hi, need any help?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 19:07, Sun 09 Mar 08, Martin Nordholts wrote:
> Hi Jan
> 
> We're absolutely interested in your contributions! Eagerly awaiting the
> patch :)
> 
> Best regards,
> Martin Nordholts
> 

Glad to hear it :) So here is the patch. Essentially, it
implements coalesced hashing as BablHashTable structure and
uses it as the babl database data structure. The code is not
long and is quite self-explanatory I believe, although I
wouldn't mind adding a few comments if needed. 

Regards,
 Jan
Index: babl/babl-util.c
===================================================================
--- babl/babl-util.c	(revision 290)
+++ babl/babl-util.c	(working copy)
@@ -22,6 +22,287 @@
 #include <math.h>
 #include "babl-memory.h"
 #include "babl-internal.h"
+#include "babl-util.h"
+
+#define UTIL_INITIAL_LIST_SIZE 0x7F
+#define UTIL_INITIAL_HT_MASK   0x7F
+
+/* static functions declarations */
+static inline int 
+hash_by_name (BablHashTable *htab,
+              const char    *str);
+
+static inline int 
+hash_by_id (BablHashTable *htab, 
+            int           id);
+
+static inline int 
+hash_insert (BablHashTable *htab,
+             Babl          *item);
+
+static void 
+hash_rehash (BablHashTable *htab);
+
+/* BablList functions */
+
+BablList *
+babl_list_init (void)
+{
+  BablList *list = babl_calloc (sizeof (BablList), 1);
+
+  list->size = UTIL_INITIAL_LIST_SIZE;
+  list->count = 0;
+  list->items = NULL;
+  if (list->size) 
+    {
+      list->items = babl_calloc (sizeof (BablInstance *), list->size);
+    }
+
+  return list;
+}
+
+void
+babl_list_destroy (BablList *list)
+{
+    babl_assert(list);
+
+    babl_free (list->items);
+    babl_free (list);
+}
+
+void
+babl_list_insert (BablList *list,
+                  Babl     *item)
+{
+  babl_assert(list);
+  babl_assert(BABL_IS_BABL(item));
+
+  if (list->size < list->count + 1)
+    {
+        Babl **new_items;
+
+        new_items = babl_realloc (list->items, (list->size * 2) * sizeof (BablInstance *));
+        babl_assert (new_items);
+        list->items = new_items;
+        memset (list->items + list->size, 0, list->size * sizeof (BablInstance *));
+        list->size *= 2;
+    }
+    list->items[list->count++] = item;
+}
+
+void
+babl_list_each_NEW (BablList         *list,
+                BablEachFunction each_fun,
+                void             *user_data)
+{
+  int i;
+
+  babl_assert(list);
+  babl_assert(each_fun);
+ 
+  for (i = 0; i < list->count; i++)
+    {
+      if (list->items[i])
+        {
+          if (each_fun ((Babl *) list->items[i], user_data))
+            break;
+        }
+    }
+}
+
+/* BablHashTable functions */
+
+
+inline int 
+babl_hash_by_str (BablHashTable *htab,
+                  const char    *str)
+{
+  int   hash = 0;
+  
+  while (*str)
+  {
+    hash += *str++;
+    hash += (hash << 10);
+    hash ^= (hash >> 6);
+  }
+  hash += (hash << 3);
+  hash ^= (hash >> 11);
+  hash += (hash << 15);
+
+  return (hash & htab->mask);
+}
+
+inline int 
+babl_hash_by_int (BablHashTable *htab, 
+                  int           id)
+{
+  int   hash = 0;
+  int   i;
+  
+  for (i = 0; i < sizeof (int); i++)
+  {
+    hash +=  id & 0xFF;
+    hash += (hash << 10);
+    hash ^= (hash >> 6);
+    id >>= 8;
+  }
+  hash += (hash << 3);
+  hash ^= (hash >> 11);
+  hash += (hash << 15);
+
+  return (hash & htab->mask);
+}
+
+static inline int 
+hash_insert (BablHashTable *htab,
+             Babl          *item)
+{
+  int hash = htab->hash_func(htab, item);
+
+  if (htab->data_table[hash] == NULL)
+    {
+      /* create new chain */
+      htab->data_table[hash] = item;
+    }
+  else 
+    {
+      int it, oit, cursor = 0;
+
+      while ((cursor < (htab->mask + 1)) && (htab->data_table[cursor] != NULL))
+        ++cursor;
+      
+      htab->data_table[cursor] = item;
+
+      for (oit = hash, it = htab->chain_table[oit]; it != -1; oit = it, it = htab->chain_table[oit])
+        ;
+      htab->chain_table[oit] = cursor; 
+    }
+
+  htab->count++;
+  return 0;
+}
+
+static void 
+hash_rehash (BablHashTable *htab)
+{
+  Babl *item;
+  int  i;
+  BablHashTable *nhtab = babl_calloc (sizeof (BablHashTable), 1);
+  
+  nhtab->data_table = NULL;
+  nhtab->chain_table = NULL;
+  nhtab->mask = (htab->mask << 1) + 1;
+  nhtab->count = 0;
+  nhtab->hash_func = htab->hash_func;
+  nhtab->find_func = htab->find_func;
+  if (nhtab->mask)
+    {
+      nhtab->data_table = babl_calloc (sizeof (BablInstance *), babl_hash_size(nhtab));
+      nhtab->chain_table = babl_malloc (sizeof (int *) * babl_hash_size(nhtab));
+      memset (nhtab->chain_table, -1, sizeof (int) * babl_hash_size(nhtab));
+    }
+  
+  for (i = 0; i < babl_hash_size (htab); i++)
+    {
+      item = htab->data_table[i];
+      babl_hash_insert (nhtab, item);
+    }
+
+  htab->mask = nhtab->mask;
+  babl_free (htab->data_table);
+  babl_free (htab->chain_table);
+  htab->data_table = nhtab->data_table;
+  htab->chain_table = nhtab->chain_table;
+  babl_free (nhtab);
+}
+
+inline int
+babl_hash_size (BablHashTable *htab)
+{
+    return htab->mask + 1;
+}
+
+BablHashTable *
+babl_hash_init (BablHashValFunction  hfunc, 
+                BablHashFindFunction ffunc)
+{
+  BablHashTable *htab;
+  
+  babl_assert(hfunc);
+  babl_assert(ffunc);
+
+  htab = babl_calloc (sizeof (BablHashTable), 1);
+  babl_assert (htab);
+
+  htab->data_table = NULL;
+  htab->chain_table = NULL;
+  htab->mask = UTIL_INITIAL_HT_MASK;
+  htab->count = 0;
+  htab->hash_func = hfunc;
+  htab->find_func = ffunc;
+  if (htab->mask)
+  {
+      htab->data_table = babl_calloc (sizeof (BablInstance *), babl_hash_size(htab));
+      htab->chain_table = babl_malloc (sizeof (int *) * babl_hash_size(htab));
+      memset (htab->chain_table, -1, sizeof (int) * babl_hash_size(htab));
+  }
+  
+  return htab;
+}
+
+void
+babl_hash_destroy (BablHashTable *htab)
+{
+  babl_assert (htab);
+
+  babl_free (htab->data_table);
+  babl_free (htab->chain_table);
+  babl_free (htab);
+}
+
+int
+babl_hash_insert (BablHashTable *htab,
+                  Babl          *item)
+{
+  babl_assert (htab);
+  babl_assert (BABL_IS_BABL(item));
+
+  if (babl_hash_size (htab) < htab->count + 1) 
+    hash_rehash (htab);
+  return hash_insert (htab, item);
+}
+
+Babl *
+babl_hash_find (BablHashTable *htab,
+                int           hash,
+                void          *data)
+{
+  int  it;
+  Babl *item;
+
+  babl_assert (htab);
+
+  it = hash;
+  item = htab->data_table[it];
+
+  if (!item)
+    return NULL;
+  
+  for (;;)
+    {
+      if (htab->find_func (item, data))
+        return item;
+      it = htab->chain_table[it];
+      if (it == -1)
+        break;
+      item = htab->data_table[it];
+    }
+    
+  return NULL;
+}
+
+
+/* Utils */
 
 static int list_length (void **list)
 {
Index: babl/babl-util.h
===================================================================
--- babl/babl-util.h	(revision 290)
+++ babl/babl-util.h	(working copy)
@@ -21,13 +21,89 @@
 
 #include <math.h>
 
-void   babl_add_ptr_to_list (void       ***list,
-                             void         *new);
+typedef struct _BablHashTable BablHashTable;
+typedef struct _BablList BablList;
+
+typedef int  (*BablHashValFunction) (BablHashTable *htab, Babl *item);
+typedef int  (*BablHashFindFunction) (Babl *item, void *data);
+
+typedef struct _BablList
+{
+  int  count;
+  int  size;
+  Babl **items;
+} _BablList;
+
+typedef struct _BablHashTable
+{
+  Babl                 **data_table;
+  int                  *chain_table;
+  int                  mask;
+  int                  count;
+  BablHashValFunction  hash_func;
+  BablHashFindFunction find_func;
+} _BablHashTable;
+
+
+/* BablList functions */
+
+BablList *
+babl_list_init (void);
+
+void
+babl_list_destroy (BablList *list);
+
+void
+babl_list_insert (BablList *list,
+                  Babl     *item);
+
+void
+babl_list_each_NEW (BablList      *list,
+                BablEachFunction each_fun,
+                void             *user_data);
 
 void
 babl_list_each (void             **list,
-                BablEachFunction   each_fun,
-                void              *user_data);
+                BablEachFunction each_fun,
+                void             *user_data);
+
+void
+babl_add_ptr_to_list (void ***list,
+                      void   *new);
+                
+
+
+/* BablHashTable functions */
+
+BablHashTable *
+babl_hash_init (BablHashValFunction  hfunc, 
+                BablHashFindFunction ffunc);
+
+inline int 
+babl_hash_by_str (BablHashTable *htab,
+                  const char    *str);
+
+inline int 
+babl_hash_by_int (BablHashTable *htab, 
+                  int           id);
+
+inline int
+babl_hash_size (BablHashTable *htab);
+
+int
+babl_hash_insert (BablHashTable *htab,
+                  Babl          *item);
+
+Babl *
+babl_hash_find (BablHashTable *htab,
+                int           hash,
+                void          *data);
+
+void
+babl_hash_destroy (BablHashTable *htab);
+
+
+/* Utils */
 
 long
 babl_ticks     (void);
Index: babl/babl-db.c
===================================================================
--- babl/babl-db.c	(revision 290)
+++ babl/babl-db.c	(working copy)
@@ -21,106 +21,90 @@
 #include <string.h>
 #include "babl-internal.h"
 
-#define DB_INITIAL_SIZE      16
-#define DB_INCREMENT_SIZE    16
-
-static inline int hash (const char *str)
+static int 
+db_find_by_name (Babl *item, void *data)
 {
-  int ret = 0;
-  int i   = 1;
-
-  while (*str)
-    ret = (ret + (i++ * (*str++ & 31))) % (HASH_TABLE_SIZE - 1);
-  return ret;
+  if (!strcmp (item->instance.name, (char *) data))
+    return 1;
+  return 0;
 }
 
-
-Babl *
-babl_db_find (BablDb     *db,
-              const char *name)
+static int 
+db_find_by_id (Babl *item, void *data)
 {
-  Babl *ret = babl_db_exist (db, 0, name);
+  if (item->instance.id == *((int *) data))
+    return 1;
+  return 0;
+}
 
-  if (!ret)
-    {
-      const char *sample_type = "unknwon";
-
-      if (db->items[0])
-        sample_type = babl_class_name (db->items[0]->class_type);
-      babl_log ("failed (query performed on a %s database)", sample_type);
-    }
-  return ret;
+static int
+db_hash_by_name (BablHashTable *htab, Babl *item)
+{
+  return babl_hash_by_str (htab, item->instance.name);
 }
 
+static int
+db_hash_by_id (BablHashTable *htab, Babl *item)
+{
+  return babl_hash_by_int (htab, item->instance.id);
+}
 
 BablDb *
 babl_db_init (void)
 {
   BablDb *db = babl_calloc (sizeof (BablDb), 1);
 
-  db->size  = DB_INITIAL_SIZE;
-  db->count = 0;
-  db->items = NULL;
-  if (db->size)
-    {
-      db->items = babl_calloc (sizeof (BablInstance *), db->size);
-    }
-  return db;
-}
+  db->name_hash = babl_hash_init (db_hash_by_name, db_find_by_name);
+  db->id_hash = babl_hash_init (db_hash_by_id, db_find_by_id);
+  db->babl_list = babl_list_init ();
 
-
-int
-babl_db_count (BablDb *db)
-{
-  return db->count;
+  return db; 
 }
 
 void
 babl_db_destroy (BablDb *db)
 {
-  babl_free (db->items);
+  babl_assert (db);
+ 
+  babl_hash_destroy (db->name_hash);
+  babl_hash_destroy (db->id_hash);
+  babl_list_destroy (db->babl_list);
   babl_free (db);
 }
 
 Babl *
-babl_db_insert (BablDb *db,
-                Babl   *item)
+babl_db_find (BablDb  *db,
+              const char *name)
 {
-  Babl *collision;
-
-  babl_assert (db && item);
-  babl_assert (item->instance.name);
-
-  collision = babl_db_exist (db, item->instance.id, item->instance.name);
-
-  if (collision)
-    return collision;
+  return babl_hash_find (db->name_hash, babl_hash_by_str (db->name_hash, name), (void *) name);
+}
 
-  if (db->count + 1 > db->size)     /* must reallocate storage */
-    {
-      Babl **new_items;
+int
+babl_db_count (BablDb *db)
+{
+  return db->babl_list->count;
+}
 
-      new_items = babl_realloc (db->items, (db->size + DB_INCREMENT_SIZE) * sizeof (BablInstance *));
-      babl_assert (new_items);
+Babl *
+babl_db_insert (BablDb *db,
+                Babl   *item)
+{
 
-      db->items = new_items;
+  Babl *found = babl_db_exist (db, item->instance.id, item->instance.name);
 
-      /* null out the currently unused portions of memory */
-      memset (db->items + db->size, 0, DB_INCREMENT_SIZE * sizeof (Babl *));
-      db->size += DB_INCREMENT_SIZE;
-    }
+  if (found)
+    return found;
 
-  {
-    int key = hash (item->instance.name);
-    if (db->hash[key] == NULL)
-      db->hash[key] = item;
-  }
-  db->items[db->count++] = item;
+  if (item->instance.id)
+    babl_hash_insert (db->id_hash, item);
+  babl_hash_insert (db->name_hash, item);
+  babl_list_insert (db->babl_list, item);
 
   /* this point all registered items pass through, a nice
   * place to brand them with where the item came from. */
   item->instance.creator = babl_extender ();
   return item;
+
 }
 
 void
@@ -128,84 +112,31 @@ babl_db_each (BablDb          *db,
               BablEachFunction each_fun,
               void            *user_data)
 {
-  int i;
-
-  for (i = 0; i < db->count; i++)
-    {
-      if (db->items[i])
-        {
-          if (each_fun ((Babl *) db->items[i], user_data))
-            break;
-        }
-    }
-}
-
-static inline void
-babl_db_each_inline (BablDb          *db,
-                     BablEachFunction each_fun,
-                     void            *user_data)
-{
-  int i;
-
-  for (i = 0; i < db->count; i++)
-    {
-      if (db->items[i])
-        {
-          if (each_fun ((Babl *) db->items[i], user_data))
-            break;
-        }
-    }
-}
-
-typedef struct BablDbExistData
-{
-  int         id;
-  const char *name;
-  Babl       *ret;
-} BablDbExistData;
-
-static int
-babl_db_each_exist (Babl *babl,
-                    void *void_data)
-{
-  BablDbExistData *data = void_data;
-
-  if (data->id && data->id == babl->instance.id)
-    {
-      data->ret = babl;
-      return 1;     /* stop iterating */
-    }
-  else if (data->name && !strcmp (babl->instance.name, data->name))
-    {
-      data->ret = babl;
-      return 1; /* stop iterating */
-    }
-  return 0;  /* continue iterating */
+  babl_list_each_NEW (db->babl_list, each_fun, user_data);
 }
 
+
 Babl *
 babl_db_exist (BablDb     *db,
                int         id,
                const char *name)
 {
-  Babl *ret = NULL;
-
-  if (name)
-    ret = db->hash[hash (name)];
-  if (ret &&
-      name[0] == ret->instance.name[0] &&
-      !strcmp (name, ret->instance.name))
-    return ret;
-
-  {
-    BablDbExistData data;
-
-    data.id   = id;
-    data.name = name;
-    data.ret  = NULL;
+  if (id) 
+    return babl_hash_find (db->id_hash, babl_hash_by_int (db->id_hash, id), &id);
+  return babl_hash_find (db->name_hash, babl_hash_by_str (db->name_hash, name), (void *) name);
+}
 
-    babl_db_each_inline (db, babl_db_each_exist, &data);
+Babl *
+babl_db_exist_by_id (BablDb *db,
+                     int    id)
+{
+  return  babl_hash_find (db->id_hash, babl_hash_by_int (db->id_hash, id),  &id);
+}
 
-    return data.ret;
-  }
+Babl *
+babl_db_exist_by_name (BablDb     *db,
+                       const char *name)
+{
+  return  babl_hash_find (db->name_hash, babl_hash_by_str (db->name_hash, name), name);
 }
+
Index: babl/babl-fish.c
===================================================================
--- babl/babl-fish.c	(revision 290)
+++ babl/babl-fish.c	(working copy)
@@ -62,9 +62,9 @@ go_fishing (const Babl *source,
   BablDb *db = babl_fish_db ();
   int i;
 
-  for (i=0; i<db->count; i++)
+  for (i=0; i<db->babl_list->count; i++)
     {
-      Babl *item = db->items[i];
+      Babl *item = db->babl_list->items[i];
       if ((void *) source == (void *) item->fish.source &&
           (void *) destination == (void *) item->fish.destination &&
           (item->class_type == BABL_FISH_PATH || /* accept only paths */
Index: babl/babl-db.h
===================================================================
--- babl/babl-db.h	(revision 290)
+++ babl/babl-db.h	(working copy)
@@ -19,20 +19,20 @@
 #ifndef _DB_H
 #define _DB_H
 
+#include "babl-util.h"
+
 #ifndef _BABL_INTERNAL_H
 #error  babl-db.h is only to be included after babl-internal.h
 #endif
 
-typedef struct _BablDb BablDb;
 
-#define HASH_TABLE_SIZE      128
-typedef struct _BablDb
+typedef struct BablDb
 {
-  Babl  *hash [HASH_TABLE_SIZE];
-  int    size;
-  int    count;
-  Babl **items;
-} _BablDb;
+  BablHashTable *name_hash;
+  BablHashTable *id_hash;
+  BablList      *babl_list;
+} BablDb;
+
 
 BablDb * babl_db_init    (void);
 void     babl_db_destroy (BablDb           *db);
@@ -48,4 +48,12 @@ Babl   * babl_db_exist   (BablDb        
 Babl   * babl_db_find    (BablDb           *db,
                           const char       *name);
 
+Babl *
+babl_db_exist_by_id (BablDb *db,
+                     int    id);
+                     
+Babl *
+babl_db_exist_by_name (BablDb     *db,
+                       const char *name);
+                       
 #endif
_______________________________________________
Gegl-developer mailing list
Gegl-developer@xxxxxxxxxxxxxxxxxxxxxx
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer

[Index of Archives]     [Yosemite News]     [Yosemite Photos]     [gtk]     [GIMP Users]     [KDE]     [Gimp's Home]     [Gimp on Windows]     [Steve's Art]

  Powered by Linux