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 <stdarg.h>
00020 #include <string.h>
00021 #include <ctype.h>
00022 #include <assert.h>
00023
00024 #include "xmmsc/xmmsv.h"
00025 #include "xmmsc/xmmsc_idnumbers.h"
00026 #include "xmmsc/xmmsc_errorcodes.h"
00027 #include "xmmsc/xmmsc_stdbool.h"
00028 #include "xmmsc/xmmsc_util.h"
00029 #include "xmmspriv/xmms_list.h"
00030
00031
00032
00033 const char *default_source_pref[] = {
00034 "server",
00035 "client/*",
00036 "plugin/id3v2",
00037 "plugin/segment",
00038 "plugin/*",
00039 "*",
00040 NULL
00041 };
00042
00043
00044 typedef struct xmmsv_list_St xmmsv_list_t;
00045 typedef struct xmmsv_dict_St xmmsv_dict_t;
00046
00047
00048 typedef struct xmmsv_bin_St {
00049 unsigned char *data;
00050 uint32_t len;
00051 } xmmsv_bin_t;
00052
00053 struct xmmsv_list_St {
00054 xmmsv_t **list;
00055 xmmsv_t *parent_value;
00056 int size;
00057 int allocated;
00058 bool restricted;
00059 xmmsv_type_t restricttype;
00060 x_list_t *iterators;
00061 };
00062
00063 static xmmsv_list_t *xmmsv_list_new (void);
00064 static void xmmsv_list_free (xmmsv_list_t *l);
00065 static int xmmsv_list_resize (xmmsv_list_t *l, int newsize);
00066 static int _xmmsv_list_insert (xmmsv_list_t *l, int pos, xmmsv_t *val);
00067 static int _xmmsv_list_append (xmmsv_list_t *l, xmmsv_t *val);
00068 static int _xmmsv_list_remove (xmmsv_list_t *l, int pos);
00069 static int _xmmsv_list_move (xmmsv_list_t *l, int old_pos, int new_pos);
00070 static void _xmmsv_list_clear (xmmsv_list_t *l);
00071
00072 static xmmsv_dict_t *xmmsv_dict_new (void);
00073 static void xmmsv_dict_free (xmmsv_dict_t *dict);
00074
00075
00076 struct xmmsv_list_iter_St {
00077 xmmsv_list_t *parent;
00078 int position;
00079 };
00080
00081 static xmmsv_list_iter_t *xmmsv_list_iter_new (xmmsv_list_t *l);
00082 static void xmmsv_list_iter_free (xmmsv_list_iter_t *it);
00083
00084
00085 static xmmsv_dict_iter_t *xmmsv_dict_iter_new (xmmsv_dict_t *d);
00086 static void xmmsv_dict_iter_free (xmmsv_dict_iter_t *it);
00087
00088
00089
00090 struct xmmsv_St {
00091 union {
00092 char *error;
00093 int32_t int32;
00094 char *string;
00095 xmmsv_coll_t *coll;
00096 xmmsv_bin_t bin;
00097 xmmsv_list_t *list;
00098 xmmsv_dict_t *dict;
00099 } value;
00100 xmmsv_type_t type;
00101
00102 int ref;
00103 };
00104
00105
00106 static xmmsv_t *xmmsv_new (xmmsv_type_t type);
00107 static void xmmsv_free (xmmsv_t *val);
00108 static int absolutify_and_validate_pos (int *pos, int size, int allow_append);
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 xmmsv_t *
00127 xmmsv_new_none (void)
00128 {
00129 xmmsv_t *val = xmmsv_new (XMMSV_TYPE_NONE);
00130 return val;
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140 xmmsv_t *
00141 xmmsv_new_error (const char *errstr)
00142 {
00143 xmmsv_t *val = xmmsv_new (XMMSV_TYPE_ERROR);
00144
00145 if (val) {
00146 val->value.error = strdup (errstr);
00147 }
00148
00149 return val;
00150 }
00151
00152
00153
00154
00155
00156
00157
00158 xmmsv_t *
00159 xmmsv_new_int (int32_t i)
00160 {
00161 xmmsv_t *val = xmmsv_new (XMMSV_TYPE_INT32);
00162
00163 if (val) {
00164 val->value.int32 = i;
00165 }
00166
00167 return val;
00168 }
00169
00170
00171
00172
00173
00174
00175
00176
00177 xmmsv_t *
00178 xmmsv_new_string (const char *s)
00179 {
00180 xmmsv_t *val;
00181
00182 x_return_val_if_fail (s, NULL);
00183 x_return_val_if_fail (xmmsv_utf8_validate (s), NULL);
00184
00185 val = xmmsv_new (XMMSV_TYPE_STRING);
00186 if (val) {
00187 val->value.string = strdup (s);
00188 }
00189
00190 return val;
00191 }
00192
00193
00194
00195
00196
00197
00198
00199 xmmsv_t *
00200 xmmsv_new_coll (xmmsv_coll_t *c)
00201 {
00202 xmmsv_t *val;
00203
00204 x_return_val_if_fail (c, NULL);
00205
00206 val = xmmsv_new (XMMSV_TYPE_COLL);
00207 if (val) {
00208 val->value.coll = c;
00209 xmmsv_coll_ref (c);
00210 }
00211
00212 return val;
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222 xmmsv_t *
00223 xmmsv_new_bin (unsigned char *data, unsigned int len)
00224 {
00225 xmmsv_t *val = xmmsv_new (XMMSV_TYPE_BIN);
00226
00227 if (val) {
00228
00229 val->value.bin.data = x_malloc (len);
00230 if (!val->value.bin.data) {
00231 free (val);
00232 x_oom ();
00233 return NULL;
00234 }
00235 memcpy (val->value.bin.data, data, len);
00236 val->value.bin.len = len;
00237 }
00238
00239 return val;
00240 }
00241
00242
00243
00244
00245
00246
00247 xmmsv_t *
00248 xmmsv_new_list (void)
00249 {
00250 xmmsv_t *val = xmmsv_new (XMMSV_TYPE_LIST);
00251
00252 if (val) {
00253 val->value.list = xmmsv_list_new ();
00254 val->value.list->parent_value = val;
00255 }
00256
00257 return val;
00258 }
00259
00260
00261
00262
00263
00264
00265 xmmsv_t *
00266 xmmsv_new_dict (void)
00267 {
00268 xmmsv_t *val = xmmsv_new (XMMSV_TYPE_DICT);
00269
00270 if (val) {
00271 val->value.dict = xmmsv_dict_new ();
00272 }
00273
00274 return val;
00275 }
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285 xmmsv_t *
00286 xmmsv_ref (xmmsv_t *val)
00287 {
00288 x_return_val_if_fail (val, NULL);
00289 val->ref++;
00290
00291 return val;
00292 }
00293
00294
00295
00296
00297
00298
00299
00300 void
00301 xmmsv_unref (xmmsv_t *val)
00302 {
00303 x_return_if_fail (val);
00304 x_api_error_if (val->ref < 1, "with a freed value",);
00305
00306 val->ref--;
00307 if (val->ref == 0) {
00308 xmmsv_free (val);
00309 }
00310 }
00311
00312
00313
00314
00315
00316
00317 static xmmsv_t *
00318 xmmsv_new (xmmsv_type_t type)
00319 {
00320 xmmsv_t *val;
00321
00322 val = x_new0 (xmmsv_t, 1);
00323 if (!val) {
00324 x_oom ();
00325 return NULL;
00326 }
00327
00328 val->type = type;
00329
00330 return xmmsv_ref (val);
00331 }
00332
00333
00334
00335
00336
00337 static void
00338 xmmsv_free (xmmsv_t *val)
00339 {
00340 x_return_if_fail (val);
00341
00342 switch (val->type) {
00343 case XMMSV_TYPE_NONE :
00344 case XMMSV_TYPE_END :
00345 case XMMSV_TYPE_INT32 :
00346 break;
00347 case XMMSV_TYPE_ERROR :
00348 free (val->value.error);
00349 val->value.error = NULL;
00350 break;
00351 case XMMSV_TYPE_STRING :
00352 free (val->value.string);
00353 val->value.string = NULL;
00354 break;
00355 case XMMSV_TYPE_COLL:
00356 xmmsv_coll_unref (val->value.coll);
00357 val->value.coll = NULL;
00358 break;
00359 case XMMSV_TYPE_BIN :
00360 free (val->value.bin.data);
00361 val->value.bin.len = 0;
00362 break;
00363 case XMMSV_TYPE_LIST:
00364 xmmsv_list_free (val->value.list);
00365 val->value.list = NULL;
00366 break;
00367 case XMMSV_TYPE_DICT:
00368 xmmsv_dict_free (val->value.dict);
00369 val->value.dict = NULL;
00370 break;
00371 }
00372
00373 free (val);
00374 }
00375
00376
00377
00378
00379
00380
00381
00382
00383 xmmsv_type_t
00384 xmmsv_get_type (const xmmsv_t *val)
00385 {
00386 x_api_error_if (!val, "NULL value",
00387 XMMSV_TYPE_NONE);
00388
00389 return val->type;
00390 }
00391
00392
00393
00394
00395
00396
00397
00398
00399 int
00400 xmmsv_is_type (const xmmsv_t *val, xmmsv_type_t t)
00401 {
00402 x_api_error_if (!val, "NULL value", 0);
00403
00404 return (xmmsv_get_type (val) == t);
00405 }
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416 int
00417 xmmsv_is_error (const xmmsv_t *val)
00418 {
00419 return xmmsv_is_type (val, XMMSV_TYPE_ERROR);
00420 }
00421
00422
00423
00424
00425
00426
00427
00428 int
00429 xmmsv_is_list (const xmmsv_t *val)
00430 {
00431 return xmmsv_is_type (val, XMMSV_TYPE_LIST);
00432 }
00433
00434
00435
00436
00437
00438
00439
00440 int
00441 xmmsv_is_dict (const xmmsv_t *val)
00442 {
00443 return xmmsv_is_type (val, XMMSV_TYPE_DICT);
00444 }
00445
00446
00447
00448
00449
00450
00451
00452
00453 const char *
00454 xmmsv_get_error_old (const xmmsv_t *val)
00455 {
00456 if (!val || val->type != XMMSV_TYPE_ERROR) {
00457 return NULL;
00458 }
00459
00460 return val->value.error;
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474 xmmsv_t *
00475 xmmsv_make_stringlist (char *array[], int num)
00476 {
00477 xmmsv_t *list, *elem;
00478 int i;
00479
00480 list = xmmsv_new_list ();
00481 if (array) {
00482 for (i = 0; (num >= 0 && i < num) || array[i]; i++) {
00483 elem = xmmsv_new_string (array[i]);
00484 xmmsv_list_append (list, elem);
00485 xmmsv_unref (elem);
00486 }
00487 }
00488
00489 return list;
00490 }
00491
00492
00493
00494
00495
00496
00497
00498
00499 xmmsv_type_t
00500 xmmsv_dict_entry_get_type (xmmsv_t *val, const char *key)
00501 {
00502 xmmsv_t *v;
00503
00504 if (!xmmsv_dict_get (val, key, &v)) {
00505 return XMMSV_TYPE_NONE;
00506 }
00507
00508 return xmmsv_get_type (v);
00509 }
00510
00511
00512
00513 #define GEN_DICT_EXTRACTOR_FUNC(typename, type) \
00514 int \
00515 xmmsv_dict_entry_get_##typename (xmmsv_t *val, const char *key, \
00516 type *r) \
00517 { \
00518 xmmsv_t *v; \
00519 if (!xmmsv_dict_get (val, key, &v)) { \
00520 return 0; \
00521 } \
00522 return xmmsv_get_##typename (v, r); \
00523 }
00524
00525 GEN_DICT_EXTRACTOR_FUNC (string, const char *)
00526 GEN_DICT_EXTRACTOR_FUNC (int, int32_t)
00527 GEN_DICT_EXTRACTOR_FUNC (coll, xmmsv_coll_t *)
00528
00529
00530 #define GEN_DICT_SET_FUNC(typename, type) \
00531 int \
00532 xmmsv_dict_set_##typename (xmmsv_t *dict, const char *key, type elem) \
00533 { \
00534 int ret; \
00535 xmmsv_t *v; \
00536 \
00537 v = xmmsv_new_##typename (elem); \
00538 ret = xmmsv_dict_set (dict, key, v); \
00539 xmmsv_unref (v); \
00540 \
00541 return ret; \
00542 }
00543
00544 GEN_DICT_SET_FUNC (string, const char *)
00545 GEN_DICT_SET_FUNC (int, int32_t)
00546 GEN_DICT_SET_FUNC (coll, xmmsv_coll_t *)
00547
00548
00549 #define GEN_DICT_ITER_EXTRACTOR_FUNC(typename, type) \
00550 int \
00551 xmmsv_dict_iter_pair_##typename (xmmsv_dict_iter_t *it, \
00552 const char **key, \
00553 type *r) \
00554 { \
00555 xmmsv_t *v; \
00556 if (!xmmsv_dict_iter_pair (it, key, &v)) { \
00557 return 0; \
00558 } \
00559 if (r) { \
00560 return xmmsv_get_##typename (v, r); \
00561 } else { \
00562 return 1; \
00563 } \
00564 }
00565
00566 GEN_DICT_ITER_EXTRACTOR_FUNC (string, const char *)
00567 GEN_DICT_ITER_EXTRACTOR_FUNC (int, int32_t)
00568 GEN_DICT_ITER_EXTRACTOR_FUNC (coll, xmmsv_coll_t *)
00569
00570
00571 #define GEN_DICT_ITER_SET_FUNC(typename, type) \
00572 int \
00573 xmmsv_dict_iter_set_##typename (xmmsv_dict_iter_t *it, type elem) \
00574 { \
00575 int ret; \
00576 xmmsv_t *v; \
00577 \
00578 v = xmmsv_new_##typename (elem); \
00579 ret = xmmsv_dict_iter_set (it, v); \
00580 xmmsv_unref (v); \
00581 \
00582 return ret; \
00583 }
00584
00585 GEN_DICT_ITER_SET_FUNC (string, const char *)
00586 GEN_DICT_ITER_SET_FUNC (int, int32_t)
00587 GEN_DICT_ITER_SET_FUNC (coll, xmmsv_coll_t *)
00588
00589
00590 #define GEN_LIST_EXTRACTOR_FUNC(typename, type) \
00591 int \
00592 xmmsv_list_get_##typename (xmmsv_t *val, int pos, type *r) \
00593 { \
00594 xmmsv_t *v; \
00595 if (!xmmsv_list_get (val, pos, &v)) { \
00596 return 0; \
00597 } \
00598 return xmmsv_get_##typename (v, r); \
00599 }
00600
00601 GEN_LIST_EXTRACTOR_FUNC (string, const char *)
00602 GEN_LIST_EXTRACTOR_FUNC (int, int32_t)
00603 GEN_LIST_EXTRACTOR_FUNC (coll, xmmsv_coll_t *)
00604
00605
00606 #define GEN_LIST_SET_FUNC(typename, type) \
00607 int \
00608 xmmsv_list_set_##typename (xmmsv_t *list, int pos, type elem) \
00609 { \
00610 int ret; \
00611 xmmsv_t *v; \
00612 \
00613 v = xmmsv_new_##typename (elem); \
00614 ret = xmmsv_list_set (list, pos, v); \
00615 xmmsv_unref (v); \
00616 \
00617 return ret; \
00618 }
00619
00620 GEN_LIST_SET_FUNC (string, const char *)
00621 GEN_LIST_SET_FUNC (int, int32_t)
00622 GEN_LIST_SET_FUNC (coll, xmmsv_coll_t *)
00623
00624
00625 #define GEN_LIST_INSERT_FUNC(typename, type) \
00626 int \
00627 xmmsv_list_insert_##typename (xmmsv_t *list, int pos, type elem) \
00628 { \
00629 int ret; \
00630 xmmsv_t *v; \
00631 \
00632 v = xmmsv_new_##typename (elem); \
00633 ret = xmmsv_list_insert (list, pos, v); \
00634 xmmsv_unref (v); \
00635 \
00636 return ret; \
00637 }
00638
00639 GEN_LIST_INSERT_FUNC (string, const char *)
00640 GEN_LIST_INSERT_FUNC (int, int32_t)
00641 GEN_LIST_INSERT_FUNC (coll, xmmsv_coll_t *)
00642
00643
00644 #define GEN_LIST_APPEND_FUNC(typename, type) \
00645 int \
00646 xmmsv_list_append_##typename (xmmsv_t *list, type elem) \
00647 { \
00648 int ret; \
00649 xmmsv_t *v; \
00650 \
00651 v = xmmsv_new_##typename (elem); \
00652 ret = xmmsv_list_append (list, v); \
00653 xmmsv_unref (v); \
00654 \
00655 return ret; \
00656 }
00657
00658 GEN_LIST_APPEND_FUNC (string, const char *)
00659 GEN_LIST_APPEND_FUNC (int, int32_t)
00660 GEN_LIST_APPEND_FUNC (coll, xmmsv_coll_t *)
00661
00662
00663 #define GEN_LIST_ITER_EXTRACTOR_FUNC(typename, type) \
00664 int \
00665 xmmsv_list_iter_entry_##typename (xmmsv_list_iter_t *it, type *r) \
00666 { \
00667 xmmsv_t *v; \
00668 if (!xmmsv_list_iter_entry (it, &v)) { \
00669 return 0; \
00670 } \
00671 return xmmsv_get_##typename (v, r); \
00672 }
00673
00674 GEN_LIST_ITER_EXTRACTOR_FUNC (string, const char *)
00675 GEN_LIST_ITER_EXTRACTOR_FUNC (int, int32_t)
00676 GEN_LIST_ITER_EXTRACTOR_FUNC (coll, xmmsv_coll_t *)
00677
00678
00679 #define GEN_LIST_ITER_INSERT_FUNC(typename, type) \
00680 int \
00681 xmmsv_list_iter_insert_##typename (xmmsv_list_iter_t *it, type elem) \
00682 { \
00683 int ret; \
00684 xmmsv_t *v; \
00685 \
00686 v = xmmsv_new_##typename (elem); \
00687 ret = xmmsv_list_iter_insert (it, v); \
00688 xmmsv_unref (v); \
00689 \
00690 return ret; \
00691 }
00692
00693 GEN_LIST_ITER_INSERT_FUNC (string, const char *)
00694 GEN_LIST_ITER_INSERT_FUNC (int, int32_t)
00695 GEN_LIST_ITER_INSERT_FUNC (coll, xmmsv_coll_t *)
00696
00697 static int
00698 source_match_pattern (const char *source, const char *pattern)
00699 {
00700 int match = 0;
00701 int lpos = strlen (pattern) - 1;
00702
00703 if (strcasecmp (pattern, source) == 0) {
00704 match = 1;
00705 } else if (lpos >= 0 && pattern[lpos] == '*' &&
00706 (lpos == 0 || strncasecmp (source, pattern, lpos) == 0)) {
00707 match = 1;
00708 }
00709
00710 return match;
00711 }
00712
00713
00714
00715
00716 static int
00717 find_match_index (const char *source, const char **src_prefs)
00718 {
00719 int i, match = -1;
00720
00721 for (i = 0; src_prefs[i]; i++) {
00722 if (source_match_pattern (source, src_prefs[i])) {
00723 match = i;
00724 break;
00725 }
00726 }
00727
00728 return match;
00729 }
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743 xmmsv_t *
00744 xmmsv_propdict_to_dict (xmmsv_t *propdict, const char **src_prefs)
00745 {
00746 xmmsv_t *dict, *source_dict, *value, *best_value;
00747 xmmsv_dict_iter_t *key_it, *source_it;
00748 const char *key, *source;
00749 const char **local_prefs;
00750 int match_index, best_index;
00751
00752 dict = xmmsv_new_dict ();
00753
00754 local_prefs = src_prefs ? src_prefs : default_source_pref;
00755
00756 xmmsv_get_dict_iter (propdict, &key_it);
00757 while (xmmsv_dict_iter_valid (key_it)) {
00758 xmmsv_dict_iter_pair (key_it, &key, &source_dict);
00759
00760 best_value = NULL;
00761 best_index = -1;
00762 xmmsv_get_dict_iter (source_dict, &source_it);
00763 while (xmmsv_dict_iter_valid (source_it)) {
00764 xmmsv_dict_iter_pair (source_it, &source, &value);
00765 match_index = find_match_index (source, local_prefs);
00766
00767 if (match_index >= 0 && (best_index < 0 ||
00768 match_index < best_index)) {
00769 best_value = value;
00770 best_index = match_index;
00771 }
00772 xmmsv_dict_iter_next (source_it);
00773 }
00774
00775
00776 if (best_value) {
00777 xmmsv_dict_set (dict, key, best_value);
00778 }
00779
00780 xmmsv_dict_iter_next (key_it);
00781 }
00782
00783 return dict;
00784 }
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 int
00796 xmmsv_get_error (const xmmsv_t *val, const char **r)
00797 {
00798 if (!val || val->type != XMMSV_TYPE_ERROR) {
00799 return 0;
00800 }
00801
00802 *r = val->value.error;
00803
00804 return 1;
00805 }
00806
00807
00808
00809
00810
00811
00812
00813
00814 int
00815 xmmsv_get_int (const xmmsv_t *val, int32_t *r)
00816 {
00817 if (!val || val->type != XMMSV_TYPE_INT32) {
00818 return 0;
00819 }
00820
00821 *r = val->value.int32;
00822
00823 return 1;
00824 }
00825
00826
00827
00828
00829
00830
00831
00832
00833 int
00834 xmmsv_get_uint (const xmmsv_t *val, uint32_t *r)
00835 {
00836 if (!val)
00837 return 0;
00838 if (val->type != XMMSV_TYPE_INT32)
00839 return 0;
00840
00841 *r = val->value.int32;
00842
00843 return 1;
00844 }
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854 int
00855 xmmsv_get_string (const xmmsv_t *val, const char **r)
00856 {
00857 if (!val || val->type != XMMSV_TYPE_STRING) {
00858 return 0;
00859 }
00860
00861 *r = val->value.string;
00862
00863 return 1;
00864 }
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874 int
00875 xmmsv_get_coll (const xmmsv_t *val, xmmsv_coll_t **c)
00876 {
00877 if (!val || val->type != XMMSV_TYPE_COLL) {
00878 return 0;
00879 }
00880
00881 *c = val->value.coll;
00882
00883 return 1;
00884 }
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895 int
00896 xmmsv_get_bin (const xmmsv_t *val, const unsigned char **r, unsigned int *rlen)
00897 {
00898 if (!val || val->type != XMMSV_TYPE_BIN) {
00899 return 0;
00900 }
00901
00902 *r = val->value.bin.data;
00903 *rlen = val->value.bin.len;
00904
00905 return 1;
00906 }
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917 int
00918 xmmsv_get_list_iter (const xmmsv_t *val, xmmsv_list_iter_t **it)
00919 {
00920 xmmsv_list_iter_t *new_it;
00921
00922 if (!val || val->type != XMMSV_TYPE_LIST) {
00923 *it = NULL;
00924 return 0;
00925 }
00926
00927 new_it = xmmsv_list_iter_new (val->value.list);
00928 if (!new_it) {
00929 *it = NULL;
00930 return 0;
00931 }
00932
00933 *it = new_it;
00934
00935 return 1;
00936 }
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946 int
00947 xmmsv_get_dict_iter (const xmmsv_t *val, xmmsv_dict_iter_t **it)
00948 {
00949 xmmsv_dict_iter_t *new_it;
00950
00951 if (!val || val->type != XMMSV_TYPE_DICT) {
00952 *it = NULL;
00953 return 0;
00954 }
00955
00956 new_it = xmmsv_dict_iter_new (val->value.dict);
00957 if (!new_it) {
00958 *it = NULL;
00959 return 0;
00960 }
00961
00962 *it = new_it;
00963
00964 return 1;
00965 }
00966
00967
00968
00969
00970 static xmmsv_list_t *
00971 xmmsv_list_new (void)
00972 {
00973 xmmsv_list_t *list;
00974
00975 list = x_new0 (xmmsv_list_t, 1);
00976 if (!list) {
00977 x_oom ();
00978 return NULL;
00979 }
00980
00981
00982
00983 return list;
00984 }
00985
00986 static void
00987 xmmsv_list_free (xmmsv_list_t *l)
00988 {
00989 xmmsv_list_iter_t *it;
00990 int i;
00991
00992
00993 while (l->iterators) {
00994 it = (xmmsv_list_iter_t *) l->iterators->data;
00995 xmmsv_list_iter_free (it);
00996 }
00997
00998
00999 for (i = 0; i < l->size; i++) {
01000 xmmsv_unref (l->list[i]);
01001 }
01002
01003 free (l->list);
01004 free (l);
01005 }
01006
01007 static int
01008 xmmsv_list_resize (xmmsv_list_t *l, int newsize)
01009 {
01010 xmmsv_t **newmem;
01011
01012 newmem = realloc (l->list, newsize * sizeof (xmmsv_t *));
01013
01014 if (newsize != 0 && newmem == NULL) {
01015 x_oom ();
01016 return 0;
01017 }
01018
01019 l->list = newmem;
01020 l->allocated = newsize;
01021
01022 return 1;
01023 }
01024
01025 static int
01026 _xmmsv_list_insert (xmmsv_list_t *l, int pos, xmmsv_t *val)
01027 {
01028 xmmsv_list_iter_t *it;
01029 x_list_t *n;
01030
01031 if (!absolutify_and_validate_pos (&pos, l->size, 1)) {
01032 return 0;
01033 }
01034
01035 if (l->restricted) {
01036 x_return_val_if_fail (xmmsv_is_type (val, l->restricttype), 0);
01037 }
01038
01039
01040 if (l->size == l->allocated) {
01041 int success;
01042 size_t double_size;
01043 if (l->allocated > 0) {
01044 double_size = l->allocated << 1;
01045 } else {
01046 double_size = 1;
01047 }
01048 success = xmmsv_list_resize (l, double_size);
01049 x_return_val_if_fail (success, 0);
01050 }
01051
01052
01053 if (l->size > pos) {
01054 memmove (l->list + pos + 1, l->list + pos,
01055 (l->size - pos) * sizeof (xmmsv_t *));
01056 }
01057
01058 l->list[pos] = xmmsv_ref (val);
01059 l->size++;
01060
01061
01062 for (n = l->iterators; n; n = n->next) {
01063 it = (xmmsv_list_iter_t *) n->data;
01064 if (it->position > pos) {
01065 it->position++;
01066 }
01067 }
01068
01069 return 1;
01070 }
01071
01072 static int
01073 _xmmsv_list_append (xmmsv_list_t *l, xmmsv_t *val)
01074 {
01075 return _xmmsv_list_insert (l, l->size, val);
01076 }
01077
01078 static int
01079 _xmmsv_list_remove (xmmsv_list_t *l, int pos)
01080 {
01081 xmmsv_list_iter_t *it;
01082 int half_size;
01083 x_list_t *n;
01084
01085
01086 if (!absolutify_and_validate_pos (&pos, l->size, 0)) {
01087 return 0;
01088 }
01089
01090 xmmsv_unref (l->list[pos]);
01091
01092 l->size--;
01093
01094
01095 if (pos < l->size) {
01096 memmove (l->list + pos, l->list + pos + 1,
01097 (l->size - pos) * sizeof (xmmsv_t *));
01098 }
01099
01100
01101 half_size = l->allocated >> 1;
01102 if (l->size <= half_size) {
01103 int success;
01104 success = xmmsv_list_resize (l, half_size);
01105 x_return_val_if_fail (success, 0);
01106 }
01107
01108
01109 for (n = l->iterators; n; n = n->next) {
01110 it = (xmmsv_list_iter_t *) n->data;
01111 if (it->position > pos) {
01112 it->position--;
01113 }
01114 }
01115
01116 return 1;
01117 }
01118
01119 static int
01120 _xmmsv_list_move (xmmsv_list_t *l, int old_pos, int new_pos)
01121 {
01122 xmmsv_t *v;
01123 xmmsv_list_iter_t *it;
01124 x_list_t *n;
01125
01126 if (!absolutify_and_validate_pos (&old_pos, l->size, 0)) {
01127 return 0;
01128 }
01129 if (!absolutify_and_validate_pos (&new_pos, l->size, 0)) {
01130 return 0;
01131 }
01132
01133 v = l->list[old_pos];
01134 if (old_pos < new_pos) {
01135 memmove (l->list + old_pos, l->list + old_pos + 1,
01136 (new_pos - old_pos) * sizeof (xmmsv_t *));
01137 l->list[new_pos] = v;
01138
01139
01140 for (n = l->iterators; n; n = n->next) {
01141 it = (xmmsv_list_iter_t *) n->data;
01142 if (it->position >= old_pos && it->position <= new_pos) {
01143 if (it->position == old_pos) {
01144 it->position = new_pos;
01145 } else {
01146 it->position--;
01147 }
01148 }
01149 }
01150 } else {
01151 memmove (l->list + new_pos + 1, l->list + new_pos,
01152 (old_pos - new_pos) * sizeof (xmmsv_t *));
01153 l->list[new_pos] = v;
01154
01155
01156 for (n = l->iterators; n; n = n->next) {
01157 it = (xmmsv_list_iter_t *) n->data;
01158 if (it->position >= new_pos && it->position <= old_pos) {
01159 if (it->position == old_pos) {
01160 it->position = new_pos;
01161 } else {
01162 it->position++;
01163 }
01164 }
01165 }
01166 }
01167
01168 return 1;
01169 }
01170
01171 static void
01172 _xmmsv_list_clear (xmmsv_list_t *l)
01173 {
01174 xmmsv_list_iter_t *it;
01175 x_list_t *n;
01176 int i;
01177
01178
01179 for (i = 0; i < l->size; i++) {
01180 xmmsv_unref (l->list[i]);
01181 }
01182
01183
01184 free (l->list);
01185 l->list = NULL;
01186
01187 l->size = 0;
01188 l->allocated = 0;
01189
01190
01191 for (n = l->iterators; n; n = n->next) {
01192 it = (xmmsv_list_iter_t *) n->data;
01193 it->position = 0;
01194 }
01195 }
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209 int
01210 xmmsv_list_get (xmmsv_t *listv, int pos, xmmsv_t **val)
01211 {
01212 xmmsv_list_t *l;
01213
01214 x_return_val_if_fail (listv, 0);
01215 x_return_val_if_fail (xmmsv_is_type (listv, XMMSV_TYPE_LIST), 0);
01216
01217 l = listv->value.list;
01218
01219
01220 if (!absolutify_and_validate_pos (&pos, l->size, 0)) {
01221 return 0;
01222 }
01223
01224 if (val) {
01225 *val = l->list[pos];
01226 }
01227
01228 return 1;
01229 }
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240 int
01241 xmmsv_list_set (xmmsv_t *listv, int pos, xmmsv_t *val)
01242 {
01243 xmmsv_t *old_val;
01244 xmmsv_list_t *l;
01245
01246 x_return_val_if_fail (listv, 0);
01247 x_return_val_if_fail (val, 0);
01248 x_return_val_if_fail (xmmsv_is_type (listv, XMMSV_TYPE_LIST), 0);
01249
01250 l = listv->value.list;
01251
01252 if (!absolutify_and_validate_pos (&pos, l->size, 0)) {
01253 return 0;
01254 }
01255
01256 old_val = l->list[pos];
01257 l->list[pos] = xmmsv_ref (val);
01258 xmmsv_unref (old_val);
01259
01260 return 1;
01261 }
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273 int
01274 xmmsv_list_insert (xmmsv_t *listv, int pos, xmmsv_t *val)
01275 {
01276 x_return_val_if_fail (listv, 0);
01277 x_return_val_if_fail (xmmsv_is_type (listv, XMMSV_TYPE_LIST), 0);
01278 x_return_val_if_fail (val, 0);
01279
01280 return _xmmsv_list_insert (listv->value.list, pos, val);
01281 }
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291 int
01292 xmmsv_list_remove (xmmsv_t *listv, int pos)
01293 {
01294 x_return_val_if_fail (listv, 0);
01295 x_return_val_if_fail (xmmsv_is_type (listv, XMMSV_TYPE_LIST), 0);
01296
01297 return _xmmsv_list_remove (listv->value.list, pos);
01298 }
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314 int
01315 xmmsv_list_move (xmmsv_t *listv, int old_pos, int new_pos)
01316 {
01317 x_return_val_if_fail (listv, 0);
01318 x_return_val_if_fail (xmmsv_is_type (listv, XMMSV_TYPE_LIST), 0);
01319
01320 return _xmmsv_list_move (listv->value.list, old_pos, new_pos);
01321 }
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331 int
01332 xmmsv_list_append (xmmsv_t *listv, xmmsv_t *val)
01333 {
01334 x_return_val_if_fail (listv, 0);
01335 x_return_val_if_fail (xmmsv_is_type (listv, XMMSV_TYPE_LIST), 0);
01336 x_return_val_if_fail (val, 0);
01337
01338 return _xmmsv_list_append (listv->value.list, val);
01339 }
01340
01341
01342
01343
01344
01345
01346
01347 int
01348 xmmsv_list_clear (xmmsv_t *listv)
01349 {
01350 x_return_val_if_fail (listv, 0);
01351 x_return_val_if_fail (xmmsv_is_type (listv, XMMSV_TYPE_LIST), 0);
01352
01353 _xmmsv_list_clear (listv->value.list);
01354
01355 return 1;
01356 }
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366 int
01367 xmmsv_list_foreach (xmmsv_t *listv, xmmsv_list_foreach_func func,
01368 void* user_data)
01369 {
01370 xmmsv_list_iter_t *it;
01371 xmmsv_t *v;
01372
01373 x_return_val_if_fail (listv, 0);
01374 x_return_val_if_fail (xmmsv_is_type (listv, XMMSV_TYPE_LIST), 0);
01375 x_return_val_if_fail (xmmsv_get_list_iter (listv, &it), 0);
01376
01377 while (xmmsv_list_iter_valid (it)) {
01378 xmmsv_list_iter_entry (it, &v);
01379 func (v, user_data);
01380 xmmsv_list_iter_next (it);
01381 }
01382
01383 xmmsv_list_iter_free (it);
01384
01385 return 1;
01386 }
01387
01388
01389
01390
01391
01392
01393
01394 int
01395 xmmsv_list_get_size (xmmsv_t *listv)
01396 {
01397 x_return_val_if_fail (listv, -1);
01398 x_return_val_if_fail (xmmsv_is_type (listv, XMMSV_TYPE_LIST), -1);
01399
01400 return listv->value.list->size;
01401 }
01402
01403
01404 int
01405 xmmsv_list_restrict_type (xmmsv_t *listv, xmmsv_type_t type)
01406 {
01407 xmmsv_list_iter_t *it;
01408 xmmsv_t *v;
01409
01410 x_return_val_if_fail (listv, 0);
01411 x_return_val_if_fail (xmmsv_is_type (listv, XMMSV_TYPE_LIST), 0);
01412
01413 x_return_val_if_fail (!listv->value.list->restricted, 0);
01414
01415 x_return_val_if_fail (xmmsv_get_list_iter (listv, &it), 0);
01416 while (xmmsv_list_iter_valid (it)) {
01417 xmmsv_list_iter_entry (it, &v);
01418 x_return_val_if_fail (xmmsv_is_type (v, type), 0);
01419 xmmsv_list_iter_next (it);
01420 }
01421
01422 xmmsv_list_iter_free (it);
01423
01424 listv->value.list->restricted = true;
01425 listv->value.list->restricttype = type;
01426
01427 return 1;
01428 }
01429
01430
01431 static xmmsv_list_iter_t *
01432 xmmsv_list_iter_new (xmmsv_list_t *l)
01433 {
01434 xmmsv_list_iter_t *it;
01435
01436 it = x_new0 (xmmsv_list_iter_t, 1);
01437 if (!it) {
01438 x_oom ();
01439 return NULL;
01440 }
01441
01442 it->parent = l;
01443 it->position = 0;
01444
01445
01446 l->iterators = x_list_prepend (l->iterators, it);
01447
01448 return it;
01449 }
01450
01451 static void
01452 xmmsv_list_iter_free (xmmsv_list_iter_t *it)
01453 {
01454
01455 it->parent->iterators = x_list_remove (it->parent->iterators, it);
01456 free (it);
01457 }
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469 void
01470 xmmsv_list_iter_explicit_destroy (xmmsv_list_iter_t *it)
01471 {
01472 xmmsv_list_iter_free (it);
01473 }
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486 int
01487 xmmsv_list_iter_entry (xmmsv_list_iter_t *it, xmmsv_t **val)
01488 {
01489 if (!xmmsv_list_iter_valid (it))
01490 return 0;
01491
01492 *val = it->parent->list[it->position];
01493
01494 return 1;
01495 }
01496
01497
01498
01499
01500
01501
01502
01503 int
01504 xmmsv_list_iter_valid (xmmsv_list_iter_t *it)
01505 {
01506 return it && (it->position < it->parent->size) && (it->position >= 0);
01507 }
01508
01509
01510
01511
01512
01513
01514 void
01515 xmmsv_list_iter_first (xmmsv_list_iter_t *it)
01516 {
01517 x_return_if_fail (it);
01518
01519 it->position = 0;
01520 }
01521
01522
01523
01524
01525
01526
01527 void
01528 xmmsv_list_iter_last (xmmsv_list_iter_t *it)
01529 {
01530 x_return_if_fail (it);
01531
01532 if (it->parent->size > 0) {
01533 it->position = it->parent->size - 1;
01534 } else {
01535 it->position = it->parent->size;
01536 }
01537 }
01538
01539
01540
01541
01542
01543
01544 void
01545 xmmsv_list_iter_next (xmmsv_list_iter_t *it)
01546 {
01547 x_return_if_fail (it);
01548
01549 if (it->position < it->parent->size) {
01550 it->position++;
01551 }
01552 }
01553
01554
01555
01556
01557
01558
01559 void
01560 xmmsv_list_iter_prev (xmmsv_list_iter_t *it)
01561 {
01562 x_return_if_fail (it);
01563
01564 if (it->position >= 0) {
01565 it->position--;
01566 }
01567 }
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578 int
01579 xmmsv_list_iter_seek (xmmsv_list_iter_t *it, int pos)
01580 {
01581 x_return_val_if_fail (it, 0);
01582
01583 if (!absolutify_and_validate_pos (&pos, it->parent->size, 1)) {
01584 return 0;
01585 }
01586 it->position = pos;
01587
01588 return 1;
01589 }
01590
01591
01592
01593
01594
01595
01596
01597 int
01598 xmmsv_list_iter_tell (const xmmsv_list_iter_t *it)
01599 {
01600 x_return_val_if_fail (it, -1);
01601
01602 return it->position;
01603 }
01604
01605
01606
01607
01608
01609
01610
01611 xmmsv_t*
01612 xmmsv_list_iter_get_parent (const xmmsv_list_iter_t *it)
01613 {
01614 x_return_val_if_fail (it, NULL);
01615
01616 return it->parent->parent_value;
01617 }
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627 int
01628 xmmsv_list_iter_insert (xmmsv_list_iter_t *it, xmmsv_t *val)
01629 {
01630 x_return_val_if_fail (it, 0);
01631 x_return_val_if_fail (val, 0);
01632
01633 return _xmmsv_list_insert (it->parent, it->position, val);
01634 }
01635
01636
01637
01638
01639
01640
01641
01642
01643 int
01644 xmmsv_list_iter_remove (xmmsv_list_iter_t *it)
01645 {
01646 x_return_val_if_fail (it, 0);
01647
01648 return _xmmsv_list_remove (it->parent, it->position);
01649 }
01650
01651
01652
01653 struct xmmsv_dict_St {
01654
01655 xmmsv_list_t *flatlist;
01656 x_list_t *iterators;
01657 };
01658
01659 struct xmmsv_dict_iter_St {
01660
01661 xmmsv_list_iter_t *lit;
01662 xmmsv_dict_t *parent;
01663 };
01664
01665 static xmmsv_dict_t *
01666 xmmsv_dict_new (void)
01667 {
01668 xmmsv_dict_t *dict;
01669
01670 dict = x_new0 (xmmsv_dict_t, 1);
01671 if (!dict) {
01672 x_oom ();
01673 return NULL;
01674 }
01675
01676 dict->flatlist = xmmsv_list_new ();
01677
01678 return dict;
01679 }
01680
01681 static void
01682 xmmsv_dict_free (xmmsv_dict_t *dict)
01683 {
01684 xmmsv_dict_iter_t *it;
01685
01686
01687 while (dict->iterators) {
01688 it = (xmmsv_dict_iter_t *) dict->iterators->data;
01689 xmmsv_dict_iter_free (it);
01690 }
01691
01692 xmmsv_list_free (dict->flatlist);
01693
01694 free (dict);
01695 }
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708 int
01709 xmmsv_dict_get (xmmsv_t *dictv, const char *key, xmmsv_t **val)
01710 {
01711 xmmsv_dict_iter_t *it;
01712 int ret = 1;
01713
01714 x_return_val_if_fail (key, 0);
01715 x_return_val_if_fail (dictv, 0);
01716 x_return_val_if_fail (xmmsv_is_type (dictv, XMMSV_TYPE_DICT), 0);
01717 x_return_val_if_fail (xmmsv_get_dict_iter (dictv, &it), 0);
01718
01719 if (!xmmsv_dict_iter_find (it, key)) {
01720 ret = 0;
01721 }
01722
01723
01724 if (ret && val) {
01725 xmmsv_dict_iter_pair (it, NULL, val);
01726 }
01727
01728 xmmsv_dict_iter_free (it);
01729
01730 return ret;
01731 }
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743 int
01744 xmmsv_dict_set (xmmsv_t *dictv, const char *key, xmmsv_t *val)
01745 {
01746 xmmsv_dict_iter_t *it;
01747 int ret;
01748
01749 x_return_val_if_fail (key, 0);
01750 x_return_val_if_fail (val, 0);
01751 x_return_val_if_fail (dictv, 0);
01752 x_return_val_if_fail (xmmsv_is_type (dictv, XMMSV_TYPE_DICT), 0);
01753 x_return_val_if_fail (xmmsv_get_dict_iter (dictv, &it), 0);
01754
01755
01756 if (xmmsv_dict_iter_find (it, key)) {
01757 ret = xmmsv_dict_iter_set (it, val);
01758
01759
01760 } else {
01761 xmmsv_t *keyval;
01762
01763 keyval = xmmsv_new_string (key);
01764
01765 ret = xmmsv_list_iter_insert (it->lit, keyval);
01766 if (ret) {
01767 xmmsv_list_iter_next (it->lit);
01768 ret = xmmsv_list_iter_insert (it->lit, val);
01769 if (!ret) {
01770
01771
01772
01773
01774 it->lit->position--;
01775 xmmsv_list_iter_remove (it->lit);
01776 }
01777 }
01778 xmmsv_unref (keyval);
01779 }
01780
01781 xmmsv_dict_iter_free (it);
01782
01783 return ret;
01784 }
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794 int
01795 xmmsv_dict_remove (xmmsv_t *dictv, const char *key)
01796 {
01797 xmmsv_dict_iter_t *it;
01798 int ret = 1;
01799
01800 x_return_val_if_fail (key, 0);
01801 x_return_val_if_fail (dictv, 0);
01802 x_return_val_if_fail (xmmsv_is_type (dictv, XMMSV_TYPE_DICT), 0);
01803 x_return_val_if_fail (xmmsv_get_dict_iter (dictv, &it), 0);
01804
01805 if (!xmmsv_dict_iter_find (it, key)) {
01806 ret = 0;
01807 } else {
01808 ret = xmmsv_list_iter_remove (it->lit) &&
01809 xmmsv_list_iter_remove (it->lit);
01810
01811 }
01812
01813 xmmsv_dict_iter_free (it);
01814
01815 return ret;
01816 }
01817
01818
01819
01820
01821
01822
01823
01824 int
01825 xmmsv_dict_clear (xmmsv_t *dictv)
01826 {
01827 x_return_val_if_fail (dictv, 0);
01828 x_return_val_if_fail (xmmsv_is_type (dictv, XMMSV_TYPE_DICT), 0);
01829
01830 _xmmsv_list_clear (dictv->value.dict->flatlist);
01831
01832 return 1;
01833 }
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844 int
01845 xmmsv_dict_foreach (xmmsv_t *dictv, xmmsv_dict_foreach_func func,
01846 void *user_data)
01847 {
01848 xmmsv_dict_iter_t *it;
01849 const char *key;
01850 xmmsv_t *v;
01851
01852 x_return_val_if_fail (dictv, 0);
01853 x_return_val_if_fail (xmmsv_is_type (dictv, XMMSV_TYPE_DICT), 0);
01854 x_return_val_if_fail (xmmsv_get_dict_iter (dictv, &it), 0);
01855
01856 while (xmmsv_dict_iter_valid (it)) {
01857 xmmsv_dict_iter_pair (it, &key, &v);
01858 func (key, v, user_data);
01859 xmmsv_dict_iter_next (it);
01860 }
01861
01862 xmmsv_dict_iter_free (it);
01863
01864 return 1;
01865 }
01866
01867
01868
01869
01870
01871
01872
01873 int
01874 xmmsv_dict_get_size (xmmsv_t *dictv)
01875 {
01876 x_return_val_if_fail (dictv, -1);
01877 x_return_val_if_fail (xmmsv_is_type (dictv, XMMSV_TYPE_DICT), -1);
01878
01879 return dictv->value.dict->flatlist->size / 2;
01880 }
01881
01882 static xmmsv_dict_iter_t *
01883 xmmsv_dict_iter_new (xmmsv_dict_t *d)
01884 {
01885 xmmsv_dict_iter_t *it;
01886
01887 it = x_new0 (xmmsv_dict_iter_t, 1);
01888 if (!it) {
01889 x_oom ();
01890 return NULL;
01891 }
01892
01893 it->lit = xmmsv_list_iter_new (d->flatlist);
01894 it->parent = d;
01895
01896
01897 d->iterators = x_list_prepend (d->iterators, it);
01898
01899 return it;
01900 }
01901
01902 static void
01903 xmmsv_dict_iter_free (xmmsv_dict_iter_t *it)
01904 {
01905
01906
01907
01908 it->parent->iterators = x_list_remove (it->parent->iterators, it);
01909 free (it);
01910 }
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922 void
01923 xmmsv_dict_iter_explicit_destroy (xmmsv_dict_iter_t *it)
01924 {
01925 xmmsv_dict_iter_free (it);
01926 }
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939 int
01940 xmmsv_dict_iter_pair (xmmsv_dict_iter_t *it, const char **key,
01941 xmmsv_t **val)
01942 {
01943 unsigned int orig;
01944 xmmsv_t *v;
01945
01946 if (!xmmsv_dict_iter_valid (it)) {
01947 return 0;
01948 }
01949
01950
01951 orig = it->lit->position;
01952
01953 if (key) {
01954 xmmsv_list_iter_entry (it->lit, &v);
01955 xmmsv_get_string (v, key);
01956 }
01957
01958 if (val) {
01959 xmmsv_list_iter_next (it->lit);
01960 xmmsv_list_iter_entry (it->lit, val);
01961 }
01962
01963 it->lit->position = orig;
01964
01965 return 1;
01966 }
01967
01968
01969
01970
01971
01972
01973
01974 int
01975 xmmsv_dict_iter_valid (xmmsv_dict_iter_t *it)
01976 {
01977 return it && xmmsv_list_iter_valid (it->lit);
01978 }
01979
01980
01981
01982
01983
01984
01985
01986 void
01987 xmmsv_dict_iter_first (xmmsv_dict_iter_t *it)
01988 {
01989 x_return_if_fail (it);
01990
01991 xmmsv_list_iter_first (it->lit);
01992 }
01993
01994
01995
01996
01997
01998
01999
02000 void
02001 xmmsv_dict_iter_next (xmmsv_dict_iter_t *it)
02002 {
02003 x_return_if_fail (it);
02004
02005
02006 xmmsv_list_iter_next (it->lit);
02007 xmmsv_list_iter_next (it->lit);
02008 }
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019 int
02020 xmmsv_dict_iter_find (xmmsv_dict_iter_t *it, const char *key)
02021 {
02022 xmmsv_t *val;
02023 const char *k;
02024 int s, dict_size, cmp, left, right;
02025
02026 x_return_val_if_fail (it, 0);
02027 x_return_val_if_fail (key, 0);
02028
02029
02030 dict_size = it->parent->flatlist->size / 2;
02031
02032
02033
02034
02035 if (!dict_size) {
02036 xmmsv_list_iter_seek (it->lit, 0);
02037
02038 return 0;
02039 }
02040
02041
02042 left = 0;
02043 right = dict_size - 1;
02044
02045 while (left <= right) {
02046 int mid = left + ((right - left) / 2);
02047
02048
02049 xmmsv_list_iter_seek (it->lit, mid * 2);
02050 xmmsv_list_iter_entry (it->lit, &val);
02051
02052
02053 s = xmmsv_get_string (val, &k);
02054 x_return_val_if_fail (s, 0);
02055
02056
02057 cmp = strcmp (k, key);
02058
02059
02060 if (cmp == 0)
02061 return 1;
02062
02063
02064 if (cmp < 0) {
02065 left = mid + 1;
02066 } else {
02067 right = mid - 1;
02068 }
02069 }
02070
02071
02072
02073
02074
02075
02076 if (cmp < 0) {
02077 xmmsv_list_iter_next (it->lit);
02078 xmmsv_list_iter_next (it->lit);
02079 }
02080
02081 return 0;
02082 }
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092 int
02093 xmmsv_dict_iter_set (xmmsv_dict_iter_t *it, xmmsv_t *val)
02094 {
02095 unsigned int orig;
02096 int ret;
02097
02098 x_return_val_if_fail (xmmsv_dict_iter_valid (it), 0);
02099
02100
02101 orig = it->lit->position;
02102
02103 xmmsv_list_iter_next (it->lit);
02104 xmmsv_list_iter_remove (it->lit);
02105 ret = xmmsv_list_iter_insert (it->lit, val);
02106
02107
02108 it->lit->position = orig;
02109
02110 return ret;
02111 }
02112
02113
02114
02115
02116
02117
02118
02119 int
02120 xmmsv_dict_iter_remove (xmmsv_dict_iter_t *it)
02121 {
02122 int ret = 0;
02123
02124 ret = xmmsv_list_iter_remove (it->lit) &&
02125 xmmsv_list_iter_remove (it->lit);
02126
02127
02128 return ret;
02129 }
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158 xmmsv_t *
02159 xmmsv_decode_url (const xmmsv_t *inv)
02160 {
02161 int i = 0, j = 0;
02162 const char *ins;
02163 unsigned char *url;
02164 xmmsv_t *ret;
02165
02166 if (!xmmsv_get_string (inv, &ins)) {
02167 return NULL;
02168 }
02169
02170 url = x_malloc (strlen (ins));
02171 if (!url) {
02172 x_oom ();
02173 return NULL;
02174 }
02175
02176 while (ins[i]) {
02177 unsigned char chr = ins[i++];
02178
02179 if (chr == '+') {
02180 chr = ' ';
02181 } else if (chr == '%') {
02182 char ts[3];
02183 char *t;
02184
02185 ts[0] = ins[i++];
02186 if (!ts[0])
02187 goto err;
02188 ts[1] = ins[i++];
02189 if (!ts[1])
02190 goto err;
02191 ts[2] = '\0';
02192
02193 chr = strtoul (ts, &t, 16);
02194
02195 if (t != &ts[2])
02196 goto err;
02197 }
02198
02199 url[j++] = chr;
02200 }
02201
02202 ret = xmmsv_new_bin (url, j);
02203 free (url);
02204
02205 return ret;
02206
02207 err:
02208 free (url);
02209 return NULL;
02210 }
02211
02212 xmmsv_t *
02213 xmmsv_build_dict (const char *firstkey, ...)
02214 {
02215 va_list ap;
02216 const char *key;
02217 xmmsv_t *val, *res;
02218
02219 res = xmmsv_new_dict ();
02220 if (!res)
02221 return NULL;
02222
02223 va_start (ap, firstkey);
02224
02225 key = firstkey;
02226 do {
02227 val = va_arg (ap, xmmsv_t *);
02228
02229 if (!xmmsv_dict_set (res, key, val)) {
02230 xmmsv_unref (res);
02231 res = NULL;
02232 break;
02233 }
02234 xmmsv_unref (val);
02235 key = va_arg (ap, const char *);
02236 } while (key);
02237
02238 va_end (ap);
02239
02240 return res;
02241 }
02242
02243 xmmsv_t *
02244 xmmsv_build_list_va (xmmsv_t *first_entry, va_list ap)
02245 {
02246 xmmsv_t *val, *res;
02247
02248 res = xmmsv_new_list ();
02249 if (!res)
02250 return NULL;
02251
02252 val = first_entry;
02253
02254 while (val) {
02255 if (!xmmsv_list_append (res, val)) {
02256 xmmsv_unref (res);
02257 res = NULL;
02258 break;
02259 }
02260
02261 xmmsv_unref (val);
02262
02263 val = va_arg (ap, xmmsv_t *);
02264 }
02265
02266 return res;
02267 }
02268
02269 xmmsv_t *
02270 xmmsv_build_list (xmmsv_t *first_entry, ...)
02271 {
02272 va_list ap;
02273 xmmsv_t *res;
02274
02275 va_start (ap, first_entry);
02276 res = xmmsv_build_list_va (first_entry, ap);
02277 va_end (ap);
02278
02279 return res;
02280 }
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295 int
02296 xmmsv_dict_format (char *target, int len, const char *fmt, xmmsv_t *val)
02297 {
02298 const char *pos;
02299
02300 if (!target) {
02301 return 0;
02302 }
02303
02304 if (!fmt) {
02305 return 0;
02306 }
02307
02308 memset (target, 0, len);
02309
02310 pos = fmt;
02311 while (strlen (target) + 1 < len) {
02312 char *next_key, *key, *end;
02313 int keylen;
02314 xmmsv_dict_iter_t *it;
02315 xmmsv_t *v;
02316
02317 next_key = strstr (pos, "${");
02318 if (!next_key) {
02319 strncat (target, pos, len - strlen (target) - 1);
02320 break;
02321 }
02322
02323 strncat (target, pos, MIN (next_key - pos, len - strlen (target) - 1));
02324 keylen = strcspn (next_key + 2, "}");
02325 key = malloc (keylen + 1);
02326
02327 if (!key) {
02328 fprintf (stderr, "Unable to allocate %u bytes of memory, OOM?", keylen);
02329 break;
02330 }
02331
02332 memset (key, 0, keylen + 1);
02333 strncpy (key, next_key + 2, keylen);
02334
02335 xmmsv_get_dict_iter (val, &it);
02336
02337 if (strcmp (key, "seconds") == 0) {
02338 int duration;
02339
02340 if (xmmsv_dict_iter_find (it, "duration")) {
02341 xmmsv_dict_iter_pair (it, NULL, &v);
02342 xmmsv_get_int (v, &duration);
02343 } else {
02344 duration = 0;
02345 }
02346
02347 if (!duration) {
02348 strncat (target, "00", len - strlen (target) - 1);
02349 } else {
02350 char seconds[10];
02351
02352 duration += 500;
02353 snprintf (seconds, sizeof (seconds), "%02d", (duration/1000)%60);
02354 strncat (target, seconds, len - strlen (target) - 1);
02355 }
02356 } else if (strcmp (key, "minutes") == 0) {
02357 int duration;
02358
02359 if (xmmsv_dict_iter_find (it, "duration")) {
02360 xmmsv_dict_iter_pair (it, NULL, &v);
02361 xmmsv_get_int (v, &duration);
02362 } else {
02363 duration = 0;
02364 }
02365
02366 if (!duration) {
02367 strncat (target, "00", len - strlen (target) - 1);
02368 } else {
02369 char minutes[10];
02370
02371 duration += 500;
02372 snprintf (minutes, sizeof (minutes), "%02d", duration/60000);
02373 strncat (target, minutes, len - strlen (target) - 1);
02374 }
02375 } else {
02376 const char *result = NULL;
02377 char tmp[12];
02378
02379 if (xmmsv_dict_iter_find (it, key)) {
02380 xmmsv_dict_iter_pair (it, NULL, &v);
02381
02382 xmmsv_type_t type = xmmsv_get_type (v);
02383 if (type == XMMSV_TYPE_STRING) {
02384 xmmsv_get_string (v, &result);
02385 } else if (type == XMMSV_TYPE_UINT32) {
02386 uint32_t ui;
02387 xmmsv_get_uint (v, &ui);
02388 snprintf (tmp, 12, "%u", ui);
02389 result = tmp;
02390 } else if (type == XMMSV_TYPE_INT32) {
02391 int32_t i;
02392 xmmsv_get_int (v, &i);
02393 snprintf (tmp, 12, "%d", i);
02394 result = tmp;
02395 }
02396 }
02397
02398 if (result)
02399 strncat (target, result, len - strlen (target) - 1);
02400 }
02401
02402 free (key);
02403 end = strchr (next_key, '}');
02404
02405 if (!end) {
02406 break;
02407 }
02408
02409 pos = end + 1;
02410 }
02411
02412 return strlen (target);
02413 }
02414
02415 static int
02416 _xmmsv_utf8_charlen (unsigned char c)
02417 {
02418 if ((c & 0x80) == 0) {
02419 return 1;
02420 } else if ((c & 0x60) == 0x40) {
02421 return 2;
02422 } else if ((c & 0x70) == 0x60) {
02423 return 3;
02424 } else if ((c & 0x78) == 0x70) {
02425 return 4;
02426 }
02427 return 0;
02428 }
02429
02430
02431
02432
02433
02434
02435 int
02436 xmmsv_utf8_validate (const char *str)
02437 {
02438 int i = 0;
02439
02440 for (;;) {
02441 unsigned char c = str[i++];
02442 int l;
02443 if (!c) {
02444
02445 return 1;
02446 }
02447
02448 l = _xmmsv_utf8_charlen (c);
02449 if (l == 0)
02450 return 0;
02451 while (l-- > 1) {
02452 if ((str[i++] & 0xC0) != 0x80)
02453 return 0;
02454 }
02455 }
02456 }
02457
02458
02459
02460
02461
02462
02463
02464
02465 static int
02466 absolutify_and_validate_pos (int *pos, int size, int allow_append)
02467 {
02468 x_return_val_if_fail (size >= 0, 0);
02469
02470 if (*pos < 0) {
02471 if (-*pos > size)
02472 return 0;
02473 *pos = size + *pos;
02474 }
02475
02476 if (*pos > size)
02477 return 0;
02478
02479 if (!allow_append && *pos == size)
02480 return 0;
02481
02482 return 1;
02483 }
02484
02485 int
02486 xmmsv_dict_has_key (xmmsv_t *dictv, const char *key)
02487 {
02488 return xmmsv_dict_get (dictv, key, NULL);
02489 }