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