48 typedef struct xmmsv_bin_St {
53 struct xmmsv_list_St {
65 static int xmmsv_list_resize (
xmmsv_list_t *l,
int newsize);
68 static int _xmmsv_list_remove (
xmmsv_list_t *l,
int pos);
69 static int _xmmsv_list_move (
xmmsv_list_t *l,
int old_pos,
int new_pos);
76 struct xmmsv_list_iter_St {
107 static void xmmsv_free (
xmmsv_t *val);
108 static int absolutify_and_validate_pos (
int *pos,
int size,
int allow_append);
146 val->value.error = strdup (errstr);
164 val->value.int32 = i;
187 val->value.string = strdup (s);
229 val->value.bin.data =
x_malloc (len);
230 if (!val->value.bin.data) {
235 memcpy (val->value.bin.data, data, len);
236 val->value.bin.len = len;
253 val->value.list = xmmsv_list_new ();
254 val->value.list->parent_value = val;
271 val->value.dict = xmmsv_dict_new ();
304 x_api_error_if (val->ref < 1,
"with a freed value",);
348 free (val->value.error);
349 val->value.error = NULL;
352 free (val->value.string);
353 val->value.string = NULL;
357 val->value.coll = NULL;
360 free (val->value.bin.data);
361 val->value.bin.len = 0;
364 xmmsv_list_free (val->value.list);
365 val->value.list = NULL;
368 xmmsv_dict_free (val->value.dict);
369 val->value.dict = NULL;
386 x_api_error_if (!val,
"NULL value",
402 x_api_error_if (!val,
"NULL value", 0);
460 return val->value.error;
482 for (i = 0; (num >= 0 && i < num) || array[i]; i++) {
513 #define GEN_DICT_EXTRACTOR_FUNC(typename, type) \ 515 xmmsv_dict_entry_get_##typename (xmmsv_t *val, const char *key, \ 519 if (!xmmsv_dict_get (val, key, &v)) { \ 522 return xmmsv_get_##typename (v, r); \ 530 #define GEN_DICT_SET_FUNC(typename, type) \ 532 xmmsv_dict_set_##typename (xmmsv_t *dict, const char *key, type elem) \ 537 v = xmmsv_new_##typename (elem); \ 538 ret = xmmsv_dict_set (dict, key, v); \ 549 #define GEN_DICT_ITER_EXTRACTOR_FUNC(typename, type) \ 551 xmmsv_dict_iter_pair_##typename (xmmsv_dict_iter_t *it, \ 556 if (!xmmsv_dict_iter_pair (it, key, &v)) { \ 560 return xmmsv_get_##typename (v, r); \ 571 #define GEN_DICT_ITER_SET_FUNC(typename, type) \ 573 xmmsv_dict_iter_set_##typename (xmmsv_dict_iter_t *it, type elem) \ 578 v = xmmsv_new_##typename (elem); \ 579 ret = xmmsv_dict_iter_set (it, v); \ 590 #define GEN_LIST_EXTRACTOR_FUNC(typename, type) \ 592 xmmsv_list_get_##typename (xmmsv_t *val, int pos, type *r) \ 595 if (!xmmsv_list_get (val, pos, &v)) { \ 598 return xmmsv_get_##typename (v, r); \ 606 #define GEN_LIST_SET_FUNC(typename, type) \ 608 xmmsv_list_set_##typename (xmmsv_t *list, int pos, type elem) \ 613 v = xmmsv_new_##typename (elem); \ 614 ret = xmmsv_list_set (list, pos, v); \ 625 #define GEN_LIST_INSERT_FUNC(typename, type) \ 627 xmmsv_list_insert_##typename (xmmsv_t *list, int pos, type elem) \ 632 v = xmmsv_new_##typename (elem); \ 633 ret = xmmsv_list_insert (list, pos, v); \ 644 #define GEN_LIST_APPEND_FUNC(typename, type) \ 646 xmmsv_list_append_##typename (xmmsv_t *list, type elem) \ 651 v = xmmsv_new_##typename (elem); \ 652 ret = xmmsv_list_append (list, v); \ 663 #define GEN_LIST_ITER_EXTRACTOR_FUNC(typename, type) \ 665 xmmsv_list_iter_entry_##typename (xmmsv_list_iter_t *it, type *r) \ 668 if (!xmmsv_list_iter_entry (it, &v)) { \ 671 return xmmsv_get_##typename (v, r); \ 679 #define GEN_LIST_ITER_INSERT_FUNC(typename, type) \ 681 xmmsv_list_iter_insert_##typename (xmmsv_list_iter_t *it, type elem) \ 686 v = xmmsv_new_##typename (elem); \ 687 ret = xmmsv_list_iter_insert (it, v); \ 698 source_match_pattern (const
char *source, const
char *pattern)
701 int lpos = strlen (pattern) - 1;
703 if (strcasecmp (pattern, source) == 0) {
705 }
else if (lpos >= 0 && pattern[lpos] ==
'*' &&
706 (lpos == 0 || strncasecmp (source, pattern, lpos) == 0)) {
717 find_match_index (
const char *source,
const char **src_prefs)
721 for (i = 0; src_prefs[i]; i++) {
722 if (source_match_pattern (source, src_prefs[i])) {
746 xmmsv_t *dict, *source_dict, *value, *best_value;
748 const char *key, *source;
749 const char **local_prefs;
750 int match_index, best_index;
765 match_index = find_match_index (source, local_prefs);
767 if (match_index >= 0 && (best_index < 0 ||
768 match_index < best_index)) {
770 best_index = match_index;
802 *r = val->value.error;
821 *r = val->value.int32;
841 *r = val->value.int32;
861 *r = val->value.string;
881 *c = val->value.coll;
902 *r = val->value.bin.data;
903 *rlen = val->value.bin.len;
927 new_it = xmmsv_list_iter_new (val->value.list);
956 new_it = xmmsv_dict_iter_new (val->value.dict);
971 xmmsv_list_new (
void)
993 while (l->iterators) {
995 xmmsv_list_iter_free (it);
999 for (i = 0; i < l->size; i++) {
1012 newmem = realloc (l->list, newsize * sizeof (
xmmsv_t *));
1014 if (newsize != 0 && newmem == NULL) {
1020 l->allocated = newsize;
1031 if (!absolutify_and_validate_pos (&pos, l->size, 1)) {
1035 if (l->restricted) {
1040 if (l->size == l->allocated) {
1043 if (l->allocated > 0) {
1044 double_size = l->allocated << 1;
1048 success = xmmsv_list_resize (l, double_size);
1053 if (l->size > pos) {
1054 memmove (l->list + pos + 1, l->list + pos,
1055 (l->size - pos) * sizeof (
xmmsv_t *));
1062 for (n = l->iterators; n; n = n->
next) {
1064 if (it->position > pos) {
1075 return _xmmsv_list_insert (l, l->size, val);
1086 if (!absolutify_and_validate_pos (&pos, l->size, 0)) {
1095 if (pos < l->size) {
1096 memmove (l->list + pos, l->list + pos + 1,
1097 (l->size - pos) * sizeof (
xmmsv_t *));
1101 half_size = l->allocated >> 1;
1102 if (l->size <= half_size) {
1104 success = xmmsv_list_resize (l, half_size);
1109 for (n = l->iterators; n; n = n->
next) {
1111 if (it->position > pos) {
1120 _xmmsv_list_move (
xmmsv_list_t *l,
int old_pos,
int new_pos)
1126 if (!absolutify_and_validate_pos (&old_pos, l->size, 0)) {
1129 if (!absolutify_and_validate_pos (&new_pos, l->size, 0)) {
1133 v = l->list[old_pos];
1134 if (old_pos < new_pos) {
1135 memmove (l->list + old_pos, l->list + old_pos + 1,
1136 (new_pos - old_pos) * sizeof (
xmmsv_t *));
1137 l->list[new_pos] = v;
1140 for (n = l->iterators; n; n = n->
next) {
1142 if (it->position >= old_pos && it->position <= new_pos) {
1143 if (it->position == old_pos) {
1144 it->position = new_pos;
1151 memmove (l->list + new_pos + 1, l->list + new_pos,
1152 (old_pos - new_pos) * sizeof (
xmmsv_t *));
1153 l->list[new_pos] = v;
1156 for (n = l->iterators; n; n = n->
next) {
1158 if (it->position >= new_pos && it->position <= old_pos) {
1159 if (it->position == old_pos) {
1160 it->position = new_pos;
1179 for (i = 0; i < l->size; i++) {
1191 for (n = l->iterators; n; n = n->
next) {
1217 l = listv->value.list;
1220 if (!absolutify_and_validate_pos (&pos, l->size, 0)) {
1225 *val = l->list[pos];
1250 l = listv->value.list;
1252 if (!absolutify_and_validate_pos (&pos, l->size, 0)) {
1256 old_val = l->list[pos];
1280 return _xmmsv_list_insert (listv->value.list, pos, val);
1297 return _xmmsv_list_remove (listv->value.list, pos);
1320 return _xmmsv_list_move (listv->value.list, old_pos, new_pos);
1338 return _xmmsv_list_append (listv->value.list, val);
1353 _xmmsv_list_clear (listv->value.list);
1379 func (v, user_data);
1383 xmmsv_list_iter_free (it);
1400 return listv->value.list->size;
1422 xmmsv_list_iter_free (it);
1424 listv->value.list->restricted =
true;
1425 listv->value.list->restricttype = type;
1455 it->parent->iterators =
x_list_remove (it->parent->iterators, it);
1472 xmmsv_list_iter_free (it);
1492 *val = it->parent->list[it->position];
1506 return it && (it->position < it->parent->size) && (it->position >= 0);
1532 if (it->parent->size > 0) {
1533 it->position = it->parent->size - 1;
1535 it->position = it->parent->size;
1549 if (it->position < it->parent->size) {
1564 if (it->position >= 0) {
1583 if (!absolutify_and_validate_pos (&pos, it->parent->size, 1)) {
1602 return it->position;
1616 return it->parent->parent_value;
1633 return _xmmsv_list_insert (it->parent, it->position, val);
1648 return _xmmsv_list_remove (it->parent, it->position);
1653 struct xmmsv_dict_St {
1659 struct xmmsv_dict_iter_St {
1666 xmmsv_dict_new (
void)
1676 dict->flatlist = xmmsv_list_new ();
1687 while (dict->iterators) {
1689 xmmsv_dict_iter_free (it);
1692 xmmsv_list_free (dict->flatlist);
1728 xmmsv_dict_iter_free (it);
1774 it->lit->position--;
1781 xmmsv_dict_iter_free (it);
1813 xmmsv_dict_iter_free (it);
1830 _xmmsv_list_clear (dictv->value.dict->flatlist);
1858 func (key, v, user_data);
1862 xmmsv_dict_iter_free (it);
1879 return dictv->value.dict->flatlist->size / 2;
1893 it->lit = xmmsv_list_iter_new (d->flatlist);
1908 it->parent->iterators =
x_list_remove (it->parent->iterators, it);
1925 xmmsv_dict_iter_free (it);
1951 orig = it->lit->position;
1963 it->lit->position = orig;
2024 int s, dict_size, cmp, left, right;
2030 dict_size = it->parent->flatlist->size / 2;
2043 right = dict_size - 1;
2045 while (left <= right) {
2046 int mid = left + ((right - left) / 2);
2057 cmp = strcmp (k, key);
2101 orig = it->lit->position;
2108 it->lit->position = orig;
2177 unsigned char chr = ins[i++];
2181 }
else if (chr ==
'%') {
2193 chr = strtoul (ts, &t, 16);
2223 va_start (ap, firstkey);
2235 key = va_arg (ap,
const char *);
2275 va_start (ap, first_entry);
2308 memset (target, 0, len);
2311 while (strlen (target) + 1 < len) {
2312 char *next_key, *key, *end;
2317 next_key = strstr (pos,
"${");
2319 strncat (target, pos, len - strlen (target) - 1);
2323 strncat (target, pos,
MIN (next_key - pos, len - strlen (target) - 1));
2324 keylen = strcspn (next_key + 2,
"}");
2325 key = malloc (keylen + 1);
2328 fprintf (stderr,
"Unable to allocate %u bytes of memory, OOM?", keylen);
2332 memset (key, 0, keylen + 1);
2333 strncpy (key, next_key + 2, keylen);
2337 if (strcmp (key,
"seconds") == 0) {
2348 strncat (target,
"00", len - strlen (target) - 1);
2353 snprintf (seconds,
sizeof (seconds),
"%02d", (duration/1000)%60);
2354 strncat (target, seconds, len - strlen (target) - 1);
2356 }
else if (strcmp (key,
"minutes") == 0) {
2367 strncat (target,
"00", len - strlen (target) - 1);
2372 snprintf (minutes,
sizeof (minutes),
"%02d", duration/60000);
2373 strncat (target, minutes, len - strlen (target) - 1);
2376 const char *result = NULL;
2388 snprintf (tmp, 12,
"%u", ui);
2393 snprintf (tmp, 12,
"%d", i);
2399 strncat (target, result, len - strlen (target) - 1);
2403 end = strchr (next_key,
'}');
2412 return strlen (target);
2416 _xmmsv_utf8_charlen (
unsigned char c)
2418 if ((c & 0x80) == 0) {
2420 }
else if ((c & 0x60) == 0x40) {
2422 }
else if ((c & 0x70) == 0x60) {
2424 }
else if ((c & 0x78) == 0x70) {
2441 unsigned char c = str[i++];
2448 l = _xmmsv_utf8_charlen (c);
2452 if ((str[i++] & 0xC0) != 0x80)
2466 absolutify_and_validate_pos (
int *pos,
int size,
int allow_append)
2479 if (!allow_append && *pos == size)
xmmsv_t * xmmsv_new_dict(void)
Allocates a new dict xmmsv_t.
#define x_return_val_if_fail(expr, val)
int xmmsv_dict_iter_remove(xmmsv_dict_iter_t *it)
Remove the pair in the dict pointed at by the iterator.
int xmmsv_list_set(xmmsv_t *listv, int pos, xmmsv_t *val)
Set the element at the given position in the list xmmsv_t.
#define GEN_LIST_APPEND_FUNC(typename, type)
void xmmsv_unref(xmmsv_t *val)
Decreases the references for the xmmsv_t When the number of references reaches 0 it will be freed...
int xmmsv_dict_set(xmmsv_t *dictv, const char *key, xmmsv_t *val)
Insert an element under the given key in the dict xmmsv_t.
int xmmsv_list_insert(xmmsv_t *listv, int pos, xmmsv_t *val)
Insert an element at the given position in the list xmmsv_t.
void(* xmmsv_list_foreach_func)(xmmsv_t *value, void *user_data)
int xmmsv_list_get(xmmsv_t *listv, int pos, xmmsv_t **val)
Get the element at the given position in the list xmmsv_t.
int xmmsv_dict_iter_valid(xmmsv_dict_iter_t *it)
Check whether the iterator is valid and points to a valid pair.
int xmmsv_get_list_iter(const xmmsv_t *val, xmmsv_list_iter_t **it)
Retrieves a list iterator from a list xmmsv_t.
struct xmmsv_list_St xmmsv_list_t
xmmsv_t * xmmsv_new_error(const char *errstr)
Allocates a new error xmmsv_t.
int xmmsv_dict_remove(xmmsv_t *dictv, const char *key)
Remove the element corresponding to a given key in the dict xmmsv_t (if it exists).
int xmmsv_list_iter_insert(xmmsv_list_iter_t *it, xmmsv_t *val)
Insert an element in the list at the position pointed at by the iterator.
#define GEN_LIST_INSERT_FUNC(typename, type)
#define GEN_DICT_EXTRACTOR_FUNC(typename, type)
xmmsv_t * xmmsv_new_none(void)
Allocates a new empty xmmsv_t.
int xmmsv_list_iter_entry(xmmsv_list_iter_t *it, xmmsv_t **val)
Get the element currently pointed at by the iterator.
#define GEN_LIST_ITER_INSERT_FUNC(typename, type)
#define GEN_LIST_SET_FUNC(typename, type)
xmmsv_t * xmmsv_new_string(const char *s)
Allocates a new string xmmsv_t.
xmmsv_coll_t * xmmsv_coll_ref(xmmsv_coll_t *coll)
Increases the references for the xmmsv_coll_t.
void xmmsv_list_iter_first(xmmsv_list_iter_t *it)
Rewind the iterator to the start of the list.
#define XMMSV_TYPE_UINT32
int xmmsv_get_int(const xmmsv_t *val, int32_t *r)
Retrieves a signed integer from the value.
xmmsv_t * xmmsv_build_list(xmmsv_t *first_entry,...)
int xmmsv_list_append(xmmsv_t *listv, xmmsv_t *val)
Append an element to the end of the list xmmsv_t.
xmmsv_t * xmmsv_build_list_va(xmmsv_t *first_entry, va_list ap)
x_list_t * x_list_remove(x_list_t *list, const void *data)
void xmmsv_list_iter_last(xmmsv_list_iter_t *it)
Move the iterator to end of the list.
#define GEN_DICT_ITER_EXTRACTOR_FUNC(typename, type)
int xmmsv_dict_format(char *target, int len, const char *fmt, xmmsv_t *val)
This function will make a pretty string about the information in xmmsv dict.
#define GEN_DICT_ITER_SET_FUNC(typename, type)
int xmmsv_dict_get(xmmsv_t *dictv, const char *key, xmmsv_t **val)
Get the element corresponding to the given key in the dict xmmsv_t (if it exists).
int xmmsv_dict_foreach(xmmsv_t *dictv, xmmsv_dict_foreach_func func, void *user_data)
Apply a function to each key-element pair in the list.
int xmmsv_dict_has_key(xmmsv_t *dictv, const char *key)
void xmmsv_dict_iter_explicit_destroy(xmmsv_dict_iter_t *it)
Explicitly free dict iterator.
void xmmsv_list_iter_explicit_destroy(xmmsv_list_iter_t *it)
Explicitly free list iterator.
int xmmsv_get_coll(const xmmsv_t *val, xmmsv_coll_t **c)
Retrieves a collection from the value.
xmmsv_type_t xmmsv_dict_entry_get_type(xmmsv_t *val, const char *key)
Gets the type of a dict entry.
int xmmsv_dict_iter_pair(xmmsv_dict_iter_t *it, const char **key, xmmsv_t **val)
Get the key-element pair currently pointed at by the iterator.
xmmsv_t * xmmsv_new_coll(xmmsv_coll_t *c)
Allocates a new collection xmmsv_t.
int xmmsv_is_type(const xmmsv_t *val, xmmsv_type_t t)
Check if value is of specified type.
void(* xmmsv_dict_foreach_func)(const char *key, xmmsv_t *value, void *user_data)
struct xmmsv_coll_St xmmsv_coll_t
int xmmsv_list_get_size(xmmsv_t *listv)
Return the size of the list.
int xmmsv_list_iter_seek(xmmsv_list_iter_t *it, int pos)
Move the iterator to the n-th element in the list.
int xmmsv_dict_iter_set(xmmsv_dict_iter_t *it, xmmsv_t *val)
Replace the element of the pair currently pointed to by the iterator.
int xmmsv_list_iter_remove(xmmsv_list_iter_t *it)
Remove the element in the list at the position pointed at by the iterator.
void xmmsv_list_iter_next(xmmsv_list_iter_t *it)
Advance the iterator to the next element in the list.
xmmsv_t * xmmsv_propdict_to_dict(xmmsv_t *propdict, const char **src_prefs)
Helper function to transform a key-source-value dict-of-dict xmmsv_t (formerly a propdict) to a regul...
#define GEN_LIST_EXTRACTOR_FUNC(typename, type)
int xmmsv_list_clear(xmmsv_t *listv)
Empty the list from all its elements.
xmmsv_type_t xmmsv_get_type(const xmmsv_t *val)
Get the type of the value.
int xmmsv_list_remove(xmmsv_t *listv, int pos)
Remove the element at the given position from the list xmmsv_t.
xmmsv_t * xmmsv_make_stringlist(char *array[], int num)
Helper function to build a list xmmsv_t containing the strings from the input array.
int xmmsv_is_list(const xmmsv_t *val)
Check if the value stores a list.
xmmsv_t * xmmsv_new_int(int32_t i)
Allocates a new integer xmmsv_t.
int xmmsv_list_move(xmmsv_t *listv, int old_pos, int new_pos)
Move the element from position #old to position #new.
xmmsv_t * xmmsv_ref(xmmsv_t *val)
References the xmmsv_t.
int xmmsv_get_error(const xmmsv_t *val, const char **r)
Retrieves an error string describing the server error from the value.
void xmmsv_dict_iter_next(xmmsv_dict_iter_t *it)
Advance the iterator to the next pair in the dict.
#define GEN_LIST_ITER_EXTRACTOR_FUNC(typename, type)
xmmsv_t * xmmsv_list_iter_get_parent(const xmmsv_list_iter_t *it)
Return the parent xmmsv_t of an iterator.
#define x_new0(type, num)
const char * xmmsv_get_error_old(const xmmsv_t *val)
Legacy alias to retrieve the error string from an xmmsv_t.
int xmmsv_dict_iter_find(xmmsv_dict_iter_t *it, const char *key)
Move the iterator to the pair with the given key (if it exists) or move it to the position where the ...
xmmsv_t * xmmsv_decode_url(const xmmsv_t *inv)
Decode an URL-encoded string.
xmmsv_t * xmmsv_new_bin(unsigned char *data, unsigned int len)
Allocates a new binary data xmmsv_t.
int xmmsv_get_dict_iter(const xmmsv_t *val, xmmsv_dict_iter_t **it)
Retrieves a dict iterator from a dict xmmsv_t.
struct xmmsv_bin_St xmmsv_bin_t
int xmmsv_is_dict(const xmmsv_t *val)
Check if the value stores a dict.
int xmmsv_get_bin(const xmmsv_t *val, const unsigned char **r, unsigned int *rlen)
Retrieves binary data from the value.
xmmsv_t * xmmsv_new_list(void)
Allocates a new list xmmsv_t.
int xmmsv_list_iter_tell(const xmmsv_list_iter_t *it)
Tell the position of the iterator.
int xmmsv_get_uint(const xmmsv_t *val, uint32_t *r)
Retrieves a unsigned integer from the value.
#define x_return_if_fail(expr)
int xmmsv_get_string(const xmmsv_t *val, const char **r)
Retrieves a string from the value.
int xmmsv_is_error(const xmmsv_t *val)
Check if the value stores an error.
x_list_t * x_list_prepend(x_list_t *list, void *data)
#define GEN_DICT_SET_FUNC(typename, type)
int xmmsv_dict_get_size(xmmsv_t *dictv)
Return the size of the dict.
struct xmmsv_dict_St xmmsv_dict_t
int xmmsv_list_restrict_type(xmmsv_t *listv, xmmsv_type_t type)
void xmmsv_dict_iter_first(xmmsv_dict_iter_t *it)
Rewind the iterator to the start of the dict.
xmmsv_t * xmmsv_build_dict(const char *firstkey,...)
void xmmsv_list_iter_prev(xmmsv_list_iter_t *it)
Move the iterator to the previous element in the list.
int xmmsv_list_foreach(xmmsv_t *listv, xmmsv_list_foreach_func func, void *user_data)
Apply a function to each element in the list, in sequential order.
struct xmmsv_list_iter_St xmmsv_list_iter_t
const char * default_source_pref[]
int xmmsv_list_iter_valid(xmmsv_list_iter_t *it)
Check whether the iterator is valid and points to a valid element.
int xmmsv_utf8_validate(const char *str)
Check if a string is valid UTF-8.
void xmmsv_coll_unref(xmmsv_coll_t *coll)
Decreases the references for the xmmsv_coll_t When the number of references reaches 0 it will be free...
struct xmmsv_dict_iter_St xmmsv_dict_iter_t
int xmmsv_dict_clear(xmmsv_t *dictv)
Empty the dict of all its elements.