35 #include "kvp-value.hpp" 36 #include "kvp-frame.hpp" 44 static QofLogModule log_module =
"qof.kvp";
46 static const char delim =
'/';
50 std::for_each(rhs.m_valuemap.begin(), rhs.m_valuemap.end(),
51 [
this](
const map_type::value_type & a)
55 this->m_valuemap.insert({key,val});
62 std::for_each(m_valuemap.begin(), m_valuemap.end(),
63 [](
const map_type::value_type &a){
72 KvpFrame::get_child_frame_or_nullptr (Path
const & path) noexcept
76 auto key = path.front ();
77 auto map_iter = m_valuemap.find (key.c_str ());
78 if (map_iter == m_valuemap.end ())
80 auto child = map_iter->second->get <KvpFrame *> ();
84 std::copy (path.begin () + 1, path.end (), std::back_inserter (send));
85 return child->get_child_frame_or_nullptr (send);
89 KvpFrame::get_child_frame_or_create (Path
const & path) noexcept
93 auto key = path.front ();
94 auto spot = m_valuemap.find (key.c_str ());
95 if (spot == m_valuemap.end () || spot->second->get_type () != KvpValue::Type::FRAME)
96 delete set_impl (key.c_str (),
new KvpValue {
new KvpFrame});
98 std::copy (path.begin () + 1, path.end (), std::back_inserter (send));
99 auto child_val = m_valuemap.at (key.c_str ());
100 auto child = child_val->get <KvpFrame *> ();
101 return child->get_child_frame_or_create (send);
106 KvpFrame::set_impl (std::string
const & key, KvpValue * value) noexcept
109 auto spot = m_valuemap.find (key.c_str ());
110 if (spot != m_valuemap.end ())
114 m_valuemap.erase (spot);
119 m_valuemap.emplace (cachedkey, value);
129 auto key = path.back ();
131 auto target = get_child_frame_or_nullptr (path);
134 return target->set_impl (key, value);
140 auto key = path.back();
142 auto target = get_child_frame_or_create (path);
145 return target->set_impl (key, value);
151 auto key = path.back();
153 auto target = get_child_frame_or_nullptr (path);
156 auto spot = target->m_valuemap.find (key.c_str ());
157 if (spot != target->m_valuemap.end ())
171 if (!m_valuemap.size())
173 std::ostringstream ret;
174 std::for_each(m_valuemap.begin(), m_valuemap.end(),
175 [
this,&ret,&prefix](
const map_type::value_type &a)
177 std::string new_prefix {prefix};
180 new_prefix += a.first;
184 ret << a.second->to_string(new_prefix) <<
"\n";
186 ret << new_prefix <<
"(null)\n";
192 std::vector<std::string>
195 std::vector<std::string> ret;
196 ret.reserve (m_valuemap.size());
197 std::for_each(m_valuemap.begin(), m_valuemap.end(),
198 [&ret](
const KvpFrameImpl::map_type::value_type &a)
200 ret.push_back(a.first);
208 if (one && !two)
return 1;
209 if (!one && two)
return -1;
210 if (!one && !two)
return 0;
223 for (
const auto & a : one.m_valuemap)
225 auto otherspot = two.m_valuemap.find(a.first);
226 if (otherspot == two.m_valuemap.end())
230 auto comparison =
compare(a.second,otherspot->second);
236 if (one.m_valuemap.size() < two.m_valuemap.size())
242 kvp_value_list_from_gvalue (GValue *gval, gpointer pList)
244 GList **kvplist = (GList**)pList;
246 if (!(gval && G_VALUE_TYPE (gval)))
249 *kvplist = g_list_prepend (*kvplist, kvp);
255 if (kval == NULL)
return NULL;
257 val = g_slice_new0 (GValue);
261 switch (kval->get_type())
263 case KvpValue::Type::INT64:
264 g_value_init (val, G_TYPE_INT64);
265 g_value_set_int64 (val, kval->get<int64_t>());
267 case KvpValue::Type::DOUBLE:
268 g_value_init (val, G_TYPE_DOUBLE);
269 g_value_set_double (val, kval->get<
double>());
271 case KvpValue::Type::NUMERIC:
272 g_value_init (val, GNC_TYPE_NUMERIC);
273 g_value_set_static_boxed (val, kval->get_ptr<gnc_numeric>());
275 case KvpValue::Type::STRING:
276 g_value_init (val, G_TYPE_STRING);
277 g_value_set_static_string (val, kval->get<
const char*>());
279 case KvpValue::Type::GUID:
280 g_value_init (val, GNC_TYPE_GUID);
281 g_value_set_static_boxed (val, kval->get<
GncGUID*>());
283 case KvpValue::Type::TIME64:
284 g_value_init (val, GNC_TYPE_TIME64);
285 g_value_set_boxed (val, kval->get_ptr<
Time64>());
287 case KvpValue::Type::GDATE:
288 g_value_init (val, G_TYPE_DATE);
289 g_value_set_static_boxed (val, kval->get_ptr<GDate>());
291 case KvpValue::Type::GLIST:
293 g_value_init (val, GNC_TYPE_VALUE_LIST);
294 g_value_set_static_boxed (val, kval->get<GList*>());
298 case KvpValue::Type::FRAME:
299 PWARN (
"Error! Attempt to transfer KvpFrame!");
301 PWARN (
"Error! Invalid KVP Transfer Request!");
302 g_slice_free (GValue, val);
312 KvpValue *val = NULL;
316 type = G_VALUE_TYPE (gval);
317 g_return_val_if_fail (G_VALUE_TYPE (gval), NULL);
319 if (type == G_TYPE_INT64)
320 val =
new KvpValue(g_value_get_int64 (gval));
321 else if (type == G_TYPE_DOUBLE)
322 val =
new KvpValue(g_value_get_double (gval));
323 else if (type == G_TYPE_BOOLEAN)
325 auto bval = g_value_get_boolean(gval);
327 val =
new KvpValue(g_strdup(
"true"));
329 else if (type == GNC_TYPE_NUMERIC)
330 val =
new KvpValue(*(gnc_numeric*)g_value_get_boxed (gval));
331 else if (type == G_TYPE_STRING)
333 auto string = g_value_get_string(gval);
334 if (
string !=
nullptr)
335 val =
new KvpValue(g_strdup(
string));
337 else if (type == GNC_TYPE_GUID)
339 auto boxed = g_value_get_boxed(gval);
340 if (boxed !=
nullptr)
341 val =
new KvpValue(
guid_copy(static_cast<GncGUID*>(boxed)));
343 else if (type == GNC_TYPE_TIME64)
344 val =
new KvpValue(*(
Time64*)g_value_get_boxed (gval));
345 else if (type == G_TYPE_DATE)
346 val =
new KvpValue(*(GDate*)g_value_get_boxed (gval));
347 else if (type == GNC_TYPE_VALUE_LIST)
349 GList *gvalue_list = (GList*)g_value_get_boxed (gval);
350 GList *kvp_list = NULL;
351 g_list_foreach (gvalue_list, (GFunc)kvp_value_list_from_gvalue,
353 kvp_list = g_list_reverse (kvp_list);
354 val =
new KvpValue(kvp_list);
359 PWARN (
"Error! Don't know how to make a KvpValue from a %s",
360 G_VALUE_TYPE_NAME (gval));
366 gnc_gvalue_copy (GValue *src, gpointer uData)
368 GList **new_list = (GList**)uData;
369 GValue *dest = g_value_init (g_slice_new0 (GValue), G_VALUE_TYPE (src));
370 g_value_copy (src, dest);
371 *new_list = g_list_prepend(*new_list, dest);
377 if (val == NULL || ! G_IS_VALUE (val))
return;
379 g_slice_free (GValue, val);
383 gnc_value_list_copy (GList *list)
385 GList *new_list = NULL;
386 g_list_foreach (list, (GFunc)gnc_gvalue_copy, &new_list);
387 new_list = g_list_reverse (new_list);
392 gnc_value_list_free (GList *list)
398 gnc_value_list_get_type (
void)
400 static GType type = 0;
403 type = g_boxed_type_register_static (
"gnc_value_list",
404 (GBoxedCopyFunc)gnc_value_list_copy,
405 (GBoxedFreeFunc)gnc_value_list_free);
411 KvpFrame::flatten_kvp_impl(std::vector <std::string> path, std::vector <KvpEntry> & entries)
const noexcept
413 for (
auto const & entry : m_valuemap)
415 std::vector<std::string> new_path {path};
416 new_path.push_back(
"/");
417 if (entry.second->get_type() == KvpValue::Type::FRAME)
419 new_path.push_back(entry.first);
420 entry.second->get<KvpFrame*>()->flatten_kvp_impl(new_path, entries);
424 new_path.emplace_back (entry.first);
425 entries.emplace_back (new_path, entry.second);
430 std::vector <KvpEntry>
431 KvpFrame::flatten_kvp(
void)
const noexcept
433 std::vector <KvpEntry> ret;
434 flatten_kvp_impl({}, ret);
~KvpFrameImpl() noexcept
Perform a deep delete.
GncGUID * guid_copy(const GncGUID *guid)
Returns a newly allocated GncGUID that matches the passed-in GUID.
std::string to_string() const noexcept
Make a string representation of the frame.
KvpValue * kvp_value_from_gvalue(const GValue *gval)
Convert a gvalue into a kvpvalue.
KvpValue * set(Path path, KvpValue *newvalue) noexcept
Set the value with the key in the immediate frame, replacing and returning the old value if it exists...
const char * qof_string_cache_insert(const char *key)
You can use this function with g_hash_table_insert(), for the key (or value), as long as you use the ...
#define PWARN(format, args...)
Log a warning.
void gnc_gvalue_free(GValue *value)
Convenience function to release the value in a GValue acquired by kvp_frame_get_gvalue and to free th...
int compare(const KvpFrameImpl &one, const KvpFrameImpl &two) noexcept
If the first KvpFrameImpl has an item that the second does not, 1 is returned.
std::vector< std::string > get_keys() const noexcept
Report the keys in the immediate frame.
Implements KvpValue using boost::variant.
KvpValue * get_slot(Path keys) noexcept
Get the value for the tail of the path or nullptr if it doesn't exist.
GValue * gvalue_from_kvp_value(const KvpValue *kval, GValue *val)
Convert a kvp_value into a GValue.
KvpValue * set_path(Path path, KvpValue *newvalue) noexcept
Set the value with the key in a subframe following the keys in path, replacing and returning the old ...
The type used to store guids in C.
void qof_string_cache_remove(const char *key)
You can use this function as a destroy notifier for a GHashTable that uses common strings as keys (or...