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