Fix includes and add prototypes for serializing/unserializing the
[mmediamanager.git] / src / mm-string-utils.c
blobbd16a8c0e5ff70c76d4d8aba967eb98cd4fda26a
1 /* MManager - a Desktop wide manager for multimedia applications.
3 * Copyright (C) 2008 Cosimo Cecchi <cosimoc@gnome.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
21 #include <glib.h>
22 #include <string.h>
23 #include <libxml/tree.h>
24 #include <libxml/xmlwriter.h>
25 #include <libxml/xmlreader.h>
26 #include "mm-string-utils.h"
27 #include "mm-utils.h"
29 typedef struct {
30 MMComparisionOperator op;
31 const char *string;
32 } OperatorGrid;
34 static OperatorGrid operator_grid[] =
36 { MM_COMP_EQUAL, "EQ" },
37 { MM_COMP_GREATER, "GR" },
38 { MM_COMP_GREATER_EQUAL, "GRQ" },
39 { MM_COMP_LESS, "LS" },
40 { MM_COMP_LESS_EQUAL, "LSQ" },
41 { MM_COMP_NONE, "" }
44 static xmlChar *
45 value_to_string (GValue *v)
47 xmlChar *safe;
48 char *ret = NULL;
49 GType type = G_VALUE_TYPE (v);
51 /* guess the most used cases and handle those first */
52 if (type == G_TYPE_STRING) {
53 ret = g_strdup (g_value_get_string (v));
54 } else if (type == G_TYPE_BOOLEAN) {
55 ret = g_strdup_printf ("%d", g_value_get_boolean (v));
56 } else if (type == G_TYPE_INT) {
57 ret = g_strdup_printf ("%d", g_value_get_int (v));
58 } else if (type == G_TYPE_FLOAT) {
59 ret = g_strdup_printf ("%f", g_value_get_float (v));
60 } else if (type == G_TYPE_DOUBLE) {
61 char double_buff[G_ASCII_DTOSTR_BUF_SIZE];
62 ret = g_ascii_dtostr (double_buff, sizeof (double_buff),
63 g_value_get_double (v));
64 } else if (type == G_TYPE_LONG) {
65 ret = g_strdup_printf ("%ld", g_value_get_long (v));
66 } else if (type == G_TYPE_INT64) {
67 ret = g_strdup_printf ("%lld", g_value_get_int64 (v));
68 } else if (type == G_TYPE_UINT) {
69 ret = g_strdup_printf ("%u", g_value_get_uint (v));
70 } else if (type == G_TYPE_ULONG) {
71 ret = g_strdup_printf ("%lu", g_value_get_ulong (v));
72 } else if (type == G_TYPE_UINT64) {
73 ret = g_strdup_printf ("%llu", g_value_get_uint64 (v));
74 } else if (G_VALUE_HOLDS_CHAR (v)) {
75 ret = g_strdup_printf ("%c", g_value_get_char (v));
76 } else if (G_VALUE_HOLDS_UCHAR (v)) {
77 ret = g_strdup_printf ("%c", g_value_get_uchar (v));
78 } else {
79 g_warning ("Can't convert the value to string: unhandled type");
80 return NULL;
83 safe = xmlCharStrdup (ret);
84 g_free (ret);
85 return safe;
88 static xmlChar *
89 op_to_string (MMComparisionOperator op)
91 int idx;
93 for (idx = 0; idx < G_N_ELEMENTS (operator_grid); idx++) {
94 if (op == operator_grid[idx].op) {
95 return xmlCharStrdup (operator_grid[idx].string);
99 return NULL;
102 static void
103 add_filter_param_to_xml (MMFilterParam *fp,
104 xmlTextWriterPtr writer)
106 MMAttribute *attribute;
107 xmlChar *safe_str;
109 attribute = mm_filter_param_get_attribute (fp);
111 xmlTextWriterStartElement (writer, BAD_CAST ("filter-param"));
113 xmlTextWriterStartElement (writer, BAD_CAST ("attribute"));
114 safe_str = xmlCharStrdup (mm_attribute_get_id (attribute));
115 xmlTextWriterWriteAttribute (writer, BAD_CAST ("id"), safe_str);
116 g_free (safe_str);
117 safe_str = xmlCharStrdup (mm_attribute_get_name (attribute));
118 xmlTextWriterWriteAttribute (writer, BAD_CAST ("name"), safe_str);
119 g_free (safe_str);
120 safe_str = xmlCharStrdup (mm_attribute_get_description (attribute));
121 xmlTextWriterWriteAttribute (writer, BAD_CAST ("description"), safe_str);
122 g_free (safe_str);
123 xmlTextWriterWriteAttribute (writer, BAD_CAST ("type"), BAD_CAST (g_type_name (mm_attribute_get_value_type (attribute))));
124 /* close "attribute" */
125 xmlTextWriterEndElement (writer);
127 safe_str = value_to_string (mm_filter_param_get_value (fp));
128 xmlTextWriterWriteElement (writer, BAD_CAST ("value"), safe_str);
129 g_free (safe_str);
131 safe_str = op_to_string (mm_filter_param_get_operator (fp));
132 xmlTextWriterWriteElement (writer, BAD_CAST ("op"), safe_str);
133 g_free (safe_str);
135 /* close "filter-param" */
136 xmlTextWriterEndElement (writer);
139 static int
140 unserialize_operator (xmlTextReaderPtr reader, MMComparisionOperator *op)
142 const xmlChar * op_string;
143 gboolean found = FALSE;
144 int idx, res;
146 /* we should be on <op> */
147 if (xmlStrcmp (xmlTextReaderConstName (reader), BAD_CAST ("op")) != 0) {
148 g_warning ("Error while parsing the serialized xml opeator");
149 return -1;
152 /* move on to the content */
153 res = xmlTextReaderRead (reader);
154 if (res <= 0) {
155 g_warning ("Error while parsing the serialized xml operator");
156 return res;
159 op_string = xmlTextReaderConstValue (reader);
160 for (idx = 0; idx < G_N_ELEMENTS (operator_grid); idx++) {
161 if (xmlStrcmp (op_string, BAD_CAST (operator_grid[idx].string)) == 0) {
162 found = TRUE;
163 break;
167 if (found) {
168 *op = operator_grid[idx].op;
169 res = xmlTextReaderRead (reader);
170 if (res <= 0) {
171 g_warning ("Error while parsing the serialized xml operator");
172 return res;
174 return xmlTextReaderRead (reader);
175 } else {
176 g_warning ("Error while parsing the serialized xml operator");
177 return -1;
181 static int
182 unserialize_value (xmlTextReaderPtr reader, GValue *v)
184 int res;
185 GType type;
186 const char *val_string;
188 /* we should be on <value> */
189 if (xmlStrcmp (xmlTextReaderConstName (reader), BAD_CAST ("value")) != 0) {
190 g_warning ("Error while parsing the serialized xml value");
191 return -1;
194 /* move on to the content node */
195 res = xmlTextReaderRead (reader);
196 if (res <= 0) {
197 g_warning ("Error while parsing the serialized xml value");
198 return res;
201 type = G_VALUE_TYPE (v);
202 val_string = (const char *) xmlTextReaderConstValue (reader);
204 if (type == G_TYPE_STRING) {
205 g_value_set_string (v, val_string);
206 } else if (type == G_TYPE_BOOLEAN) {
207 gboolean bval;
208 sscanf (val_string, "%d", &bval);
209 g_value_set_boolean (v, bval);
210 } else if (type == G_TYPE_INT) {
211 gint ival;
212 sscanf (val_string, "%d", &ival);
213 g_value_set_int (v, ival);
214 } else if (type == G_TYPE_FLOAT) {
215 gfloat fval;
216 sscanf (val_string, "%f", &fval);
217 g_value_set_float (v, fval);
218 } else if (type == G_TYPE_DOUBLE) {
219 gdouble dval;
220 dval = g_ascii_strtod (val_string, NULL);
221 g_value_set_double (v, dval);
222 } else if (type == G_TYPE_LONG) {
223 glong lval;
224 sscanf (val_string, "%ld", &lval);
225 g_value_set_long (v, lval);
226 } else if (type == G_TYPE_INT64) {
227 g_value_set_int64 (v, g_ascii_strtoll (val_string, NULL, 0));
228 } else if (type == G_TYPE_UINT) {
229 guint uval;
230 sscanf (val_string, "%u", &uval);
231 g_value_set_uint (v, uval);
232 } else if (type == G_TYPE_ULONG) {
233 gulong ulval;
234 sscanf (val_string, "%lu", &ulval);
235 g_value_set_ulong (v, ulval);
236 } else if (type == G_TYPE_UINT64) {
237 g_value_set_uint64 (v, g_ascii_strtoull (val_string, NULL, 0));
238 } else if (G_VALUE_HOLDS_CHAR (v)) {
239 gchar cval;
240 sscanf (val_string, "%c", &cval);
241 g_value_set_char (v, cval);
242 } else if (G_VALUE_HOLDS_UCHAR (v)) {
243 guchar ucval;
244 sscanf (val_string, "%c", &ucval);
245 g_value_set_uchar (v, ucval);
246 } else {
247 g_warning ("Can't convert the string to a value: unhandled type");
250 /* move over </value> */
251 res = xmlTextReaderRead (reader);
252 if (res <= 0) {
253 g_warning ("Error while parsing the serialized xml value");
254 return res;
257 return xmlTextReaderRead (reader);
260 static int
261 unserialize_attribute (xmlTextReaderPtr reader, MMAttribute **attribute)
263 xmlChar *id, *name, *desc, *type_name;
264 GType type;
266 /* we should be on <attribute> */
267 if (xmlStrcmp (xmlTextReaderConstName (reader), BAD_CAST ("attribute")) != 0) {
268 g_warning ("Error while parsing the serialized xml attribute");
269 return -1;
272 id = xmlTextReaderGetAttribute (reader, BAD_CAST ("id"));
273 name = xmlTextReaderGetAttribute (reader, BAD_CAST ("name"));
274 desc = xmlTextReaderGetAttribute (reader, BAD_CAST ("desc"));
275 type_name = xmlTextReaderGetAttribute (reader, BAD_CAST ("type"));
277 type = g_type_from_name ((const char *) type_name);
278 if (type == 0) {
279 g_warning ("Error while parsing the serialized xml attribute");
280 return -1;
283 *attribute = mm_attribute_new (type,
284 (const char *) id,
285 (const char *) name,
286 (const char *) desc);
288 g_free (id);
289 g_free (name);
290 g_free (desc);
291 g_free (type_name);
293 return xmlTextReaderRead (reader);
296 static MMFilterParam *
297 unserialize_filter_param (xmlTextReaderPtr reader)
299 int res;
300 MMAttribute *attribute = NULL;
301 MMComparisionOperator op = MM_COMP_NONE;
302 GValue *val = NULL;
303 MMFilterParam *fp;
305 res = xmlTextReaderRead (reader);
306 /* we're either on <attribute> or </filter-param> if the object is empty */
307 while (!((xmlTextReaderNodeType (reader) == XML_READER_TYPE_END_ELEMENT) &&
308 xmlStrcmp (xmlTextReaderConstName (reader), BAD_CAST ("filter-param")) == 0) && res > 0) {
309 res = unserialize_attribute (reader, &attribute);
310 if (res <= 0) {
311 break;
313 val = mm_create_gvalue_for_attribute (attribute);
314 res = unserialize_value (reader, val);
315 if (res <= 0) {
316 break;
318 res = unserialize_operator (reader, &op);
319 if (res <= 0) {
320 break;
324 if (res == -1) {
325 g_warning ("Error while parsing the serialized xml filter param");
326 return NULL;
329 if (attribute == NULL || op == MM_COMP_NONE || val == NULL) {
330 g_warning ("Error while parsing the serialized xml filter param");
331 return NULL;
334 fp = mm_filter_param_new (attribute, val, op);
335 return fp;
338 /* public functions */
339 char *
340 mm_filter_serialize (MMFilter *filter)
342 char *serialized;
343 xmlBufferPtr buffer;
344 xmlTextWriterPtr writer;
345 GList *filter_params;
347 buffer = xmlBufferCreate ();
348 writer = xmlNewTextWriterMemory (buffer, 0);
350 xmlTextWriterStartDocument (writer, NULL, NULL, NULL);
352 xmlTextWriterStartElement (writer, BAD_CAST ("filter"));
353 filter_params = mm_filter_get_filtering_params (filter);
354 g_list_foreach (filter_params, (GFunc) add_filter_param_to_xml, writer);
355 /* close "filter" */
356 xmlTextWriterEndElement (writer);
358 xmlTextWriterEndDocument (writer);
360 xmlFreeTextWriter (writer);
361 serialized = g_strdup ((char *) xmlBufferContent (buffer));
362 xmlBufferFree (buffer);
364 return serialized;
367 MMFilter *
368 mm_filter_unserialize (const char *s)
370 MMFilter *f;
371 MMFilterParam *fp;
372 xmlTextReaderPtr reader;
373 int res;
374 const xmlChar *node_name;
376 f = mm_filter_new ();
377 reader = xmlReaderForMemory (s, strlen (s), NULL, NULL, 0);
379 /* cut all the elements before <filter> */
380 do {
381 res = xmlTextReaderRead (reader);
382 node_name = xmlTextReaderConstName (reader);
383 } while (xmlStrcmp (node_name, BAD_CAST ("filter")) != 0);
385 res = xmlTextReaderRead (reader);
386 /* we're either on the first <filter-param> or on </filter> if the
387 * object is empty. cycle until we're on </filter>.
389 while (!((xmlTextReaderNodeType (reader) == XML_READER_TYPE_END_ELEMENT) &&
390 xmlStrcmp (xmlTextReaderConstName (reader), BAD_CAST ("filter")) == 0) && res > 0) {
391 fp = unserialize_filter_param (reader);
392 if (!fp) {
393 break;
395 mm_filter_add_filtering_param (f, fp);
396 res = xmlTextReaderRead (reader);
399 if (res == -1) {
400 g_warning ("Error while parsing the serialized filter.");
403 xmlFreeTextReader (reader);
405 return f;
408 char *
409 mm_hit_collection_serialize (MMHitCollection *hc)
411 /* TODO: implement */
412 return NULL;
415 MMHitCollection *
416 mm_hit_collection_unserialize (const char *s)
418 /* TODO: implement */
419 return NULL;