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