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