diff --git a/libgnucash/engine/kvp-frame.cpp b/libgnucash/engine/kvp-frame.cpp index 06101352d0..13a0e4e604 100644 --- a/libgnucash/engine/kvp-frame.cpp +++ b/libgnucash/engine/kvp-frame.cpp @@ -181,23 +181,30 @@ KvpFrameImpl::set_path(Path path, KvpValue* value) noexcept 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(); } diff --git a/libgnucash/engine/kvp-frame.hpp b/libgnucash/engine/kvp-frame.hpp index e5308ec208..1af4217bf5 100644 --- a/libgnucash/engine/kvp-frame.hpp +++ b/libgnucash/engine/kvp-frame.hpp @@ -187,6 +187,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 & prefix) const noexcept; /** * Report the keys in the immediate frame. Be sensible about using this, it * isn't a very efficient way to iterate. diff --git a/libgnucash/engine/kvp-value.cpp b/libgnucash/engine/kvp-value.cpp index 55e0e6e08f..a0329d2112 100644 --- a/libgnucash/engine/kvp-value.cpp +++ b/libgnucash/engine/kvp-value.cpp @@ -125,34 +125,32 @@ struct to_string_visitor : boost::static_visitor 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(val->data); output << ' ' << realvalue->to_string() << ','; } - output << " ]"; output << ")"; } @@ -161,53 +159,66 @@ struct to_string_visitor : boost::static_visitor { 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 << " (timespec)"; } 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()->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 diff --git a/libgnucash/engine/kvp-value.hpp b/libgnucash/engine/kvp-value.hpp index 003ee7d702..78a8eb7fa7 100644 --- a/libgnucash/engine/kvp-value.hpp +++ b/libgnucash/engine/kvp-value.hpp @@ -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 T get() const noexcept; diff --git a/libgnucash/engine/test/utest-Transaction.cpp b/libgnucash/engine/test/utest-Transaction.cpp index dde0a48582..a95a5acaff 100644 --- a/libgnucash/engine/test/utest-Transaction.cpp +++ b/libgnucash/engine/test/utest-Transaction.cpp @@ -885,7 +885,7 @@ test_xaccTransEqual (Fixture *fixture, gconstpointer pData) 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));