Forgotten patch: qofid.diff

Chris Shoemaker c.shoemaker at cox.net
Tue Oct 25 10:18:29 EDT 2005


Subject: [qofid.diff] Minor tweaks to Qof Code in src/engine.

Neil, I don't know if this patch messes up your plans.  The only
essential thing here is qof_collection_get_list().  If we have to, I
suppose we could pull this into the budget namespace until the next
qof release.  What do you think?

 * src/engine/qof-be-utils.h
   - avoid declare-after-statement
   - minor tweaks to ugly macros

 * src/engine/qofid.[ch]:
   - Collection's hash of entities was using guid->data as lookup key.
     The key is actually just guid everywhere else.
   - Introduced qof_collection_get_list() for getting GList of entity GUIDs.
   - line-wrap and whitespace fixes
   - add comment about problems with get/set_data interface.

 * src/engine/qofclass.c:
   - Catch uses of qof_class system without qof_class_init and throw error.
   - Comment that 3 qof_class functions are actually private.

 * src/engine/qofquery.c:
   - ENTER/LEAVE balance. 


 src/engine/qof-be-utils.h |   22 +++++++-------
 src/engine/qofclass.c     |   69 +++++++++++++++++++++++++++-------------------
 src/engine/qofid.c        |   46 ++++++++++++++++++++----------
 src/engine/qofid.h        |   30 +++++++++++++++-----
 src/engine/qofquery.c     |    1 
 5 files changed, 106 insertions(+), 62 deletions(-)

Index: gnucash/src/engine/qof-be-utils.h
===================================================================
--- gnucash.orig/src/engine/qof-be-utils.h
+++ gnucash/src/engine/qof-be-utils.h
@@ -52,7 +52,6 @@
  */
 
 #define QOF_BEGIN_EDIT(inst)                                        \
-  QofBackend * be;                                                  \
   if (!(inst)) return;                                              \
                                                                     \
   (inst)->editlevel++;                                              \
@@ -66,12 +65,13 @@
   ENTER ("(inst=%p)", (inst));                                      \
                                                                     \
   /* See if there's a backend.  If there is, invoke it. */          \
-  be = qof_book_get_backend ((inst)->book);                         \
-    if (be && qof_backend_begin_exists((be))) {                     \
-     qof_backend_run_begin((be), (inst));                           \
-  } else {                                                          \
-     /* We tried and failed to start transaction! */                \
-     (inst)->dirty = TRUE;                                          \
+  {                                                                 \
+      QofBackend * be;                                              \
+      be = qof_book_get_backend ((inst)->book);                     \
+      if (be && qof_backend_begin_exists(be))                       \
+          qof_backend_run_begin(be, (inst));                        \
+      else /* We tried and failed to start transaction! */          \
+          (inst)->dirty = TRUE;                                     \
   }                                                                 \
   LEAVE (" ");
 
@@ -109,8 +109,8 @@ gboolean qof_begin_edit(QofInstance *ins
   {                                                              \
     QofBackend * be;                                             \
     be = qof_book_get_backend ((inst)->book);                    \
-    if (be && qof_backend_begin_exists((be))) {                  \
-     qof_backend_run_begin((be), (inst));                        \
+    if (be && qof_backend_begin_exists(be)) {                    \
+        qof_backend_run_begin(be, (inst));                       \
     }                                                            \
     (inst)->editlevel = 0;                                       \
   }                                                              \
@@ -148,7 +148,7 @@ gboolean qof_commit_edit(QofInstance *in
                                                                  \
   /* See if there's a backend.  If there is, invoke it. */       \
   be = qof_book_get_backend ((inst)->book);                      \
-  if (be && qof_backend_commit_exists((be)))                     \
+  if (be && qof_backend_commit_exists(be))                       \
   {                                                              \
     QofBackendError errcode;                                     \
                                                                  \
@@ -157,7 +157,7 @@ gboolean qof_commit_edit(QofInstance *in
       errcode = qof_backend_get_error (be);                      \
     } while (ERR_BACKEND_NO_ERR != errcode);                     \
                                                                  \
-    qof_backend_run_commit((be), (inst));                        \
+    qof_backend_run_commit(be, (inst));                          \
     errcode = qof_backend_get_error (be);                        \
     if (ERR_BACKEND_NO_ERR != errcode)                           \
     {                                                            \
Index: gnucash/src/engine/qofclass.c
===================================================================
--- gnucash.orig/src/engine/qofclass.c
+++ gnucash/src/engine/qofclass.c
@@ -43,6 +43,44 @@ static gboolean clear_table (gpointer ke
   return TRUE;
 }
 
+static gboolean check_init (void)
+{
+    if (initialized) return TRUE;
+
+    PERR("You must call qof_class_init() before using qof_class.");
+    return FALSE;
+}
+
+/********************************************************************/
+/* PRIVATE PUBLISHED API FUNCTIONS */
+void
+qof_class_init(void)
+{
+  if (initialized) return;
+  initialized = TRUE;
+
+  classTable = g_hash_table_new (g_str_hash, g_str_equal);
+  sortTable = g_hash_table_new (g_str_hash, g_str_equal);
+}
+
+void
+qof_class_shutdown (void)
+{
+  if (!initialized) return;
+  initialized = FALSE;
+
+  g_hash_table_foreach_remove (classTable, clear_table, NULL);
+  g_hash_table_destroy (classTable);
+  g_hash_table_destroy (sortTable);
+}
+
+QofSortFunc
+qof_class_get_default_sort (QofIdTypeConst obj_name)
+{
+  if (!obj_name) return NULL;
+  return g_hash_table_lookup (sortTable, obj_name);
+}
+
 /********************************************************************/
 /* PUBLISHED API FUNCTIONS */
 
@@ -55,6 +93,7 @@ qof_class_register (QofIdTypeConst obj_n
   int i;
 
   if (!obj_name) return;
+  if (!check_init()) return;
 
   if (default_sort_function)
   {
@@ -83,31 +122,11 @@ qof_class_register (QofIdTypeConst obj_n
   }
 }
 
-void 
-qof_class_init(void)
-{
-  if (initialized) return;
-  initialized = TRUE;
-
-  classTable = g_hash_table_new (g_str_hash, g_str_equal);
-  sortTable = g_hash_table_new (g_str_hash, g_str_equal);
-}
-
-void 
-qof_class_shutdown (void)
-{
-  if (!initialized) return;
-  initialized = FALSE;
-
-  g_hash_table_foreach_remove (classTable, clear_table, NULL);
-  g_hash_table_destroy (classTable);
-  g_hash_table_destroy (sortTable);
-}
-
 gboolean
 qof_class_is_registered (QofIdTypeConst obj_name)
 {
   if (!obj_name) return FALSE;
+  if (!check_init()) return FALSE;
 
   if (g_hash_table_lookup (classTable, obj_name)) return TRUE;
 
@@ -122,6 +141,7 @@ qof_class_get_parameter (QofIdTypeConst 
 
   g_return_val_if_fail (obj_name, NULL);
   g_return_val_if_fail (parameter, NULL);
+  if (!check_init()) return NULL;
 
   ht = g_hash_table_lookup (classTable, obj_name);
   if (!ht)
@@ -179,13 +199,6 @@ qof_class_get_parameter_type (QofIdTypeC
   return (prm->param_type);
 }
 
-QofSortFunc 
-qof_class_get_default_sort (QofIdTypeConst obj_name)
-{
-  if (!obj_name) return NULL;
-  return g_hash_table_lookup (sortTable, obj_name);
-}
-
 /* ================================================================ */
 
 struct class_iterate {
Index: gnucash/src/engine/qofid.c
===================================================================
--- gnucash.orig/src/engine/qofid.c
+++ gnucash/src/engine/qofid.c
@@ -53,11 +53,11 @@ qof_entity_init (QofEntity *ent, QofIdTy
   g_return_if_fail (NULL != tab);
   
   /* XXX We passed redundant info to this routine ... but I think that's
-	* OK, it might eliminate programming errors. */
+   * OK, it might eliminate programming errors. */
   if (safe_strcmp(tab->e_type, type))
   {
     PERR ("attempt to insert \"%s\" into \"%s\"", type, tab->e_type);
-	 return;
+    return;
   }
   ent->e_type = CACHE_INSERT (type);
 
@@ -158,8 +158,8 @@ void
 qof_collection_destroy (QofCollection *col)
 {
   CACHE_REMOVE (col->e_type);
-  g_hash_table_destroy(col->hash_of_entities);
   col->e_type = NULL;
+  g_hash_table_destroy(col->hash_of_entities);
   col->hash_of_entities = NULL;
   col->data = NULL;   /** XXX there should be a destroy notifier for this */
   g_free (col);
@@ -289,7 +289,7 @@ qof_collection_lookup_entity (QofCollect
   QofEntity *ent;
   g_return_val_if_fail (col, NULL);
   if (guid == NULL) return NULL;
-  ent = g_hash_table_lookup (col->hash_of_entities, guid->data);
+  ent = g_hash_table_lookup (col->hash_of_entities, guid);
   return ent;
 }
 
@@ -326,22 +326,21 @@ qof_collection_count (QofCollection *col
 gboolean 
 qof_collection_is_dirty (QofCollection *col)
 {
-   if (!col) return FALSE;
-   return col->is_dirty;
+    return col ? col->is_dirty : FALSE;
 }
 
 void 
 qof_collection_mark_clean (QofCollection *col)
 {
-   if (!col) return;
-   col->is_dirty = FALSE;
+    if (col)
+        col->is_dirty = FALSE;
 }
 
 void 
 qof_collection_mark_dirty (QofCollection *col)
 {
-   if (!col) return;
-   col->is_dirty = TRUE;
+    if (col)
+        col->is_dirty = TRUE;
 }
 
 /* =============================================================== */
@@ -349,15 +348,14 @@ qof_collection_mark_dirty (QofCollection
 gpointer 
 qof_collection_get_data (QofCollection *col)
 {
-   if (!col) return NULL;
-   return col->data;
+    return col ? col->data : NULL;
 }
 
 void 
 qof_collection_set_data (QofCollection *col, gpointer user_data)
 {
-   if (!col) return;
-   col->data = user_data;
+    if (col)
+        col->data = user_data;
 }
 
 /* =============================================================== */
@@ -376,8 +374,8 @@ static void foreach_cb (gpointer key, gp
 }
 
 void
-qof_collection_foreach (QofCollection *col, 
-                   QofEntityForeachCB cb_func, gpointer user_data)
+qof_collection_foreach (QofCollection *col, QofEntityForeachCB cb_func,
+                        gpointer user_data)
 {
   struct _iterate iter;
 
@@ -390,4 +388,20 @@ qof_collection_foreach (QofCollection *c
   g_hash_table_foreach (col->hash_of_entities, foreach_cb, &iter);
 }
 
+
+static void
+add_to_list(gpointer key, gpointer val, gpointer data) {
+    GList **list = data;
+    *list = g_list_append(*list, QOF_ENTITY(val));
+}
+
+GList *
+qof_collection_get_list(QofCollection *col) {
+    GList *list = NULL;
+    g_return_val_if_fail (col, NULL);
+
+    g_hash_table_foreach(col->hash_of_entities, add_to_list, &list);
+    return list;
+}
+
 /* =============================================================== */
Index: gnucash/src/engine/qofid.h
===================================================================
--- gnucash.orig/src/engine/qofid.h
+++ gnucash/src/engine/qofid.h
@@ -105,7 +105,8 @@ typedef const gchar* QofLogModule;
 })
 
 /** return TRUE if object is of the given type */
-#define QOF_CHECK_TYPE(obj,type) (0 == QSTRCMP((type),(((QofEntity *)(obj))->e_type)))
+#define QOF_CHECK_TYPE(obj,type) ( ((obj) != NULL) && \
+   (0 == QSTRCMP((type),(((QofEntity *)(obj))->e_type))))
 
 /** cast object to the indicated type, print error message if its bad  */
 #define QOF_CHECK_CAST(obj,e_type,c_type) (                   \
@@ -138,9 +139,9 @@ typedef struct QofCollection_s QofCollec
 
 struct QofEntity_s
 {
-   QofIdType        e_type;
-	GUID             guid;
-	QofCollection  * collection;
+  QofIdType        e_type;
+  GUID             guid;
+  QofCollection  * collection;
 };
 
 /** @name QOF Entity Initialization & Shutdown 
@@ -178,14 +179,29 @@ QofEntity * qof_collection_lookup_entity
 typedef void (*QofEntityForeachCB) (QofEntity *, gpointer user_data);
 
 /** Call the callback for each entity in the collection. */
-void qof_collection_foreach (QofCollection *, 
-                       QofEntityForeachCB, gpointer user_data);
+void qof_collection_foreach (QofCollection *, QofEntityForeachCB,
+                             gpointer user_data);
 
-/** Store and retreive arbitrary object-defined data 
+/** Get a list of entities in the collection.  Caller owns the list. */
+GList * qof_collection_get_list(QofCollection *col);
+
+/** Store and retrieve arbitrary object-defined data
  *
  * XXX We need to add a callback for when the collection is being
  * destroyed, so that the user has a chance to clean up anything
  * that was put in the 'data' member here.
+ *
+ * CAS: Besides the potential leak, this interface is kind of bogus in
+ * other ways, too.  For example, using collection data is risky
+ * because even though the collection data is very public, its use
+ * must be universally consistent.  That's a visibility violation.
+ *
+ * Here's what I think is needed: Object implementations need to be
+ * allowed a say in how their collection is managed.  Maybe they can
+ * register functions that control what happens to the collection when
+ * an object is added to or removed from the book.  Then we can remove
+ * public access to the collection's data via these two functions here.
+ *
  */
 gpointer qof_collection_get_data (QofCollection *col);
 void qof_collection_set_data (QofCollection *col, gpointer user_data);
Index: gnucash/src/engine/qofquery.c
===================================================================
--- gnucash.orig/src/engine/qofquery.c
+++ gnucash/src/engine/qofquery.c
@@ -1273,6 +1273,7 @@ void qof_query_init (void)
   ENTER (" ");
   qof_query_core_init ();
   qof_class_init ();
+  LEAVE ("Completed initialization of QofQuery");
 }
 
 void qof_query_shutdown (void)


More information about the gnucash-patches mailing list