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

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 
)

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

01820 {
01821     gchar *tmp1;
01822 
01823     g_return_val_if_fail (frame != NULL, NULL);
01824 
01825     tmp1 = g_strdup_printf("{\n");
01826 
01827     if (frame->hash)
01828       g_hash_table_foreach(frame->hash, kvp_frame_to_string_helper, &tmp1);
01829 
01830     {
01831         gchar *tmp2;
01832         tmp2 = g_strdup_printf("%s}\n", tmp1);
01833         g_free(tmp1);
01834         tmp1 = tmp2;
01835     }
01836 
01837     return tmp1;
01838 }

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

01058 {
01059   GList * retval = NULL;
01060   GList * lptr;
01061 
01062   if (!list) return retval;
01063   
01064   /* Duplicate the backbone of the list (this duplicates the POINTERS
01065    * to the values; we need to deep-copy the values separately) */
01066   retval = g_list_copy((GList *) list);
01067   
01068   /* This step deep-copies the values */
01069   for(lptr = retval; lptr; lptr = lptr->next) 
01070   {
01071     lptr->data = kvp_value_copy(lptr->data);
01072   }
01073   
01074   return retval;
01075 }

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

01041 {
01042   GList *node;
01043   if(!list) return;
01044   
01045   /* Delete the data in the list */
01046   for (node=list; node; node=node->next)
01047   {
01048     KvpValue *val = node->data;
01049     kvp_value_delete(val);
01050   }
01051   
01052   /* Free the backbone */
01053   g_list_free(list);
01054 }

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

01490 {
01491   if(kva == kvb) return 0;
01492   /* nothing is always less than something */
01493   if(!kva && kvb) return -1;
01494   if(kva && !kvb) return 1;
01495 
01496   if(kva->type < kvb->type) return -1;
01497   if(kva->type > kvb->type) return 1;
01498 
01499   switch(kva->type) {
01500   case KVP_TYPE_GINT64:
01501     if(kva->value.int64 < kvb->value.int64) return -1;
01502     if(kva->value.int64 > kvb->value.int64) return 1;
01503     return 0;
01504     break;
01505   case KVP_TYPE_DOUBLE:
01506     return double_compare(kva->value.dbl, kvb->value.dbl);
01507     break;
01508   case KVP_TYPE_NUMERIC:
01509     return gnc_numeric_compare (kva->value.numeric, kvb->value.numeric);
01510     break;
01511   case KVP_TYPE_STRING:
01512     return strcmp(kva->value.str, kvb->value.str);
01513     break;
01514   case KVP_TYPE_GUID:
01515     return guid_compare(kva->value.guid, kvb->value.guid);
01516     break;
01517   case KVP_TYPE_TIMESPEC:
01518     return timespec_cmp(&(kva->value.timespec), &(kvb->value.timespec));
01519     break;
01520   case KVP_TYPE_BINARY:
01521     /* I don't know that this is a good compare. Ab is bigger than Acef.
01522        But I'm not sure that actually matters here. */
01523     if(kva->value.binary.datasize < kvb->value.binary.datasize) return -1;
01524     if(kva->value.binary.datasize > kvb->value.binary.datasize) return 1;
01525     return memcmp(kva->value.binary.data,
01526                   kvb->value.binary.data,
01527                   kva->value.binary.datasize);
01528     break;
01529   case KVP_TYPE_GLIST:
01530     return kvp_glist_compare(kva->value.list, kvb->value.list);
01531     break;
01532   case KVP_TYPE_FRAME:
01533     return kvp_frame_compare(kva->value.frame, kvb->value.frame);
01534     break;
01535   }
01536   PERR ("reached unreachable code.");
01537   return FALSE;
01538 }

KvpValue* kvp_value_copy ( const KvpValue value  ) 

This is a deep value copy.

Definition at line 1428 of file kvp_frame.c.

01429 {
01430   if(!value) return NULL;
01431 
01432   switch(value->type) {
01433   case KVP_TYPE_GINT64:
01434     return kvp_value_new_gint64(value->value.int64);
01435     break;
01436   case KVP_TYPE_DOUBLE:
01437     return kvp_value_new_double(value->value.dbl);
01438     break;
01439   case KVP_TYPE_NUMERIC:
01440     return kvp_value_new_gnc_numeric(value->value.numeric);
01441     break;
01442   case KVP_TYPE_STRING:
01443     return kvp_value_new_string(value->value.str);
01444     break;
01445   case KVP_TYPE_GUID:
01446     return kvp_value_new_guid(value->value.guid);
01447     break;
01448   case KVP_TYPE_TIMESPEC:
01449     return kvp_value_new_timespec(value->value.timespec);
01450     break;
01451   case KVP_TYPE_BINARY:
01452     return kvp_value_new_binary(value->value.binary.data,
01453                                 value->value.binary.datasize);
01454     break;
01455   case KVP_TYPE_GLIST:
01456     return kvp_value_new_glist(value->value.list);
01457     break;
01458   case KVP_TYPE_FRAME:
01459     return kvp_value_new_frame(value->value.frame);
01460     break;
01461   }  
01462   return NULL;
01463 }

void kvp_value_delete ( KvpValue value  ) 

This is a deep (recursive) delete.

Definition at line 1246 of file kvp_frame.c.

01247 {
01248   if(!value) return;
01249 
01250   switch(value->type) 
01251   {
01252   case KVP_TYPE_STRING:
01253     g_free(value->value.str);
01254     break;
01255   case KVP_TYPE_GUID:
01256     g_free(value->value.guid);
01257     break;
01258   case KVP_TYPE_BINARY:
01259     g_free(value->value.binary.data);
01260     break;
01261   case KVP_TYPE_GLIST:
01262     kvp_glist_delete(value->value.list);
01263     break;
01264   case KVP_TYPE_FRAME:
01265     kvp_frame_delete(value->value.frame);
01266     break;
01267     
01268   case KVP_TYPE_GINT64:    
01269   case KVP_TYPE_DOUBLE:
01270   case KVP_TYPE_NUMERIC:
01271   default:
01272     break;
01273   }
01274   g_free(value);
01275 }

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

01357 {
01358   if (!value)
01359   {
01360     if (size_return)
01361       *size_return = 0;
01362     return NULL;
01363   }
01364 
01365   if(value->type == KVP_TYPE_BINARY) {
01366     if (size_return)
01367       *size_return = value->value.binary.datasize;
01368     return value->value.binary.data;
01369   }
01370   else {
01371     if (size_return)
01372       *size_return = 0;
01373     return NULL;
01374   }
01375 }

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

01391 {
01392   if (!value) return NULL;
01393   if(value->type == KVP_TYPE_FRAME) {
01394     return value->value.frame;
01395   }
01396   else {
01397     return NULL;
01398   }
01399 }

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

01286 {
01287   if (!value) return 0;
01288   if(value->type == KVP_TYPE_GINT64) {
01289     return value->value.int64;
01290   }
01291   else {
01292     return 0;
01293   }
01294 }

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

01379 {
01380   if (!value) return NULL;
01381   if(value->type == KVP_TYPE_GLIST) {
01382     return value->value.list;
01383   }
01384   else {
01385     return NULL;
01386   }
01387 }

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

01334 {
01335   if (!value) return NULL;
01336   if(value->type == KVP_TYPE_GUID) {
01337     return value->value.guid;
01338   }
01339   else {
01340     return NULL;
01341   }
01342 }

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

01322 {
01323   if (!value) return NULL;
01324   if(value->type == KVP_TYPE_STRING) {
01325     return value->value.str;
01326   }
01327   else { 
01328     return NULL; 
01329   }
01330 }

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

01186 {
01187   KvpValue * retval;
01188   if (!value) return NULL;
01189 
01190   retval = g_new0(KvpValue, 1);
01191   retval->type = KVP_TYPE_BINARY;
01192   retval->value.binary.data = value;
01193   retval->value.binary.datasize = datasize;
01194   return retval;
01195 }

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

01235 {
01236   KvpValue * retval;
01237   if (!value) return NULL;
01238 
01239   retval  = g_new0(KvpValue, 1);
01240   retval->type        = KVP_TYPE_FRAME;
01241   retval->value.frame = value;
01242   return retval;  
01243 }

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

01199 {
01200   KvpValue * retval;
01201   if (!value) return NULL;
01202 
01203   retval = g_new0(KvpValue, 1);
01204   retval->type       = KVP_TYPE_GLIST;
01205   retval->value.list = kvp_glist_copy(value);
01206   return retval;
01207 }  

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

01211 {
01212   KvpValue * retval;
01213   if (!value) return NULL;
01214 
01215   retval = g_new0(KvpValue, 1);
01216   retval->type       = KVP_TYPE_GLIST;
01217   retval->value.list = value;
01218   return retval;
01219 }  

KvpFrame* kvp_value_replace_frame_nc ( KvpValue value,
KvpFrame newframe 
)

Replace old frame value with new, return old frame

Definition at line 1402 of file kvp_frame.c.

01403 {
01404   KvpFrame *oldframe;
01405   if (!value) return NULL;
01406   if (KVP_TYPE_FRAME != value->type) return NULL;
01407 
01408   oldframe = value->value.frame;
01409   value->value.frame = newframe;
01410   return oldframe;  
01411 }

GList* kvp_value_replace_glist_nc ( KvpValue value,
GList *  newlist 
)

Replace old glist value with new, return old glist

Definition at line 1414 of file kvp_frame.c.

01415 {
01416   GList *oldlist;
01417   if (!value) return NULL;
01418   if (KVP_TYPE_GLIST != value->type) return NULL;
01419 
01420   oldlist = value->value.list;
01421   value->value.list = newlist;
01422   return oldlist;
01423 }

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

01642 {
01643     gchar *tmp1;
01644     gchar *tmp2;
01645     const gchar *ctmp;
01646     
01647     g_return_val_if_fail(val, NULL);
01648     tmp1 = g_strdup("");
01649     switch(kvp_value_get_type(val))
01650     {
01651     case KVP_TYPE_GINT64:
01652         return g_strdup_printf("%" G_GINT64_FORMAT, kvp_value_get_gint64(val));
01653         break;
01654 
01655     case KVP_TYPE_DOUBLE:
01656         return g_strdup_printf("(%g)", kvp_value_get_double(val));
01657         break;
01658 
01659     case KVP_TYPE_NUMERIC:
01660         tmp1 = gnc_numeric_to_string(kvp_value_get_numeric(val));
01661         tmp2 = g_strdup_printf("%s", tmp1 ? tmp1 : "");
01662         g_free(tmp1);
01663         return tmp2;
01664         break;
01665 
01666     case KVP_TYPE_STRING:
01667         tmp1 = kvp_value_get_string (val);
01668         return g_strdup_printf("%s", tmp1 ? tmp1 : "");
01669         break;
01670 
01671     case KVP_TYPE_GUID:
01672         ctmp = guid_to_string(kvp_value_get_guid(val));
01673         tmp2 = g_strdup_printf("%s", ctmp ? ctmp : "");
01674         return tmp2;
01675         break;
01676 
01677     case KVP_TYPE_TIMESPEC:
01678         {
01679                 time_t t;
01680                 t = timespecToTime_t(kvp_value_get_timespec(val));
01681         qof_date_format_set(QOF_DATE_FORMAT_UTC);
01682         return qof_print_date(t);
01683         break;
01684         }
01685     case KVP_TYPE_BINARY:
01686     {
01687         guint64 len;
01688         void *data;
01689         data = kvp_value_get_binary(val, &len);
01690         tmp1 = binary_to_string(data, len);
01691         return g_strdup_printf("%s", tmp1 ? tmp1 : "");
01692     }
01693         break;
01694  
01695     case KVP_TYPE_GLIST:
01696                 /* borked. kvp_value_glist_to_string is a debug fcn */
01697         {
01698         tmp1 = kvp_value_glist_to_string(kvp_value_get_glist(val));
01699         tmp2 = g_strdup_printf("%s", tmp1 ? tmp1 : "");
01700         g_free(tmp1);
01701         return tmp2;
01702         break;
01703         }
01704     case KVP_TYPE_FRAME:
01705         {
01706                 KvpFrame *frame;
01707 
01708                 frame = kvp_value_get_frame(val);
01709                 if (frame->hash) {
01710                         tmp1 = g_strdup("");
01711                         g_hash_table_foreach(frame->hash, kvp_frame_to_bare_string_helper, &tmp1);
01712                 }
01713         return tmp1;
01714         break;
01715         }
01716     default:
01717         return g_strdup_printf(" ");
01718         break;
01719     }
01720 }

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

01724 {
01725     gchar *tmp1;
01726     gchar *tmp2;
01727     const gchar *ctmp;
01728     
01729     g_return_val_if_fail(val, NULL);
01730     
01731     switch(kvp_value_get_type(val))
01732     {
01733     case KVP_TYPE_GINT64:
01734         return g_strdup_printf("KVP_VALUE_GINT64(%" G_GINT64_FORMAT ")",
01735                                kvp_value_get_gint64(val));
01736         break;
01737 
01738     case KVP_TYPE_DOUBLE:
01739         return g_strdup_printf("KVP_VALUE_DOUBLE(%g)",
01740                                kvp_value_get_double(val));
01741         break;
01742 
01743     case KVP_TYPE_NUMERIC:
01744         tmp1 = gnc_numeric_to_string(kvp_value_get_numeric(val));
01745         tmp2 = g_strdup_printf("KVP_VALUE_NUMERIC(%s)", tmp1 ? tmp1 : "");
01746         g_free(tmp1);
01747         return tmp2;
01748         break;
01749 
01750     case KVP_TYPE_STRING:
01751         tmp1 = kvp_value_get_string (val);
01752         return g_strdup_printf("KVP_VALUE_STRING(%s)", tmp1 ? tmp1 : "");
01753         break;
01754 
01755     case KVP_TYPE_GUID:
01756                 /* THREAD-UNSAFE */
01757         ctmp = guid_to_string(kvp_value_get_guid(val));
01758         tmp2 = g_strdup_printf("KVP_VALUE_GUID(%s)", ctmp ? ctmp : "");
01759         return tmp2;
01760         break;
01761 
01762     case KVP_TYPE_TIMESPEC:
01763         tmp1 = g_new0 (char, 40);
01764         gnc_timespec_to_iso8601_buff (kvp_value_get_timespec (val), tmp1);
01765         tmp2 = g_strdup_printf("KVP_VALUE_TIMESPEC(%s)", tmp1);
01766         g_free(tmp1);
01767         return tmp2;
01768         break;
01769 
01770     case KVP_TYPE_BINARY:
01771     {
01772         guint64 len;
01773         void *data;
01774         data = kvp_value_get_binary(val, &len);
01775         tmp1 = binary_to_string(data, len);
01776         return g_strdup_printf("KVP_VALUE_BINARY(%s)", tmp1 ? tmp1 : "");
01777     }
01778         break;
01779  
01780     case KVP_TYPE_GLIST:
01781         tmp1 = kvp_value_glist_to_string(kvp_value_get_glist(val));
01782         tmp2 = g_strdup_printf("KVP_VALUE_GLIST(%s)", tmp1 ? tmp1 : "");
01783         g_free(tmp1);
01784         return tmp2;
01785         break;
01786 
01787     case KVP_TYPE_FRAME:
01788         tmp1 = kvp_frame_to_string(kvp_value_get_frame(val));
01789         tmp2 = g_strdup_printf("KVP_VALUE_FRAME(%s)", tmp1 ? tmp1 : "");
01790         g_free(tmp1);
01791         return tmp2;
01792         break;
01793 
01794     default:
01795         return g_strdup_printf(" ");
01796         break;
01797     }
01798 }


Generated on Sat Jul 4 04:36:46 2009 for GnuCash by  doxygen 1.5.7.1