KVP: Key-Value Pairs
[Query Object Framework]


Detailed Description

A KvpFrame is a set of associations between character strings (keys) and KvpValue structures. A KvpValue is a union with possible types enumerated in the KvpValueType enum, and includes, among other things, ints, doubles, strings, guid's, 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 may be specified as varargs (variable number of arguments to a subrutine, NULL-terminated), as a GSList, or as a standard URL-like path name. The later is parsed and treated in the same way as file paths would be: / separates keys, /./ is treated as / and /../ means backup one level. Repeated slashes are treated as one slash.

Note that although, in principle, keys may contain the / and . and .. characters, doing so may lead to confusion, and will make path-string parsing routines fail. In other words, don't use a key such as 'some/key' or 'some/./other/../key' because you may get unexpected results.

To set a value into a frame, you will want to use one of the kvp_frame_set_xxx() routines. Most of the other routines provide only low-level access that you probably shouldn't use.


Files

file  kvp-util-p.h
 misc odd-job kvp utils engine-private routines
file  kvp-util.h
 QOF KVP utility functions.
file  kvp_frame.h
 A key-value frame system.

Data Structures

struct  GHashTableKVPair

KvpBag Bags of GUID Pointers

KvpFramegnc_kvp_bag_add (KvpFrame *kvp_root, const char *path, time_t secs, const char *first_name,...)
void gnc_kvp_bag_merge (KvpFrame *kvp_into, const char *intopath, KvpFrame *kvp_from, const char *frompath)
KvpFramegnc_kvp_bag_find_by_guid (KvpFrame *root, const char *path, const char *guid_name, const GUID *desired_guid)
void gnc_kvp_bag_remove_frame (KvpFrame *root, const char *path, KvpFrame *fr)

Hash Utilities

GSList * g_hash_table_key_value_pairs (GHashTable *table)
void g_hash_table_kv_pair_free_gfunc (gpointer data, gpointer user_data)

KvpFrame Constructors

KvpFramekvp_frame_new (void)
void kvp_frame_delete (KvpFrame *frame)
KvpFramekvp_frame_copy (const KvpFrame *frame)
gboolean kvp_frame_is_empty (const KvpFrame *frame)

KvpFrame Basic Value Storing

void kvp_frame_set_gint64 (KvpFrame *frame, const gchar *path, gint64 ival)
void kvp_frame_set_double (KvpFrame *frame, const gchar *path, double dval)
void kvp_frame_set_numeric (KvpFrame *frame, const gchar *path, gnc_numeric nval)
void kvp_frame_set_timespec (KvpFrame *frame, const gchar *path, Timespec ts)
void kvp_frame_set_string (KvpFrame *frame, const gchar *path, const gchar *str)
 Store a copy of the string at the indicated path.
void kvp_frame_set_guid (KvpFrame *frame, const gchar *path, const GUID *guid)
void kvp_frame_set_frame (KvpFrame *frame, const gchar *path, KvpFrame *chld)
void kvp_frame_set_frame_nc (KvpFrame *frame, const gchar *path, KvpFrame *chld)
KvpFramekvp_frame_set_value (KvpFrame *frame, const gchar *path, const KvpValue *value)
KvpFramekvp_frame_set_value_nc (KvpFrame *frame, const gchar *path, KvpValue *value)
KvpValuekvp_frame_replace_value_nc (KvpFrame *frame, const gchar *slot, KvpValue *new_value)
#define kvp_frame_set_gnc_numeric   kvp_frame_set_numeric
#define kvp_frame_set_str   kvp_frame_set_string

KvpFrame URL handling

void kvp_frame_add_url_encoding (KvpFrame *frame, const gchar *enc)

KvpFrame Glist Bag Storing

void kvp_frame_add_gint64 (KvpFrame *frame, const gchar *path, gint64 ival)
void kvp_frame_add_double (KvpFrame *frame, const gchar *path, double dval)
void kvp_frame_add_numeric (KvpFrame *frame, const gchar *path, gnc_numeric nval)
void kvp_frame_add_timespec (KvpFrame *frame, const gchar *path, Timespec ts)
void kvp_frame_add_string (KvpFrame *frame, const gchar *path, const gchar *str)
 Copy of the string to the glist bag at the indicated path.
void kvp_frame_add_guid (KvpFrame *frame, const gchar *path, const GUID *guid)
void kvp_frame_add_frame (KvpFrame *frame, const gchar *path, KvpFrame *chld)
void kvp_frame_add_frame_nc (KvpFrame *frame, const gchar *path, KvpFrame *chld)
KvpFramekvp_frame_add_value (KvpFrame *frame, const gchar *path, KvpValue *value)
KvpFramekvp_frame_add_value_nc (KvpFrame *frame, const gchar *path, KvpValue *value)
#define kvp_frame_add_gnc_numeric   kvp_frame_add_numeric
#define kvp_frame_add_str   kvp_frame_add_string

KvpFrame Value Fetching

Value accessors. These all take a unix-style slash-separated path as an argument, and return the value stored at that location. If the object at the end of that path is not of the type that was asked for, then a NULL or a zero is returned. So, for example, asking for a string when the path stored an int will return a NULL. In some future date, this may be changed to a looser type system, such as perl's automatic re-typing (e.g. an integer value might be converted to a printed string representing that value).

If any part of the path does not exist, then NULL or zero will be returned.

The values returned for GUID, binary, GList, KvpFrame and string are "non-copying" -- the returned item is the actual item stored. Do not delete this item unless you take the required care to avoid possible bad pointer derefrences (i.e. core dumps). Also, be careful hanging on to those references if you are also storing at the same path names: the referenced item will be freed during the store.

That is, if you get a string value (or guid, binary or frame), and then store something else at that path, the string that you've gotten will be freed during the store (internally, by the set_*() routines), and you will be left hanging onto an invalid pointer.

gint64 kvp_frame_get_gint64 (const KvpFrame *frame, const gchar *path)
double kvp_frame_get_double (const KvpFrame *frame, const gchar *path)
gnc_numeric kvp_frame_get_numeric (const KvpFrame *frame, const gchar *path)
const gchar * kvp_frame_get_string (const KvpFrame *frame, const gchar *path)
GUIDkvp_frame_get_guid (const KvpFrame *frame, const gchar *path)
void * kvp_frame_get_binary (const KvpFrame *frame, const gchar *path, guint64 *size_return)
Timespec kvp_frame_get_timespec (const KvpFrame *frame, const gchar *path)
KvpValuekvp_frame_get_value (const KvpFrame *frame, const gchar *path)
KvpFramekvp_frame_get_frame (const KvpFrame *frame, const gchar *path)
KvpFramekvp_frame_get_frame_path (KvpFrame *frame, const gchar *,...)
KvpFramekvp_frame_get_frame_gslist (KvpFrame *frame, const GSList *key_path)
KvpFramekvp_frame_get_frame_slash (KvpFrame *frame, const gchar *path)

KvpFrame KvpValue low-level storing routines.

You probably shouldn't be using these low-level routines

All of the kvp_frame_set_slot_*() routines set the slot values "destructively", in that if there was an old value there, that old value is destroyed (and the memory freed). Thus, one should not hang on to value pointers, as these will get trashed if set_slot is called on the corresponding key.

If you want the old value, use kvp_frame_replace_slot().

KvpValuekvp_frame_replace_slot_nc (KvpFrame *frame, const gchar *slot, KvpValue *new_value)
void kvp_frame_set_slot (KvpFrame *frame, const gchar *key, const KvpValue *value)
void kvp_frame_set_slot_nc (KvpFrame *frame, const gchar *key, KvpValue *value)
void kvp_frame_set_slot_path (KvpFrame *frame, const KvpValue *value, const gchar *first_key,...)
void kvp_frame_set_slot_path_gslist (KvpFrame *frame, const KvpValue *value, GSList *key_path)

KvpFrame KvpValue Low-Level Retrieval Routines

You probably shouldn't be using these low-level routines

Returns the KvpValue in the given KvpFrame 'frame' that is associated with 'key'. If there is no key in the frame, NULL is returned. If the value associated with the key is NULL, NULL is returned.

Pointers passed as arguments into get_slot are the responsibility of the caller. Pointers returned by get_slot are owned by the kvp_frame. Make copies as needed.

KvpValuekvp_frame_get_slot (const KvpFrame *frame, const gchar *key)
KvpValuekvp_frame_get_slot_path (KvpFrame *frame, const gchar *first_key,...)
KvpValuekvp_frame_get_slot_path_gslist (KvpFrame *frame, const GSList *key_path)
gint kvp_frame_compare (const KvpFrame *fa, const KvpFrame *fb)
gint double_compare (double v1, double v2)

KvpValue List Convenience Functions

You probably shouldn't be using these low-level routines

kvp_glist_compare() compares GLists of kvp_values (not to be confused with GLists of something else): it iterates over the list elements, performing a kvp_value_compare on each.

gint kvp_glist_compare (const GList *list1, const GList *list2)
GList * kvp_glist_copy (const GList *list)
void kvp_glist_delete (GList *list)

KvpValue Constructors

You probably shouldn't be using these low-level routines

The following routines are constructors for kvp_value. Those with pointer arguments copy in the value. The *_nc() versions do *not* copy in thier values, but use them directly.

KvpValuekvp_value_new_gint64 (gint64 value)
KvpValuekvp_value_new_double (double value)
KvpValuekvp_value_new_numeric (gnc_numeric value)
KvpValuekvp_value_new_string (const gchar *value)
KvpValuekvp_value_new_guid (const GUID *guid)
KvpValuekvp_value_new_timespec (Timespec timespec)
KvpValuekvp_value_new_binary (const void *data, guint64 datasize)
KvpValuekvp_value_new_frame (const KvpFrame *value)
KvpValuekvp_value_new_glist (const GList *value)
KvpValuekvp_value_new_binary_nc (void *data, guint64 datasize)
KvpValuekvp_value_new_glist_nc (GList *lst)
KvpValuekvp_value_new_frame_nc (KvpFrame *value)
void kvp_value_delete (KvpValue *value)
KvpValuekvp_value_copy (const KvpValue *value)
KvpFramekvp_value_replace_frame_nc (KvpValue *value, KvpFrame *newframe)
GList * kvp_value_replace_glist_nc (KvpValue *value, GList *newlist)
#define kvp_value_new_gnc_numeric   kvp_value_new_numeric

KvpValue Value access

You probably shouldn't be using these low-level routines

KvpValueType kvp_value_get_type (const KvpValue *value)
gint64 kvp_value_get_gint64 (const KvpValue *value)
double kvp_value_get_double (const KvpValue *value)
gnc_numeric kvp_value_get_numeric (const KvpValue *value)
char * kvp_value_get_string (const KvpValue *value)
GUIDkvp_value_get_guid (const KvpValue *value)
void * kvp_value_get_binary (const KvpValue *value, guint64 *size_return)
GList * kvp_value_get_glist (const KvpValue *value)
KvpFramekvp_value_get_frame (const KvpValue *value)
Timespec kvp_value_get_timespec (const KvpValue *value)
gint kvp_value_compare (const KvpValue *va, const KvpValue *vb)

Iterators

void kvp_frame_for_each_slot (KvpFrame *f, void(*proc)(const gchar *key, KvpValue *value, gpointer data), gpointer data)

Defines

#define QOF_MOD_KVP   "qof.kvp"
#define kvp_frame   KvpFrame
#define kvp_value   KvpValue
#define kvp_value_t   KvpValueType

Typedefs

typedef _KvpFrame KvpFrame
typedef _KvpValue KvpValue

Enumerations

enum  KvpValueType {
  KVP_TYPE_GINT64 = 1, KVP_TYPE_DOUBLE, KVP_TYPE_NUMERIC, KVP_TYPE_STRING,
  KVP_TYPE_GUID, KVP_TYPE_TIMESPEC, KVP_TYPE_BINARY, KVP_TYPE_GLIST,
  KVP_TYPE_FRAME
}
 possible types in the union KvpValue More...

Functions

gchar * kvp_value_to_bare_string (const KvpValue *val)
 General purpose function to convert any KvpValue to a string.
gchar * kvp_value_to_string (const KvpValue *val)
 Debug version of kvp_value_to_string.
gboolean kvp_value_binary_append (KvpValue *v, void *data, guint64 size)
gchar * kvp_frame_to_string (const KvpFrame *frame)
gchar * binary_to_string (const void *data, guint32 size)
gchar * kvp_value_glist_to_string (const GList *list)
GHashTable * kvp_frame_get_hash (const KvpFrame *frame)


Define Documentation

#define kvp_frame   KvpFrame

Deprecated:
Deprecated backwards compat token
do not use these in new code.

Definition at line 104 of file kvp_frame.h.

#define kvp_frame_add_gnc_numeric   kvp_frame_add_numeric

Deprecated:
Use kvp_frame_add_numeric instead of kvp_frame_add_gnc_numeric

Definition at line 270 of file kvp_frame.h.

#define kvp_frame_add_str   kvp_frame_add_string

Deprecated:
Use kvp_frame_add_string instead of kvp_frame_add_str

Definition at line 279 of file kvp_frame.h.

#define kvp_frame_set_gnc_numeric   kvp_frame_set_numeric

Deprecated:
Use kvp_frame_set_numeric instead of kvp_frame_set_gnc_numeric

Definition at line 154 of file kvp_frame.h.

#define kvp_frame_set_str   kvp_frame_set_string

Deprecated:
Use kvp_frame_set_string instead of kvp_frame_set_str

Definition at line 172 of file kvp_frame.h.

#define kvp_value   KvpValue

Deprecated:
Deprecated backwards compat token

Definition at line 106 of file kvp_frame.h.

#define kvp_value_new_gnc_numeric   kvp_value_new_numeric

Deprecated:
Use kvp_value_new_numeric instead of kvp_value_new_gnc_numeric

Definition at line 558 of file kvp_frame.h.

#define kvp_value_t   KvpValueType

Deprecated:
Deprecated backwards compat token

Definition at line 108 of file kvp_frame.h.


Typedef Documentation

typedef struct _KvpFrame KvpFrame

Opaque frame structure

Definition at line 71 of file kvp_frame.h.

typedef struct _KvpValue KvpValue

A KvpValue is a union with possible types enumerated in the KvpValueType enum.

Definition at line 75 of file kvp_frame.h.


Enumeration Type Documentation

enum KvpValueType

possible types in the union KvpValue

Todo:
: People have asked for boolean values, e.g. in xaccAccountSetAutoInterestXfer
Todo:
In the long run, this should be synchronized with the core QOF types, which in turn should be synced to the g_types in GLib. Unfortunately, this requires writing a pile of code to handle all of the different cases. An alternative might be to make kvp values inherit from the core g_types (i.e. add new core g_types) ??
Enumerator:
KVP_TYPE_GINT64  QOF_TYPE_INT64 gint64
KVP_TYPE_DOUBLE  QOF_TYPE_DOUBLE gdouble
KVP_TYPE_NUMERIC  QOF_TYPE_NUMERIC
KVP_TYPE_STRING  QOF_TYPE_STRING gchar*
KVP_TYPE_GUID  QOF_TYPE_GUID
KVP_TYPE_TIMESPEC  QOF_TYPE_DATE
KVP_TYPE_BINARY  no QOF equivalent.
KVP_TYPE_GLIST  no QOF equivalent.
KVP_TYPE_FRAME  no QOF equivalent.

Definition at line 88 of file kvp_frame.h.


Function Documentation

GSList* g_hash_table_key_value_pairs ( GHashTable *  table  ) 

Returns a GSList* of all the keys and values in a given hash table. Data elements of lists are actual hash elements, so be careful, and deallocation of the GHashTableKVPairs in the result list are the caller's responsibility. A typical sequence might look like this:

GSList *kvps = g_hash_table_key_value_pairs(hash); ... use kvps->data->key and kvps->data->val, etc. here ... g_slist_foreach(kvps, g_hash_table_kv_pair_free_gfunc, NULL); g_slist_free(kvps);

Definition at line 221 of file kvp-util.c.

00222 {
00223   GSList *result_list = NULL;
00224   g_hash_table_foreach(table, kv_pair_helper, &result_list);
00225   return result_list;
00226 }

KvpFrame* gnc_kvp_bag_add ( KvpFrame kvp_root,
const char *  path,
time_t  secs,
const char *  first_name,
  ... 
)

The gnc_kvp_bag_add() routine is used to maintain a collection of pointers in a kvp tree.

The thing being pointed at is uniquely identified by its GUID. This routine is typically used to create a linked list, and/or a collection of pointers to objects that are 'related' to each other in some way.

The var-args should be pairs of strings (const char *) followed by the corresponding GUID pointer (const GUID *). Terminate the varargs with a NULL as the last string argument.

The actual 'pointer' is stored in a subdirectory in a bag located at the node directory 'path'. A 'bag' is merely a collection of (unamed) values. The name of our bag is 'path'. A bag can contain any kind of values, including frames. This routine will create a frame, and put it in the bag. The frame will contain named data from the subroutine arguments. Thus, for example:

gnc_kvp_array (kvp, "foo", secs, "acct_guid", aguid, "book_guid", bguid, NULL);

will create a frame containing "/acct_guid" and "/book_guid", whose values are aguid and bguid respecitvely. The frame will also contain "/date", whose value will be secs. This frame will be placed into the bag located at "foo".

This routine returns a pointer to the frame that was created, or NULL if an error occured.

Definition at line 74 of file kvp-util.c.

00076 {
00077    KvpFrame *cwd;
00078    va_list ap;
00079    va_start (ap, first_name);
00080    cwd = gnc_kvp_array_va (pwd, path, secs, first_name, ap);
00081    va_end (ap);
00082    return cwd;
00083 }

KvpFrame* gnc_kvp_bag_find_by_guid ( KvpFrame root,
const char *  path,
const char *  guid_name,
const GUID desired_guid 
)

The gnc_kvp_bag_find_by_guid() routine examines the bag pointed located at root. It looks for a frame in that bag that has the guid value of "desired_guid" filed under the key name "guid_name". If it finds that matching guid, then it returns a pointer to the KVP frame that contains it. If it is not found, or if there is any other error, NULL is returned.

Definition at line 96 of file kvp-util.c.

00098 {
00099   KvpValue *arr;
00100   KvpValueType valtype;
00101   GList *node;
00102 
00103   arr = kvp_frame_get_value (root, path);
00104   valtype = kvp_value_get_type (arr);
00105   if (KVP_TYPE_FRAME == valtype)
00106   {
00107     MATCH_GUID (arr);
00108     return NULL;
00109   }
00110 
00111   /* Its gotta be a single isolated frame, or a list of them. */
00112   if (KVP_TYPE_GLIST != valtype) return NULL;
00113 
00114   for (node = kvp_value_get_glist(arr); node; node=node->next)
00115   {
00116     KvpValue *va = node->data;
00117     MATCH_GUID (va);
00118   }
00119   return NULL;
00120 }

void gnc_kvp_bag_merge ( KvpFrame kvp_into,
const char *  intopath,
KvpFrame kvp_from,
const char *  frompath 
)

The gnc_kvp_bag_merge() routine will move the bag contents from the 'kvp_from', to the 'into' bag. It will then delete the 'from' bag from the kvp tree.

Definition at line 190 of file kvp-util.c.

00192 {
00193   KvpFrame *fr;
00194 
00195   fr = gnc_kvp_bag_get_first (kvp_from, frompath);
00196   while (fr) 
00197   {
00198     gnc_kvp_bag_remove_frame (kvp_from, frompath, fr);
00199     kvp_frame_add_frame_nc (kvp_into, intopath, fr);
00200     fr = gnc_kvp_bag_get_first (kvp_from, frompath);
00201   }
00202 }

void gnc_kvp_bag_remove_frame ( KvpFrame root,
const char *  path,
KvpFrame fr 
)

Remove the given frame from the bag. The frame is removed, however, it is not deleted. Note that the frame pointer must be a pointer to the actual frame (for example, as returned by gnc_kvp_bag_find_by_guid() for by gnc_kvp_bag_add()), and not some copy of the frame.

Definition at line 125 of file kvp-util.c.

00126 {
00127   KvpValue *arr;
00128   KvpValueType valtype;
00129   GList *node, *listhead;
00130 
00131   arr = kvp_frame_get_value (root, path);
00132   valtype = kvp_value_get_type (arr);
00133   if (KVP_TYPE_FRAME == valtype)
00134   {
00135     if (fr == kvp_value_get_frame (arr))
00136     {
00137       KvpValue *old_val = kvp_frame_replace_value_nc (root, path, NULL); 
00138       kvp_value_replace_frame_nc (old_val, NULL);
00139       kvp_value_delete (old_val);
00140     }
00141     return;
00142   }
00143 
00144   /* Its gotta be a single isolated frame, or a list of them. */
00145   if (KVP_TYPE_GLIST != valtype) return;
00146 
00147   listhead = kvp_value_get_glist(arr);
00148   for (node = listhead; node; node=node->next)
00149   {
00150     KvpValue *va = node->data;
00151     if (fr == kvp_value_get_frame (va))
00152     {
00153       listhead = g_list_remove_link (listhead, node);
00154       g_list_free_1 (node);
00155       kvp_value_replace_glist_nc (arr, listhead);
00156       kvp_value_replace_frame_nc (va, NULL);
00157       kvp_value_delete (va);
00158       return;
00159     }
00160   }
00161 }

void kvp_frame_add_gint64 ( KvpFrame frame,
const gchar *  path,
gint64  ival 
)

The kvp_frame_add_gint64() routine will add the value of the gint64 to the glist bag of values at the indicated path. If not all frame components of the path exist, they are created. If the value previously stored at this path was not a glist bag, then a bag will be formed there, the old value placed in the bag, and the new value added to the bag.

Similarly, the add_double, add_numeric, and add_timespec routines perform the same function, for each of the respective types.

void kvp_frame_add_string ( KvpFrame frame,
const gchar *  path,
const gchar *  str 
)

Copy of the string to the glist bag at the indicated path.

If not all frame components of the path exist, they are created. If there was another item previously stored at that path, then the path is converted to a bag, and the old value, along with the new value, is added to the bag.

Similarly, the add_guid and add_frame will make copies and add those.

The kvp_frame_add_frame_nc() routine works as above, but does *NOT* copy the frame.

void kvp_frame_add_url_encoding ( KvpFrame frame,
const gchar *  enc 
)

The kvp_frame_add_url_encoding() routine will parse the value string, assuming it to be URL-encoded in the standard way, turning it into a set of key-value pairs, and adding those to the indicated frame. URL-encoded strings are the things that are returned by web browsers when a form is filled out. For example, 'start-date=June&end-date=November' consists of two keys, 'start-date' and 'end-date', which have the values 'June' and 'November', respectively. This routine also handles % encoding.

This routine treats all values as strings; it does *not* attempt to perform any type-conversion.

gint kvp_frame_compare ( const KvpFrame fa,
const KvpFrame fb 
)

Similar returns as strcmp.

Definition at line 1562 of file kvp_frame.c.

01563 {
01564   kvp_frame_cmp_status status;
01565 
01566   if(fa == fb) return 0;
01567   /* nothing is always less than something */
01568   if(!fa && fb) return -1;
01569   if(fa && !fb) return 1;
01570 
01571   /* nothing is always less than something */
01572   if(!fa->hash && fb->hash) return -1;
01573   if(fa->hash && !fb->hash) return 1;
01574 
01575   status.compare = 0;
01576   status.other_frame = (KvpFrame *) fb;
01577 
01578   kvp_frame_for_each_slot((KvpFrame *) fa, kvp_frame_compare_helper, &status);
01579 
01580   if (status.compare != 0)
01581     return status.compare;
01582 
01583   status.other_frame = (KvpFrame *) fa;
01584 
01585   kvp_frame_for_each_slot((KvpFrame *) fb, kvp_frame_compare_helper, &status);
01586 
01587   return(-status.compare);
01588 }

KvpFrame* kvp_frame_copy ( const KvpFrame frame  ) 

Perform a deep (recursive) value copy, copying the fraame, subframes, and the values as well.

Definition at line 149 of file kvp_frame.c.

00150 {
00151   KvpFrame * retval = kvp_frame_new();
00152 
00153   if (!frame) return retval;
00154 
00155   if(frame->hash) 
00156   {
00157     if(!init_frame_body_if_needed(retval)) return(NULL);
00158     g_hash_table_foreach(frame->hash,
00159                          & kvp_frame_copy_worker, 
00160                          (gpointer)retval);
00161   }
00162   return retval;
00163 }

void kvp_frame_delete ( KvpFrame frame  ) 

Perform a deep (recursive) delete of the frame and any subframes.

kvp_frame_delete and kvp_value_delete are deep (recursive) deletes. kvp_frame_copy and kvp_value_copy are deep value copies.

Definition at line 114 of file kvp_frame.c.

00115 {
00116   if (!frame) return;
00117 
00118   if(frame->hash) 
00119   {
00120     /* free any allocated resource for frame or its children */
00121     g_hash_table_foreach(frame->hash, & kvp_frame_delete_worker, 
00122                          (gpointer)frame);
00123     
00124     /* delete the hash table */
00125     g_hash_table_destroy(frame->hash);
00126     frame->hash = NULL;
00127   }
00128   g_free(frame);
00129 }

void kvp_frame_for_each_slot ( KvpFrame f,
void(*)(const gchar *key, KvpValue *value, gpointer data)  proc,
gpointer  data 
)

Traverse all of the slots in the given kvp_frame. This function does not descend recursively to traverse any kvp_frames stored as slot values. You must handle that in proc, with a suitable recursive call if desired.

KvpFrame* kvp_frame_get_frame ( const KvpFrame frame,
const gchar *  path 
)

Value accessor. Takes a unix-style slash-separated path as an argument, and return the KvpFrame stored at that location. If the KvpFrame does not exist, then a NULL is returned.

Note:
The semantics here have changed: In gnucash-1.8, if the KvpFrame did not exist, this function automatically created one and returned it. However, now this function will return NULL in this case and the caller has to create a KvpFrame on his own. The old functionality is now implemented by kvp_frame_get_frame_path(). This happened on 2003-09-14, revision 1.31. FIXME: Is it really a good idea to change the semantics of an existing function and move the old semantics to a new function??! It would save us a lot of trouble if the new semantics would have been available in a new function!
Returns:
The KvpFrame at the specified path, or NULL if it doesn't exist.

KvpFrame* kvp_frame_get_frame_gslist ( KvpFrame frame,
const GSList *  key_path 
)

This routine returns the last frame of the path. If the frame path doesn't exist, it is created. Note that this is *VERY DIFFERENT FROM* kvp_frame_get_frame()

Definition at line 924 of file kvp_frame.c.

00925 {
00926   if (!frame) return frame;
00927 
00928   while (key_path) 
00929   {
00930     const char *key = key_path->data;
00931 
00932     if (!key) return frame;  /* an unusual but valid exit for this routine. */
00933 
00934     frame = get_or_make (frame, key);
00935     if (!frame) return frame;  /* this should never happen */
00936 
00937     key_path = key_path->next;
00938   }
00939   return frame;  /* this is the normal exit for this func */
00940 }

KvpFrame* kvp_frame_get_frame_path ( KvpFrame frame,
const gchar *  ,
  ... 
)

This routine returns the last frame of the path. If the frame path doesn't exist, it is created. Note that this is *VERY DIFFERENT FROM* like kvp_frame_get_frame()

Note:
The semantics of this function implemented the gnucash-1.8 behaviour of kvp_frame_get_frame: In gnucash-1.8, if the KvpFrame did not exist, kvp_frame_get_frame automatically created one and returned it. However, now that one will return NULL in this case and the caller has to create a KvpFrame on his own. The old functionality is implemented by this kvp_frame_get_frame_path(). This happened on 2003-09-14, revision 1.31.

KvpFrame* kvp_frame_get_frame_slash ( KvpFrame frame,
const gchar *  path 
)

This routine returns the last frame of the path. If the frame path doesn't exist, it is created. Note that this is *VERY DIFFERENT FROM* kvp_frame_get_frame()

The kvp_frame_get_frame_slash() routine takes a single string where the keys are separated by slashes; thus, for example: /this/is/a/valid/path and///so//is////this/ Multiple slashes are compresed. Leading slash is optional. The pointers . and .. are *not* currently followed/obeyed. (This is a bug that needs fixing).

KvpValue* kvp_frame_get_slot_path ( KvpFrame frame,
const gchar *  first_key,
  ... 
)

This routine return the value at the end of the path, or NULL if any portion of the path doesn't exist.

KvpValue* kvp_frame_get_slot_path_gslist ( KvpFrame frame,
const GSList *  key_path 
)

This routine return the value at the end of the path, or NULL if any portion of the path doesn't exist.

Definition at line 1012 of file kvp_frame.c.

01014 {
01015   if (!frame || !key_path) return NULL;
01016 
01017   while (TRUE) 
01018   {
01019     const char *key = key_path->data;
01020     KvpValue *value;
01021 
01022     if (!key) return NULL;
01023 
01024     value = kvp_frame_get_slot (frame, key);
01025     if (!value) return NULL;
01026 
01027     key_path = key_path->next;
01028     if (!key_path) return value;
01029 
01030     frame = kvp_value_get_frame (value);
01031     if (!frame) return NULL;
01032   }
01033 }

gboolean kvp_frame_is_empty ( const KvpFrame frame  ) 

Return TRUE if the KvpFrame is empty

Definition at line 132 of file kvp_frame.c.

00133 {
00134   if (!frame) return TRUE;
00135   if (!frame->hash) return TRUE;
00136   return FALSE;
00137 }

KvpFrame* kvp_frame_new ( void   ) 

Return a new empty instance of KvpFrame

Definition at line 97 of file kvp_frame.c.

00098 {
00099   KvpFrame * retval = g_new0(KvpFrame, 1);
00100 
00101   /* Save space until the frame is actually used */
00102   retval->hash = NULL;
00103   return retval;
00104 }

KvpValue* kvp_frame_replace_slot_nc ( KvpFrame frame,
const gchar *  slot,
KvpValue new_value 
)

The kvp_frame_replace_slot_nc() routine places the new value into the indicated frame, for the given key. It returns the old value, if any. It returns NULL if the slot doesn't exist, if there was some other an error, or if there was no old value. Passing in a NULL new_value has the effect of deleting that slot.

KvpValue* kvp_frame_replace_value_nc ( KvpFrame frame,
const gchar *  slot,
KvpValue new_value 
)

The kvp_frame_replace_value_nc() routine places the new value at the indicated path. It returns the old value, if any. It returns NULL if there was an error, or if there was no old value. If the path doesn't exist, it is created, unless new_value is NULL. Passing in a NULL new_value has the effect of deleting the trailing slot (i.e. the trailing path element).

void kvp_frame_set_double ( KvpFrame frame,
const gchar *  path,
double  dval 
)

store the value of the double at the indicated path. If not all frame components of the path exist, they are created.

void kvp_frame_set_gint64 ( KvpFrame frame,
const gchar *  path,
gint64  ival 
)

store the value of the gint64 at the indicated path. If not all frame components of the path exist, they are created.

void kvp_frame_set_numeric ( KvpFrame frame,
const gchar *  path,
gnc_numeric  nval 
)

store the value of the gnc_numeric at the indicated path. If not all frame components of the path exist, they are created.

void kvp_frame_set_slot ( KvpFrame frame,
const gchar *  key,
const KvpValue value 
)

The kvp_frame_set_slot() routine copies the value into the frame, associating it with a copy of 'key'. Pointers passed as arguments into kvp_frame_set_slot are the responsibility of the caller; the pointers are *not* taken over or managed. The old value at this location, if any, is destroyed.

void kvp_frame_set_slot_nc ( KvpFrame frame,
const gchar *  key,
KvpValue value 
)

The kvp_frame_set_slot_nc() routine puts the value (without copying it) into the frame, associating it with a copy of 'key'. This routine is handy for avoiding excess memory allocations & frees. Note that because the KvpValue was grabbed, you can't just delete unless you remove the key as well (or unless you replace the value). The old value at this location, if any, is destroyed.

void kvp_frame_set_slot_path ( KvpFrame frame,
const KvpValue value,
const gchar *  first_key,
  ... 
)

The kvp_frame_set_slot_path() routine walks the hierarchy, using the key values to pick each branch. When the terminal node is reached, the value is copied into it. The old value at this location, if any, is destroyed.

void kvp_frame_set_slot_path_gslist ( KvpFrame frame,
const KvpValue value,
GSList *  key_path 
)

The kvp_frame_set_slot_path_gslist() routine walks the hierarchy, using the key values to pick each branch. When the terminal node is reached, the value is copied into it. The old value at this location, if any, is destroyed.

Definition at line 725 of file kvp_frame.c.

00728 {
00729   if (!frame || !key_path) return;
00730 
00731   while (TRUE) 
00732   {
00733     const char *key = key_path->data;
00734     KvpValue *value;
00735 
00736     if (!key)
00737       return;
00738 
00739     g_return_if_fail (*key != '\0');
00740 
00741     key_path = key_path->next;
00742     if (!key_path) 
00743     {
00744       kvp_frame_set_slot (frame, key, new_value);
00745       return;
00746     }
00747 
00748     value = kvp_frame_get_slot (frame, key);
00749     if (!value) 
00750     {
00751       KvpFrame *new_frame = kvp_frame_new ();
00752       KvpValue *frame_value = kvp_value_new_frame (new_frame);
00753 
00754       kvp_frame_set_slot_nc (frame, key, frame_value);
00755 
00756       value = kvp_frame_get_slot (frame, key);
00757       if (!value)
00758         return;
00759     }
00760 
00761     frame = kvp_value_get_frame (value);
00762     if (!frame)
00763       return;
00764   }
00765 }

void kvp_frame_set_string ( KvpFrame frame,
const gchar *  path,
const gchar *  str