diff options
Diffstat (limited to 'xs.h')
| -rw-r--r-- | xs.h | 254 |
1 files changed, 151 insertions, 103 deletions
| @@ -21,8 +21,8 @@ typedef enum { | |||
| 21 | XSTYPE_FALSE = 0x15, /* Boolean */ | 21 | XSTYPE_FALSE = 0x15, /* Boolean */ |
| 22 | XSTYPE_LIST = 0x1d, /* Sequence of LITEMs up to EOM (with size) */ | 22 | XSTYPE_LIST = 0x1d, /* Sequence of LITEMs up to EOM (with size) */ |
| 23 | XSTYPE_LITEM = 0x1f, /* Element of a list (any type) */ | 23 | XSTYPE_LITEM = 0x1f, /* Element of a list (any type) */ |
| 24 | XSTYPE_DICT = 0x1c, /* Sequence of DITEMs up to EOM (with size) */ | 24 | XSTYPE_DICT = 0x1c, /* Sequence of KEYVALs up to EOM (with size) */ |
| 25 | XSTYPE_DITEM = 0x1e, /* Element of a dict (STRING key + any type) */ | 25 | XSTYPE_KEYVAL = 0x1e, /* key + value (STRING key + any type) */ |
| 26 | XSTYPE_EOM = 0x19, /* End of Multiple (LIST or DICT) */ | 26 | XSTYPE_EOM = 0x19, /* End of Multiple (LIST or DICT) */ |
| 27 | XSTYPE_DATA = 0x10 /* A block of anonymous data */ | 27 | XSTYPE_DATA = 0x10 /* A block of anonymous data */ |
| 28 | } xstype; | 28 | } xstype; |
| @@ -32,6 +32,7 @@ typedef enum { | |||
| 32 | typedef char xs_val; | 32 | typedef char xs_val; |
| 33 | typedef char xs_str; | 33 | typedef char xs_str; |
| 34 | typedef char xs_list; | 34 | typedef char xs_list; |
| 35 | typedef char xs_keyval; | ||
| 35 | typedef char xs_dict; | 36 | typedef char xs_dict; |
| 36 | typedef char xs_number; | 37 | typedef char xs_number; |
| 37 | typedef char xs_data; | 38 | typedef char xs_data; |
| @@ -45,6 +46,10 @@ typedef char xs_data; | |||
| 45 | /* not really all, just very much */ | 46 | /* not really all, just very much */ |
| 46 | #define XS_ALL 0xfffffff | 47 | #define XS_ALL 0xfffffff |
| 47 | 48 | ||
| 49 | #ifndef xs_countof | ||
| 50 | #define xs_countof(a) (sizeof((a)) / sizeof((*a))) | ||
| 51 | #endif | ||
| 52 | |||
| 48 | void *xs_free(void *ptr); | 53 | void *xs_free(void *ptr); |
| 49 | void *_xs_realloc(void *ptr, size_t size, const char *file, int line, const char *func); | 54 | void *_xs_realloc(void *ptr, size_t size, const char *file, int line, const char *func); |
| 50 | #define xs_realloc(ptr, size) _xs_realloc(ptr, size, __FILE__, __LINE__, __FUNCTION__) | 55 | #define xs_realloc(ptr, size) _xs_realloc(ptr, size, __FILE__, __LINE__, __FUNCTION__) |
| @@ -89,9 +94,10 @@ xs_list *xs_list_new(void); | |||
| 89 | xs_list *xs_list_append_m(xs_list *list, const char *mem, int dsz); | 94 | xs_list *xs_list_append_m(xs_list *list, const char *mem, int dsz); |
| 90 | xs_list *_xs_list_append(xs_list *list, const xs_val *vals[]); | 95 | xs_list *_xs_list_append(xs_list *list, const xs_val *vals[]); |
| 91 | #define xs_list_append(list, ...) _xs_list_append(list, (const xs_val *[]){ __VA_ARGS__, NULL }) | 96 | #define xs_list_append(list, ...) _xs_list_append(list, (const xs_val *[]){ __VA_ARGS__, NULL }) |
| 92 | int xs_list_iter(xs_list **list, xs_val **value); | 97 | int xs_list_iter(xs_list **list, const xs_val **value); |
| 98 | int xs_list_next(const xs_list *list, const xs_val **value, int *ctxt); | ||
| 93 | int xs_list_len(const xs_list *list); | 99 | int xs_list_len(const xs_list *list); |
| 94 | xs_val *xs_list_get(const xs_list *list, int num); | 100 | const xs_val *xs_list_get(const xs_list *list, int num); |
| 95 | xs_list *xs_list_del(xs_list *list, int num); | 101 | xs_list *xs_list_del(xs_list *list, int num); |
| 96 | xs_list *xs_list_insert(xs_list *list, int num, const xs_val *data); | 102 | xs_list *xs_list_insert(xs_list *list, int num, const xs_val *data); |
| 97 | xs_list *xs_list_set(xs_list *list, int num, const xs_val *data); | 103 | xs_list *xs_list_set(xs_list *list, int num, const xs_val *data); |
| @@ -104,17 +110,20 @@ xs_list *xs_split_n(const char *str, const char *sep, int times); | |||
| 104 | #define xs_split(str, sep) xs_split_n(str, sep, XS_ALL) | 110 | #define xs_split(str, sep) xs_split_n(str, sep, XS_ALL) |
| 105 | xs_list *xs_list_cat(xs_list *l1, const xs_list *l2); | 111 | xs_list *xs_list_cat(xs_list *l1, const xs_list *l2); |
| 106 | 112 | ||
| 113 | int xs_keyval_size(const xs_str *key, const xs_val *value); | ||
| 114 | xs_str *xs_keyval_key(const xs_keyval *keyval); | ||
| 115 | xs_val *xs_keyval_value(const xs_keyval *keyval); | ||
| 116 | xs_keyval *xs_keyval_make(xs_keyval *keyval, const xs_str *key, const xs_val *value); | ||
| 117 | |||
| 107 | xs_dict *xs_dict_new(void); | 118 | xs_dict *xs_dict_new(void); |
| 108 | xs_dict *xs_dict_append_m(xs_dict *dict, const xs_str *key, const xs_val *mem, int dsz); | 119 | xs_dict *xs_dict_append(xs_dict *dict, const xs_str *key, const xs_val *value); |
| 109 | #define xs_dict_append(dict, key, data) xs_dict_append_m(dict, key, data, xs_size(data)) | 120 | xs_dict *xs_dict_prepend(xs_dict *dict, const xs_str *key, const xs_val *value); |
| 110 | xs_dict *xs_dict_prepend_m(xs_dict *dict, const xs_str *key, const xs_val *mem, int dsz); | 121 | int xs_dict_next(const xs_dict *dict, const xs_str **key, const xs_val **value, int *ctxt); |
| 111 | #define xs_dict_prepend(dict, key, data) xs_dict_prepend_m(dict, key, data, xs_size(data)) | 122 | const xs_val *xs_dict_get_def(const xs_dict *dict, const xs_str *key, const xs_val *def); |
| 112 | int xs_dict_iter(xs_dict **dict, xs_str **key, xs_val **value); | ||
| 113 | int xs_dict_next(const xs_dict *dict, xs_str **key, xs_val **value, int *ctxt); | ||
| 114 | xs_val *xs_dict_get_def(const xs_dict *dict, const xs_str *key, const xs_val *def); | ||
| 115 | #define xs_dict_get(dict, key) xs_dict_get_def(dict, key, NULL) | 123 | #define xs_dict_get(dict, key) xs_dict_get_def(dict, key, NULL) |
| 116 | xs_dict *xs_dict_del(xs_dict *dict, const xs_str *key); | 124 | xs_dict *xs_dict_del(xs_dict *dict, const xs_str *key); |
| 117 | xs_dict *xs_dict_set(xs_dict *dict, const xs_str *key, const xs_val *data); | 125 | xs_dict *xs_dict_set(xs_dict *dict, const xs_str *key, const xs_val *data); |
| 126 | xs_dict *xs_dict_gc(xs_dict *dict); | ||
| 118 | 127 | ||
| 119 | xs_val *xs_val_new(xstype t); | 128 | xs_val *xs_val_new(xstype t); |
| 120 | xs_number *xs_number_new(double f); | 129 | xs_number *xs_number_new(double f); |
| @@ -242,7 +251,7 @@ xstype xs_type(const xs_val *data) | |||
| 242 | case XSTYPE_LIST: | 251 | case XSTYPE_LIST: |
| 243 | case XSTYPE_LITEM: | 252 | case XSTYPE_LITEM: |
| 244 | case XSTYPE_DICT: | 253 | case XSTYPE_DICT: |
| 245 | case XSTYPE_DITEM: | 254 | case XSTYPE_KEYVAL: |
| 246 | case XSTYPE_NUMBER: | 255 | case XSTYPE_NUMBER: |
| 247 | case XSTYPE_EOM: | 256 | case XSTYPE_EOM: |
| 248 | case XSTYPE_DATA: | 257 | case XSTYPE_DATA: |
| @@ -260,7 +269,7 @@ xstype xs_type(const xs_val *data) | |||
| 260 | void _xs_put_size(xs_val *ptr, int i) | 269 | void _xs_put_size(xs_val *ptr, int i) |
| 261 | /* must match _XS_TYPE_SIZE */ | 270 | /* must match _XS_TYPE_SIZE */ |
| 262 | { | 271 | { |
| 263 | memcpy(ptr, &i, sizeof(i)); | 272 | memcpy(ptr + 1, &i, sizeof(i)); |
| 264 | } | 273 | } |
| 265 | 274 | ||
| 266 | 275 | ||
| @@ -294,7 +303,7 @@ int xs_size(const xs_val *data) | |||
| 294 | 303 | ||
| 295 | break; | 304 | break; |
| 296 | 305 | ||
| 297 | case XSTYPE_DITEM: | 306 | case XSTYPE_KEYVAL: |
| 298 | /* calculate the size of the key and the value */ | 307 | /* calculate the size of the key and the value */ |
| 299 | p = data + 1; | 308 | p = data + 1; |
| 300 | p += xs_size(p); | 309 | p += xs_size(p); |
| @@ -378,7 +387,7 @@ xs_val *xs_expand(xs_val *data, int offset, int size) | |||
| 378 | if (xs_type(data) == XSTYPE_LIST || | 387 | if (xs_type(data) == XSTYPE_LIST || |
| 379 | xs_type(data) == XSTYPE_DICT || | 388 | xs_type(data) == XSTYPE_DICT || |
| 380 | xs_type(data) == XSTYPE_DATA) | 389 | xs_type(data) == XSTYPE_DATA) |
| 381 | _xs_put_size(data + 1, sz); | 390 | _xs_put_size(data, sz); |
| 382 | 391 | ||
| 383 | return data; | 392 | return data; |
| 384 | } | 393 | } |
| @@ -403,7 +412,7 @@ xs_val *xs_collapse(xs_val *data, int offset, int size) | |||
| 403 | if (xs_type(data) == XSTYPE_LIST || | 412 | if (xs_type(data) == XSTYPE_LIST || |
| 404 | xs_type(data) == XSTYPE_DICT || | 413 | xs_type(data) == XSTYPE_DICT || |
| 405 | xs_type(data) == XSTYPE_DATA) | 414 | xs_type(data) == XSTYPE_DATA) |
| 406 | _xs_put_size(data + 1, sz); | 415 | _xs_put_size(data, sz); |
| 407 | 416 | ||
| 408 | return xs_realloc(data, _xs_blk_size(sz)); | 417 | return xs_realloc(data, _xs_blk_size(sz)); |
| 409 | } | 418 | } |
| @@ -664,10 +673,10 @@ xs_list *xs_list_new(void) | |||
| 664 | { | 673 | { |
| 665 | int sz = 1 + _XS_TYPE_SIZE + 1; | 674 | int sz = 1 + _XS_TYPE_SIZE + 1; |
| 666 | xs_list *l = xs_realloc(NULL, sz); | 675 | xs_list *l = xs_realloc(NULL, sz); |
| 667 | memset(l, '\0', sz); | 676 | memset(l, XSTYPE_EOM, sz); |
| 668 | 677 | ||
| 669 | l[0] = XSTYPE_LIST; | 678 | l[0] = XSTYPE_LIST; |
| 670 | _xs_put_size(&l[1], sz); | 679 | _xs_put_size(l, sz); |
| 671 | 680 | ||
| 672 | return l; | 681 | return l; |
| 673 | } | 682 | } |
| @@ -717,7 +726,7 @@ xs_list *_xs_list_append(xs_list *list, const xs_val *vals[]) | |||
| 717 | } | 726 | } |
| 718 | 727 | ||
| 719 | 728 | ||
| 720 | int xs_list_iter(xs_list **list, xs_val **value) | 729 | int xs_list_iter(xs_list **list, const xs_val **value) |
| 721 | /* iterates a list value */ | 730 | /* iterates a list value */ |
| 722 | { | 731 | { |
| 723 | int goon = 1; | 732 | int goon = 1; |
| @@ -748,23 +757,58 @@ int xs_list_iter(xs_list **list, xs_val **value) | |||
| 748 | } | 757 | } |
| 749 | 758 | ||
| 750 | 759 | ||
| 760 | int xs_list_next(const xs_list *list, const xs_val **value, int *ctxt) | ||
| 761 | /* iterates a list, with context */ | ||
| 762 | { | ||
| 763 | if (xs_type(list) != XSTYPE_LIST) | ||
| 764 | return 0; | ||
| 765 | |||
| 766 | int goon = 1; | ||
| 767 | |||
| 768 | const char *p = list; | ||
| 769 | |||
| 770 | /* skip the start of the list */ | ||
| 771 | if (*ctxt == 0) | ||
| 772 | *ctxt = 1 + _XS_TYPE_SIZE; | ||
| 773 | |||
| 774 | p += *ctxt; | ||
| 775 | |||
| 776 | /* an element? */ | ||
| 777 | if (xs_type(p) == XSTYPE_LITEM) { | ||
| 778 | p++; | ||
| 779 | |||
| 780 | *value = p; | ||
| 781 | |||
| 782 | p += xs_size(*value); | ||
| 783 | } | ||
| 784 | else { | ||
| 785 | /* end of list */ | ||
| 786 | goon = 0; | ||
| 787 | } | ||
| 788 | |||
| 789 | /* update the context */ | ||
| 790 | *ctxt = p - list; | ||
| 791 | |||
| 792 | return goon; | ||
| 793 | } | ||
| 794 | |||
| 795 | |||
| 751 | int xs_list_len(const xs_list *list) | 796 | int xs_list_len(const xs_list *list) |
| 752 | /* returns the number of elements in the list */ | 797 | /* returns the number of elements in the list */ |
| 753 | { | 798 | { |
| 754 | XS_ASSERT_TYPE_NULL(list, XSTYPE_LIST); | 799 | XS_ASSERT_TYPE_NULL(list, XSTYPE_LIST); |
| 755 | 800 | ||
| 756 | int c = 0; | 801 | int c = 0, ct = 0; |
| 757 | xs_list *p = (xs_list *)list; | 802 | const xs_val *v; |
| 758 | xs_val *v; | ||
| 759 | 803 | ||
| 760 | while (xs_list_iter(&p, &v)) | 804 | while (xs_list_next(list, &v, &ct)) |
| 761 | c++; | 805 | c++; |
| 762 | 806 | ||
| 763 | return c; | 807 | return c; |
| 764 | } | 808 | } |
| 765 | 809 | ||
| 766 | 810 | ||
| 767 | xs_val *xs_list_get(const xs_list *list, int num) | 811 | const xs_val *xs_list_get(const xs_list *list, int num) |
| 768 | /* returns the element #num */ | 812 | /* returns the element #num */ |
| 769 | { | 813 | { |
| 770 | XS_ASSERT_TYPE(list, XSTYPE_LIST); | 814 | XS_ASSERT_TYPE(list, XSTYPE_LIST); |
| @@ -772,11 +816,10 @@ xs_val *xs_list_get(const xs_list *list, int num) | |||
| 772 | if (num < 0) | 816 | if (num < 0) |
| 773 | num = xs_list_len(list) + num; | 817 | num = xs_list_len(list) + num; |
| 774 | 818 | ||
| 775 | int c = 0; | 819 | int c = 0, ct = 0; |
| 776 | xs_list *p = (xs_list *)list; | 820 | const xs_val *v; |
| 777 | xs_val *v; | ||
| 778 | 821 | ||
| 779 | while (xs_list_iter(&p, &v)) { | 822 | while (xs_list_next(list, &v, &ct)) { |
| 780 | if (c == num) | 823 | if (c == num) |
| 781 | return v; | 824 | return v; |
| 782 | 825 | ||
| @@ -792,7 +835,7 @@ xs_list *xs_list_del(xs_list *list, int num) | |||
| 792 | { | 835 | { |
| 793 | XS_ASSERT_TYPE(list, XSTYPE_LIST); | 836 | XS_ASSERT_TYPE(list, XSTYPE_LIST); |
| 794 | 837 | ||
| 795 | xs_val *v; | 838 | const xs_val *v; |
| 796 | 839 | ||
| 797 | if ((v = xs_list_get(list, num)) != NULL) | 840 | if ((v = xs_list_get(list, num)) != NULL) |
| 798 | list = xs_collapse(list, v - 1 - list, xs_size(v - 1)); | 841 | list = xs_collapse(list, v - 1 - list, xs_size(v - 1)); |
| @@ -806,7 +849,7 @@ xs_list *xs_list_insert(xs_list *list, int num, const xs_val *data) | |||
| 806 | { | 849 | { |
| 807 | XS_ASSERT_TYPE(list, XSTYPE_LIST); | 850 | XS_ASSERT_TYPE(list, XSTYPE_LIST); |
| 808 | 851 | ||
| 809 | xs_val *v; | 852 | const xs_val *v; |
| 810 | int offset; | 853 | int offset; |
| 811 | 854 | ||
| 812 | if ((v = xs_list_get(list, num)) != NULL) | 855 | if ((v = xs_list_get(list, num)) != NULL) |
| @@ -835,16 +878,16 @@ xs_list *xs_list_dequeue(xs_list *list, xs_val **data, int last) | |||
| 835 | { | 878 | { |
| 836 | XS_ASSERT_TYPE(list, XSTYPE_LIST); | 879 | XS_ASSERT_TYPE(list, XSTYPE_LIST); |
| 837 | 880 | ||
| 838 | xs_list *p = list; | 881 | int ct = 0; |
| 839 | xs_val *v = NULL; | 882 | const xs_val *v = NULL; |
| 840 | 883 | ||
| 841 | if (!last) { | 884 | if (!last) { |
| 842 | /* get the first */ | 885 | /* get the first */ |
| 843 | xs_list_iter(&p, &v); | 886 | xs_list_next(list, &v, &ct); |
| 844 | } | 887 | } |
| 845 | else { | 888 | else { |
| 846 | /* iterate to the end */ | 889 | /* iterate to the end */ |
| 847 | while (xs_list_iter(&p, &v)); | 890 | while (xs_list_next(list, &v, &ct)); |
| 848 | } | 891 | } |
| 849 | 892 | ||
| 850 | if (v != NULL) { | 893 | if (v != NULL) { |
| @@ -864,11 +907,11 @@ int xs_list_in(const xs_list *list, const xs_val *val) | |||
| 864 | XS_ASSERT_TYPE_NULL(list, XSTYPE_LIST); | 907 | XS_ASSERT_TYPE_NULL(list, XSTYPE_LIST); |
| 865 | 908 | ||
| 866 | int n = 0; | 909 | int n = 0; |
| 867 | xs_list *p = (xs_list *)list; | 910 | int ct = 0; |
| 868 | xs_val *v; | 911 | const xs_val *v; |
| 869 | int sz = xs_size(val); | 912 | int sz = xs_size(val); |
| 870 | 913 | ||
| 871 | while (xs_list_iter(&p, &v)) { | 914 | while (xs_list_next(list, &v, &ct)) { |
| 872 | if (sz == xs_size(v) && memcmp(val, v, sz) == 0) | 915 | if (sz == xs_size(v) && memcmp(val, v, sz) == 0) |
| 873 | return n; | 916 | return n; |
| 874 | 917 | ||
| @@ -885,13 +928,13 @@ xs_str *xs_join(const xs_list *list, const char *sep) | |||
| 885 | XS_ASSERT_TYPE(list, XSTYPE_LIST); | 928 | XS_ASSERT_TYPE(list, XSTYPE_LIST); |
| 886 | 929 | ||
| 887 | xs_str *s = NULL; | 930 | xs_str *s = NULL; |
| 888 | xs_list *p = (xs_list *)list; | 931 | const xs_val *v; |
| 889 | xs_val *v; | ||
| 890 | int c = 0; | 932 | int c = 0; |
| 933 | int ct = 0; | ||
| 891 | int offset = 0; | 934 | int offset = 0; |
| 892 | int ssz = strlen(sep); | 935 | int ssz = strlen(sep); |
| 893 | 936 | ||
| 894 | while (xs_list_iter(&p, &v)) { | 937 | while (xs_list_next(list, &v, &ct)) { |
| 895 | /* refuse to join non-string values */ | 938 | /* refuse to join non-string values */ |
| 896 | if (xs_type(v) == XSTYPE_STRING) { | 939 | if (xs_type(v) == XSTYPE_STRING) { |
| 897 | int sz; | 940 | int sz; |
| @@ -961,6 +1004,40 @@ xs_list *xs_list_cat(xs_list *l1, const xs_list *l2) | |||
| 961 | } | 1004 | } |
| 962 | 1005 | ||
| 963 | 1006 | ||
| 1007 | /** keyvals **/ | ||
| 1008 | |||
| 1009 | int xs_keyval_size(const xs_str *key, const xs_val *value) | ||
| 1010 | /* returns the needed size for a keyval */ | ||
| 1011 | { | ||
| 1012 | return 1 + xs_size(key) + xs_size(value); | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | |||
| 1016 | xs_str *xs_keyval_key(const xs_keyval *keyval) | ||
| 1017 | /* returns a pointer to the key of the keyval */ | ||
| 1018 | { | ||
| 1019 | return (xs_str *)&keyval[1]; | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | |||
| 1023 | xs_val *xs_keyval_value(const xs_keyval *keyval) | ||
| 1024 | /* returns a pointer to the value of the keyval */ | ||
| 1025 | { | ||
| 1026 | return (xs_val *)&keyval[1 + xs_size(xs_keyval_key(keyval))]; | ||
| 1027 | } | ||
| 1028 | |||
| 1029 | |||
| 1030 | xs_keyval *xs_keyval_make(xs_keyval *keyval, const xs_str *key, const xs_val *value) | ||
| 1031 | /* builds a keyval into mem (should have enough size) */ | ||
| 1032 | { | ||
| 1033 | keyval[0] = XSTYPE_KEYVAL; | ||
| 1034 | memcpy(xs_keyval_key(keyval), key, xs_size(key)); | ||
| 1035 | memcpy(xs_keyval_value(keyval), value, xs_size(value)); | ||
| 1036 | |||
| 1037 | return keyval; | ||
| 1038 | } | ||
| 1039 | |||
| 1040 | |||
| 964 | /** dicts **/ | 1041 | /** dicts **/ |
| 965 | 1042 | ||
| 966 | xs_dict *xs_dict_new(void) | 1043 | xs_dict *xs_dict_new(void) |
| @@ -968,87 +1045,47 @@ xs_dict *xs_dict_new(void) | |||
| 968 | { | 1045 | { |
| 969 | int sz = 1 + _XS_TYPE_SIZE + 1; | 1046 | int sz = 1 + _XS_TYPE_SIZE + 1; |
| 970 | xs_dict *d = xs_realloc(NULL, sz); | 1047 | xs_dict *d = xs_realloc(NULL, sz); |
| 971 | memset(d, '\0', sz); | 1048 | memset(d, XSTYPE_EOM, sz); |
| 972 | 1049 | ||
| 973 | d[0] = XSTYPE_DICT; | 1050 | d[0] = XSTYPE_DICT; |
| 974 | _xs_put_size(&d[1], sz); | 1051 | _xs_put_size(d, sz); |
| 975 | 1052 | ||
| 976 | return d; | 1053 | return d; |
| 977 | } | 1054 | } |
| 978 | 1055 | ||
| 979 | 1056 | ||
| 980 | xs_dict *_xs_dict_write_ditem(xs_dict *dict, int offset, const xs_str *key, | 1057 | xs_dict *_xs_dict_write_keyval(xs_dict *dict, int offset, const xs_str *key, const xs_val *value) |
| 981 | const xs_val *data, int dsz) | 1058 | /* adds a new keyval to the dict */ |
| 982 | /* inserts a memory block into the dict */ | ||
| 983 | { | 1059 | { |
| 984 | XS_ASSERT_TYPE(dict, XSTYPE_DICT); | 1060 | XS_ASSERT_TYPE(dict, XSTYPE_DICT); |
| 985 | XS_ASSERT_TYPE(key, XSTYPE_STRING); | 1061 | XS_ASSERT_TYPE(key, XSTYPE_STRING); |
| 986 | 1062 | ||
| 987 | if (data == NULL) { | 1063 | if (value == NULL) |
| 988 | data = xs_stock(XSTYPE_NULL); | 1064 | value = xs_stock(XSTYPE_NULL); |
| 989 | dsz = xs_size(data); | ||
| 990 | } | ||
| 991 | |||
| 992 | int ksz = xs_size(key); | ||
| 993 | 1065 | ||
| 994 | dict = xs_expand(dict, offset, 1 + ksz + dsz); | 1066 | dict = xs_expand(dict, offset, xs_keyval_size(key, value)); |
| 995 | 1067 | ||
| 996 | dict[offset] = XSTYPE_DITEM; | 1068 | xs_keyval_make(&dict[offset], key, value); |
| 997 | memcpy(&dict[offset + 1], key, ksz); | ||
| 998 | memcpy(&dict[offset + 1 + ksz], data, dsz); | ||
| 999 | 1069 | ||
| 1000 | return dict; | 1070 | return dict; |
| 1001 | } | 1071 | } |
| 1002 | 1072 | ||
| 1003 | 1073 | ||
| 1004 | xs_dict *xs_dict_append_m(xs_dict *dict, const xs_str *key, const xs_val *mem, int dsz) | 1074 | xs_dict *xs_dict_append(xs_dict *dict, const xs_str *key, const xs_val *value) |
| 1005 | /* appends a memory block to the dict */ | 1075 | /* appends a memory block to the dict */ |
| 1006 | { | 1076 | { |
| 1007 | return _xs_dict_write_ditem(dict, xs_size(dict) - 1, key, mem, dsz); | 1077 | return _xs_dict_write_keyval(dict, xs_size(dict) - 1, key, value); |
| 1008 | } | 1078 | } |
| 1009 | 1079 | ||
| 1010 | 1080 | ||
| 1011 | xs_dict *xs_dict_prepend_m(xs_dict *dict, const xs_str *key, const xs_val *mem, int dsz) | 1081 | xs_dict *xs_dict_prepend(xs_dict *dict, const xs_str *key, const xs_val *value) |
| 1012 | /* prepends a memory block to the dict */ | 1082 | /* prepends a memory block to the dict */ |
| 1013 | { | 1083 | { |
| 1014 | return _xs_dict_write_ditem(dict, 4, key, mem, dsz); | 1084 | return _xs_dict_write_keyval(dict, 1 + _XS_TYPE_SIZE, key, value); |
| 1015 | } | ||
| 1016 | |||
| 1017 | |||
| 1018 | int xs_dict_iter(xs_dict **dict, xs_str **key, xs_val **value) | ||
| 1019 | /* iterates a dict value */ | ||
| 1020 | { | ||
| 1021 | int goon = 1; | ||
| 1022 | |||
| 1023 | xs_val *p = *dict; | ||
| 1024 | |||
| 1025 | /* skip the start of the list */ | ||
| 1026 | if (xs_type(p) == XSTYPE_DICT) | ||
| 1027 | p += 1 + _XS_TYPE_SIZE; | ||
| 1028 | |||
| 1029 | /* an element? */ | ||
| 1030 | if (xs_type(p) == XSTYPE_DITEM) { | ||
| 1031 | p++; | ||
| 1032 | |||
| 1033 | *key = p; | ||
| 1034 | p += xs_size(*key); | ||
| 1035 | |||
| 1036 | *value = p; | ||
| 1037 | p += xs_size(*value); | ||
| 1038 | } | ||
| 1039 | else { | ||
| 1040 | /* end of list */ | ||
| 1041 | goon = 0; | ||
| 1042 | } | ||
| 1043 | |||
| 1044 | /* store back the pointer */ | ||
| 1045 | *dict = p; | ||
| 1046 | |||
| 1047 | return goon; | ||
| 1048 | } | 1085 | } |
| 1049 | 1086 | ||
| 1050 | 1087 | ||
| 1051 | int xs_dict_next(const xs_dict *dict, xs_str **key, xs_val **value, int *ctxt) | 1088 | int xs_dict_next(const xs_dict *dict, const xs_str **key, const xs_val **value, int *ctxt) |
| 1052 | /* iterates a dict, with context */ | 1089 | /* iterates a dict, with context */ |
| 1053 | { | 1090 | { |
| 1054 | if (xs_type(dict) != XSTYPE_DICT) | 1091 | if (xs_type(dict) != XSTYPE_DICT) |
| @@ -1065,7 +1102,7 @@ int xs_dict_next(const xs_dict *dict, xs_str **key, xs_val **value, int *ctxt) | |||
| 1065 | p += *ctxt; | 1102 | p += *ctxt; |
| 1066 | 1103 | ||
| 1067 | /* an element? */ | 1104 | /* an element? */ |
| 1068 | if (xs_type(p) == XSTYPE_DITEM) { | 1105 | if (xs_type(p) == XSTYPE_KEYVAL) { |
| 1069 | p++; | 1106 | p++; |
| 1070 | 1107 | ||
| 1071 | *key = p; | 1108 | *key = p; |
| @@ -1086,14 +1123,14 @@ int xs_dict_next(const xs_dict *dict, xs_str **key, xs_val **value, int *ctxt) | |||
| 1086 | } | 1123 | } |
| 1087 | 1124 | ||
| 1088 | 1125 | ||
| 1089 | xs_val *xs_dict_get_def(const xs_dict *dict, const xs_str *key, const xs_val *def) | 1126 | const xs_val *xs_dict_get_def(const xs_dict *dict, const xs_str *key, const xs_val *def) |
| 1090 | /* returns the value directed by key, or the default value */ | 1127 | /* returns the value directed by key, or the default value */ |
| 1091 | { | 1128 | { |
| 1092 | XS_ASSERT_TYPE(dict, XSTYPE_DICT); | 1129 | XS_ASSERT_TYPE(dict, XSTYPE_DICT); |
| 1093 | XS_ASSERT_TYPE(key, XSTYPE_STRING); | 1130 | XS_ASSERT_TYPE(key, XSTYPE_STRING); |
| 1094 | 1131 | ||
| 1095 | xs_str *k; | 1132 | const xs_str *k; |
| 1096 | xs_val *v; | 1133 | const xs_val *v; |
| 1097 | int c = 0; | 1134 | int c = 0; |
| 1098 | 1135 | ||
| 1099 | while (xs_dict_next(dict, &k, &v, &c)) { | 1136 | while (xs_dict_next(dict, &k, &v, &c)) { |
| @@ -1111,14 +1148,14 @@ xs_dict *xs_dict_del(xs_dict *dict, const xs_str *key) | |||
| 1111 | XS_ASSERT_TYPE(dict, XSTYPE_DICT); | 1148 | XS_ASSERT_TYPE(dict, XSTYPE_DICT); |
| 1112 | XS_ASSERT_TYPE(key, XSTYPE_STRING); | 1149 | XS_ASSERT_TYPE(key, XSTYPE_STRING); |
| 1113 | 1150 | ||
| 1114 | xs_str *k; | 1151 | const xs_str *k; |
| 1115 | xs_val *v; | 1152 | const xs_val *v; |
| 1116 | int c = 0; | 1153 | int c = 0; |
| 1117 | 1154 | ||
| 1118 | while (xs_dict_next(dict, &k, &v, &c)) { | 1155 | while (xs_dict_next(dict, &k, &v, &c)) { |
| 1119 | if (strcmp(k, key) == 0) { | 1156 | if (strcmp(k, key) == 0) { |
| 1120 | /* the address of the item is just behind the key */ | 1157 | /* the address of the item is just behind the key */ |
| 1121 | char *i = k - 1; | 1158 | char *i = (char *)k - 1; |
| 1122 | 1159 | ||
| 1123 | dict = xs_collapse(dict, i - dict, xs_size(i)); | 1160 | dict = xs_collapse(dict, i - dict, xs_size(i)); |
| 1124 | break; | 1161 | break; |
| @@ -1145,6 +1182,14 @@ xs_dict *xs_dict_set(xs_dict *dict, const xs_str *key, const xs_val *data) | |||
| 1145 | } | 1182 | } |
| 1146 | 1183 | ||
| 1147 | 1184 | ||
| 1185 | xs_dict *xs_dict_gc(xs_dict *dict) | ||
| 1186 | /* collects garbage (leaked values) inside a dict */ | ||
| 1187 | { | ||
| 1188 | /* this kind of dicts does not get garbage */ | ||
| 1189 | return dict; | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | |||
| 1148 | /** other values **/ | 1193 | /** other values **/ |
| 1149 | 1194 | ||
| 1150 | xs_val *xs_val_new(xstype t) | 1195 | xs_val *xs_val_new(xstype t) |
| @@ -1195,8 +1240,11 @@ double xs_number_get(const xs_number *v) | |||
| 1195 | { | 1240 | { |
| 1196 | double f = 0.0; | 1241 | double f = 0.0; |
| 1197 | 1242 | ||
| 1198 | if (v != NULL && v[0] == XSTYPE_NUMBER) | 1243 | if (xs_type(v) == XSTYPE_NUMBER) |
| 1199 | f = atof(&v[1]); | 1244 | f = atof(&v[1]); |
| 1245 | else | ||
| 1246 | if (xs_type(v) == XSTYPE_STRING) | ||
| 1247 | f = atof(v); | ||
| 1200 | 1248 | ||
| 1201 | return f; | 1249 | return f; |
| 1202 | } | 1250 | } |
| @@ -1207,7 +1255,7 @@ const char *xs_number_str(const xs_number *v) | |||
| 1207 | { | 1255 | { |
| 1208 | const char *p = NULL; | 1256 | const char *p = NULL; |
| 1209 | 1257 | ||
| 1210 | if (v != NULL && v[0] == XSTYPE_NUMBER) | 1258 | if (xs_type(v) == XSTYPE_NUMBER) |
| 1211 | p = &v[1]; | 1259 | p = &v[1]; |
| 1212 | 1260 | ||
| 1213 | return p; | 1261 | return p; |
| @@ -1227,7 +1275,7 @@ xs_data *xs_data_new(const void *data, int size) | |||
| 1227 | v = xs_realloc(NULL, _xs_blk_size(total_size)); | 1275 | v = xs_realloc(NULL, _xs_blk_size(total_size)); |
| 1228 | v[0] = XSTYPE_DATA; | 1276 | v[0] = XSTYPE_DATA; |
| 1229 | 1277 | ||
| 1230 | _xs_put_size(v + 1, total_size); | 1278 | _xs_put_size(v, total_size); |
| 1231 | 1279 | ||
| 1232 | memcpy(&v[1 + _XS_TYPE_SIZE], data, size); | 1280 | memcpy(&v[1 + _XS_TYPE_SIZE], data, size); |
| 1233 | 1281 | ||