00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "config.h"
00027
00028 #include <glib.h>
00029 #include <stdarg.h>
00030 #include <stdio.h>
00031 #include <string.h>
00032 #include "qof.h"
00033
00034
00035
00036
00037
00038 struct _KvpFrame
00039 {
00040 GHashTable *hash;
00041 };
00042
00043 typedef struct
00044 {
00045 gpointer data;
00046 gint64 datasize;
00047 } KvpValueBinaryData;
00048
00049 struct _KvpValue
00050 {
00051 KvpValueType type;
00052 union
00053 {
00054 gint64 int64;
00055 gdouble dbl;
00056 QofNumeric numeric;
00057 gchar *str;
00058 GUID *guid;
00059 QofTime *qt;
00060 gboolean gbool;
00061 #ifndef QOF_DISABLE_DEPRECATED
00062 Timespec timespec;
00063 #endif
00064 KvpValueBinaryData binary;
00065 GList *list;
00066 KvpFrame *frame;
00067 } value;
00068 };
00069
00070
00071 static QofLogModule log_module = QOF_MOD_KVP;
00072
00073
00074
00075
00076
00077 static guint
00078 kvp_hash_func (gconstpointer v)
00079 {
00080 return g_str_hash (v);
00081 }
00082
00083 static gint
00084 kvp_comp_func (gconstpointer v, gconstpointer v2)
00085 {
00086 return g_str_equal (v, v2);
00087 }
00088
00089 static gboolean
00090 init_frame_body_if_needed (KvpFrame * f)
00091 {
00092 if (!f->hash)
00093 {
00094 f->hash = g_hash_table_new (&kvp_hash_func, &kvp_comp_func);
00095 }
00096 return (f->hash != NULL);
00097 }
00098
00099 KvpFrame *
00100 kvp_frame_new (void)
00101 {
00102 KvpFrame *retval = g_new0 (KvpFrame, 1);
00103
00104
00105 retval->hash = NULL;
00106 return retval;
00107 }
00108
00109 static void
00110 kvp_frame_delete_worker (gpointer key, gpointer value,
00111 gpointer user_data __attribute__ ((unused)))
00112 {
00113 qof_util_string_cache_remove (key);
00114 kvp_value_delete ((KvpValue *) value);
00115 }
00116
00117 void
00118 kvp_frame_delete (KvpFrame * frame)
00119 {
00120 if (!frame)
00121 return;
00122
00123 if (frame->hash)
00124 {
00125
00126 g_hash_table_foreach (frame->hash, &kvp_frame_delete_worker,
00127 (gpointer) frame);
00128
00129
00130 g_hash_table_destroy (frame->hash);
00131 frame->hash = NULL;
00132 }
00133 g_free (frame);
00134 }
00135
00136 gboolean
00137 kvp_frame_is_empty (KvpFrame * frame)
00138 {
00139 if (!frame)
00140 return TRUE;
00141 if (!frame->hash)
00142 return TRUE;
00143 return FALSE;
00144 }
00145
00146 static void
00147 kvp_frame_copy_worker (gpointer key, gpointer value, gpointer user_data)
00148 {
00149 KvpFrame *dest = (KvpFrame *) user_data;
00150 g_hash_table_insert (dest->hash,
00151 qof_util_string_cache_insert (key),
00152 (gpointer) kvp_value_copy (value));
00153 }
00154
00155 KvpFrame *
00156 kvp_frame_copy (const KvpFrame * frame)
00157 {
00158 KvpFrame *retval = kvp_frame_new ();
00159
00160 if (!frame)
00161 return retval;
00162
00163 if (frame->hash)
00164 {
00165 if (!init_frame_body_if_needed (retval))
00166 return (NULL);
00167 g_hash_table_foreach (frame->hash,
00168 &kvp_frame_copy_worker, (gpointer) retval);
00169 }
00170 return retval;
00171 }
00172
00173
00174
00175
00176
00177 KvpValue *
00178 kvp_frame_replace_slot_nc (KvpFrame * frame, const gchar *slot,
00179 KvpValue * new_value)
00180 {
00181 gpointer orig_key;
00182 gpointer orig_value = NULL;
00183 int key_exists;
00184
00185 if (!frame || !slot)
00186 return NULL;
00187 if (!init_frame_body_if_needed (frame))
00188 return NULL;
00189
00190 key_exists = g_hash_table_lookup_extended (frame->hash, slot,
00191 &orig_key, &orig_value);
00192 if (key_exists)
00193 {
00194 g_hash_table_remove (frame->hash, slot);
00195 qof_util_string_cache_remove (orig_key);
00196 }
00197 else
00198 orig_value = NULL;
00199 if (new_value)
00200 g_hash_table_insert (frame->hash,
00201 qof_util_string_cache_insert ((gpointer) slot), new_value);
00202 return (KvpValue *) orig_value;
00203 }
00204
00205
00206
00207
00208 static inline void
00209 kvp_frame_set_slot_destructively (KvpFrame * frame, const gchar *slot,
00210 KvpValue * new_value)
00211 {
00212 KvpValue *old_value;
00213 old_value = kvp_frame_replace_slot_nc (frame, slot, new_value);
00214 kvp_value_delete (old_value);
00215 }
00216
00217
00218
00219
00220
00221
00222 static inline KvpFrame *
00223 get_or_make (KvpFrame * fr, const gchar *key)
00224 {
00225 KvpFrame *next_frame;
00226 KvpValue *value;
00227
00228 value = kvp_frame_get_slot (fr, key);
00229 if (value)
00230 next_frame = kvp_value_get_frame (value);
00231 else
00232 {
00233 next_frame = kvp_frame_new ();
00234 kvp_frame_set_slot_nc (fr, key,
00235 kvp_value_new_frame_nc (next_frame));
00236 }
00237 return next_frame;
00238 }
00239
00240
00241
00242
00243
00244 static inline KvpFrame *
00245 kvp_frame_get_frame_slash_trash (KvpFrame * frame, gchar *key_path)
00246 {
00247 gchar *key, *next;
00248 if (!frame || !key_path)
00249 return frame;
00250
00251 key = key_path;
00252 key--;
00253
00254 while (key)
00255 {
00256 key++;
00257 while ('/' == *key)
00258 key++;
00259 if (0x0 == *key)
00260 break;
00261 next = strchr (key, '/');
00262 if (next)
00263 *next = 0x0;
00264
00265 frame = get_or_make (frame, key);
00266 if (!frame)
00267 break;
00268
00269 key = next;
00270 }
00271 return frame;
00272 }
00273
00274
00275
00276
00277
00278 static inline const KvpFrame *
00279 kvp_frame_get_frame_or_null_slash_trash (const KvpFrame * frame,
00280 gchar *key_path)
00281 {
00282 KvpValue *value;
00283 gchar *key, *next;
00284 if (!frame || !key_path)
00285 return NULL;
00286
00287 key = key_path;
00288 key--;
00289
00290 while (key)
00291 {
00292 key++;
00293 while ('/' == *key)
00294 key++;
00295 if (0x0 == *key)
00296 break;
00297 next = strchr (key, '/');
00298 if (next)
00299 *next = 0x0;
00300
00301 value = kvp_frame_get_slot (frame, key);
00302 if (!value)
00303 return NULL;
00304 frame = kvp_value_get_frame (value);
00305 if (!frame)
00306 return NULL;
00307
00308 key = next;
00309 }
00310 return frame;
00311 }
00312
00313
00314
00315
00316
00317
00318 static inline KvpFrame *
00319 get_trailer_make (KvpFrame * frame, const gchar *key_path,
00320 gchar **end_key)
00321 {
00322 gchar *last_key;
00323
00324 if (!frame || !key_path || (0 == key_path[0]))
00325 return NULL;
00326
00327 last_key = strrchr (key_path, '/');
00328 if (NULL == last_key)
00329 last_key = (gchar *) key_path;
00330 else if (last_key == key_path)
00331 last_key++;
00332 else if (0 == last_key[1])
00333 return NULL;
00334 else
00335 {
00336 gchar *root, *lkey;
00337 root = g_strdup (key_path);
00338 lkey = strrchr (root, '/');
00339 *lkey = 0;
00340 frame = kvp_frame_get_frame_slash_trash (frame, root);
00341 g_free (root);
00342 last_key++;
00343 }
00344
00345 *end_key = last_key;
00346 return frame;
00347 }
00348
00349
00350
00351
00352
00353
00354
00355 static inline const KvpFrame *
00356 get_trailer_or_null (const KvpFrame * frame, const gchar *key_path,
00357 gchar **end_key)
00358 {
00359 gchar *last_key;
00360
00361 if (!frame || !key_path || (0 == key_path[0]))
00362 return NULL;
00363
00364 last_key = strrchr (key_path, '/');
00365 if (NULL == last_key)
00366 last_key = (gchar *) key_path;
00367 else if (last_key == key_path)
00368 last_key++;
00369 else if (0 == last_key[1])
00370 return NULL;
00371 else
00372 {
00373 gchar *root, *lkey;
00374 root = g_strdup (key_path);
00375 lkey = strrchr (root, '/');
00376 *lkey = 0;
00377 frame = kvp_frame_get_frame_or_null_slash_trash (frame, root);
00378 g_free (root);
00379
00380 last_key++;
00381 }
00382
00383 *end_key = last_key;
00384 return frame;
00385 }
00386
00387
00388
00389 void
00390 kvp_frame_set_gint64 (KvpFrame * frame, const gchar *path, gint64 ival)
00391 {
00392 KvpValue *value;
00393 value = kvp_value_new_gint64 (ival);
00394 frame = kvp_frame_set_value_nc (frame, path, value);
00395 if (!frame)
00396 kvp_value_delete (value);
00397 }
00398
00399 void
00400 kvp_frame_set_double (KvpFrame * frame, const gchar *path, gdouble dval)
00401 {
00402 KvpValue *value;
00403 value = kvp_value_new_double (dval);
00404 frame = kvp_frame_set_value_nc (frame, path, value);
00405 if (!frame)
00406 kvp_value_delete (value);
00407 }
00408
00409 void
00410 kvp_frame_set_time (KvpFrame * frame, const gchar *path, QofTime *qt)
00411 {
00412 KvpValue *value;
00413 value = kvp_value_new_time (qt);
00414 frame = kvp_frame_set_value_nc (frame, path, value);
00415 if (!frame)
00416 kvp_value_delete (value);
00417 }
00418
00419 void
00420 kvp_frame_set_numeric (KvpFrame * frame, const gchar *path,
00421 QofNumeric nval)
00422 {
00423 KvpValue *value;
00424 value = kvp_value_new_numeric (nval);
00425 frame = kvp_frame_set_value_nc (frame, path, value);
00426 if (!frame)
00427 kvp_value_delete (value);
00428 }
00429
00430 void
00431 kvp_frame_set_boolean (KvpFrame * frame, const gchar * path,
00432 gboolean val)
00433 {
00434 KvpValue * value;
00435 value = kvp_value_new_boolean (val);
00436 frame = kvp_frame_set_value_nc (frame, path, value);
00437 if (!frame)
00438 kvp_value_delete (value);
00439 }
00440
00441 void
00442 kvp_frame_set_string (KvpFrame * frame, const gchar *path,
00443 const gchar *str)
00444 {
00445 KvpValue *value;
00446 value = kvp_value_new_string (str);
00447 frame = kvp_frame_set_value_nc (frame, path, value);
00448 if (!frame)
00449 kvp_value_delete (value);
00450 }
00451
00452 void
00453 kvp_frame_set_guid (KvpFrame * frame, const gchar *path,
00454 const GUID * guid)
00455 {
00456 KvpValue *value;
00457 value = kvp_value_new_guid (guid);
00458 frame = kvp_frame_set_value_nc (frame, path, value);
00459 if (!frame)
00460 kvp_value_delete (value);
00461 }
00462
00463 void
00464 kvp_frame_set_frame (KvpFrame * frame, const gchar *path, KvpFrame * fr)
00465 {
00466 KvpValue *value;
00467 value = kvp_value_new_frame (fr);
00468 frame = kvp_frame_set_value_nc (frame, path, value);
00469 if (!frame)
00470 kvp_value_delete (value);
00471 }
00472
00473 void
00474 kvp_frame_set_frame_nc (KvpFrame * frame, const gchar *path, KvpFrame * fr)
00475 {
00476 KvpValue *value;
00477 value = kvp_value_new_frame_nc (fr);
00478 frame = kvp_frame_set_value_nc (frame, path, value);
00479 if (!frame)
00480 kvp_value_delete (value);
00481 }
00482
00483
00484
00485 KvpFrame *
00486 kvp_frame_set_value_nc (KvpFrame * frame, const gchar *key_path,
00487 KvpValue * value)
00488 {
00489 gchar *last_key;
00490
00491 frame = get_trailer_make (frame, key_path, &last_key);
00492 if (!frame)
00493 return NULL;
00494 kvp_frame_set_slot_destructively (frame, last_key, value);
00495 return frame;
00496 }
00497
00498 KvpFrame *
00499 kvp_frame_set_value (KvpFrame * frame, const gchar *key_path,
00500 const KvpValue * value)
00501 {
00502 KvpValue *new_value = NULL;
00503 gchar *last_key;
00504
00505 frame = get_trailer_make (frame, key_path, &last_key);
00506 if (!frame)
00507 return NULL;
00508
00509 if (value)
00510 new_value = kvp_value_copy (value);
00511 kvp_frame_set_slot_destructively (frame, last_key, new_value);
00512 return frame;
00513 }
00514
00515 KvpValue *
00516 kvp_frame_replace_value_nc (KvpFrame * frame, const gchar *key_path,
00517 KvpValue * new_value)
00518 {
00519 KvpValue *old_value;
00520 gchar *last_key;
00521
00522 last_key = NULL;
00523 if (new_value)
00524 frame = get_trailer_make (frame, key_path, &last_key);
00525 else
00526 frame =
00527 (KvpFrame *) get_trailer_or_null (frame, key_path, &last_key);
00528 if (!frame)
00529 return NULL;
00530
00531 old_value = kvp_frame_replace_slot_nc (frame, last_key, new_value);
00532 return old_value;
00533 }
00534
00535
00536
00537 KvpFrame *
00538 kvp_frame_add_value_nc (KvpFrame * frame, const gchar *path,
00539 KvpValue * value)
00540 {
00541 gchar *key = NULL;
00542 KvpValue *oldvalue;
00543
00544 frame = (KvpFrame *) get_trailer_or_null (frame, path, &key);
00545 oldvalue = kvp_frame_get_slot (frame, key);
00546
00547 ENTER ("old frame=%s", kvp_frame_to_string (frame));
00548 if (oldvalue)
00549 {
00550
00551 if (KVP_TYPE_GLIST == oldvalue->type)
00552 {
00553 GList *vlist = oldvalue->value.list;
00554 vlist = g_list_append (vlist, value);
00555 oldvalue->value.list = vlist;
00556 }
00557 else
00558
00559 {
00560 KvpValue *klist;
00561 GList *vlist = NULL;
00562
00563 vlist = g_list_append (vlist, oldvalue);
00564 vlist = g_list_append (vlist, value);
00565 klist = kvp_value_new_glist_nc (vlist);
00566
00567 kvp_frame_replace_slot_nc (frame, key, klist);
00568 }
00569 LEAVE ("new frame=%s", kvp_frame_to_string (frame));
00570 return frame;
00571 }
00572
00573
00574
00575 frame = kvp_frame_set_value_nc (frame, path, value);
00576 LEAVE ("new frame=%s", kvp_frame_to_string (frame));
00577 return frame;
00578 }
00579
00580 KvpFrame *
00581 kvp_frame_add_value (KvpFrame * frame, const gchar *path, KvpValue * value)
00582 {
00583 value = kvp_value_copy (value);
00584 frame = kvp_frame_add_value_nc (frame, path, value);
00585 if (!frame)
00586 kvp_value_delete (value);
00587 return frame;
00588 }
00589
00590 void
00591 kvp_frame_add_gint64 (KvpFrame * frame, const gchar *path, gint64 ival)
00592 {
00593 KvpValue *value;
00594 value = kvp_value_new_gint64 (ival);
00595 frame = kvp_frame_add_value_nc (frame, path, value);
00596 if (!frame)
00597 kvp_value_delete (value);
00598 }
00599
00600 void
00601 kvp_frame_add_double (KvpFrame * frame, const gchar *path, gdouble dval)
00602 {
00603 KvpValue *value;
00604 value = kvp_value_new_double (dval);
00605 frame = kvp_frame_add_value_nc (frame, path, value);
00606 if (!frame)
00607 kvp_value_delete (value);
00608 }
00609
00610 void
00611 kvp_frame_add_numeric (KvpFrame * frame, const gchar *path,
00612 QofNumeric nval)
00613 {
00614 KvpValue *value;
00615 value = kvp_value_new_numeric (nval);
00616 frame = kvp_frame_add_value_nc (frame, path, value);
00617 if (!frame)
00618 kvp_value_delete (value);
00619 }
00620
00621 void
00622 kvp_frame_add_time (KvpFrame * frame, const gchar *path, QofTime *qt)
00623 {
00624 KvpValue *value;
00625 value = kvp_value_new_time (qt);
00626 frame = kvp_frame_add_value_nc (frame, path, value);
00627 if (!frame)
00628 kvp_value_delete (value);
00629 }
00630
00631 void
00632 kvp_frame_add_boolean (KvpFrame * frame, const gchar * path, gboolean val)
00633 {
00634 KvpValue * value;
00635 value = kvp_value_new_boolean (val);
00636 frame = kvp_frame_add_value_nc (frame, path, value);
00637 if (!frame)
00638 kvp_value_delete (value);
00639 }
00640
00641 void
00642 kvp_frame_add_string (KvpFrame * frame, const gchar *path, const gchar *str)
00643 {
00644 KvpValue *value;
00645 value = kvp_value_new_string (str);
00646 frame = kvp_frame_add_value_nc (frame, path, value);
00647 if (!frame)
00648 kvp_value_delete (value);
00649 }
00650
00651 void
00652 kvp_frame_add_guid (KvpFrame * frame, const gchar *path, const GUID * guid)
00653 {
00654 KvpValue *value;
00655 value = kvp_value_new_guid (guid);
00656 frame = kvp_frame_add_value_nc (frame, path, value);
00657 if (!frame)
00658 kvp_value_delete (value);
00659 }
00660
00661 void
00662 kvp_frame_add_frame (KvpFrame * frame, const gchar *path, KvpFrame * fr)
00663 {
00664 KvpValue *value;
00665 value = kvp_value_new_frame (fr);
00666 frame = kvp_frame_add_value_nc (frame, path, value);
00667 if (!frame)
00668 kvp_value_delete (value);
00669 }
00670
00671 void
00672 kvp_frame_add_frame_nc (KvpFrame * frame, const gchar *path, KvpFrame * fr)
00673 {
00674 KvpValue *value;
00675 value = kvp_value_new_frame_nc (fr);
00676 frame = kvp_frame_add_value_nc (frame, path, value);
00677 if (!frame)
00678 kvp_value_delete (value);
00679 }
00680
00681
00682
00683 void
00684 kvp_frame_set_slot (KvpFrame * frame, const gchar *slot,
00685 const KvpValue * value)
00686 {
00687 KvpValue *new_value = NULL;
00688
00689 if (!frame)
00690 return;
00691
00692 g_return_if_fail (slot && *slot != '\0');
00693
00694 if (value)
00695 new_value = kvp_value_copy (value);
00696 kvp_frame_set_slot_destructively (frame, slot, new_value);
00697 }
00698
00699 void
00700 kvp_frame_set_slot_nc (KvpFrame * frame, const gchar *slot,
00701 KvpValue * value)
00702 {
00703 if (!frame)
00704 return;
00705
00706 g_return_if_fail (slot && *slot != '\0');
00707
00708 kvp_frame_set_slot_destructively (frame, slot, value);
00709 }
00710
00711 KvpValue *
00712 kvp_frame_get_slot (const KvpFrame * frame, const gchar *slot)
00713 {
00714 KvpValue *v;
00715 if (!frame)
00716 return NULL;
00717 if (!frame->hash)
00718 return NULL;
00719 v = g_hash_table_lookup (frame->hash, slot);
00720 return v;
00721 }
00722
00723
00724
00725 void
00726 kvp_frame_set_slot_path (KvpFrame * frame,
00727 const KvpValue * new_value, const gchar *first_key, ...)
00728 {
00729 va_list ap;
00730 const gchar *key;
00731
00732 if (!frame)
00733 return;
00734
00735 g_return_if_fail (first_key && *first_key != '\0');
00736
00737 va_start (ap, first_key);
00738
00739 key = first_key;
00740
00741 while (TRUE)
00742 {
00743 KvpValue *value;
00744 const gchar *next_key;
00745
00746 next_key = va_arg (ap, const gchar *);
00747 if (!next_key)
00748 {
00749 kvp_frame_set_slot (frame, key, new_value);
00750 break;
00751 }
00752
00753 g_return_if_fail (*next_key != '\0');
00754
00755 value = kvp_frame_get_slot (frame, key);
00756 if (!value)
00757 {
00758 KvpFrame *new_frame = kvp_frame_new ();
00759 KvpValue *frame_value = kvp_value_new_frame (new_frame);
00760
00761 kvp_frame_set_slot_nc (frame, key, frame_value);
00762
00763 value = kvp_frame_get_slot (frame, key);
00764 if (!value)
00765 break;
00766 }
00767
00768 frame = kvp_value_get_frame (value);
00769 if (!frame)
00770 break;
00771
00772 key = next_key;
00773 }
00774
00775 va_end (ap);
00776 }
00777
00778 void
00779 kvp_frame_set_slot_path_gslist (KvpFrame * frame,
00780 const KvpValue * new_value, GSList * key_path)
00781 {
00782 if (!frame || !key_path)
00783 return;
00784
00785 while (TRUE)
00786 {
00787 const gchar *key = key_path->data;
00788 KvpValue *value;
00789
00790 if (!key)
00791 return;
00792
00793 g_return_if_fail (*key != '\0');
00794
00795 key_path = key_path->next;
00796 if (!key_path)
00797 {
00798 kvp_frame_set_slot (frame, key, new_value);
00799 return;
00800 }
00801
00802 value = kvp_frame_get_slot (frame, key);
00803 if (!value)
00804 {
00805 KvpFrame *new_frame = kvp_frame_new ();
00806 KvpValue *frame_value = kvp_value_new_frame (new_frame);
00807
00808 kvp_frame_set_slot_nc (frame, key, frame_value);
00809
00810 value = kvp_frame_get_slot (frame, key);
00811 if (!value)
00812 return;
00813 }
00814
00815 frame = kvp_value_get_frame (value);
00816 if (!frame)
00817 return;
00818 }
00819 }
00820
00821
00822
00823
00824
00825
00826
00827 static void
00828 decode (gchar *enc)
00829 {
00830 gchar *p, *w;
00831
00832
00833 p = strchr (enc, '+');
00834 while (p)
00835 {
00836 *p = ' ';
00837 p = strchr (p, '+');
00838 }
00839
00840 p = strchr (enc, '%');
00841 w = p;
00842
00843 while (p)
00844 {
00845 gint ch, cl;
00846 p++;
00847 ch = *p - 0x30;
00848 if (9 < ch)
00849 ch -= 0x11 - 10;
00850 if (16 < ch)
00851 ch -= 0x20;
00852
00853 p++;
00854 cl = *p - 0x30;
00855 if (9 < cl)
00856 cl -= 0x11 - 10;
00857 if (16 < cl)
00858 cl -= 0x20;
00859
00860 *w = (gchar) (ch << 4 | cl);
00861
00862 do
00863 {
00864 ++w;
00865 ++p;
00866 *w = *p;
00867 if (0x0 == *p)
00868 {
00869 p = 0;
00870 break;
00871 }
00872 if ('%' == *p)
00873 break;
00874 }
00875 while (*p);
00876 }
00877 }
00878
00879 void
00880 kvp_frame_add_url_encoding (KvpFrame * frame, const gchar *enc)
00881 {
00882 gchar *buff, *p;
00883 if (!frame || !enc)
00884 return;
00885
00886
00887 buff = g_strdup (enc);
00888 p = buff;
00889 while (*p)
00890 {
00891 gchar *n, *v;
00892 n = strchr (p, '&');
00893 if (n)
00894 *n = 0x0;
00895
00896 v = strchr (p, '=');
00897 if (!v)
00898 break;
00899 *v = 0x0;
00900 v++;
00901
00902 decode (p);
00903 decode (v);
00904 kvp_frame_set_slot_nc (frame, p, kvp_value_new_string (v));
00905
00906 if (!n)
00907 break;
00908 p = ++n;
00909 }
00910
00911 g_free (buff);
00912 }
00913
00914
00915
00916
00917 gint64
00918 kvp_frame_get_gint64 (const KvpFrame * frame, const gchar *path)
00919 {
00920 gchar *key = NULL;
00921 frame = get_trailer_or_null (frame, path, &key);
00922 return kvp_value_get_gint64 (kvp_frame_get_slot (frame, key));
00923 }
00924
00925 gdouble
00926 kvp_frame_get_double (const KvpFrame * frame, const gchar *path)
00927 {
00928 gchar *key = NULL;
00929 frame = get_trailer_or_null (frame, path, &key);
00930 return kvp_value_get_double (kvp_frame_get_slot (frame, key));
00931 }
00932
00933 QofNumeric
00934 kvp_frame_get_numeric (const KvpFrame * frame, const gchar *path)
00935 {
00936 gchar *key = NULL;
00937 frame = get_trailer_or_null (frame, path, &key);
00938 return kvp_value_get_numeric (kvp_frame_get_slot (frame, key));
00939 }
00940
00941 gchar *
00942 kvp_frame_get_string (const KvpFrame * frame, const gchar *path)
00943 {
00944 gchar *key = NULL;
00945 frame = get_trailer_or_null (frame, path, &key);
00946 return kvp_value_get_string (kvp_frame_get_slot (frame, key));
00947 }
00948
00949 gboolean
00950 kvp_frame_get_boolean (const KvpFrame * frame, const gchar * path)
00951 {
00952 gchar * key = NULL;
00953 frame = get_trailer_or_null (frame, path, &key);
00954 return kvp_value_get_boolean (kvp_frame_get_slot (frame, key));
00955 }
00956
00957 GUID *
00958 kvp_frame_get_guid (const KvpFrame * frame, const gchar *path)
00959 {
00960 gchar *key = NULL;
00961 frame = get_trailer_or_null (frame, path, &key);
00962 return kvp_value_get_guid (kvp_frame_get_slot (frame, key));
00963 }
00964
00965 void *
00966 kvp_frame_get_binary (const KvpFrame * frame, const gchar *path,
00967 guint64 * size_return)
00968 {
00969 gchar *key = NULL;
00970 frame = get_trailer_or_null (frame, path, &key);
00971 return kvp_value_get_binary (kvp_frame_get_slot (frame, key),
00972 size_return);
00973 }
00974
00975 QofTime *
00976 kvp_frame_get_time (const KvpFrame * frame, const gchar *path)
00977 {
00978 gchar *key = NULL;
00979 frame = get_trailer_or_null (frame, path, &key);
00980 return kvp_value_get_time (kvp_frame_get_slot (frame, key));
00981 }
00982
00983 KvpFrame *
00984 kvp_frame_get_frame (const KvpFrame * frame, const gchar *path)
00985 {
00986 gchar *key = NULL;
00987 frame = get_trailer_or_null (frame, path, &key);
00988 return kvp_value_get_frame (kvp_frame_get_slot (frame, key));
00989 }
00990
00991 KvpValue *
00992 kvp_frame_get_value (const KvpFrame * frame, const gchar *path)
00993 {
00994 gchar *key = NULL;
00995 frame = get_trailer_or_null (frame, path, &key);
00996 return kvp_frame_get_slot (frame, key);
00997 }
00998
00999
01000
01001 KvpFrame *
01002 kvp_frame_get_frame_gslist (KvpFrame * frame, GSList * key_path)
01003 {
01004 if (!frame)
01005 return frame;
01006
01007 while (key_path)
01008 {
01009 const gchar *key = key_path->data;
01010
01011 if (!key)
01012 return frame;
01013
01014 frame = get_or_make (frame, key);
01015 if (!frame)
01016 return frame;
01017
01018 key_path = key_path->next;
01019 }
01020 return frame;
01021 }
01022
01023 KvpFrame *
01024 kvp_frame_get_frame_path (KvpFrame * frame, const gchar *key, ...)
01025 {
01026 va_list ap;
01027 if (!frame || !key)
01028 return frame;
01029
01030 va_start (ap, key);
01031
01032 while (key)
01033 {
01034 frame = get_or_make (frame, key);
01035 if (!frame)
01036 break;
01037 key = va_arg (ap, const char *);
01038 }
01039
01040 va_end (ap);
01041 return frame;
01042 }
01043
01044 KvpFrame *
01045 kvp_frame_get_frame_slash (KvpFrame * frame, const gchar *key_path)
01046 {
01047 gchar *root;
01048 if (!frame || !key_path)
01049 return frame;
01050
01051 root = g_strdup (key_path);
01052 frame = kvp_frame_get_frame_slash_trash (frame, root);
01053 g_free (root);
01054 return frame;
01055 }
01056
01057
01058
01059 KvpValue *
01060 kvp_frame_get_slot_path (KvpFrame * frame, const gchar *first_key, ...)
01061 {
01062 va_list ap;
01063 KvpValue *value;
01064 const gchar *key;
01065
01066 if (!frame || !first_key)
01067 return NULL;
01068
01069 va_start (ap, first_key);
01070
01071 key = first_key;
01072 value = NULL;
01073
01074 while (TRUE)
01075 {
01076 value = kvp_frame_get_slot (frame, key);
01077 if (!value)
01078 break;
01079
01080 key = va_arg (ap, const gchar *);
01081 if (!key)
01082 break;
01083
01084 frame = kvp_value_get_frame (value);
01085 if (!frame)
01086 {
01087 value = NULL;
01088 break;
01089 }
01090 }
01091
01092 va_end (ap);
01093
01094 return value;
01095 }
01096
01097 KvpValue *
01098 kvp_frame_get_slot_path_gslist (KvpFrame * frame, GSList * key_path)
01099 {
01100 if (!frame || !key_path)
01101 return NULL;
01102
01103 while (TRUE)
01104 {
01105 const gchar *key = key_path->data;
01106 KvpValue *value;
01107
01108 if (!key)
01109 return NULL;
01110
01111 value = kvp_frame_get_slot (frame, key);
01112 if (!value)
01113 return NULL;
01114
01115 key_path = key_path->next;
01116 if (!key_path)
01117 return value;
01118
01119 frame = kvp_value_get_frame (value);
01120 if (!frame)
01121 return NULL;
01122 }
01123 }
01124
01125
01126
01127
01128
01129 void
01130 kvp_glist_delete (GList * list)
01131 {
01132 GList *node;
01133 if (!list)
01134 return;
01135
01136
01137 for (node = list; node; node = node->next)
01138 {
01139 KvpValue *val = node->data;
01140 kvp_value_delete (val);
01141 }
01142
01143
01144 g_list_free (list);
01145 }
01146
01147 GList *
01148 kvp_glist_copy (const GList * list)
01149 {
01150 GList *retval = NULL;
01151 GList *lptr;
01152
01153 if (!list)
01154 return retval;
01155
01156
01157
01158 retval = g_list_copy ((GList *) list);
01159
01160
01161 for (lptr = retval; lptr; lptr = lptr->next)
01162 {
01163 lptr->data = kvp_value_copy (lptr->data);
01164 }
01165
01166 return retval;
01167 }
01168
01169 gint
01170 kvp_glist_compare (const GList * list1, const GList * list2)
01171 {
01172 const GList *lp1;
01173 const GList *lp2;
01174
01175 if (list1 == list2)
01176 return 0;
01177
01178
01179 if (!list1 && list2)
01180 return -1;
01181 if (list1 && !list2)
01182 return 1;
01183
01184 lp1 = list1;
01185 lp2 = list2;
01186 while (lp1 && lp2)
01187 {
01188 KvpValue *v1 = (KvpValue *) lp1->data;
01189 KvpValue *v2 = (KvpValue *) lp2->data;
01190 gint vcmp = kvp_value_compare (v1, v2);
01191 if (vcmp != 0)
01192 return vcmp;
01193 lp1 = lp1->next;
01194 lp2 = lp2->next;
01195 }
01196 if (!lp1 && lp2)
01197 return -1;
01198 if (!lp2 && lp1)
01199 return 1;
01200 return 0;
01201 }
01202
01203
01204
01205
01206
01207 KvpValue *
01208 kvp_value_new_gint64 (gint64 value)
01209 {
01210 KvpValue *retval = g_new0 (KvpValue, 1);
01211 retval->type = KVP_TYPE_GINT64;
01212 retval->value.int64 = value;
01213 return retval;
01214 }
01215
01216 KvpValue *
01217 kvp_value_new_double (gdouble value)
01218 {
01219 KvpValue *retval = g_new0 (KvpValue, 1);
01220 retval->type = KVP_TYPE_DOUBLE;
01221 retval->value.dbl = value;
01222 return retval;
01223 }
01224
01225 KvpValue *
01226 kvp_value_new_boolean (gboolean value)
01227 {
01228 KvpValue * retval = g_new0 (KvpValue, 1);
01229 retval->type = KVP_TYPE_BOOLEAN;
01230 retval->value.gbool = value;
01231 return retval;
01232 }
01233
01234 KvpValue *
01235 kvp_value_new_numeric (QofNumeric value)
01236 {
01237 KvpValue *retval = g_new0 (KvpValue, 1);
01238 retval->type = KVP_TYPE_NUMERIC;
01239 retval->value.numeric = value;
01240 return retval;
01241 }
01242
01243 KvpValue *
01244 kvp_value_new_string (const gchar *value)
01245 {
01246 KvpValue *retval;
01247 if (!value)
01248 return NULL;
01249
01250 retval = g_new0 (KvpValue, 1);
01251 retval->type = KVP_TYPE_STRING;
01252 retval->value.str = g_strdup (value);
01253 return retval;
01254 }
01255
01256 KvpValue *
01257 kvp_value_new_guid (const GUID * value)
01258 {
01259 KvpValue *retval;
01260 if (!value)
01261 return NULL;
01262
01263 retval = g_new0 (KvpValue, 1);
01264 retval->type = KVP_TYPE_GUID;
01265 retval->value.guid = g_new0 (GUID, 1);
01266 memcpy (retval->value.guid, value, sizeof (GUID));
01267 return retval;
01268 }
01269
01270 KvpValue *
01271 kvp_value_new_time (QofTime *value)
01272 {
01273 KvpValue *retval = g_new0 (KvpValue, 1);
01274 retval->type = KVP_TYPE_TIME;
01275 retval->value.qt = value;
01276 return retval;
01277 }
01278
01279 KvpValue *
01280 kvp_value_new_binary (gconstpointer value, guint64 datasize)
01281 {
01282 KvpValue *retval;
01283 if (!value)
01284 return NULL;
01285
01286 retval = g_new0 (KvpValue, 1);
01287 retval->type = KVP_TYPE_BINARY;
01288 retval->value.binary.data = g_new0 (gpointer, datasize);
01289 retval->value.binary.datasize = datasize;
01290 memcpy (retval->value.binary.data, value, datasize);
01291 return retval;
01292 }
01293
01294 KvpValue *
01295 kvp_value_new_binary_nc (gpointer value, guint64 datasize)
01296 {
01297 KvpValue *retval;
01298 if (!value)
01299 return NULL;
01300
01301 retval = g_new0 (KvpValue, 1);
01302 retval->type = KVP_TYPE_BINARY;
01303 retval->value.binary.data = value;
01304 retval->value.binary.datasize = datasize;
01305 return retval;
01306 }
01307
01308 KvpValue *
01309 kvp_value_new_glist (const GList * value)
01310 {
01311 KvpValue *retval;
01312 if (!value)
01313 return NULL;
01314
01315 retval = g_new0 (KvpValue, 1);
01316 retval->type = KVP_TYPE_GLIST;
01317 retval->value.list = kvp_glist_copy (value);
01318 return retval;
01319 }
01320
01321 KvpValue *
01322 kvp_value_new_glist_nc (GList * value)
01323 {
01324 KvpValue *retval;
01325 if (!value)
01326 return NULL;
01327
01328 retval = g_new0 (KvpValue, 1);
01329 retval->type = KVP_TYPE_GLIST;
01330 retval->value.list = value;
01331 return retval;
01332 }
01333
01334 KvpValue *
01335 kvp_value_new_frame (const KvpFrame * value)
01336 {
01337 KvpValue *retval;
01338 if (!value)
01339 return NULL;
01340
01341 retval = g_new0 (KvpValue, 1);
01342 retval->type = KVP_TYPE_FRAME;
01343 retval->value.frame = kvp_frame_copy (value);
01344 return retval;
01345 }
01346
01347 KvpValue *
01348 kvp_value_new_frame_nc (KvpFrame * value)
01349 {
01350 KvpValue *retval;
01351 if (!value)
01352 return NULL;
01353
01354 retval = g_new0 (KvpValue, 1);
01355 retval->type = KVP_TYPE_FRAME;
01356 retval->value.frame = value;
01357 return retval;
01358 }
01359
01360 void
01361 kvp_value_delete (KvpValue * value)
01362 {
01363 if (!value)
01364 return;
01365
01366 switch (value->type)
01367 {
01368 case KVP_TYPE_STRING:
01369 g_free (value->value.str);
01370 break;
01371 case KVP_TYPE_GUID:
01372 g_free (value->value.guid);
01373 break;
01374 case KVP_TYPE_BINARY:
01375 g_free (value->value.binary.data);
01376 break;
01377 case KVP_TYPE_GLIST:
01378 kvp_glist_delete (value->value.list);
01379 break;
01380 case KVP_TYPE_FRAME:
01381 kvp_frame_delete (value->value.frame);
01382 break;
01383 case KVP_TYPE_BOOLEAN:
01384 case KVP_TYPE_GINT64:
01385 case KVP_TYPE_DOUBLE:
01386 case KVP_TYPE_NUMERIC:
01387 default:
01388 break;
01389 }
01390 g_free (value);
01391 }
01392
01393 KvpValueType
01394 kvp_value_get_type (const KvpValue * value)
01395 {
01396 if (!value)
01397 return QOF_FATAL;
01398 return value->type;
01399 }
01400
01401 gint64
01402 kvp_value_get_gint64 (const KvpValue * value)
01403 {
01404 if (!value)
01405 return 0;
01406 if (value->type == KVP_TYPE_GINT64)
01407 return value->value.int64;
01408 else
01409 {
01410 PERR (" value type %d does not match KVP_TYPE_GINT64",
01411 value->type);
01412 return 0;
01413 }
01414 }
01415
01416 gdouble
01417 kvp_value_get_double (const KvpValue * value)
01418 {
01419 if (!value)
01420 return 0.0;
01421 if (value->type == KVP_TYPE_DOUBLE)
01422 return value->value.dbl;
01423 else
01424 {
01425 PERR (" value type %d does not match KVP_TYPE_DOUBLE",
01426 value->type);
01427 return 0.0;
01428 }
01429 }
01430
01431 QofNumeric
01432 kvp_value_get_numeric (const KvpValue * value)
01433 {
01434 if (!value)
01435 return qof_numeric_zero ();
01436 if (value->type == KVP_TYPE_NUMERIC)
01437 return value->value.numeric;
01438 else
01439 {
01440 PERR (" value type %d does not match KVP_TYPE_NUMERIC",
01441 value->type);
01442 return qof_numeric_zero ();
01443 }
01444 }
01445
01446 gchar *
01447 kvp_value_get_string (const KvpValue * value)
01448 {
01449 if (!value)
01450 return NULL;
01451 if (value->type == KVP_TYPE_STRING)
01452 return value->value.str;
01453 else
01454 {
01455 PERR (" value type %d does not match KVP_TYPE_STRING",
01456 value->type);
01457 return NULL;
01458 }
01459 }
01460
01461 gboolean
01462 kvp_value_get_boolean (const KvpValue * value)
01463 {
01464 if (!value)
01465 return FALSE;
01466 if (value->type == KVP_TYPE_BOOLEAN)
01467 return value->value.gbool;
01468 else
01469 {
01470 PERR (" value type %d does not match KVP_TYPE_BOOLEAN",
01471 value->type);
01472 return FALSE;
01473 }
01474 }
01475
01476 GUID *
01477 kvp_value_get_guid (const KvpValue * value)
01478 {
01479 if (!value)
01480 return NULL;
01481 if (value->type == KVP_TYPE_GUID)
01482 return value->value.guid;
01483 else
01484 {
01485 PERR (" value type %d does not match KVP_TYPE_GUID",
01486 value->type);
01487 return NULL;
01488 }
01489 }
01490
01491 QofTime*
01492 kvp_value_get_time (const KvpValue * value)
01493 {
01494 if (!value)
01495 return NULL;
01496 if (value->type == KVP_TYPE_TIME)
01497 return value->value.qt;
01498 else
01499 {
01500 PERR (" value type %d does not match KVP_TYPE_TIME",
01501 value->type);
01502 return NULL;
01503 }
01504 }
01505
01506 void *
01507 kvp_value_get_binary (const KvpValue * value, guint64 * size_return)
01508 {
01509 if (!value)
01510 {
01511 if (size_return)
01512 *size_return = 0;
01513 PERR (" no size specified");
01514 return NULL;
01515 }
01516
01517 if (value->type == KVP_TYPE_BINARY)
01518 {
01519 if (size_return)
01520 *size_return = value->value.binary.datasize;
01521 return value->value.binary.data;
01522 }
01523 else
01524 {
01525 if (size_return)
01526 *size_return = 0;
01527 PERR (" value type %d does not match KVP_TYPE_BINARY",
01528 value->type);
01529 return NULL;
01530 }
01531 }
01532
01533 GList *
01534 kvp_value_get_glist (const KvpValue * value)
01535 {
01536 if (!value)
01537 return NULL;
01538 if (value->type == KVP_TYPE_GLIST)
01539 return value->value.list;
01540 else
01541 {
01542 PERR (" value type %d does not match KVP_TYPE_GLIST",
01543 value->type);
01544 return NULL;
01545 }
01546 }
01547
01548 KvpFrame *
01549 kvp_value_get_frame (const KvpValue * value)
01550 {
01551 if (!value)
01552 return NULL;
01553 if (value->type == KVP_TYPE_FRAME)
01554 return value->value.frame;
01555 else
01556 {
01557 PERR (" value type %d does not match KVP_TYPE_FRAME",
01558 value->type);
01559 return NULL;
01560 }
01561 }
01562
01563 KvpFrame *
01564 kvp_value_replace_frame_nc (KvpValue * value, KvpFrame * newframe)
01565 {
01566 KvpFrame *oldframe;
01567 if (!value)
01568 return NULL;
01569 if (KVP_TYPE_FRAME != value->type)
01570 {
01571 PERR (" value type %d does not match KVP_TYPE_FRAME",
01572 value->type);
01573 return NULL;
01574 }
01575 oldframe = value->value.frame;
01576 value->value.frame = newframe;
01577 return oldframe;
01578 }
01579
01580 GList *
01581 kvp_value_replace_glist_nc (KvpValue * value, GList * newlist)
01582 {
01583 GList *oldlist;
01584 if (!value)
01585 return NULL;
01586 if (KVP_TYPE_GLIST != value->type)
01587 {
01588 PERR (" value type %d does not match KVP_TYPE_GLIST",
01589 value->type);
01590 return NULL;
01591 }
01592
01593 oldlist = value->value.list;
01594 value->value.list = newlist;
01595 return oldlist;
01596 }
01597
01598
01599
01600 KvpValue *
01601 kvp_value_copy (const KvpValue * value)
01602 {
01603 if (!value)
01604 return NULL;
01605
01606 switch (value->type)
01607 {
01608 case KVP_TYPE_GINT64:
01609 return kvp_value_new_gint64 (value->value.int64);
01610 break;
01611 case KVP_TYPE_DOUBLE:
01612 return kvp_value_new_double (value->value.dbl);
01613 break;
01614 case KVP_TYPE_NUMERIC:
01615 return kvp_value_new_numeric (value->value.numeric);
01616 break;
01617 case KVP_TYPE_STRING:
01618 return kvp_value_new_string (value->value.str);
01619 break;
01620 case KVP_TYPE_GUID:
01621 return kvp_value_new_guid (value->value.guid);
01622 break;
01623 case KVP_TYPE_BOOLEAN:
01624 return NULL;
01625 return kvp_value_new_boolean (value->value.gbool);
01626 break;
01627 case KVP_TYPE_TIME :
01628 return kvp_value_new_time (value->value.qt);
01629 break;
01630 #ifndef QOF_DISABLE_DEPRECATED
01631 case KVP_TYPE_TIMESPEC:
01632 return kvp_value_new_timespec (value->value.timespec);
01633 break;
01634 #endif
01635 case KVP_TYPE_BINARY:
01636 return kvp_value_new_binary (value->value.binary.data,
01637 value->value.binary.datasize);
01638 break;
01639 case KVP_TYPE_GLIST:
01640 return kvp_value_new_glist (value->value.list);
01641 break;
01642 case KVP_TYPE_FRAME:
01643 return kvp_value_new_frame (value->value.frame);
01644 break;
01645 }
01646 return NULL;
01647 }
01648
01649 void
01650 kvp_frame_for_each_slot (KvpFrame * f, KvpValueForeachCB proc, gpointer data)
01651 {
01652 if (!f)
01653 return;
01654 if (!proc)
01655 return;
01656 if (!(f->hash))
01657 return;
01658 g_hash_table_foreach (f->hash, (GHFunc) proc, data);
01659 }
01660
01661 gint
01662 kvp_value_compare (const KvpValue * kva, const KvpValue * kvb)
01663 {
01664 if (kva == kvb)
01665 return 0;
01666
01667 if (!kva && kvb)
01668 return -1;
01669 if (kva && !kvb)
01670 return 1;
01671
01672 if (kva->type < kvb->type)
01673 return -1;
01674 if (kva->type > kvb->type)
01675 return 1;
01676
01677 switch (kva->type)
01678 {
01679 case KVP_TYPE_GINT64:
01680 if (kva->value.int64 < kvb->value.int64)
01681 return -1;
01682 if (kva->value.int64 > kvb->value.int64)
01683 return 1;
01684 return 0;
01685 break;
01686 case KVP_TYPE_DOUBLE:
01687 return qof_util_double_compare (kva->value.dbl, kvb->value.dbl);
01688 break;
01689 case KVP_TYPE_NUMERIC:
01690 return qof_numeric_compare (kva->value.numeric,
01691 kvb->value.numeric);
01692 break;
01693 case KVP_TYPE_STRING:
01694 return strcmp (kva->value.str, kvb->value.str);
01695 break;
01696 case KVP_TYPE_GUID:
01697 return guid_compare (kva->value.guid, kvb->value.guid);
01698 break;
01699 case KVP_TYPE_BOOLEAN:
01700 {
01701
01702 if (kva->value.gbool != kvb->value.gbool)
01703 return (kva->value.gbool) ? 1 : -1;
01704 return 0;
01705 break;
01706 }
01707 case KVP_TYPE_TIME :
01708 return qof_time_cmp (kva->value.qt, kvb->value.qt);
01709 break;
01710 #ifndef QOF_DISABLE_DEPRECATED
01711 case KVP_TYPE_TIMESPEC:
01712 return timespec_cmp (&(kva->value.timespec),
01713 &(kvb->value.timespec));
01714 break;
01715 #endif
01716 case KVP_TYPE_BINARY:
01717 if (kva->value.binary.datasize < kvb->value.binary.datasize)
01718 return -1;
01719 if (kva->value.binary.datasize > kvb->value.binary.datasize)
01720 return 1;
01721 return memcmp (kva->value.binary.data,
01722 kvb->value.binary.data, kva->value.binary.datasize);
01723 break;
01724 case KVP_TYPE_GLIST:
01725 return kvp_glist_compare (kva->value.list, kvb->value.list);
01726 break;
01727 case KVP_TYPE_FRAME:
01728 return kvp_frame_compare (kva->value.frame, kvb->value.frame);
01729 break;
01730 }
01731 return 0;
01732 }
01733
01734 typedef struct
01735 {
01736 gint compare;
01737 KvpFrame *other_frame;
01738 } KvpFrameCompare;
01739
01740 static void
01741 kvp_frame_compare_helper (const gchar *key, KvpValue * val, gpointer data)
01742 {
01743 KvpFrameCompare *status = (KvpFrameCompare *) data;
01744 if (status->compare == 0)
01745 {
01746 KvpFrame *other_frame = status->other_frame;
01747 KvpValue *other_val = kvp_frame_get_slot (other_frame, key);
01748
01749 if (other_val)
01750 status->compare = kvp_value_compare (val, other_val);
01751 else
01752 status->compare = 1;
01753 }
01754 }
01755
01756 gint
01757 kvp_frame_compare (const KvpFrame * fa, const KvpFrame * fb)
01758 {
01759 KvpFrameCompare status;
01760
01761 if (fa == fb)
01762 return 0;
01763
01764 if (!fa && fb)
01765 return -1;
01766 if (fa && !fb)
01767 return 1;
01768
01769
01770 if (!fa->hash && fb->hash)
01771 return -1;
01772 if (fa->hash && !fb->hash)
01773 return 1;
01774
01775 status.compare = 0;
01776 status.other_frame = (KvpFrame *) fb;
01777
01778 kvp_frame_for_each_slot ((KvpFrame *) fa, kvp_frame_compare_helper,
01779 &status);
01780
01781 if (status.compare != 0)
01782 return status.compare;
01783
01784 status.other_frame = (KvpFrame *) fa;
01785
01786 kvp_frame_for_each_slot ((KvpFrame *) fb, kvp_frame_compare_helper,
01787 &status);
01788
01789 return (-status.compare);
01790 }
01791
01792
01793 gchar *
01794 binary_to_string (gconstpointer data, guint32 size)
01795 {
01796 GString *output;
01797 guint32 i;
01798 guchar *data_str = (guchar *) data;
01799
01800 output = g_string_sized_new (size * sizeof (gchar));
01801
01802 for (i = 0; i < size; i++)
01803 {
01804 g_string_append_printf (output, "%02x",
01805 (guint32) (data_str[i]));
01806 }
01807
01808 return output->str;
01809 }
01810
01811 gchar *
01812 kvp_value_glist_to_string (const GList * list)
01813 {
01814 gchar *tmp1;
01815 gchar *tmp2;
01816 const GList *cursor;
01817
01818 tmp1 = g_strdup_printf ("[ ");
01819
01820 for (cursor = list; cursor; cursor = cursor->next)
01821 {
01822 gchar *tmp3;
01823
01824 tmp3 = kvp_value_to_string ((KvpValue *) cursor->data);
01825 tmp2 = g_strdup_printf ("%s %s,", tmp1, tmp3 ? tmp3 : "");
01826 g_free (tmp1);
01827 g_free (tmp3);
01828 tmp1 = tmp2;
01829 }
01830
01831 tmp2 = g_strdup_printf ("%s ]", tmp1);
01832 g_free (tmp1);
01833
01834 return tmp2;
01835 }
01836
01837 static void
01838 kvp_frame_to_bare_string_helper (gpointer key __attribute__ ((unused)),
01839 gpointer value, gpointer data)
01840 {
01841 gchar **str = (gchar **) data;
01842 *str =
01843 g_strdup_printf ("%s",
01844 kvp_value_to_bare_string ((KvpValue *) value));
01845 }
01846
01847 gchar *
01848 kvp_value_to_bare_string (const KvpValue * val)
01849 {
01850 gchar *tmp1;
01851 gchar *tmp2;
01852 const gchar *ctmp;
01853
01854 g_return_val_if_fail (val, NULL);
01855 tmp1 = g_strdup ("");
01856 switch (kvp_value_get_type (val))
01857 {
01858 case KVP_TYPE_GINT64:
01859 {
01860 return g_strdup_printf ("%" G_GINT64_FORMAT,
01861 kvp_value_get_gint64 (val));
01862 break;
01863 }
01864 case KVP_TYPE_DOUBLE:
01865 {
01866 return g_strdup_printf ("(%g)", kvp_value_get_double (val));
01867 break;
01868 }
01869 case KVP_TYPE_NUMERIC:
01870 {
01871 tmp1 = qof_numeric_to_string (kvp_value_get_numeric (val));
01872 tmp2 = g_strdup_printf ("%s", tmp1 ? tmp1 : "");
01873 g_free (tmp1);
01874 return tmp2;
01875 break;
01876 }
01877 case KVP_TYPE_STRING:
01878 {
01879 tmp1 = kvp_value_get_string (val);
01880 return g_strdup_printf ("%s", tmp1 ? tmp1 : "");
01881 break;
01882 }
01883 case KVP_TYPE_GUID:
01884 {
01885 ctmp = guid_to_string (kvp_value_get_guid (val));
01886 tmp2 = g_strdup_printf ("%s", ctmp ? ctmp : "");
01887 return tmp2;
01888 break;
01889 }
01890 #ifndef QOF_DISABLE_DEPRECATED
01891 case KVP_TYPE_TIMESPEC:
01892 {
01893 time_t t;
01894 t = timespecToTime_t (kvp_value_get_timespec (val));
01895 qof_date_format_set (QOF_DATE_FORMAT_UTC);
01896 return qof_print_date (t);
01897 break;
01898 }
01899 #endif
01900 case KVP_TYPE_BOOLEAN :
01901 return (kvp_value_get_boolean (val)) ? "TRUE" : "FALSE";
01902 case KVP_TYPE_BINARY:
01903 {
01904 guint64 len;
01905 gpointer data;
01906 data = kvp_value_get_binary (val, &len);
01907 tmp1 = binary_to_string (data, len);
01908 return g_strdup_printf ("%s", tmp1 ? tmp1 : "");
01909 break;
01910 }
01911 case KVP_TYPE_GLIST:
01912
01913 {
01914 tmp1 = kvp_value_glist_to_string (kvp_value_get_glist (val));
01915 tmp2 = g_strdup_printf ("%s", tmp1 ? tmp1 : "");
01916 g_free (tmp1);
01917 return tmp2;
01918 break;
01919 }
01920 case KVP_TYPE_FRAME:
01921 {
01922 KvpFrame *frame;
01923
01924 frame = kvp_value_get_frame (val);
01925 if (frame->hash)
01926 {
01927 tmp1 = g_strdup ("");
01928 g_hash_table_foreach (frame->hash,
01929 kvp_frame_to_bare_string_helper, &tmp1);
01930 }
01931 return tmp1;
01932 break;
01933 }
01934 default:
01935 return g_strdup_printf (" ");
01936 break;
01937 }
01938 }
01939
01940 gchar *
01941 kvp_value_to_string (const KvpValue * val)
01942 {
01943 gchar *tmp1;
01944 gchar *tmp2;
01945 const gchar *ctmp;
01946
01947 g_return_val_if_fail (val, NULL);
01948
01949 switch (kvp_value_get_type (val))
01950 {
01951 case KVP_TYPE_GINT64:
01952 {
01953 return g_strdup_printf ("KVP_VALUE_GINT64(%" G_GINT64_FORMAT ")",
01954 kvp_value_get_gint64 (val));
01955 break;
01956 }
01957 case KVP_TYPE_DOUBLE:
01958 {
01959 return g_strdup_printf ("KVP_VALUE_DOUBLE(%g)",
01960 kvp_value_get_double (val));
01961 break;
01962 }
01963 case KVP_TYPE_NUMERIC:
01964 {
01965 tmp1 = qof_numeric_to_string (kvp_value_get_numeric (val));
01966 tmp2 = g_strdup_printf ("KVP_VALUE_NUMERIC(%s)", tmp1 ? tmp1 : "");
01967 g_free (tmp1);
01968 return tmp2;
01969 break;
01970 }
01971 case KVP_TYPE_STRING:
01972 {
01973 tmp1 = kvp_value_get_string (val);
01974 return g_strdup_printf ("KVP_VALUE_STRING(%s)", tmp1 ? tmp1 : "");
01975 break;
01976 }
01977 case KVP_TYPE_GUID:
01978 {
01979
01980 ctmp = guid_to_string (kvp_value_get_guid (val));
01981 tmp2 = g_strdup_printf ("KVP_VALUE_GUID(%s)", ctmp ? ctmp : "");
01982 return tmp2;
01983 break;
01984 }
01985 #ifndef QOF_DISABLE_DEPRECATED
01986 case KVP_TYPE_TIMESPEC:
01987 {
01988 tmp1 = g_new0 (gchar, 40);
01989 gnc_timespec_to_iso8601_buff (kvp_value_get_timespec (val), tmp1);
01990 tmp2 = g_strdup_printf ("KVP_VALUE_TIMESPEC(%s)", tmp1);
01991 g_free (tmp1);
01992 return tmp2;
01993 break;
01994 }
01995 #endif
01996 case KVP_TYPE_BINARY:
01997 {
01998 guint64 len;
01999 gpointer data;
02000 data = kvp_value_get_binary (val, &len);
02001 tmp1 = binary_to_string (data, len);
02002 return g_strdup_printf ("KVP_VALUE_BINARY(%s)",
02003 tmp1 ? tmp1 : "");
02004 break;
02005 }
02006 case KVP_TYPE_GLIST:
02007 {
02008 tmp1 = kvp_value_glist_to_string (kvp_value_get_glist (val));
02009 tmp2 = g_strdup_printf ("KVP_VALUE_GLIST(%s)", tmp1 ? tmp1 : "");
02010 g_free (tmp1);
02011 return tmp2;
02012 break;
02013 }
02014 case KVP_TYPE_FRAME:
02015 {
02016 tmp1 = kvp_frame_to_string (kvp_value_get_frame (val));
02017 tmp2 = g_strdup_printf ("KVP_VALUE_FRAME(%s)", tmp1 ? tmp1 : "");
02018 g_free (tmp1);
02019 return tmp2;
02020 break;
02021 }
02022 default:
02023 return g_strdup_printf (" ");
02024 break;
02025 }
02026 }
02027
02028 static void
02029 kvp_frame_to_string_helper (gpointer key, gpointer value, gpointer data)
02030 {
02031 gchar *tmp_val;
02032 gchar **str = (gchar **) data;
02033 gchar *old_data = *str;
02034
02035 tmp_val = kvp_value_to_string ((KvpValue *) value);
02036
02037 *str = g_strdup_printf ("%s %s => %s,\n",
02038 *str ? *str : "", key ? (gchar *) key : "", tmp_val ? tmp_val : "");
02039
02040 g_free (old_data);
02041 g_free (tmp_val);
02042 }
02043
02044 gchar *
02045 kvp_frame_to_string (const KvpFrame * frame)
02046 {
02047 gchar *tmp1;
02048
02049 g_return_val_if_fail (frame != NULL, NULL);
02050
02051 tmp1 = g_strdup_printf ("{\n");
02052
02053 if (frame->hash)
02054 g_hash_table_foreach (frame->hash, kvp_frame_to_string_helper,
02055 &tmp1);
02056 {
02057 gchar *tmp2;
02058 tmp2 = g_strdup_printf ("%s}\n", tmp1);
02059 g_free (tmp1);
02060 tmp1 = tmp2;
02061 }
02062
02063 return tmp1;
02064 }
02065
02066 GHashTable *
02067 kvp_frame_get_hash (const KvpFrame * frame)
02068 {
02069 g_return_val_if_fail (frame != NULL, NULL);
02070 return frame->hash;
02071 }
02072
02073