XMMS2
coll.c
Go to the documentation of this file.
1 /* XMMS2 - X Music Multiplexer System
2  * Copyright (C) 2003-2011 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 <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <ctype.h>
21 
22 #include "xmmsc/xmmsc_idnumbers.h"
23 #include "xmmsc/xmmsv.h"
24 #include "xmmsc/xmmsv_coll.h"
25 #include "xmmsc/xmmsc_util.h"
26 #include "xmmspriv/xmms_list.h"
27 
28 
29 struct xmmsv_coll_St {
30 
31  /* refcounting */
32  int ref;
33 
34  xmmsv_coll_type_t type;
35  xmmsv_t *operands;
36  xmmsv_t *attributes;
37  xmmsv_t *idlist;
38 
39  int32_t *legacy_idlist;
40 };
41 
42 
43 static void xmmsv_coll_free (xmmsv_coll_t *coll);
44 
45 
46 /**
47  * @defgroup CollectionStructure CollectionStructure
48  * @ingroup Collections
49  * @brief The API to be used to work with collection structures.
50  *
51  * @{
52  */
53 
54 /**
55  * Increases the references for the #xmmsv_coll_t
56  *
57  * @param coll the collection to reference.
58  * @return coll
59  */
62 {
63  x_return_val_if_fail (coll, NULL);
64 
65  coll->ref++;
66 
67  return coll;
68 }
69 
70 /**
71  * Allocate a new collection of the given type.
72  * The pointer will have to be deallocated using #xmmsv_coll_unref.
73  *
74  * @param type the #xmmsv_coll_type_t specifying the type of collection to create.
75  * @return a pointer to the newly created collection, or NULL if the type is invalid.
76  */
79 {
80  xmmsv_coll_t *coll;
81 
83 
84  coll = x_new0 (xmmsv_coll_t, 1);
85  if (!coll) {
86  x_oom ();
87  return NULL;
88  }
89 
90  coll->ref = 0;
91  coll->type = type;
92 
93  coll->idlist = xmmsv_new_list ();
95 
96  coll->operands = xmmsv_new_list ();
97  xmmsv_list_restrict_type (coll->operands, XMMSV_TYPE_COLL);
98 
99  coll->attributes = xmmsv_new_dict ();
100 
101  coll->legacy_idlist = NULL;
102 
103  /* user must give this back */
104  xmmsv_coll_ref (coll);
105 
106  return coll;
107 }
108 
109 /**
110  * Free the memory owned by the collection.
111  * You probably want to use #xmmsv_coll_unref instead, which handles
112  * reference counting.
113  *
114  * @param coll the collection to free.
115  */
116 static void
117 xmmsv_coll_free (xmmsv_coll_t *coll)
118 {
119  x_return_if_fail (coll);
120 
121  /* Unref all the operands and attributes */
122  xmmsv_unref (coll->operands);
123  xmmsv_unref (coll->attributes);
124  xmmsv_unref (coll->idlist);
125  if (coll->legacy_idlist) {
126  free (coll->legacy_idlist);
127  }
128 
129  free (coll);
130 }
131 
132 /**
133  * Decreases the references for the #xmmsv_coll_t
134  * When the number of references reaches 0 it will
135  * be freed and all its operands unreferenced as well.
136  *
137  * @param coll the collection to unref.
138  */
139 void
141 {
142  x_return_if_fail (coll);
143  x_api_error_if (coll->ref < 1, "with a freed collection",);
144 
145  coll->ref--;
146  if (coll->ref == 0) {
147  xmmsv_coll_free (coll);
148  }
149 }
150 
151 
152 /**
153  * Set the list of ids in the given collection.
154  * The list must be 0-terminated.
155  * Note that the idlist is only relevant for idlist collections.
156  *
157  * @param coll the collection to modify.
158  * @param ids the 0-terminated list of ids to store in the collection.
159  */
160 void
162 {
163  unsigned int i;
164 
165  xmmsv_list_clear (coll->idlist);
166  for (i = 0; ids[i]; i++) {
167  xmmsv_list_append_int (coll->idlist, ids[i]);
168  }
169 }
170 
171 static int
172 _xmmsv_coll_operand_find (xmmsv_list_iter_t *it, xmmsv_coll_t *op)
173 {
174  xmmsv_coll_t *c;
175  xmmsv_t *v;
176 
177  while (xmmsv_list_iter_valid (it)) {
178  xmmsv_list_iter_entry (it, &v);
179  if (xmmsv_get_coll (v, &c)) {
180  if (c == op) {
181  return 1;
182  }
183  }
185  }
186  return 0;
187 }
188 
189 /**
190  * Add the operand to the given collection.
191  * @param coll The collection to add the operand to.
192  * @param op The operand to add.
193  */
194 void
196 {
197  xmmsv_list_iter_t *it;
198  xmmsv_t *v;
199  x_return_if_fail (coll);
200  x_return_if_fail (op);
201 
202  /* we used to check if it already existed here before */
203  if (!xmmsv_get_list_iter (coll->operands, &it))
204  return;
205 
206  if (_xmmsv_coll_operand_find (it, op)) {
207  x_api_warning ("with an operand already in operand list");
209  return;
210  }
211 
213 
214  v = xmmsv_new_coll (op);
215  x_return_if_fail (v);
216  xmmsv_list_append (coll->operands, v);
217  xmmsv_unref (v);
218 }
219 
220 /**
221  * Remove all the occurences of the operand in the given collection.
222  * @param coll The collection to remove the operand from.
223  * @param op The operand to remove.
224  */
225 void
227 {
228  xmmsv_list_iter_t *it;
229 
230  x_return_if_fail (coll);
231  x_return_if_fail (op);
232 
233  if (!xmmsv_get_list_iter (coll->operands, &it))
234  return;
235 
236  if (_xmmsv_coll_operand_find (it, op)) {
238  } else {
239  x_api_warning ("with an operand not in operand list");
240  }
242 }
243 
244 
245 /**
246  * Append a value to the idlist.
247  * @param coll The collection to update.
248  * @param id The id to append to the idlist.
249  * @return TRUE on success, false otherwise.
250  */
251 int
253 {
254  x_return_val_if_fail (coll, 0);
255 
256  return xmmsv_list_append_int (coll->idlist, id);
257 }
258 
259 /**
260  * Insert a value at a given position in the idlist.
261  * @param coll The collection to update.
262  * @param id The id to insert in the idlist.
263  * @param index The position at which to insert the value.
264  * @return TRUE on success, false otherwise.
265  */
266 int
267 xmmsv_coll_idlist_insert (xmmsv_coll_t *coll, int index, int id)
268 {
269  x_return_val_if_fail (coll, 0);
270 
271  return xmmsv_list_insert_int (coll->idlist, index, id);
272 }
273 
274 /**
275  * Move a value of the idlist to a new position.
276  * @param coll The collection to update.
277  * @param index The index of the value to move.
278  * @param newindex The newindex to which to move the value.
279  * @return TRUE on success, false otherwise.
280  */
281 int
282 xmmsv_coll_idlist_move (xmmsv_coll_t *coll, int index, int newindex)
283 {
284  x_return_val_if_fail (coll, 0);
285 
286  return xmmsv_list_move (coll->idlist, index, newindex);
287 }
288 
289 /**
290  * Remove the value at a given index from the idlist.
291  * @param coll The collection to update.
292  * @param index The index at which to remove the value.
293  * @return TRUE on success, false otherwise.
294  */
295 int
297 {
298  x_return_val_if_fail (coll, 0);
299 
300  return xmmsv_list_remove (coll->idlist, index);
301 }
302 
303 /**
304  * Empties the idlist.
305  * @param coll The collection to update.
306  * @return TRUE on success, false otherwise.
307  */
308 int
310 {
311  x_return_val_if_fail (coll, 0);
312 
313  return xmmsv_list_clear (coll->idlist);
314 }
315 
316 /**
317  * Retrieves the value at the given position in the idlist.
318  * @param coll The collection to update.
319  * @param index The position of the value to retrieve.
320  * @param val The pointer at which to store the found value.
321  * @return TRUE on success, false otherwise.
322  */
323 int
324 xmmsv_coll_idlist_get_index (xmmsv_coll_t *coll, int index, int32_t *val)
325 {
326  x_return_val_if_fail (coll, 0);
327 
328  return xmmsv_list_get_int (coll->idlist, index, val);
329 }
330 
331 /**
332  * Sets the value at the given position in the idlist.
333  * @param coll The collection to update.
334  * @param index The position of the value to set.
335  * @param val The new value.
336  * @return TRUE on success, false otherwise.
337  */
338 int
339 xmmsv_coll_idlist_set_index (xmmsv_coll_t *coll, int index, int32_t val)
340 {
341  x_return_val_if_fail (coll, 0);
342 
343  return xmmsv_list_set_int (coll->idlist, index, val);
344 }
345 
346 /**
347  * Get the size of the idlist.
348  * @param coll The collection to update.
349  * @return The size of the idlist.
350  */
351 size_t
353 {
354  x_return_val_if_fail (coll, 0);
355 
356  return xmmsv_list_get_size (coll->idlist);
357 }
358 
359 
360 
361 /**
362  * Return the type of the collection.
363  * @param coll The collection to consider.
364  * @return The #xmmsv_coll_type_t of the collection, or -1 if invalid.
365  */
368 {
369  x_return_val_if_fail (coll, -1);
370 
371  return coll->type;
372 }
373 
374 /**
375  * Return the list of ids stored in the collection.
376  * The list is owned by the collection.
377  * Note that this must not be confused with the content of the
378  * collection, which must be queried using xmmsc_coll_query_ids!
379  *
380  * Also note that this function is deprecated (use xmmsv_coll_idlist_get
381  * instead) and that changes to the returned array will be ignored. The array
382  * is also not updated when the idlist is changed using the supplied functions.
383  * Additionally every call to this function allocates a new array, so calling
384  * it repetitively will be a performance penalty.
385  *
386  * @param coll The collection to consider.
387  * @return The 0-terminated list of ids.
388  */
389 const int32_t*
391 {
392  xmmsv_list_iter_t *it;
393  unsigned int i;
394  int32_t entry;
395 
396  x_return_null_if_fail (coll);
397 
398  /* free and allocate a new legacy list */
399  if (coll->legacy_idlist) {
400  free (coll->legacy_idlist);
401  }
402  coll->legacy_idlist = calloc (xmmsv_coll_idlist_get_size (coll) + 1,
403  sizeof (int32_t));
404 
405  /* copy contents to legacy list */
406  for (xmmsv_get_list_iter (coll->idlist, &it), i = 0;
408  xmmsv_list_iter_next (it), i++) {
409  xmmsv_list_iter_entry_int (it, &entry);
410  coll->legacy_idlist[i] = entry;
411  }
412  coll->legacy_idlist[i] = 0;
413 
414  return coll->legacy_idlist;
415 }
416 
417 /**
418  * Return the list of ids stored in the collection.
419  * This function does not increase the refcount of the list, the reference is
420  * still owned by the collection.
421  *
422  * Note that this must not be confused with the content of the collection,
423  * which must be queried using xmmsc_coll_query_ids!
424  *
425  * @param coll The collection to consider.
426  * @return The 0-terminated list of ids.
427  */
428 xmmsv_t *
430 {
431  x_return_null_if_fail (coll);
432 
433  return coll->idlist;
434 }
435 
436 xmmsv_t *
438 {
439  x_return_val_if_fail (coll, NULL);
440 
441  return coll->operands;
442 }
443 
444 xmmsv_t *
446 {
447  x_return_val_if_fail (coll, NULL);
448 
449  return coll->attributes;
450 }
451 
452 /**
453  * Set an attribute in the given collection.
454  *
455  * @param coll The collection in which to set the attribute.
456  * @param key The name of the attribute to set.
457  * @param value The value of the attribute.
458  */
459 void
460 xmmsv_coll_attribute_set (xmmsv_coll_t *coll, const char *key, const char *value)
461 {
462  xmmsv_t *v;
463 
464  v = xmmsv_new_string (value);
465  x_return_if_fail (v);
466 
467  xmmsv_dict_set (coll->attributes, key, v);
468  xmmsv_unref (v);
469 }
470 
471 /**
472  * Remove an attribute from the given collection.
473  * The return value indicated whether the attribute was found (and
474  * removed)
475  *
476  * @param coll The collection to remove the attribute from.
477  * @param key The name of the attribute to remove.
478  * @return 1 upon success, 0 otherwise
479  */
480 int
482 {
483  return xmmsv_dict_remove (coll->attributes, key);
484 }
485 
486 /**
487  * Retrieve the value of the attribute of the given collection.
488  * The return value is 1 if the attribute was found and 0 otherwise.
489  * The value of the attribute is owned by the collection and must not
490  * be freed by the caller.
491  *
492  * @param coll The collection to retrieve the attribute from.
493  * @param key The name of the attribute.
494  * @param value The value of the attribute if found (owned by the collection).
495  * @return 1 if the attribute was found, 0 otherwise
496  */
497 int
498 xmmsv_coll_attribute_get (xmmsv_coll_t *coll, const char *key, char **value)
499 {
500  if (xmmsv_dict_entry_get_string (coll->attributes, key, value)) {
501  return 1;
502  }
503  *value = NULL;
504  return 0;
505 }
506 
507 
508 
509 struct attr_fe_data {
511  void *userdata;
512 };
513 
514 static void
515 attr_fe_func (const char *key, xmmsv_t *val, void *user_data)
516 {
517  struct attr_fe_data *d = user_data;
518  const char *v;
519  int r;
520 
521  r = xmmsv_get_string (val, &v);
522  x_return_if_fail (r)
523 
524  d->func (key, v, d->userdata);
525 }
526 /**
527  * Iterate over all key/value-pair of the collection attributes.
528  *
529  * Calls specified function for each key/value-pair of the attribute list.
530  *
531  * void function (const char *key, const char *value, void *user_data);
532  *
533  * @param coll the #xmmsv_coll_t.
534  * @param func function that is called for each key/value-pair
535  * @param user_data extra data passed to func
536  */
537 void
540  void *user_data)
541 {
542  struct attr_fe_data d = {func, user_data};
543  xmmsv_dict_foreach (coll->attributes, attr_fe_func, &d);
544 }
545 
546 /**
547  * Return a collection referencing the whole media library,
548  * that is a reference to the "All Media" collection.
549  * The returned structure must be unref'd using #xmmsv_coll_unref
550  * after usage.
551  *
552  * @return a collection referring to the "All Media" collection.
553  */
556 {
558  xmmsv_coll_attribute_set (univ, "reference", "All Media");
559  /* FIXME: namespace? */
560 
561  return univ;
562 }
563 
564 /** @} */
int xmmsv_coll_idlist_insert(xmmsv_coll_t *coll, int index, int id)
Insert a value at a given position in the idlist.
Definition: coll.c:267
#define x_return_val_if_fail(expr, val)
Definition: xmmsc_util.h:13
int xmmsv_list_insert_int(xmmsv_t *v, int pos, int32_t val)
struct xmmsv_list_iter_St xmmsv_list_iter_t
Definition: xmmsv_list.h:69
int xmmsv_dict_set(xmmsv_t *dictv, const char *key, xmmsv_t *val)
Insert an element under the given key in the dict xmmsv_t.
Definition: value.c:1752
void xmmsv_unref(xmmsv_t *val)
Decreases the references for the xmmsv_t When the number of references reaches 0 it will be freed...
Definition: value.c:303
int xmmsv_list_append(xmmsv_t *listv, xmmsv_t *val)
Append an element to the end of the list xmmsv_t.
Definition: value.c:1340
int xmmsv_coll_attribute_get(xmmsv_coll_t *coll, const char *key, char **value)
Retrieve the value of the attribute of the given collection.
Definition: coll.c:498
int xmmsv_list_clear(xmmsv_t *listv)
Empty the list from all its elements.
Definition: value.c:1356
const int32_t * xmmsv_coll_get_idlist(xmmsv_coll_t *coll)
Return the list of ids stored in the collection.
Definition: coll.c:390
int xmmsv_coll_idlist_append(xmmsv_coll_t *coll, int id)
Append a value to the idlist.
Definition: coll.c:252
int xmmsv_list_iter_remove(xmmsv_list_iter_t *it)
Remove the element in the list at the position pointed at by the iterator.
Definition: value.c:1652
struct xmmsv_St xmmsv_t
Definition: xmmsv_general.h:48
void xmmsv_coll_attribute_set(xmmsv_coll_t *coll, const char *key, const char *value)
Set an attribute in the given collection.
Definition: coll.c:460
xmmsv_t * xmmsv_new_string(const char *s)
Allocates a new string xmmsv_t.
Definition: value.c:180
xmmsv_coll_t * xmmsv_coll_ref(xmmsv_coll_t *coll)
Increases the references for the xmmsv_coll_t.
Definition: coll.c:61
int xmmsv_list_get_int(xmmsv_t *v, int pos, int32_t *val)
int xmmsv_coll_attribute_remove(xmmsv_coll_t *coll, const char *key)
Remove an attribute from the given collection.
Definition: coll.c:481
int xmmsv_get_list_iter(const xmmsv_t *val, xmmsv_list_iter_t **it)
Retrieves a list iterator from a list xmmsv_t.
Definition: value.c:926
xmmsv_coll_type_t
xmmsv_t * xmmsv_new_dict(void)
Allocates a new dict xmmsv_t.
Definition: value.c:268
int xmmsv_list_append_int(xmmsv_t *v, int32_t val)
int xmmsv_list_restrict_type(xmmsv_t *listv, xmmsv_type_t type)
Definition: value.c:1413
xmmsv_t * xmmsv_coll_operands_get(xmmsv_coll_t *coll)
Definition: coll.c:437
size_t xmmsv_coll_idlist_get_size(xmmsv_coll_t *coll)
Get the size of the idlist.
Definition: coll.c:352
int xmmsv_dict_foreach(xmmsv_t *dictv, xmmsv_dict_foreach_func func, void *user_data)
Apply a function to each key-element pair in the list.
Definition: value.c:1853
xmmsv_t * xmmsv_coll_idlist_get(xmmsv_coll_t *coll)
Return the list of ids stored in the collection.
Definition: coll.c:429
int xmmsv_coll_idlist_get_index(xmmsv_coll_t *coll, int index, int32_t *val)
Retrieves the value at the given position in the idlist.
Definition: coll.c:324
int xmmsv_list_move(xmmsv_t *listv, int old_pos, int new_pos)
Move the element from position #old to position #new.
Definition: value.c:1323
void xmmsv_list_iter_next(xmmsv_list_iter_t *it)
Advance the iterator to the next element in the list.
Definition: value.c:1553
xmmsv_t * xmmsv_new_list(void)
Allocates a new list xmmsv_t.
Definition: value.c:250
void xmmsv_list_iter_explicit_destroy(xmmsv_list_iter_t *it)
Explicitly free list iterator.
Definition: value.c:1478
struct xmmsv_coll_St xmmsv_coll_t
Definition: xmmsv_coll.h:28
void(* xmmsv_coll_attribute_foreach_func)(const char *key, const char *value, void *udata)
Definition: xmmsv_coll.h:30
int xmmsv_dict_entry_get_string(xmmsv_t *val, const char *key, const char **r)
xmmsv_t * xmmsv_new_coll(xmmsv_coll_t *coll)
Allocates a new collection xmmsv_t.
Definition: value.c:202
xmmsv_coll_t * xmmsv_coll_new(xmmsv_coll_type_t type)
Allocate a new collection of the given type.
Definition: coll.c:78
int xmmsv_list_remove(xmmsv_t *listv, int pos)
Remove the element at the given position from the list xmmsv_t.
Definition: value.c:1300
xmmsv_t * xmmsv_coll_attributes_get(xmmsv_coll_t *coll)
Definition: coll.c:445
void xmmsv_coll_add_operand(xmmsv_coll_t *coll, xmmsv_coll_t *op)
Add the operand to the given collection.
Definition: coll.c:195
int xmmsv_list_get_size(xmmsv_t *listv)
Return the size of the list.
Definition: value.c:1403
void xmmsv_coll_set_idlist(xmmsv_coll_t *coll, int ids[])
Set the list of ids in the given collection.
Definition: coll.c:161
int xmmsv_coll_idlist_remove(xmmsv_coll_t *coll, int index)
Remove the value at a given index from the idlist.
Definition: coll.c:296
#define x_return_null_if_fail(expr)
Definition: xmmsc_util.h:14
void xmmsv_coll_remove_operand(xmmsv_coll_t *coll, xmmsv_coll_t *op)
Remove all the occurences of the operand in the given collection.
Definition: coll.c:226
#define x_new0(type, num)
Definition: xmmsc_util.h:16
#define x_oom()
Definition: xmmsc_util.h:15
int xmmsv_coll_idlist_set_index(xmmsv_coll_t *coll, int index, int32_t val)
Sets the value at the given position in the idlist.
Definition: coll.c:339
void xmmsv_coll_attribute_foreach(xmmsv_coll_t *coll, xmmsv_coll_attribute_foreach_func func, void *user_data)
Iterate over all key/value-pair of the collection attributes.
Definition: coll.c:538
#define x_return_if_fail(expr)
Definition: xmmsc_util.h:12
int xmmsv_list_iter_valid(xmmsv_list_iter_t *it)
Check whether the iterator is valid and points to a valid element.
Definition: value.c:1512
int xmmsv_get_string(const xmmsv_t *val, const char **r)
Retrieves a string from the value.
Definition: value.c:863
int xmmsv_list_iter_entry(xmmsv_list_iter_t *it, xmmsv_t **val)
Get the element currently pointed at by the iterator.
Definition: value.c:1495
int xmmsv_list_set_int(xmmsv_t *v, int pos, int32_t val)
int xmmsv_coll_idlist_move(xmmsv_coll_t *coll, int index, int newindex)
Move a value of the idlist to a new position.
Definition: coll.c:282
int xmmsv_list_iter_entry_int(xmmsv_list_iter_t *it, int32_t *val)
int xmmsv_coll_idlist_clear(xmmsv_coll_t *coll)
Empties the idlist.
Definition: coll.c:309
int xmmsv_dict_remove(xmmsv_t *dictv, const char *key)
Remove the element corresponding to a given key in the dict xmmsv_t (if it exists).
Definition: value.c:1803
xmmsv_coll_type_t xmmsv_coll_get_type(xmmsv_coll_t *coll)
Return the type of the collection.
Definition: coll.c:367
int xmmsv_get_coll(const xmmsv_t *val, xmmsv_coll_t **coll)
Retrieves a collection from the value.
Definition: value.c:883
xmmsv_coll_t * xmmsv_coll_universe()
Return a collection referencing the whole media library, that is a reference to the "All Media" colle...
Definition: coll.c:555
void xmmsv_coll_unref(xmmsv_coll_t *coll)
Decreases the references for the xmmsv_coll_t When the number of references reaches 0 it will be free...
Definition: coll.c:140