gnucash maint: [gnc-features.cpp] convert to cpp

Christopher Lam clam at code.gnucash.org
Fri Oct 28 08:51:41 EDT 2022


Updated	 via  https://github.com/Gnucash/gnucash/commit/8192deff (commit)
	from  https://github.com/Gnucash/gnucash/commit/6f6d2fef (commit)



commit 8192deff37e4a5063ad62a90753bcd9a60b2f716
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Tue Oct 25 00:17:30 2022 +0800

    [gnc-features.cpp] convert to cpp
    
    - don't need to create/destroy GHashTable for each feature query
    - plugs leak: g_hash_table_unref (features_used) not always called properly
    - to check 1 feature, don't need to traverse whole GHashTable

diff --git a/libgnucash/engine/CMakeLists.txt b/libgnucash/engine/CMakeLists.txt
index 8dde8461b..b9d11b877 100644
--- a/libgnucash/engine/CMakeLists.txt
+++ b/libgnucash/engine/CMakeLists.txt
@@ -93,6 +93,7 @@ set (engine_HEADERS
   qof-backend.hpp
   qofbackend.h
   qofbook.h
+  qofbook.hpp
   qofbookslots.h
   qofchoice.h
   qofclass.h
@@ -145,7 +146,7 @@ set (engine_SOURCES
   gnc-datetime.cpp
   gnc-engine.c
   gnc-event.c
-  gnc-features.c
+  gnc-features.cpp
   gnc-hooks.c
   gnc-int128.cpp
   gnc-lot.c
diff --git a/libgnucash/engine/gnc-features.c b/libgnucash/engine/gnc-features.cpp
similarity index 53%
rename from libgnucash/engine/gnc-features.c
rename to libgnucash/engine/gnc-features.cpp
index f710677d2..5e2823a3c 100644
--- a/libgnucash/engine/gnc-features.c
+++ b/libgnucash/engine/gnc-features.cpp
@@ -19,28 +19,22 @@
  *                                                                  *
 \********************************************************************/
 
+#include <unordered_map>
+#include <string>
+#include <numeric>
+
 #include <config.h>
 
 #include <glib.h>
 #include <glib/gi18n.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "qof.h"
-#include "gnc-features.h"
-#include "gnc-glib-utils.h"
+#include "qofbook.hpp"
 
-typedef struct
+extern "C"
 {
-    const gchar *key;
-    const gchar *desc;
-} gncFeature;
+#include "gnc-features.h"
+}
 
-static GHashTable *features_table = NULL;
-static gncFeature known_features[] =
+static const FeaturesTable features_table
 {
     { GNC_FEATURE_CREDIT_NOTES, "Customer and vendor credit notes (requires at least GnuCash 2.5.0)" },
     { GNC_FEATURE_NUM_FIELD_SOURCE, "User specifies source of 'num' field'; either transaction number or split action (requires at least GnuCash 2.5.0)" },
@@ -53,7 +47,6 @@ static gncFeature known_features[] =
     { GNC_FEATURE_BUDGET_UNREVERSED, "Store budget amounts unreversed (i.e. natural) signs (requires at least Gnucash 3.8)"},
     { GNC_FEATURE_BUDGET_SHOW_EXTRA_ACCOUNT_COLS, "Show extra account columns in the Budget View (requires at least Gnucash 3.8)"},
     { GNC_FEATURE_EQUITY_TYPE_OPENING_BALANCE, GNC_FEATURE_EQUITY_TYPE_OPENING_BALANCE " (requires at least Gnucash 4.3)" },
-    { NULL },
 };
 
 /* This static indicates the debugging module that this .o belongs to.  */
@@ -62,40 +55,11 @@ static QofLogModule log_module = G_LOG_DOMAIN;
 /********************************************************************\
 \********************************************************************/
 
-static void gnc_features_init ()
-{
-    gint i;
-
-    if (features_table)
-        return;
-
-    features_table = g_hash_table_new (g_str_hash, g_str_equal);
-    for (i = 0; known_features[i].key; i++)
-        g_hash_table_insert (features_table,
-                             g_strdup (known_features[i].key),
-                             g_strdup (known_features[i].desc));
-}
-
-static void gnc_features_test_one(gpointer pkey, gpointer value,
-                  gpointer data)
-{
-    const gchar *key = (const gchar*)pkey;
-    const gchar *feature_desc = (const gchar*)value;
-    GList **unknown_features;
-
-    g_assert(data);
-    unknown_features = (GList**) data;
-
-    /* Check if this feature is in the known features list. */
-    if (g_hash_table_lookup_extended (features_table, key, NULL, NULL))
-        return;
-
-    /* It is unknown, so add the description to the unknown features list: */
-    g_assert(feature_desc);
-
-    *unknown_features = g_list_prepend(*unknown_features,
-                       (gpointer)feature_desc);
-}
+static const char*
+header = N_("This Dataset contains features not supported "
+            "by this version of GnuCash. You must use a "
+            "newer version of GnuCash in order to support "
+            "the following features:");
 
 /* Check if the session requires features unknown to this version of GnuCash.
  *
@@ -104,78 +68,31 @@ static void gnc_features_test_one(gpointer pkey, gpointer value,
  */
 gchar *gnc_features_test_unknown (QofBook *book)
 {
-
-    GList* features_list = NULL;
-    GHashTable *features_used = qof_book_get_features (book);
-
-    /* Setup the known_features hash table */
-    gnc_features_init();
-
-    /* Iterate over the members of this frame for unknown features */
-    g_hash_table_foreach (features_used, &gnc_features_test_one,
-              &features_list);
-    if (features_list)
-    {
-        const char* sep = "\n* ";
-        const char* header = _("This Dataset contains features not supported "
-                               "by this version of GnuCash. You must use a "
-                               "newer version of GnuCash in order to support "
-                               "the following features:");
-
-        char *features_str = gnc_g_list_stringjoin (features_list, sep);
-        char *msg = g_strconcat (header, sep, features_str, NULL);
-        g_free (features_str);
-        g_list_free(features_list);
-        return msg;
-    }
-    g_hash_table_unref (features_used);
-    return NULL;
+    auto unknowns {qof_book_get_unknown_features (book, features_table)};
+    auto accum = [](const auto& a, const auto& b){ return a + "\n* " + b; };
+    return unknowns.empty() ? nullptr :
+        g_strdup (std::accumulate (unknowns.begin(), unknowns.end(),
+                                   std::string (_(header)), accum).c_str());
 }
 
 void gnc_features_set_used (QofBook *book, const gchar *feature)
 {
-    const gchar *description;
-
     g_return_if_fail (book);
     g_return_if_fail (feature);
 
-    gnc_features_init();
-
     /* Can't set an unknown feature */
-    description = g_hash_table_lookup (features_table, feature);
-    if (!description)
+    auto iter = features_table.find (feature);
+    if (iter == features_table.end ())
     {
         PWARN("Tried to set unknown feature as used.");
         return;
     }
 
-    qof_book_set_feature (book, feature, description);
-}
-
-struct CheckFeature
-{
-    gchar const * checked_feature;
-    gboolean found;
-};
-
-static void gnc_features_check_feature_cb (gpointer pkey, gpointer value,
-                  gpointer data)
-{
-    const gchar *key = (const gchar*)pkey;
-    struct CheckFeature * check_data = data;
-    g_assert(data);
-    if (!g_strcmp0 (key, check_data->checked_feature))
-        check_data->found = TRUE;
+    qof_book_set_feature (book, feature, iter->second.c_str());
 }
 
 gboolean gnc_features_check_used (QofBook *book, const gchar * feature)
 {
-    GHashTable *features_used = qof_book_get_features (book);
-    struct CheckFeature check_data = {feature, FALSE};
-    /* Setup the known_features hash table */
-    gnc_features_init();
-    g_hash_table_foreach (features_used, &gnc_features_check_feature_cb, &check_data);
-    g_hash_table_unref (features_used);
-    return check_data.found;
+    return qof_book_test_feature (book, feature);
 }
 
diff --git a/libgnucash/engine/qofbook.cpp b/libgnucash/engine/qofbook.cpp
index ab2b01231..da4e2c843 100644
--- a/libgnucash/engine/qofbook.cpp
+++ b/libgnucash/engine/qofbook.cpp
@@ -61,6 +61,8 @@ extern "C"
 // For GNC_ID_ROOT_ACCOUNT:
 #include "AccountP.h"
 
+#include "qofbook.hpp"
+
 static QofLogModule log_module = QOF_MOD_ENGINE;
 #define AB_KEY "hbci"
 #define AB_TEMPLATES "template-list"
@@ -1255,6 +1257,32 @@ qof_book_set_feature (QofBook *book, const gchar *key, const gchar *descr)
     }
 }
 
+std::vector<std::string>
+qof_book_get_unknown_features (QofBook *book, const FeaturesTable& features)
+{
+    std::vector<std::string> rv;
+    auto test_feature = [&](const KvpFrameImpl::map_type::value_type& feature)
+    {
+        if (features.find (feature.first) == features.end ())
+            rv.push_back (feature.second->get<const char*>());
+    };
+    auto frame = qof_instance_get_slots (QOF_INSTANCE (book));
+    auto slot = frame->get_slot({GNC_FEATURES});
+    if (slot != nullptr)
+    {
+        frame = slot->get<KvpFrame*>();
+        std::for_each (frame->begin (), frame->end (), test_feature);
+    }
+    return rv;
+}
+
+bool
+qof_book_test_feature (QofBook *book, const char *feature)
+{
+    auto frame = qof_instance_get_slots (QOF_INSTANCE (book));
+    return (frame->get_slot({GNC_FEATURES, feature}) != nullptr);
+}
+
 void
 qof_book_load_options (QofBook *book, GNCOptionLoad load_cb, GNCOptionDB *odb)
 {
diff --git a/libgnucash/engine/qofbook.hpp b/libgnucash/engine/qofbook.hpp
new file mode 100644
index 000000000..402de1711
--- /dev/null
+++ b/libgnucash/engine/qofbook.hpp
@@ -0,0 +1,36 @@
+/********************************************************************\
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+ *                                                                  *
+\********************************************************************/
+
+#ifndef __QOF_BOOK__HPP__
+#define __QOF_BOOK__HPP__
+
+#include <vector>
+#include <unordered_map>
+#include <string>
+
+#include "qof.h"
+
+using FeaturesTable = std::unordered_map<std::string,std::string>;
+
+std::vector<std::string>
+qof_book_get_unknown_features (QofBook *book, const FeaturesTable& features);
+bool qof_book_test_feature (QofBook*, const char*);
+
+#endif /* QOF_BOOK_HPP */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 6c9be8e2c..3d2a0e7b3 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -641,7 +641,7 @@ libgnucash/engine/gncEmployee.c
 libgnucash/engine/gnc-engine.c
 libgnucash/engine/gncEntry.c
 libgnucash/engine/gnc-event.c
-libgnucash/engine/gnc-features.c
+libgnucash/engine/gnc-features.cpp
 libgnucash/engine/gnc-hooks.c
 libgnucash/engine/gncIDSearch.c
 libgnucash/engine/gnc-int128.cpp



Summary of changes:
 libgnucash/engine/CMakeLists.txt                   |   3 +-
 .../engine/{gnc-features.c => gnc-features.cpp}    | 129 ++++-----------------
 libgnucash/engine/qofbook.cpp                      |  28 +++++
 libgnucash/engine/{gnc-session.h => qofbook.hpp}   |  17 ++-
 po/POTFILES.in                                     |   2 +-
 5 files changed, 67 insertions(+), 112 deletions(-)
 rename libgnucash/engine/{gnc-features.c => gnc-features.cpp} (53%)
 copy libgnucash/engine/{gnc-session.h => qofbook.hpp} (78%)



More information about the gnucash-changes mailing list