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 *
qof_kvp_array_va(KvpFrame * kvp_root,const gchar * path,QofTime * qt,const gchar * first_name,va_list ap)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 *
qof_kvp_bag_add(KvpFrame * pwd,const gchar * path,QofTime * qt,const gchar * first_name,...)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 *
qof_kvp_bag_find_by_guid(KvpFrame * root,const gchar * path,const gchar * guid_name,GUID * desired_guid)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
qof_kvp_bag_remove_frame(KvpFrame * root,const gchar * path,KvpFrame * fr)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 *
qof_kvp_bag_get_first(KvpFrame * root,const gchar * path)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
qof_kvp_bag_merge(KvpFrame * kvp_into,const gchar * intopath,KvpFrame * kvp_from,const gchar * frompath)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
kv_pair_helper(gpointer key,gpointer val,gpointer user_data)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 *
g_hash_table_key_value_pairs(GHashTable * table)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
g_hash_table_kv_pair_free_gfunc(gpointer data,gpointer user_data)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 KvpValueType
qof_id_to_kvp_value_type(QofIdTypeConst type_string)228 qof_id_to_kvp_value_type (QofIdTypeConst type_string)
229 {
230 if (0 == safe_strcmp (QOF_TYPE_INT64, type_string))
231 return KVP_TYPE_GINT64;
232 if (0 == safe_strcmp (QOF_TYPE_DOUBLE, type_string))
233 return KVP_TYPE_DOUBLE;
234 if (0 == safe_strcmp (QOF_TYPE_NUMERIC, type_string))
235 return KVP_TYPE_NUMERIC;
236 if (0 == safe_strcmp (QOF_TYPE_STRING, type_string))
237 return KVP_TYPE_STRING;
238 if (0 == safe_strcmp (QOF_TYPE_GUID, type_string))
239 return KVP_TYPE_GUID;
240 if (0 == safe_strcmp (QOF_TYPE_TIME, type_string))
241 return KVP_TYPE_TIME;
242 return 0;
243 }
244
245 QofIdTypeConst
kvp_value_type_to_qof_id(KvpValueType n)246 kvp_value_type_to_qof_id (KvpValueType n)
247 {
248 switch (n)
249 {
250 case KVP_TYPE_GINT64:
251 {
252 return QOF_TYPE_INT64;
253 break;
254 }
255 case KVP_TYPE_DOUBLE:
256 {
257 return QOF_TYPE_DOUBLE;
258 break;
259 }
260 case KVP_TYPE_NUMERIC:
261 {
262 return QOF_TYPE_NUMERIC;
263 break;
264 }
265 case KVP_TYPE_STRING:
266 {
267 return QOF_TYPE_STRING;
268 break;
269 }
270 case KVP_TYPE_GUID:
271 {
272 return QOF_TYPE_GUID;
273 break;
274 }
275 case KVP_TYPE_BOOLEAN :
276 {
277 return QOF_TYPE_BOOLEAN;
278 break;
279 }
280 case KVP_TYPE_TIME :
281 {
282 return QOF_TYPE_TIME;
283 break;
284 }
285 default:
286 {
287 return NULL;
288 }
289 }
290 }
291
292 /*======================== END OF FILE =============================*/
293