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