diff options
Diffstat (limited to 'xs.h')
| -rw-r--r-- | xs.h | 26 |
1 files changed, 18 insertions, 8 deletions
| @@ -1,4 +1,4 @@ | |||
| 1 | /* copyright (c) 2022 - 2024 grunfink et al. / MIT license */ | 1 | /* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ |
| 2 | 2 | ||
| 3 | #ifndef _XS_H | 3 | #ifndef _XS_H |
| 4 | 4 | ||
| @@ -157,6 +157,9 @@ unsigned int xs_hash_func(const char *data, int size); | |||
| 157 | #define xs_is_true(v) (xs_type((v)) == XSTYPE_TRUE) | 157 | #define xs_is_true(v) (xs_type((v)) == XSTYPE_TRUE) |
| 158 | #define xs_is_false(v) (xs_type((v)) == XSTYPE_FALSE) | 158 | #define xs_is_false(v) (xs_type((v)) == XSTYPE_FALSE) |
| 159 | #define xs_not(v) xs_stock(xs_is_true((v)) ? XSTYPE_FALSE : XSTYPE_TRUE) | 159 | #define xs_not(v) xs_stock(xs_is_true((v)) ? XSTYPE_FALSE : XSTYPE_TRUE) |
| 160 | #define xs_is_string(v) (xs_type((v)) == XSTYPE_STRING) | ||
| 161 | #define xs_is_list(v) (xs_type((v)) == XSTYPE_LIST) | ||
| 162 | #define xs_is_dict(v) (xs_type((v)) == XSTYPE_DICT) | ||
| 160 | 163 | ||
| 161 | #define xs_list_foreach(l, v) for (int ct_##__LINE__ = 0; xs_list_next(l, &v, &ct_##__LINE__); ) | 164 | #define xs_list_foreach(l, v) for (int ct_##__LINE__ = 0; xs_list_next(l, &v, &ct_##__LINE__); ) |
| 162 | #define xs_dict_foreach(l, k, v) for (int ct_##__LINE__ = 0; xs_dict_next(l, &k, &v, &ct_##__LINE__); ) | 165 | #define xs_dict_foreach(l, k, v) for (int ct_##__LINE__ = 0; xs_dict_next(l, &k, &v, &ct_##__LINE__); ) |
| @@ -623,15 +626,14 @@ int xs_between(const char *prefix, const char *str, const char *suffix) | |||
| 623 | xs_str *xs_crop_i(xs_str *str, int start, int end) | 626 | xs_str *xs_crop_i(xs_str *str, int start, int end) |
| 624 | /* crops the string to be only from start to end */ | 627 | /* crops the string to be only from start to end */ |
| 625 | { | 628 | { |
| 626 | XS_ASSERT_TYPE(str, XSTYPE_STRING); | ||
| 627 | |||
| 628 | int sz = strlen(str); | 629 | int sz = strlen(str); |
| 629 | 630 | ||
| 630 | if (end <= 0) | 631 | if (end <= 0) |
| 631 | end = sz + end; | 632 | end = sz + end; |
| 632 | 633 | ||
| 633 | /* crop from the top */ | 634 | /* crop from the top */ |
| 634 | str[end] = '\0'; | 635 | if (end > 0 && end < sz) |
| 636 | str[end] = '\0'; | ||
| 635 | 637 | ||
| 636 | /* crop from the bottom */ | 638 | /* crop from the bottom */ |
| 637 | str = xs_collapse(str, 0, start); | 639 | str = xs_collapse(str, 0, start); |
| @@ -1061,14 +1063,15 @@ xs_keyval *xs_keyval_make(xs_keyval *keyval, const xs_str *key, const xs_val *va | |||
| 1061 | 1063 | ||
| 1062 | typedef struct { | 1064 | typedef struct { |
| 1063 | int value_offset; /* offset to value (from dict start) */ | 1065 | int value_offset; /* offset to value (from dict start) */ |
| 1064 | int next; /* next node in sequential search */ | 1066 | int next; /* next node in sequential scanning */ |
| 1065 | int child[4]; /* child nodes in hashed search */ | 1067 | int child[4]; /* child nodes in hashed search */ |
| 1066 | char key[]; /* C string key */ | 1068 | char key[]; /* C string key */ |
| 1067 | } ditem_hdr; | 1069 | } ditem_hdr; |
| 1068 | 1070 | ||
| 1069 | typedef struct { | 1071 | typedef struct { |
| 1070 | int size; /* size of full dict (_XS_TYPE_SIZE) */ | 1072 | int size; /* size of full dict (_XS_TYPE_SIZE) */ |
| 1071 | int first; /* first node for sequential search */ | 1073 | int first; /* first node for sequential scanning */ |
| 1074 | int last; /* last node for sequential scanning */ | ||
| 1072 | int root; /* root node for hashed search */ | 1075 | int root; /* root node for hashed search */ |
| 1073 | /* a bunch of ditem_hdr and value follows */ | 1076 | /* a bunch of ditem_hdr and value follows */ |
| 1074 | } dict_hdr; | 1077 | } dict_hdr; |
| @@ -1153,8 +1156,15 @@ xs_dict *xs_dict_set(xs_dict *dict, const xs_str *key, const xs_val *value) | |||
| 1153 | memcpy(dict + di->value_offset, value, vsz); | 1156 | memcpy(dict + di->value_offset, value, vsz); |
| 1154 | 1157 | ||
| 1155 | /* chain to the sequential list */ | 1158 | /* chain to the sequential list */ |
| 1156 | di->next = dh->first; | 1159 | if (dh->first == 0) |
| 1157 | dh->first = end; | 1160 | dh->first = end; |
| 1161 | else { | ||
| 1162 | /* chain this new element to the last one */ | ||
| 1163 | ditem_hdr *dil = (ditem_hdr *)(dict + dh->last); | ||
| 1164 | dil->next = end; | ||
| 1165 | } | ||
| 1166 | |||
| 1167 | dh->last = end; | ||
| 1158 | } | 1168 | } |
| 1159 | else { | 1169 | else { |
| 1160 | /* ditem already exists */ | 1170 | /* ditem already exists */ |