File: | build-analysis/../src/xmms/medialib_query_result.c |
Warning: | line 321, column 12 Function call argument is an uninitialized value |
1 | /* XMMS2 - X Music Multiplexer System | |||
2 | * Copyright (C) 2003-2017 XMMS2 Team | |||
3 | * | |||
4 | * PLUGINS ARE NOT CONSIDERED TO BE DERIVED WORK !!! | |||
5 | * | |||
6 | * This library is free software; you can redistribute it and/or | |||
7 | * modify it under the terms of the GNU Lesser General Public | |||
8 | * License as published by the Free Software Foundation; either | |||
9 | * version 2.1 of the License, or (at your option) any later version. | |||
10 | * | |||
11 | * This library 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 GNU | |||
14 | * Lesser General Public License for more details. | |||
15 | */ | |||
16 | ||||
17 | #include <xmmspriv/xmms_fetch_info.h> | |||
18 | #include <xmmspriv/xmms_fetch_spec.h> | |||
19 | #include "s4.h" | |||
20 | ||||
21 | #include <glib.h> | |||
22 | #include <glib/gstdio.h> | |||
23 | ||||
24 | xmmsv_t *xmms_medialib_query_to_xmmsv (s4_resultset_t *set, xmms_fetch_spec_t *spec); | |||
25 | ||||
26 | typedef struct { | |||
27 | gint64 sum; | |||
28 | gint n; | |||
29 | } avg_data_t; | |||
30 | ||||
31 | typedef struct { | |||
32 | xmmsv_t *data; | |||
33 | gint n; | |||
34 | } random_data_t; | |||
35 | ||||
36 | typedef struct { | |||
37 | GHashTable *ht; | |||
38 | xmmsv_t *list; | |||
39 | } set_data_t; | |||
40 | ||||
41 | static xmmsv_t * | |||
42 | aggregate_first (xmmsv_t *current, gint int_value, const gchar *str_value) | |||
43 | { | |||
44 | if (current != NULL((void*)0)) { | |||
45 | return current; | |||
46 | } | |||
47 | ||||
48 | if (str_value != NULL((void*)0)) { | |||
49 | current = xmmsv_new_string (str_value); | |||
50 | } else { | |||
51 | current = xmmsv_new_int (int_value); | |||
52 | } | |||
53 | ||||
54 | return current; | |||
55 | } | |||
56 | ||||
57 | static xmmsv_t * | |||
58 | aggregate_list (xmmsv_t *current, gint int_value, const gchar *str_value) | |||
59 | { | |||
60 | if (current == NULL((void*)0)) { | |||
61 | current = xmmsv_new_list (); | |||
62 | } | |||
63 | ||||
64 | if (str_value != NULL((void*)0)) { | |||
65 | xmmsv_list_append_string (current, str_value); | |||
66 | } else { | |||
67 | xmmsv_list_append_int (current, int_value); | |||
68 | } | |||
69 | ||||
70 | return current; | |||
71 | } | |||
72 | ||||
73 | static xmmsv_t * | |||
74 | aggregate_set (xmmsv_t *current, gint int_value, const gchar *str_value) | |||
75 | { | |||
76 | set_data_t *data; | |||
77 | xmmsv_t *value; | |||
78 | gpointer key; | |||
79 | guint length; | |||
80 | ||||
81 | if (current == NULL((void*)0)) { | |||
82 | set_data_t init = { | |||
83 | .ht = g_hash_table_new (NULL((void*)0), NULL((void*)0)), | |||
84 | .list = xmmsv_new_list () | |||
85 | }; | |||
86 | current = xmmsv_new_bin ((guchar *) &init, sizeof (set_data_t)); | |||
87 | } | |||
88 | ||||
89 | xmmsv_get_bin (current, (const guchar **) &data, &length); | |||
90 | ||||
91 | if (str_value != NULL((void*)0)) { | |||
92 | value = xmmsv_new_string (str_value); | |||
93 | key = (gpointer) str_value; | |||
94 | } else { | |||
95 | value = xmmsv_new_int (int_value); | |||
96 | key = GINT_TO_POINTER (int_value)((gpointer) (glong) (int_value)); | |||
97 | } | |||
98 | ||||
99 | if (g_hash_table_lookup (data->ht, key) == NULL((void*)0)) { | |||
100 | g_hash_table_insert (data->ht, key, value); | |||
101 | xmmsv_list_append (data->list, value); | |||
102 | } | |||
103 | ||||
104 | xmmsv_unref (value); | |||
105 | ||||
106 | return current; | |||
107 | } | |||
108 | ||||
109 | static xmmsv_t * | |||
110 | aggregate_sum (xmmsv_t *current, gint int_value, const gchar *str_value) | |||
111 | { | |||
112 | int64_t old_value = 0; | |||
113 | ||||
114 | if (str_value != NULL((void*)0)) { | |||
115 | /* 'sum' only applies to numbers */ | |||
116 | return current; | |||
117 | } | |||
118 | ||||
119 | if (current != NULL((void*)0)) { | |||
120 | xmmsv_get_int64 (current, &old_value); | |||
121 | } | |||
122 | ||||
123 | return xmmsv_new_int (old_value + int_value); | |||
124 | } | |||
125 | ||||
126 | static xmmsv_t * | |||
127 | aggregate_min (xmmsv_t *current, gint int_value, const gchar *str_value) | |||
128 | { | |||
129 | gint old_value; | |||
130 | ||||
131 | if (str_value != NULL((void*)0)) { | |||
132 | /* 'min' only applies to numbers */ | |||
133 | return current; | |||
134 | } | |||
135 | ||||
136 | if (current == NULL((void*)0)) { | |||
137 | return xmmsv_new_int (int_value); | |||
138 | } | |||
139 | ||||
140 | xmmsv_get_intxmmsv_get_int32 (current, &old_value); | |||
141 | ||||
142 | if (old_value > int_value) { | |||
143 | return xmmsv_new_int (int_value); | |||
144 | } | |||
145 | ||||
146 | return current; | |||
147 | } | |||
148 | ||||
149 | static xmmsv_t * | |||
150 | aggregate_max (xmmsv_t *current, gint int_value, const gchar *str_value) | |||
151 | { | |||
152 | gint old_value; | |||
153 | ||||
154 | if (str_value != NULL((void*)0)) { | |||
155 | /* 'max' only applies to numbers */ | |||
156 | return current; | |||
157 | } | |||
158 | ||||
159 | if (current == NULL((void*)0)) { | |||
160 | return xmmsv_new_int (int_value); | |||
161 | } | |||
162 | ||||
163 | xmmsv_get_intxmmsv_get_int32 (current, &old_value); | |||
164 | ||||
165 | if (old_value < int_value) { | |||
166 | return xmmsv_new_int (int_value); | |||
167 | } | |||
168 | ||||
169 | return current; | |||
170 | } | |||
171 | ||||
172 | static xmmsv_t * | |||
173 | aggregate_random (xmmsv_t *current, gint int_value, const gchar *str_value) | |||
174 | { | |||
175 | random_data_t *data; | |||
176 | guint length; | |||
177 | ||||
178 | if (current == NULL((void*)0)) { | |||
179 | random_data_t init = { 0 }; | |||
180 | current = xmmsv_new_bin ((guchar *) &init, sizeof (random_data_t)); | |||
181 | } | |||
182 | ||||
183 | xmmsv_get_bin (current, (const guchar **) &data, &length); | |||
184 | ||||
185 | data->n++; | |||
186 | ||||
187 | if (g_random_int_range (0, data->n) == 0) { | |||
188 | if (data->data != NULL((void*)0)) { | |||
189 | xmmsv_unref (data->data); | |||
190 | } | |||
191 | ||||
192 | if (str_value != NULL((void*)0)) { | |||
193 | data->data = xmmsv_new_string (str_value); | |||
194 | } else { | |||
195 | data->data = xmmsv_new_int (int_value); | |||
196 | } | |||
197 | } | |||
198 | ||||
199 | return current; | |||
200 | } | |||
201 | ||||
202 | static xmmsv_t * | |||
203 | aggregate_average (xmmsv_t *current, gint int_value, const gchar *str_value) | |||
204 | { | |||
205 | avg_data_t *data; | |||
206 | guint length; | |||
207 | ||||
208 | if (current == NULL((void*)0)) { | |||
209 | avg_data_t init = { 0 }; | |||
210 | current = xmmsv_new_bin ((guchar *) &init, sizeof (avg_data_t)); | |||
211 | } | |||
212 | ||||
213 | xmmsv_get_bin (current, (const guchar **) &data, &length); | |||
214 | ||||
215 | if (str_value == NULL((void*)0)) { | |||
216 | data->n++; | |||
217 | data->sum += int_value; | |||
218 | } | |||
219 | ||||
220 | return current; | |||
221 | } | |||
222 | ||||
223 | /* Converts an S4 result (a column) into an xmmsv values */ | |||
224 | static void * | |||
225 | result_to_xmmsv (xmmsv_t *ret, gint32 id, const s4_result_t *res, | |||
226 | xmms_fetch_spec_t *spec) | |||
227 | { | |||
228 | static xmmsv_t * (*aggregate_functions[AGGREGATE_END])(xmmsv_t *c, gint i, const gchar *s) = { | |||
229 | aggregate_first, | |||
230 | aggregate_sum, | |||
231 | aggregate_max, | |||
232 | aggregate_min, | |||
233 | aggregate_set, | |||
234 | aggregate_list, | |||
235 | aggregate_random, | |||
236 | aggregate_average | |||
237 | }; | |||
238 | const s4_val_t *val; | |||
239 | xmmsv_t *dict, *current; | |||
240 | const gchar *str_value, *key = NULL((void*)0); | |||
241 | gint32 i, int_value; | |||
| ||||
242 | xmmsv_t *newval; | |||
243 | ||||
244 | g_return_val_if_fail (spec->data.metadata.get_size > 0, ret)do{ if (spec->data.metadata.get_size > 0) { } else { g_return_if_fail_warning ("core", ((const char*) (__func__)), "spec->data.metadata.get_size > 0" ); return (ret); }; }while (0); | |||
245 | g_return_val_if_fail (spec->data.metadata.get_size <= METADATA_END, ret)do{ if (spec->data.metadata.get_size <= METADATA_END) { } else { g_return_if_fail_warning ("core", ((const char*) (__func__ )), "spec->data.metadata.get_size <= METADATA_END"); return (ret); }; }while (0); | |||
246 | g_return_val_if_fail (spec->data.metadata.aggr_func >= 0, ret)do{ if (spec->data.metadata.aggr_func >= 0) { } else { g_return_if_fail_warning ("core", ((const char*) (__func__)), "spec->data.metadata.aggr_func >= 0" ); return (ret); }; }while (0); | |||
247 | g_return_val_if_fail (spec->data.metadata.aggr_func < AGGREGATE_END, ret)do{ if (spec->data.metadata.aggr_func < AGGREGATE_END) { } else { g_return_if_fail_warning ("core", ((const char*) (__func__ )), "spec->data.metadata.aggr_func < AGGREGATE_END"); return (ret); }; }while (0); | |||
248 | ||||
249 | /* Loop through all the values the column has */ | |||
250 | while (res != NULL((void*)0)) { | |||
251 | dict = ret; | |||
252 | current = ret; | |||
253 | ||||
254 | /* Loop through the list of what to get ("key", "source", ..) */ | |||
255 | for (i = 0; i < spec->data.metadata.get_size; i++) { | |||
256 | str_value = NULL((void*)0); | |||
257 | int_value = 0; | |||
258 | ||||
259 | /* Fill str_value with the correct value if it is a string | |||
260 | * or int_value if it is an integer | |||
261 | */ | |||
262 | switch (spec->data.metadata.get[i]) { | |||
263 | case METADATA_KEY: | |||
264 | str_value = s4_result_get_key (res); | |||
265 | break; | |||
266 | case METADATA_SOURCE: | |||
267 | str_value = s4_result_get_src (res); | |||
268 | if (str_value == NULL((void*)0)) | |||
269 | str_value = "server"; | |||
270 | break; | |||
271 | case METADATA_ID: | |||
272 | int_value = id; | |||
273 | break; | |||
274 | case METADATA_VALUE: | |||
275 | val = s4_result_get_val (res); | |||
276 | ||||
277 | if (!s4_val_get_int (val, &int_value)) { | |||
278 | s4_val_get_str (val, &str_value); | |||
279 | } | |||
280 | break; | |||
281 | default: | |||
282 | g_assert_not_reached ()do { g_assertion_message_expr ("core", "../src/xmms/medialib_query_result.c" , 282, ((const char*) (__func__)), ((void*)0)); } while (0); | |||
283 | } | |||
284 | ||||
285 | /* If this is not the last property to get we use this property | |||
286 | * as a key in a dict | |||
287 | */ | |||
288 | if (i < (spec->data.metadata.get_size - 1)) { | |||
289 | /* Convert integers to strings */ | |||
290 | if (str_value == NULL((void*)0)) { | |||
291 | /* Big enough to hold 2^32 with minus sign */ | |||
292 | gchar buf[12]; | |||
293 | g_sprintf (buf, "%i", int_value); | |||
294 | key = buf; | |||
295 | } else { | |||
296 | key = str_value; | |||
297 | } | |||
298 | ||||
299 | /* Make sure the root dict exists */ | |||
300 | if (dict == NULL((void*)0)) { | |||
301 | ret = dict = xmmsv_new_dict (); | |||
302 | } | |||
303 | ||||
304 | /* If this dict contains dicts we have to create a new | |||
305 | * dict if one does not exists for the key yet | |||
306 | */ | |||
307 | if (!xmmsv_dict_get (dict, key, ¤t)) | |||
308 | current = NULL((void*)0); | |||
309 | ||||
310 | if (i < (spec->data.metadata.get_size - 2)) { | |||
311 | if (current == NULL((void*)0)) { | |||
312 | current = xmmsv_new_dict (); | |||
313 | xmmsv_dict_set (dict, key, current); | |||
314 | xmmsv_unref (current); | |||
315 | } | |||
316 | dict = current; | |||
317 | } | |||
318 | } | |||
319 | } | |||
320 | ||||
321 | newval = aggregate_functions[spec->data.metadata.aggr_func](current, int_value, str_value); | |||
| ||||
322 | ||||
323 | /* Update the previous dict (if there is one) */ | |||
324 | if (newval != current) { | |||
325 | if (i > 1) { | |||
326 | xmmsv_dict_set (dict, key, newval); | |||
327 | xmmsv_unref (newval); | |||
328 | } else { | |||
329 | ret = newval; | |||
330 | if (current != NULL((void*)0)) { | |||
331 | xmmsv_unref (current); | |||
332 | } | |||
333 | } | |||
334 | } | |||
335 | ||||
336 | res = s4_result_next (res); | |||
337 | } | |||
338 | ||||
339 | return ret; | |||
340 | } | |||
341 | ||||
342 | /* Converts the temporary value returned by result_to_xmmsv into the real value */ | |||
343 | static xmmsv_t * | |||
344 | aggregate_data (xmmsv_t *value, aggregate_function_t aggr_func) | |||
345 | { | |||
346 | const random_data_t *random_data; | |||
347 | const avg_data_t *avg_data; | |||
348 | const set_data_t *set_data; | |||
349 | gconstpointer data; | |||
350 | xmmsv_t *ret; | |||
351 | guint len; | |||
352 | ||||
353 | ret = NULL((void*)0); | |||
354 | data = NULL((void*)0); | |||
355 | ||||
356 | if (value != NULL((void*)0) && xmmsv_is_type (value, XMMSV_TYPE_BIN)) | |||
357 | xmmsv_get_bin (value, (const guchar **) &data, &len); | |||
358 | ||||
359 | switch (aggr_func) { | |||
360 | case AGGREGATE_FIRST: | |||
361 | case AGGREGATE_MIN: | |||
362 | case AGGREGATE_MAX: | |||
363 | case AGGREGATE_SUM: | |||
364 | if (value != NULL((void*)0)) { | |||
365 | ret = xmmsv_ref (value); | |||
366 | } else { | |||
367 | ret = xmmsv_new_none (); | |||
368 | } | |||
369 | break; | |||
370 | case AGGREGATE_LIST: | |||
371 | if (value != NULL((void*)0)) { | |||
372 | ret = xmmsv_ref (value); | |||
373 | } else { | |||
374 | ret = xmmsv_new_list (); | |||
375 | } | |||
376 | break; | |||
377 | case AGGREGATE_RANDOM: | |||
378 | random_data = data; | |||
379 | if (random_data != NULL((void*)0)) { | |||
380 | ret = random_data->data; | |||
381 | } else { | |||
382 | ret = xmmsv_new_none (); | |||
383 | } | |||
384 | break; | |||
385 | case AGGREGATE_SET: | |||
386 | set_data = data; | |||
387 | if (set_data != NULL((void*)0)) { | |||
388 | g_hash_table_destroy (set_data->ht); | |||
389 | ret = set_data->list; | |||
390 | } else { | |||
391 | ret = xmmsv_new_list (); | |||
392 | } | |||
393 | break; | |||
394 | case AGGREGATE_AVG: | |||
395 | avg_data = data; | |||
396 | if (avg_data != NULL((void*)0)) { | |||
397 | ret = xmmsv_new_float (avg_data->n ? avg_data->sum * 1.0 / avg_data->n : 0); | |||
398 | } else { | |||
399 | ret = xmmsv_new_none (); | |||
400 | } | |||
401 | break; | |||
402 | default: | |||
403 | g_assert_not_reached ()do { g_assertion_message_expr ("core", "../src/xmms/medialib_query_result.c" , 403, ((const char*) (__func__)), ((void*)0)); } while (0); | |||
404 | } | |||
405 | ||||
406 | if (value != NULL((void*)0)) { | |||
407 | xmmsv_unref (value); | |||
408 | } | |||
409 | ||||
410 | return ret; | |||
411 | } | |||
412 | ||||
413 | /* Applies an aggregation function to the leafs in an xmmsv dict tree */ | |||
414 | static xmmsv_t * | |||
415 | aggregate_result (xmmsv_t *val, gint depth, aggregate_function_t aggr_func) | |||
416 | { | |||
417 | xmmsv_dict_iter_t *it; | |||
418 | ||||
419 | if (depth == 0) { | |||
420 | return aggregate_data (val, aggr_func); | |||
421 | } | |||
422 | ||||
423 | if (val == NULL((void*)0) && depth > 0) { | |||
424 | return xmmsv_new_dict(); | |||
425 | } | |||
426 | ||||
427 | /* If it's a dict we call this function recursively on all its values */ | |||
428 | xmmsv_get_dict_iter (val, &it); | |||
429 | ||||
430 | while (xmmsv_dict_iter_valid (it)) { | |||
431 | xmmsv_t *entry; | |||
432 | ||||
433 | xmmsv_dict_iter_pair (it, NULL((void*)0), &entry); | |||
434 | xmmsv_ref (entry); | |||
435 | ||||
436 | entry = aggregate_result (entry, depth - 1, aggr_func); | |||
437 | xmmsv_dict_iter_set (it, entry); | |||
438 | xmmsv_unref (entry); | |||
439 | ||||
440 | xmmsv_dict_iter_next (it); | |||
441 | } | |||
442 | ||||
443 | return val; | |||
444 | } | |||
445 | ||||
446 | /* Converts an S4 resultset to an xmmsv using the fetch specification */ | |||
447 | static xmmsv_t * | |||
448 | metadata_to_xmmsv (s4_resultset_t *set, xmms_fetch_spec_t *spec) | |||
449 | { | |||
450 | const s4_resultrow_t *row; | |||
451 | xmmsv_t *ret = NULL((void*)0); | |||
452 | gint i; | |||
453 | ||||
454 | /* Loop over the rows in the resultset */ | |||
455 | for (i = 0; s4_resultset_get_row (set, i, &row); i++) { | |||
456 | gint32 id, j; | |||
457 | ||||
458 | s4_val_get_int (s4_result_get_val (s4_resultset_get_result (set, i, 0)), &id); | |||
459 | for (j = 0; j < spec->data.metadata.col_count; j++) { | |||
460 | const s4_result_t *res; | |||
461 | ||||
462 | if (s4_resultrow_get_col (row, spec->data.metadata.cols[j], &res)) { | |||
463 | ret = result_to_xmmsv (ret, id, res, spec); | |||
464 | } | |||
465 | } | |||
466 | } | |||
467 | ||||
468 | return aggregate_result (ret, spec->data.metadata.get_size - 1, | |||
469 | spec->data.metadata.aggr_func); | |||
470 | } | |||
471 | ||||
472 | ||||
473 | /* Divides an S4 set into a list of smaller sets with | |||
474 | * the same values for the cluster attributes | |||
475 | */ | |||
476 | static void | |||
477 | cluster_set (s4_resultset_t *set, xmms_fetch_spec_t *spec, | |||
478 | GHashTable *table, GList **list) | |||
479 | { | |||
480 | const s4_resultrow_t *row; | |||
481 | gint position; | |||
482 | ||||
483 | /* Run through all the rows in the result set. | |||
484 | * Uses a hash table to find the correct cluster to put the row in | |||
485 | */ | |||
486 | for (position = 0; s4_resultset_get_row (set, position, &row); position++) { | |||
487 | s4_resultset_t *cluster; | |||
488 | const s4_result_t *res; | |||
489 | const gchar *value = spec->data.cluster.fallback; | |||
490 | gchar buf[12]; | |||
491 | ||||
492 | if (spec->data.cluster.type == CLUSTER_BY_POSITION) { | |||
493 | g_snprintf (buf, sizeof (buf), "%i", position); | |||
494 | value = buf; | |||
495 | } else if (s4_resultrow_get_col (row, spec->data.cluster.column, &res)) { | |||
496 | const s4_val_t *val = s4_result_get_val (res); | |||
497 | if (!s4_val_get_str (val, &value)) { | |||
498 | gint32 ival; | |||
499 | s4_val_get_int (val, &ival); | |||
500 | g_snprintf (buf, sizeof (buf), "%i", ival); | |||
501 | value = buf; | |||
502 | } | |||
503 | } | |||
504 | ||||
505 | if (value == NULL((void*)0)) { | |||
506 | /* value not found, and no fallback provided */ | |||
507 | continue; | |||
508 | } | |||
509 | ||||
510 | cluster = g_hash_table_lookup (table, value); | |||
511 | if (cluster == NULL((void*)0)) { | |||
512 | cluster = s4_resultset_create (s4_resultset_get_colcount (set)); | |||
513 | g_hash_table_insert (table, g_strdup (value), cluster); | |||
514 | *list = g_list_prepend (*list, cluster); | |||
515 | } | |||
516 | s4_resultset_add_row (cluster, row); | |||
517 | } | |||
518 | } | |||
519 | ||||
520 | static GList * | |||
521 | cluster_list (s4_resultset_t *set, xmms_fetch_spec_t *spec) | |||
522 | { | |||
523 | GHashTable *table; | |||
524 | GList *list = NULL((void*)0); | |||
525 | ||||
526 | table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL((void*)0)); | |||
527 | cluster_set (set, spec, table, &list); | |||
528 | g_hash_table_destroy (table); | |||
529 | ||||
530 | return g_list_reverse (list); | |||
531 | } | |||
532 | ||||
533 | static GHashTable * | |||
534 | cluster_dict (s4_resultset_t *set, xmms_fetch_spec_t *spec) | |||
535 | { | |||
536 | GHashTable *table; | |||
537 | GList *list = NULL((void*)0); | |||
538 | ||||
539 | table = g_hash_table_new_full (g_str_hash, g_str_equal, | |||
540 | g_free, (GDestroyNotify) s4_resultset_free); | |||
541 | ||||
542 | cluster_set (set, spec, table, &list); | |||
543 | g_list_free (list); | |||
544 | ||||
545 | return table; | |||
546 | } | |||
547 | ||||
548 | static xmmsv_t * | |||
549 | convert_ghashtable_to_xmmsv (GHashTable *table, xmms_fetch_spec_t *spec) | |||
550 | { | |||
551 | GHashTableIter iter; | |||
552 | s4_resultset_t *value; | |||
553 | const gchar *key; | |||
554 | xmmsv_t *ret; | |||
555 | ||||
556 | g_hash_table_iter_init (&iter, table); | |||
557 | ||||
558 | ret = xmmsv_new_dict (); | |||
559 | ||||
560 | while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value)) { | |||
561 | xmmsv_t *converted; | |||
562 | ||||
563 | if (value == NULL((void*)0)) { | |||
564 | continue; | |||
565 | } | |||
566 | ||||
567 | converted = xmms_medialib_query_to_xmmsv (value, spec); | |||
568 | xmmsv_dict_set (ret, key, converted); | |||
569 | xmmsv_unref (converted); | |||
570 | } | |||
571 | ||||
572 | if (xmmsv_dict_get_size (ret) == 0) { | |||
573 | xmmsv_unref (ret); | |||
574 | ret = NULL((void*)0); | |||
575 | } | |||
576 | ||||
577 | return ret; | |||
578 | } | |||
579 | ||||
580 | /* Converts an S4 resultset into an xmmsv_t, based on the fetch specification */ | |||
581 | xmmsv_t * | |||
582 | xmms_medialib_query_to_xmmsv (s4_resultset_t *set, xmms_fetch_spec_t *spec) | |||
583 | { | |||
584 | GHashTable *set_table; | |||
585 | GList *sets; | |||
586 | xmmsv_t *val, *ret = NULL((void*)0); | |||
587 | gint i; | |||
588 | ||||
589 | switch (spec->type) { | |||
590 | case FETCH_COUNT: | |||
591 | ret = xmmsv_new_int (s4_resultset_get_rowcount (set)); | |||
592 | break; | |||
593 | case FETCH_METADATA: | |||
594 | ret = metadata_to_xmmsv (set, spec); | |||
595 | break; | |||
596 | case FETCH_ORGANIZE: | |||
597 | ret = xmmsv_new_dict (); | |||
598 | ||||
599 | for (i = 0; i < spec->data.organize.count; i++) { | |||
600 | val = xmms_medialib_query_to_xmmsv (set, spec->data.organize.data[i]); | |||
601 | if (val != NULL((void*)0)) { | |||
602 | xmmsv_dict_set (ret, spec->data.organize.keys[i], val); | |||
603 | xmmsv_unref (val); | |||
604 | } | |||
605 | } | |||
606 | break; | |||
607 | case FETCH_CLUSTER_LIST: | |||
608 | sets = cluster_list (set, spec); | |||
609 | ret = xmmsv_new_list (); | |||
610 | for (; sets != NULL((void*)0); sets = g_list_delete_link (sets, sets)) { | |||
611 | set = sets->data; | |||
612 | ||||
613 | val = xmms_medialib_query_to_xmmsv (set, spec->data.cluster.data); | |||
614 | if (val != NULL((void*)0)) { | |||
615 | xmmsv_list_append (ret, val); | |||
616 | xmmsv_unref (val); | |||
617 | } | |||
618 | s4_resultset_free (set); | |||
619 | } | |||
620 | break; | |||
621 | case FETCH_CLUSTER_DICT: | |||
622 | set_table = cluster_dict (set, spec); | |||
623 | ret = convert_ghashtable_to_xmmsv (set_table, spec->data.cluster.data); | |||
624 | ||||
625 | g_hash_table_destroy (set_table); | |||
626 | break; | |||
627 | default: | |||
628 | g_assert_not_reached ()do { g_assertion_message_expr ("core", "../src/xmms/medialib_query_result.c" , 628, ((const char*) (__func__)), ((void*)0)); } while (0); | |||
629 | } | |||
630 | ||||
631 | return ret; | |||
632 | } |