KVP: Key-Value Pairs
[Query Object Framework]


Data Structures

struct  GHashTableKVPair

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.

Defines

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

Typedefs

typedef struct _KvpFrame KvpFrame
typedef struct _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)

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.


Define Documentation

#define kvp_frame   KvpFrame

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

Definition at line 105 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 271 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 280 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 155 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 173 of file kvp_frame.h.

#define kvp_value   KvpValue

Deprecated:
Deprecated backwards compat token

Definition at line 107 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 560 of file kvp_frame.h.

#define kvp_value_t   KvpValueType

Deprecated:
Deprecated backwards compat token

Definition at line 109 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

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 1607 of file kvp_frame.c.

01608 {
01609     kvp_frame_cmp_status status;
01610 
01611     if (fa == fb) return 0;
01612     /* nothing is always less than something */
01613     if (!fa && fb) return -1;
01614     if (fa && !fb) return 1;
01615 
01616     /* nothing is always less than something */
01617     if (!fa->hash && fb->hash) return -1;
01618     if (fa->hash && !fb->hash) return 1;
01619 
01620     status.compare = 0;
01621     status.other_frame = (KvpFrame *) fb;
01622 
01623     kvp_frame_for_each_slot((KvpFrame *) fa, kvp_frame_compare_helper, &status);
01624 
01625     if (status.compare != 0)
01626         return status.compare;
01627 
01628     status.other_frame = (KvpFrame *) fa;
01629 
01630     kvp_frame_for_each_slot((KvpFrame *) fb, kvp_frame_compare_helper, &status);
01631 
01632     return(-status.compare);
01633 }

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 150 of file kvp_frame.c.

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

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 115 of file kvp_frame.c.

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

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 941 of file kvp_frame.c.

00942 {
00943     if (!frame) return frame;
00944 
00945     while (key_path)
00946     {
00947         const char *key = key_path->data;
00948 
00949         if (!key) return frame;  /* an unusual but valid exit for this routine. */
00950 
00951         frame = get_or_make (frame, key);
00952         if (!frame) return frame;  /* this should never happen */
00953 
00954         key_path = key_path->next;
00955     }
00956     return frame;  /* this is the normal exit for this func */
00957 }

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 1029 of file kvp_frame.c.

01031 {
01032     if (!frame || !key_path) return NULL;
01033 
01034     while (TRUE)
01035     {
01036         const char *key = key_path->data;
01037         KvpValue *value;
01038 
01039         if (!key) return NULL;
01040 
01041         value = kvp_frame_get_slot (frame, key);
01042         if (!value) return NULL;
01043 
01044         key_path = key_path->next;
01045         if (!key_path) return value;
01046 
01047         frame = kvp_value_get_frame (value);
01048         if (!frame) return NULL;
01049     }
01050 }

gboolean kvp_frame_is_empty ( const KvpFrame frame  ) 

Return TRUE if the KvpFrame is empty

Definition at line 133 of file kvp_frame.c.

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

KvpFrame* kvp_frame_new ( void   ) 

Return a new empty instance of KvpFrame

Definition at line 98 of file kvp_frame.c.

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

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 733 of file kvp_frame.c.

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

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

Store a copy of the string at the indicated path.

If not all frame components of the path exist, they are created. If there was another string previously stored at that path, the old copy is deleted.

Similarly, the set_guid and set_frame will make copies and store those. Old copies, if any, are deleted.

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

void kvp_frame_set_timespec ( KvpFrame frame,
const gchar *  path,
Timespec  ts 
)

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

KvpFrame* kvp_frame_set_value ( KvpFrame frame,
const gchar *  path,
const KvpValue value 
)

The kvp_frame_set_value() routine copies the value into the frame, at the location 'path'. If the path contains slashes '/', these are assumed to represent a sequence of keys. The returned value is a pointer to the actual frame into which the value was inserted; it is NULL if the frame couldn't be found (and thus the value wasn't inserted). The old value at this location, if any, is destroyed.

Pointers passed as arguments into this routine are the responsibility of the caller; the pointers are *not* taken over or managed.

KvpFrame* kvp_frame_set_value_nc ( KvpFrame frame,
const gchar *  path,
KvpValue value 
)

The kvp_frame_set_value_nc() routine puts the value (without copying it) into the frame, putting it at the location 'path'. If the path contains slashes '/', these are assumed to represent a sequence of keys. The returned value is a pointer to the actual frame into which the value was inserted; it is NULL if the frame couldn't be found (and thus the value wasn't inserted). The old value at this location, if any, is destroyed.

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).

gchar* kvp_frame_to_string ( const KvpFrame frame  ) 

Internal helper routines, you probably shouldn't be using these.

Definition at line 1865 of file kvp_frame.c.

01866 {
01867     gchar *tmp1;
01868 
01869     g_return_val_if_fail (frame != NULL, NULL);
01870 
01871     tmp1 = g_strdup_printf("{\n");
01872 
01873     if (frame->hash)
01874         g_hash_table_foreach(frame->hash, kvp_frame_to_string_helper, &tmp1);
01875 
01876     {
01877         gchar *tmp2;
01878         tmp2 = g_strdup_printf("%s}\n", tmp1);
01879         g_free(tmp1);
01880         tmp1 = tmp2;
01881     }
01882 
01883     return tmp1;
01884 }

GList* kvp_glist_copy ( const GList *  list  ) 

kvp_glist_copy() performs a deep copy of a GList of kvp_values (not to be confused with GLists of something else): same as mapping kvp_value_copy() over the elements and then copying the spine.

Definition at line 1074 of file kvp_frame.c.

01075 {
01076     GList * retval = NULL;
01077     GList * lptr;
01078 
01079     if (!list) return retval;
01080 
01081     /* Duplicate the backbone of the list (this duplicates the POINTERS
01082      * to the values; we need to deep-copy the values separately) */
01083     retval = g_list_copy((GList *) list);
01084 
01085     /* This step deep-copies the values */
01086     for (lptr = retval; lptr; lptr = lptr->next)
01087     {
01088         lptr->data = kvp_value_copy(lptr->data);
01089     }
01090 
01091     return retval;
01092 }

void kvp_glist_delete ( GList *  list  ) 

kvp_glist_delete() performs a deep delete of a GList of kvp_values (not to be confused with GLists of something else): same as mapping * kvp_value_delete() over the elements and then deleting the GList.

Definition at line 1057 of file kvp_frame.c.

01058 {
01059     GList *node;
01060     if (!list) return;
01061 
01062     /* Delete the data in the list */
01063     for (node = list; node; node = node->next)
01064     {
01065         KvpValue *val = node->data;
01066         kvp_value_delete(val);
01067     }
01068 
01069     /* Free the backbone */
01070     g_list_free(list);
01071 }

gboolean kvp_value_binary_append ( KvpValue v,
void *  data,
guint64  size 
)

Manipulator:

copying - but more efficient than creating a new KvpValue manually.

gint kvp_value_compare ( const KvpValue va,
const KvpValue vb 
)

Similar returns as strcmp.

Definition at line 1528 of file kvp_frame.c.

01529 {
01530     if (kva == kvb) return 0;
01531     /* nothing is always less than something */
01532     if (!kva && kvb) return -1;
01533     if (kva && !kvb) return 1;
01534 
01535     if (kva->type < kvb->type) return -1;
01536     if (kva->type > kvb->type) return 1;
01537 
01538     switch (kva->type)
01539     {
01540     case KVP_TYPE_GINT64:
01541         if (kva->value.int64 < kvb->value.int64) return -1;
01542         if (kva->value.int64 > kvb->value.int64) return 1;
01543         return 0;
01544         break;
01545     case KVP_TYPE_DOUBLE:
01546         return double_compare(kva->value.dbl, kvb->value.dbl);
01547         break;
01548     case KVP_TYPE_NUMERIC:
01549         return gnc_numeric_compare (kva->value.numeric, kvb->value.numeric);
01550         break;
01551     case KVP_TYPE_STRING:
01552         return strcmp(kva->value.str, kvb->value.str);
01553         break;
01554     case KVP_TYPE_GUID:
01555         return guid_compare(kva->value.guid, kvb->value.guid);
01556         break;
01557     case KVP_TYPE_TIMESPEC:
01558         return timespec_cmp(&(kva->value.timespec), &(kvb->value.timespec));
01559         break;
01560     case KVP_TYPE_BINARY:
01561         /* I don't know that this is a good compare. Ab is bigger than Acef.
01562            But I'm not sure that actually matters here. */
01563         if (kva->value.binary.datasize < kvb->value.binary.datasize) return -1;
01564         if (kva->value.binary.datasize > kvb->value.binary.datasize) return 1;
01565         return memcmp(kva->value.binary.data,
01566                       kvb->value.binary.data,
01567                       kva->value.binary.datasize);
01568         break;
01569     case KVP_TYPE_GLIST:
01570         return kvp_glist_compare(kva->value.list, kvb->value.list);
01571         break;
01572     case KVP_TYPE_FRAME:
01573         return kvp_frame_compare(kva->value.frame, kvb->value.frame);
01574         break;
01575     }
01576     PERR ("reached unreachable code.");
01577     return FALSE;
01578 }

KvpValue* kvp_value_copy ( const KvpValue value  ) 

This is a deep value copy.

Definition at line 1463 of file kvp_frame.c.

01464 {
01465     if (!value) return NULL;
01466 
01467     switch (value->type)
01468     {
01469     case KVP_TYPE_GINT64:
01470         return kvp_value_new_gint64(value->value.int64);
01471         break;
01472     case KVP_TYPE_DOUBLE:
01473         return kvp_value_new_double(value->value.dbl);
01474         break;
01475     case KVP_TYPE_NUMERIC:
01476         return kvp_value_new_gnc_numeric(value->value.numeric);
01477         break;
01478     case KVP_TYPE_STRING:
01479         return kvp_value_new_string(value->value.str);
01480         break;
01481     case KVP_TYPE_GUID:
01482         return kvp_value_new_guid(value->value.guid);
01483         break;
01484     case KVP_TYPE_TIMESPEC:
01485         return kvp_value_new_timespec(value->value.timespec);
01486         break;
01487     case KVP_TYPE_BINARY:
01488         return kvp_value_new_binary(value->value.binary.data,
01489                                     value->value.binary.datasize);
01490         break;
01491     case KVP_TYPE_GLIST:
01492         return kvp_value_new_glist(value->value.list);
01493         break;
01494     case KVP_TYPE_FRAME:
01495         return kvp_value_new_frame(value->value.frame);
01496         break;
01497     }
01498     return NULL;
01499 }

void kvp_value_delete ( KvpValue value  ) 

This is a deep (recursive) delete.

Definition at line 1263 of file kvp_frame.c.

01264 {
01265     if (!value) return;
01266 
01267     switch (value->type)
01268     {
01269     case KVP_TYPE_STRING:
01270         g_free(value->value.str);
01271         break;
01272     case KVP_TYPE_GUID:
01273         g_free(value->value.guid);
01274         break;
01275     case KVP_TYPE_BINARY:
01276         g_free(value->value.binary.data);
01277         break;
01278     case KVP_TYPE_GLIST:
01279         kvp_glist_delete(value->value.list);
01280         break;
01281     case KVP_TYPE_FRAME:
01282         kvp_frame_delete(value->value.frame);
01283         break;
01284 
01285     case KVP_TYPE_GINT64:
01286     case KVP_TYPE_DOUBLE:
01287     case KVP_TYPE_NUMERIC:
01288     default:
01289         break;
01290     }
01291     g_free(value);
01292 }

void* kvp_value_get_binary ( const KvpValue value,
guint64 *  size_return 
)

Value accessor. This one is non-copying -- the caller can modify the value directly.

Definition at line 1385 of file kvp_frame.c.

01386 {
01387     if (!value)
01388     {
01389         if (size_return)
01390             *size_return = 0;
01391         return NULL;
01392     }
01393 
01394     if (value->type == KVP_TYPE_BINARY)
01395     {
01396         if (size_return)
01397             *size_return = value->value.binary.datasize;
01398         return value->value.binary.data;
01399     }
01400     else
01401     {
01402         if (size_return)
01403             *size_return = 0;
01404         return NULL;
01405     }
01406 }

KvpFrame* kvp_value_get_frame ( const KvpValue value  ) 

Value accessor. This one is non-copying -- the caller can modify the value directly.

Definition at line 1423 of file kvp_frame.c.

01424 {
01425     if (!value) return NULL;
01426     if (value->type == KVP_TYPE_FRAME)
01427     {
01428         return value->value.frame;
01429     }
01430     else
01431     {
01432         return NULL;
01433     }
01434 }

gint64 kvp_value_get_gint64 ( const KvpValue value  ) 

Value accessors. Those for GUID, binary, GList, KvpFrame and string are non-copying -- the caller can modify the value directly. Just don't free it, or you screw up everything. Note that if another value is stored at the key location that this value came from, then this value will be uncermoniously deleted, and you will be left pointing to garbage. So don't store values at the same time you are examining their contents.

Definition at line 1302 of file kvp_frame.c.

01303 {
01304     if (!value) return 0;
01305     if (value->type == KVP_TYPE_GINT64)
01306     {
01307         return value->value.int64;
01308     }
01309     else
01310     {
01311         return 0;
01312     }
01313 }

GList* kvp_value_get_glist ( const KvpValue value  ) 

Returns the GList of kvp_frame's (not to be confused with GList's of something else!) from the given kvp_frame. This one is non-copying -- the caller can modify the value directly.

Definition at line 1409 of file kvp_frame.c.

01410 {
01411     if (!value) return NULL;
01412     if (value->type == KVP_TYPE_GLIST)
01413     {
01414         return value->value.list;
01415     }
01416     else
01417     {
01418         return NULL;
01419     }
01420 }

GUID* kvp_value_get_guid ( const KvpValue value  ) 

Value accessor. This one is non-copying -- the caller can modify the value directly.

Definition at line 1358 of file kvp_frame.c.

01359 {
01360     if (!value) return NULL;
01361     if (value->type == KVP_TYPE_GUID)
01362     {
01363         return value->value.guid;
01364     }
01365     else
01366     {
01367         return NULL;
01368     }
01369 }

char* kvp_value_get_string ( const KvpValue value  ) 

Value accessor. This one is non-copying -- the caller can modify the value directly.

Definition at line 1344 of file kvp_frame.c.

01345 {
01346     if (!value) return NULL;
01347     if (value->type == KVP_TYPE_STRING)
01348     {
01349         return value->value.str;
01350     }
01351     else
01352     {
01353         return NULL;
01354     }
01355 }

KvpValue* kvp_value_new_binary_nc ( void *  data,
guint64  datasize 
)

value constructors (non-copying - KvpValue takes pointer ownership) values *must* have been allocated via glib allocators! (gnew, etc.)

Definition at line 1202 of file kvp_frame.c.

01203 {
01204     KvpValue * retval;
01205     if (!value) return NULL;
01206 
01207     retval = g_new0(KvpValue, 1);
01208     retval->type = KVP_TYPE_BINARY;
01209     retval->value.binary.data = value;
01210     retval->value.binary.datasize = datasize;
01211     return retval;
01212 }

KvpValue* kvp_value_new_frame_nc ( KvpFrame value  ) 

value constructors (non-copying - KvpValue takes pointer ownership) values *must* have been allocated via glib allocators! (gnew, etc.)

Definition at line 1251 of file kvp_frame.c.

01252 {
01253     KvpValue * retval;
01254     if (!value) return NULL;
01255 
01256     retval  = g_new0(KvpValue, 1);
01257     retval->type        = KVP_TYPE_FRAME;
01258     retval->value.frame = value;
01259     return retval;
01260 }

KvpValue* kvp_value_new_glist ( const GList *  value  ) 

Creates a KvpValue from a GList of kvp_value's! (Not to be confused with GList's of something else!)

Definition at line 1215 of file kvp_frame.c.

01216 {
01217     KvpValue * retval;
01218     if (!value) return NULL;
01219 
01220     retval = g_new0(KvpValue, 1);
01221     retval->type       = KVP_TYPE_GLIST;
01222     retval->value.list = kvp_glist_copy(value);
01223     return retval;
01224 }

KvpValue* kvp_value_new_glist_nc ( GList *  lst  ) 

Creates a KvpValue from a GList of kvp_value's! (Not to be confused with GList's of something else!)

This value constructor is non-copying (KvpValue takes pointer ownership). The values *must* have been allocated via glib allocators! (gnew, etc.)

Definition at line 1227 of file kvp_frame.c.

01228 {
01229     KvpValue * retval;
01230     if (!value) return NULL;
01231 
01232     retval = g_new0(KvpValue, 1);
01233     retval->type       = KVP_TYPE_GLIST;
01234     retval->value.list = value;
01235     return retval;
01236 }

KvpFrame* kvp_value_replace_frame_nc ( KvpValue value,
KvpFrame newframe 
)

Replace old frame value with new, return old frame

Definition at line 1437 of file kvp_frame.c.

01438 {
01439     KvpFrame *oldframe;
01440     if (!value) return NULL;
01441     if (KVP_TYPE_FRAME != value->type) return NULL;
01442 
01443     oldframe = value->value.frame;
01444     value->value.frame = newframe;
01445     return oldframe;
01446 }

GList* kvp_value_replace_glist_nc ( KvpValue value,
GList *  newlist 
)

Replace old glist value with new, return old glist

Definition at line 1449 of file kvp_frame.c.

01450 {
01451     GList *oldlist;
01452     if (!value) return NULL;
01453     if (KVP_TYPE_GLIST != value->type) return NULL;
01454 
01455     oldlist = value->value.list;
01456     value->value.list = newlist;
01457     return oldlist;
01458 }

gchar* kvp_value_to_bare_string ( const KvpValue val  ) 

General purpose function to convert any KvpValue to a string.

Only the bare string is returned, there is no debugging information.

Definition at line 1686 of file kvp_frame.c.

01687 {
01688     gchar *tmp1;
01689     gchar *tmp2;
01690     const gchar *ctmp;
01691 
01692     g_return_val_if_fail(val, NULL);
01693     tmp1 = g_strdup("");
01694     switch (kvp_value_get_type(val))
01695     {
01696     case KVP_TYPE_GINT64:
01697         return g_strdup_printf("%" G_GINT64_FORMAT, kvp_value_get_gint64(val));
01698         break;
01699 
01700     case KVP_TYPE_DOUBLE:
01701         return g_strdup_printf("(%g)", kvp_value_get_double(val));
01702         break;
01703 
01704     case KVP_TYPE_NUMERIC:
01705         tmp1 = gnc_numeric_to_string(kvp_value_get_numeric(val));
01706         tmp2 = g_strdup_printf("%s", tmp1 ? tmp1 : "");
01707         g_free(tmp1);
01708         return tmp2;
01709         break;
01710 
01711     case KVP_TYPE_STRING:
01712         tmp1 = kvp_value_get_string (val);
01713         return g_strdup_printf("%s", tmp1 ? tmp1 : "");
01714         break;
01715 
01716     case KVP_TYPE_GUID:
01717         ctmp = guid_to_string(kvp_value_get_guid(val));
01718         tmp2 = g_strdup_printf("%s", ctmp ? ctmp : "");
01719         return tmp2;
01720         break;
01721 
01722     case KVP_TYPE_TIMESPEC:
01723     {
01724         time_t t;
01725         t = timespecToTime_t(kvp_value_get_timespec(val));
01726         qof_date_format_set(QOF_DATE_FORMAT_UTC);
01727         return qof_print_date(t);
01728         break;
01729     }
01730     case KVP_TYPE_BINARY:
01731     {
01732         guint64 len;
01733         void *data;
01734         data = kvp_value_get_binary(val, &len);
01735         tmp1 = binary_to_string(data, len);
01736         return g_strdup_printf("%s", tmp1 ? tmp1 : "");
01737     }
01738     break;
01739 
01740     case KVP_TYPE_GLIST:
01741         /* borked. kvp_value_glist_to_string is a debug fcn */
01742     {
01743         tmp1 = kvp_value_glist_to_string(kvp_value_get_glist(val));
01744         tmp2 = g_strdup_printf("%s", tmp1 ? tmp1 : "");
01745         g_free(tmp1);
01746         return tmp2;
01747         break;
01748     }
01749     case KVP_TYPE_FRAME:
01750     {
01751         KvpFrame *frame;
01752 
01753         frame = kvp_value_get_frame(val);
01754         if (frame->hash)
01755         {
01756             tmp1 = g_strdup("");
01757             g_hash_table_foreach(frame->hash, kvp_frame_to_bare_string_helper, &tmp1);
01758         }
01759         return tmp1;
01760         break;
01761     }
01762     default:
01763         return g_strdup_printf(" ");
01764         break;
01765     }
01766 }

gchar* kvp_value_to_string ( const KvpValue val  ) 

Debug version of kvp_value_to_string.

This version is used only by qof_query_printValueForParam, itself a debugging and development utility function.

Definition at line 1769 of file kvp_frame.c.

01770 {
01771     gchar *tmp1;
01772     gchar *tmp2;
01773     const gchar *ctmp;
01774 
01775     g_return_val_if_fail(val, NULL);
01776 
01777     switch (kvp_value_get_type(val))
01778     {
01779     case KVP_TYPE_GINT64:
01780         return g_strdup_printf("KVP_VALUE_GINT64(%" G_GINT64_FORMAT ")",
01781                                kvp_value_get_gint64(val));
01782         break;
01783 
01784     case KVP_TYPE_DOUBLE:
01785         return g_strdup_printf("KVP_VALUE_DOUBLE(%g)",
01786                                kvp_value_get_double(val));
01787         break;
01788 
01789     case KVP_TYPE_NUMERIC:
01790         tmp1 = gnc_numeric_to_string(kvp_value_get_numeric(val));
01791         tmp2 = g_strdup_printf("KVP_VALUE_NUMERIC(%s)", tmp1 ? tmp1 : "");
01792         g_free(tmp1);
01793         return tmp2;
01794         break;
01795 
01796     case KVP_TYPE_STRING:
01797         tmp1 = kvp_value_get_string (val);
01798         return g_strdup_printf("KVP_VALUE_STRING(%s)", tmp1 ? tmp1 : "");
01799         break;
01800 
01801     case KVP_TYPE_GUID:
01802         /* THREAD-UNSAFE */
01803         ctmp = guid_to_string(kvp_value_get_guid(val));
01804         tmp2 = g_strdup_printf("KVP_VALUE_GUID(%s)", ctmp ? ctmp : "");
01805         return tmp2;
01806         break;
01807 
01808     case KVP_TYPE_TIMESPEC:
01809         tmp1 = g_new0 (char, 40);
01810         gnc_timespec_to_iso8601_buff (kvp_value_get_timespec (val), tmp1);
01811         tmp2 = g_strdup_printf("KVP_VALUE_TIMESPEC(%s)", tmp1);
01812         g_free(tmp1);
01813         return tmp2;
01814         break;
01815 
01816     case KVP_TYPE_BINARY:
01817     {
01818         guint64 len;
01819         void *data;
01820         data = kvp_value_get_binary(val, &len);
01821         tmp1 = binary_to_string(data, len);
01822         return g_strdup_printf("KVP_VALUE_BINARY(%s)", tmp1 ? tmp1 : "");
01823     }
01824     break;
01825 
01826     case KVP_TYPE_GLIST:
01827         tmp1 = kvp_value_glist_to_string(kvp_value_get_glist(val));
01828         tmp2 = g_strdup_printf("KVP_VALUE_GLIST(%s)", tmp1 ? tmp1 : "");
01829         g_free(tmp1);
01830         return tmp2;
01831         break;
01832 
01833     case KVP_TYPE_FRAME:
01834         tmp1 = kvp_frame_to_string(kvp_value_get_frame(val));
01835         tmp2 = g_strdup_printf("KVP_VALUE_FRAME(%s)", tmp1 ? tmp1 : "");
01836         g_free(tmp1);
01837         return tmp2;
01838         break;
01839 
01840     default:
01841         return g_strdup_printf(" ");
01842         break;
01843     }
01844 }


Generated on Wed Mar 17 04:47:15 2010 for GnuCash by  doxygen 1.5.7.1