XMMS2
coll.c
Go to the documentation of this file.
1 /* XMMS2 - X Music Multiplexer System
2  * Copyright (C) 2003-2009 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 
38  /* List of ids, 0-terminated. */
39  uint32_t *idlist;
40  size_t idlist_size;
41  size_t idlist_allocated;
42 
43 };
44 
45 
46 static void xmmsv_coll_free (xmmsv_coll_t *coll);
47 
48 static int xmmsv_coll_idlist_resize (xmmsv_coll_t *coll, size_t newsize);
49 
50 
51 /**
52  * @defgroup CollectionStructure CollectionStructure
53  * @ingroup Collections
54  * @brief The API to be used to work with collection structures.
55  *
56  * @{
57  */
58 
59 /**
60  * Increases the references for the #xmmsv_coll_t
61  *
62  * @param coll the collection to reference.
63  * @return coll
64  */
67 {
68  x_return_val_if_fail (coll, NULL);
69 
70  coll->ref++;
71 
72  return coll;
73 }
74 
75 /**
76  * Allocate a new collection of the given type.
77  * The pointer will have to be deallocated using #xmmsv_coll_unref.
78  *
79  * @param type the #xmmsv_coll_type_t specifying the type of collection to create.
80  * @return a pointer to the newly created collection, or NULL if the type is invalid.
81  */
84 {
85  xmmsv_coll_t *coll;
86 
88 
89  coll = x_new0 (xmmsv_coll_t, 1);
90  if (!coll) {
91  x_oom ();
92  return NULL;
93  }
94 
95  if (!(coll->idlist = x_new0 (uint32_t, 1))) {
96  x_oom ();
97  free (coll);
98  return NULL;
99  }
100  coll->idlist_size = 1;
101  coll->idlist_allocated = 1;
102 
103  coll->ref = 0;
104  coll->type = type;
105 
106  coll->operands = xmmsv_new_list ();
107  xmmsv_list_restrict_type (coll->operands, XMMSV_TYPE_COLL);
108 
109  coll->attributes = xmmsv_new_dict ();
110 
111  /* user must give this back */
112  xmmsv_coll_ref (coll);
113 
114  return coll;
115 }
116 
117 /**
118  * Free the memory owned by the collection.
119  * You probably want to use #xmmsv_coll_unref instead, which handles
120  * reference counting.
121  *
122  * @param coll the collection to free.
123  */
124 static void
125 xmmsv_coll_free (xmmsv_coll_t *coll)
126 {
127  x_return_if_fail (coll);
128 
129  /* Unref all the operands and attributes */
130  xmmsv_unref (coll->operands);
131 
132  xmmsv_unref (coll->attributes);
133 
134  free (coll->idlist);
135 
136  free (coll);
137 }
138 
139 /**
140  * Decreases the references for the #xmmsv_coll_t
141  * When the number of references reaches 0 it will
142  * be freed and all its operands unreferenced as well.
143  *
144  * @param coll the collection to unref.
145  */
146 void
148 {
149  x_return_if_fail (coll);
150  x_api_error_if (coll->ref < 1, "with a freed collection",);
151 
152  coll->ref--;
153  if (coll->ref == 0) {
154  xmmsv_coll_free (coll);
155  }
156 }
157 
158 
159 /**
160  * Set the list of ids in the given collection.
161  * The list must be 0-terminated.
162  * Note that the idlist is only relevant for idlist collections.
163  *
164  * @param coll the collection to modify.
165  * @param ids the 0-terminated list of ids to store in the collection.
166  */
167 void
168 xmmsv_coll_set_idlist (xmmsv_coll_t *coll, unsigned int ids[])
169 {
170  unsigned int i;
171  unsigned int size = 0;
172 
173  x_return_if_fail (coll);
174 
175  while (ids[size] != 0) {
176  ++size;
177  }
178  ++size;
179 
180  free (coll->idlist);
181  if (!(coll->idlist = x_new0 (uint32_t, size))) {
182  x_oom ();
183  return;
184  }
185 
186  for (i = 0; i < size; ++i) {
187  coll->idlist[i] = ids[i];
188  }
189 
190  coll->idlist_size = size;
191  coll->idlist_allocated = size;
192 }
193 
194 static int
195 _xmmsv_coll_operand_find (xmmsv_list_iter_t *it, xmmsv_coll_t *op)
196 {
197  xmmsv_coll_t *c;
198  xmmsv_t *v;
199 
200  while (xmmsv_list_iter_valid (it)) {
201  xmmsv_list_iter_entry (it, &v);
202  if (xmmsv_get_coll (v, &c)) {
203  if (c == op) {
204  return 1;
205  }
206  }
208  }
209  return 0;
210 }
211 
212 /**
213  * Add the operand to the given collection.
214  * @param coll The collection to add the operand to.
215  * @param op The operand to add.
216  */
217 void
219 {
220  xmmsv_list_iter_t *it;
221  xmmsv_t *v;
222  x_return_if_fail (coll);
223  x_return_if_fail (op);
224 
225  /* we used to check if it already existed here before */
226  if (!xmmsv_get_list_iter (coll->operands, &it))
227  return;
228 
229  if (_xmmsv_coll_operand_find (it, op)) {
230  x_api_warning ("with an operand already in operand list");
232  return;
233  }
234 
236 
237  v = xmmsv_new_coll (op);
238  x_return_if_fail (v);
239  xmmsv_list_append (coll->operands, v);
240  xmmsv_unref (v);
241 }
242 
243 /**
244  * Remove all the occurences of the operand in the given collection.
245  * @param coll The collection to remove the operand from.
246  * @param op The operand to remove.
247  */
248 void
250 {
251  xmmsv_list_iter_t *it;
252 
253  x_return_if_fail (coll);
254  x_return_if_fail (op);
255 
256  if (!xmmsv_get_list_iter (coll->operands, &it))
257  return;
258 
259  if (_xmmsv_coll_operand_find (it, op)) {
261  } else {
262  x_api_warning ("with an operand not in operand list");
263  }
265 }
266 
267 
268 /**
269  * Append a value to the idlist.
270  * @param coll The collection to update.
271  * @param id The id to append to the idlist.
272  * @return TRUE on success, false otherwise.
273  */
274 int
275 xmmsv_coll_idlist_append (xmmsv_coll_t *coll, unsigned int id)
276 {
277  x_return_val_if_fail (coll, 0);
278 
279  return xmmsv_coll_idlist_insert (coll, coll->idlist_size - 1, id);
280 }
281 
282 /**
283  * Insert a value at a given position in the idlist.
284  * @param coll The collection to update.
285  * @param id The id to insert in the idlist.
286  * @param index The position at which to insert the value.
287  * @return TRUE on success, false otherwise.
288  */
289 int
290 xmmsv_coll_idlist_insert (xmmsv_coll_t *coll, unsigned int index, unsigned int id)
291 {
292  int i;
293  x_return_val_if_fail (coll, 0);
294 
295  if (index >= coll->idlist_size) {
296  return 0;
297  }
298 
299  /* We need more memory, reallocate */
300  if (coll->idlist_size == coll->idlist_allocated) {
301  int success;
302  size_t double_size = coll->idlist_allocated * 2;
303  success = xmmsv_coll_idlist_resize (coll, double_size);
304  x_return_val_if_fail (success, 0);
305  }
306 
307  for (i = coll->idlist_size; i > index; i--) {
308  coll->idlist[i] = coll->idlist[i - 1];
309  }
310 
311  coll->idlist[index] = id;
312  coll->idlist_size++;
313 
314  return 1;
315 }
316 
317 /**
318  * Move a value of the idlist to a new position.
319  * @param coll The collection to update.
320  * @param index The index of the value to move.
321  * @param newindex The newindex to which to move the value.
322  * @return TRUE on success, false otherwise.
323  */
324 int
325 xmmsv_coll_idlist_move (xmmsv_coll_t *coll, unsigned int index, unsigned int newindex)
326 {
327  int i;
328  uint32_t tmp;
329 
330  x_return_val_if_fail (coll, 0);
331 
332  if ((index >= coll->idlist_size - 1) || (newindex >= coll->idlist_size - 1)) {
333  return 0;
334  }
335 
336  tmp = coll->idlist[index];
337  if (index < newindex) {
338  for (i = index; i < newindex; i++) {
339  coll->idlist[i] = coll->idlist[i + 1];
340  }
341  }
342  else if (index > newindex) {
343  for (i = index; i > newindex; i--) {
344  coll->idlist[i] = coll->idlist[i - 1];
345  }
346  }
347  coll->idlist[newindex] = tmp;
348 
349  return 1;
350 }
351 
352 /**
353  * Remove the value at a given index from the idlist.
354  * @param coll The collection to update.
355  * @param index The index at which to remove the value.
356  * @return TRUE on success, false otherwise.
357  */
358 int
359 xmmsv_coll_idlist_remove (xmmsv_coll_t *coll, unsigned int index)
360 {
361  int i;
362  size_t half_size;
363 
364  x_return_val_if_fail (coll, 0);
365 
366  if (index >= coll->idlist_size - 1) {
367  return 0;
368  }
369 
370  coll->idlist_size--;
371  for (i = index; i < coll->idlist_size; i++) {
372  coll->idlist[i] = coll->idlist[i + 1];
373  }
374 
375  /* Reduce memory usage by two if possible */
376  half_size = coll->idlist_allocated / 2;
377  if (coll->idlist_size <= half_size) {
378  xmmsv_coll_idlist_resize (coll, half_size);
379  }
380 
381  return 1;
382 }
383 
384 /**
385  * Empties the idlist.
386  * @param coll The collection to update.
387  * @return TRUE on success, false otherwise.
388  */
389 int
391 {
392  unsigned int empty[] = { 0 };
393 
394  x_return_val_if_fail (coll, 0);
395 
396  xmmsv_coll_set_idlist (coll, empty);
397 
398  return 1;
399 }
400 
401 /**
402  * Retrieves the value at the given position in the idlist.
403  * @param coll The collection to update.
404  * @param index The position of the value to retrieve.
405  * @param val The pointer at which to store the found value.
406  * @return TRUE on success, false otherwise.
407  */
408 int
409 xmmsv_coll_idlist_get_index (xmmsv_coll_t *coll, unsigned int index, uint32_t *val)
410 {
411  x_return_val_if_fail (coll, 0);
412 
413  if (index >= (coll->idlist_size - 1)) {
414  return 0;
415  }
416 
417  *val = coll->idlist[index];
418 
419  return 1;
420 }
421 
422 /**
423  * Sets the value at the given position in the idlist.
424  * @param coll The collection to update.
425  * @param index The position of the value to set.
426  * @param val The new value.
427  * @return TRUE on success, false otherwise.
428  */
429 int
430 xmmsv_coll_idlist_set_index (xmmsv_coll_t *coll, unsigned int index, uint32_t val)
431 {
432  x_return_val_if_fail (coll, 0);
433 
434  if (index >= (coll->idlist_size - 1)) {
435  return 0;
436  }
437 
438  coll->idlist[index] = val;
439 
440  return 1;
441 }
442 
443 /**
444  * Get the size of the idlist.
445  * @param coll The collection to update.
446  * @return The size of the idlist.
447  */
448 size_t
450 {
451  x_return_val_if_fail (coll, 0);
452 
453  return coll->idlist_size - 1;
454 }
455 
456 
457 
458 /**
459  * Return the type of the collection.
460  * @param coll The collection to consider.
461  * @return The #xmmsv_coll_type_t of the collection, or -1 if invalid.
462  */
465 {
466  x_return_val_if_fail (coll, -1);
467 
468  return coll->type;
469 }
470 
471 /**
472  * Return the list of ids stored in the collection.
473  * The list is owned by the collection.
474  * Note that this must not be confused with the content of the
475  * collection, which must be queried using xmmsc_coll_query_ids!
476  *
477  * @param coll The collection to consider.
478  * @return The 0-terminated list of ids.
479  */
480 uint32_t*
482 {
483  x_return_null_if_fail (coll);
484 
485  return coll->idlist;
486 }
487 
488 xmmsv_t *
490 {
491  x_return_val_if_fail (coll, NULL);
492 
493  return coll->operands;
494 }
495 
496 xmmsv_t *
498 {
499  x_return_val_if_fail (coll, NULL);
500 
501  return coll->attributes;
502 }
503 
504 /**
505  * Set an attribute in the given collection.
506  *
507  * @param coll The collection in which to set the attribute.
508  * @param key The name of the attribute to set.
509  * @param value The value of the attribute.
510  */
511 void
512 xmmsv_coll_attribute_set (xmmsv_coll_t *coll, const char *key, const char *value)
513 {
514  xmmsv_t *v;
515 
516  v = xmmsv_new_string (value);
517  x_return_if_fail (v);
518 
519  xmmsv_dict_set (coll->attributes, key, v);
520  xmmsv_unref (v);
521 }
522 
523 /**
524  * Remove an attribute from the given collection.
525  * The return value indicated whether the attribute was found (and
526  * removed)
527  *
528  * @param coll The collection to remove the attribute from.
529  * @param key The name of the attribute to remove.
530  * @return 1 upon success, 0 otherwise
531  */
532 int
534 {
535  return xmmsv_dict_remove (coll->attributes, key);
536 }
537 
538 /**
539  * Retrieve the value of the attribute of the given collection.
540  * The return value is 1 if the attribute was found and 0 otherwise.
541  * The value of the attribute is owned by the collection and must not
542  * be freed by the caller.
543  *
544  * @param coll The collection to retrieve the attribute from.
545  * @param key The name of the attribute.
546  * @param value The value of the attribute if found (owned by the collection).
547  * @return 1 if the attribute was found, 0 otherwise
548  */
549 int
550 xmmsv_coll_attribute_get (xmmsv_coll_t *coll, const char *key, char **value)
551 {
552  if (xmmsv_dict_entry_get_string (coll->attributes, key, value)) {
553  return 1;
554  }
555  *value = NULL;
556  return 0;
557 }
558 
559 
560 
561 struct attr_fe_data {
563  void *userdata;
564 };
565 
566 static void
567 attr_fe_func (const char *key, xmmsv_t *val, void *user_data)
568 {
569  struct attr_fe_data *d = user_data;
570  const char *v;
571  int r;
572 
573  r = xmmsv_get_string (val, &v);
574  x_return_if_fail (r)
575 
576  d->func (key, v, d->userdata);
577 }
578 /**
579  * Iterate over all key/value-pair of the collection attributes.
580  *
581  * Calls specified function for each key/value-pair of the attribute list.
582  *
583  * void function (const char *key, const char *value, void *user_data);
584  *
585  * @param coll the #xmmsv_coll_t.
586  * @param func function that is called for each key/value-pair
587  * @param user_data extra data passed to func
588  */
589 void
592  void *user_data)
593 {
594  struct attr_fe_data d = {func, user_data};
595  xmmsv_dict_foreach (coll->attributes, attr_fe_func, &d);
596 }
597 
598 /**
599  * Return a collection referencing the whole media library,
600  * that is a reference to the "All Media" collection.
601  * The returned structure must be unref'd using #xmmsv_coll_unref
602  * after usage.
603  *
604  * @return a collection referring to the "All Media" collection.
605  */
608 {
610  xmmsv_coll_attribute_set (univ, "reference", "All Media");
611  /* FIXME: namespace? */
612 
613  return univ;
614 }
615 
616 /** @} */
617 
618 
619 
620 /** @internal */
621 
622 
623 static int
624 xmmsv_coll_idlist_resize (xmmsv_coll_t *coll, size_t newsize)
625 {
626  uint32_t *newmem;
627 
628  newmem = realloc (coll->idlist, newsize * sizeof (uint32_t));
629 
630  if (newmem == NULL) {
631  x_oom ();
632  return 0;
633  }
634 
635  coll->idlist = newmem;
636  coll->idlist_allocated = newsize;
637 
638  return 1;
639 }
struct xmmsv_St xmmsv_t
Definition: xmmsv.h:51
xmmsv_t * xmmsv_new_dict(void)
Allocates a new dict xmmsv_t.
Definition: value.c:266
int xmmsv_coll_idlist_append(xmmsv_coll_t *coll, unsigned int id)
Append a value to the idlist.
Definition: coll.c:275
#define x_return_val_if_fail(expr, val)
Definition: xmmsc_util.h:12
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:301
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:1744
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:550
int xmmsv_dict_entry_get_string(xmmsv_t *val, const char *key, const char **r)
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:918
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:1795
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:1487
void(* xmmsv_coll_attribute_foreach_func)(const char *key, const char *value, void *udata)
Definition: xmmsv_coll.h:30
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:512
xmmsv_t * xmmsv_new_string(const char *s)
Allocates a new string xmmsv_t.
Definition: value.c:178
xmmsv_coll_t * xmmsv_coll_ref(xmmsv_coll_t *coll)
Increases the references for the xmmsv_coll_t.
Definition: coll.c:66
int xmmsv_coll_attribute_remove(xmmsv_coll_t *coll, const char *key)
Remove an attribute from the given collection.
Definition: coll.c:533
int xmmsv_list_append(xmmsv_t *listv, xmmsv_t *val)
Append an element to the end of the list xmmsv_t.
Definition: value.c:1332
int xmmsv_coll_idlist_set_index(xmmsv_coll_t *coll, unsigned int index, uint32_t val)
Sets the value at the given position in the idlist.
Definition: coll.c:430
xmmsv_coll_type_t
struct xmmsv_St * xmmsv_coll_operands_get(xmmsv_coll_t *coll)
Definition: coll.c:489
size_t xmmsv_coll_idlist_get_size(xmmsv_coll_t *coll)
Get the size of the idlist.
Definition: coll.c:449
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:1845
void xmmsv_list_iter_explicit_destroy(xmmsv_list_iter_t *it)
Explicitly free list iterator.
Definition: value.c:1470
int xmmsv_get_coll(const xmmsv_t *val, xmmsv_coll_t **coll)
Retrieves a collection from the value.
Definition: value.c:875
xmmsv_t * xmmsv_new_coll(xmmsv_coll_t *coll)
Allocates a new collection xmmsv_t.
Definition: value.c:200
struct xmmsv_coll_St xmmsv_coll_t
Definition: xmmsv_coll.h:28
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:1644
void xmmsv_list_iter_next(xmmsv_list_iter_t *it)
Advance the iterator to the next element in the list.
Definition: value.c:1545
xmmsv_coll_t * xmmsv_coll_new(xmmsv_coll_type_t type)
Allocate a new collection of the given type.
Definition: coll.c:83
int xmmsv_coll_idlist_get_index(xmmsv_coll_t *coll, unsigned int index, uint32_t *val)
Retrieves the value at the given position in the idlist.
Definition: coll.c:409
struct xmmsv_St * xmmsv_coll_attributes_get(xmmsv_coll_t *coll)
Definition: coll.c:497
void xmmsv_coll_add_operand(xmmsv_coll_t *coll, xmmsv_coll_t *op)
Add the operand to the given collection.
Definition: coll.c:218
#define x_return_null_if_fail(expr)
Definition: xmmsc_util.h:13
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:249
void xmmsv_coll_set_idlist(xmmsv_coll_t *coll, unsigned int ids[])
Set the list of ids in the given collection.
Definition: coll.c:168
#define x_new0(type, num)
Definition: xmmsc_util.h:15
#define x_oom()
Definition: xmmsc_util.h:14
void xmmsv_coll_attribute_foreach(xmmsv_coll_t *coll, xmmsv_coll_attribute_foreach_func func, void *user_data) XMMS_DEPRECATED
Iterate over all key/value-pair of the collection attributes.
Definition: coll.c:590
xmmsv_t * xmmsv_new_list(void)
Allocates a new list xmmsv_t.
Definition: value.c:248
int xmmsv_coll_idlist_insert(xmmsv_coll_t *coll, unsigned int index, unsigned int id)
Insert a value at a given position in the idlist.
Definition: coll.c:290
#define x_return_if_fail(expr)
Definition: xmmsc_util.h:11
int xmmsv_get_string(const xmmsv_t *val, const char **r)
Retrieves a string from the value.
Definition: value.c:855
int xmmsv_list_restrict_type(xmmsv_t *listv, xmmsv_type_t type)
Definition: value.c:1405
int xmmsv_coll_idlist_clear(xmmsv_coll_t *coll)
Empties the idlist.
Definition: coll.c:390
uint32_t * xmmsv_coll_get_idlist(xmmsv_coll_t *coll)
Return the list of ids stored in the collection.
Definition: coll.c:481
xmmsv_coll_type_t xmmsv_coll_get_type(xmmsv_coll_t *coll)
Return the type of the collection.
Definition: coll.c:464
int xmmsv_coll_idlist_move(xmmsv_coll_t *coll, unsigned int index, unsigned int newindex)
Move a value of the idlist to a new position.
Definition: coll.c:325
struct xmmsv_list_iter_St xmmsv_list_iter_t
Definition: xmmsv.h:53
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:1504
xmmsv_coll_t * xmmsv_coll_universe(void)
Return a collection referencing the whole media library, that is a reference to the &quot;All Media&quot; colle...
Definition: coll.c:607
int xmmsv_coll_idlist_remove(xmmsv_coll_t *coll, unsigned int index)
Remove the value at a given index from the idlist.
Definition: coll.c:359
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:147