Merge branch 'fix_bayes' of https://github.com/limitedAtonement/gnucash into unstable

This commit is contained in:
Geert Janssens 2017-12-23 15:10:48 +01:00
commit 2f96b19c77
70 changed files with 1644 additions and 1700 deletions

View File

@ -57,7 +57,9 @@ Otherwise, only failures are printed out.
#include <glib.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Privately used to indicate a test result. You may use these if you
* wish, but it's easier to use the do_test macro above.
@ -150,5 +152,8 @@ gint64 get_random_gint64(void);
double get_random_double(void);
const char* get_random_string_in_array(const char* str_list[]);
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /* TEST_STUFF_H */

View File

@ -143,6 +143,29 @@ test_clear_error_list (void)
message_queue = NULL;
}
gboolean
test_list_substring_handler (const char *log_domain, GLogLevelFlags log_level,
const gchar *msg, gpointer user_data)
{
GList *list = g_list_first (message_queue);
const guint fatal = G_LOG_FLAG_FATAL;
while (list)
{
TestErrorStruct *error = (TestErrorStruct*)list->data;
if (!g_strcmp0 (log_domain, error->log_domain)
&& ((log_level | fatal) == (error->log_level | fatal))
&& g_strrstr (msg, error->msg))
{
++(error->hits);
return FALSE;
}
list = g_list_next (list);
}
/* No list or no matches, fall through */
return test_checked_substring_handler (log_domain, log_level, msg, user_data);
}
static gboolean
do_test_list_handler (const char *log_domain, GLogLevelFlags log_level,
const gchar *msg, gpointer user_data, gboolean hits)
@ -205,6 +228,27 @@ do_test_checked_handler (const char *log_domain, GLogLevelFlags log_level,
}
gboolean
test_checked_substring_handler (const char *log_domain, GLogLevelFlags log_level,
const gchar *msg, gpointer user_data)
{
TestErrorStruct *tdata = (TestErrorStruct*)user_data;
if ((tdata == NULL)
|| (tdata->log_domain != NULL
&& g_strcmp0 (log_domain, tdata->log_domain))
|| (tdata->log_level && tdata->log_level != log_level)
|| (tdata->msg && !g_strrstr (msg, tdata->msg)))
{
gchar *level = test_log_level (log_level);
g_printf ( "<%s> (%s) %s\n", level, log_domain, msg);
g_free (level);
g_assert (log_level ^ G_LOG_FLAG_FATAL);
return FALSE;
}
++(tdata->hits);
return FALSE;
}
gboolean
test_checked_handler (const char *log_domain, GLogLevelFlags log_level,
const gchar *msg, gpointer user_data )

View File

@ -178,6 +178,14 @@ GSList *test_log_set_fatal_handler (GSList *list, TestErrorStruct *error,
*/
void test_free_log_handler (gpointer item);
/**
* Check that the user_data error message is a substring of the
* actual error otherwise assert. Displays the error (and asserts
* if G_LOG_FLAG_FATAL is TRUE) if NULL is passed as user_data,
* but a NULL or 0 value member matches anything.
*/
gboolean test_checked_substring_handler (const char *log_domain, GLogLevelFlags log_level,
const gchar *msg, gpointer user_data);
/**
* Check the user_data against the actual error and assert on any
* differences. Displays the error (and asserts if G_LOG_FLAG_FATAL
@ -213,6 +221,18 @@ gboolean test_null_handler (const char *log_domain, GLogLevelFlags log_level,
void test_add_error (TestErrorStruct *error);
void test_clear_error_list (void);
/**
* Checks received errors against the list created by
* test_add_error. Rather than checking for an exact match, this function
* checks using a substring match. If the list is empty or nothing
* matches, passes control on to test_checked_substring_handler, giving
* the opportunity for an additional check that's not in the list
* (set user_data to NULL if you want test_checked_handler to
* immediately print the error).
*/
gboolean test_list_substring_handler (const char *log_domain, GLogLevelFlags log_level,
const gchar *msg, gpointer user_data);
/**
* Checks received errors against the list created by
* test_add_error. If the list is empty or nothing matches, passes

View File

@ -1022,12 +1022,6 @@ RESTART:
gnc_warning_dialog(NULL, "%s", message);
g_free ( message );
}
// Convert imap mappings from account full name to guid strings
qof_event_suspend();
gnc_account_imap_convert_bayes (gnc_get_current_book());
qof_event_resume();
return TRUE;
}

View File

@ -69,7 +69,7 @@ setup_kvp (Fixture *fixture, gconstpointer pData)
"autoreadonly-days", (double)21,
NULL);
slots->set_path("options/Business/Company Name",
slots->set_path({"options", "Business", "Company Name"},
new KvpValue("Bogus Company"));
qof_commit_edit (QOF_INSTANCE (book));
}
@ -120,10 +120,10 @@ test_option_save (Fixture *fixture, gconstpointer pData)
OPTION_NAME_AUTO_READONLY_DAYS,
17));
qof_book_save_options (book, gnc_option_db_save, odb, TRUE);
g_assert_cmpstr (slots->get_slot("options/Accounts/Use Trading Accounts")->get<const char*>(), == , "t");
g_assert_cmpstr (slots->get_slot("options/Accounts/Use Split Action Field for Number")->get<const char*>(), == , "t");
g_assert_cmpstr (slots->get_slot("options/Business/Company Name")->get<const char*>(), ==, "Bogus Company");
g_assert_cmpfloat (slots->get_slot("options/Accounts/Day Threshold for Read-Only Transactions (red line)")->get<double>(), ==, 17);
g_assert_cmpstr (slots->get_slot({"options", "Accounts", "Use Trading Accounts"})->get<const char*>(), == , "t");
g_assert_cmpstr (slots->get_slot({"options", "Accounts", "Use Split Action Field for Number"})->get<const char*>(), == , "t");
g_assert_cmpstr (slots->get_slot({"options", "Business", "Company Name"})->get<const char*>(), ==, "Bogus Company");
g_assert_cmpfloat (slots->get_slot({"options", "Accounts", "Day Threshold for Read-Only Transactions (red line)"})->get<double>(), ==, 17);
gnc_option_db_destroy (odb);
}

View File

@ -132,15 +132,13 @@ setup_memory (Fixture* fixture, gconstpointer pData)
xaccAccountSetCommodity (acct1, currency);
auto frame = qof_instance_get_slots (QOF_INSTANCE (acct1));
frame->set ("int64-val", new KvpValue (INT64_C (100)));
frame->set ("double-val", new KvpValue (3.14159));
frame->set ("numeric-val", new KvpValue (gnc_numeric_zero ()));
frame->set ("timespec-val", new KvpValue (timespec_now ()));
frame->set ("string-val", new KvpValue ("abcdefghijklmnop"));
frame->set ({"int64-val"}, new KvpValue (INT64_C (100)));
frame->set ({"double-val"}, new KvpValue (3.14159));
frame->set ({"numeric-val"}, new KvpValue (gnc_numeric_zero ()));
frame->set ({"timespec-val"}, new KvpValue (timespec_now ()));
frame->set ({"string-val"}, new KvpValue ("abcdefghijklmnop"));
auto guid = qof_instance_get_guid (QOF_INSTANCE (acct1));
frame->set ("guid-val", new KvpValue (const_cast<GncGUID*> (guid_copy (
frame->set ({"guid-val"}, new KvpValue (const_cast<GncGUID*> (guid_copy (
guid))));
gnc_account_append_child (root, acct1);

View File

@ -226,7 +226,7 @@ set_slot_from_value (slot_info_t* pInfo, KvpValue* pValue)
case FRAME:
{
auto key = get_key_from_path (pInfo->path);
pInfo->pKvpFrame->set (key.c_str(), pValue);
pInfo->pKvpFrame->set ({key.c_str()}, pValue);
break;
}
case LIST:
@ -245,7 +245,7 @@ set_slot_from_value (slot_info_t* pInfo, KvpValue* pValue)
frame->set_path ({path.c_str(), key.c_str()}, pValue);
}
else
frame->set (key.c_str(), pValue);
frame->set ({key.c_str()}, pValue);
break;
}
}
@ -464,7 +464,7 @@ set_guid_val (gpointer pObject, gpointer pValue)
slots_load_info (newInfo);
pValue = new KvpValue {newInfo->pList};
pInfo->pKvpFrame->set (key.c_str(), pValue);
pInfo->pKvpFrame->set ({key.c_str()}, pValue);
delete newInfo;
break;
}
@ -487,7 +487,7 @@ set_guid_val (gpointer pObject, gpointer pValue)
default:
{
auto key = get_key_from_path (pInfo->path);
pInfo->pKvpFrame->set (key.c_str(), new KvpValue {newFrame});
pInfo->pKvpFrame->set ({key.c_str()}, new KvpValue {newFrame});
break;
}
}
@ -581,81 +581,78 @@ slot_info_copy (slot_info_t* pInfo, GncGUID* guid)
}
static void
save_slot (const char* key, KvpValue* value, gpointer data)
save_slot (const char* key, KvpValue* value, slot_info_t & slot_info)
{
slot_info_t* pSlot_info = (slot_info_t*)data;
g_return_if_fail (value != NULL);
g_return_if_fail (data != NULL);
// Ignore if we've already run into a failure
if (!pSlot_info->is_ok)
if (!slot_info.is_ok)
{
return;
}
auto curlen = pSlot_info->path.length();
pSlot_info->pKvpValue = value;
auto curlen = slot_info.path.length();
slot_info.pKvpValue = value;
if (curlen != 0)
pSlot_info->path += "/";
slot_info.path += "/";
pSlot_info->path += key;
pSlot_info->value_type = value->get_type ();
slot_info.path += key;
slot_info.value_type = value->get_type ();
switch (pSlot_info->value_type)
switch (slot_info.value_type)
{
case KvpValue::Type::FRAME:
{
auto pKvpFrame = value->get<KvpFrame*> ();
auto guid = guid_new ();
slot_info_t* pNewInfo = slot_info_copy (pSlot_info, guid);
KvpValue* oldValue = pSlot_info->pKvpValue;
pSlot_info->pKvpValue = new KvpValue {guid};
pSlot_info->is_ok = pSlot_info->be->do_db_operation(OP_DB_INSERT,
slot_info_t* pNewInfo = slot_info_copy (&slot_info, guid);
KvpValue* oldValue = slot_info.pKvpValue;
slot_info.pKvpValue = new KvpValue {guid};
slot_info.is_ok = slot_info.be->do_db_operation(OP_DB_INSERT,
TABLE_NAME,
TABLE_NAME,
pSlot_info,
&slot_info,
col_table);
g_return_if_fail (pSlot_info->is_ok);
pKvpFrame->for_each_slot (save_slot, pNewInfo);
delete pSlot_info->pKvpValue;
pSlot_info->pKvpValue = oldValue;
g_return_if_fail (slot_info.is_ok);
pKvpFrame->for_each_slot_temp (save_slot, *pNewInfo);
delete slot_info.pKvpValue;
slot_info.pKvpValue = oldValue;
delete pNewInfo;
}
break;
case KvpValue::Type::GLIST:
{
GncGUID* guid = guid_new ();
slot_info_t* pNewInfo = slot_info_copy (pSlot_info, guid);
KvpValue* oldValue = pSlot_info->pKvpValue;
pSlot_info->pKvpValue = new KvpValue {guid}; // Transfer ownership!
pSlot_info->is_ok = pSlot_info->be->do_db_operation(OP_DB_INSERT,
slot_info_t* pNewInfo = slot_info_copy (&slot_info, guid);
KvpValue* oldValue = slot_info.pKvpValue;
slot_info.pKvpValue = new KvpValue {guid}; // Transfer ownership!
slot_info.is_ok = slot_info.be->do_db_operation(OP_DB_INSERT,
TABLE_NAME,
TABLE_NAME,
pSlot_info,
&slot_info,
col_table);
g_return_if_fail (pSlot_info->is_ok);
g_return_if_fail (slot_info.is_ok);
for (auto cursor = value->get<GList*> (); cursor; cursor = cursor->next)
{
auto val = static_cast<KvpValue*> (cursor->data);
save_slot ("", val, pNewInfo);
save_slot ("", val, *pNewInfo);
}
delete pSlot_info->pKvpValue;
pSlot_info->pKvpValue = oldValue;
delete slot_info.pKvpValue;
slot_info.pKvpValue = oldValue;
delete pNewInfo;
}
break;
default:
{
pSlot_info->is_ok = pSlot_info->be->do_db_operation (OP_DB_INSERT,
slot_info.is_ok = slot_info.be->do_db_operation (OP_DB_INSERT,
TABLE_NAME,
TABLE_NAME,
pSlot_info,
&slot_info,
col_table);
}
break;
}
pSlot_info->path.erase(curlen);
slot_info.path.erase(curlen);
}
gboolean
@ -678,7 +675,7 @@ gnc_sql_slots_save (GncSqlBackend* sql_be, const GncGUID* guid, gboolean is_infa
slot_info.be = sql_be;
slot_info.guid = guid;
pFrame->for_each_slot (save_slot, &slot_info);
pFrame->for_each_slot_temp (save_slot, slot_info);
return slot_info.is_ok;
}

View File

@ -808,7 +808,7 @@ kvp_frame_slot_end_handler (gpointer data_for_children,
if (key_node_count != 1) return (FALSE);
value_cr->should_cleanup = TRUE;
f->set (key, value);
f->set ({key}, value);
if (delete_value)
delete value;
return (TRUE);

View File

@ -334,7 +334,7 @@ add_kvp_value_node (xmlNodePtr node, const gchar* tag, KvpValue* val)
auto frame = val->get<KvpFrame*> ();
if (!frame)
break;
frame->for_each_slot (add_kvp_slot, static_cast<void*> (val_node));
frame->for_each_slot_temp (&add_kvp_slot, val_node);
break;
}
default:
@ -366,6 +366,6 @@ qof_instance_slots_to_dom_tree (const char* tag, const QofInstance* inst)
return nullptr;
ret = xmlNewNode (nullptr, BAD_CAST tag);
frame->for_each_slot (add_kvp_slot, static_cast<void*> (ret));
frame->for_each_slot_temp (&add_kvp_slot, ret);
return ret;
}

View File

@ -440,7 +440,7 @@ dom_tree_to_kvp_frame_given (xmlNodePtr node, KvpFrame* frame)
if (val)
{
//We're deleting the old KvpValue returned by replace_nc().
delete frame->set (key, val);
delete frame->set ({key}, val);
}
else
{

View File

@ -21,7 +21,6 @@ extern "C"
{
#include <config.h>
#include "test-stuff.h"
#include "test-engine-stuff.h"
#include <stdlib.h>
@ -30,6 +29,7 @@ extern "C"
#include "test-file-stuff.h"
#include "sixtp-utils.h"
#include "sixtp-dom-generators.h"
#include "test-stuff.h"
#define GNC_V2_STRING "gnc-v2"
const gchar* gnc_v2_xml_version_string = GNC_V2_STRING;

View File

@ -30,7 +30,6 @@ extern "C"
#include <glib.h>
#include "test-stuff.h"
#include "test-engine-stuff.h"
#include "cashobjects.h"
#include "gnc-engine.h"
@ -44,6 +43,7 @@ extern "C"
#include "sixtp-utils.h"
#include "sixtp-dom-parsers.h"
#include "sixtp-dom-generators.h"
#include "test-stuff.h"
#define GNC_V2_STRING "gnc-v2"
const gchar* gnc_v2_xml_version_string = GNC_V2_STRING;

View File

@ -25,7 +25,7 @@ test_kvp_get_slot (int run,
KvpFrame* test_frame1, const KvpValue* test_val1,
const gchar* test_key)
{
auto test_val2 = test_frame1->get_slot (test_key);
auto test_val2 = test_frame1->get_slot ({test_key});
auto msg = "KvpFrame::get_slot";
if (compare (test_val1, test_val2) == 0)
{
@ -70,7 +70,7 @@ test_kvp_copy_get_slot (int run,
const gchar* test_key)
{
auto test_frame2 = new KvpFrame (*test_frame1);
auto test_val2 = test_frame2->get_slot (test_key);
auto test_val2 = test_frame2->get_slot ({test_key});
auto msg = "KvpFrame::get_slot() from a copy-constructed frame";
if (compare (test_val1, test_val2) == 0)
{
@ -114,7 +114,7 @@ test_kvp_frames1 (void)
auto test_frame1 = new KvpFrame;
auto test_key = get_random_string_without ("/");
test_frame1->set (test_key, test_val1);
test_frame1->set ({test_key}, test_val1);
test_kvp_get_slot (i, test_frame1, test_val1, test_key);
test_kvp_copy_compare (i, test_frame1, test_val1, test_key);

View File

@ -34,7 +34,6 @@ extern "C"
#include "gnc-module.h"
#include "gnc-engine.h"
#include "test-stuff.h"
#include "test-engine-stuff.h"
}
@ -43,6 +42,7 @@ extern "C"
#include "io-gncxml-v2.h"
#include "io-example-account.h"
#include "test-stuff.h"
static const gchar* da_ending = ".gnucash-xea";

View File

@ -45,7 +45,6 @@ extern "C"
#include <gnc-engine.h>
#include <gnc-prefs.h>
#include <test-stuff.h>
#include <unittest-support.h>
#include <test-engine-stuff.h>
}
@ -53,6 +52,7 @@ extern "C"
#include "../gnc-backend-xml.h"
#include "../io-gncxml-v2.h"
#include "test-file-stuff.h"
#include <test-stuff.h>
#define GNC_LIB_NAME "gncmod-backend-xml"
#define GNC_LIB_REL_PATH "xml"

View File

@ -30,7 +30,6 @@ extern "C"
#include <stdlib.h>
#include <string.h>
#include "test-stuff.h"
#include "test-engine-stuff.h"
#include "gnc-engine.h"
@ -39,6 +38,7 @@ extern "C"
#include "test-file-stuff.h"
#include "io-gncxml-v2.h"
#include "test-stuff.h"
const char* possible_envs[] =
{

View File

@ -24,13 +24,13 @@ extern "C"
#include <stdlib.h>
#include "gnc-engine.h"
#include "test-stuff.h"
#include "test-engine-stuff.h"
}
#include "test-file-stuff.h"
#include "sixtp-dom-parsers.h"
#include "sixtp-dom-generators.h"
#include "test-stuff.h"
#define GNC_V2_STRING "gnc-v2"

View File

@ -32,7 +32,6 @@ extern "C"
#include <gnc-engine.h>
#include <cashobjects.h>
#include <test-stuff.h>
#include <test-engine-stuff.h>
#include <unittest-support.h>
@ -45,6 +44,7 @@ extern "C"
#include "../sixtp-parsers.h"
#include "../sixtp-dom-parsers.h"
#include "test-file-stuff.h"
#include <test-stuff.h>
static QofBook* sixbook;

View File

@ -28,7 +28,6 @@ extern "C"
#include "gnc-module.h"
#include "qof.h"
#include "test-stuff.h"
#include "test-engine-stuff.h"
#include "Account.h"
@ -41,6 +40,7 @@ extern "C"
#include "sixtp-dom-parsers.h"
#include "io-gncxml-gen.h"
#include "test-file-stuff.h"
#include "test-stuff.h"
static QofBook* book;

View File

@ -34,7 +34,6 @@ extern "C"
#include "gnc-engine.h"
#include "gnc-pricedb.h"
#include "test-stuff.h"
#include "test-engine-stuff.h"
}
@ -45,6 +44,7 @@ extern "C"
#include "sixtp-dom-parsers.h"
#include "io-gncxml-v2.h"
#include "test-file-stuff.h"
#include "test-stuff.h"
static QofSession* session;
static int iter;

View File

@ -38,7 +38,6 @@ extern "C"
#include <cashobjects.h>
#include <TransLog.h>
#include <test-stuff.h>
#include <test-engine-stuff.h>
#include <unittest-support.h>
@ -53,7 +52,7 @@ extern "C"
#include "../sixtp-dom-parsers.h"
#include "../io-gncxml-gen.h"
#include "test-file-stuff.h"
#include <test-stuff.h>
static QofBook* book;
extern gboolean gnc_transaction_xml_v2_testing;

View File

@ -23,12 +23,12 @@ extern "C"
#include <stdlib.h>
#include <string.h>
#include "test-stuff.h"
#include "test-engine-stuff.h"
}
#include "io-gncxml-v2.h"
#include "test-file-stuff.h"
#include "test-stuff.h"
#define FILENAME "Money95bank_fr.gml2"

View File

@ -39,6 +39,10 @@
#include <glib.h>
#ifdef __cplusplus
extern "C" {
#endif
/** @name Character Sets
@{
*/
@ -186,6 +190,10 @@ void gnc_gpid_kill(GPid pid);
/** @} */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* GNC_GLIB_UTILS_H */
/** @} */
/** @} */

File diff suppressed because it is too large Load Diff

View File

@ -48,6 +48,9 @@
#include "gnc-engine.h"
#include "policy.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef gnc_numeric (*xaccGetBalanceFn)( const Account *account );
typedef gnc_numeric (*xaccGetBalanceInCurrencyFn) (
@ -1446,11 +1449,6 @@ gchar *gnc_account_get_map_entry (Account *acc, const char *full_category);
*/
void gnc_account_delete_map_entry (Account *acc, char *full_category, gboolean empty);
/** Search for Bayesian entries with mappings based on full account name and change
* them to be based on the account guid
*/
void gnc_account_imap_convert_bayes (QofBook *book);
/** @} */
@ -1517,6 +1515,10 @@ const char * dxaccAccountGetQuoteTZ (const Account *account);
* in the gnome-search parameter list. Be careful when you use this. */
#define ACCOUNT_MATCH_ALL_TYPE "account-match-all"
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* XACC_ACCOUNT_H */
/** @} */
/** @} */

View File

@ -41,6 +41,10 @@
#include "Account.h"
#ifdef __cplusplus
extern "C" {
#endif
#define GNC_ID_ROOT_ACCOUNT "RootAccount"
/** STRUCTS *********************************************************/
@ -149,5 +153,8 @@ typedef struct
AccountTestFunctions* _utest_account_fill_functions(void);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* XACC_ACCOUNT_P_H */

View File

@ -136,7 +136,7 @@ ADD_CUSTOM_COMMAND (
ADD_CUSTOM_TARGET(iso-4217-c DEPENDS ${ISO_4217_C})
SET (engine_SOURCES
Account.c
Account.cpp
Recurrence.c
Query.c
SchedXaction.c

View File

@ -18,7 +18,7 @@ AM_CPPFLAGS = \
libgncmod_engine_la_SOURCES = \
Account.c \
Account.cpp \
Recurrence.c \
Query.c \
SchedXaction.c \

View File

@ -50,7 +50,7 @@
#include "Transaction.h"
#include "TransactionP.h"
#include "gnc-commodity.h"
#include <qofinstance-p.h>
#include "qofinstance-p.h"
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "gnc.engine.scrub"
@ -1228,10 +1228,10 @@ xaccAccountDeleteOldData (Account *account)
{
if (!account) return;
xaccAccountBeginEdit (account);
qof_instance_set_kvp (QOF_INSTANCE (account), "old-currency", NULL);
qof_instance_set_kvp (QOF_INSTANCE (account), "old-security", NULL);
qof_instance_set_kvp (QOF_INSTANCE (account), "old-currency-scu", NULL);
qof_instance_set_kvp (QOF_INSTANCE (account), "old-security-scu", NULL);
qof_instance_set_kvp (QOF_INSTANCE (account), NULL, 1, "old-currency");
qof_instance_set_kvp (QOF_INSTANCE (account), NULL, 1, "old-security");
qof_instance_set_kvp (QOF_INSTANCE (account), NULL, 1, "old-currency-scu");
qof_instance_set_kvp (QOF_INSTANCE (account), NULL, 1, "old-security-scu");
qof_instance_set_dirty (QOF_INSTANCE (account));
xaccAccountCommitEdit (account);
}
@ -1337,7 +1337,7 @@ xaccAccountScrubKvp (Account *account)
if (!account) return;
qof_instance_get_kvp (QOF_INSTANCE (account), "notes", &v);
qof_instance_get_kvp (QOF_INSTANCE (account), &v, 1, "notes");
if (G_VALUE_HOLDS_STRING (&v))
{
str2 = g_strstrip(g_value_dup_string(&v));
@ -1346,7 +1346,7 @@ xaccAccountScrubKvp (Account *account)
g_free(str2);
}
qof_instance_get_kvp (QOF_INSTANCE (account), "placeholder", &v);
qof_instance_get_kvp (QOF_INSTANCE (account), &v, 1, "placeholder");
if ((G_VALUE_HOLDS_STRING (&v) &&
strcmp(g_value_get_string (&v), "false") == 0) ||
(G_VALUE_HOLDS_BOOLEAN (&v) && ! g_value_get_boolean (&v)))

View File

@ -182,40 +182,31 @@ gnc_split_get_property(GObject *object,
g_value_take_object(value, split->lot);
break;
case PROP_SX_CREDIT_FORMULA:
key = GNC_SX_ID "/" GNC_SX_CREDIT_FORMULA;
qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
qof_instance_get_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_CREDIT_FORMULA);
break;
case PROP_SX_CREDIT_NUMERIC:
key = GNC_SX_ID "/" GNC_SX_CREDIT_NUMERIC;
qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
qof_instance_get_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_CREDIT_NUMERIC);
break;
case PROP_SX_DEBIT_FORMULA:
key = GNC_SX_ID "/" GNC_SX_DEBIT_FORMULA;
qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
qof_instance_get_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_DEBIT_FORMULA);
break;
case PROP_SX_DEBIT_NUMERIC:
key = GNC_SX_ID "/" GNC_SX_DEBIT_NUMERIC;
qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
qof_instance_get_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_DEBIT_NUMERIC);
break;
case PROP_SX_ACCOUNT:
key = GNC_SX_ID "/" GNC_SX_ACCOUNT;
qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
qof_instance_get_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_ACCOUNT);
break;
case PROP_SX_SHARES:
key = GNC_SX_ID "/" GNC_SX_SHARES;
qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
qof_instance_get_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_SHARES);
break;
case PROP_ONLINE_ACCOUNT:
key = "online_id";
qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
qof_instance_get_kvp (QOF_INSTANCE (split), value, 1, "online_id");
break;
case PROP_GAINS_SPLIT:
key = "gains-split";
qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
qof_instance_get_kvp (QOF_INSTANCE (split), value, 1, "gains-split");
break;
case PROP_GAINS_SOURCE:
key = "gains-source";
qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
qof_instance_get_kvp (QOF_INSTANCE (split), value, 1, "gains-source");
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@ -268,40 +259,31 @@ gnc_split_set_property(GObject *object,
xaccSplitSetLot(split, g_value_get_object(value));
break;
case PROP_SX_CREDIT_FORMULA:
key = GNC_SX_ID "/" GNC_SX_CREDIT_FORMULA;
qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
qof_instance_set_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_CREDIT_FORMULA);
break;
case PROP_SX_CREDIT_NUMERIC:
key = GNC_SX_ID "/" GNC_SX_CREDIT_NUMERIC;
qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
qof_instance_set_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_CREDIT_NUMERIC);
break;
case PROP_SX_DEBIT_FORMULA:
key = GNC_SX_ID "/" GNC_SX_DEBIT_FORMULA;
qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
qof_instance_set_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_DEBIT_FORMULA);
break;
case PROP_SX_DEBIT_NUMERIC:
key = GNC_SX_ID "/" GNC_SX_DEBIT_NUMERIC;
qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
qof_instance_set_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_DEBIT_NUMERIC);
break;
case PROP_SX_ACCOUNT:
key = GNC_SX_ID "/" GNC_SX_ACCOUNT;
qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
qof_instance_set_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_ACCOUNT);
break;
case PROP_SX_SHARES:
key = GNC_SX_ID "/" GNC_SX_SHARES;
qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
qof_instance_set_kvp (QOF_INSTANCE (split), value, 2, GNC_SX_ID, GNC_SX_SHARES);
break;
case PROP_ONLINE_ACCOUNT:
key = "online_id";
qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
qof_instance_set_kvp (QOF_INSTANCE (split), value, 1, "online_id");
break;
case PROP_GAINS_SPLIT:
key = "gains-split";
qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
qof_instance_set_kvp (QOF_INSTANCE (split), value, 1, "gains-split");
break;
case PROP_GAINS_SOURCE:
key = "gains-source";
qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
qof_instance_set_kvp (QOF_INSTANCE (split), value, 1, "gains-source");
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@ -1095,7 +1077,7 @@ xaccSplitDetermineGainStatus (Split *split)
return;
}
qof_instance_get_kvp (QOF_INSTANCE (split), "gains-source", &v);
qof_instance_get_kvp (QOF_INSTANCE (split), &v, 1, "gains-source");
if (G_VALUE_HOLDS_BOXED (&v))
guid = (GncGUID*)g_value_get_boxed (&v);
if (!guid)
@ -1987,7 +1969,7 @@ xaccSplitGetType(const Split *s)
const char *split_type = NULL;
if (!s) return NULL;
qof_instance_get_kvp (QOF_INSTANCE (s), "split-type", &v);
qof_instance_get_kvp (QOF_INSTANCE (s), &v, 1, "split-type");
if (G_VALUE_HOLDS_STRING (&v))
split_type = g_value_get_string (&v);
return split_type ? split_type : "normal";
@ -2004,7 +1986,7 @@ xaccSplitMakeStockSplit(Split *s)
s->value = gnc_numeric_zero();
g_value_init (&v, G_TYPE_STRING);
g_value_set_string (&v, "stock-split");
qof_instance_set_kvp (QOF_INSTANCE (s), "split-type", &v);
qof_instance_set_kvp (QOF_INSTANCE (s), &v, 1, "split-type");
SET_GAINS_VDIRTY(s);
mark_split(s);
qof_instance_set_dirty(QOF_INSTANCE(s));
@ -2141,7 +2123,7 @@ xaccSplitVoidFormerAmount(const Split *split)
GValue v = G_VALUE_INIT;
gnc_numeric *num = NULL;
g_return_val_if_fail(split, gnc_numeric_zero());
qof_instance_get_kvp (QOF_INSTANCE (split), void_former_amt_str, &v);
qof_instance_get_kvp (QOF_INSTANCE (split), &v, 1, void_former_amt_str);
if (G_VALUE_HOLDS_BOXED (&v))
num = (gnc_numeric*)g_value_get_boxed (&v);
return num ? *num : gnc_numeric_zero();
@ -2153,7 +2135,7 @@ xaccSplitVoidFormerValue(const Split *split)
GValue v = G_VALUE_INIT;
gnc_numeric *num = NULL;
g_return_val_if_fail(split, gnc_numeric_zero());
qof_instance_get_kvp (QOF_INSTANCE (split), void_former_val_str, &v);
qof_instance_get_kvp (QOF_INSTANCE (split), &v, 1, void_former_val_str);
if (G_VALUE_HOLDS_BOXED (&v))
num = (gnc_numeric*)g_value_get_boxed (&v);
return num ? *num : gnc_numeric_zero();
@ -2168,10 +2150,10 @@ xaccSplitVoid(Split *split)
g_value_init (&v, GNC_TYPE_NUMERIC);
num = xaccSplitGetAmount(split);
g_value_set_boxed (&v, &num);
qof_instance_set_kvp (QOF_INSTANCE (split), void_former_amt_str, &v);
qof_instance_set_kvp (QOF_INSTANCE (split), &v, 1, void_former_amt_str);
num = xaccSplitGetValue(split);
g_value_set_boxed (&v, &num);
qof_instance_set_kvp (QOF_INSTANCE (split), void_former_val_str, &v);
qof_instance_set_kvp (QOF_INSTANCE (split), &v, 1, void_former_val_str);
/* Marking dirty handled by SetAmount etc. */
xaccSplitSetAmount (split, zero);
@ -2185,8 +2167,8 @@ xaccSplitUnvoid(Split *split)
xaccSplitSetAmount (split, xaccSplitVoidFormerAmount(split));
xaccSplitSetValue (split, xaccSplitVoidFormerValue(split));
xaccSplitSetReconcile(split, NREC);
qof_instance_set_kvp (QOF_INSTANCE (split), void_former_amt_str, NULL);
qof_instance_set_kvp (QOF_INSTANCE (split), void_former_val_str, NULL);
qof_instance_set_kvp (QOF_INSTANCE (split), NULL, 1, void_former_amt_str);
qof_instance_set_kvp (QOF_INSTANCE (split), NULL, 1, void_former_val_str);
qof_instance_set_dirty (QOF_INSTANCE (split));
}

View File

@ -41,6 +41,10 @@ typedef struct _SplitClass SplitClass;
#include "gnc-commodity.h"
#include "gnc-engine.h"
#ifdef __cplusplus
extern "C" {
#endif
/* --- type macros --- */
#define GNC_TYPE_SPLIT (gnc_split_get_type ())
#define GNC_SPLIT(o) \
@ -550,6 +554,10 @@ gnc_numeric xaccSplitVoidFormerValue(const Split *split);
/** \deprecated */
#define xaccSplitReturnGUID(X) (X ? *(qof_entity_get_guid(QOF_INSTANCE(X))) : *(guid_null()))
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* XACC_SPLIT_H */
/** @} */
/** @} */

View File

@ -338,17 +338,14 @@ gnc_transaction_get_property(GObject* object,
g_value_set_boxed(value, &tx->date_entered);
break;
case PROP_INVOICE:
key = GNC_INVOICE_ID "/" GNC_INVOICE_GUID;
qof_instance_get_kvp (QOF_INSTANCE (tx), key, value);
break;
qof_instance_get_kvp (QOF_INSTANCE (tx), value, 2, GNC_INVOICE_ID, GNC_INVOICE_GUID);
break;
case PROP_SX_TXN:
key = GNC_SX_FROM;
qof_instance_get_kvp (QOF_INSTANCE (tx), key, value);
break;
qof_instance_get_kvp (QOF_INSTANCE (tx), value, 1, GNC_SX_FROM);
break;
case PROP_ONLINE_ACCOUNT:
key = "online_id";
qof_instance_get_kvp (QOF_INSTANCE (tx), key, value);
break;
qof_instance_get_kvp (QOF_INSTANCE (tx), value, 1, "online_id");
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -387,17 +384,14 @@ gnc_transaction_set_property(GObject* object,
xaccTransSetDateEnteredTS(tx, g_value_get_boxed(value));
break;
case PROP_INVOICE:
key = GNC_INVOICE_ID "/" GNC_INVOICE_GUID;
qof_instance_set_kvp (QOF_INSTANCE (tx), key, value);
break;
qof_instance_set_kvp (QOF_INSTANCE (tx), value, 2, GNC_INVOICE_ID, GNC_INVOICE_GUID);
break;
case PROP_SX_TXN:
key = GNC_SX_FROM;
qof_instance_set_kvp (QOF_INSTANCE (tx), key, value);
break;
qof_instance_set_kvp (QOF_INSTANCE (tx), value, 1, GNC_SX_FROM);
break;
case PROP_ONLINE_ACCOUNT:
key = "online_id";
qof_instance_set_kvp (QOF_INSTANCE (tx), key, value);
break;
qof_instance_set_kvp (QOF_INSTANCE (tx), value, 1, "online_id");
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -1993,7 +1987,7 @@ xaccTransSetDatePostedGDate (Transaction *trans, GDate date)
* clearly be distinguished from the Timespec. */
g_value_init (&v, G_TYPE_DATE);
g_value_set_boxed (&v, &date);
qof_instance_set_kvp (QOF_INSTANCE(trans), TRANS_DATE_POSTED, &v);
qof_instance_set_kvp (QOF_INSTANCE(trans), &v, 1, TRANS_DATE_POSTED);
/* mark dirty and commit handled by SetDateInternal */
xaccTransSetDateInternal(trans, &trans->date_posted,
gdate_to_timespec(date));
@ -2069,7 +2063,7 @@ xaccTransSetDateDueTS (Transaction *trans, const Timespec *ts)
g_value_init (&v, GNC_TYPE_TIMESPEC);
g_value_set_boxed (&v, ts);
xaccTransBeginEdit(trans);
qof_instance_set_kvp (QOF_INSTANCE (trans), TRANS_DATE_DUE_KVP, &v);
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, TRANS_DATE_DUE_KVP);
qof_instance_set_dirty(QOF_INSTANCE(trans));
xaccTransCommitEdit(trans);
}
@ -2083,7 +2077,7 @@ xaccTransSetTxnType (Transaction *trans, char type)
g_value_init (&v, G_TYPE_STRING);
g_value_set_string (&v, s);
xaccTransBeginEdit(trans);
qof_instance_set_kvp (QOF_INSTANCE (trans), TRANS_TXN_TYPE_KVP, &v);
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, TRANS_TXN_TYPE_KVP);
qof_instance_set_dirty(QOF_INSTANCE(trans));
xaccTransCommitEdit(trans);
}
@ -2093,8 +2087,7 @@ void xaccTransClearReadOnly (Transaction *trans)
if (trans)
{
xaccTransBeginEdit(trans);
qof_instance_set_kvp (QOF_INSTANCE (trans),
TRANS_READ_ONLY_REASON, NULL);
qof_instance_set_kvp (QOF_INSTANCE (trans), NULL, 1, TRANS_READ_ONLY_REASON);
qof_instance_set_dirty(QOF_INSTANCE(trans));
xaccTransCommitEdit(trans);
}
@ -2105,11 +2098,11 @@ xaccTransSetReadOnly (Transaction *trans, const char *reason)
{
if (trans && reason)
{
GValue v = G_VALUE_INIT;
g_value_init (&v, G_TYPE_STRING);
g_value_set_string (&v, reason);
GValue v = G_VALUE_INIT;
g_value_init (&v, G_TYPE_STRING);
g_value_set_string (&v, reason);
xaccTransBeginEdit(trans);
qof_instance_set_kvp (QOF_INSTANCE (trans), TRANS_READ_ONLY_REASON, &v);
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, TRANS_READ_ONLY_REASON);
qof_instance_set_dirty(QOF_INSTANCE(trans));
xaccTransCommitEdit(trans);
}
@ -2167,7 +2160,7 @@ xaccTransSetAssociation (Transaction *trans, const char *assoc)
g_value_init (&v, G_TYPE_STRING);
g_value_set_string (&v, assoc);
xaccTransBeginEdit(trans);
qof_instance_set_kvp (QOF_INSTANCE (trans), assoc_uri_str, &v);
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, assoc_uri_str);
qof_instance_set_dirty(QOF_INSTANCE(trans));
xaccTransCommitEdit(trans);
}
@ -2189,7 +2182,7 @@ xaccTransSetNotes (Transaction *trans, const char *notes)
g_value_set_string (&v, notes);
xaccTransBeginEdit(trans);
qof_instance_set_kvp (QOF_INSTANCE (trans), trans_notes_str, &v);
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, trans_notes_str);
qof_instance_set_dirty(QOF_INSTANCE(trans));
xaccTransCommitEdit(trans);
}
@ -2202,13 +2195,13 @@ xaccTransSetIsClosingTxn (Transaction *trans, gboolean is_closing)
if (is_closing)
{
GValue v = G_VALUE_INIT;
g_value_init (&v, G_TYPE_INT64);
g_value_set_int64 (&v, 1);
qof_instance_set_kvp (QOF_INSTANCE (trans), trans_is_closing_str, &v);
GValue v = G_VALUE_INIT;
g_value_init (&v, G_TYPE_INT64);
g_value_set_int64 (&v, 1);
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, trans_is_closing_str);
}
else
qof_instance_set_kvp (QOF_INSTANCE (trans), trans_is_closing_str, NULL);
qof_instance_set_kvp (QOF_INSTANCE (trans), NULL, 1, trans_is_closing_str);
qof_instance_set_dirty(QOF_INSTANCE(trans));
xaccTransCommitEdit(trans);
}
@ -2343,7 +2336,7 @@ xaccTransGetAssociation (const Transaction *trans)
{
GValue v = G_VALUE_INIT;
if (!trans) return NULL;
qof_instance_get_kvp (QOF_INSTANCE (trans), assoc_uri_str, &v);
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, assoc_uri_str);
if (G_VALUE_HOLDS_STRING (&v))
return g_value_get_string (&v);
return NULL;
@ -2354,7 +2347,7 @@ xaccTransGetNotes (const Transaction *trans)
{
GValue v = G_VALUE_INIT;
if (!trans) return NULL;
qof_instance_get_kvp (QOF_INSTANCE (trans), trans_notes_str, &v);
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, trans_notes_str);
if (G_VALUE_HOLDS_STRING (&v))
return g_value_get_string (&v);
return NULL;
@ -2365,7 +2358,7 @@ xaccTransGetIsClosingTxn (const Transaction *trans)
{
GValue v = G_VALUE_INIT;
if (!trans) return FALSE;
qof_instance_get_kvp (QOF_INSTANCE (trans), trans_is_closing_str, &v);
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, trans_is_closing_str);
if (G_VALUE_HOLDS_INT64 (&v))
return g_value_get_int64 (&v);
return FALSE;
@ -2419,11 +2412,11 @@ xaccTransGetDatePostedGDate (const Transaction *trans)
/* Can we look up this value in the kvp slot? If yes, use it
* from there because it doesn't suffer from time zone
* shifts. */
GValue v = G_VALUE_INIT;
qof_instance_get_kvp (QOF_INSTANCE (trans), TRANS_DATE_POSTED, &v);
GValue v = G_VALUE_INIT;
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, TRANS_DATE_POSTED);
if (G_VALUE_HOLDS_BOXED (&v))
result = *(GDate*)g_value_get_boxed (&v);
if (! g_date_valid (&result))
if (! g_date_valid (&result))
{
/* Well, this txn doesn't have a GDate saved in a
* slot. Avoid getting the date in the local TZ by
@ -2455,7 +2448,7 @@ xaccTransGetDateDueTS (const Transaction *trans, Timespec *ts)
GValue v = G_VALUE_INIT;
if (!trans || !ts) return;
qof_instance_get_kvp (QOF_INSTANCE (trans), TRANS_DATE_DUE_KVP, &v);
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, TRANS_DATE_DUE_KVP);
if (G_VALUE_HOLDS_BOXED (&v))
*ts = *(Timespec*)g_value_get_boxed (&v);
if (ts->tv_sec == 0)
@ -2477,11 +2470,11 @@ xaccTransGetTxnType (const Transaction *trans)
GValue v = G_VALUE_INIT;
if (!trans) return TXN_TYPE_NONE;
qof_instance_get_kvp (QOF_INSTANCE (trans), TRANS_TXN_TYPE_KVP, &v);
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, TRANS_TXN_TYPE_KVP);
if (G_VALUE_HOLDS_STRING (&v))
s = g_value_get_string (&v);
if (s && strlen (s) == 1)
return *s;
return *s;
return TXN_TYPE_NONE;
}
@ -2495,11 +2488,11 @@ xaccTransGetReadOnly (const Transaction *trans)
GValue v = G_VALUE_INIT;
const char *s = NULL;
if (trans == NULL) return NULL;
qof_instance_get_kvp (QOF_INSTANCE(trans), TRANS_READ_ONLY_REASON, &v);
qof_instance_get_kvp (QOF_INSTANCE(trans), &v, 1, TRANS_READ_ONLY_REASON);
if (G_VALUE_HOLDS_STRING (&v))
s = g_value_get_string (&v);
if (s && strlen (s))
return s;
return s;
return NULL;
}
@ -2693,20 +2686,20 @@ xaccTransVoid(Transaction *trans, const char *reason)
return;
}
xaccTransBeginEdit(trans);
qof_instance_get_kvp (QOF_INSTANCE (trans), trans_notes_str, &v);
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, trans_notes_str);
if (G_VALUE_HOLDS_STRING (&v))
qof_instance_set_kvp (QOF_INSTANCE (trans), void_former_notes_str, &v);
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, void_former_notes_str);
else
g_value_init (&v, G_TYPE_STRING);
g_value_set_string (&v, _("Voided transaction"));
qof_instance_set_kvp (QOF_INSTANCE (trans), trans_notes_str, &v);
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, trans_notes_str);
g_value_set_string (&v, reason);
qof_instance_set_kvp (QOF_INSTANCE (trans), void_reason_str, &v);
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, void_reason_str);
gnc_timespec_to_iso8601_buff (timespec_now (), iso8601_str);
g_value_set_string (&v, iso8601_str);
qof_instance_set_kvp (QOF_INSTANCE (trans), void_time_str, &v);
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, void_time_str);
FOR_EACH_SPLIT(trans, xaccSplitVoid(s));
@ -2722,7 +2715,7 @@ xaccTransGetVoidStatus(const Transaction *trans)
GValue v = G_VALUE_INIT;
g_return_val_if_fail(trans, FALSE);
qof_instance_get_kvp (QOF_INSTANCE (trans), void_reason_str, &v);
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, void_reason_str);
if (G_VALUE_HOLDS_STRING (&v))
s = g_value_get_string (&v);
return s && strlen(s);
@ -2734,7 +2727,7 @@ xaccTransGetVoidReason(const Transaction *trans)
GValue v = G_VALUE_INIT;
g_return_val_if_fail(trans, FALSE);
qof_instance_get_kvp (QOF_INSTANCE (trans), void_reason_str, &v);
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, void_reason_str);
if (G_VALUE_HOLDS_STRING (&v))
return g_value_get_string (&v);
return NULL;
@ -2748,11 +2741,11 @@ xaccTransGetVoidTime(const Transaction *tr)
Timespec void_time = {0, 0};
g_return_val_if_fail(tr, void_time);
qof_instance_get_kvp (QOF_INSTANCE (tr), void_time_str, &v);
qof_instance_get_kvp (QOF_INSTANCE (tr), &v, 1, void_time_str);
if (G_VALUE_HOLDS_STRING (&v))
s = g_value_get_string (&v);
if (s)
return gnc_iso8601_to_timespec_gmt (s);
return gnc_iso8601_to_timespec_gmt (s);
return void_time;
}
@ -2763,18 +2756,18 @@ xaccTransUnvoid (Transaction *trans)
const char *s = NULL;
g_return_if_fail(trans);
qof_instance_get_kvp (QOF_INSTANCE (trans), void_reason_str, &v);
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, void_reason_str);
if (G_VALUE_HOLDS_STRING (&v))
s = g_value_get_string (&v);
if (s == NULL) return; /* Transaction isn't voided. Bail. */
xaccTransBeginEdit(trans);
qof_instance_get_kvp (QOF_INSTANCE (trans), void_former_notes_str, &v);
qof_instance_get_kvp (QOF_INSTANCE (trans), &v, 1, void_former_notes_str);
if (G_VALUE_HOLDS_STRING (&v))
qof_instance_set_kvp (QOF_INSTANCE (trans), trans_notes_str, &v);
qof_instance_set_kvp (QOF_INSTANCE (trans), void_former_notes_str, NULL);
qof_instance_set_kvp (QOF_INSTANCE (trans), void_reason_str, NULL);
qof_instance_set_kvp (QOF_INSTANCE (trans), void_time_str, NULL);
qof_instance_set_kvp (QOF_INSTANCE (trans), &v, 1, trans_notes_str);
qof_instance_set_kvp (QOF_INSTANCE (trans), NULL, 1, void_former_notes_str);
qof_instance_set_kvp (QOF_INSTANCE (trans), NULL, 1, void_reason_str);
qof_instance_set_kvp (QOF_INSTANCE (trans), NULL, 1, void_time_str);
FOR_EACH_SPLIT(trans, xaccSplitUnvoid(s));
@ -2804,7 +2797,7 @@ xaccTransReverse (Transaction *orig)
/* Now update the original with a pointer to the new one */
g_value_init (&v, GNC_TYPE_GUID);
g_value_set_boxed (&v, xaccTransGetGUID(trans));
qof_instance_set_kvp (QOF_INSTANCE (orig), TRANS_REVERSED_BY, &v);
qof_instance_set_kvp (QOF_INSTANCE (orig), &v, 1, TRANS_REVERSED_BY);
/* Make sure the reverse transaction is not read-only */
xaccTransClearReadOnly(trans);
@ -2819,7 +2812,7 @@ xaccTransGetReversedBy(const Transaction *trans)
{
GValue v = G_VALUE_INIT;
g_return_val_if_fail(trans, NULL);
qof_instance_get_kvp (QOF_INSTANCE(trans), TRANS_REVERSED_BY, &v);
qof_instance_get_kvp (QOF_INSTANCE(trans), &v, 1, TRANS_REVERSED_BY);
if (G_VALUE_HOLDS_BOXED (&v))
return xaccTransLookup((GncGUID*)g_value_get_boxed (&v),
qof_instance_get_book(trans));

View File

@ -94,6 +94,10 @@ typedef struct _TransactionClass TransactionClass;
#include "gnc-engine.h"
#include "Split.h"
#ifdef __cplusplus
extern "C" {
#endif
/* --- type macros --- */
#define GNC_TYPE_TRANSACTION (gnc_transaction_get_type ())
#define GNC_TRANSACTION(o) \
@ -789,6 +793,10 @@ void xaccTransDump (const Transaction *trans, const char *tag);
/** \deprecated */
#define xaccTransReturnGUID(X) (X ? *(qof_entity_get_guid(QOF_INSTANCE(X))) : *(guid_null()))
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* XACC_TRANSACTION_H */
/** @} */
/** @} */

View File

@ -30,9 +30,9 @@
extern "C"
{
#include "gnc-aqbanking-templates.h"
#include "qofinstance-p.h"
}
#include "qofinstance-p.h"
#include "kvp-frame.hpp"
#include "gnc-rational.hpp"
@ -106,13 +106,13 @@ KvpFrame*
_GncABTransTempl::make_kvp_frame()
{
auto frame = new KvpFrame;
frame->set(TT_NAME, new KvpValue(m_name.c_str()));
frame->set(TT_RNAME, new KvpValue(m_recipient_name.c_str()));
frame->set(TT_RACC, new KvpValue(m_recipient_account.c_str()));
frame->set(TT_RBCODE, new KvpValue(m_recipient_bankcode.c_str()));
frame->set(TT_AMOUNT, new KvpValue(m_amount));
frame->set(TT_PURPOS, new KvpValue(m_purpose.c_str()));
frame->set(TT_PURPOSCT, new KvpValue(m_purpose_continuation.c_str()));
frame->set({TT_NAME}, new KvpValue(m_name.c_str()));
frame->set({TT_RNAME}, new KvpValue(m_recipient_name.c_str()));
frame->set({TT_RACC}, new KvpValue(m_recipient_account.c_str()));
frame->set({TT_RBCODE}, new KvpValue(m_recipient_bankcode.c_str()));
frame->set({TT_AMOUNT}, new KvpValue(m_amount));
frame->set({TT_PURPOS}, new KvpValue(m_purpose.c_str()));
frame->set({TT_PURPOSCT}, new KvpValue(m_purpose_continuation.c_str()));
return frame;
}
@ -145,12 +145,12 @@ gnc_ab_trans_templ_list_new_from_book(QofBook *b)
{
KvpFrame *frame = static_cast<KvpValue*>(node->data)->get<KvpFrame*>();
auto c_func = [frame](const char* key)
{ auto slot = frame->get_slot(key);
{ auto slot = frame->get_slot({key});
return slot == nullptr ? std::string("") : std::string(slot->get<const char*>());};
auto n_func = [frame](const char* key)
{ auto slot = frame->get_slot(key);
{ auto slot = frame->get_slot({key});
return slot == nullptr ? gnc_numeric_zero() : slot->get<gnc_numeric>();};
auto amt_slot = frame->get_slot(TT_AMOUNT);
auto amt_slot = frame->get_slot({TT_AMOUNT});
auto templ = new _GncABTransTempl (c_func(TT_NAME), c_func(TT_RNAME),
c_func(TT_RACC), c_func(TT_RBCODE),
n_func(TT_AMOUNT), c_func(TT_PURPOS),

View File

@ -473,32 +473,31 @@ gnc_budget_get_num_periods(const GncBudget* budget)
return GET_PRIVATE(budget)->num_periods;
}
#define BUF_SIZE (10 + GUID_ENCODING_LENGTH + \
GNC_BUDGET_MAX_NUM_PERIODS_DIGITS)
static inline void
make_period_path (const Account *account, guint period_num, char *path)
make_period_path (const Account *account, guint period_num, char *path1, char *path2)
{
const GncGUID *guid;
gchar *bufend;
guid = xaccAccountGetGUID(account);
bufend = guid_to_string_buff(guid, path);
g_sprintf(bufend, "/%d", period_num);
guid = xaccAccountGetGUID (account);
guid_to_string_buff (guid, path1);
g_sprintf (path2, "%d", period_num);
}
/* period_num is zero-based */
/* What happens when account is deleted, after we have an entry for it? */
void
gnc_budget_unset_account_period_value(GncBudget *budget, const Account *account,
guint period_num)
{
gchar path[BUF_SIZE];
gchar path_part_one [GUID_ENCODING_LENGTH + 1];
gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
g_return_if_fail (budget != NULL);
g_return_if_fail (account != NULL);
make_period_path (account, period_num, path);
make_period_path (account, period_num, path_part_one, path_part_two);
gnc_budget_begin_edit(budget);
qof_instance_set_kvp (QOF_INSTANCE (budget), path, NULL);
qof_instance_set_kvp (QOF_INSTANCE (budget), NULL, 2, path_part_one, path_part_two);
qof_instance_set_dirty(&budget->inst);
gnc_budget_commit_edit(budget);
@ -512,7 +511,8 @@ void
gnc_budget_set_account_period_value(GncBudget *budget, const Account *account,
guint period_num, gnc_numeric val)
{
gchar path[BUF_SIZE];
gchar path_part_one [GUID_ENCODING_LENGTH + 1];
gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
/* Watch out for an off-by-one error here:
* period_num starts from 0 while num_periods starts from 1 */
@ -525,17 +525,17 @@ gnc_budget_set_account_period_value(GncBudget *budget, const Account *account,
g_return_if_fail (budget != NULL);
g_return_if_fail (account != NULL);
make_period_path (account, period_num, path);
make_period_path (account, period_num, path_part_one, path_part_two);
gnc_budget_begin_edit(budget);
if (gnc_numeric_check(val))
qof_instance_set_kvp (QOF_INSTANCE (budget), path, NULL);
qof_instance_set_kvp (QOF_INSTANCE (budget), NULL, 2, path_part_one, path_part_two);
else
{
GValue v = G_VALUE_INIT;
g_value_init (&v, GNC_TYPE_NUMERIC);
g_value_set_boxed (&v, &val);
qof_instance_set_kvp (QOF_INSTANCE (budget), path, &v);
qof_instance_set_kvp (QOF_INSTANCE (budget), &v, 2, path_part_one, path_part_two);
}
qof_instance_set_dirty(&budget->inst);
gnc_budget_commit_edit(budget);
@ -553,14 +553,15 @@ gnc_budget_is_account_period_value_set(const GncBudget *budget,
guint period_num)
{
GValue v = G_VALUE_INIT;
gchar path[BUF_SIZE];
gchar path_part_one [GUID_ENCODING_LENGTH + 1];
gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
gconstpointer ptr = NULL;
g_return_val_if_fail(GNC_IS_BUDGET(budget), FALSE);
g_return_val_if_fail(account, FALSE);
make_period_path (account, period_num, path);
qof_instance_get_kvp (QOF_INSTANCE (budget), path, &v);
make_period_path (account, period_num, path_part_one, path_part_two);
qof_instance_get_kvp (QOF_INSTANCE (budget), &v, 2, path_part_one, path_part_two);
if (G_VALUE_HOLDS_BOXED (&v))
ptr = g_value_get_boxed (&v);
return (ptr != NULL);
@ -572,14 +573,15 @@ gnc_budget_get_account_period_value(const GncBudget *budget,
guint period_num)
{
gnc_numeric *numeric = NULL;
gchar path[BUF_SIZE];
gchar path_part_one [GUID_ENCODING_LENGTH + 1];
gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
GValue v = G_VALUE_INIT;
g_return_val_if_fail(GNC_IS_BUDGET(budget), gnc_numeric_zero());
g_return_val_if_fail(account, gnc_numeric_zero());
make_period_path (account, period_num, path);
qof_instance_get_kvp (QOF_INSTANCE (budget), path, &v);
make_period_path (account, period_num, path_part_one, path_part_two);
qof_instance_get_kvp (QOF_INSTANCE (budget), &v, 2, path_part_one, path_part_two);
if (G_VALUE_HOLDS_BOXED (&v))
numeric = (gnc_numeric*)g_value_get_boxed (&v);

View File

@ -1083,7 +1083,7 @@ gnc_commodity_get_auto_quote_control_flag(const gnc_commodity *cm)
GValue v = G_VALUE_INIT;
if (!cm) return FALSE;
qof_instance_get_kvp (QOF_INSTANCE (cm), "auto_quote_control", &v);
qof_instance_get_kvp (QOF_INSTANCE (cm), &v, 1, "auto_quote_control");
if (G_VALUE_HOLDS_STRING (&v) &&
strcmp(g_value_get_string (&v), "false") == 0)
return FALSE;
@ -1145,7 +1145,7 @@ gnc_commodity_get_user_symbol(const gnc_commodity *cm)
{
GValue v = G_VALUE_INIT;
if (!cm) return NULL;
qof_instance_get_kvp (QOF_INSTANCE(cm), "user_symbol", &v);
qof_instance_get_kvp (QOF_INSTANCE(cm), &v, 1, "user_symbol");
if (G_VALUE_HOLDS_STRING (&v))
return g_value_get_string (&v);
return NULL;
@ -1316,12 +1316,12 @@ gnc_commodity_set_auto_quote_control_flag(gnc_commodity *cm,
}
gnc_commodity_begin_edit(cm);
if (flag)
qof_instance_set_kvp (QOF_INSTANCE (cm), "auto_quote_control", NULL);
qof_instance_set_kvp (QOF_INSTANCE (cm), NULL, 1, "auto_quote_control");
else
{
g_value_init (&v, G_TYPE_STRING);
g_value_set_string (&v, "false");
qof_instance_set_kvp (QOF_INSTANCE (cm), "auto_quote_control", &v);
qof_instance_set_kvp (QOF_INSTANCE (cm), &v, 1, "auto_quote_control");
}
mark_commodity_dirty(cm);
gnc_commodity_commit_edit(cm);
@ -1456,10 +1456,10 @@ gnc_commodity_set_user_symbol(gnc_commodity * cm, const char * user_symbol)
{
g_value_init (&v, G_TYPE_STRING);
g_value_set_string (&v, user_symbol);
qof_instance_set_kvp (QOF_INSTANCE(cm), "user_symbol", &v);
qof_instance_set_kvp (QOF_INSTANCE(cm), &v, 1, "user_symbol");
}
else
qof_instance_set_kvp (QOF_INSTANCE(cm), "user_symbol", NULL);
qof_instance_set_kvp (QOF_INSTANCE(cm), NULL, 1, "user_symbol");
mark_commodity_dirty(cm);
gnc_commodity_commit_edit(cm);

View File

@ -53,6 +53,10 @@ typedef struct _GncCommodityNamespaceClass gnc_commodity_namespaceClass;
#include <glib/gi18n.h>
#include "gnc-engine.h"
#ifdef __cplusplus
extern "C" {
#endif
/* --- type macros --- */
#define GNC_TYPE_COMMODITY (gnc_commodity_get_type ())
#define GNC_COMMODITY(o) \
@ -1056,6 +1060,10 @@ void gnc_monetary_list_free(MonetaryList *list);
/** @} */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* GNC_COMMODITY_H */
/** @} */
/** @} */

View File

@ -39,6 +39,10 @@
#include <glib.h>
#include "qof.h"
#ifdef __cplusplus
extern "C" {
#endif
/** \name QofLogModule identifiers */
// @{
#define GNC_MOD_ROOT "gnc"
@ -257,6 +261,9 @@ void gnc_engine_signal_commit_error( QofBackendError errcode );
#define GNC_OWNER_GUID "owner-guid"
#define GNC_SX_ID "sched-xaction"
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
/** @} */

View File

@ -46,6 +46,7 @@ static gncFeature known_features[] =
{ GNC_FEATURE_KVP_EXTRA_DATA, "Extra data for addresses, jobs or invoice entries (requires at least GnuCash 2.6.4)" },
{ GNC_FEATURE_BOOK_CURRENCY, "User specifies a 'book-currency'; costs of other currencies/commodities tracked in terms of book-currency (requires at least GnuCash 2.7.0)" },
{ GNC_FEATURE_GUID_BAYESIAN, "Use account GUID as key for Bayesian data (requires at least GnuCash 2.6.12)" },
{ GNC_FEATURE_GUID_FLAT_BAYESIAN, "Use account GUID as key for bayesian data and store KVP flat (requires at least Gnucash 2.6.19)" },
{ NULL },
};
@ -148,6 +149,32 @@ void gnc_features_set_used (QofBook *book, const gchar *feature)
}
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;
}
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;
}

View File

@ -38,6 +38,10 @@
#include "qof.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @name Defined features
@{
*/
@ -46,6 +50,7 @@
#define GNC_FEATURE_KVP_EXTRA_DATA "Extra data in addresses, jobs or invoice entries"
#define GNC_FEATURE_BOOK_CURRENCY "Use a Book-Currency"
#define GNC_FEATURE_GUID_BAYESIAN "Account GUID based Bayesian data"
#define GNC_FEATURE_GUID_FLAT_BAYESIAN "Account GUID based bayesian with flat KVP"
/** @} */
@ -64,6 +69,14 @@ gchar *gnc_features_test_unknown (QofBook *book);
*/
void gnc_features_set_used (QofBook *book, const gchar *feature);
/*
* Returns true if the specified feature is used.
*/
gboolean gnc_features_check_used (QofBook *, char const * feature);
#ifdef __cplusplus
} /* extern "C" */
#endif /*__cplusplus*/
#endif /* GNC_FEATURES_H */
/** @} */
/** @} */

View File

@ -148,16 +148,13 @@ gnc_lot_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec*
g_value_set_int(value, priv->marker);
break;
case PROP_INVOICE:
key = GNC_INVOICE_ID "/" GNC_INVOICE_GUID;
qof_instance_get_kvp (QOF_INSTANCE (lot), key, value);
qof_instance_get_kvp (QOF_INSTANCE (lot), value, 2, GNC_INVOICE_ID, GNC_INVOICE_GUID);
break;
case PROP_OWNER_TYPE:
key = GNC_OWNER_ID"/" GNC_OWNER_TYPE;
qof_instance_get_kvp (QOF_INSTANCE (lot), key, value);
qof_instance_get_kvp (QOF_INSTANCE (lot), value, 2, GNC_OWNER_ID, GNC_OWNER_TYPE);
break;
case PROP_OWNER_GUID:
key = GNC_OWNER_ID "/" GNC_OWNER_GUID;
qof_instance_get_kvp (QOF_INSTANCE (lot), key, value);
qof_instance_get_kvp (QOF_INSTANCE (lot), value, 2, GNC_OWNER_ID, GNC_OWNER_GUID);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@ -191,16 +188,13 @@ gnc_lot_set_property (GObject* object,
priv->marker = g_value_get_int(value);
break;
case PROP_INVOICE:
key = GNC_INVOICE_ID"/" GNC_INVOICE_GUID;
qof_instance_set_kvp (QOF_INSTANCE (lot), key, value);
qof_instance_set_kvp (QOF_INSTANCE (lot), value, 2, GNC_INVOICE_ID, GNC_INVOICE_GUID);
break;
case PROP_OWNER_TYPE:
key = GNC_OWNER_ID "/" GNC_OWNER_TYPE;
qof_instance_set_kvp (QOF_INSTANCE (lot), key, value);
qof_instance_set_kvp (QOF_INSTANCE (lot), value, 2, GNC_OWNER_ID, GNC_OWNER_TYPE);
break;
case PROP_OWNER_GUID:
key = GNC_OWNER_ID "/" GNC_OWNER_GUID;
qof_instance_set_kvp (QOF_INSTANCE (lot), key, value);
qof_instance_set_kvp (QOF_INSTANCE (lot), value, 2, GNC_OWNER_ID, GNC_OWNER_GUID);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@ -433,7 +427,7 @@ gnc_lot_get_title (const GNCLot *lot)
{
GValue v = G_VALUE_INIT;
if (!lot) return NULL;
qof_instance_get_kvp (QOF_INSTANCE (lot), "/title", &v);
qof_instance_get_kvp (QOF_INSTANCE (lot), &v, 1, "title");
if (G_VALUE_HOLDS_STRING (&v))
return g_value_get_string (&v);
return NULL;
@ -444,7 +438,7 @@ gnc_lot_get_notes (const GNCLot *lot)
{
GValue v = G_VALUE_INIT;
if (!lot) return NULL;
qof_instance_get_kvp (QOF_INSTANCE (lot), "/notes", &v);
qof_instance_get_kvp (QOF_INSTANCE (lot), &v, 1, "notes");
if (G_VALUE_HOLDS_STRING (&v))
return g_value_get_string (&v);
return NULL;
@ -458,7 +452,7 @@ gnc_lot_set_title (GNCLot *lot, const char *str)
qof_begin_edit(QOF_INSTANCE(lot));
g_value_init (&v, G_TYPE_STRING);
g_value_set_string (&v, str);
qof_instance_set_kvp (QOF_INSTANCE (lot), "/title", &v);
qof_instance_set_kvp (QOF_INSTANCE (lot), &v, 1, "title");
qof_instance_set_dirty(QOF_INSTANCE(lot));
gnc_lot_commit_edit(lot);
}
@ -471,7 +465,7 @@ gnc_lot_set_notes (GNCLot *lot, const char *str)
qof_begin_edit(QOF_INSTANCE(lot));
g_value_init (&v, G_TYPE_STRING);
g_value_set_string (&v, str);
qof_instance_set_kvp (QOF_INSTANCE (lot), "/notes", &v);
qof_instance_set_kvp (QOF_INSTANCE (lot), &v, 1, "notes");
qof_instance_set_dirty(QOF_INSTANCE(lot));
gnc_lot_commit_edit(lot);
}

View File

@ -65,6 +65,10 @@
#include "gnc-engine.h"
/*#include "gnc-lot-p.h"*/
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
QofInstanceClass parent_class;
@ -174,6 +178,11 @@ GNCLot * gnc_lot_make_default (Account * acc);
#define LOT_BALANCE "balance"
#define LOT_TITLE "lot-title"
#define LOT_NOTES "notes"
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* GNC_LOT_H */
/** @} */
/** @} */

View File

@ -31,6 +31,10 @@ typedef struct _GncPriceDBClass GNCPriceDBClass;
#include "gnc-commodity.h"
#include "gnc-engine.h"
#ifdef __cplusplus
extern "C" {
#endif
/* --- type macros --- */
#define GNC_TYPE_PRICE (gnc_price_get_type ())
#define GNC_PRICE(o) \
@ -662,6 +666,10 @@ void gnc_pricedb_print_contents(GNCPriceDB *db, FILE *f);
/** @} */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* GNC_PRICEDB_H */
/** @} */
/** @} */

View File

@ -140,17 +140,14 @@ gnc_customer_get_property (GObject *object,
g_value_set_string(value, cust->name);
break;
case PROP_PDF_DIRNAME:
key = OWNER_EXPORT_PDF_DIRNAME;
qof_instance_get_kvp (QOF_INSTANCE (cust), key, value);
break;
qof_instance_get_kvp (QOF_INSTANCE (cust), value, 1, OWNER_EXPORT_PDF_DIRNAME);
break;
case PROP_LAST_POSTED:
key = LAST_POSTED_TO_ACCT;
qof_instance_get_kvp (QOF_INSTANCE (cust), key, value);
break;
qof_instance_get_kvp (QOF_INSTANCE (cust), value, 1, LAST_POSTED_TO_ACCT);
break;
case PROP_PAYMENT_LAST_ACCT:
key = GNC_PAYMENT "/" GNC_LAST_ACCOUNT;
qof_instance_get_kvp (QOF_INSTANCE (cust), key, value);
break;
qof_instance_get_kvp (QOF_INSTANCE (cust), value, 2, GNC_PAYMENT, GNC_LAST_ACCOUNT);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -177,17 +174,14 @@ gnc_customer_set_property (GObject *object,
gncCustomerSetName(cust, g_value_get_string(value));
break;
case PROP_PDF_DIRNAME:
key = OWNER_EXPORT_PDF_DIRNAME;
qof_instance_set_kvp (QOF_INSTANCE (cust), key, value);
break;
qof_instance_set_kvp (QOF_INSTANCE (cust), value, 1, OWNER_EXPORT_PDF_DIRNAME);
break;
case PROP_LAST_POSTED:
key = LAST_POSTED_TO_ACCT;
qof_instance_set_kvp (QOF_INSTANCE (cust), key, value);
break;
qof_instance_set_kvp (QOF_INSTANCE (cust), value, 1, LAST_POSTED_TO_ACCT);
break;
case PROP_PAYMENT_LAST_ACCT:
key = GNC_PAYMENT "/" GNC_LAST_ACCOUNT;
qof_instance_set_kvp (QOF_INSTANCE (cust), key, value);
break;
qof_instance_set_kvp (QOF_INSTANCE (cust), value, 2, GNC_PAYMENT, GNC_LAST_ACCOUNT);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;

View File

@ -128,10 +128,7 @@ gnc_employee_get_property (GObject *object,
GParamSpec *pspec)
{
GncEmployee *emp;
gchar *key;
g_return_if_fail(GNC_IS_EMPLOYEE(object));
emp = GNC_EMPLOYEE(object);
switch (prop_id)
{
@ -166,17 +163,14 @@ gnc_employee_get_property (GObject *object,
g_value_take_object(value, emp->ccard_acc);
break;
case PROP_PDF_DIRNAME:
key = OWNER_EXPORT_PDF_DIRNAME;
qof_instance_get_kvp (QOF_INSTANCE (emp), key, value);
break;
qof_instance_get_kvp (QOF_INSTANCE (emp), value, 1, OWNER_EXPORT_PDF_DIRNAME);
break;
case PROP_LAST_POSTED:
key = LAST_POSTED_TO_ACCT;
qof_instance_get_kvp (QOF_INSTANCE (emp), key, value);
break;
qof_instance_get_kvp (QOF_INSTANCE (emp), value, 1, LAST_POSTED_TO_ACCT);
break;
case PROP_PAYMENT_LAST_ACCT:
key = GNC_PAYMENT "/" GNC_LAST_ACCOUNT;
qof_instance_get_kvp (QOF_INSTANCE (emp), key, value);
break;
qof_instance_get_kvp (QOF_INSTANCE (emp), value, 2, GNC_PAYMENT, GNC_LAST_ACCOUNT);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -190,13 +184,9 @@ gnc_employee_set_property (GObject *object,
GParamSpec *pspec)
{
GncEmployee *emp;
gchar *key;
g_return_if_fail(GNC_IS_EMPLOYEE(object));
emp = GNC_EMPLOYEE(object);
g_assert (qof_instance_get_editlevel(emp));
switch (prop_id)
{
case PROP_USERNAME:
@ -230,17 +220,14 @@ gnc_employee_set_property (GObject *object,
gncEmployeeSetCCard(emp, g_value_get_object(value));
break;
case PROP_PDF_DIRNAME:
key = OWNER_EXPORT_PDF_DIRNAME;
qof_instance_set_kvp (QOF_INSTANCE (emp), key, value);
break;
qof_instance_set_kvp (QOF_INSTANCE (emp), value, 1, OWNER_EXPORT_PDF_DIRNAME);
break;
case PROP_LAST_POSTED:
key = LAST_POSTED_TO_ACCT;
qof_instance_set_kvp (QOF_INSTANCE (emp), key, value);
break;
qof_instance_set_kvp (QOF_INSTANCE (emp), value, 1, LAST_POSTED_TO_ACCT);
break;
case PROP_PAYMENT_LAST_ACCT:
key = GNC_PAYMENT "/" GNC_LAST_ACCOUNT;
qof_instance_set_kvp (QOF_INSTANCE (emp), key, value);
break;
qof_instance_set_kvp (QOF_INSTANCE (emp), value, 2, GNC_PAYMENT, GNC_LAST_ACCOUNT);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;

View File

@ -354,9 +354,9 @@ GncInvoice *gncInvoiceCopy (const GncInvoice *from)
invoice->billing_id = CACHE_INSERT (from->billing_id);
invoice->active = from->active;
qof_instance_get_kvp (QOF_INSTANCE (from), GNC_INVOICE_IS_CN, &v);
qof_instance_get_kvp (QOF_INSTANCE (from), &v, 1, GNC_INVOICE_IS_CN);
if (G_VALUE_HOLDS_INT64 (&v))
qof_instance_set_kvp (QOF_INSTANCE (invoice), GNC_INVOICE_IS_CN, &v);
qof_instance_set_kvp (QOF_INSTANCE (invoice), &v, 1, GNC_INVOICE_IS_CN);
invoice->terms = from->terms;
gncBillTermIncRef (invoice->terms);
@ -551,7 +551,7 @@ void gncInvoiceSetIsCreditNote (GncInvoice *invoice, gboolean credit_note)
gncInvoiceBeginEdit (invoice);
g_value_init (&v, G_TYPE_INT64);
g_value_set_int64(&v, credit_note ? 1 : 0);
qof_instance_set_kvp (QOF_INSTANCE (invoice), GNC_INVOICE_IS_CN, &v);
qof_instance_set_kvp (QOF_INSTANCE (invoice), &v, 1, GNC_INVOICE_IS_CN);
mark_invoice (invoice);
gncInvoiceCommitEdit (invoice);
@ -1040,7 +1040,7 @@ gboolean gncInvoiceGetIsCreditNote (const GncInvoice *invoice)
{
GValue v = G_VALUE_INIT;
if (!invoice) return FALSE;
qof_instance_get_kvp (QOF_INSTANCE(invoice), GNC_INVOICE_IS_CN, &v);
qof_instance_get_kvp (QOF_INSTANCE(invoice), &v, 1, GNC_INVOICE_IS_CN);
if (G_VALUE_HOLDS_INT64(&v) && g_value_get_int64(&v))
return TRUE;
else

View File

@ -120,8 +120,7 @@ gnc_job_get_property (GObject *object,
g_value_set_string(value, job->name);
break;
case PROP_PDF_DIRNAME:
key = OWNER_EXPORT_PDF_DIRNAME;
qof_instance_get_kvp (QOF_INSTANCE (job), key, value);
qof_instance_get_kvp (QOF_INSTANCE (job), value, 1, OWNER_EXPORT_PDF_DIRNAME);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@ -149,8 +148,7 @@ gnc_job_set_property (GObject *object,
gncJobSetName(job, g_value_get_string(value));
break;
case PROP_PDF_DIRNAME:
key = OWNER_EXPORT_PDF_DIRNAME;
qof_instance_set_kvp (QOF_INSTANCE (job), key, value);
qof_instance_set_kvp (QOF_INSTANCE (job), value, 1, OWNER_EXPORT_PDF_DIRNAME);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@ -318,11 +316,11 @@ void gncJobSetRate (GncJob *job, gnc_numeric rate)
GValue v = G_VALUE_INIT;
g_value_init (&v, GNC_TYPE_NUMERIC);
g_value_set_boxed (&v, &rate);
qof_instance_set_kvp (QOF_INSTANCE (job), GNC_JOB_RATE, &v);
qof_instance_set_kvp (QOF_INSTANCE (job), &v, 1, GNC_JOB_RATE);
}
else
{
qof_instance_set_kvp (QOF_INSTANCE (job), GNC_JOB_RATE, NULL);
qof_instance_set_kvp (QOF_INSTANCE (job), NULL, 1, GNC_JOB_RATE);
}
mark_job (job);
gncJobCommitEdit (job);
@ -456,7 +454,7 @@ gnc_numeric gncJobGetRate (const GncJob *job)
GValue v = G_VALUE_INIT;
gnc_numeric *rate = NULL;
if (!job) return gnc_numeric_zero ();
qof_instance_get_kvp (QOF_INSTANCE (job), GNC_JOB_RATE, &v);
qof_instance_get_kvp (QOF_INSTANCE (job), &v, 1, GNC_JOB_RATE);
if (G_VALUE_HOLDS_BOXED (&v))
rate = (gnc_numeric*)g_value_get_boxed (&v);
if (rate)

View File

@ -179,17 +179,14 @@ gnc_vendor_get_property (GObject *object,
g_value_set_string(value, qofVendorGetTaxIncluded(vendor));
break;
case PROP_PDF_DIRNAME:
key = OWNER_EXPORT_PDF_DIRNAME;
qof_instance_get_kvp (QOF_INSTANCE (vendor), key, value);
break;
qof_instance_get_kvp (QOF_INSTANCE (vendor), value, 1, OWNER_EXPORT_PDF_DIRNAME);
break;
case PROP_LAST_POSTED:
key = LAST_POSTED_TO_ACCT;
qof_instance_get_kvp (QOF_INSTANCE (vendor), key, value);
break;
qof_instance_get_kvp (QOF_INSTANCE (vendor), value, 1, LAST_POSTED_TO_ACCT);
break;
case PROP_PAYMENT_LAST_ACCT:
key = GNC_PAYMENT "/" GNC_LAST_ACCOUNT;
qof_instance_get_kvp (QOF_INSTANCE (vendor), key, value);
break;
qof_instance_get_kvp (QOF_INSTANCE (vendor), value, 2, GNC_PAYMENT, GNC_LAST_ACCOUNT);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -246,17 +243,14 @@ gnc_vendor_set_property (GObject *object,
qofVendorSetTaxIncluded(vendor, g_value_get_string(value));
break;
case PROP_PDF_DIRNAME:
key = OWNER_EXPORT_PDF_DIRNAME;
qof_instance_set_kvp (QOF_INSTANCE (vendor), key, value);
break;
qof_instance_set_kvp (QOF_INSTANCE (vendor), value, 1, OWNER_EXPORT_PDF_DIRNAME);
break;
case PROP_LAST_POSTED:
key = LAST_POSTED_TO_ACCT;
qof_instance_set_kvp (QOF_INSTANCE (vendor), key, value);
break;
qof_instance_set_kvp (QOF_INSTANCE (vendor), value, 1, LAST_POSTED_TO_ACCT);
break;
case PROP_PAYMENT_LAST_ACCT:
key = GNC_PAYMENT "/" GNC_LAST_ACCOUNT;
qof_instance_set_kvp (QOF_INSTANCE (vendor), key, value);
break;
qof_instance_set_kvp (QOF_INSTANCE (vendor), value, 2, GNC_PAYMENT, GNC_LAST_ACCOUNT);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;

View File

@ -177,7 +177,9 @@ guid_to_string_buff (const GncGUID * guid, gchar *str)
gnc::GUID temp {*guid};
auto val = temp.to_string ();
/*We need to be sure to copy the terminating null character.*/
/*We need to be sure to copy the terminating null character.
* The standard guarantees that std::basic_string::c_str ()
* returns with a terminating null character, too.*/
std::copy (val.c_str (), val.c_str () + val.size () + 1, str);
return str + val.size ();
}
@ -356,6 +358,21 @@ GUID::from_string (std::string const & str)
}
}
bool
GUID::is_valid_guid (std::string const & str)
{
try
{
static boost::uuids::string_generator strgen;
auto a = strgen (str);
return true;
}
catch (...)
{
return false;
}
}
guid_syntax_exception::guid_syntax_exception () noexcept
: invalid_argument {"Invalid syntax for guid."}
{

View File

@ -50,6 +50,7 @@ struct GUID
static GUID create_random () noexcept;
static GUID const & null_guid () noexcept;
static GUID from_string (std::string const &);
static bool is_valid_guid (std::string const &);
std::string to_string () const noexcept;
auto begin () const noexcept -> decltype (implementation.begin ());
auto end () const noexcept -> decltype (implementation.end ());

View File

@ -38,6 +38,7 @@ extern "C"
#include <sstream>
#include <algorithm>
#include <vector>
#include <numeric>
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = "qof.kvp";
@ -67,137 +68,119 @@ KvpFrameImpl::~KvpFrameImpl() noexcept
m_valuemap.clear();
}
static inline Path
make_vector(std::string key)
KvpFrame *
KvpFrame::get_child_frame_or_nullptr (Path const & path) noexcept
{
Path path;
for (auto length = key.find(delim); length != std::string::npos;)
{
if (length != 0)
path.push_back(key.substr(0, length));
key = key.substr(length + 1);
length = key.find(delim);
}
if (!key.empty())
path.push_back(key);
return path;
if (!path.size ())
return this;
auto key = path.front ();
if (m_valuemap.find (key.c_str ()) == m_valuemap.end ())
return nullptr;
auto child = m_valuemap.at (key.c_str ())->get <KvpFrame *> ();
Path send;
std::copy (path.begin () + 1, path.end (), std::back_inserter (send));
return child->get_child_frame_or_nullptr (send);
}
KvpValue*
KvpFrameImpl::set(const char* key, KvpValue* value) noexcept
KvpFrame *
KvpFrame::get_child_frame_or_create (Path const & path) noexcept
{
if (!key) return nullptr;
if (strchr(key, delim))
return set(make_vector(key), value);
KvpValue* ret {nullptr};
auto spot = m_valuemap.find(key);
if (spot != m_valuemap.end())
{
qof_string_cache_remove(spot->first);
ret = spot->second;
m_valuemap.erase(spot);
}
if (!path.size ())
return this;
auto key = path.front ();
auto spot = m_valuemap.find (key.c_str ());
if (spot == m_valuemap.end () || spot->second->get_type () != KvpValue::Type::FRAME)
delete set_impl (key.c_str (), new KvpValue {new KvpFrame});
Path send;
std::copy (path.begin () + 1, path.end (), std::back_inserter (send));
auto child_val = m_valuemap.at (key.c_str ());
auto child = child_val->get <KvpFrame *> ();
return child->get_child_frame_or_create (send);
}
KvpValue *
KvpFrame::set_impl (std::string const & key, KvpValue * value) noexcept
{
KvpValue * ret {};
auto spot = m_valuemap.find (key.c_str ());
if (spot != m_valuemap.end ())
{
qof_string_cache_remove (spot->first);
ret = spot->second;
m_valuemap.erase (spot);
}
if (value)
{
auto cachedkey =
static_cast<const char *>(qof_string_cache_insert(key));
m_valuemap.insert({cachedkey,value});
auto cachedkey = static_cast <char const *> (qof_string_cache_insert (key.c_str ()));
m_valuemap.emplace (cachedkey, value);
}
return ret;
}
static inline KvpFrameImpl*
walk_path_or_nullptr(const KvpFrameImpl* frame, Path& path)
KvpValue *
KvpFrameImpl::set (Path path, KvpValue* value) noexcept
{
KvpFrameImpl* cur_frame = const_cast<KvpFrameImpl*>(frame);
for(auto key:path)
{
auto slot = cur_frame->get_slot(key.c_str());
if (slot == nullptr || slot->get_type() != KvpValue::Type::FRAME)
return nullptr;
cur_frame = slot->get<KvpFrame*>();
}
return cur_frame;
}
KvpValue*
KvpFrameImpl::set(Path path, KvpValue* value) noexcept
{
auto last_key = path.back();
path.pop_back();
auto cur_frame = walk_path_or_nullptr(this, path);
if (cur_frame == nullptr)
auto key = path.back ();
path.pop_back ();
auto target = get_child_frame_or_nullptr (path);
if (!target)
return nullptr;
if (last_key.find(delim) != std::string::npos)
return set(make_vector(last_key), value);
return cur_frame->set(last_key.c_str(), value);
return target->set_impl (key, value);
}
static inline KvpFrameImpl*
walk_path_and_create(KvpFrameImpl* frame, Path path)
KvpValue *
KvpFrameImpl::set_path (Path path, KvpValue* value) noexcept
{
for(auto key:path)
{
if (key.empty())
continue;
if (key.find(delim) != std::string::npos)
{
frame = walk_path_and_create(frame, make_vector(key));
continue;
}
auto slot = frame->get_slot(key.c_str());
if (slot == nullptr || slot->get_type() != KvpValue::Type::FRAME)
{
auto new_frame = new KvpFrame;
delete frame->set(key.c_str(), new KvpValue{new_frame});
frame = new_frame;
continue;
}
frame = slot->get<KvpFrame*>();
}
return frame;
}
KvpValue*
KvpFrameImpl::set_path(const char* path, KvpValue* value) noexcept
{
return set_path(make_vector(path), value);
}
KvpValue*
KvpFrameImpl::set_path(Path path, KvpValue* value) noexcept
{
auto cur_frame = this;
auto last_key = path.back();
auto key = path.back();
path.pop_back();
cur_frame = walk_path_and_create(const_cast<KvpFrame*>(this), path);
if (last_key.find(delim) != std::string::npos)
return set_path(make_vector(last_key), value);
return cur_frame->set(last_key.c_str(), value);
auto target = get_child_frame_or_create (path);
if (!target)
return nullptr;
return target->set_impl (key, value);
}
KvpValue *
KvpFrameImpl::get_slot (Path path) noexcept
{
auto key = path.back();
path.pop_back();
auto target = get_child_frame_or_nullptr (path);
if (!target)
return nullptr;
auto spot = target->m_valuemap.find (key.c_str ());
if (spot != target->m_valuemap.end ())
return spot->second;
return nullptr;
}
std::string
KvpFrameImpl::to_string() const noexcept
{
std::ostringstream ret;
ret << "{\n";
return to_string("");
}
std::string
KvpFrameImpl::to_string(std::string const & prefix) const noexcept
{
if (!m_valuemap.size())
return prefix;
std::ostringstream ret;
std::for_each(m_valuemap.begin(), m_valuemap.end(),
[this,&ret](const map_type::value_type &a)
[this,&ret,&prefix](const map_type::value_type &a)
{
ret << " ";
std::string new_prefix {prefix};
if (a.first)
ret << a.first;
ret << " => ";
{
new_prefix += a.first;
new_prefix += "/";
}
if (a.second)
ret << a.second->to_string();
ret << ",\n";
ret << a.second->to_string(new_prefix) << "\n";
else
ret << new_prefix << "(null)\n";
}
);
ret << "}\n";
return ret.str();
}
@ -214,46 +197,6 @@ KvpFrameImpl::get_keys() const noexcept
return ret;
}
void
KvpFrameImpl::for_each_slot(void (*proc)(const char *key, KvpValue *value,
void * data),
void *data) const noexcept
{
if (!proc) return;
std::for_each (m_valuemap.begin(), m_valuemap.end(),
[proc,data](const KvpFrameImpl::map_type::value_type & a)
{
proc (a.first, a.second, data);
}
);
}
KvpValueImpl *
KvpFrameImpl::get_slot(const char * key) const noexcept
{
if (!key) return nullptr;
if (strchr(key, delim))
return get_slot(make_vector(key));
auto spot = m_valuemap.find(key);
if (spot == m_valuemap.end())
return nullptr;
return spot->second;
}
KvpValueImpl *
KvpFrameImpl::get_slot(Path path) const noexcept
{
auto last_key = path.back();
path.pop_back();
auto cur_frame = walk_path_or_nullptr(this, path);
if (cur_frame == nullptr)
return nullptr;
if (last_key.find(delim) != std::string::npos)
return get_slot(make_vector(last_key));
return cur_frame->get_slot(last_key.c_str());
}
int compare(const KvpFrameImpl * one, const KvpFrameImpl * two) noexcept
{
if (one && !two) return 1;
@ -479,4 +422,30 @@ gnc_value_list_get_type (void)
return type;
}
/* ========================== END OF FILE ======================= */
void
KvpFrame::flatten_kvp_impl(std::vector <std::string> path, std::vector <KvpEntry> & entries) const noexcept
{
for (auto const & entry : m_valuemap)
{
std::vector<std::string> new_path {path};
new_path.push_back("/");
if (entry.second->get_type() == KvpValue::Type::FRAME)
{
new_path.push_back(entry.first);
entry.second->get<KvpFrame*>()->flatten_kvp_impl(new_path, entries);
}
else
{
new_path.emplace_back (entry.first);
entries.emplace_back (new_path, entry.second);
}
}
}
std::vector <KvpEntry>
KvpFrame::flatten_kvp(void) const noexcept
{
std::vector <KvpEntry> ret;
flatten_kvp_impl({}, ret);
return ret;
}

View File

@ -44,12 +44,8 @@
* KVP modifications are written to the database. Two generic abstractions are
* provided:
*
* * @ref qof_instance_set_kvp and @ref qof_instance_get_kvp provide single-item
access via GValues to support object properties.
* * @ref qof_book_set_option and @ref qof_book_get_option provide similar
access for book options.
* access for book options.
*
* @ref kvpvalues provides a catolog of KVP entries including what objects
* they're part of and how they're used.
@ -93,7 +89,10 @@
#include <string>
#include <vector>
#include <cstring>
#include <algorithm>
#include <iostream>
using Path = std::vector<std::string>;
using KvpEntry = std::pair <std::vector <std::string>, KvpValue*>;
/** Implements KvpFrame.
* It's a struct because QofInstance needs to use the typename to declare a
@ -143,7 +142,7 @@ struct KvpFrameImpl
* @param newvalue: The value to set at key.
* @return The old value if there was one or nullptr.
*/
KvpValue* set(const char * key, KvpValue* newvalue) noexcept;
//KvpValue* set(const char * key, KvpValue* newvalue) noexcept;
/**
* Set the value with the key in a subframe following the keys in path,
* replacing and returning the old value if it exists or nullptr if it
@ -158,18 +157,6 @@ struct KvpFrameImpl
* @return The old value if there was one or nullptr.
*/
KvpValue* set(Path path, KvpValue* newvalue) noexcept;
/**
* Set the value with the key in a subframe following the keys in path,
* replacing and returning the old value if it exists or nullptr if it
* doesn't. Creates any missing intermediate frames. Takes
* ownership of new value and releases ownership of the returned old
* value. Values must be allocated on the free store with operator new.
* @param path: The path of subframes as a '/'-delimited string leading to
* the frame in which to insert/replace.
* @param newvalue: The value to set at key.
* @return The old value if there was one or nullptr.
*/
KvpValue* set_path(const char* path, KvpValue* newvalue) noexcept;
/**
* Set the value with the key in a subframe following the keys in path,
* replacing and returning the old value if it exists or nullptr if it
@ -187,6 +174,12 @@ struct KvpFrameImpl
* @return A std::string representing the frame and all its children.
*/
std::string to_string() const noexcept;
/**
* Make a string representation of the frame with the specified string
* prefixed to every item in the frame.
* @return A std::string representing all the children of the frame.
*/
std::string to_string(std::string const &) const noexcept;
/**
* Report the keys in the immediate frame. Be sensible about using this, it
* isn't a very efficient way to iterate.
@ -194,21 +187,38 @@ struct KvpFrameImpl
*/
std::vector<std::string> get_keys() const noexcept;
/** Get the value for the key or nullptr if it doesn't exist.
* @param key: The key.
* @return The value at the key or nullptr.
*/
KvpValue* get_slot(const char * key) const noexcept;
/** Get the value for the tail of the path or nullptr if it doesn't exist.
* @param path: Path of keys leading to the desired value.
* @return The value at the key or nullptr.
*/
KvpValue* get_slot(Path keys) const noexcept;
/** Convenience wrapper for std::for_each, which should be preferred.
KvpValue* get_slot(Path keys) noexcept;
/** The function should be of the form:
* <anything> func (char const *, KvpValue *, data_type &);
* Do not pass nullptr as the function.
*/
void for_each_slot(void (*proc)(const char *key, KvpValue *value,
void * data),
void *data) const noexcept;
template <typename func_type, typename data_type>
void for_each_slot_temp(func_type const &, data_type &) const noexcept;
template <typename func_type>
void for_each_slot_temp(func_type const &) const noexcept;
/**
* Like for_each_slot, but doesn't traverse nested values. This will only loop
* over root-level values whose keys match the specified prefix.
*/
template <typename func_type, typename data_type>
void for_each_slot_prefix(std::string const & prefix, func_type const &, data_type &) const noexcept;
template <typename func_type>
void for_each_slot_prefix(std::string const & prefix, func_type const &) const noexcept;
/**
* Returns all keys and values of this frame recursively, flattening
* the frame-containing values.
*/
std::vector <KvpEntry>
flatten_kvp(void) const noexcept;
/** Test for emptiness
* @return true if the frame contains nothing.
@ -218,8 +228,69 @@ struct KvpFrameImpl
private:
map_type m_valuemap;
KvpFrame * get_child_frame_or_nullptr (Path const &) noexcept;
KvpFrame * get_child_frame_or_create (Path const &) noexcept;
void flatten_kvp_impl(std::vector <std::string>, std::vector <KvpEntry> &) const noexcept;
KvpValue * set_impl (std::string const &, KvpValue *) noexcept;
};
template<typename func_type>
void KvpFrame::for_each_slot_prefix(std::string const & prefix,
func_type const & func) const noexcept
{
std::for_each (m_valuemap.begin(), m_valuemap.end(),
[&prefix,&func](const KvpFrameImpl::map_type::value_type & a)
{
std::string temp_key {a.first};
if (temp_key.size() < prefix.size())
return;
/* Testing for prefix matching */
if (std::mismatch(prefix.begin(), prefix.end(), temp_key.begin()).first == prefix.end())
func (a.first, a.second);
}
);
}
template<typename func_type, typename data_type>
void KvpFrame::for_each_slot_prefix(std::string const & prefix,
func_type const & func, data_type & data) const noexcept
{
std::for_each (m_valuemap.begin(), m_valuemap.end(),
[&prefix,&func,&data](const KvpFrameImpl::map_type::value_type & a)
{
std::string temp_key {a.first};
if (temp_key.size() < prefix.size())
return;
/* Testing for prefix matching */
if (std::mismatch(prefix.begin(), prefix.end(), temp_key.begin()).first == prefix.end())
func (a.first, a.second, data);
}
);
}
template <typename func_type>
void KvpFrame::for_each_slot_temp(func_type const & func) const noexcept
{
std::for_each (m_valuemap.begin(), m_valuemap.end(),
[&func](const KvpFrameImpl::map_type::value_type & a)
{
func (a.first, a.second);
}
);
}
template <typename func_type, typename data_type>
void KvpFrame::for_each_slot_temp(func_type const & func, data_type & data) const noexcept
{
std::for_each (m_valuemap.begin(), m_valuemap.end(),
[&func,&data](const KvpFrameImpl::map_type::value_type & a)
{
func (a.first, a.second, data);
}
);
}
int compare (const KvpFrameImpl &, const KvpFrameImpl &) noexcept;
int compare (const KvpFrameImpl *, const KvpFrameImpl *) noexcept;
/** @} Doxygen Group */

View File

@ -125,34 +125,32 @@ struct to_string_visitor : boost::static_visitor<void>
void operator()(int64_t val)
{
output << "KVP_VALUE_GINT64(" << val << ")";
output << val << " (64-bit int)";
}
void operator()(KvpFrame * val)
void operator()(KvpFrame* val)
{
output << "KVP_VALUE_FRAME(" << val->to_string() << ")";
output << val->to_string();
}
void operator()(GDate val)
{
output << "KVP_VALUE_GDATE(";
output << std::setw(4) << g_date_get_year(&val) << '-';
output << std::setw(2) << g_date_get_month(&val) << '-';
output << std::setw(2) << g_date_get_day(&val) << ')';
output << std::setw(2) << g_date_get_day(&val);
output << " (gdate)";
}
void operator()(GList * val)
{
output << "KVP_VALUE_GLIST(";
output << "[ ";
/*Since val is passed by value, we can modify it*/
for (;val; val = val->next)
{
auto realvalue = static_cast<const KvpValue *>(val->data);
output << ' ' << realvalue->to_string() << ',';
}
output << " ]";
output << ")";
}
@ -161,53 +159,66 @@ struct to_string_visitor : boost::static_visitor<void>
{
char tmp1[40] {};
gnc_timespec_to_iso8601_buff (val, tmp1);
output << "KVP_VALUE_TIMESPEC(" << tmp1 << ")";
output << tmp1 << " (timespec)";
}
void operator()(gnc_numeric val)
{
auto tmp1 = gnc_numeric_to_string(val);
output << "KVP_VALUE_NUMERIC(";
if (tmp1)
{
output << tmp1;
g_free(tmp1);
}
output << ")";
else
{
output << "(null)";
}
output << " (gnc_numeric)";
}
void operator()(GncGUID * val)
{
char guidstr[GUID_ENCODING_LENGTH+1];
output << "KVP_VALUE_GUID(";
if (val)
{
guid_to_string_buff(val,guidstr);
output << guidstr;
}
output << ")";
else
{
output << "(null)";
}
output << " (guid)";
}
void operator()(const char * val)
{
output << "KVP_VALUE_STRING(" << val << ")";
output << val << " (char *)";
}
void operator()(double val)
{
output << "KVP_VALUE_DOUBLE(" << val << ")";
output << val << " (double)";
}
};
std::string
KvpValueImpl::to_string() const noexcept
KvpValueImpl::to_string(std::string const & prefix) const noexcept
{
if (this->datastore.type() == typeid(KvpFrame*))
return this->get<KvpFrame*>()->to_string(prefix);
std::ostringstream ret;
to_string_visitor visitor {ret};
boost::apply_visitor(visitor, datastore);
/*We still use g_strdup since the return value will be freed by g_free*/
return ret.str();
return prefix + ret.str();
}
std::string
KvpValueImpl::to_string() const noexcept
{
return to_string("");
}
static int

View File

@ -138,6 +138,7 @@ struct KvpValueImpl
KvpValueImpl::Type get_type() const noexcept;
std::string to_string() const noexcept;
std::string to_string(std::string const & prefix) const noexcept;
template <typename T>
T get() const noexcept;

View File

@ -37,6 +37,10 @@
#ifndef XACC_POLICY_H
#define XACC_POLICY_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct gncpolicy_s GNCPolicy;
/** Valid Policy List
@ -83,6 +87,10 @@ GNCPolicy *xaccGetFIFOPolicy (void);
*/
GNCPolicy *xaccGetLIFOPolicy (void);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* XACC_POLICY_H */
/** @} */
/** @} */

View File

@ -45,12 +45,12 @@ extern "C"
{
#include "qofbackend.h"
#include "qofbook.h"
#include "qofinstance-p.h"
#include "qofquery.h"
#include "qofsession.h"
#include <gmodule.h>
}
#include "qofinstance-p.h"
#include <string>
#include <algorithm>
#include <vector>

View File

@ -82,7 +82,7 @@ qof_string_cache_destroy (void)
/* If the key exists in the cache, check the refcount. If 1, just
* remove the key. Otherwise, decrement the refcount */
void
qof_string_cache_remove(gconstpointer key)
qof_string_cache_remove(const char * key)
{
if (key)
{
@ -106,8 +106,8 @@ qof_string_cache_remove(gconstpointer key)
/* If the key exists in the cache, increment the refcount. Otherwise,
* add it with a refcount of 1. */
gpointer
qof_string_cache_insert(gconstpointer key)
char *
qof_string_cache_insert(const char * key)
{
if (key)
{
@ -118,7 +118,7 @@ qof_string_cache_insert(gconstpointer key)
{
guint* refcount = (guint*)value;
++(*refcount);
return cache_key;
return static_cast <char *> (cache_key);
}
else
{
@ -126,10 +126,17 @@ qof_string_cache_insert(gconstpointer key)
guint* refcount = static_cast<unsigned int*>(g_malloc(sizeof(guint)));
*refcount = 1;
g_hash_table_insert(cache, new_key, refcount);
return new_key;
return static_cast <char *> (new_key);
}
}
return NULL;
}
char *
qof_string_cache_replace(char const * dst, char const * src)
{
char * tmp {qof_string_cache_insert (src)};
qof_string_cache_remove (dst);
return tmp;
}
/* ************************ END OF FILE ***************************** */

View File

@ -79,14 +79,18 @@ void qof_string_cache_destroy(void);
/** You can use this function as a destroy notifier for a GHashTable
that uses common strings as keys (or values, for that matter.)
*/
void qof_string_cache_remove(gconstpointer key);
void qof_string_cache_remove(const char * key);
/** You can use this function with g_hash_table_insert(), for the key
(or value), as long as you use the destroy notifier above.
*/
gpointer qof_string_cache_insert(gconstpointer key);
char * qof_string_cache_insert(const char * key);
#define CACHE_INSERT(str) qof_string_cache_insert((gconstpointer)(str))
/** Same as CACHE_REPLACE below, but safe to call from C++.
*/
char * qof_string_cache_replace(const char * dst, const char * src);
#define CACHE_INSERT(str) qof_string_cache_insert((str))
#define CACHE_REMOVE(str) qof_string_cache_remove((str))
/* Replace cached string currently in 'dst' with string in 'src'.

View File

@ -142,62 +142,40 @@ qof_book_get_property (GObject* object,
switch (prop_id)
{
case PROP_OPT_TRADING_ACCOUNTS:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_TRADING_ACCOUNTS);
qof_instance_get_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
qof_instance_get_path_kvp (QOF_INSTANCE (book), value, {KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS, OPTION_NAME_TRADING_ACCOUNTS});
break;
case PROP_OPT_BOOK_CURRENCY:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_BOOK_CURRENCY);
qof_instance_get_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
qof_instance_get_path_kvp (QOF_INSTANCE (book), value, {KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS, OPTION_NAME_BOOK_CURRENCY});
break;
case PROP_OPT_DEFAULT_GAINS_POLICY:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_DEFAULT_GAINS_POLICY);
qof_instance_get_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
qof_instance_get_path_kvp (QOF_INSTANCE (book), value, {KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS, OPTION_NAME_DEFAULT_GAINS_POLICY});
break;
case PROP_OPT_DEFAULT_GAINS_ACCOUNT_GUID:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_DEFAULT_GAINS_LOSS_ACCT_GUID);
qof_instance_get_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
qof_instance_get_path_kvp (QOF_INSTANCE (book), value, {KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS, OPTION_NAME_DEFAULT_GAINS_LOSS_ACCT_GUID});
break;
case PROP_OPT_AUTO_READONLY_DAYS:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_AUTO_READONLY_DAYS);
qof_instance_get_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
qof_instance_get_path_kvp (QOF_INSTANCE (book), value, {KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS, OPTION_NAME_AUTO_READONLY_DAYS});
break;
case PROP_OPT_NUM_FIELD_SOURCE:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_NUM_FIELD_SOURCE);
qof_instance_get_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
qof_instance_get_path_kvp (QOF_INSTANCE (book), value, {KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS, OPTION_NAME_NUM_FIELD_SOURCE});
break;
case PROP_OPT_DEFAULT_BUDGET:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_DEFAULT_BUDGET);
qof_instance_get_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
qof_instance_get_path_kvp (QOF_INSTANCE (book), value, {KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS, OPTION_NAME_DEFAULT_BUDGET});
break;
case PROP_OPT_FY_END:
key = const_cast<char*>("fy_end");
qof_instance_get_kvp (QOF_INSTANCE (book), key, value);
break;
qof_instance_get_path_kvp (QOF_INSTANCE (book), value, {"fy_end"});
break;
case PROP_AB_TEMPLATES:
key = const_cast<char*>(AB_KEY "/" AB_TEMPLATES);
qof_instance_get_kvp (QOF_INSTANCE (book), key, value);
break;
key = const_cast<char*>(AB_KEY "/" AB_TEMPLATES);
qof_instance_get_path_kvp (QOF_INSTANCE (book), value, {"AB_KEY", "AB_TEMPLATES"});
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -220,62 +198,39 @@ qof_book_set_property (GObject *object,
switch (prop_id)
{
case PROP_OPT_TRADING_ACCOUNTS:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_TRADING_ACCOUNTS);
qof_instance_set_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
qof_instance_set_path_kvp (QOF_INSTANCE (book), value, {KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS, OPTION_NAME_TRADING_ACCOUNTS});
break;
case PROP_OPT_BOOK_CURRENCY:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_BOOK_CURRENCY);
qof_instance_set_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
qof_instance_set_path_kvp (QOF_INSTANCE (book), value, {KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS, OPTION_NAME_BOOK_CURRENCY});
break;
case PROP_OPT_DEFAULT_GAINS_POLICY:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_DEFAULT_GAINS_POLICY);
qof_instance_set_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
qof_instance_set_path_kvp (QOF_INSTANCE (book), value, {KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS, OPTION_NAME_DEFAULT_GAINS_POLICY});
break;
case PROP_OPT_DEFAULT_GAINS_ACCOUNT_GUID:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_DEFAULT_GAINS_LOSS_ACCT_GUID);
qof_instance_set_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
qof_instance_set_path_kvp (QOF_INSTANCE (book), value, {KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS, OPTION_NAME_DEFAULT_GAINS_LOSS_ACCT_GUID});
break;
case PROP_OPT_AUTO_READONLY_DAYS:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_AUTO_READONLY_DAYS);
qof_instance_set_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
qof_instance_set_path_kvp (QOF_INSTANCE (book), value, {KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS, OPTION_NAME_AUTO_READONLY_DAYS});
break;
case PROP_OPT_NUM_FIELD_SOURCE:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_NUM_FIELD_SOURCE);
qof_instance_set_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
qof_instance_set_path_kvp (QOF_INSTANCE (book), value, {KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS, OPTION_NAME_NUM_FIELD_SOURCE});
break;
case PROP_OPT_DEFAULT_BUDGET:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_DEFAULT_BUDGET);
qof_instance_set_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
qof_instance_set_path_kvp (QOF_INSTANCE (book), value, {KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS, OPTION_NAME_DEFAULT_BUDGET});
break;
case PROP_OPT_FY_END:
key = const_cast<char*>("fy_end");
qof_instance_set_kvp (QOF_INSTANCE (book), key, value);
break;
qof_instance_set_path_kvp (QOF_INSTANCE (book), value, {"fy_end"});
break;
case PROP_AB_TEMPLATES:
key = const_cast<char*>(AB_KEY "/" AB_TEMPLATES);
qof_instance_set_kvp (QOF_INSTANCE (book), key, value);
break;
qof_instance_set_path_kvp (QOF_INSTANCE (book), value, {AB_KEY, AB_TEMPLATES});
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -608,7 +563,7 @@ qof_book_get_collection (const QofBook *book, QofIdType entity_type)
col = qof_collection_new (entity_type);
g_hash_table_insert(
book->hash_of_collections,
qof_string_cache_insert((gpointer) entity_type), col);
qof_string_cache_insert(entity_type), col);
}
return col;
}
@ -1085,7 +1040,7 @@ GDate* qof_book_get_autoreadonly_gdate (const QofBook *book)
const char*
qof_book_get_string_option(const QofBook* book, const char* opt_name)
{
auto slot = qof_instance_get_slots(QOF_INSTANCE (book))->get_slot(opt_name);
auto slot = qof_instance_get_slots(QOF_INSTANCE (book))->get_slot({opt_name});
if (slot == nullptr)
return nullptr;
return slot->get<const char*>();
@ -1097,9 +1052,9 @@ qof_book_set_string_option(QofBook* book, const char* opt_name, const char* opt_
qof_book_begin_edit(book);
auto frame = qof_instance_get_slots(QOF_INSTANCE(book));
if (opt_val && (*opt_val != '\0'))
delete frame->set(opt_name, new KvpValue(g_strdup(opt_val)));
delete frame->set({opt_name}, new KvpValue(g_strdup(opt_val)));
else
delete frame->set(opt_name, nullptr);
delete frame->set({opt_name}, nullptr);
qof_instance_set_dirty (QOF_INSTANCE (book));
qof_book_commit_edit(book);
}
@ -1118,10 +1073,10 @@ static void commit_err (G_GNUC_UNUSED QofInstance *inst, QofBackendError errcode
#define GNC_FEATURES "features"
static void
add_feature_to_hash (const gchar *key, KvpValue *value, gpointer user_data)
add_feature_to_hash (const gchar *key, KvpValue *value, GHashTable * user_data)
{
gchar *descr = g_strdup(value->get<const char*>());
g_hash_table_insert (*(GHashTable**)user_data, (gchar*)key, descr);
g_hash_table_insert (user_data, (gchar*)key, descr);
}
GHashTable *
@ -1131,11 +1086,11 @@ qof_book_get_features (QofBook *book)
GHashTable *features = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL, g_free);
auto slot = frame->get_slot(GNC_FEATURES);
auto slot = frame->get_slot({GNC_FEATURES});
if (slot != nullptr)
{
frame = slot->get<KvpFrame*>();
frame->for_each_slot(&add_feature_to_hash, &features);
frame = slot->get<KvpFrame*>();
frame->for_each_slot_temp(&add_feature_to_hash, features);
}
return features;
}
@ -1145,11 +1100,11 @@ qof_book_set_feature (QofBook *book, const gchar *key, const gchar *descr)
{
KvpFrame *frame = qof_instance_get_slots (QOF_INSTANCE (book));
KvpValue* feature = nullptr;
auto feature_slot = frame->get_slot(GNC_FEATURES);
auto feature_slot = frame->get_slot({GNC_FEATURES});
if (feature_slot)
{
auto feature_frame = feature_slot->get<KvpFrame*>();
feature = feature_frame->get_slot(key);
feature = feature_frame->get_slot({key});
}
if (feature == nullptr || g_strcmp0 (feature->get<const char*>(), descr))
{
@ -1223,7 +1178,7 @@ qof_book_options_delete (QofBook *book, GSList *path)
delete root->set_path(path_v, nullptr);
}
else
delete root->set_path(KVP_OPTION_PATH, nullptr);
delete root->set_path({KVP_OPTION_PATH}, nullptr);
}
/* QofObject function implementation and registration */

View File

@ -25,6 +25,7 @@
*
* Copyright (C) 2003 Linas Vepstas <linas@linas.org>
* Copyright (c) 2007 David Hampton <hampton@employees.org>
* Copyright 2017 Aaron Laws <dartme18@gmail.com>
*/
#ifndef QOF_INSTANCE_P_H
@ -33,6 +34,8 @@
#include "qofinstance.h"
#ifdef __cplusplus
#include "kvp-frame.hpp"
#include <string>
extern "C"
{
#endif
@ -113,23 +116,24 @@ void qof_instance_set_idata(gpointer inst, guint32 idata);
* @return TRUE if Kvp isn't empty.
*/
gboolean qof_instance_has_kvp (QofInstance *inst);
/** Sets a KVP slot to a value from a GValue. The key can be a '/'-delimited
* path, and intermediate container frames will be created if necessary.
* Commits the change to the QofInstance.
/** Sets a KVP slot to a value from a GValue. Intermediate container
* frames will be created if necessary. Commits the change to the QofInstance.
* @param inst: The QofInstance on which to set the value.
* @param key: The key for the slot or '/'-delimited path
* @param key: The path to the slot.
* @param value: A GValue containing an item of a type which KvpValue knows
* how to store.
* how to store.
*/
void qof_instance_set_kvp (QofInstance *inst, const gchar *key, const GValue *value);
void qof_instance_set_kvp (QofInstance *, GValue const * value, unsigned count, ...);
/** Retrieves the contents of a KVP slot into a provided GValue.
* @param inst: The QofInstance
* @param key: The key of or '/'-delimited path to the slot.
* @param key: The path to the slot.
* @param value: A GValue into which to store the value of the slot. It will be
* set to the correct type.
*/
void qof_instance_get_kvp (const QofInstance *inst, const gchar *key, GValue
*value);
void qof_instance_get_kvp (QofInstance *, GValue * value, unsigned count, ...);
/** @} Close out the DOxygen ingroup */
/* Functions to isolate the KVP mechanism inside QOF for cases where
GValue * operations won't work.
@ -149,15 +153,39 @@ gboolean qof_instance_kvp_has_guid (const QofInstance *inst, const char *path,
void qof_instance_kvp_merge_guids (const QofInstance *target,
const QofInstance *donor, const char* path);
gboolean qof_instance_has_slot (const QofInstance *inst, const char *path);
void qof_instance_slot_delete (const QofInstance *inst, const char *path);
void qof_instance_slot_delete_if_empty (const QofInstance *inst,
const char *path);
void qof_instance_slot_delete (const QofInstance *, const char * path);
void qof_instance_slot_delete_if_empty (const QofInstance *, const char * path);
void qof_instance_foreach_slot (const QofInstance *inst, const char *path,
void(*proc)(const char*, const GValue*, void*),
void* data);
#ifdef __cplusplus
} /* extern "C" */
void qof_instance_get_path_kvp (QofInstance *, GValue *, std::vector<std::string> const &);
void qof_instance_set_path_kvp (QofInstance *, GValue const *, std::vector<std::string> const &);
bool qof_instance_has_path_slot (QofInstance const *, std::vector<std::string> const &);
void qof_instance_slot_path_delete (QofInstance const *, std::vector<std::string> const &);
void qof_instance_slot_path_delete_if_empty (QofInstance const *, std::vector<std::string> const &);
/** Returns all keys that match the given prefix and their corresponding values.*/
std::vector <std::pair <std::string, KvpValue*>>
qof_instance_get_slots_prefix (QofInstance const *, std::string const & prefix);
/**
* Similar to qof_instance_foreach_slot, but we don't traverse the depth of the key value frame,
* we only check the root level for keys that match the specified prefix.
*/
template<typename func_type, typename data_type>
void qof_instance_foreach_slot_prefix(QofInstance const * inst, std::string const & path_prefix,
func_type const & func, data_type & data)
{
inst->kvp_data->for_each_slot_prefix(path_prefix, func, data);
}
#endif
#endif /* QOF_INSTANCE_P_H */

View File

@ -26,6 +26,7 @@
*
* Copyright (C) 2003 Linas Vepstas <linas@linas.org>
* Copyright (c) 2007 David Hampton <hampton@employees.org>
* Copyright 2017 Aaron Laws <dartme18@gmail.com>
*/
#include "guid.hpp"
@ -1059,23 +1060,53 @@ qof_instance_has_kvp (QofInstance *inst)
return (inst->kvp_data != NULL && !inst->kvp_data->empty());
}
void
qof_instance_set_kvp (QofInstance *inst, const gchar *key, const GValue *value)
void qof_instance_set_path_kvp (QofInstance * inst, GValue const * value, std::vector<std::string> const & path)
{
delete inst->kvp_data->set_path(key, kvp_value_from_gvalue(value));
delete inst->kvp_data->set_path (path, kvp_value_from_gvalue (value));
}
void
qof_instance_get_kvp (const QofInstance *inst, const gchar *key, GValue *value)
qof_instance_set_kvp (QofInstance * inst, GValue const * value, unsigned count, ...)
{
auto temp = gvalue_from_kvp_value (inst->kvp_data->get_slot(key));
std::vector<std::string> path;
va_list args;
va_start (args, count);
for (unsigned i{0}; i < count; ++i)
path.push_back (va_arg (args, char const *));
va_end (args);
delete inst->kvp_data->set_path (path, kvp_value_from_gvalue (value));
}
void qof_instance_get_path_kvp (QofInstance * inst, GValue * value, std::vector<std::string> const & path)
{
auto temp = gvalue_from_kvp_value (inst->kvp_data->get_slot (path));
if (G_IS_VALUE (temp))
{
if (G_IS_VALUE (value))
g_value_unset (value);
g_value_init (value, G_VALUE_TYPE (temp));
g_value_copy (temp, value);
gnc_gvalue_free (temp);
g_value_copy (temp, value);
gnc_gvalue_free (temp);
}
}
void
qof_instance_get_kvp (QofInstance * inst, GValue * value, unsigned count, ...)
{
std::vector<std::string> path;
va_list args;
va_start (args, count);
for (unsigned i{0}; i < count; ++i)
path.push_back (va_arg (args, char const *));
va_end (args);
auto temp = gvalue_from_kvp_value (inst->kvp_data->get_slot (path));
if (G_IS_VALUE (temp))
{
if (G_IS_VALUE (value))
g_value_unset (value);
g_value_init (value, G_VALUE_TYPE (temp));
g_value_copy (temp, value);
gnc_gvalue_free (temp);
}
}
@ -1113,18 +1144,18 @@ qof_instance_kvp_add_guid (const QofInstance *inst, const char* path,
g_return_if_fail (inst->kvp_data != NULL);
auto container = new KvpFrame;
container->set(key, new KvpValue(const_cast<GncGUID*>(guid)));
container->set("date", new KvpValue(time));
delete inst->kvp_data->set_path(path, new KvpValue(container));
container->set({key}, new KvpValue(const_cast<GncGUID*>(guid)));
container->set({"date"}, new KvpValue(time));
delete inst->kvp_data->set_path({path}, new KvpValue(container));
}
inline static gboolean
kvp_match_guid (KvpValue *v, const char *key, const GncGUID *guid)
kvp_match_guid (KvpValue *v, std::vector<std::string> const & path, const GncGUID *guid)
{
if (v->get_type() != KvpValue::Type::FRAME)
return FALSE;
auto frame = v->get<KvpFrame*>();
auto val = frame->get_slot(key);
auto val = frame->get_slot(path);
if (val == nullptr || val->get_type() != KvpValue::Type::GUID)
return FALSE;
auto this_guid = val->get<GncGUID*>();
@ -1139,13 +1170,13 @@ qof_instance_kvp_has_guid (const QofInstance *inst, const char *path,
g_return_val_if_fail (inst->kvp_data != NULL, FALSE);
g_return_val_if_fail (guid != NULL, FALSE);
auto v = inst->kvp_data->get_slot(path);
auto v = inst->kvp_data->get_slot({path});
if (v == nullptr) return FALSE;
switch (v->get_type())
{
case KvpValue::Type::FRAME:
return kvp_match_guid (v, key, guid);
return kvp_match_guid (v, {key}, guid);
break;
case KvpValue::Type::GLIST:
{
@ -1153,7 +1184,7 @@ qof_instance_kvp_has_guid (const QofInstance *inst, const char *path,
for (auto node = list; node != NULL; node = node->next)
{
auto val = static_cast<KvpValue*>(node->data);
if (kvp_match_guid (val, key, guid))
if (kvp_match_guid (val, {key}, guid))
{
return TRUE;
}
@ -1174,15 +1205,15 @@ qof_instance_kvp_remove_guid (const QofInstance *inst, const char *path,
g_return_if_fail (inst->kvp_data != NULL);
g_return_if_fail (guid != NULL);
auto v = inst->kvp_data->get_slot(path);
auto v = inst->kvp_data->get_slot({path});
if (v == NULL) return;
switch (v->get_type())
{
case KvpValue::Type::FRAME:
if (kvp_match_guid (v, key, guid))
if (kvp_match_guid (v, {key}, guid))
{
delete inst->kvp_data->set_path(path, nullptr);
delete inst->kvp_data->set_path({path}, nullptr);
delete v;
}
break;
@ -1192,7 +1223,7 @@ qof_instance_kvp_remove_guid (const QofInstance *inst, const char *path,
for (auto node = list; node != nullptr; node = node->next)
{
auto val = static_cast<KvpValue*>(node->data);
if (kvp_match_guid (val, key, guid))
if (kvp_match_guid (val, {key}, guid))
{
list = g_list_delete_link (list, node);
v->set(list);
@ -1216,19 +1247,19 @@ qof_instance_kvp_merge_guids (const QofInstance *target,
g_return_if_fail (target != NULL);
g_return_if_fail (donor != NULL);
if (! qof_instance_has_slot (donor, path)) return;
auto v = donor->kvp_data->get_slot(path);
if (! qof_instance_has_slot (donor, {path})) return;
auto v = donor->kvp_data->get_slot({path});
if (v == NULL) return;
auto target_val = target->kvp_data->get_slot(path);
auto target_val = target->kvp_data->get_slot({path});
switch (v->get_type())
{
case KvpValue::Type::FRAME:
if (target_val)
target_val->add(v);
else
target->kvp_data->set_path(path, v);
donor->kvp_data->set(path, nullptr); //Contents moved, Don't delete!
target->kvp_data->set_path({path}, v);
donor->kvp_data->set({path}, nullptr); //Contents moved, Don't delete!
break;
case KvpValue::Type::GLIST:
if (target_val)
@ -1238,8 +1269,8 @@ qof_instance_kvp_merge_guids (const QofInstance *target,
target_val->set(list);
}
else
target->kvp_data->set(path, v);
donor->kvp_data->set(path, nullptr); //Contents moved, Don't delete!
target->kvp_data->set({path}, v);
donor->kvp_data->set({path}, nullptr); //Contents moved, Don't delete!
break;
default:
PWARN ("Instance KVP on path %s contains the wrong type.", path);
@ -1247,29 +1278,62 @@ qof_instance_kvp_merge_guids (const QofInstance *target,
}
}
bool qof_instance_has_path_slot (QofInstance const * inst, std::vector<std::string> const & path)
{
return inst->kvp_data->get_slot (path) != nullptr;
}
gboolean
qof_instance_has_slot (const QofInstance *inst, const char *path)
{
return inst->kvp_data->get_slot(path) != NULL;
return inst->kvp_data->get_slot({path}) != NULL;
}
void qof_instance_slot_path_delete (QofInstance const * inst, std::vector<std::string> const & path)
{
delete inst->kvp_data->set (path, nullptr);
}
void
qof_instance_slot_delete (const QofInstance *inst, const char *path)
qof_instance_slot_delete (QofInstance const *inst, char const * path)
{
inst->kvp_data->set(path, nullptr);
delete inst->kvp_data->set ({path}, nullptr);
}
void
qof_instance_slot_delete_if_empty (const QofInstance *inst, const char *path)
void qof_instance_slot_path_delete_if_empty (QofInstance const * inst, std::vector<std::string> const & path)
{
auto slot = inst->kvp_data->get_slot(path);
auto slot = inst->kvp_data->get_slot (path);
if (slot)
{
auto frame = slot->get<KvpFrame*>();
auto frame = slot->get <KvpFrame*> ();
if (frame && frame->empty())
inst->kvp_data->set(path, nullptr);
delete inst->kvp_data->set (path, nullptr);
}
}
void
qof_instance_slot_delete_if_empty (QofInstance const *inst, char const * path)
{
auto slot = inst->kvp_data->get_slot ({path});
if (slot)
{
auto frame = slot->get <KvpFrame*> ();
if (frame && frame->empty ())
delete inst->kvp_data->set ({path}, nullptr);
}
}
std::vector <std::pair <std::string, KvpValue*>>
qof_instance_get_slots_prefix (QofInstance const * inst, std::string const & prefix)
{
std::vector <std::pair <std::string, KvpValue*>> ret;
inst->kvp_data->for_each_slot_temp ([&prefix, &ret] (std::string const & key, KvpValue * val) {
if (key.find (prefix) == 0)
ret.emplace_back (key, val);
});
return ret;
}
namespace {
struct wrap_param
{
@ -1277,11 +1341,11 @@ struct wrap_param
void *user_data;
};
}
static void
wrap_gvalue_function (const char* key, KvpValue *val, gpointer data)
wrap_gvalue_function (const char* key, KvpValue *val, wrap_param & param)
{
GValue *gv;
auto param = static_cast<wrap_param*>(data);
if (val->get_type() != KvpValue::Type::FRAME)
gv = gvalue_from_kvp_value(val);
else
@ -1290,7 +1354,7 @@ wrap_gvalue_function (const char* key, KvpValue *val, gpointer data)
g_value_init (gv, G_TYPE_STRING);
g_value_set_string (gv, nullptr);
}
param->proc(key, gv, param->user_data);
param.proc(key, gv, param.user_data);
g_slice_free (GValue, gv);
}
@ -1299,12 +1363,12 @@ qof_instance_foreach_slot (const QofInstance *inst, const char* path,
void (*proc)(const char*, const GValue*, void*),
void* data)
{
auto slot = inst->kvp_data->get_slot(path);
auto slot = inst->kvp_data->get_slot({path});
if (slot == nullptr || slot->get_type() != KvpValue::Type::FRAME)
return;
auto frame = slot->get<KvpFrame*>();
wrap_param new_data {proc, data};
frame->for_each_slot(wrap_gvalue_function, &new_data);
frame->for_each_slot_temp(&wrap_gvalue_function, new_data);
}
/* ========================== END OF FILE ======================= */

View File

@ -50,12 +50,12 @@ extern "C"
#include <glib.h>
#include "qof.h"
#include "qofbook-p.h"
#include "qofobject-p.h"
static QofLogModule log_module = QOF_MOD_SESSION;
} //extern 'C'
#include "qofbook-p.h"
#include "qof-backend.hpp"
#include "qofsession.hpp"
#include "gnc-backend-prov.hpp"

View File

@ -55,7 +55,6 @@ extern "C"
#include <string.h>
#include <sys/stat.h>
#include <qof.h>
#include <qofinstance-p.h>
#include "Account.h"
#include "AccountP.h"
@ -71,6 +70,7 @@ extern "C"
#include "test-stuff.h"
#include "test-engine-strings.h"
}
#include <qofinstance-p.h>
static gboolean glist_strings_only = FALSE;
@ -381,7 +381,7 @@ get_random_kvp_frame_depth (gint depth)
val_added = TRUE;
ret->set_path(key, val);
ret->set_path({key}, val);
g_free(key);
}

View File

@ -25,11 +25,12 @@ extern "C"
#include <config.h>
#include "../Account.h"
#include <qof.h>
#include <qofinstance-p.h>
}
#include <qofinstance-p.h>
#include <kvp-frame.hpp>
#include <gtest/gtest.h>
#include <string>
class ImapTest : public testing::Test
{
@ -67,7 +68,11 @@ protected:
gnc_account_append_child(t_expense_account, t_expense_account2);
}
void TearDown() {
qof_book_destroy (gnc_account_get_book (t_bank_account));
auto root = gnc_account_get_root (t_bank_account);
auto book = gnc_account_get_book (root);
xaccAccountBeginEdit (root);
xaccAccountDestroy (root);
qof_book_destroy (book);
}
Account *t_bank_account {};
Account *t_sav_account {};
@ -110,18 +115,16 @@ protected:
TEST_F(ImapPlainTest, FindAccount)
{
auto root = qof_instance_get_slots(QOF_INSTANCE(t_bank_account));
auto acc1_val = new KvpValue(const_cast<GncGUID*>(xaccAccountGetGUID(t_expense_account1)));
auto acc2_val = new KvpValue(const_cast<GncGUID*>(xaccAccountGetGUID(t_expense_account2)));
auto acc1_val = new KvpValue(guid_copy(xaccAccountGetGUID(t_expense_account1)));
auto acc2_val = new KvpValue(guid_copy(xaccAccountGetGUID(t_expense_account2)));
root->set_path({IMAP_FRAME, "foo", "bar"}, acc1_val);
root->set_path({IMAP_FRAME, "baz", "waldo"}, acc2_val);
root->set_path({IMAP_FRAME, "pepper"}, acc1_val);
root->set_path({IMAP_FRAME, "salt"}, acc2_val);
root->set_path({IMAP_FRAME, "pepper"}, new KvpValue{*acc1_val});
root->set_path({IMAP_FRAME, "salt"}, new KvpValue{*acc2_val});
EXPECT_EQ(t_expense_account1, gnc_account_imap_find_account(t_imap, "foo", "bar"));
EXPECT_EQ(t_expense_account2,
gnc_account_imap_find_account(t_imap, "baz", "waldo"));
EXPECT_EQ(t_expense_account1,
gnc_account_imap_find_account(t_imap, NULL, "pepper"));
EXPECT_EQ(t_expense_account2, gnc_account_imap_find_account(t_imap, "baz", "waldo"));
EXPECT_EQ(t_expense_account1, gnc_account_imap_find_account(t_imap, NULL, "pepper"));
EXPECT_EQ(t_expense_account2, gnc_account_imap_find_account(t_imap, NULL, "salt"));
EXPECT_EQ(nullptr, gnc_account_imap_find_account(t_imap, "salt", NULL));
}
@ -251,12 +254,12 @@ TEST_F(ImapBayesTest, FindAccountBayes)
auto acct2_guid = guid_to_string (xaccAccountGetGUID(t_expense_account2));
auto value = new KvpValue(INT64_C(42));
root->set_path({IMAP_FRAME_BAYES, foo, acct1_guid}, value);
root->set_path({IMAP_FRAME_BAYES, bar, acct1_guid}, value);
root->set_path({IMAP_FRAME_BAYES, baz, acct2_guid}, value);
root->set_path({IMAP_FRAME_BAYES, waldo, acct2_guid}, value);
root->set_path({IMAP_FRAME_BAYES, pepper, acct1_guid}, value);
root->set_path({IMAP_FRAME_BAYES, salt, acct2_guid}, value);
root->set_path({std::string{IMAP_FRAME_BAYES} + "/" + foo + "/" + acct1_guid}, value);
root->set_path({std::string{IMAP_FRAME_BAYES} + "/" + bar + "/" + acct1_guid}, new KvpValue{*value});
root->set_path({std::string{IMAP_FRAME_BAYES} + "/" + baz + "/" + acct2_guid}, new KvpValue{*value});
root->set_path({std::string{IMAP_FRAME_BAYES} + "/" + waldo + "/" + acct2_guid}, new KvpValue{*value});
root->set_path({std::string{IMAP_FRAME_BAYES} + "/" + pepper + "/" + acct1_guid}, new KvpValue{*value});
root->set_path({std::string{IMAP_FRAME_BAYES} + "/" + salt + "/" + acct2_guid}, new KvpValue{*value});
auto account = gnc_account_imap_find_account_bayes(t_imap, t_list1);
EXPECT_EQ(t_expense_account1, account);
@ -289,103 +292,103 @@ TEST_F(ImapBayesTest, AddAccountBayes)
auto root = qof_instance_get_slots(QOF_INSTANCE(t_bank_account));
auto acct1_guid = guid_to_string (xaccAccountGetGUID(t_expense_account1));
auto acct2_guid = guid_to_string (xaccAccountGetGUID(t_expense_account2));
auto value = root->get_slot({IMAP_FRAME_BAYES, "foo", "bar"});
auto value = root->get_slot({std::string{IMAP_FRAME_BAYES} + "/foo/bar"});
auto check_account = [this](KvpValue* v) {
return (v->get<const char*>(), this->t_imap->book); };
value = root->get_slot({IMAP_FRAME_BAYES, foo, acct1_guid});
value = root->get_slot({std::string{IMAP_FRAME_BAYES} + "/" + foo + "/" + acct1_guid});
EXPECT_EQ(1, value->get<int64_t>());
value = root->get_slot({IMAP_FRAME_BAYES, bar, acct1_guid});
value = root->get_slot({std::string{IMAP_FRAME_BAYES} + "/" + bar + "/" + acct1_guid});
EXPECT_EQ(1, value->get<int64_t>());
value = root->get_slot({IMAP_FRAME_BAYES, baz, acct2_guid});
value = root->get_slot({std::string{IMAP_FRAME_BAYES} + "/" + baz + "/" + acct2_guid});
EXPECT_EQ(1, value->get<int64_t>());
value = root->get_slot({IMAP_FRAME_BAYES, waldo, acct2_guid});
value = root->get_slot({std::string{IMAP_FRAME_BAYES} + "/" + waldo + "/" + acct2_guid});
EXPECT_EQ(1, value->get<int64_t>());
value = root->get_slot({IMAP_FRAME_BAYES, pepper, acct1_guid});
value = root->get_slot({std::string{IMAP_FRAME_BAYES} + "/" + pepper + "/" + acct1_guid});
EXPECT_EQ(1, value->get<int64_t>());
value = root->get_slot({IMAP_FRAME_BAYES, salt, acct2_guid});
value = root->get_slot({std::string{IMAP_FRAME_BAYES} + "/" + salt + "/" + acct2_guid});
EXPECT_EQ(1, value->get<int64_t>());
value = root->get_slot({IMAP_FRAME_BAYES, baz, acct1_guid});
value = root->get_slot({std::string{IMAP_FRAME_BAYES} + "/" + baz + "/" + acct1_guid});
EXPECT_EQ(nullptr, value);
qof_instance_increase_editlevel(QOF_INSTANCE(t_bank_account));
gnc_account_imap_add_account_bayes(t_imap, t_list2, t_expense_account2);
qof_instance_mark_clean(QOF_INSTANCE(t_bank_account));
qof_instance_reset_editlevel(QOF_INSTANCE(t_bank_account));
value = root->get_slot({IMAP_FRAME_BAYES, baz, acct2_guid});
value = root->get_slot({std::string{IMAP_FRAME_BAYES} + "/" + baz + "/" + acct2_guid});
EXPECT_EQ(2, value->get<int64_t>());
}
TEST_F(ImapBayesTest, ConvertAccountBayes)
TEST_F(ImapBayesTest, ConvertBayesData)
{
// prevent the embedded beginedit/committedit from doing anything
qof_instance_increase_editlevel(QOF_INSTANCE(t_bank_account));
qof_instance_mark_clean(QOF_INSTANCE(t_bank_account));
gnc_account_imap_add_account_bayes(t_imap, t_list1, t_expense_account1); //Food
gnc_account_imap_add_account_bayes(t_imap, t_list2, t_expense_account2); //Drink
auto root = qof_instance_get_slots(QOF_INSTANCE(t_bank_account));
auto book = qof_instance_get_slots(QOF_INSTANCE(t_imap->book));
auto acct1_guid = guid_to_string (xaccAccountGetGUID(t_expense_account1)); //Food
auto acct2_guid = guid_to_string (xaccAccountGetGUID(t_expense_account2)); //Drink
auto acct3_guid = guid_to_string (xaccAccountGetGUID(t_asset_account2)); //Asset-Bank
auto acct4_guid = guid_to_string (xaccAccountGetGUID(t_sav_account)); //Sav Bank
auto val1 = new KvpValue(static_cast<int64_t>(10));
auto val2 = new KvpValue(static_cast<int64_t>(5));
auto val3 = new KvpValue(static_cast<int64_t>(2));
// Test for existing entries, all will be 1
auto value = root->get_slot({IMAP_FRAME_BAYES, foo, acct1_guid});
EXPECT_EQ(1, value->get<int64_t>());
value = root->get_slot({IMAP_FRAME_BAYES, bar, acct1_guid});
EXPECT_EQ(1, value->get<int64_t>());
value = root->get_slot({IMAP_FRAME_BAYES, baz, acct2_guid});
EXPECT_EQ(1, value->get<int64_t>());
value = root->get_slot({IMAP_FRAME_BAYES, waldo, acct2_guid});
EXPECT_EQ(1, value->get<int64_t>());
// Set up some old entries
root->set_path({IMAP_FRAME_BAYES, pepper, "Asset-Bank"}, val1);
root->set_path({IMAP_FRAME_BAYES, salt, "Asset-Bank#Bank"}, val1);
root->set_path({IMAP_FRAME_BAYES, "severely", "divided", "token", "Asset-Bank"}, val1);
root->set_path({IMAP_FRAME_BAYES, salt, "Asset-Bank#Bank"}, new KvpValue{*val1});
root->set_path({IMAP_FRAME_BAYES, salt, "Asset>Bank#Bank"}, val2);
root->set_path({IMAP_FRAME_BAYES, pork, "Expense#Food"}, val2);
root->set_path({IMAP_FRAME_BAYES, pork, "Expense#Food"}, new KvpValue{*val2});
root->set_path({IMAP_FRAME_BAYES, sausage, "Expense#Drink"}, val3);
root->set_path({IMAP_FRAME_BAYES, foo, "Expense#Food"}, val2);
EXPECT_EQ(1, qof_instance_get_editlevel(QOF_INSTANCE(t_bank_account)));
EXPECT_TRUE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account)));
qof_instance_mark_clean(QOF_INSTANCE(t_bank_account));
// Start Convert
gnc_account_imap_convert_bayes (t_imap->book);
root->set_path({IMAP_FRAME_BAYES, foo, "Expense#Food"}, new KvpValue{*val2});
root->set_path({IMAP_FRAME_BAYES, salt, acct1_guid}, new KvpValue{*val1});
/*Calling into the imap functions should trigger a conversion.*/
gnc_account_imap_add_account_bayes(t_imap, t_list5, t_expense_account2); //pork and sausage; account Food
// convert from 'Asset-Bank' to 'Asset-Bank' guid
value = root->get_slot({IMAP_FRAME_BAYES, pepper, acct3_guid});
auto value = root->get_slot({std::string{IMAP_FRAME_BAYES} + "/severely/divided/token/" + acct3_guid});
EXPECT_EQ(10, value->get<int64_t>());
// convert from 'Asset-Bank#Bank' to 'Sav Bank' guid
value = root->get_slot({IMAP_FRAME_BAYES, salt, acct4_guid});
value = root->get_slot({std::string{IMAP_FRAME_BAYES} + "/" + salt + "/" + acct4_guid});
EXPECT_EQ(10, value->get<int64_t>());
// convert from 'Expense#Food' to 'Food' guid
value = root->get_slot({IMAP_FRAME_BAYES, pork, acct1_guid});
value = root->get_slot({std::string{IMAP_FRAME_BAYES} + "/" + pork + "/" + acct1_guid});
EXPECT_EQ(5, value->get<int64_t>());
// convert from 'Expense#Drink' to 'Drink' guid
value = root->get_slot({IMAP_FRAME_BAYES, sausage, acct2_guid});
EXPECT_EQ(2, value->get<int64_t>());
value = root->get_slot({std::string{IMAP_FRAME_BAYES} + "/" + sausage + "/" + acct2_guid});
/*We put in 2, then called it once to bring it up to 3.*/
EXPECT_EQ(3, value->get<int64_t>());
// convert from 'Expense#Food' to 'Food' guid but add to original value
value = root->get_slot({IMAP_FRAME_BAYES, foo, acct1_guid});
EXPECT_EQ(6, value->get<int64_t>());
// Check for run once flag
auto vals = book->get_slot("changed-bayesian-to-guid");
EXPECT_STREQ("true", vals->get<const char*>());
EXPECT_EQ(1, qof_instance_get_editlevel(QOF_INSTANCE(t_bank_account)));
value = root->get_slot({std::string{IMAP_FRAME_BAYES} + "/" + foo + "/" + acct1_guid});
EXPECT_EQ(5, value->get<int64_t>());
// Keep GUID value from original
value = root->get_slot({std::string{IMAP_FRAME_BAYES} + "/" + salt + "/" + acct1_guid});
EXPECT_EQ(10, value->get<int64_t>());
EXPECT_TRUE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account)));
}
/* Tests the import map's handling of KVP delimiters */
TEST_F (ImapBayesTest, import_map_with_delimiters)
{
GList * tokens {nullptr};
tokens = g_list_prepend (tokens, const_cast<char*> ("one/two/three"));
gnc_account_imap_add_account_bayes (t_imap, tokens, t_expense_account1);
gnc_account_imap_add_account_bayes (t_imap, tokens, t_expense_account1);
gnc_account_imap_add_account_bayes (t_imap, tokens, t_expense_account1);
auto account = gnc_account_imap_find_account_bayes (t_imap, tokens);
EXPECT_EQ (account, t_expense_account1);
}
TEST_F (ImapBayesTest, get_bayes_info)
{
GList * tokens {nullptr};
tokens = g_list_prepend (tokens, const_cast <char*> ("one/two/three"));
gnc_account_imap_add_account_bayes(t_imap, tokens, t_expense_account1);
auto account = gnc_account_imap_find_account_bayes (t_imap, tokens);
EXPECT_EQ (account, t_expense_account1);
auto infos = gnc_account_imap_get_info_bayes (t_bank_account);
EXPECT_EQ (g_list_first (infos), g_list_last (infos));
auto info = static_cast <imap_info*> (g_list_first (infos)->data);
EXPECT_EQ (info->source_account, t_bank_account);
EXPECT_EQ (info->map_account, t_expense_account1);
auto acct1_guid = guid_to_string (xaccAccountGetGUID(t_expense_account1)); //Food
EXPECT_STREQ (info->full_category, (std::string {IMAP_FRAME_BAYES} + "/one/two/three/" + acct1_guid).c_str ());
EXPECT_STREQ (info->match_string, "one/two/three");
EXPECT_STREQ (info->category_head, (std::string {IMAP_FRAME_BAYES} + "/one/two/three").c_str ());
EXPECT_STREQ (info->count, "1");
}

View File

@ -32,10 +32,10 @@ extern "C"
#include "qof.h"
#include "Account.h"
#include "cashobjects.h"
#include "test-stuff.h"
#include "test-engine-stuff.h"
#include <qofinstance-p.h>
}
#include <qofinstance-p.h>
#include "test-stuff.h"
static void
run_test (void)

View File

@ -35,10 +35,10 @@ public:
t_int_val{new KvpValue {INT64_C(15)}},
t_str_val{new KvpValue{"a value"}} {
auto f1 = new KvpFrame;
t_root.set("top", new KvpValue{f1});
f1->set("first", t_int_val);
f1->set("second", new KvpValue{new KvpFrame});
f1->set("third", t_str_val);
t_root.set({"top"}, new KvpValue{f1});
f1->set({"first"}, t_int_val);
f1->set({"second"}, new KvpValue{new KvpFrame});
f1->set({"third"}, t_str_val);
}
protected:
KvpFrameImpl t_root;
@ -59,13 +59,12 @@ TEST_F (KvpFrameTest, SetLocal)
auto v1 = new KvpValueImpl {15.0};
auto v2 = new KvpValueImpl { (int64_t)52};
const char* k1 = "first key";
const char* k2 = "first key/second key";
EXPECT_EQ (nullptr, f1->set (k1, v1));
EXPECT_EQ (nullptr, f1->set ({k1}, v1));
auto first_frame = new KvpFrame;
EXPECT_EQ (v1, f1->set (k1, new KvpValue{first_frame}));
EXPECT_EQ (nullptr, f1->set(k2, v2));
EXPECT_EQ (v2, first_frame->get_slot("second key"));
EXPECT_EQ (v1, f1->set ({k1}, new KvpValue{first_frame}));
EXPECT_EQ (nullptr, f1->set({"first key", "second key"}, v2));
EXPECT_EQ (v2, first_frame->get_slot({"second key"}));
delete f1; //this should also delete v2.
delete v1;
@ -88,15 +87,14 @@ TEST_F (KvpFrameTest, SetPath)
TEST_F (KvpFrameTest, SetPathSlash)
{
Path path1 {"top", "second/twenty", "twenty-first"};
Path path1 {"top", "second", "twenty", "twenty-first"};
Path path2 {"top", "third", "thirty-first"};
auto v1 = new KvpValueImpl {15.0};
auto v2 = new KvpValueImpl { (int64_t)52};
EXPECT_EQ (nullptr, t_root.set(path1, v1));
EXPECT_EQ (nullptr, t_root.set(path1, v2));
auto second_frame = t_root.get_slot("top")->get<KvpFrame*>()->get_slot("second")->get<KvpFrame*>();
second_frame->set("twenty", new KvpValue{new KvpFrame});
auto second_frame = t_root.get_slot({"top"})->get<KvpFrame*>()->get_slot({"second"})->get<KvpFrame*>();
second_frame->set({"twenty"}, new KvpValue{new KvpFrame});
EXPECT_EQ (nullptr, t_root.set(path1, v1));
EXPECT_EQ (v1, t_root.set(path1, v2));
EXPECT_EQ (v2, t_root.get_slot(path1));
@ -104,16 +102,6 @@ TEST_F (KvpFrameTest, SetPathSlash)
delete v1;
}
TEST_F (KvpFrameTest, SetPathIgnoreBeginEndSlash)
{
Path path1 {"top", "/second/", "twenty-first"};
Path path2 {"top", "second", "twenty-first"};
auto v1 = new KvpValueImpl {15.0};
EXPECT_EQ (nullptr, t_root.set_path(path1, v1));
EXPECT_EQ (v1, t_root.get_slot(path2));
}
TEST_F (KvpFrameTest, SetPathWithCreate)
{
Path path1 {"top", "second", "twenty-first"};
@ -130,7 +118,7 @@ TEST_F (KvpFrameTest, SetPathWithCreate)
TEST_F (KvpFrameTest, SetPathWithCreateSlash)
{
Path path1 {"top", "second/twenty", "twenty-first"};
Path path1 {"top", "second", "twenty", "twenty-first"};
Path path2 {"top", "third", "thirty-first"};
Path path1a {"top", "second", "twenty", "twenty-first"};
auto v1 = new KvpValueImpl {15.0};
@ -154,7 +142,7 @@ TEST_F (KvpFrameTest, GetKeys)
EXPECT_EQ (keys.size (), 1ul);
assert_contains (keys, k1);
auto frameval = t_root.get_slot(k1);
auto frameval = t_root.get_slot({k1});
ASSERT_EQ(frameval->get_type(), KvpValue::Type::FRAME);
keys = frameval->get<KvpFrame*>()->get_keys();
assert_contains (keys, k2);
@ -166,15 +154,13 @@ TEST_F (KvpFrameTest, GetLocalSlot)
auto k1 = "first";
auto k2 = "third";
auto k3 = "doesn't exist";
auto k4 = "top/first";
auto frameval = t_root.get_slot("top");
auto frameval = t_root.get_slot({"top"});
ASSERT_EQ(frameval->get_type(), KvpValue::Type::FRAME);
auto f1 = frameval->get<KvpFrame*>();
EXPECT_EQ (t_int_val, f1->get_slot(k1));
EXPECT_EQ (t_str_val, f1->get_slot(k2));
EXPECT_EQ (nullptr, f1->get_slot(k3));
EXPECT_EQ (t_int_val, t_root.get_slot(k4));
EXPECT_EQ (t_int_val, f1->get_slot({k1}));
EXPECT_EQ (t_str_val, f1->get_slot({k2}));
EXPECT_EQ (nullptr, f1->get_slot({k3}));
EXPECT_EQ (t_int_val, t_root.get_slot({"top", "first"}));
}
TEST_F (KvpFrameTest, GetSlotPath)
@ -182,7 +168,7 @@ TEST_F (KvpFrameTest, GetSlotPath)
Path path1 {"top", "second", "twenty-first"};
Path path2 {"top", "third", "thirty-first"};
Path path3 {"top", "second", "twenty", "twenty-first"};
Path path3a {"top", "second/twenty", "twenty-first"};
Path path3a {"top", "second", "twenty", "twenty-first"};
auto v1 = new KvpValueImpl {15.0};
auto v2 = new KvpValueImpl { (int64_t)52};
@ -198,7 +184,45 @@ TEST_F (KvpFrameTest, GetSlotPath)
TEST_F (KvpFrameTest, Empty)
{
KvpFrameImpl f1, f2;
f2.set("value", new KvpValue {2.2});
f2.set({"value"}, new KvpValue {2.2});
EXPECT_TRUE(f1.empty());
EXPECT_FALSE(f2.empty());
}
TEST (KvpFrameTestForEachPrefix, for_each_prefix_1)
{
KvpFrame fr;
fr.set({"one"}, new KvpValue{new KvpFrame});
fr.set({"one", "two"}, new KvpValue{new KvpFrame});
fr.set({"top", "two", "three"}, new KvpValue {15.0});
fr.set({"onetwo"}, new KvpValue{new KvpFrame});
fr.set({"onetwo", "three"}, new KvpValue {15.0});
fr.set({"onetwothree"}, new KvpValue {(int64_t)52});
unsigned count {};
auto counter = [] (char const *, KvpValue*, unsigned & count) { ++count; };
fr.for_each_slot_prefix("one", counter, count);
EXPECT_EQ(count, 3);
count = 0;
fr.for_each_slot_prefix("onetwo", counter, count);
EXPECT_EQ(count, 2);
count = 0;
fr.for_each_slot_prefix("onetwothree", counter, count);
EXPECT_EQ(count, 1);
count = 0;
fr.for_each_slot_prefix("two", counter, count);
EXPECT_EQ(count, 0);
}
TEST (KvpFrameTestForEachPrefix, for_each_prefix_2)
{
KvpFrame fr;
fr.set({"onetwo", "three"}, new KvpValue {15.0});
fr.set({"onethree"}, new KvpValue {(int64_t)52});
unsigned count;
fr.for_each_slot_prefix("onetwo", [](char const *, KvpValue * value, unsigned) {
EXPECT_EQ(value->get_type(), KvpValue::Type::FRAME);
}, count);
fr.for_each_slot_prefix("onetwo", [](char const *, KvpValue * value, unsigned) {
EXPECT_EQ(value->get_type(), KvpValue::Type::INT64);
}, count);
}

View File

@ -27,7 +27,6 @@ extern "C"
#include <unittest-support.h>
#include <gnc-event.h>
#include <gnc-date.h>
#include <qofinstance-p.h>
/* Add specific headers for this class */
#include "../Account.h"
#include "../AccountP.h"
@ -42,6 +41,7 @@ static const gchar *suitename = "/engine/Account";
void test_suite_account (void);
}
#include <qofinstance-p.h>
#include <kvp-frame.hpp>
typedef struct
@ -467,13 +467,7 @@ test_gnc_account_list_name_violations (Fixture *fixture, gconstpointer pData)
{
auto log_level = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
auto log_domain = "gnc.engine";
#ifdef USE_CLANG_FUNC_SIG
#define _func "GList *gnc_account_list_name_violations(QofBook *, const gchar *)"
#else
#define _func "gnc_account_list_name_violations"
#endif
auto msg = _func ": assertion 'separator != NULL' failed";
#undef _func
auto msg = ": assertion 'separator != NULL' failed";
auto check = test_error_struct_new(log_domain, log_level, msg);
GList *results, *res_iter;
auto sep = ":";
@ -482,7 +476,7 @@ test_gnc_account_list_name_violations (Fixture *fixture, gconstpointer pData)
* affect the test_log_fatal_handler
*/
GLogFunc oldlogger = g_log_set_default_handler ((GLogFunc)test_null_handler, check);
g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, check);
g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_substring_handler, check);
g_assert (gnc_account_list_name_violations (NULL, NULL) == NULL);
g_assert_cmpint (check->hits, ==, 1);
g_assert (gnc_account_list_name_violations (book, NULL) == NULL);
@ -759,19 +753,13 @@ test_xaccCloneAccount (Fixture *fixture, gconstpointer pData)
Account *clone;
QofBook *book = gnc_account_get_book (fixture->acct);
auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
#ifdef USE_CLANG_FUNC_SIG
#define _func "Account *xaccCloneAccount(const Account *, QofBook *)"
#else
#define _func "xaccCloneAccount"
#endif
auto msg1 = _func ": assertion 'GNC_IS_ACCOUNT(from)' failed";
auto msg2 = _func ": assertion 'QOF_IS_BOOK(book)' failed";
#undef _func
auto msg1 = ": assertion 'GNC_IS_ACCOUNT(from)' failed";
auto msg2 = ": assertion 'QOF_IS_BOOK(book)' failed";
auto check = test_error_struct_new("gnc.engine", loglevel, msg1);
AccountPrivate *acct_p, *clone_p;
auto oldlogger = g_log_set_default_handler ((GLogFunc)test_null_handler,
check);
g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, check);
g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_substring_handler, check);
clone = xaccCloneAccount (NULL, book);
g_assert (clone == NULL);
g_assert_cmpint (check->hits, ==, 1);
@ -1095,14 +1083,8 @@ test_gnc_account_insert_remove_split (Fixture *fixture, gconstpointer pData)
Split *split3 = xaccMallocSplit (book);
TestSignal sig1, sig2, sig3;
AccountPrivate *priv = fixture->func->get_private (fixture->acct);
#ifdef USE_CLANG_FUNC_SIG
#define _func "gboolean gnc_account_insert_split(Account *, Split *)"
#else
#define _func "gnc_account_insert_split"
#endif
auto msg1 = _func ": assertion 'GNC_IS_ACCOUNT(acc)' failed";
auto msg2 = _func ": assertion 'GNC_IS_SPLIT(s)' failed";
#undef _func
auto msg1 = ": assertion 'GNC_IS_ACCOUNT(acc)' failed";
auto msg2 = ": assertion 'GNC_IS_SPLIT(s)' failed";
auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
// auto log_domain = "gnc.engine";
auto check1 = test_error_struct_new("gnc.engine", loglevel, msg1);
@ -1116,7 +1098,7 @@ test_gnc_account_insert_remove_split (Fixture *fixture, gconstpointer pData)
test_add_error (check2);
logger = g_log_set_handler ("gnc.engine", loglevel,
(GLogFunc)test_null_handler, check3);
g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_list_handler, NULL);
g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_list_substring_handler, NULL);
/* Check that the call fails with invalid account and split (throws) */
g_assert (!gnc_account_insert_split (NULL, split1));

View File

@ -35,7 +35,6 @@ extern "C"
#include <TransactionP.h>
#include <gnc-lot.h>
#include <gnc-event.h>
#include <qofinstance-p.h>
#if defined(__clang__) && (__clang_major__ == 5 || (__clang_major__ == 3 && __clang_minor__ < 5))
#define USE_CLANG_FUNC_SIG 1
@ -45,6 +44,7 @@ static const gchar *suitename = "/engine/Split";
void test_suite_split ( void );
}
#include <qofinstance-p.h>
#include <kvp-frame.hpp>
typedef struct
@ -735,12 +735,12 @@ test_xaccSplitDetermineGainStatus (Fixture *fixture, gconstpointer pData)
fixture->split->gains = GAINS_STATUS_UNKNOWN;
fixture->split->gains_split = NULL;
g_assert (fixture->split->inst.kvp_data->get_slot("gains_source") == NULL);
g_assert (fixture->split->inst.kvp_data->get_slot({"gains_source"}) == NULL);
xaccSplitDetermineGainStatus (fixture->split);
g_assert (fixture->split->gains_split == NULL);
g_assert_cmpint (fixture->split->gains, ==, GAINS_STATUS_A_VDIRTY | GAINS_STATUS_DATE_DIRTY);
fixture->split->inst.kvp_data->set("gains-source", new KvpValue(const_cast<GncGUID*>(guid_copy(g_guid))));
fixture->split->inst.kvp_data->set({"gains-source"}, new KvpValue(guid_copy(g_guid)));
g_assert (fixture->split->gains_split == NULL);
fixture->split->gains = GAINS_STATUS_UNKNOWN;
xaccSplitDetermineGainStatus (fixture->split);
@ -1797,7 +1797,7 @@ test_xaccSplitGetOtherSplit (Fixture *fixture, gconstpointer pData)
g_assert (xaccSplitGetOtherSplit (split1) == NULL);
g_assert (xaccTransUseTradingAccounts (txn) == FALSE);
g_assert (split->inst.kvp_data->get_slot("lot-split") == NULL);
g_assert (split->inst.kvp_data->get_slot({"lot-split"}) == NULL);
g_assert_cmpint (xaccTransCountSplits (txn), !=, 2);
g_assert (xaccSplitGetOtherSplit (split) == NULL);
@ -1808,18 +1808,18 @@ test_xaccSplitGetOtherSplit (Fixture *fixture, gconstpointer pData)
xaccSplitSetParent (split2, txn);
g_assert (xaccSplitGetOtherSplit (split) == NULL);
split->inst.kvp_data->set("lot-split", kvpnow);
g_assert (split->inst.kvp_data->get_slot("lot-split"));
split->inst.kvp_data->set({"lot-split"}, kvpnow);
g_assert (split->inst.kvp_data->get_slot({"lot-split"}));
g_assert (xaccSplitGetOtherSplit (split) == NULL);
split1->inst.kvp_data->set("lot-split", kvpnow);
g_assert (split1->inst.kvp_data->get_slot("lot-split"));
split1->inst.kvp_data->set({"lot-split"}, kvpnow);
g_assert (split1->inst.kvp_data->get_slot({"lot-split"}));
g_assert (xaccSplitGetOtherSplit (split) == split2);
split->inst.kvp_data->set("lot-split", NULL);
g_assert (split->inst.kvp_data->get_slot("lot-split") == NULL);
split1->inst.kvp_data->set("lot-split", NULL);
g_assert (split1->inst.kvp_data->get_slot("lot-split") == NULL);
split->inst.kvp_data->set({"lot-split"}, NULL);
g_assert (split->inst.kvp_data->get_slot({"lot-split"}) == NULL);
split1->inst.kvp_data->set({"lot-split"}, NULL);
g_assert (split1->inst.kvp_data->get_slot({"lot-split"}) == NULL);
qof_book_begin_edit (book);
qof_instance_set (QOF_INSTANCE (book),
"trading-accts", "t",

View File

@ -153,8 +153,8 @@ setup (Fixture *fixture, gconstpointer pData)
xaccTransSetCurrency (txn, fixture->curr);
xaccSplitSetParent (split1, txn);
xaccSplitSetParent (split2, txn);
frame->set(trans_notes_str, new KvpValue("Salt pork sausage"));
frame->set_path("/qux/quux/corge", new KvpValue(123.456));
frame->set({trans_notes_str}, new KvpValue("Salt pork sausage"));
frame->set_path({"qux", "quux", "corge"}, new KvpValue(123.456));
qof_instance_set_slots (QOF_INSTANCE (txn), frame);
}
xaccTransCommitEdit (txn);
@ -562,7 +562,7 @@ test_dupe_trans (Fixture *fixture, gconstpointer pData)
oldtxn->date_posted = posted;
oldtxn->date_entered = entered;
oldtxn->inst.kvp_data->set("/foo/bar/baz",
oldtxn->inst.kvp_data->set({"foo", "bar", "baz"},
new KvpValue("The Great Waldo Pepper"));
newtxn = fixture->func->dupe_trans (oldtxn);
@ -881,11 +881,11 @@ test_xaccTransEqual (Fixture *fixture, gconstpointer pData)
g_free(clone->description);
clone->description = static_cast<char*>(CACHE_INSERT ("Waldo Pepper"));
auto frame = qof_instance_get_slots (QOF_INSTANCE (clone));
frame->set("/qux/quux/corge", new KvpValue(654.321));
frame->set({"qux", "quux", "corge"}, new KvpValue(654.321));
xaccTransCommitEdit (clone);
g_free (cleanup->msg);
g_free (check->msg);
check->msg = g_strdup ("[xaccTransEqual] kvp frames differ:\n{\n notes => KVP_VALUE_STRING(Salt pork sausage),\n qux => KVP_VALUE_FRAME({\n quux => KVP_VALUE_FRAME({\n corge => KVP_VALUE_DOUBLE(654.321),\n}\n),\n}\n),\n}\n\n\nvs\n\n{\n notes => KVP_VALUE_STRING(Salt pork sausage),\n qux => KVP_VALUE_FRAME({\n quux => KVP_VALUE_FRAME({\n corge => KVP_VALUE_DOUBLE(123.456),\n}\n),\n}\n),\n}\n");
check->msg = g_strdup ("[xaccTransEqual] kvp frames differ:\nnotes/Salt pork sausage (char *)\nqux/quux/corge/654.321 (double)\n\n\n\n\nvs\n\nnotes/Salt pork sausage (char *)\nqux/quux/corge/123.456 (double)\n\n\n");
g_assert (!xaccTransEqual (clone, txn0, TRUE, FALSE, TRUE, TRUE));
@ -893,7 +893,7 @@ test_xaccTransEqual (Fixture *fixture, gconstpointer pData)
xaccTransBeginEdit (clone);
cleanup->msg = g_strdup_printf (cleanup_fmt, clone->orig);
clone->description = static_cast<char*>(CACHE_INSERT ("Waldo Pepper"));
frame->set("/qux/quux/corge", new KvpValue(123.456));
frame->set({"qux", "quux", "corge"}, new KvpValue(123.456));
xaccTransCommitEdit (clone);
g_free (cleanup->msg);
g_free (check->msg);
@ -1858,22 +1858,22 @@ test_xaccTransVoid (Fixture *fixture, gconstpointer pData)
/* Actual function variables start here. */
auto frame = fixture->txn->inst.kvp_data;
auto void_reason = "Voided for Unit Test";
auto txn_notes = g_strdup (frame->get_slot(trans_notes_str)->get<const char*>());
auto txn_notes = g_strdup (frame->get_slot({trans_notes_str})->get<const char*>());
Timespec now = timespec_now ();
char iso8601_str[ISO_DATELENGTH + 1] = "";
GList *split = NULL;
xaccTransVoid (fixture->txn, void_reason);
g_assert_cmpstr (frame->get_slot(trans_notes_str)->get<const char*>(), ==,
g_assert_cmpstr (frame->get_slot({trans_notes_str})->get<const char*>(), ==,
"Voided transaction");
g_assert_cmpstr (frame->get_slot(void_former_notes_str)->get<const char*>(),
g_assert_cmpstr (frame->get_slot({void_former_notes_str})->get<const char*>(),
==, txn_notes);
g_assert_cmpstr (frame->get_slot(void_reason_str)->get<const char*>(), ==,
g_assert_cmpstr (frame->get_slot({void_reason_str})->get<const char*>(), ==,
void_reason);
gnc_timespec_to_iso8601_buff (now, iso8601_str);
g_assert_cmpstr (frame->get_slot(void_time_str)->get<const char*>(), ==,
g_assert_cmpstr (frame->get_slot({void_time_str})->get<const char*>(), ==,
iso8601_str);
g_assert_cmpstr (frame->get_slot(TRANS_READ_ONLY_REASON)->get<const char*>(),
g_assert_cmpstr (frame->get_slot({TRANS_READ_ONLY_REASON})->get<const char*>(),
==, "Transaction Voided");
for (split = fixture->txn->splits; split; split=g_list_next (split))
{
@ -1883,12 +1883,12 @@ test_xaccTransVoid (Fixture *fixture, gconstpointer pData)
xaccTransUnvoid (fixture->txn);
g_assert_cmpstr (frame->get_slot(trans_notes_str)->get<const char*>(), ==,
g_assert_cmpstr (frame->get_slot({trans_notes_str})->get<const char*>(), ==,
txn_notes);
g_assert (frame->get_slot(void_former_notes_str) == NULL);
g_assert (frame->get_slot(void_reason_str) == NULL);
g_assert (frame->get_slot(void_time_str) == NULL);
g_assert (frame->get_slot(TRANS_READ_ONLY_REASON) == NULL);
g_assert (frame->get_slot({void_former_notes_str}) == NULL);
g_assert (frame->get_slot({void_reason_str}) == NULL);
g_assert (frame->get_slot({void_time_str}) == NULL);
g_assert (frame->get_slot({TRANS_READ_ONLY_REASON}) == NULL);
for (split = fixture->txn->splits; split; split=g_list_next (split))
{
g_assert (!gnc_numeric_zero_p (((Split*)(split->data))->value));
@ -1909,7 +1909,7 @@ test_xaccTransReverse (Fixture *fixture, gconstpointer pData)
auto frame = fixture->txn->inst.kvp_data;
GList *orig_splits = NULL, *rev_splits = NULL;
g_assert (guid_equal (frame->get_slot(TRANS_REVERSED_BY)->get<GncGUID*>(),
g_assert (guid_equal (frame->get_slot({TRANS_REVERSED_BY})->get<GncGUID*>(),
xaccTransGetGUID (rev)));
g_assert (!qof_instance_is_dirty (QOF_INSTANCE (rev))); //Cleared by commit

View File

@ -608,7 +608,7 @@ libgnucash/core-utils/gnc-locale-utils.c
libgnucash/core-utils/gnc-path.c
libgnucash/core-utils/gnc-prefs.c
libgnucash/doc/doxygen_main_page.c
libgnucash/engine/Account.c
libgnucash/engine/Account.cpp
libgnucash/engine/business-core.scm
libgnucash/engine/cap-gains.c
libgnucash/engine/cashobjects.c