From 75cc7ae7a3799a27a5647a2c7d912e6a6e2fbb5b Mon Sep 17 00:00:00 2001 From: grunfink Date: Sat, 23 Aug 2025 20:41:16 +0200 Subject: Added some more helping functions. --- xs.h | 77 ++++++++++++++++++++++++++++++++++++++++++++++-------------- xs_set.h | 27 ++++++++++++++++++++- xs_unicode.h | 4 ++++ xs_version.h | 2 +- 4 files changed, 91 insertions(+), 19 deletions(-) diff --git a/xs.h b/xs.h index 54b913e..5f2e6aa 100644 --- a/xs.h +++ b/xs.h @@ -134,7 +134,9 @@ xs_dict *xs_dict_set_path_sep(xs_dict *dict, const char *path, const xs_val *val xs_val *xs_val_new(xstype t); xs_number *xs_number_new(double f); +xs_number *xs_number_new_l(long l); double xs_number_get(const xs_number *v); +long xs_number_get_l(const xs_number *v); const char *xs_number_str(const xs_number *v); xs_data *xs_data_new(const void *data, int size); @@ -163,6 +165,7 @@ uint64_t xs_hash64_func(const char *data, int size); #define xs_is_string(v) (xs_type((v)) == XSTYPE_STRING) #define xs_is_list(v) (xs_type((v)) == XSTYPE_LIST) #define xs_is_dict(v) (xs_type((v)) == XSTYPE_DICT) +#define xs_is_number(v) (xs_type((v)) == XSTYPE_NUMBER) #define xs_list_foreach(l, v) for (int ct_##__LINE__ = 0; xs_list_next(l, &v, &ct_##__LINE__); ) #define xs_dict_foreach(l, k, v) for (int ct_##__LINE__ = 0; xs_dict_next(l, &k, &v, &ct_##__LINE__); ) @@ -362,9 +365,22 @@ int xs_is_null(const xs_val *data) int xs_cmp(const xs_val *v1, const xs_val *v2) /* compares two values */ { - if (xs_type(v1) == XSTYPE_STRING && xs_type(v2) == XSTYPE_STRING) + xstype t1 = xs_type(v1); + xstype t2 = xs_type(v2); + + if (t1 == XSTYPE_NULL || t2 == XSTYPE_NULL) + return 0; + + if (t1 == XSTYPE_STRING && t2 == XSTYPE_STRING) return strcmp(v1, v2); + if (t1 == XSTYPE_NUMBER && t2 == XSTYPE_NUMBER) { + double d1 = xs_number_get(v1); + double d2 = xs_number_get(v2); + + return d1 == d2 ? 0 : d1 < d2 ? -1 : 1; + } + int s1 = xs_size(v1); int s2 = xs_size(v2); int d = s1 - s2; @@ -975,6 +991,9 @@ xs_str *xs_join(const xs_list *list, const char *sep) xs_list_foreach(list, v) { /* refuse to join non-string values */ + if (xs_type(v) == XSTYPE_NUMBER) + v = xs_number_str(v); + if (xs_type(v) == XSTYPE_STRING) { int sz; @@ -1396,10 +1415,20 @@ xs_val *xs_val_new(xstype t) /** numbers */ +xs_number *_xs_number_new(const char *str) +{ + xs_number *v = xs_realloc(NULL, 1 + xs_size(str)); + + v[0] = XSTYPE_NUMBER; + memcpy(&v[1], str, xs_size(str)); + + return v; +} + + xs_number *xs_number_new(double f) -/* adds a new number value */ +/* creates a new number value from a double */ { - xs_number *v; char tmp[64]; snprintf(tmp, sizeof(tmp), "%.15lf", f); @@ -1416,40 +1445,54 @@ xs_number *xs_number_new(double f) *ptr = '\0'; } - /* alloc for the marker and the full string */ - v = xs_realloc(NULL, _xs_blk_size(1 + xs_size(tmp))); + return _xs_number_new(tmp); +} - v[0] = XSTYPE_NUMBER; - memcpy(&v[1], tmp, xs_size(tmp)); - return v; +xs_number *xs_number_new_l(long l) +/* creates a new number value from a long */ +{ + char tmp[64]; + + snprintf(tmp, sizeof(tmp), "%ld", l); + + return _xs_number_new(tmp); } double xs_number_get(const xs_number *v) /* gets the number as a double */ { - double f = 0.0; + if (xs_type(v) == XSTYPE_NUMBER) + v++; + + if (xs_type(v) == XSTYPE_STRING) + return atof(v); + return 0.0; +} + + +long xs_number_get_l(const xs_number *v) +/* gets the number as a long */ +{ if (xs_type(v) == XSTYPE_NUMBER) - f = atof(&v[1]); - else + v++; + if (xs_type(v) == XSTYPE_STRING) - f = atof(v); + return atol(v); - return f; + return 0; } const char *xs_number_str(const xs_number *v) /* gets the number as a string */ { - const char *p = NULL; - if (xs_type(v) == XSTYPE_NUMBER) - p = &v[1]; + return v + 1; - return p; + return NULL; } diff --git a/xs_set.h b/xs_set.h index 3eaefdf..8946e42 100644 --- a/xs_set.h +++ b/xs_set.h @@ -14,6 +14,7 @@ typedef struct _xs_set { void xs_set_init(xs_set *s); xs_list *xs_set_result(xs_set *s); void xs_set_free(xs_set *s); +int xs_set_in(const xs_set *s, const xs_val *data); int xs_set_add(xs_set *s, const xs_val *data); @@ -60,7 +61,7 @@ static int _store_hash(xs_set *s, const char *data, int value) while (s->hash[(i = hash % s->elems)]) { /* get the pointer to the stored data */ - char *p = &s->list[s->hash[i]]; + const char *p = &s->list[s->hash[i]]; /* already here? */ if (memcmp(p, data, sz) == 0) @@ -79,6 +80,30 @@ static int _store_hash(xs_set *s, const char *data, int value) } +int xs_set_in(const xs_set *s, const xs_val *data) +/* returns 1 if the data is already in the set */ +{ + unsigned int hash, i; + int sz = xs_size(data); + + hash = xs_hash_func(data, sz); + + while (s->hash[(i = hash % s->elems)]) { + /* get the pointer to the stored data */ + const char *p = &s->list[s->hash[i]]; + + /* already here? */ + if (memcmp(p, data, sz) == 0) + return 1; + + /* try next value */ + hash++; + } + + return 0; +} + + int xs_set_add(xs_set *s, const xs_val *data) /* adds the data to the set */ /* returns: 1 if added, 0 if already there */ diff --git a/xs_unicode.h b/xs_unicode.h index ef18fea..67b3827 100644 --- a/xs_unicode.h +++ b/xs_unicode.h @@ -79,6 +79,10 @@ unsigned int xs_utf8_dec(const char **str) /* decodes an utf-8 char inside str and updates the pointer */ { const char *p = *str; + + if (!xs_is_string(p)) + return 0; + unsigned int cpoint = 0; unsigned char c = *p++; int cb = 0; diff --git a/xs_version.h b/xs_version.h index 466535b..cd52531 100644 --- a/xs_version.h +++ b/xs_version.h @@ -1 +1 @@ -/* 401d229ffbec89b4a5cf97793926b7afb84a4f26 2025-07-08T15:44:54+02:00 */ +/* ad90abcefd455c0ba0faf155dc2976490dbde0b0 2025-08-23T20:36:11+02:00 */ -- cgit v1.2.3