Parcourir la source

New file xs_list_tools.h.

grunfink il y a 6 mois
Parent
commit
fdd2217be4
3 fichiers modifiés avec 171 ajouts et 1 suppressions
  1. 1 0
      snac.c
  2. 169 0
      xs_list_tools.h
  3. 1 1
      xs_version.h

+ 1 - 0
snac.c

@@ -27,6 +27,7 @@
 #include "xs_html.h"
 #include "xs_po.h"
 #include "xs_webmention.h"
+#include "xs_list_tools.h"
 
 #include "snac.h"
 

+ 169 - 0
xs_list_tools.h

@@ -0,0 +1,169 @@
+/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */
+
+#ifndef _XS_LIST_TOOLS_H
+
+#define _XS_LIST_TOOLS_H
+
+ xs_list *xs_list_insert_sorted(xs_list *list, const xs_val *nv);
+ xs_list *xs_list_reverse(const xs_list *l);
+ xs_val **xs_list_to_array(const xs_list *l, int *len);
+ int xs_list_sort_cmp(const void *p1, const void *p2);
+ int xs_list_sort_inv_cmp(const void *p1, const void *p2);
+ int xs_list_sort_dict_cmp(const char *field, const void *p1, const void *p2);
+ xs_list *xs_list_sort(const xs_list *l, int (*cmp)(const void *, const void *));
+ xs_list *xs_list_shuffle(const xs_list *l);
+
+#ifdef XS_IMPLEMENTATION
+
+#include "xs_random.h"
+
+xs_list *xs_list_insert_sorted(xs_list *list, const xs_val *nv)
+/* inserts a string in the list in its ordered position */
+{
+    XS_ASSERT_TYPE(list, XSTYPE_LIST);
+
+    int offset = xs_size(list);
+
+    const xs_val *v;
+    xs_list_foreach(list, v) {
+        /* if this element is greater or equal, insert here */
+        if (xs_cmp(v, nv) >= 0) {
+            offset = v - list;
+            break;
+        }
+    }
+
+    return _xs_list_write_litem(list, offset - 1, nv, xs_size(nv));
+}
+
+
+xs_list *xs_list_reverse(const xs_list *l)
+/* creates a new list as a reverse version of l */
+{
+    xs_list *n = xs_dup(l);
+    const xs_val *v;
+
+    /* move to one byte before the EOM */
+    char *p = n + xs_size(n) - 1;
+
+    xs_list_foreach(l, v) {
+        /* size of v, plus the LITEM */
+        int z = xs_size(v) + 1;
+
+        p -= z;
+
+        /* copy v, including its LITEM */
+        memcpy(p, v - 1, z);
+    }
+
+    return n;
+}
+
+
+xs_val **xs_list_to_array(const xs_list *l, int *len)
+/* converts a list to an array of values */
+/* must be freed after use */
+{
+    *len = xs_list_len(l);
+    xs_val **a = xs_realloc(NULL, *len * sizeof(xs_val *));
+    const xs_val *v;
+    int n = 0;
+
+    xs_list_foreach(l, v)
+        a[n++] = (xs_val *)v;
+
+    return a;
+}
+
+
+int xs_list_sort_cmp(const void *p1, const void *p2)
+/* default list sorting function */
+{
+    const xs_val *v1 = *(xs_val **)p1;
+    const xs_val *v2 = *(xs_val **)p2;
+
+    return xs_cmp(v1, v2);
+}
+
+
+int xs_list_sort_inv_cmp(const void *p1, const void *p2)
+/* default list inverse sorting function */
+{
+    const xs_val *v1 = *(xs_val **)p1;
+    const xs_val *v2 = *(xs_val **)p2;
+
+    return xs_cmp(v2, v1);
+}
+
+
+int xs_list_sort_dict_cmp(const char *field, const void *p1, const void *p2)
+/* compare sorting function for a field an array of dicts */
+{
+    const xs_dict *d1 = *(xs_val **)p1;
+    const xs_dict *d2 = *(xs_val **)p2;
+
+    if (xs_type(d1) != XSTYPE_DICT || xs_type(d2) != XSTYPE_DICT)
+        return 0;
+
+    return xs_cmp(xs_dict_get_def(d1, field, ""),
+                  xs_dict_get_def(d2, field, ""));
+}
+
+
+xs_list *xs_list_sort(const xs_list *l, int (*cmp)(const void *, const void *))
+/* returns a sorted copy of l. cmp can be null for standard sorting */
+{
+    int sz;
+    xs_val **a = xs_list_to_array(l, &sz);
+    xs_list *nl = xs_dup(l);
+    char *p = nl + 1 + _XS_TYPE_SIZE;
+
+    /* sort the array */
+    qsort(a, sz, sizeof(xs_val *), cmp ? cmp : xs_list_sort_cmp);
+
+    /* transfer the sorted list over the copy */
+    for (int n = 0; n < sz; n++) {
+        /* get the litem */
+        const char *e = a[n] - 1;
+        int z = xs_size(e);
+
+        memcpy(p, e, z);
+        p += z;
+    }
+
+    xs_free(a);
+
+    return nl;
+}
+
+
+xs_list *xs_list_shuffle(const xs_list *l)
+/* returns a shuffled list */
+{
+    int sz;
+    xs_val **a = xs_list_to_array(l, &sz);
+    xs_list *nl = xs_list_new();
+    unsigned int seed = 0;
+
+    xs_rnd_buf(&seed, sizeof(seed));
+
+    /* shuffle */
+    for (int n = sz - 1; n > 0; n--) {
+        int m = xs_rnd_int32_d(&seed) % n;
+        void *p = a[n];
+        a[n] = a[m];
+        a[m] = p;
+    }
+
+    for (int n = 0; n < sz; n++)
+        nl = xs_list_append(nl, a[n]);
+
+    xs_free(a);
+
+    return nl;
+}
+
+
+#endif /* XS_IMPLEMENTATION */
+
+#endif /* XS_LIST_TOOLS_H */

+ 1 - 1
xs_version.h

@@ -1 +1 @@
-/* ad74258be9b1585840a5366cdb4b6ef707c0e95a 2026-01-01T16:58:39+01:00 */
+/* 270f9376eabd4f8e0ed3ae22a1f8eb6e06ea8b8b 2026-01-10T20:39:12+01:00 */