QOF  0.8.7
kvpframe.c
1 /********************************************************************
2  * kvpframe.c -- Implements a key-value frame system *
3  * Copyright (C) 2000 Bill Gribble *
4  * Copyright (C) 2001,2003 Linas Vepstas <linas@linas.org> *
5  * Copyright (c) 2006-2008 Neil Williams <linux@codehelp.co.uk> *
6  * *
7  * This program is free software; you can redistribute it and/or *
8  * modify it under the terms of the GNU General Public License as *
9  * published by the Free Software Foundation; either version 2 of *
10  * the License, or (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License*
18  * along with this program; if not, contact: *
19  * *
20  * Free Software Foundation Voice: +1-617-542-5942 *
21  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
22  * Boston, MA 02110-1301, USA gnu@gnu.org *
23  * *
24  ********************************************************************/
25 
26 #include "config.h"
27 
28 #include <glib.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include "qof.h"
33 
34  /* Note that we keep the keys for this hash table in a GCache
35  * (qof_util_string_cache), as it is very likely we will see the
36  * same keys over and over again */
37 
38 struct _KvpFrame
39 {
40  GHashTable *hash;
41 };
42 
43 typedef struct
44 {
45  gpointer data;
46  gint64 datasize;
47 } KvpValueBinaryData;
48 
49 struct _KvpValue
50 {
51  KvpValueType type;
52  union
53  {
54  gint64 int64;
55  gdouble dbl;
56  QofNumeric numeric;
57  gchar *str;
58  GUID *guid;
59  QofTime *qt;
60  gboolean gbool; /* since 0.7.2 */
61  KvpValueBinaryData binary;
62  GList *list;
63  KvpFrame *frame;
64  } value;
65 };
66 
67 /* This static indicates the debugging module that this .o belongs to. */
68 static QofLogModule log_module = QOF_MOD_KVP;
69 
70 /* *******************************************************************
71  * KvpFrame functions
72  ********************************************************************/
73 
74 static guint
75 kvp_hash_func (gconstpointer v)
76 {
77  return g_str_hash (v);
78 }
79 
80 static gint
81 kvp_comp_func (gconstpointer v, gconstpointer v2)
82 {
83  return g_str_equal (v, v2);
84 }
85 
86 static gboolean
87 init_frame_body_if_needed (KvpFrame * f)
88 {
89  if (!f->hash)
90  {
91  f->hash = g_hash_table_new (&kvp_hash_func, &kvp_comp_func);
92  }
93  return (f->hash != NULL);
94 }
95 
96 KvpFrame *
98 {
99  KvpFrame *retval = g_new0 (KvpFrame, 1);
100 
101  /* Save space until the frame is actually used */
102  retval->hash = NULL;
103  return retval;
104 }
105 
106 static void
107 kvp_frame_delete_worker (gpointer key, gpointer value,
108  gpointer user_data __attribute__ ((unused)))
109 {
111  kvp_value_delete ((KvpValue *) value);
112 }
113 
114 void
116 {
117  if (!frame)
118  return;
119 
120  if (frame->hash)
121  {
122  /* free any allocated resource for frame or its children */
123  g_hash_table_foreach (frame->hash, &kvp_frame_delete_worker,
124  (gpointer) frame);
125 
126  /* delete the hash table */
127  g_hash_table_destroy (frame->hash);
128  frame->hash = NULL;
129  }
130  g_free (frame);
131 }
132 
133 gboolean
135 {
136  if (!frame)
137  return TRUE;
138  if (!frame->hash)
139  return TRUE;
140  return FALSE;
141 }
142 
143 static void
144 kvp_frame_copy_worker (gpointer key, gpointer value, gpointer user_data)
145 {
146  KvpFrame *dest = (KvpFrame *) user_data;
147  g_hash_table_insert (dest->hash,
149  (gpointer) kvp_value_copy (value));
150 }
151 
152 KvpFrame *
153 kvp_frame_copy (const KvpFrame * frame)
154 {
155  KvpFrame *retval = kvp_frame_new ();
156 
157  if (!frame)
158  return retval;
159 
160  if (frame->hash)
161  {
162  if (!init_frame_body_if_needed (retval))
163  return (NULL);
164  g_hash_table_foreach (frame->hash,
165  &kvp_frame_copy_worker, (gpointer) retval);
166  }
167  return retval;
168 }
169 
170 /* Replace the old value with the new value. Return the old value.
171  * Passing in a null value into this routine has the effect of
172  * removing the key from the KVP tree.
173  */
174 KvpValue *
175 kvp_frame_replace_slot_nc (KvpFrame * frame, const gchar *slot,
176  KvpValue * new_value)
177 {
178  gpointer orig_key;
179  gpointer orig_value = NULL;
180  int key_exists;
181 
182  if (!frame || !slot)
183  return NULL;
184  if (!init_frame_body_if_needed (frame))
185  return NULL; /* Error ... */
186 
187  key_exists = g_hash_table_lookup_extended (frame->hash, slot,
188  &orig_key, &orig_value);
189  if (key_exists)
190  {
191  g_hash_table_remove (frame->hash, slot);
192  qof_util_string_cache_remove (orig_key);
193  }
194  else
195  orig_value = NULL;
196  if (new_value)
197  g_hash_table_insert (frame->hash,
198  qof_util_string_cache_insert ((gpointer) slot), new_value);
199  return (KvpValue *) orig_value;
200 }
201 
202 /* Passing in a null value into this routine has the effect
203  * of deleting the old value stored at this slot.
204  */
205 static inline void
206 kvp_frame_set_slot_destructively (KvpFrame * frame, const gchar *slot,
207  KvpValue * new_value)
208 {
209  KvpValue *old_value;
210  old_value = kvp_frame_replace_slot_nc (frame, slot, new_value);
211  kvp_value_delete (old_value);
212 }
213 
214 /* ============================================================ */
215 /* Get the named frame, or create it if it doesn't exist.
216  * gcc -O3 should inline it. It performs no error checks,
217  * the caller is responsible of passing good keys and frames.
218  */
219 static inline KvpFrame *
220 get_or_make (KvpFrame * fr, const gchar *key)
221 {
222  KvpFrame *next_frame;
223  KvpValue *value;
224 
225  value = kvp_frame_get_slot (fr, key);
226  if (value)
227  next_frame = kvp_value_get_frame (value);
228  else
229  {
230  next_frame = kvp_frame_new ();
231  kvp_frame_set_slot_nc (fr, key,
232  kvp_value_new_frame_nc (next_frame));
233  }
234  return next_frame;
235 }
236 
237 /* Get pointer to last frame in path. If the path doesn't exist,
238  * it is created. The string stored in keypath will be hopelessly
239  * mangled .
240  */
241 static KvpFrame *
242 kvp_frame_get_frame_slash_trash (KvpFrame * frame, gchar *key_path)
243 {
244  gchar *key, *next;
245  if (!frame || !key_path)
246  return frame;
247 
248  key = key_path;
249  key--;
250 
251  while (key)
252  {
253  key++;
254  while ('/' == *key)
255  key++;
256  if (0x0 == *key)
257  break; /* trailing slash */
258  next = strchr (key, '/');
259  if (next)
260  *next = 0x0;
261 
262  frame = get_or_make (frame, key);
263  if (!frame)
264  break; /* error - should never happen */
265 
266  key = next;
267  }
268  return frame;
269 }
270 
271 /* ============================================================ */
272 /* Get pointer to last frame in path, or NULL if the path doesn't
273  * exist. The string stored in keypath will be hopelessly mangled .
274  */
275 static inline const KvpFrame *
276 kvp_frame_get_frame_or_null_slash_trash (const KvpFrame * frame,
277  gchar *key_path)
278 {
279  KvpValue *value;
280  gchar *key, *next;
281  if (!frame || !key_path)
282  return NULL;
283 
284  key = key_path;
285  key--;
286 
287  while (key)
288  {
289  key++;
290  while ('/' == *key)
291  key++;
292  if (0x0 == *key)
293  break; /* trailing slash */
294  next = strchr (key, '/');
295  if (next)
296  *next = 0x0;
297 
298  value = kvp_frame_get_slot (frame, key);
299  if (!value)
300  return NULL;
301  frame = kvp_value_get_frame (value);
302  if (!frame)
303  return NULL;
304 
305  key = next;
306  }
307  return frame;
308 }
309 
310 /* Return pointer to last frame in path, and also store the
311  * last dangling part of path in 'end_key'. If path doesn't
312  * exist, it is created.
313  */
314 
315 static inline KvpFrame *
316 get_trailer_make (KvpFrame * frame, const gchar *key_path,
317  gchar **end_key)
318 {
319  gchar *last_key;
320 
321  if (!frame || !key_path || (0 == key_path[0]))
322  return NULL;
323 
324  last_key = strrchr (key_path, '/');
325  if (NULL == last_key)
326  last_key = (gchar *) key_path;
327  else if (last_key == key_path)
328  last_key++;
329  else if (0 == last_key[1])
330  return NULL;
331  else
332  {
333  gchar *root, *lkey;
334  root = g_strdup (key_path);
335  lkey = strrchr (root, '/');
336  *lkey = 0;
337  frame = kvp_frame_get_frame_slash_trash (frame, root);
338  g_free (root);
339  last_key++;
340  }
341 
342  *end_key = last_key;
343  return frame;
344 }
345 
346 
347 /* Return pointer to last frame in path, or NULL if the path
348  * doesn't exist. Also store the last dangling part of path
349  * in 'end_key'.
350  */
351 
352 static inline const KvpFrame *
353 get_trailer_or_null (const KvpFrame * frame, const gchar *key_path,
354  gchar **end_key)
355 {
356  gchar *last_key;
357 
358  if (!frame || !key_path || (0 == key_path[0]))
359  return NULL;
360 
361  last_key = strrchr (key_path, '/');
362  if (NULL == last_key)
363  last_key = (gchar *) key_path;
364  else if (last_key == key_path)
365  last_key++;
366  else if (0 == last_key[1])
367  return NULL;
368  else
369  {
370  gchar *root, *lkey;
371  root = g_strdup (key_path);
372  lkey = strrchr (root, '/');
373  *lkey = 0;
374  frame = kvp_frame_get_frame_or_null_slash_trash (frame, root);
375  g_free (root);
376 
377  last_key++;
378  }
379 
380  *end_key = last_key;
381  return frame;
382 }
383 
384 /* ============================================================ */
385 
386 void
387 kvp_frame_set_gint64 (KvpFrame * frame, const gchar *path, gint64 ival)
388 {
389  KvpValue *value;
390  value = kvp_value_new_gint64 (ival);
391  frame = kvp_frame_set_value_nc (frame, path, value);
392  if (!frame)
393  kvp_value_delete (value);
394 }
395 
396 void
397 kvp_frame_set_double (KvpFrame * frame, const gchar *path, gdouble dval)
398 {
399  KvpValue *value;
400  value = kvp_value_new_double (dval);
401  frame = kvp_frame_set_value_nc (frame, path, value);
402  if (!frame)
403  kvp_value_delete (value);
404 }
405 
406 void
407 kvp_frame_set_time (KvpFrame * frame, const gchar *path, QofTime *qt)
408 {
409  KvpValue *value;
410  value = kvp_value_new_time (qt);
411  frame = kvp_frame_set_value_nc (frame, path, value);
412  if (!frame)
413  kvp_value_delete (value);
414 }
415 
416 void
417 kvp_frame_set_numeric (KvpFrame * frame, const gchar *path,
418  QofNumeric nval)
419 {
420  KvpValue *value;
421  value = kvp_value_new_numeric (nval);
422  frame = kvp_frame_set_value_nc (frame, path, value);
423  if (!frame)
424  kvp_value_delete (value);
425 }
426 
427 void
428 kvp_frame_set_boolean (KvpFrame * frame, const gchar * path,
429  gboolean val)
430 {
431  KvpValue * value;
432  value = kvp_value_new_boolean (val);
433  frame = kvp_frame_set_value_nc (frame, path, value);
434  if (!frame)
435  kvp_value_delete (value);
436 }
437 
438 void
439 kvp_frame_set_string (KvpFrame * frame, const gchar *path,
440  const gchar *str)
441 {
442  KvpValue *value;
443  value = kvp_value_new_string (str);
444  frame = kvp_frame_set_value_nc (frame, path, value);
445  if (!frame)
446  kvp_value_delete (value);
447 }
448 
449 void
450 kvp_frame_set_guid (KvpFrame * frame, const gchar *path,
451  const GUID * guid)
452 {
453  KvpValue *value;
454  value = kvp_value_new_guid (guid);
455  frame = kvp_frame_set_value_nc (frame, path, value);
456  if (!frame)
457  kvp_value_delete (value);
458 }
459 
460 void
461 kvp_frame_set_frame (KvpFrame * frame, const gchar *path, KvpFrame * fr)
462 {
463  KvpValue *value;
464  value = kvp_value_new_frame (fr);
465  frame = kvp_frame_set_value_nc (frame, path, value);
466  if (!frame)
467  kvp_value_delete (value);
468 }
469 
470 void
471 kvp_frame_set_frame_nc (KvpFrame * frame, const gchar *path, KvpFrame * fr)
472 {
473  KvpValue *value;
474  value = kvp_value_new_frame_nc (fr);
475  frame = kvp_frame_set_value_nc (frame, path, value);
476  if (!frame)
477  kvp_value_delete (value);
478 }
479 
480 /* ============================================================ */
481 
482 KvpFrame *
483 kvp_frame_set_value_nc (KvpFrame * frame, const gchar *key_path,
484  KvpValue * value)
485 {
486  gchar *last_key;
487 
488  frame = get_trailer_make (frame, key_path, &last_key);
489  if (!frame)
490  return NULL;
491  kvp_frame_set_slot_destructively (frame, last_key, value);
492  return frame;
493 }
494 
495 KvpFrame *
496 kvp_frame_set_value (KvpFrame * frame, const gchar *key_path,
497  const KvpValue * value)
498 {
499  KvpValue *new_value = NULL;
500  gchar *last_key;
501 
502  frame = get_trailer_make (frame, key_path, &last_key);
503  if (!frame)
504  return NULL;
505 
506  if (value)
507  new_value = kvp_value_copy (value);
508  kvp_frame_set_slot_destructively (frame, last_key, new_value);
509  return frame;
510 }
511 
512 KvpValue *
513 kvp_frame_replace_value_nc (KvpFrame * frame, const gchar *key_path,
514  KvpValue * new_value)
515 {
516  KvpValue *old_value;
517  gchar *last_key;
518 
519  last_key = NULL;
520  if (new_value)
521  frame = get_trailer_make (frame, key_path, &last_key);
522  else
523  frame =
524  (KvpFrame *) get_trailer_or_null (frame, key_path, &last_key);
525  if (!frame)
526  return NULL;
527 
528  old_value = kvp_frame_replace_slot_nc (frame, last_key, new_value);
529  return old_value;
530 }
531 
532 /* ============================================================ */
533 
534 KvpFrame *
535 kvp_frame_add_value_nc (KvpFrame * frame, const gchar *path,
536  KvpValue * value)
537 {
538  gchar *key = NULL;
539  KvpValue *oldvalue;
540 
541  frame = (KvpFrame *) get_trailer_or_null (frame, path, &key);
542  oldvalue = kvp_frame_get_slot (frame, key);
543 
544  ENTER ("old frame=%s", kvp_frame_to_string (frame));
545  if (oldvalue)
546  {
547  /* If already a glist here, just append */
548  if (KVP_TYPE_GLIST == oldvalue->type)
549  {
550  GList *vlist = oldvalue->value.list;
551  vlist = g_list_append (vlist, value);
552  oldvalue->value.list = vlist;
553  }
554  else
555  /* If some other value, convert it to a glist */
556  {
557  KvpValue *klist;
558  GList *vlist = NULL;
559 
560  vlist = g_list_append (vlist, oldvalue);
561  vlist = g_list_append (vlist, value);
562  klist = kvp_value_new_glist_nc (vlist);
563 
564  kvp_frame_replace_slot_nc (frame, key, klist);
565  }
566  LEAVE ("new frame=%s", kvp_frame_to_string (frame));
567  return frame;
568  }
569 
570  /* Hmm, if we are here, the path doesn't exist. We need to
571  * create the path, add the value to it. */
572  frame = kvp_frame_set_value_nc (frame, path, value);
573  LEAVE ("new frame=%s", kvp_frame_to_string (frame));
574  return frame;
575 }
576 
577 KvpFrame *
578 kvp_frame_add_value (KvpFrame * frame, const gchar *path, KvpValue * value)
579 {
580  value = kvp_value_copy (value);
581  frame = kvp_frame_add_value_nc (frame, path, value);
582  if (!frame)
583  kvp_value_delete (value);
584  return frame;
585 }
586 
587 void
588 kvp_frame_add_gint64 (KvpFrame * frame, const gchar *path, gint64 ival)
589 {
590  KvpValue *value;
591  value = kvp_value_new_gint64 (ival);
592  frame = kvp_frame_add_value_nc (frame, path, value);
593  if (!frame)
594  kvp_value_delete (value);
595 }
596 
597 void
598 kvp_frame_add_double (KvpFrame * frame, const gchar *path, gdouble dval)
599 {
600  KvpValue *value;
601  value = kvp_value_new_double (dval);
602  frame = kvp_frame_add_value_nc (frame, path, value);
603  if (!frame)
604  kvp_value_delete (value);
605 }
606 
607 void
608 kvp_frame_add_numeric (KvpFrame * frame, const gchar *path,
609  QofNumeric nval)
610 {
611  KvpValue *value;
612  value = kvp_value_new_numeric (nval);
613  frame = kvp_frame_add_value_nc (frame, path, value);
614  if (!frame)
615  kvp_value_delete (value);
616 }
617 
618 void
619 kvp_frame_add_time (KvpFrame * frame, const gchar *path, QofTime *qt)
620 {
621  KvpValue *value;
622  value = kvp_value_new_time (qt);
623  frame = kvp_frame_add_value_nc (frame, path, value);
624  if (!frame)
625  kvp_value_delete (value);
626 }
627 
628 void
629 kvp_frame_add_boolean (KvpFrame * frame, const gchar * path, gboolean val)
630 {
631  KvpValue * value;
632  value = kvp_value_new_boolean (val);
633  frame = kvp_frame_add_value_nc (frame, path, value);
634  if (!frame)
635  kvp_value_delete (value);
636 }
637 
638 void
639 kvp_frame_add_string (KvpFrame * frame, const gchar *path, const gchar *str)
640 {
641  KvpValue *value;
642  value = kvp_value_new_string (str);
643  frame = kvp_frame_add_value_nc (frame, path, value);
644  if (!frame)
645  kvp_value_delete (value);
646 }
647 
648 void
649 kvp_frame_add_guid (KvpFrame * frame, const gchar *path, const GUID * guid)
650 {
651  KvpValue *value;
652  value = kvp_value_new_guid (guid);
653  frame = kvp_frame_add_value_nc (frame, path, value);
654  if (!frame)
655  kvp_value_delete (value);
656 }
657 
658 void
659 kvp_frame_add_frame (KvpFrame * frame, const gchar *path, KvpFrame * fr)
660 {
661  KvpValue *value;
662  value = kvp_value_new_frame (fr);
663  frame = kvp_frame_add_value_nc (frame, path, value);
664  if (!frame)
665  kvp_value_delete (value);
666 }
667 
668 void
669 kvp_frame_add_frame_nc (KvpFrame * frame, const gchar *path, KvpFrame * fr)
670 {
671  KvpValue *value;
672  value = kvp_value_new_frame_nc (fr);
673  frame = kvp_frame_add_value_nc (frame, path, value);
674  if (!frame)
675  kvp_value_delete (value);
676 }
677 
678 /* ============================================================ */
679 
680 void
681 kvp_frame_set_slot (KvpFrame * frame, const gchar *slot,
682  const KvpValue * value)
683 {
684  KvpValue *new_value = NULL;
685 
686  if (!frame)
687  return;
688 
689  g_return_if_fail (slot && *slot != '\0');
690 
691  if (value)
692  new_value = kvp_value_copy (value);
693  kvp_frame_set_slot_destructively (frame, slot, new_value);
694 }
695 
696 void
697 kvp_frame_set_slot_nc (KvpFrame * frame, const gchar *slot,
698  KvpValue * value)
699 {
700  if (!frame)
701  return;
702 
703  g_return_if_fail (slot && *slot != '\0');
704 
705  kvp_frame_set_slot_destructively (frame, slot, value);
706 }
707 
708 KvpValue *
709 kvp_frame_get_slot (const KvpFrame * frame, const gchar *slot)
710 {
711  KvpValue *v;
712  if (!frame)
713  return NULL;
714  if (!frame->hash)
715  return NULL; /* Error ... */
716  v = g_hash_table_lookup (frame->hash, slot);
717  return v;
718 }
719 
720 /* ============================================================ */
721 
722 void
724  const KvpValue * new_value, const gchar *first_key, ...)
725 {
726  va_list ap;
727  const gchar *key;
728 
729  if (!frame)
730  return;
731 
732  g_return_if_fail (first_key && *first_key != '\0');
733 
734  va_start (ap, first_key);
735 
736  key = first_key;
737 
738  while (TRUE)
739  {
740  KvpValue *value;
741  const gchar *next_key;
742 
743  next_key = va_arg (ap, const gchar *);
744  if (!next_key)
745  {
746  kvp_frame_set_slot (frame, key, new_value);
747  break;
748  }
749 
750  g_return_if_fail (*next_key != '\0');
751 
752  value = kvp_frame_get_slot (frame, key);
753  if (!value)
754  {
755  KvpFrame *new_frame = kvp_frame_new ();
756  KvpValue *frame_value = kvp_value_new_frame (new_frame);
757 
758  kvp_frame_set_slot_nc (frame, key, frame_value);
759 
760  value = kvp_frame_get_slot (frame, key);
761  if (!value)
762  break;
763  }
764 
765  frame = kvp_value_get_frame (value);
766  if (!frame)
767  break;
768 
769  key = next_key;
770  }
771 
772  va_end (ap);
773 }
774 
775 void
777  const KvpValue * new_value, GSList * key_path)
778 {
779  if (!frame || !key_path)
780  return;
781 
782  while (TRUE)
783  {
784  const gchar *key = key_path->data;
785  KvpValue *value;
786 
787  if (!key)
788  return;
789 
790  g_return_if_fail (*key != '\0');
791 
792  key_path = key_path->next;
793  if (!key_path)
794  {
795  kvp_frame_set_slot (frame, key, new_value);
796  return;
797  }
798 
799  value = kvp_frame_get_slot (frame, key);
800  if (!value)
801  {
802  KvpFrame *new_frame = kvp_frame_new ();
803  KvpValue *frame_value = kvp_value_new_frame (new_frame);
804 
805  kvp_frame_set_slot_nc (frame, key, frame_value);
806 
807  value = kvp_frame_get_slot (frame, key);
808  if (!value)
809  return;
810  }
811 
812  frame = kvp_value_get_frame (value);
813  if (!frame)
814  return;
815  }
816 }
817 
818 /* ============================================================ */
819 /* decode url-encoded string, do it in place
820  * + == space
821  * %xx == asci char where xx is hexadecimal ascii value
822  */
823 
824 static void
825 decode (gchar *enc)
826 {
827  gchar *p, *w;
828 
829  /* Loop, convert +'s to blanks */
830  p = strchr (enc, '+');
831  while (p)
832  {
833  *p = ' ';
834  p = strchr (p, '+');
835  }
836 
837  p = strchr (enc, '%');
838  w = p;
839 
840  while (p)
841  {
842  gint ch, cl;
843  p++;
844  ch = *p - 0x30; /* ascii 0 = 0x30 */
845  if (9 < ch)
846  ch -= 0x11 - 10; /* uppercase A = 0x41 */
847  if (16 < ch)
848  ch -= 0x20; /* lowercase a = 0x61 */
849 
850  p++;
851  cl = *p - 0x30; /* ascii 0 = 0x30 */
852  if (9 < cl)
853  cl -= 0x11 - 10; /* uppercase A = 0x41 */
854  if (16 < cl)
855  cl -= 0x20; /* lowercase a = 0x61 */
856 
857  *w = (gchar) (ch << 4 | cl);
858 
859  do
860  {
861  ++w;
862  ++p;
863  *w = *p;
864  if (0x0 == *p)
865  {
866  p = 0;
867  break;
868  }
869  if ('%' == *p)
870  break;
871  }
872  while (*p);
873  }
874 }
875 
876 void
877 kvp_frame_add_url_encoding (KvpFrame * frame, const gchar *enc)
878 {
879  gchar *buff, *p;
880  if (!frame || !enc)
881  return;
882 
883  /* Loop over all key-value pairs in the encoded string */
884  buff = g_strdup (enc);
885  p = buff;
886  while (*p)
887  {
888  gchar *n, *v;
889  n = strchr (p, '&'); /* n = next key-value */
890  if (n)
891  *n = 0x0;
892 
893  v = strchr (p, '='); /* v = pointer to value */
894  if (!v)
895  break;
896  *v = 0x0;
897  v++;
898 
899  decode (p);
900  decode (v);
901  kvp_frame_set_slot_nc (frame, p, kvp_value_new_string (v));
902 
903  if (!n)
904  break; /* no next key, we are done */
905  p = ++n;
906  }
907 
908  g_free (buff);
909 }
910 
911 /* ============================================================ */
912 
913 
914 gint64
915 kvp_frame_get_gint64 (const KvpFrame * frame, const gchar *path)
916 {
917  gchar *key = NULL;
918  frame = get_trailer_or_null (frame, path, &key);
919  return kvp_value_get_gint64 (kvp_frame_get_slot (frame, key));
920 }
921 
922 gdouble
923 kvp_frame_get_double (const KvpFrame * frame, const gchar *path)
924 {
925  gchar *key = NULL;
926  frame = get_trailer_or_null (frame, path, &key);
927  return kvp_value_get_double (kvp_frame_get_slot (frame, key));
928 }
929 
931 kvp_frame_get_numeric (const KvpFrame * frame, const gchar *path)
932 {
933  gchar *key = NULL;
934  frame = get_trailer_or_null (frame, path, &key);
935  return kvp_value_get_numeric (kvp_frame_get_slot (frame, key));
936 }
937 
938 gchar *
939 kvp_frame_get_string (const KvpFrame * frame, const gchar *path)
940 {
941  gchar *key = NULL;
942  frame = get_trailer_or_null (frame, path, &key);
943  return kvp_value_get_string (kvp_frame_get_slot (frame, key));
944 }
945 
946 gboolean
947 kvp_frame_get_boolean (const KvpFrame * frame, const gchar * path)
948 {
949  gchar * key = NULL;
950  frame = get_trailer_or_null (frame, path, &key);
951  return kvp_value_get_boolean (kvp_frame_get_slot (frame, key));
952 }
953 
954 GUID *
955 kvp_frame_get_guid (const KvpFrame * frame, const gchar *path)
956 {
957  gchar *key = NULL;
958  frame = get_trailer_or_null (frame, path, &key);
959  return kvp_value_get_guid (kvp_frame_get_slot (frame, key));
960 }
961 
962 void *
963 kvp_frame_get_binary (const KvpFrame * frame, const gchar *path,
964  guint64 * size_return)
965 {
966  gchar *key = NULL;
967  frame = get_trailer_or_null (frame, path, &key);
968  return kvp_value_get_binary (kvp_frame_get_slot (frame, key),
969  size_return);
970 }
971 
972 QofTime *
973 kvp_frame_get_time (const KvpFrame * frame, const gchar *path)
974 {
975  gchar *key = NULL;
976  frame = get_trailer_or_null (frame, path, &key);
977  return kvp_value_get_time (kvp_frame_get_slot (frame, key));
978 }
979 
980 KvpFrame *
981 kvp_frame_get_frame (const KvpFrame * frame, const gchar *path)
982 {
983  gchar *key = NULL;
984  frame = get_trailer_or_null (frame, path, &key);
985  return kvp_value_get_frame (kvp_frame_get_slot (frame, key));
986 }
987 
988 KvpValue *
989 kvp_frame_get_value (const KvpFrame * frame, const gchar *path)
990 {
991  gchar *key = NULL;
992  frame = get_trailer_or_null (frame, path, &key);
993  return kvp_frame_get_slot (frame, key);
994 }
995 
996 /* ============================================================ */
997 
998 KvpFrame *
999 kvp_frame_get_frame_gslist (KvpFrame * frame, GSList * key_path)
1000 {
1001  if (!frame)
1002  return frame;
1003 
1004  while (key_path)
1005  {
1006  const gchar *key = key_path->data;
1007 
1008  if (!key)
1009  return frame; /* an unusual but valid exit for this routine. */
1010 
1011  frame = get_or_make (frame, key);
1012  if (!frame)
1013  return frame; /* this should never happen */
1014 
1015  key_path = key_path->next;
1016  }
1017  return frame; /* this is the normal exit for this func */
1018 }
1019 
1020 KvpFrame *
1021 kvp_frame_get_frame_path (KvpFrame * frame, const gchar *key, ...)
1022 {
1023  va_list ap;
1024  if (!frame || !key)
1025  return frame;
1026 
1027  va_start (ap, key);
1028 
1029  while (key)
1030  {
1031  frame = get_or_make (frame, key);
1032  if (!frame)
1033  break; /* error, should never occur */
1034  key = va_arg (ap, const char *);
1035  }
1036 
1037  va_end (ap);
1038  return frame;
1039 }
1040 
1041 KvpFrame *
1042 kvp_frame_get_frame_slash (KvpFrame * frame, const gchar *key_path)
1043 {
1044  gchar *root;
1045  if (!frame || !key_path)
1046  return frame;
1047 
1048  root = g_strdup (key_path);
1049  frame = kvp_frame_get_frame_slash_trash (frame, root);
1050  g_free (root);
1051  return frame;
1052 }
1053 
1054 /* ============================================================ */
1055 
1056 KvpValue *
1057 kvp_frame_get_slot_path (KvpFrame * frame, const gchar *first_key, ...)
1058 {
1059  va_list ap;
1060  KvpValue *value;
1061  const gchar *key;
1062 
1063  if (!frame || !first_key)
1064  return NULL;
1065 
1066  va_start (ap, first_key);
1067 
1068  key = first_key;
1069  value = NULL;
1070 
1071  while (TRUE)
1072  {
1073  value = kvp_frame_get_slot (frame, key);
1074  if (!value)
1075  break;
1076 
1077  key = va_arg (ap, const gchar *);
1078  if (!key)
1079  break;
1080 
1081  frame = kvp_value_get_frame (value);
1082  if (!frame)
1083  {
1084  value = NULL;
1085  break;
1086  }
1087  }
1088 
1089  va_end (ap);
1090 
1091  return value;
1092 }
1093 
1094 KvpValue *
1095 kvp_frame_get_slot_path_gslist (KvpFrame * frame, GSList * key_path)
1096 {
1097  if (!frame || !key_path)
1098  return NULL;
1099 
1100  while (TRUE)
1101  {
1102  const gchar *key = key_path->data;
1103  KvpValue *value;
1104 
1105  if (!key)
1106  return NULL;
1107 
1108  value = kvp_frame_get_slot (frame, key);
1109  if (!value)
1110  return NULL;
1111 
1112  key_path = key_path->next;
1113  if (!key_path)
1114  return value;
1115 
1116  frame = kvp_value_get_frame (value);
1117  if (!frame)
1118  return NULL;
1119  }
1120 }
1121 
1122 /* *******************************************************************
1123  * kvp glist functions
1124  ********************************************************************/
1125 
1126 void
1127 kvp_glist_delete (GList * list)
1128 {
1129  GList *node;
1130  if (!list)
1131  return;
1132 
1133  /* Delete the data in the list */
1134  for (node = list; node; node = node->next)
1135  {
1136  KvpValue *val = node->data;
1137  kvp_value_delete (val);
1138  }
1139 
1140  /* Free the backbone */
1141  g_list_free (list);
1142 }
1143 
1144 GList *
1145 kvp_glist_copy (const GList * list)
1146 {
1147  GList *retval = NULL;
1148  GList *lptr;
1149 
1150  if (!list)
1151  return retval;
1152 
1153  /* Duplicate the backbone of the list (this duplicates the POINTERS
1154  * to the values; we need to deep-copy the values separately) */
1155  retval = g_list_copy ((GList *) list);
1156 
1157  /* This step deep-copies the values */
1158  for (lptr = retval; lptr; lptr = lptr->next)
1159  {
1160  lptr->data = kvp_value_copy (lptr->data);
1161  }
1162 
1163  return retval;
1164 }
1165 
1166 gint
1167 kvp_glist_compare (const GList * list1, const GList * list2)
1168 {
1169  const GList *lp1;
1170  const GList *lp2;
1171 
1172  if (list1 == list2)
1173  return 0;
1174 
1175  /* Nothing is always less than something */
1176  if (!list1 && list2)
1177  return -1;
1178  if (list1 && !list2)
1179  return 1;
1180 
1181  lp1 = list1;
1182  lp2 = list2;
1183  while (lp1 && lp2)
1184  {
1185  KvpValue *v1 = (KvpValue *) lp1->data;
1186  KvpValue *v2 = (KvpValue *) lp2->data;
1187  gint vcmp = kvp_value_compare (v1, v2);
1188  if (vcmp != 0)
1189  return vcmp;
1190  lp1 = lp1->next;
1191  lp2 = lp2->next;
1192  }
1193  if (!lp1 && lp2)
1194  return -1;
1195  if (!lp2 && lp1)
1196  return 1;
1197  return 0;
1198 }
1199 
1200 /* *******************************************************************
1201  * KvpValue functions
1202  ********************************************************************/
1203 
1204 KvpValue *
1205 kvp_value_new_gint64 (gint64 value)
1206 {
1207  KvpValue *retval = g_new0 (KvpValue, 1);
1208  retval->type = KVP_TYPE_GINT64;
1209  retval->value.int64 = value;
1210  return retval;
1211 }
1212 
1213 KvpValue *
1214 kvp_value_new_double (gdouble value)
1215 {
1216  KvpValue *retval = g_new0 (KvpValue, 1);
1217  retval->type = KVP_TYPE_DOUBLE;
1218  retval->value.dbl = value;
1219  return retval;
1220 }
1221 
1222 KvpValue *
1223 kvp_value_new_boolean (gboolean value)
1224 {
1225  KvpValue * retval = g_new0 (KvpValue, 1);
1226  retval->type = KVP_TYPE_BOOLEAN;
1227  retval->value.gbool = value;
1228  return retval;
1229 }
1230 
1231 KvpValue *
1232 kvp_value_new_numeric (QofNumeric value)
1233 {
1234  KvpValue *retval = g_new0 (KvpValue, 1);
1235  retval->type = KVP_TYPE_NUMERIC;
1236  retval->value.numeric = value;
1237  return retval;
1238 }
1239 
1240 KvpValue *
1241 kvp_value_new_string (const gchar *value)
1242 {
1243  KvpValue *retval;
1244  if (!value)
1245  return NULL;
1246 
1247  retval = g_new0 (KvpValue, 1);
1248  retval->type = KVP_TYPE_STRING;
1249  retval->value.str = g_strdup (value);
1250  return retval;
1251 }
1252 
1253 KvpValue *
1254 kvp_value_new_guid (const GUID * value)
1255 {
1256  KvpValue *retval;
1257  if (!value)
1258  return NULL;
1259 
1260  retval = g_new0 (KvpValue, 1);
1261  retval->type = KVP_TYPE_GUID;
1262  retval->value.guid = g_new0 (GUID, 1);
1263  memcpy (retval->value.guid, value, sizeof (GUID));
1264  return retval;
1265 }
1266 
1267 KvpValue *
1268 kvp_value_new_time (QofTime *value)
1269 {
1270  KvpValue *retval = g_new0 (KvpValue, 1);
1271  retval->type = KVP_TYPE_TIME;
1272  retval->value.qt = value;
1273  return retval;
1274 }
1275 
1276 KvpValue *
1277 kvp_value_new_binary (gconstpointer value, guint64 datasize)
1278 {
1279  KvpValue *retval;
1280  if (!value)
1281  return NULL;
1282 
1283  retval = g_new0 (KvpValue, 1);
1284  retval->type = KVP_TYPE_BINARY;
1285  retval->value.binary.data = g_new0 (gpointer, datasize);
1286  retval->value.binary.datasize = datasize;
1287  memcpy (retval->value.binary.data, value, datasize);
1288  return retval;
1289 }
1290 
1291 KvpValue *
1292 kvp_value_new_binary_nc (gpointer value, guint64 datasize)
1293 {
1294  KvpValue *retval;
1295  if (!value)
1296  return NULL;
1297 
1298  retval = g_new0 (KvpValue, 1);
1299  retval->type = KVP_TYPE_BINARY;
1300  retval->value.binary.data = value;
1301  retval->value.binary.datasize = datasize;
1302  return retval;
1303 }
1304 
1305 KvpValue *
1306 kvp_value_new_glist (const GList * value)
1307 {
1308  KvpValue *retval;
1309  if (!value)
1310  return NULL;
1311 
1312  retval = g_new0 (KvpValue, 1);
1313  retval->type = KVP_TYPE_GLIST;
1314  retval->value.list = kvp_glist_copy (value);
1315  return retval;
1316 }
1317 
1318 KvpValue *
1319 kvp_value_new_glist_nc (GList * value)
1320 {
1321  KvpValue *retval;
1322  if (!value)
1323  return NULL;
1324 
1325  retval = g_new0 (KvpValue, 1);
1326  retval->type = KVP_TYPE_GLIST;
1327  retval->value.list = value;
1328  return retval;
1329 }
1330 
1331 KvpValue *
1332 kvp_value_new_frame (const KvpFrame * value)
1333 {
1334  KvpValue *retval;
1335  if (!value)
1336  return NULL;
1337 
1338  retval = g_new0 (KvpValue, 1);
1339  retval->type = KVP_TYPE_FRAME;
1340  retval->value.frame = kvp_frame_copy (value);
1341  return retval;
1342 }
1343 
1344 KvpValue *
1346 {
1347  KvpValue *retval;
1348  if (!value)
1349  return NULL;
1350 
1351  retval = g_new0 (KvpValue, 1);
1352  retval->type = KVP_TYPE_FRAME;
1353  retval->value.frame = value;
1354  return retval;
1355 }
1356 
1357 void
1359 {
1360  if (!value)
1361  return;
1362 
1363  switch (value->type)
1364  {
1365  case KVP_TYPE_STRING:
1366  g_free (value->value.str);
1367  break;
1368  case KVP_TYPE_GUID:
1369  g_free (value->value.guid);
1370  break;
1371  case KVP_TYPE_BINARY:
1372  g_free (value->value.binary.data);
1373  break;
1374  case KVP_TYPE_GLIST:
1375  kvp_glist_delete (value->value.list);
1376  break;
1377  case KVP_TYPE_FRAME:
1378  kvp_frame_delete (value->value.frame);
1379  break;
1380  case KVP_TYPE_BOOLEAN:
1381  case KVP_TYPE_GINT64:
1382  case KVP_TYPE_DOUBLE:
1383  case KVP_TYPE_NUMERIC:
1384  default:
1385  break;
1386  }
1387  g_free (value);
1388 }
1389 
1391 kvp_value_get_type (const KvpValue * value)
1392 {
1393  if (!value)
1394  return QOF_FATAL;
1395  return value->type;
1396 }
1397 
1398 gint64
1400 {
1401  if (!value)
1402  return 0;
1403  if (value->type == KVP_TYPE_GINT64)
1404  return value->value.int64;
1405  else
1406  {
1407  PERR (" value type %d does not match KVP_TYPE_GINT64",
1408  value->type);
1409  return 0;
1410  }
1411 }
1412 
1413 gdouble
1414 kvp_value_get_double (const KvpValue * value)
1415 {
1416  if (!value)
1417  return 0.0;
1418  if (value->type == KVP_TYPE_DOUBLE)
1419  return value->value.dbl;
1420  else
1421  {
1422  PERR (" value type %d does not match KVP_TYPE_DOUBLE",
1423  value->type);
1424  return 0.0;
1425  }
1426 }
1427 
1428 QofNumeric
1429 kvp_value_get_numeric (const KvpValue * value)
1430 {
1431  if (!value)
1432  return qof_numeric_zero ();
1433  if (value->type == KVP_TYPE_NUMERIC)
1434  return value->value.numeric;
1435  else
1436  {
1437  PERR (" value type %d does not match KVP_TYPE_NUMERIC",
1438  value->type);
1439  return qof_numeric_zero ();
1440  }
1441 }
1442 
1443 gchar *
1445 {
1446  if (!value)
1447  return NULL;
1448  if (value->type == KVP_TYPE_STRING)
1449  return value->value.str;
1450  else
1451  {
1452  PERR (" value type %d does not match KVP_TYPE_STRING",
1453  value->type);
1454  return NULL;
1455  }
1456 }
1457 
1458 gboolean
1459 kvp_value_get_boolean (const KvpValue * value)
1460 {
1461  if (!value)
1462  return FALSE;
1463  if (value->type == KVP_TYPE_BOOLEAN)
1464  return value->value.gbool;
1465  else
1466  {
1467  PERR (" value type %d does not match KVP_TYPE_BOOLEAN",
1468  value->type);
1469  return FALSE;
1470  }
1471 }
1472 
1473 GUID *
1475 {
1476  if (!value)
1477  return NULL;
1478  if (value->type == KVP_TYPE_GUID)
1479  return value->value.guid;
1480  else
1481  {
1482  PERR (" value type %d does not match KVP_TYPE_GUID",
1483  value->type);
1484  return NULL;
1485  }
1486 }
1487 
1488 QofTime*
1489 kvp_value_get_time (const KvpValue * value)
1490 {
1491  if (!value)
1492  return NULL;
1493  if (value->type == KVP_TYPE_TIME)
1494  return value->value.qt;
1495  else
1496  {
1497  PERR (" value type %d does not match KVP_TYPE_TIME",
1498  value->type);
1499  return NULL;
1500  }
1501 }
1502 
1503 void *
1504 kvp_value_get_binary (const KvpValue * value, guint64 * size_return)
1505 {
1506  if (!value)
1507  {
1508  if (size_return)
1509  *size_return = 0;
1510  PERR (" no size specified");
1511  return NULL;
1512  }
1513 
1514  if (value->type == KVP_TYPE_BINARY)
1515  {
1516  if (size_return)
1517  *size_return = value->value.binary.datasize;
1518  return value->value.binary.data;
1519  }
1520  else
1521  {
1522  if (size_return)
1523  *size_return = 0;
1524  PERR (" value type %d does not match KVP_TYPE_BINARY",
1525  value->type);
1526  return NULL;
1527  }
1528 }
1529 
1530 GList *
1532 {
1533  if (!value)
1534  return NULL;
1535  if (value->type == KVP_TYPE_GLIST)
1536  return value->value.list;
1537  else
1538  {
1539  PERR (" value type %d does not match KVP_TYPE_GLIST",
1540  value->type);
1541  return NULL;
1542  }
1543 }
1544 
1545 KvpFrame *
1547 {
1548  if (!value)
1549  return NULL;
1550  if (value->type == KVP_TYPE_FRAME)
1551  return value->value.frame;
1552  else
1553  {
1554  PERR (" value type %d does not match KVP_TYPE_FRAME",
1555  value->type);
1556  return NULL;
1557  }
1558 }
1559 
1560 KvpFrame *
1562 {
1563  KvpFrame *oldframe;
1564  if (!value)
1565  return NULL;
1566  if (KVP_TYPE_FRAME != value->type)
1567  {
1568  PERR (" value type %d does not match KVP_TYPE_FRAME",
1569  value->type);
1570  return NULL;
1571  }
1572  oldframe = value->value.frame;
1573  value->value.frame = newframe;
1574  return oldframe;
1575 }
1576 
1577 GList *
1578 kvp_value_replace_glist_nc (KvpValue * value, GList * newlist)
1579 {
1580  GList *oldlist;
1581  if (!value)
1582  return NULL;
1583  if (KVP_TYPE_GLIST != value->type)
1584  {
1585  PERR (" value type %d does not match KVP_TYPE_GLIST",
1586  value->type);
1587  return NULL;
1588  }
1589 
1590  oldlist = value->value.list;
1591  value->value.list = newlist;
1592  return oldlist;
1593 }
1594 
1595 /* manipulators */
1596 
1597 KvpValue *
1598 kvp_value_copy (const KvpValue * value)
1599 {
1600  if (!value)
1601  return NULL;
1602 
1603  switch (value->type)
1604  {
1605  case KVP_TYPE_GINT64:
1606  return kvp_value_new_gint64 (value->value.int64);
1607  break;
1608  case KVP_TYPE_DOUBLE:
1609  return kvp_value_new_double (value->value.dbl);
1610  break;
1611  case KVP_TYPE_NUMERIC:
1612  return kvp_value_new_numeric (value->value.numeric);
1613  break;
1614  case KVP_TYPE_STRING:
1615  return kvp_value_new_string (value->value.str);
1616  break;
1617  case KVP_TYPE_GUID:
1618  return kvp_value_new_guid (value->value.guid);
1619  break;
1620  case KVP_TYPE_BOOLEAN:
1621  return NULL;
1622  return kvp_value_new_boolean (value->value.gbool);
1623  break;
1624  case KVP_TYPE_TIME :
1625  return kvp_value_new_time (value->value.qt);
1626  break;
1627  case KVP_TYPE_BINARY:
1628  return kvp_value_new_binary (value->value.binary.data,
1629  value->value.binary.datasize);
1630  break;
1631  case KVP_TYPE_GLIST:
1632  return kvp_value_new_glist (value->value.list);
1633  break;
1634  case KVP_TYPE_FRAME:
1635  return kvp_value_new_frame (value->value.frame);
1636  break;
1637  }
1638  return NULL;
1639 }
1640 
1641 void
1643 {
1644  if (!f)
1645  return;
1646  if (!proc)
1647  return;
1648  if (!(f->hash))
1649  return;
1650  g_hash_table_foreach (f->hash, (GHFunc) proc, data);
1651 }
1652 
1653 gint
1654 kvp_value_compare (const KvpValue * kva, const KvpValue * kvb)
1655 {
1656  if (kva == kvb)
1657  return 0;
1658  /* nothing is always less than something */
1659  if (!kva && kvb)
1660  return -1;
1661  if (kva && !kvb)
1662  return 1;
1663 
1664  if (kva->type < kvb->type)
1665  return -1;
1666  if (kva->type > kvb->type)
1667  return 1;
1668 
1669  switch (kva->type)
1670  {
1671  case KVP_TYPE_GINT64:
1672  if (kva->value.int64 < kvb->value.int64)
1673  return -1;
1674  if (kva->value.int64 > kvb->value.int64)
1675  return 1;
1676  return 0;
1677  break;
1678  case KVP_TYPE_DOUBLE:
1679  return qof_util_double_compare (kva->value.dbl, kvb->value.dbl);
1680  break;
1681  case KVP_TYPE_NUMERIC:
1682  return qof_numeric_compare (kva->value.numeric,
1683  kvb->value.numeric);
1684  break;
1685  case KVP_TYPE_STRING:
1686  return strcmp (kva->value.str, kvb->value.str);
1687  break;
1688  case KVP_TYPE_GUID:
1689  return guid_compare (kva->value.guid, kvb->value.guid);
1690  break;
1691  case KVP_TYPE_BOOLEAN:
1692  {
1693  /* true > false */
1694  if (kva->value.gbool != kvb->value.gbool)
1695  return (kva->value.gbool) ? 1 : -1;
1696  return 0;
1697  break;
1698  }
1699  case KVP_TYPE_TIME :
1700  return qof_time_cmp (kva->value.qt, kvb->value.qt);
1701  break;
1702  case KVP_TYPE_BINARY:
1703  if (kva->value.binary.datasize < kvb->value.binary.datasize)
1704  return -1;
1705  if (kva->value.binary.datasize > kvb->value.binary.datasize)
1706  return 1;
1707  return memcmp (kva->value.binary.data,
1708  kvb->value.binary.data, kva->value.binary.datasize);
1709  break;
1710  case KVP_TYPE_GLIST:
1711  return kvp_glist_compare (kva->value.list, kvb->value.list);
1712  break;
1713  case KVP_TYPE_FRAME:
1714  return kvp_frame_compare (kva->value.frame, kvb->value.frame);
1715  break;
1716  }
1717  return 0;
1718 }
1719 
1720 typedef struct
1721 {
1722  gint compare;
1723  KvpFrame *other_frame;
1724 } KvpFrameCompare;
1725 
1726 static void
1727 kvp_frame_compare_helper (const gchar *key, KvpValue * val, gpointer data)
1728 {
1729  KvpFrameCompare *status = (KvpFrameCompare *) data;
1730  if (status->compare == 0)
1731  {
1732  KvpFrame *other_frame = status->other_frame;
1733  KvpValue *other_val = kvp_frame_get_slot (other_frame, key);
1734 
1735  if (other_val)
1736  status->compare = kvp_value_compare (val, other_val);
1737  else
1738  status->compare = 1;
1739  }
1740 }
1741 
1742 gint
1743 kvp_frame_compare (const KvpFrame * fa, const KvpFrame * fb)
1744 {
1745  KvpFrameCompare status;
1746 
1747  if (fa == fb)
1748  return 0;
1749  /* nothing is always less than something */
1750  if (!fa && fb)
1751  return -1;
1752  if (fa && !fb)
1753  return 1;
1754 
1755  /* nothing is always less than something */
1756  if (!fa->hash && fb->hash)
1757  return -1;
1758  if (fa->hash && !fb->hash)
1759  return 1;
1760 
1761  status.compare = 0;
1762  status.other_frame = (KvpFrame *) fb;
1763 
1764  kvp_frame_for_each_slot ((KvpFrame *) fa, kvp_frame_compare_helper,
1765  &status);
1766 
1767  if (status.compare != 0)
1768  return status.compare;
1769 
1770  status.other_frame = (KvpFrame *) fa;
1771 
1772  kvp_frame_for_each_slot ((KvpFrame *) fb, kvp_frame_compare_helper,
1773  &status);
1774 
1775  return (-status.compare);
1776 }
1777 
1778 /* FIXME: genuine binary content cannot be made a string reliably. */
1779 gchar *
1780 binary_to_string (gconstpointer data, guint32 size)
1781 {
1782  GString *output;
1783  guint32 i;
1784  guchar *data_str = (guchar *) data;
1785 
1786  output = g_string_sized_new (size * sizeof (gchar));
1787 
1788  for (i = 0; i < size; i++)
1789  {
1790  g_string_append_printf (output, "%02x",
1791  (guint32) (data_str[i]));
1792  }
1793 
1794  return output->str;
1795 }
1796 
1797 gchar *
1798 kvp_value_glist_to_string (const GList * list)
1799 {
1800  gchar *tmp1;
1801  gchar *tmp2;
1802  const GList *cursor;
1803 
1804  tmp1 = g_strdup_printf ("[ ");
1805 
1806  for (cursor = list; cursor; cursor = cursor->next)
1807  {
1808  gchar *tmp3;
1809 
1810  tmp3 = kvp_value_to_string ((KvpValue *) cursor->data);
1811  tmp2 = g_strdup_printf ("%s %s,", tmp1, tmp3 ? tmp3 : "");
1812  g_free (tmp1);
1813  g_free (tmp3);
1814  tmp1 = tmp2;
1815  }
1816 
1817  tmp2 = g_strdup_printf ("%s ]", tmp1);
1818  g_free (tmp1);
1819 
1820  return tmp2;
1821 }
1822 
1823 static void
1824 kvp_frame_to_bare_string_helper (gpointer key __attribute__ ((unused)),
1825  gpointer value, gpointer data)
1826 {
1827  gchar **str = (gchar **) data;
1828  *str =
1829  g_strdup_printf ("%s",
1830  kvp_value_to_bare_string ((KvpValue *) value));
1831 }
1832 
1833 gchar *
1835 {
1836  gchar *tmp1;
1837  gchar *tmp2;
1838  const gchar *ctmp;
1839 
1840  g_return_val_if_fail (val, NULL);
1841  tmp1 = g_strdup ("");
1842  switch (kvp_value_get_type (val))
1843  {
1844  case KVP_TYPE_GINT64:
1845  {
1846  return g_strdup_printf ("%" G_GINT64_FORMAT,
1847  kvp_value_get_gint64 (val));
1848  break;
1849  }
1850  case KVP_TYPE_DOUBLE:
1851  {
1852  return g_strdup_printf ("(%g)", kvp_value_get_double (val));
1853  break;
1854  }
1855  case KVP_TYPE_NUMERIC:
1856  {
1857  tmp1 = qof_numeric_to_string (kvp_value_get_numeric (val));
1858  tmp2 = g_strdup_printf ("%s", tmp1 ? tmp1 : "");
1859  g_free (tmp1);
1860  return tmp2;
1861  break;
1862  }
1863  case KVP_TYPE_STRING:
1864  {
1865  tmp1 = kvp_value_get_string (val);
1866  return g_strdup_printf ("%s", tmp1 ? tmp1 : "");
1867  break;
1868  }
1869  case KVP_TYPE_GUID:
1870  {
1871  ctmp = guid_to_string (kvp_value_get_guid (val));
1872  tmp2 = g_strdup_printf ("%s", ctmp ? ctmp : "");
1873  return tmp2;
1874  break;
1875  }
1876  case KVP_TYPE_BOOLEAN :
1877  return (kvp_value_get_boolean (val)) ? "TRUE" : "FALSE";
1878  case KVP_TYPE_BINARY:
1879  {
1880  guint64 len;
1881  gpointer data;
1882  data = kvp_value_get_binary (val, &len);
1883  tmp1 = binary_to_string (data, len);
1884  return g_strdup_printf ("%s", tmp1 ? tmp1 : "");
1885  break;
1886  }
1887  case KVP_TYPE_GLIST:
1888  /* borked. kvp_value_glist_to_string is a debug fcn */
1889  {
1890  tmp1 = kvp_value_glist_to_string (kvp_value_get_glist (val));
1891  tmp2 = g_strdup_printf ("%s", tmp1 ? tmp1 : "");
1892  g_free (tmp1);
1893  return tmp2;
1894  break;
1895  }
1896  case KVP_TYPE_FRAME:
1897  {
1898  KvpFrame *frame;
1899 
1900  frame = kvp_value_get_frame (val);
1901  if (frame->hash)
1902  {
1903  tmp1 = g_strdup ("");
1904  g_hash_table_foreach (frame->hash,
1905  kvp_frame_to_bare_string_helper, &tmp1);
1906  }
1907  return tmp1;
1908  break;
1909  }
1910  default:
1911  return g_strdup_printf (" ");
1912  break;
1913  }
1914 }
1915 
1916 gchar *
1918 {
1919  gchar *tmp1;
1920  gchar *tmp2;
1921  const gchar *ctmp;
1922 
1923  g_return_val_if_fail (val, NULL);
1924 
1925  switch (kvp_value_get_type (val))
1926  {
1927  case KVP_TYPE_GINT64:
1928  {
1929  return g_strdup_printf ("KVP_VALUE_GINT64(%" G_GINT64_FORMAT ")",
1930  kvp_value_get_gint64 (val));
1931  break;
1932  }
1933  case KVP_TYPE_DOUBLE:
1934  {
1935  return g_strdup_printf ("KVP_VALUE_DOUBLE(%g)",
1936  kvp_value_get_double (val));
1937  break;
1938  }
1939  case KVP_TYPE_NUMERIC:
1940  {
1941  tmp1 = qof_numeric_to_string (kvp_value_get_numeric (val));
1942  tmp2 = g_strdup_printf ("KVP_VALUE_NUMERIC(%s)", tmp1 ? tmp1 : "");
1943  g_free (tmp1);
1944  return tmp2;
1945  break;
1946  }
1947  case KVP_TYPE_STRING:
1948  {
1949  tmp1 = kvp_value_get_string (val);
1950  return g_strdup_printf ("KVP_VALUE_STRING(%s)", tmp1 ? tmp1 : "");
1951  break;
1952  }
1953  case KVP_TYPE_GUID:
1954  {
1955  /* THREAD-UNSAFE */
1956  ctmp = guid_to_string (kvp_value_get_guid (val));
1957  tmp2 = g_strdup_printf ("KVP_VALUE_GUID(%s)", ctmp ? ctmp : "");
1958  return tmp2;
1959  break;
1960  }
1961  case KVP_TYPE_BINARY:
1962  {
1963  guint64 len;
1964  gpointer data;
1965  data = kvp_value_get_binary (val, &len);
1966  tmp1 = binary_to_string (data, len);
1967  return g_strdup_printf ("KVP_VALUE_BINARY(%s)",
1968  tmp1 ? tmp1 : "");
1969  break;
1970  }
1971  case KVP_TYPE_GLIST:
1972  {
1973  tmp1 = kvp_value_glist_to_string (kvp_value_get_glist (val));
1974  tmp2 = g_strdup_printf ("KVP_VALUE_GLIST(%s)", tmp1 ? tmp1 : "");
1975  g_free (tmp1);
1976  return tmp2;
1977  break;
1978  }
1979  case KVP_TYPE_FRAME:
1980  {
1981  tmp1 = kvp_frame_to_string (kvp_value_get_frame (val));
1982  tmp2 = g_strdup_printf ("KVP_VALUE_FRAME(%s)", tmp1 ? tmp1 : "");
1983  g_free (tmp1);
1984  return tmp2;
1985  break;
1986  }
1987  default:
1988  return g_strdup_printf (" ");
1989  break;
1990  }
1991 }
1992 
1993 static void
1994 kvp_frame_to_string_helper (gpointer key, gpointer value, gpointer data)
1995 {
1996  gchar *tmp_val;
1997  gchar **str = (gchar **) data;
1998  gchar *old_data = *str;
1999 
2000  tmp_val = kvp_value_to_string ((KvpValue *) value);
2001 
2002  *str = g_strdup_printf ("%s %s => %s,\n",
2003  *str ? *str : "", key ? (gchar *) key : "", tmp_val ? tmp_val : "");
2004 
2005  g_free (old_data);
2006  g_free (tmp_val);
2007 }
2008 
2009 gchar *
2010 kvp_frame_to_string (const KvpFrame * frame)
2011 {
2012  gchar *tmp1;
2013 
2014  g_return_val_if_fail (frame != NULL, NULL);
2015 
2016  tmp1 = g_strdup_printf ("{\n");
2017 
2018  if (frame->hash)
2019  g_hash_table_foreach (frame->hash, kvp_frame_to_string_helper,
2020  &tmp1);
2021  {
2022  gchar *tmp2;
2023  tmp2 = g_strdup_printf ("%s}\n", tmp1);
2024  g_free (tmp1);
2025  tmp1 = tmp2;
2026  }
2027 
2028  return tmp1;
2029 }
2030 
2031 GHashTable *
2032 kvp_frame_get_hash (const KvpFrame * frame)
2033 {
2034  g_return_val_if_fail (frame != NULL, NULL);
2035  return frame->hash;
2036 }
2037 
2038 /* ========================== END OF FILE ======================= */
GUID * kvp_value_get_guid(const KvpValue *value)
Definition: kvpframe.c:1474
KvpFrame * kvp_frame_get_frame_path(KvpFrame *frame, const gchar *key,...)
Definition: kvpframe.c:1021
#define PERR(format, args...)
Definition: qoflog.h:183
void kvp_frame_add_time(KvpFrame *frame, const gchar *path, QofTime *qt)
Add the value of the QofTime to the glist bag.
Definition: kvpframe.c:619
gint qof_numeric_compare(QofNumeric a, QofNumeric b)
Definition: qofnumeric.c:169
GList * kvp_value_replace_glist_nc(KvpValue *value, GList *newlist)
Definition: kvpframe.c:1578
GList * kvp_glist_copy(const GList *list)
Definition: kvpframe.c:1145
void kvp_frame_set_guid(KvpFrame *frame, const gchar *path, const GUID *guid)
Store a copy of the GUID at the indicated path.
Definition: kvpframe.c:450
KvpValueType
possible types in the union KvpValue
Definition: kvpframe.h:87
void kvp_frame_set_numeric(KvpFrame *frame, const gchar *path, QofNumeric nval)
store the value of the QofNumeric at the indicated path.
Definition: kvpframe.c:417
Unique identifier.
Definition: kvpframe.h:118
void kvp_frame_set_frame_nc(KvpFrame *frame, const gchar *path, KvpFrame *fr)
Store a KvpFrame at the indicated path without copying.
Definition: kvpframe.c:471
void kvp_frame_set_time(KvpFrame *frame, const gchar *path, QofTime *qt)
Store a copy of the QofTime at the indicated path.
Definition: kvpframe.c:407
KvpFrame * kvp_frame_add_value(KvpFrame *frame, const gchar *path, KvpValue *value)
Add a copy of the value to the glist bag.
Definition: kvpframe.c:578
void kvp_frame_add_frame_nc(KvpFrame *frame, const gchar *path, KvpFrame *fr)
Add the frame to the glist bag without copying.
Definition: kvpframe.c:669
gint kvp_frame_compare(const KvpFrame *fa, const KvpFrame *fb)
Definition: kvpframe.c:1743
KvpFrame * kvp_frame_get_frame_slash(KvpFrame *frame, const gchar *key_path)
Definition: kvpframe.c:1042
KvpFrame * kvp_frame_copy(const KvpFrame *frame)
Definition: kvpframe.c:153
struct _KvpFrame KvpFrame
Definition: kvpframe.h:74
void kvp_frame_set_slot_path(KvpFrame *frame, const KvpValue *new_value, const gchar *first_key,...)
Definition: kvpframe.c:723
gint kvp_glist_compare(const GList *list1, const GList *list2)
Definition: kvpframe.c:1167
void kvp_frame_set_gint64(KvpFrame *frame, const gchar *path, gint64 ival)
store the value of the gint64 at the indicated path.
Definition: kvpframe.c:387
KvpValue * kvp_value_new_boolean(gboolean value)
Definition: kvpframe.c:1223
gboolean kvp_frame_is_empty(KvpFrame *frame)
Definition: kvpframe.c:134
#define LEAVE(format, args...)
Definition: qoflog.h:227
KvpValue * kvp_value_new_frame_nc(KvpFrame *value)
Definition: kvpframe.c:1345
void kvp_frame_set_slot_path_gslist(KvpFrame *frame, const KvpValue *new_value, GSList *key_path)
Definition: kvpframe.c:776
KvpFrame * kvp_frame_get_frame_gslist(KvpFrame *frame, GSList *key_path)
Definition: kvpframe.c:999
KvpFrame * kvp_frame_set_value(KvpFrame *frame, const gchar *key_path, const KvpValue *value)
Copy the KvpValue into the frame.
Definition: kvpframe.c:496
void * kvp_value_get_binary(const KvpValue *value, guint64 *size_return)
Definition: kvpframe.c:1504
128bit denominator/numerator maths.
Definition: kvpframe.h:106
void kvp_frame_add_url_encoding(KvpFrame *frame, const gchar *enc)
Definition: kvpframe.c:877
void kvp_frame_delete(KvpFrame *frame)
Definition: kvpframe.c:115
gint64 kvp_value_get_gint64(const KvpValue *value)
Definition: kvpframe.c:1399
KvpValue * kvp_frame_replace_value_nc(KvpFrame *frame, const gchar *key_path, KvpValue *new_value)
Definition: kvpframe.c:513
void kvp_frame_set_frame(KvpFrame *frame, const gchar *path, KvpFrame *fr)
Store a copy of the KvpFrame at the indicated path.
Definition: kvpframe.c:461
void(* KvpValueForeachCB)(const gchar *key, KvpValue *value, gpointer data)
Definition: kvpframe.h:766
struct _KvpValue KvpValue
Definition: kvpframe.h:78
KvpValue * kvp_frame_replace_slot_nc(KvpFrame *frame, const gchar *slot, KvpValue *new_value)
Definition: kvpframe.c:175
gpointer qof_util_string_cache_insert(gconstpointer key)
Definition: qofutil.c:456
void kvp_frame_set_slot(KvpFrame *frame, const gchar *slot, const KvpValue *value)
Definition: kvpframe.c:681
void qof_util_string_cache_remove(gconstpointer key)
Definition: qofutil.c:450
KvpValue * kvp_value_copy(const KvpValue *value)
Definition: kvpframe.c:1598
const char * guid_to_string(const GUID *guid)
Definition: guid.c:568
gint qof_time_cmp(const QofTime *ta, const QofTime *tb)
Definition: qoftime.c:165
KvpValue * kvp_value_new_binary_nc(void *data, guint64 datasize)
64bit integer
Definition: kvpframe.h:94
void kvp_frame_add_double(KvpFrame *frame, const gchar *path, gdouble dval)
Add the value of the double to the glist bag.
Definition: kvpframe.c:598
void kvp_frame_set_slot_nc(KvpFrame *frame, const gchar *slot, KvpValue *value)
Definition: kvpframe.c:697
void kvp_frame_set_boolean(KvpFrame *frame, const gchar *path, gboolean val)
Store the value of the boolean at the indicated path.
Definition: kvpframe.c:428
GList * kvp_value_get_glist(const KvpValue *value)
Definition: kvpframe.c:1531
gchar * kvp_value_to_bare_string(const KvpValue *val)
General purpose function to convert any KvpValue to a string.
Definition: kvpframe.c:1834
KvpFrame * kvp_value_replace_frame_nc(KvpValue *value, KvpFrame *newframe)
Definition: kvpframe.c:1561
void kvp_glist_delete(GList *list)
Definition: kvpframe.c:1127
gchar * kvp_value_get_string(const KvpValue *value)
Definition: kvpframe.c:1444
void kvp_frame_add_frame(KvpFrame *frame, const gchar *path, KvpFrame *fr)
Copy the frame to the glist bag at the indicated path.
Definition: kvpframe.c:659
void kvp_frame_add_string(KvpFrame *frame, const gchar *path, const gchar *str)
Copy the string to the glist bag at the indicated path.
Definition: kvpframe.c:639
KvpValue * kvp_frame_get_slot_path(KvpFrame *frame, const gchar *first_key,...)
Definition: kvpframe.c:1057
KvpFrame * kvp_frame_set_value_nc(KvpFrame *frame, const gchar *key_path, KvpValue *value)
Store the KvpValue in the frame without copying.
Definition: kvpframe.c:483
void kvp_frame_for_each_slot(KvpFrame *f, KvpValueForeachCB proc, gpointer data)
Definition: kvpframe.c:1642
Definition: guid.h:53
gchar * qof_numeric_to_string(QofNumeric n)
Definition: qofnumeric.c:1084
KvpValue * kvp_value_new_glist(const GList *value)
Definition: kvpframe.c:1306
KvpValue * kvp_value_new_glist_nc(GList *value)
Definition: kvpframe.c:1319
struct QofTime64 QofTime
Use a 64-bit signed int QofTime.
Definition: qoftime.h:112
Simple boolean type.
Definition: kvpframe.h:136
void kvp_frame_add_gint64(KvpFrame *frame, const gchar *path, gint64 ival)
add the value of the gint64 to the glist bag
Definition: kvpframe.c:588
gint qof_util_double_compare(gdouble d1, gdouble d2)
Compare two gdouble values.
Definition: qofutil.c:182
standard C string
Definition: kvpframe.h:112
#define QOF_FATAL
general error value
Definition: qoferror.h:131
static QofNumeric qof_numeric_zero(void)
Definition: qofnumeric.h:253
void kvp_frame_set_double(KvpFrame *frame, const gchar *path, gdouble dval)
store the value of the double at the indicated path.
Definition: kvpframe.c:397
KvpFrame * kvp_frame_new(void)
Definition: kvpframe.c:97
KvpFrame * kvp_value_get_frame(const KvpValue *value)
Definition: kvpframe.c:1546
standard C double type
Definition: kvpframe.h:100
KvpFrame * kvp_frame_get_frame(const KvpFrame *frame, const gchar *path)
Definition: kvpframe.c:981
void kvp_value_delete(KvpValue *value)
Definition: kvpframe.c:1358
KvpValue * kvp_frame_get_slot_path_gslist(KvpFrame *frame, GSList *key_path)
Definition: kvpframe.c:1095
gint kvp_value_compare(const KvpValue *kva, const KvpValue *kvb)
Definition: kvpframe.c:1654
#define ENTER(format, args...)
Definition: qoflog.h:217
gchar * kvp_value_to_string(const KvpValue *val)
Debug version.
Definition: kvpframe.c:1917
const gchar * QofLogModule
Definition: qofid.h:85
void kvp_frame_set_string(KvpFrame *frame, const gchar *path, const gchar *str)
Store a copy of the string at the indicated path.
Definition: kvpframe.c:439
void kvp_frame_add_numeric(KvpFrame *frame, const gchar *path, QofNumeric nval)
Add the value of the QofNumeric to the glist bag.
Definition: kvpframe.c:608
64bit time/date handling.
Definition: kvpframe.h:124
void kvp_frame_add_guid(KvpFrame *frame, const gchar *path, const GUID *guid)
Copy the GUID to the glist bag at the indicated path.
Definition: kvpframe.c:649