From fdd2217be47799d93fe7505faffd7c948d69ecdb Mon Sep 17 00:00:00 2001 From: grunfink Date: Sat, 10 Jan 2026 20:40:13 +0100 Subject: New file xs_list_tools.h. --- snac.c | 1 + xs_list_tools.h | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ xs_version.h | 2 +- 3 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 xs_list_tools.h diff --git a/snac.c b/snac.c index 965edbb..41db86d 100644 --- a/snac.c +++ b/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" diff --git a/xs_list_tools.h b/xs_list_tools.h new file mode 100644 index 0000000..33d4b87 --- /dev/null +++ b/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 */ diff --git a/xs_version.h b/xs_version.h index 598c72e..92a865e 100644 --- a/xs_version.h +++ b/xs_version.h @@ -1 +1 @@ -/* ad74258be9b1585840a5366cdb4b6ef707c0e95a 2026-01-01T16:58:39+01:00 */ +/* 270f9376eabd4f8e0ed3ae22a1f8eb6e06ea8b8b 2026-01-10T20:39:12+01:00 */ -- cgit v1.2.3