gnucash stable: [sixtp-dom-parsers.cpp] Remove unnecessary commodity allocation during XML load

Christopher Lam clam at code.gnucash.org
Sun Dec 7 09:41:17 EST 2025


Updated	 via  https://github.com/Gnucash/gnucash/commit/2f7e51cf (commit)
	from  https://github.com/Gnucash/gnucash/commit/b397a344 (commit)



commit 2f7e51cf2a8258180ed382801ace7ff5705d7a79
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Sun Dec 7 14:11:47 2025 +0800

    [sixtp-dom-parsers.cpp] Remove unnecessary commodity allocation during XML load
    
    dom_tree_to_commodity_ref() is called for every transaction or
    price. It created and destroyed a commodity only to read its namespace
    and mnemonic when loading books. Rewrite to avoid creating temporary
    commodity.
    
    dom_tree_to_commodity_ref_no_engine () is called when creating
    commodities.
    
    Introduce get_commodity_ns_mnemonic() to parse namespace/mnemonic
    directly, and use it in both code paths.

diff --git a/libgnucash/backend/xml/sixtp-dom-parsers.cpp b/libgnucash/backend/xml/sixtp-dom-parsers.cpp
index 792ae697a3..bd2f4ed9b4 100644
--- a/libgnucash/backend/xml/sixtp-dom-parsers.cpp
+++ b/libgnucash/backend/xml/sixtp-dom-parsers.cpp
@@ -641,9 +641,14 @@ failure:
     return NULL;
 }
 
+struct CommodityRef
+{
+    std::string space;
+    std::string id;
+};
 
-gnc_commodity*
-dom_tree_to_commodity_ref_no_engine (xmlNodePtr node, QofBook* book)
+static std::optional<CommodityRef>
+parse_commodity_ref (xmlNodePtr node, QofBook* book)
 {
     /* Turn something like this
 
@@ -655,13 +660,13 @@ dom_tree_to_commodity_ref_no_engine (xmlNodePtr node, QofBook* book)
        into a gnc_commodity*, returning NULL on failure.  Both sub-nodes
        are required, though for now, order is irrelevant. */
 
-    gnc_commodity* c = NULL;
+    CommodityRef rv;
     gchar* space_str = NULL;
     gchar* id_str = NULL;
     xmlNodePtr n;
 
-    if (!node) return NULL;
-    if (!node->xmlChildrenNode) return NULL;
+    if (!node) return {};
+    if (!node->xmlChildrenNode) return {};
 
     for (n = node->xmlChildrenNode; n; n = n->next)
     {
@@ -675,12 +680,12 @@ dom_tree_to_commodity_ref_no_engine (xmlNodePtr node, QofBook* book)
             {
                 if (space_str)
                 {
-                    return NULL;
+                    return {};
                 }
                 else
                 {
                     gchar* content = dom_tree_to_text (n);
-                    if (!content) return NULL;
+                    if (!content) return {};
                     space_str = content;
                 }
             }
@@ -688,57 +693,63 @@ dom_tree_to_commodity_ref_no_engine (xmlNodePtr node, QofBook* book)
             {
                 if (id_str)
                 {
-                    return NULL;
+                    return {};
                 }
                 else
                 {
                     gchar* content = dom_tree_to_text (n);
-                    if (!content) return NULL;
+                    if (!content) return {};
                     id_str = content;
                 }
             }
             break;
         default:
             PERR ("unexpected sub-node.");
-            return NULL;
+            return {};
             break;
         }
     }
-    if (! (space_str && id_str))
-    {
-        c = NULL;
-    }
-    else
+    if (space_str && id_str)
     {
         g_strstrip (space_str);
         g_strstrip (id_str);
-        c = gnc_commodity_new (book, NULL, space_str, id_str, NULL, 0);
+        rv = {space_str, id_str};
     }
 
     g_free (space_str);
     g_free (id_str);
 
-    return c;
+    return rv;
+}
+
+gnc_commodity*
+dom_tree_to_commodity_ref_no_engine (xmlNodePtr node, QofBook* book)
+{
+    auto ref = parse_commodity_ref (node, book);
+
+    if (!ref)
+        return nullptr;
+
+    return gnc_commodity_new (book, nullptr, ref->space.c_str(), ref->id.c_str(),
+                              nullptr, 0);
 }
 
 gnc_commodity*
 dom_tree_to_commodity_ref (xmlNodePtr node, QofBook* book)
 {
-    gnc_commodity* daref;
     gnc_commodity* ret;
     gnc_commodity_table* table;
 
-    daref = dom_tree_to_commodity_ref_no_engine (node, book);
+    auto ref = parse_commodity_ref (node, book);
+
+    if (!ref)
+        return nullptr;
 
     table = gnc_commodity_table_get_table (book);
 
     g_return_val_if_fail (table != NULL, NULL);
 
-    ret =  gnc_commodity_table_lookup (table,
-                                       gnc_commodity_get_namespace (daref),
-                                       gnc_commodity_get_mnemonic (daref));
-
-    gnc_commodity_destroy (daref);
+    ret =  gnc_commodity_table_lookup (table, ref->space.c_str(), ref->id.c_str());
 
     g_return_val_if_fail (ret != NULL, NULL);
 



Summary of changes:
 libgnucash/backend/xml/sixtp-dom-parsers.cpp | 59 +++++++++++++++++-----------
 1 file changed, 35 insertions(+), 24 deletions(-)



More information about the gnucash-changes mailing list