GnuCash  3.0-75-g4a4e7a9
Data Structures | Typedefs | Functions | Friends
KVP: Key-Value Pairs

A KvpFrame is a set of associations between character strings (keys) and KvpValues. More...

Data Structures

struct  KvpFrameImpl
 Implements KvpFrame. More...
 
class  KvpFrameImpl::cstring_comparer
 
struct  KvpValue
 Implements KvpValue using boost::variant. More...
 

Typedefs

using Path = std::vector< std::string >
 
using KvpEntry = std::pair< std::vector< std::string >, KvpValue * >
 
using KvpFrameImpl::map_type = std::map< const char *, KvpValue *, cstring_comparer >
 

Functions

bool KvpFrameImpl::cstring_comparer::operator() (const char *one, const char *two) const
 
 KvpFrameImpl::KvpFrameImpl (const KvpFrameImpl &) noexcept
 Performs a deep copy.
 
 KvpFrameImpl::~KvpFrameImpl () noexcept
 Perform a deep delete.
 
KvpValue * KvpFrameImpl::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 or nullptr if it doesn't. More...
 
KvpValue * KvpFrameImpl::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 value if it exists or nullptr if it doesn't. More...
 
std::string KvpFrameImpl::to_string () const noexcept
 Make a string representation of the frame. More...
 
std::string KvpFrameImpl::to_string (std::string const &) const noexcept
 Make a string representation of the frame with the specified string prefixed to every item in the frame. More...
 
std::vector< std::string > KvpFrameImpl::get_keys () const noexcept
 Report the keys in the immediate frame. More...
 
KvpValue * KvpFrameImpl::get_slot (Path keys) noexcept
 Get the value for the tail of the path or nullptr if it doesn't exist. More...
 
template<typename func_type , typename data_type >
void KvpFrameImpl::for_each_slot_temp (func_type const &, data_type &) const noexcept
 The function should be of the form: <anything> func (char const *, KvpValue *, data_type &); Do not pass nullptr as the function.
 
template<typename func_type >
void KvpFrameImpl::for_each_slot_temp (func_type const &) const noexcept
 
template<typename func_type , typename data_type >
void KvpFrameImpl::for_each_slot_prefix (std::string const &prefix, func_type const &, data_type &) const noexcept
 Like for_each_slot, but doesn't traverse nested values. More...
 
template<typename func_type >
void KvpFrameImpl::for_each_slot_prefix (std::string const &prefix, func_type const &) const noexcept
 
std::vector< KvpEntry > KvpFrameImpl::flatten_kvp (void) const noexcept
 Returns all keys and values of this frame recursively, flattening the frame-containing values.
 
bool KvpFrameImpl::empty () const noexcept
 Test for emptiness. More...
 
int compare (const KvpValueImpl *, const KvpValue *) noexcept
 

Friends

int KvpFrameImpl::compare (const KvpFrameImpl &, const KvpFrameImpl &) noexcept
 If the first KvpFrameImpl has an item that the second does not, 1 is returned. More...
 
int compare (const KvpFrameImpl &, const KvpFrameImpl &) noexcept
 If the first KvpFrameImpl has an item that the second does not, 1 is returned. More...
 
int compare (const KvpFrameImpl *, const KvpFrameImpl *) noexcept
 
GValue * gvalue_from_kvp_value (const KvpValue *kval)
 Convert a kvp_value into a GValue. More...
 
KvpValue * kvp_value_from_gvalue (const GValue *gval)
 Convert a gvalue into a kvpvalue. More...
 
void gnc_gvalue_free (GValue *value)
 Convenience function to release the value in a GValue acquired by kvp_frame_get_gvalue and to free the GValue. More...
 
void qof_book_load_options (QofBook *book, GNCOptionLoad load_cb, GNCOptionDB *odb)
 Load a GNCOptionsDB from KVP data. More...
 
void qof_book_save_options (QofBook *book, GNCOptionSave save_cb, GNCOptionDB *odb, gboolean clear)
 Save a GNCOptionsDB back to the book's KVP. More...
 
void qof_book_set_option (QofBook *book, KvpValue *value, GSList *path)
 Save a single option value. More...
 
KvpValue * qof_book_get_option (QofBook *book, GSList *path)
 Read a single option value. More...
 
void qof_book_options_delete (QofBook *book, GSList *path)
 Delete the options. More...
 
gboolean qof_instance_has_kvp (QofInstance *inst)
 Report whether a QofInstance has anything stored in KVP. More...
 
void qof_instance_set_kvp (QofInstance *, GValue const *value, unsigned count,...)
 Sets a KVP slot to a value from a GValue. More...
 
void qof_instance_get_kvp (QofInstance *, GValue *value, unsigned count,...)
 Retrieves the contents of a KVP slot into a provided GValue. More...
 

Detailed Description

A KvpFrame is a set of associations between character strings (keys) and KvpValues.

A KvpValue is notionally a union with possible types enumerated in the KvpValue::Type enum, and includes, among other things, ints, doubles, strings, guids, lists, time and numeric values. KvpValues may also be other frames, so KVP is inherently hierarchical.

Values are stored in a 'slot' associated with a key. Pointers passed as arguments into set_slot and get_slot are the responsibility of the caller. Pointers returned by get_slot are owned by the kvp_frame. Make copies as needed.

A 'path' is a sequence of keys that can be followed to a value. Paths are passed as either '/'-delimited strings or as std::vectors of keys. Unlike file system paths, the tokens '.' and '..' have no special meaning.

KVP is an implementation detail whose direct use should be avoided; create an abstraction object in libqof to keep KVP encapsulated here and ensure that KVP modifications are written to the database. Two generic abstractions are provided:

KVP Values used By GnuCash provides a catolog of KVP entries including what objects they're part of and how they're used.

Purpose

KVP is used to extend the class structure without directly reflecting the extension in the database or xML schema. The backend will directly load and store KVP slots without any checking, which allows older versions of GnuCash to load the database without complaint and without damaging the KVP data that they don't understand.

When a feature is entirely implemented in KVP and doesn't affect the meaning of the books or other features, this isn't a problem, but when it's not true then it should be registered in Features so that older versions of GnuCash will refuse to load the database.

Policy

Function Documentation

◆ compare()

int compare ( const KvpFrameImpl one,
const KvpFrameImpl two 
)
noexcept

If the first KvpFrameImpl has an item that the second does not, 1 is returned.

The first item within the two KvpFrameImpl that is not similar, that comparison is returned. If all the items within the first KvpFrameImpl match items within the second, but the second has more elements, -1 is returned. Otherwise, 0 is returned.

Definition at line 217 of file kvp-frame.cpp.

218 {
219  for (const auto & a : one.m_valuemap)
220  {
221  auto otherspot = two.m_valuemap.find(a.first);
222  if (otherspot == two.m_valuemap.end())
223  {
224  return 1;
225  }
226  auto comparison = compare(a.second,otherspot->second);
227 
228  if (comparison != 0)
229  return comparison;
230  }
231 
232  if (one.m_valuemap.size() < two.m_valuemap.size())
233  return -1;
234  return 0;
235 }
int compare(const KvpFrameImpl &one, const KvpFrameImpl &two) noexcept
If the first KvpFrameImpl has an item that the second does not, 1 is returned.
Definition: kvp-frame.cpp:217

◆ empty()

bool KvpFrameImpl::empty ( ) const
inlinenoexcept

Test for emptiness.

Returns
true if the frame contains nothing.

Definition at line 226 of file kvp-frame.hpp.

226 { return m_valuemap.empty(); }

◆ for_each_slot_prefix()

template<typename func_type , typename data_type >
void KvpFrameImpl::for_each_slot_prefix ( std::string const &  prefix,
func_type const &  ,
data_type &   
) 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.

◆ get_keys()

std::vector< std::string > KvpFrameImpl::get_keys ( ) const
noexcept

Report the keys in the immediate frame.

Be sensible about using this, it isn't a very efficient way to iterate.

Returns
std::vector of keys as std::strings.

Definition at line 190 of file kvp-frame.cpp.

191 {
192  std::vector<std::string> ret;
193  std::for_each(m_valuemap.begin(), m_valuemap.end(),
194  [&ret](const KvpFrameImpl::map_type::value_type &a)
195  {
196  ret.push_back(a.first);
197  }
198  );
199  return ret;
200 }

◆ get_slot()

KvpValue * KvpFrameImpl::get_slot ( Path  keys)
noexcept

Get the value for the tail of the path or nullptr if it doesn't exist.

Parameters
pathPath of keys leading to the desired value.
Returns
The value at the key or nullptr.

Definition at line 146 of file kvp-frame.cpp.

147 {
148  auto key = path.back();
149  path.pop_back();
150  auto target = get_child_frame_or_nullptr (path);
151  if (!target)
152  return nullptr;
153  auto spot = target->m_valuemap.find (key.c_str ());
154  if (spot != target->m_valuemap.end ())
155  return spot->second;
156  return nullptr;
157 }

◆ gnc_gvalue_free()

void gnc_gvalue_free ( GValue *  value)

Convenience function to release the value in a GValue acquired by kvp_frame_get_gvalue and to free the GValue.

Parameters
valueA GValue* created by kvp_frame_get_gvalue

Definition at line 392 of file kvp-frame.cpp.

393 {
394  if (val == NULL || ! G_IS_VALUE (val)) return;
395  g_value_unset (val);
396  g_slice_free (GValue, val);
397 }

◆ gvalue_from_kvp_value()

GValue* gvalue_from_kvp_value ( const KvpValue *  kval)

Convert a kvp_value into a GValue.

Frames aren't converted.

Parameters
kvalA KvpValue.
Returns
GValue*. Must be freed with g_free().

Definition at line 260 of file kvp-frame.cpp.

261 {
262  GValue *val;
263  gnc_numeric num;
264  Timespec tm;
265  GDate gdate;
266 
267  if (kval == NULL) return NULL;
268  val = g_slice_new0 (GValue);
269 
270  switch (kval->get_type())
271  {
272  case KvpValue::Type::INT64:
273  g_value_init (val, G_TYPE_INT64);
274  g_value_set_int64 (val, kval->get<int64_t>());
275  break;
276  case KvpValue::Type::DOUBLE:
277  g_value_init (val, G_TYPE_DOUBLE);
278  g_value_set_double (val, kval->get<double>());
279  break;
280  case KvpValue::Type::NUMERIC:
281  g_value_init (val, GNC_TYPE_NUMERIC);
282  num = kval->get<gnc_numeric>();
283  g_value_set_boxed (val, &num);
284  break;
285  case KvpValue::Type::STRING:
286  g_value_init (val, G_TYPE_STRING);
287  g_value_set_string (val, kval->get<const char*>());
288  break;
289  case KvpValue::Type::GUID:
290  g_value_init (val, GNC_TYPE_GUID);
291  g_value_set_boxed (val, kval->get<GncGUID*>());
292  break;
293  case KvpValue::Type::TIMESPEC:
294  g_value_init (val, GNC_TYPE_TIMESPEC);
295  tm = kval->get<Timespec>();
296  g_value_set_boxed (val, &tm);
297  break;
298  case KvpValue::Type::GDATE:
299  g_value_init (val, G_TYPE_DATE);
300  gdate = kval->get<GDate>();
301  g_value_set_boxed (val, &gdate);
302  break;
303  case KvpValue::Type::GLIST:
304  {
305  GList *gvalue_list = NULL;
306  GList *kvp_list = kval->get<GList*>();
307  g_list_foreach (kvp_list, (GFunc)gvalue_list_from_kvp_value,
308  &gvalue_list);
309  g_value_init (val, GNC_TYPE_VALUE_LIST);
310  gvalue_list = g_list_reverse (gvalue_list);
311  g_value_set_boxed (val, gvalue_list);
312  break;
313  }
314 /* No transfer of KVP frames outside of QofInstance-derived classes! */
315  case KvpValue::Type::FRAME:
316  PWARN ("Error! Attempt to transfer KvpFrame!");
317  default:
318  PWARN ("Error! Invalid KVP Transfer Request!");
319  g_slice_free (GValue, val);
320  val = NULL;
321  break;
322  }
323  return val;
324 }
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:248
The type used to store guids in C.
Definition: guid.h:75

◆ kvp_value_from_gvalue()

KvpValue* kvp_value_from_gvalue ( const GValue *  gval)

Convert a gvalue into a kvpvalue.

Parameters
gvalA GValue of a type KvpValue can digest.
Returns
KvpValue created from the GValue's contents.

Definition at line 327 of file kvp-frame.cpp.

328 {
329  KvpValue *val = NULL;
330  GType type;
331  if (gval == NULL)
332  return NULL;
333  type = G_VALUE_TYPE (gval);
334  g_return_val_if_fail (G_VALUE_TYPE (gval), NULL);
335 
336  if (type == G_TYPE_INT64)
337  val = new KvpValue(g_value_get_int64 (gval));
338  else if (type == G_TYPE_DOUBLE)
339  val = new KvpValue(g_value_get_double (gval));
340  else if (type == G_TYPE_BOOLEAN)
341  {
342  auto bval = g_value_get_boolean(gval);
343  if (bval)
344  val = new KvpValue(g_strdup("true"));
345  }
346  else if (type == GNC_TYPE_NUMERIC)
347  val = new KvpValue(*(gnc_numeric*)g_value_get_boxed (gval));
348  else if (type == G_TYPE_STRING)
349  {
350  auto string = g_value_get_string(gval);
351  if (string != nullptr)
352  val = new KvpValue(g_strdup(string));
353  }
354  else if (type == GNC_TYPE_GUID)
355  {
356  auto boxed = g_value_get_boxed(gval);
357  if (boxed != nullptr)
358  val = new KvpValue(guid_copy(static_cast<GncGUID*>(boxed)));
359  }
360  else if (type == GNC_TYPE_TIMESPEC)
361  val = new KvpValue(*(Timespec*)g_value_get_boxed (gval));
362  else if (type == G_TYPE_DATE)
363  val = new KvpValue(*(GDate*)g_value_get_boxed (gval));
364  else if (type == GNC_TYPE_VALUE_LIST)
365  {
366  GList *gvalue_list = (GList*)g_value_get_boxed (gval);
367  GList *kvp_list = NULL;
368  g_list_foreach (gvalue_list, (GFunc)kvp_value_list_from_gvalue,
369  &kvp_list);
370  kvp_list = g_list_reverse (kvp_list);
371  val = new KvpValue(kvp_list);
372 // g_list_free_full (gvalue_list, (GDestroyNotify)g_value_unset);
373 // gvalue_list = NULL;
374  }
375  else
376  PWARN ("Error! Don't know how to make a KvpValue from a %s",
377  G_VALUE_TYPE_NAME (gval));
378 
379  return val;
380 }
GncGUID * guid_copy(const GncGUID *guid)
Returns a newly allocated GncGUID that matches the passed-in GUID.
Definition: guid.cpp:121
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:248

◆ qof_book_get_option()

KvpValue* qof_book_get_option ( QofBook *  book,
GSList *  path 
)

Read a single option value.

Used from Scheme, the KvpValue<–>SCM translation is handled by the functions in kvp-scm.c and automated by SWIG. The starting element is set as KVP_OPTION_PATH in qofbookslots.h.

Parameters
bookThe book.
pathA GSList of keys which form a path under KVP_OPTION_PATH.

Definition at line 1188 of file qofbook.cpp.

1189 {
1190  KvpFrame *root = qof_instance_get_slots(QOF_INSTANCE (book));
1191  return root->get_slot(gslist_to_option_path(path));
1192 }

◆ qof_book_load_options()

void qof_book_load_options ( QofBook *  book,
GNCOptionLoad  load_cb,
GNCOptionDB *  odb 
)

Load a GNCOptionsDB from KVP data.

Parameters
bookThe book.
load_cbA callback function that does the loading.
odbThe GNCOptionDB to load.

Definition at line 1133 of file qofbook.cpp.

1134 {
1135  load_cb (odb, book);
1136 }

◆ qof_book_options_delete()

void qof_book_options_delete ( QofBook *  book,
GSList *  path 
)

Delete the options.

Primarily used from Scheme to clear out the options before saving a new set.

Parameters
bookThe book.
listA GList of keys which from a path under KVP_OPTION_PATH. If GList is Null, the whole option is deleted.

Definition at line 1195 of file qofbook.cpp.

1196 {
1197  KvpFrame *root = qof_instance_get_slots(QOF_INSTANCE (book));
1198  if (path != nullptr)
1199  {
1200  Path path_v {KVP_OPTION_PATH};
1201  Path tmp_path;
1202  for (auto item = path; item != nullptr; item = g_slist_next(item))
1203  tmp_path.push_back(static_cast<const char*>(item->data));
1204  delete root->set_path(gslist_to_option_path(path), nullptr);
1205  }
1206  else
1207  delete root->set_path({KVP_OPTION_PATH}, nullptr);
1208 }

◆ qof_book_save_options()

void qof_book_save_options ( QofBook *  book,
GNCOptionSave  save_cb,
GNCOptionDB *  odb,
gboolean  clear 
)

Save a GNCOptionsDB back to the book's KVP.

Parameters
bookThe book.
save_cbA callback function that does the saving.
odbThe GNCOptionsDB to save from.
clearShould the GNCOptionsDB be emptied after the save?

Definition at line 1139 of file qofbook.cpp.

1141 {
1142  /* Wrap this in begin/commit so that it commits only once instead of doing
1143  * so for every option. Qof_book_set_option will take care of dirtying the
1144  * book.
1145  */
1146  qof_book_begin_edit (book);
1147  save_cb (odb, book, clear);
1148  qof_book_commit_edit (book);
1149 }

◆ qof_book_set_option()

void qof_book_set_option ( QofBook *  book,
KvpValue *  value,
GSList *  path 
)

Save a single option value.

Used from Scheme, the KvpValue<–>SCM translation is handled by the functions in kvp-scm.c and automated by SWIG. The starting element is set as KVP_OPTION_PATH in qofbookslots.h.

Parameters
bookThe book.
valueThe KvpValue to store.
pathA GSList of keys which form a path under KVP_OPTION_PATH.

Definition at line 1178 of file qofbook.cpp.

1179 {
1180  KvpFrame *root = qof_instance_get_slots (QOF_INSTANCE (book));
1181  qof_book_begin_edit (book);
1182  delete root->set_path(gslist_to_option_path(path), value);
1183  qof_instance_set_dirty (QOF_INSTANCE (book));
1184  qof_book_commit_edit (book);
1185 }

◆ qof_instance_get_kvp()

void qof_instance_get_kvp ( QofInstance *  ,
GValue *  value,
unsigned  count,
  ... 
)

Retrieves the contents of a KVP slot into a provided GValue.

Parameters
instThe QofInstance
keyThe path to the slot.
valueA GValue into which to store the value of the slot. It will be set to the correct type.

Definition at line 1094 of file qofinstance.cpp.

1095 {
1096  std::vector<std::string> path;
1097  va_list args;
1098  va_start (args, count);
1099  for (unsigned i{0}; i < count; ++i)
1100  path.push_back (va_arg (args, char const *));
1101  va_end (args);
1102  auto temp = gvalue_from_kvp_value (inst->kvp_data->get_slot (path));
1103  if (G_IS_VALUE (temp))
1104  {
1105  if (G_IS_VALUE (value))
1106  g_value_unset (value);
1107  g_value_init (value, G_VALUE_TYPE (temp));
1108  g_value_copy (temp, value);
1109  gnc_gvalue_free (temp);
1110  }
1111 }
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...
Definition: kvp-frame.cpp:392
GValue * gvalue_from_kvp_value(const KvpValue *kval)
Convert a kvp_value into a GValue.
Definition: kvp-frame.cpp:260

◆ qof_instance_has_kvp()

gboolean qof_instance_has_kvp ( QofInstance *  inst)

Report whether a QofInstance has anything stored in KVP.

Parameters
instThe QofInstance
Returns
TRUE if Kvp isn't empty.

Definition at line 1058 of file qofinstance.cpp.

1059 {
1060  return (inst->kvp_data != NULL && !inst->kvp_data->empty());
1061 }

◆ qof_instance_set_kvp()

void qof_instance_set_kvp ( QofInstance *  ,
GValue const *  value,
unsigned  count,
  ... 
)

Sets a KVP slot to a value from a GValue.

Intermediate container frames will be created if necessary. Commits the change to the QofInstance.

Parameters
instThe QofInstance on which to set the value.
keyThe path to the slot.
valueA GValue containing an item of a type which KvpValue knows how to store.

Definition at line 1069 of file qofinstance.cpp.

1070 {
1071  std::vector<std::string> path;
1072  va_list args;
1073  va_start (args, count);
1074  for (unsigned i{0}; i < count; ++i)
1075  path.push_back (va_arg (args, char const *));
1076  va_end (args);
1077  delete inst->kvp_data->set_path (path, kvp_value_from_gvalue (value));
1078 }
KvpValue * kvp_value_from_gvalue(const GValue *gval)
Convert a gvalue into a kvpvalue.
Definition: kvp-frame.cpp:327

◆ set()

KvpValue * KvpFrameImpl::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 or nullptr if it doesn't.

Takes ownership of new value and releases ownership of the returned old value. Values must be allocated on the free store with operator new.

Parameters
keyThe key to insert/replace.
newvalueThe value to set at key.
Returns
The old value if there was one or nullptr. 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. Takes ownership of new value and releases ownership of the returned old value. Values must be allocated on the free store with operator new.
Parameters
keyThe key to insert/replace.
Exceptions
invalid_argumentif the path doesn't exist.
Parameters
pathThe path of subframes leading to the frame in which to insert/replace.
newvalueThe value to set at key.
Returns
The old value if there was one or nullptr.

Definition at line 122 of file kvp-frame.cpp.

123 {
124  if (path.empty())
125  return nullptr;
126  auto key = path.back ();
127  path.pop_back ();
128  auto target = get_child_frame_or_nullptr (path);
129  if (!target)
130  return nullptr;
131  return target->set_impl (key, value);
132 }

◆ set_path()

KvpValue * KvpFrameImpl::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 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.

Parameters
pathThe path of subframes as a std::vector leading to the frame in which to insert/replace.
newvalueThe value to set at key.
Returns
The old value if there was one or nullptr.

Definition at line 135 of file kvp-frame.cpp.

136 {
137  auto key = path.back();
138  path.pop_back();
139  auto target = get_child_frame_or_create (path);
140  if (!target)
141  return nullptr;
142  return target->set_impl (key, value);
143 }

◆ to_string() [1/2]

std::string KvpFrameImpl::to_string ( ) const
noexcept

Make a string representation of the frame.

Mostly useful for debugging.

Returns
A std::string representing the frame and all its children.

Definition at line 160 of file kvp-frame.cpp.

161 {
162  return to_string("");
163 }
std::string to_string() const noexcept
Make a string representation of the frame.
Definition: kvp-frame.cpp:160

◆ to_string() [2/2]

std::string KvpFrameImpl::to_string ( std::string const &  prefix) const
noexcept

Make a string representation of the frame with the specified string prefixed to every item in the frame.

Returns
A std::string representing all the children of the frame.

Definition at line 166 of file kvp-frame.cpp.

167 {
168  if (!m_valuemap.size())
169  return prefix;
170  std::ostringstream ret;
171  std::for_each(m_valuemap.begin(), m_valuemap.end(),
172  [this,&ret,&prefix](const map_type::value_type &a)
173  {
174  std::string new_prefix {prefix};
175  if (a.first)
176  {
177  new_prefix += a.first;
178  new_prefix += "/";
179  }
180  if (a.second)
181  ret << a.second->to_string(new_prefix) << "\n";
182  else
183  ret << new_prefix << "(null)\n";
184  }
185  );
186  return ret.str();
187 }

Friends

◆ compare

int compare ( const KvpFrameImpl ,
const KvpFrameImpl  
)
friend

If the first KvpFrameImpl has an item that the second does not, 1 is returned.

The first item within the two KvpFrameImpl that is not similar, that comparison is returned. If all the items within the first KvpFrameImpl match items within the second, but the second has more elements, -1 is returned. Otherwise, 0 is returned.

Definition at line 217 of file kvp-frame.cpp.

218 {
219  for (const auto & a : one.m_valuemap)
220  {
221  auto otherspot = two.m_valuemap.find(a.first);
222  if (otherspot == two.m_valuemap.end())
223  {
224  return 1;
225  }
226  auto comparison = compare(a.second,otherspot->second);
227 
228  if (comparison != 0)
229  return comparison;
230  }
231 
232  if (one.m_valuemap.size() < two.m_valuemap.size())
233  return -1;
234  return 0;
235 }
friend int compare(const KvpFrameImpl &, const KvpFrameImpl &) noexcept
If the first KvpFrameImpl has an item that the second does not, 1 is returned.
Definition: kvp-frame.cpp:217