QOF  0.7.5
kvputil.c
1 /********************************************************************\
2  * kvp_util.c -- misc odd-job kvp utils *
3  * Copyright (C) 2001 Linas Vepstas <linas@linas.org> *
4  * Copyright (C) 2006 Neil Williams <linux@codehelp.co.uk> *
5  * *
6  * This program is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU General Public License as *
8  * published by the Free Software Foundation; either version 2 of *
9  * the License, or (at your option) any later version. *
10  * *
11  * This program is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14  * GNU General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU General Public License*
17  * along with this program; if not, contact: *
18  * *
19  * Free Software Foundation Voice: +1-617-542-5942 *
20  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
21  * Boston, MA 02110-1301, USA gnu@gnu.org *
22  * *
23 \********************************************************************/
24 
25 #include "config.h"
26 #include <glib.h>
27 #include <stdio.h>
28 #include "qof.h"
29 #include "kvputil-p.h"
30 
31 static KvpFrame *
32 qof_kvp_array_va (KvpFrame * kvp_root, const gchar *path,
33  QofTime *qt, const gchar *first_name, va_list ap)
34 {
35  KvpFrame *cwd;
36  const gchar *name;
37 
38  if (!kvp_root)
39  return NULL;
40  if (!first_name)
41  return NULL;
42 
43  /* Create subdirectory and put the actual data */
44  cwd = kvp_frame_new ();
45 
46  /* Record the time */
47  kvp_frame_set_time (cwd, "time", qt);
48 
49  /* Loop over the args */
50  name = first_name;
51  while (name)
52  {
53  const GUID *guid;
54  guid = va_arg (ap, const GUID *);
55 
56  kvp_frame_set_guid (cwd, name, guid);
57 
58  name = va_arg (ap, const char *);
59  }
60 
61  /* Attach cwd into the array */
62  kvp_frame_add_frame_nc (kvp_root, path, cwd);
63  return cwd;
64 }
65 
66 KvpFrame *
67 qof_kvp_bag_add (KvpFrame * pwd, const gchar *path,
68  QofTime *qt, const gchar *first_name, ...)
69 {
70  KvpFrame *cwd;
71  va_list ap;
72  va_start (ap, first_name);
73  cwd = qof_kvp_array_va (pwd, path, qt, first_name, ap);
74  va_end (ap);
75  return cwd;
76 }
77 
78 /* ================================================================ */
79 
80 #define MATCH_GUID(elt) { \
81  KvpFrame *fr = kvp_value_get_frame (elt); \
82  if (fr) { \
83  GUID *guid = kvp_frame_get_guid (fr, guid_name); \
84  if (guid && guid_equal (desired_guid, guid)) return fr; \
85  } \
86 }
87 
88 KvpFrame *
89 qof_kvp_bag_find_by_guid (KvpFrame * root, const gchar *path,
90  const gchar *guid_name, GUID * desired_guid)
91 {
92  KvpValue *arr;
93  KvpValueType valtype;
94  GList *node;
95 
96  arr = kvp_frame_get_value (root, path);
97  valtype = kvp_value_get_type (arr);
98  if (KVP_TYPE_FRAME == valtype)
99  {
100  MATCH_GUID (arr);
101  return NULL;
102  }
103 
104  /* Its got to be a single isolated frame, or a list of them. */
105  if (KVP_TYPE_GLIST != valtype)
106  return NULL;
107 
108  for (node = kvp_value_get_glist (arr); node; node = node->next)
109  {
110  KvpValue *va = node->data;
111  MATCH_GUID (va);
112  }
113  return NULL;
114 }
115 
116 /* ================================================================ */
117 
118 void
119 qof_kvp_bag_remove_frame (KvpFrame * root, const gchar *path, KvpFrame * fr)
120 {
121  KvpValue *arr;
122  KvpValueType valtype;
123  GList *node, *listhead;
124 
125  arr = kvp_frame_get_value (root, path);
126  valtype = kvp_value_get_type (arr);
127  if (KVP_TYPE_FRAME == valtype)
128  {
129  if (fr == kvp_value_get_frame (arr))
130  {
131  KvpValue *old_val =
132  kvp_frame_replace_value_nc (root, path, NULL);
133  kvp_value_replace_frame_nc (old_val, NULL);
134  kvp_value_delete (old_val);
135  }
136  return;
137  }
138 
139  /* Its got to be a single isolated frame, or a list of them. */
140  if (KVP_TYPE_GLIST != valtype)
141  return;
142 
143  listhead = kvp_value_get_glist (arr);
144  for (node = listhead; node; node = node->next)
145  {
146  KvpValue *va = node->data;
147  if (fr == kvp_value_get_frame (va))
148  {
149  listhead = g_list_remove_link (listhead, node);
150  g_list_free_1 (node);
151  kvp_value_replace_glist_nc (arr, listhead);
152  kvp_value_replace_frame_nc (va, NULL);
153  kvp_value_delete (va);
154  return;
155  }
156  }
157 }
158 
159 /* ================================================================ */
160 
161 static KvpFrame *
162 qof_kvp_bag_get_first (KvpFrame * root, const gchar *path)
163 {
164  KvpValue *arr, *va;
165  KvpValueType valtype;
166  GList *node;
167 
168  arr = kvp_frame_get_value (root, path);
169  valtype = kvp_value_get_type (arr);
170  if (KVP_TYPE_FRAME == valtype)
171  return kvp_value_get_frame (arr);
172 
173  /* Its gotta be a single isolated frame, or a list of them. */
174  if (KVP_TYPE_GLIST != valtype)
175  return NULL;
176 
177  node = kvp_value_get_glist (arr);
178  if (NULL == node)
179  return NULL;
180 
181  va = node->data;
182  return kvp_value_get_frame (va);
183 }
184 
185 void
186 qof_kvp_bag_merge (KvpFrame * kvp_into, const gchar *intopath,
187  KvpFrame * kvp_from, const gchar *frompath)
188 {
189  KvpFrame *fr;
190 
191  fr = qof_kvp_bag_get_first (kvp_from, frompath);
192  while (fr)
193  {
194  qof_kvp_bag_remove_frame (kvp_from, frompath, fr);
195  kvp_frame_add_frame_nc (kvp_into, intopath, fr);
196  fr = qof_kvp_bag_get_first (kvp_from, frompath);
197  }
198 }
199 
200 static void
201 kv_pair_helper (gpointer key, gpointer val, gpointer user_data)
202 {
203  GSList **result = (GSList **) user_data;
204  GHashTableKVPair *kvp = g_new0 (GHashTableKVPair, 1);
205 
206  kvp->key = key;
207  kvp->value = val;
208  *result = g_slist_prepend (*result, kvp);
209 }
210 
211 GSList *
212 g_hash_table_key_value_pairs (GHashTable * table)
213 {
214  GSList *result_list = NULL;
215  g_hash_table_foreach (table, kv_pair_helper, &result_list);
216  return result_list;
217 }
218 
219 void
220 g_hash_table_kv_pair_free_gfunc (gpointer data, gpointer user_data
221  __attribute__ ((unused)))
222 {
223  GHashTableKVPair *kvp = (GHashTableKVPair *) data;
224  g_free (kvp);
225 }
226 
227 /*======================== END OF FILE =============================*/