Procházet zdrojové kódy

Added some more helping functions.

grunfink před 11 měsíci
rodič
revize
75cc7ae7a3
4 změnil soubory, kde provedl 91 přidání a 19 odebrání
  1. 60 17
      xs.h
  2. 26 1
      xs_set.h
  3. 4 0
      xs_unicode.h
  4. 1 1
      xs_version.h

+ 60 - 17
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;
 }
 
 

+ 26 - 1
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 */

+ 4 - 0
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;

+ 1 - 1
xs_version.h

@@ -1 +1 @@
-/* 401d229ffbec89b4a5cf97793926b7afb84a4f26 2025-07-08T15:44:54+02:00 */
+/* ad90abcefd455c0ba0faf155dc2976490dbde0b0 2025-08-23T20:36:11+02:00 */