gnucash future: Multiple changes pushed
John Ralls
jralls at code.gnucash.org
Thu Jun 25 15:32:26 EDT 2026
Updated via https://github.com/Gnucash/gnucash/commit/994b04a1 (commit)
via https://github.com/Gnucash/gnucash/commit/3b2daddb (commit)
via https://github.com/Gnucash/gnucash/commit/c7d35bcd (commit)
via https://github.com/Gnucash/gnucash/commit/00803ba0 (commit)
via https://github.com/Gnucash/gnucash/commit/2d1859ff (commit)
via https://github.com/Gnucash/gnucash/commit/29d74209 (commit)
via https://github.com/Gnucash/gnucash/commit/2a01ce23 (commit)
via https://github.com/Gnucash/gnucash/commit/b3e29a81 (commit)
from https://github.com/Gnucash/gnucash/commit/b4fd332d (commit)
commit 994b04a161d43e623eefad5e9d39537f3dc0a4ce
Merge: 3b2daddb47 c7d35bcdb2
Author: John Ralls <jralls at ceridwen.us>
Date: Thu Jun 25 12:31:53 2026 -0700
Merge Brent McBride's 'uri-format' into future.
commit 3b2daddb477c98a4d116e6cd1c9e3a62b6a0045a
Merge: b4fd332de3 00803ba018
Author: John Ralls <jralls at ceridwen.us>
Date: Thu Jun 25 12:13:29 2026 -0700
Merge branch 'use-boost-flat-map' of https://github.com/christopherlam/gnucash into future
diff --cc libgnucash/engine/qofid.cpp
index f649c281a6,7724106866..62d4ec46b0
--- a/libgnucash/engine/qofid.cpp
+++ b/libgnucash/engine/qofid.cpp
@@@ -43,8 -47,13 +47,14 @@@ struct QofCollection_
QofCollection_s (QofIdType type) : e_type{static_cast<QofIdType>(CACHE_INSERT(type))}
, is_dirty{FALSE}
- , hash_of_entities{guid_hash_table_new()}
- , data{NULL} {}
+ , data{NULL}
+ {
+ if (!g_strcmp0 (e_type, "Split"))
+ guid_entity_map.reserve (50000);
+ else if (!g_strcmp0 (e_type, "Trans"))
+ guid_entity_map.reserve (10000);
+ }
++
~QofCollection_s ()
{
CACHE_REMOVE (e_type);
commit c7d35bcdb2cbd8fb552e28b196cef862e92d8b39
Author: Brent McBride <mcbridebt at hotmail.com>
Date: Tue Jun 23 19:33:40 2026 -0700
gnc-uri: compose URIs with std::format
diff --git a/libgnucash/engine/gnc-uri.cpp b/libgnucash/engine/gnc-uri.cpp
index 3f30857a83..c85a7fe864 100755
--- a/libgnucash/engine/gnc-uri.cpp
+++ b/libgnucash/engine/gnc-uri.cpp
@@ -25,6 +25,7 @@
#include <glib.h>
#include <cstdint>
+#include <format>
#include <optional>
#include <stdexcept>
#include <string>
@@ -239,8 +240,8 @@ GncUri::try_str (bool allow_password) const
*/
bool absolute = !abs_path.empty() &&
(abs_path.front() == '/' || abs_path.front() == '\\');
- return absolute ? scheme + "://" + abs_path
- : scheme + ":///" + abs_path; // extra "/" for windows
+ return absolute ? std::format ("{}://{}", scheme, abs_path)
+ : std::format ("{}:///{}", scheme, abs_path); // extra "/" for windows
}
std::string userpass;
@@ -257,9 +258,9 @@ GncUri::try_str (bool allow_password) const
std::string portstr;
if (m_port != 0)
- portstr = ":" + std::to_string (m_port);
+ portstr = std::format (":{}", m_port);
- return *m_scheme + "://" + userpass + *m_hostname + portstr + "/" + path;
+ return std::format ("{}://{}{}{}/{}", *m_scheme, userpass, *m_hostname, portstr, path);
}
std::string
commit 00803ba018527f30ea3239fd60a8675009a878ef
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Wed Jun 17 11:07:55 2026 +0800
[qofid.cpp] for Split and Trans reserve QofInstance* map
diff --git a/libgnucash/engine/qofid.cpp b/libgnucash/engine/qofid.cpp
index cde7fd524e..7724106866 100644
--- a/libgnucash/engine/qofid.cpp
+++ b/libgnucash/engine/qofid.cpp
@@ -47,7 +47,13 @@ struct QofCollection_s
QofCollection_s (QofIdType type) : e_type{static_cast<QofIdType>(CACHE_INSERT(type))}
, is_dirty{FALSE}
- , data{NULL} {}
+ , data{NULL}
+ {
+ if (!g_strcmp0 (e_type, "Split"))
+ guid_entity_map.reserve (50000);
+ else if (!g_strcmp0 (e_type, "Trans"))
+ guid_entity_map.reserve (10000);
+ }
~QofCollection_s ()
{
CACHE_REMOVE (e_type);
commit 2d1859ff3e9e88c1fb723b246ed80407f479d95b
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Sat May 30 23:36:04 2026 +0800
[qofid.cpp] use boost::unordered_flat_map
to store guid->qof entities
note this is appropriate if the map values are QofInstance* pointers,
because unordered_flat_map does not guarantee stable iterators.
diff --git a/libgnucash/engine/qofid.cpp b/libgnucash/engine/qofid.cpp
index f649c281a6..cde7fd524e 100644
--- a/libgnucash/engine/qofid.cpp
+++ b/libgnucash/engine/qofid.cpp
@@ -27,10 +27,14 @@
#include <config.h>
#include <string.h>
+#include <guid.hpp>
#include "qof.h"
#include "qofid-p.h"
#include "qofinstance-p.h"
+#include <boost/unordered/unordered_flat_map.hpp>
+using GuidEntityMap = boost::unordered_flat_map<GncGUID, QofInstance*, std::hash<GncGUID>>;
+
static QofLogModule log_module = QOF_MOD_ENGINE;
struct QofCollection_s
@@ -38,17 +42,15 @@ struct QofCollection_s
QofIdType e_type;
gboolean is_dirty;
- GHashTable * hash_of_entities;
+ GuidEntityMap guid_entity_map;
gpointer data; /* place where object class can hang arbitrary data */
QofCollection_s (QofIdType type) : e_type{static_cast<QofIdType>(CACHE_INSERT(type))}
, is_dirty{FALSE}
- , hash_of_entities{guid_hash_table_new()}
, data{NULL} {}
~QofCollection_s ()
{
CACHE_REMOVE (e_type);
- g_hash_table_destroy (hash_of_entities);
}
};
@@ -87,48 +89,30 @@ qof_collection_remove_entity (QofInstance *ent)
col = qof_instance_get_collection(ent);
if (!col) return;
guid = qof_instance_get_guid(ent);
- g_hash_table_remove (col->hash_of_entities, guid);
+ col->guid_entity_map.erase(*guid);
qof_instance_set_collection(ent, NULL);
}
void
qof_collection_insert_entity (QofCollection *col, QofInstance *ent)
{
- const GncGUID *guid;
-
if (!col || !ent) return;
- guid = qof_instance_get_guid(ent);
+ const GncGUID *guid = qof_instance_get_guid(ent);
if (guid_equal(guid, guid_null())) return;
g_return_if_fail (col->e_type == ent->e_type);
qof_collection_remove_entity (ent);
- g_hash_table_insert (col->hash_of_entities, (gpointer)guid, ent);
+ col->guid_entity_map[*guid] = ent;
qof_instance_set_collection(ent, col);
}
gboolean
qof_collection_add_entity (QofCollection *coll, QofInstance *ent)
{
- QofInstance *e;
- const GncGUID *guid;
-
- e = NULL;
- if (!coll || !ent)
- {
- return FALSE;
- }
- guid = qof_instance_get_guid(ent);
- if (guid_equal(guid, guid_null()))
- {
- return FALSE;
- }
+ if (!coll || !ent) return FALSE;
+ const GncGUID *guid = qof_instance_get_guid(ent);
+ if (guid_equal(guid, guid_null())) return FALSE;
g_return_val_if_fail (coll->e_type == ent->e_type, FALSE);
- e = qof_collection_lookup_entity(coll, guid);
- if ( e != NULL )
- {
- return FALSE;
- }
- g_hash_table_insert (coll->hash_of_entities, (gpointer)guid, ent);
- return TRUE;
+ return coll->guid_entity_map.try_emplace (*guid, ent).second;
}
@@ -208,22 +192,18 @@ qof_collection_compare (QofCollection *target, QofCollection *merge)
QofInstance *
qof_collection_lookup_entity (const QofCollection *col, const GncGUID * guid)
{
- QofInstance *ent;
g_return_val_if_fail (col, NULL);
if (guid == NULL) return NULL;
- ent = static_cast<QofInstance*>(g_hash_table_lookup (col->hash_of_entities,
- guid));
- if (ent != NULL && qof_instance_get_destroying(ent)) return NULL;
- return ent;
+ auto it = col->guid_entity_map.find(*guid);
+ if (it == col->guid_entity_map.end() || qof_instance_get_destroying(it->second))
+ return nullptr;
+ return it->second;
}
guint
qof_collection_count (const QofCollection *col)
{
- guint c;
-
- c = g_hash_table_size(col->hash_of_entities);
- return c;
+ return col->guid_entity_map.size();
}
/* =============================================================== */
@@ -283,20 +263,21 @@ void
qof_collection_foreach_sorted (const QofCollection *col, QofInstanceForeachCB cb_func,
gpointer user_data, GCompareFunc sort_fn)
{
- GList *entries;
-
g_return_if_fail (col);
g_return_if_fail (cb_func);
- PINFO("Hash Table size of %s before is %d", col->e_type, g_hash_table_size(col->hash_of_entities));
+ PINFO("Hash Table size of %s before is %ld", col->e_type, col->guid_entity_map.size());
- entries = g_hash_table_get_values (col->hash_of_entities);
+ std::vector<QofInstance*> entries (col->guid_entity_map.size());
+ std::transform (col->guid_entity_map.cbegin(), col->guid_entity_map.cend(),
+ entries.begin(), [](const auto& kv) { return kv.second; });
if (sort_fn)
- entries = g_list_sort (entries, sort_fn);
- g_list_foreach (entries, (GFunc)cb_func, user_data);
- g_list_free (entries);
+ std::sort (entries.begin(), entries.end(),
+ [sort_fn](auto a, auto b) { return sort_fn (a, b) < 0; });
+ std::for_each (entries.cbegin(), entries.cend(),
+ [&](auto ent) { cb_func (ent, user_data); });
- PINFO("Hash Table size of %s after is %d", col->e_type, g_hash_table_size(col->hash_of_entities));
+ PINFO("Hash Table size of %s after is %ld", col->e_type, col->guid_entity_map.size());
}
void
commit 29d74209a7b6edbe00abf9501b7ffe59256dccfd
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Sun Jun 14 12:05:47 2026 +0800
[guid.cpp] create templated guid_hash function
for arbitrary sized hashes
diff --git a/libgnucash/engine/guid.cpp b/libgnucash/engine/guid.cpp
index 0bd359a450..cb083dc913 100644
--- a/libgnucash/engine/guid.cpp
+++ b/libgnucash/engine/guid.cpp
@@ -254,15 +254,8 @@ guid_compare (const GncGUID *guid_1, const GncGUID *guid_2)
guint
guid_hash_to_guint (gconstpointer ptr)
{
- if (!ptr)
- {
- PERR ("received nullptr guid pointer.");
- return 0;
- }
- const GncGUID* g = static_cast<const GncGUID*>(ptr);
- guint rv;
- memcpy (&rv, &g->reserved[12], sizeof (guint));
- return rv;
+ g_return_val_if_fail (ptr, 0);
+ return gnc_guid_hash<guint> (*static_cast<const GncGUID*>(ptr));
}
gint
diff --git a/libgnucash/engine/guid.hpp b/libgnucash/engine/guid.hpp
index 7a883ecd9b..4f493ffd71 100644
--- a/libgnucash/engine/guid.hpp
+++ b/libgnucash/engine/guid.hpp
@@ -22,6 +22,7 @@
#ifndef GUID_HPP_HEADER
#define GUID_HPP_HEADER
+#include <boost/functional/hash.hpp>
#include <boost/uuid/uuid.hpp>
#include <stdexcept>
#include <string>
@@ -68,4 +69,19 @@ bool operator == (GUID const &, GncGUID const &) noexcept;
} // namespace gnc
bool operator== (const GncGUID&, const GncGUID&);
+
+template <typename T>
+T
+gnc_guid_hash (const GncGUID& g)
+{
+ static_assert(std::is_integral_v<T>);
+ return static_cast<T>(boost::hash_range(g.reserved, g.reserved + sizeof (g.reserved)));
+};
+
+
+template<> struct std::hash<GncGUID>
+{
+ std::size_t operator()(const GncGUID& g) const{ return gnc_guid_hash<size_t> (g); }
+};
+
#endif
commit 2a01ce23763756d7c3241a76bf08415193bd2d3b
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Tue Jun 16 13:57:56 2026 +0800
[guid.cpp] plug char* guid_to_string leak
it seems unused however
diff --git a/libgnucash/engine/guid.cpp b/libgnucash/engine/guid.cpp
index 946f3c1d03..0bd359a450 100644
--- a/libgnucash/engine/guid.cpp
+++ b/libgnucash/engine/guid.cpp
@@ -300,14 +300,14 @@ gnc_string_to_guid (const GValue *src, GValue *dest)
static void
gnc_guid_to_string (const GValue *src, GValue *dest)
{
- const gchar *str;
+ gchar *str;
g_return_if_fail (G_VALUE_HOLDS_STRING (dest) &&
GNC_VALUE_HOLDS_GUID (src));
str = guid_to_string (gnc_value_get_guid (src));
- g_value_set_string (dest, str);
+ g_value_take_string (dest, str);
}
G_DEFINE_BOXED_TYPE_WITH_CODE (GncGUID, gnc_guid, guid_copy, guid_free,
commit b3e29a81fdfd784b1dc9229577fa289ff2c13afa
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Sun Jun 14 10:30:02 2026 +0800
[qofid.cpp] use ctor/dtor for QofCollection
which will make it easier to construct in-place in book->hash_of_collections
diff --git a/libgnucash/engine/qofid.cpp b/libgnucash/engine/qofid.cpp
index 3e47ff9158..f649c281a6 100644
--- a/libgnucash/engine/qofid.cpp
+++ b/libgnucash/engine/qofid.cpp
@@ -40,6 +40,16 @@ struct QofCollection_s
GHashTable * hash_of_entities;
gpointer data; /* place where object class can hang arbitrary data */
+
+ QofCollection_s (QofIdType type) : e_type{static_cast<QofIdType>(CACHE_INSERT(type))}
+ , is_dirty{FALSE}
+ , hash_of_entities{guid_hash_table_new()}
+ , data{NULL} {}
+ ~QofCollection_s ()
+ {
+ CACHE_REMOVE (e_type);
+ g_hash_table_destroy (hash_of_entities);
+ }
};
/* =============================================================== */
@@ -47,24 +57,13 @@ struct QofCollection_s
QofCollection *
qof_collection_new (QofIdType type)
{
- QofCollection *col;
- col = g_new0(QofCollection, 1);
- col->e_type = static_cast<QofIdType>(CACHE_INSERT (type));
- col->is_dirty = FALSE;
- col->hash_of_entities = guid_hash_table_new();
- col->data = NULL;
- return col;
+ return new QofCollection (type);
}
void
qof_collection_destroy (QofCollection *col)
{
- CACHE_REMOVE (col->e_type);
- g_hash_table_destroy(col->hash_of_entities);
- col->e_type = NULL;
- col->hash_of_entities = NULL;
- col->data = NULL; /** XXX there should be a destroy notifier for this */
- g_free (col);
+ delete col;
}
/* =============================================================== */
Summary of changes:
libgnucash/engine/gnc-uri.cpp | 9 ++---
libgnucash/engine/guid.cpp | 11 ++----
libgnucash/engine/guid.hpp | 16 +++++++++
libgnucash/engine/qofid.cpp | 80 ++++++++++++++++++-------------------------
4 files changed, 57 insertions(+), 59 deletions(-)
More information about the gnucash-changes
mailing list