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. --- xs_list_tools.h | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 xs_list_tools.h (limited to 'xs_list_tools.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 */ -- cgit v1.2.3