00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <stdio.h>
00018 #include <stdlib.h>
00019 #include <string.h>
00020 #include <ctype.h>
00021
00022 #include "xmmsclient/xmmsclient.h"
00023 #include "xmmsc/xmmsc_idnumbers.h"
00024 #include "xmmspriv/xmms_list.h"
00025
00026
00027 struct xmmsc_coll_St {
00028
00029
00030 int ref;
00031
00032 xmmsc_coll_type_t type;
00033
00034 x_list_t *operands;
00035 x_list_t *curr_op;
00036
00037
00038 x_list_t *curr_stack;
00039
00040
00041 x_list_t *attributes;
00042 x_list_t *curr_att;
00043
00044
00045 uint32_t *idlist;
00046 size_t idlist_size;
00047 size_t idlist_allocated;
00048
00049 };
00050
00051
00052 static void xmmsc_coll_free (xmmsc_coll_t *coll);
00053 static int free_udata (void *ptr, void *userdata);
00054
00055 static int xmmsc_coll_unref_udata (void *coll, void *userdata);
00056 static int xmmsc_coll_idlist_resize (xmmsc_coll_t *coll, size_t newsize);
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 xmmsc_coll_t *
00074 xmmsc_coll_ref (xmmsc_coll_t *coll)
00075 {
00076 x_return_val_if_fail (coll, NULL);
00077
00078 coll->ref++;
00079
00080 return coll;
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090 xmmsc_coll_t*
00091 xmmsc_coll_new (xmmsc_coll_type_t type)
00092 {
00093 xmmsc_coll_t *coll;
00094
00095 if (!(coll = x_new0 (xmmsc_coll_t, 1))) {
00096 x_oom ();
00097 return NULL;
00098 }
00099
00100 if (!(coll->idlist = x_new0 (uint32_t, 1))) {
00101 x_oom ();
00102 return NULL;
00103 }
00104 coll->idlist_size = 1;
00105 coll->idlist_allocated = 1;
00106
00107 coll->ref = 0;
00108 coll->type = type;
00109
00110 coll->operands = NULL;
00111 coll->attributes = NULL;
00112
00113 coll->curr_op = coll->operands;
00114 coll->curr_stack = NULL;
00115
00116
00117 xmmsc_coll_ref (coll);
00118
00119 return coll;
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129 static void
00130 xmmsc_coll_free (xmmsc_coll_t *coll)
00131 {
00132 x_return_if_fail (coll);
00133
00134
00135 x_list_foreach (coll->operands, xmmsc_coll_unref_udata, NULL);
00136 x_list_foreach (coll->attributes, free_udata, NULL);
00137
00138 x_list_free (coll->operands);
00139 x_list_free (coll->attributes);
00140 x_list_free (coll->curr_stack);
00141
00142 free (coll->idlist);
00143
00144 free (coll);
00145 }
00146
00147
00148
00149
00150
00151
00152
00153
00154 void
00155 xmmsc_coll_unref (xmmsc_coll_t *coll)
00156 {
00157 x_return_if_fail (coll);
00158 x_api_error_if (coll->ref < 1, "with a freed collection",);
00159
00160 coll->ref--;
00161 if (coll->ref == 0) {
00162 xmmsc_coll_free (coll);
00163 }
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 void
00176 xmmsc_coll_set_idlist (xmmsc_coll_t *coll, unsigned int ids[])
00177 {
00178 unsigned int i;
00179 unsigned int size = 0;
00180
00181 x_return_if_fail (coll);
00182
00183 while (ids[size] != 0) {
00184 ++size;
00185 }
00186 ++size;
00187
00188 free (coll->idlist);
00189 if (!(coll->idlist = x_new0 (uint32_t, size))) {
00190 x_oom ();
00191 return;
00192 }
00193
00194 for (i = 0; i < size; ++i) {
00195 coll->idlist[i] = ids[i];
00196 }
00197
00198 coll->idlist_size = size;
00199 coll->idlist_allocated = size;
00200 }
00201
00202
00203
00204
00205
00206
00207
00208 void
00209 xmmsc_coll_add_operand (xmmsc_coll_t *coll, xmmsc_coll_t *op)
00210 {
00211 x_return_if_fail (coll);
00212 x_return_if_fail (op);
00213
00214
00215 if (x_list_index (coll->operands, op) != -1) {
00216 return;
00217 }
00218
00219 xmmsc_coll_ref (op);
00220
00221 coll->operands = x_list_append (coll->operands, op);
00222 }
00223
00224
00225
00226
00227
00228
00229 void
00230 xmmsc_coll_remove_operand (xmmsc_coll_t *coll, xmmsc_coll_t *op)
00231 {
00232 x_list_t *entry;
00233
00234 x_return_if_fail (coll);
00235 x_return_if_fail (op);
00236
00237
00238 entry = x_list_find (coll->operands, op);
00239 if (entry == NULL) {
00240 return;
00241 }
00242
00243 coll->operands = x_list_delete_link (coll->operands, entry);
00244
00245 xmmsc_coll_unref (op);
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255 int
00256 xmmsc_coll_idlist_append (xmmsc_coll_t *coll, unsigned int id)
00257 {
00258 x_return_val_if_fail (coll, 0);
00259
00260 return xmmsc_coll_idlist_insert (coll, coll->idlist_size - 1, id);
00261 }
00262
00263
00264
00265
00266
00267
00268
00269
00270 int
00271 xmmsc_coll_idlist_insert (xmmsc_coll_t *coll, unsigned int index, unsigned int id)
00272 {
00273 int i;
00274 x_return_val_if_fail (coll, 0);
00275
00276 if (index >= coll->idlist_size) {
00277 return 0;
00278 }
00279
00280
00281 if (coll->idlist_size == coll->idlist_allocated) {
00282 int success;
00283 size_t double_size = coll->idlist_allocated * 2;
00284 success = xmmsc_coll_idlist_resize (coll, double_size);
00285 x_return_val_if_fail (success, 0);
00286 }
00287
00288 for (i = coll->idlist_size; i > index; i--) {
00289 coll->idlist[i] = coll->idlist[i - 1];
00290 }
00291
00292 coll->idlist[index] = id;
00293 coll->idlist_size++;
00294
00295 return 1;
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305 int
00306 xmmsc_coll_idlist_move (xmmsc_coll_t *coll, unsigned int index, unsigned int newindex)
00307 {
00308 int i;
00309 uint32_t tmp;
00310
00311 x_return_val_if_fail (coll, 0);
00312
00313 if ((index >= coll->idlist_size - 1) || (newindex >= coll->idlist_size - 1)) {
00314 return 0;
00315 }
00316
00317 tmp = coll->idlist[index];
00318 if (index < newindex) {
00319 for (i = index; i < newindex; i++) {
00320 coll->idlist[i] = coll->idlist[i + 1];
00321 }
00322 }
00323 else if (index > newindex) {
00324 for (i = index; i > newindex; i--) {
00325 coll->idlist[i] = coll->idlist[i - 1];
00326 }
00327 }
00328 coll->idlist[newindex] = tmp;
00329
00330 return 1;
00331 }
00332
00333
00334
00335
00336
00337
00338
00339 int
00340 xmmsc_coll_idlist_remove (xmmsc_coll_t *coll, unsigned int index)
00341 {
00342 int i;
00343 size_t half_size;
00344
00345 x_return_val_if_fail (coll, 0);
00346
00347 if (index >= coll->idlist_size - 1) {
00348 return 0;
00349 }
00350
00351 coll->idlist_size--;
00352 for (i = index; i < coll->idlist_size; i++) {
00353 coll->idlist[i] = coll->idlist[i + 1];
00354 }
00355
00356
00357 half_size = coll->idlist_allocated / 2;
00358 if (coll->idlist_size <= half_size) {
00359 xmmsc_coll_idlist_resize (coll, half_size);
00360 }
00361
00362 return 1;
00363 }
00364
00365
00366
00367
00368
00369
00370 int
00371 xmmsc_coll_idlist_clear (xmmsc_coll_t *coll)
00372 {
00373 unsigned int empty[] = { 0 };
00374
00375 x_return_val_if_fail (coll, 0);
00376
00377 xmmsc_coll_set_idlist (coll, empty);
00378
00379 return 1;
00380 }
00381
00382
00383
00384
00385
00386
00387
00388
00389 int
00390 xmmsc_coll_idlist_get_index (xmmsc_coll_t *coll, unsigned int index, uint32_t *val)
00391 {
00392 x_return_val_if_fail (coll, 0);
00393
00394 if (index >= (coll->idlist_size - 1)) {
00395 return 0;
00396 }
00397
00398 *val = coll->idlist[index];
00399
00400 return 1;
00401 }
00402
00403
00404
00405
00406
00407
00408
00409
00410 int
00411 xmmsc_coll_idlist_set_index (xmmsc_coll_t *coll, unsigned int index, uint32_t val)
00412 {
00413 x_return_val_if_fail (coll, 0);
00414
00415 if (index >= (coll->idlist_size - 1)) {
00416 return 0;
00417 }
00418
00419 coll->idlist[index] = val;
00420
00421 return 1;
00422 }
00423
00424
00425
00426
00427
00428
00429 size_t
00430 xmmsc_coll_idlist_get_size (xmmsc_coll_t *coll)
00431 {
00432 x_return_val_if_fail (coll, 0);
00433
00434 return coll->idlist_size - 1;
00435 }
00436
00437
00438
00439
00440
00441
00442
00443
00444 xmmsc_coll_type_t
00445 xmmsc_coll_get_type (xmmsc_coll_t *coll)
00446 {
00447 x_return_val_if_fail (coll, -1);
00448
00449 return coll->type;
00450 }
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461 uint32_t*
00462 xmmsc_coll_get_idlist (xmmsc_coll_t *coll)
00463 {
00464 x_return_null_if_fail (coll);
00465
00466 return coll->idlist;
00467 }
00468
00469
00470
00471
00472
00473
00474
00475
00476 int
00477 xmmsc_coll_operand_list_first (xmmsc_coll_t *coll)
00478 {
00479 x_return_val_if_fail (coll, 0);
00480
00481 coll->curr_op = coll->operands;
00482
00483 return 1;
00484 }
00485
00486
00487
00488
00489
00490
00491
00492 int
00493 xmmsc_coll_operand_list_valid (xmmsc_coll_t *coll)
00494 {
00495 x_return_val_if_fail (coll, 0);
00496
00497 return (coll->curr_op != NULL);
00498 }
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510 int
00511 xmmsc_coll_operand_list_entry (xmmsc_coll_t *coll, xmmsc_coll_t **operand)
00512 {
00513 x_return_val_if_fail (coll, 0);
00514 if (coll->curr_op == NULL) {
00515 return 0;
00516 }
00517
00518 *operand = (xmmsc_coll_t *)coll->curr_op->data;
00519
00520 return 1;
00521 }
00522
00523
00524
00525
00526
00527
00528
00529 int
00530 xmmsc_coll_operand_list_next (xmmsc_coll_t *coll)
00531 {
00532 x_return_val_if_fail (coll, 0);
00533 if (coll->curr_op == NULL) {
00534 return 0;
00535 }
00536
00537 coll->curr_op = coll->curr_op->next;
00538
00539 return 1;
00540 }
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554 int
00555 xmmsc_coll_operand_list_save (xmmsc_coll_t *coll)
00556 {
00557 x_return_val_if_fail (coll, 0);
00558
00559 coll->curr_stack = x_list_prepend (coll->curr_stack, coll->curr_op);
00560
00561 return 1;
00562 }
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575 int
00576 xmmsc_coll_operand_list_restore (xmmsc_coll_t *coll)
00577 {
00578 x_return_val_if_fail (coll, 0);
00579 x_return_val_if_fail (coll->curr_stack, 0);
00580
00581
00582 coll->curr_op = x_list_nth_data (coll->curr_stack, 0);
00583 coll->curr_stack = x_list_delete_link (coll->curr_stack, coll->curr_stack);
00584
00585 return 1;
00586 }
00587
00588
00589
00590
00591
00592
00593
00594 void
00595 xmmsc_coll_operand_list_clear (xmmsc_coll_t *coll)
00596 {
00597 xmmsc_coll_t *op;
00598
00599 x_return_if_fail (coll);
00600
00601
00602 while (coll->operands != NULL) {
00603 op = (xmmsc_coll_t *) coll->operands->data;
00604 coll->operands = x_list_delete_link (coll->operands, coll->operands);
00605 xmmsc_coll_unref (op);
00606 }
00607
00608 coll->curr_op = NULL;
00609 coll->curr_stack = NULL;
00610 }
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 void
00621 xmmsc_coll_attribute_set (xmmsc_coll_t *coll, const char *key, const char *value)
00622 {
00623 x_list_t *n;
00624 for (n = coll->attributes; n; n = x_list_next (n)) {
00625 const char *k = n->data;
00626 if (strcasecmp (k, key) == 0 && n->next) {
00627
00628 free (n->next->data);
00629 n->next->data = strdup (value);
00630 return;
00631 } else {
00632
00633 n = x_list_next (n);
00634 }
00635 }
00636
00637
00638 coll->attributes = x_list_append (coll->attributes, strdup (key));
00639 coll->attributes = x_list_append (coll->attributes, strdup (value));
00640
00641 return;
00642 }
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653 int
00654 xmmsc_coll_attribute_remove (xmmsc_coll_t *coll, const char *key)
00655 {
00656 x_list_t *n;
00657 for (n = coll->attributes; n; n = x_list_next (n)) {
00658 char *k = n->data;
00659 if (strcasecmp (k, key) == 0 && n->next) {
00660 char *v = n->next->data;
00661
00662 coll->attributes = x_list_delete_link (coll->attributes, n->next);
00663 coll->attributes = x_list_delete_link (coll->attributes, n);
00664 free (k);
00665 free (v);
00666 return 1;
00667 } else {
00668
00669 n = x_list_next (n);
00670 }
00671 }
00672
00673
00674 return 0;
00675 }
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688 int
00689 xmmsc_coll_attribute_get (xmmsc_coll_t *coll, const char *key, char **value)
00690 {
00691 x_list_t *n;
00692 for (n = coll->attributes; n; n = x_list_next (n)) {
00693 const char *k = n->data;
00694 if (strcasecmp (k, key) == 0 && n->next) {
00695
00696 if (value) {
00697 *value = (char*) n->next->data;
00698 }
00699
00700 return 1;
00701 } else {
00702
00703 n = x_list_next (n);
00704 }
00705 }
00706
00707 if (value) {
00708 *value = NULL;
00709 }
00710
00711 return 0;
00712 }
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725 void
00726 xmmsc_coll_attribute_foreach (xmmsc_coll_t *coll,
00727 xmmsc_coll_attribute_foreach_func func,
00728 void *user_data)
00729 {
00730 x_list_t *n;
00731 for (n = coll->attributes; n; n = x_list_next (n)) {
00732 const char *val = NULL;
00733 if (n->next) {
00734 val = n->next->data;
00735 }
00736 func ((const char*)n->data, val, user_data);
00737 n = x_list_next (n);
00738 }
00739
00740 return;
00741 }
00742
00743 void
00744 xmmsc_coll_attribute_list_first (xmmsc_coll_t *coll)
00745 {
00746 x_return_if_fail (coll);
00747
00748 coll->curr_att = coll->attributes;
00749 }
00750
00751 int
00752 xmmsc_coll_attribute_list_valid (xmmsc_coll_t *coll)
00753 {
00754 x_return_val_if_fail (coll, 0);
00755
00756 return !!coll->curr_att;
00757 }
00758
00759 void
00760 xmmsc_coll_attribute_list_entry (xmmsc_coll_t *coll, const char **k, const char **v)
00761 {
00762 x_return_if_fail (coll);
00763 x_return_if_fail (coll->curr_att);
00764 x_return_if_fail (coll->curr_att->next);
00765
00766 *k = coll->curr_att->data;
00767 *v = coll->curr_att->next->data;
00768 }
00769
00770 void
00771 xmmsc_coll_attribute_list_next (xmmsc_coll_t *coll)
00772 {
00773 x_return_if_fail (coll);
00774
00775 if (coll->curr_att && coll->curr_att->next && coll->curr_att->next->next) {
00776 coll->curr_att = coll->curr_att->next->next;
00777 } else {
00778 coll->curr_att = NULL;
00779 }
00780 }
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790 xmmsc_coll_t*
00791 xmmsc_coll_universe ()
00792 {
00793 xmmsc_coll_t *univ = xmmsc_coll_new (XMMS_COLLECTION_TYPE_REFERENCE);
00794 xmmsc_coll_attribute_set (univ, "reference", "All Media");
00795
00796
00797 return univ;
00798 }
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811 static int
00812 xmmsc_coll_unref_udata (void *coll, void *userdata)
00813 {
00814 xmmsc_coll_unref ((xmmsc_coll_t *)coll);
00815 return 1;
00816 }
00817
00818
00819
00820
00821
00822 static int
00823 free_udata (void *ptr, void *userdata)
00824 {
00825 free (ptr);
00826 return 1;
00827 }
00828
00829
00830 static int
00831 xmmsc_coll_idlist_resize (xmmsc_coll_t *coll, size_t newsize)
00832 {
00833 uint32_t *newmem;
00834
00835 newmem = realloc (coll->idlist, newsize * sizeof (uint32_t));
00836
00837 if (newmem == NULL) {
00838 x_oom ();
00839 return 0;
00840 }
00841
00842 coll->idlist = newmem;
00843 coll->idlist_allocated = newsize;
00844
00845 return 1;
00846 }