commit fdd2217
grunfink
·
2026-01-10 19:40:13 +0000 UTC
parent a8cbbee
New file xs_list_tools.h.
3 files changed,
+171,
-1
M
snac.c
+1,
-0
1@@ -27,6 +27,7 @@
2 #include "xs_html.h"
3 #include "xs_po.h"
4 #include "xs_webmention.h"
5+#include "xs_list_tools.h"
6
7 #include "snac.h"
8
+169,
-0
1@@ -0,0 +1,169 @@
2+/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */
3+
4+#ifndef _XS_LIST_TOOLS_H
5+
6+#define _XS_LIST_TOOLS_H
7+
8+ xs_list *xs_list_insert_sorted(xs_list *list, const xs_val *nv);
9+ xs_list *xs_list_reverse(const xs_list *l);
10+ xs_val **xs_list_to_array(const xs_list *l, int *len);
11+ int xs_list_sort_cmp(const void *p1, const void *p2);
12+ int xs_list_sort_inv_cmp(const void *p1, const void *p2);
13+ int xs_list_sort_dict_cmp(const char *field, const void *p1, const void *p2);
14+ xs_list *xs_list_sort(const xs_list *l, int (*cmp)(const void *, const void *));
15+ xs_list *xs_list_shuffle(const xs_list *l);
16+
17+#ifdef XS_IMPLEMENTATION
18+
19+#include "xs_random.h"
20+
21+xs_list *xs_list_insert_sorted(xs_list *list, const xs_val *nv)
22+/* inserts a string in the list in its ordered position */
23+{
24+ XS_ASSERT_TYPE(list, XSTYPE_LIST);
25+
26+ int offset = xs_size(list);
27+
28+ const xs_val *v;
29+ xs_list_foreach(list, v) {
30+ /* if this element is greater or equal, insert here */
31+ if (xs_cmp(v, nv) >= 0) {
32+ offset = v - list;
33+ break;
34+ }
35+ }
36+
37+ return _xs_list_write_litem(list, offset - 1, nv, xs_size(nv));
38+}
39+
40+
41+xs_list *xs_list_reverse(const xs_list *l)
42+/* creates a new list as a reverse version of l */
43+{
44+ xs_list *n = xs_dup(l);
45+ const xs_val *v;
46+
47+ /* move to one byte before the EOM */
48+ char *p = n + xs_size(n) - 1;
49+
50+ xs_list_foreach(l, v) {
51+ /* size of v, plus the LITEM */
52+ int z = xs_size(v) + 1;
53+
54+ p -= z;
55+
56+ /* copy v, including its LITEM */
57+ memcpy(p, v - 1, z);
58+ }
59+
60+ return n;
61+}
62+
63+
64+xs_val **xs_list_to_array(const xs_list *l, int *len)
65+/* converts a list to an array of values */
66+/* must be freed after use */
67+{
68+ *len = xs_list_len(l);
69+ xs_val **a = xs_realloc(NULL, *len * sizeof(xs_val *));
70+ const xs_val *v;
71+ int n = 0;
72+
73+ xs_list_foreach(l, v)
74+ a[n++] = (xs_val *)v;
75+
76+ return a;
77+}
78+
79+
80+int xs_list_sort_cmp(const void *p1, const void *p2)
81+/* default list sorting function */
82+{
83+ const xs_val *v1 = *(xs_val **)p1;
84+ const xs_val *v2 = *(xs_val **)p2;
85+
86+ return xs_cmp(v1, v2);
87+}
88+
89+
90+int xs_list_sort_inv_cmp(const void *p1, const void *p2)
91+/* default list inverse sorting function */
92+{
93+ const xs_val *v1 = *(xs_val **)p1;
94+ const xs_val *v2 = *(xs_val **)p2;
95+
96+ return xs_cmp(v2, v1);
97+}
98+
99+
100+int xs_list_sort_dict_cmp(const char *field, const void *p1, const void *p2)
101+/* compare sorting function for a field an array of dicts */
102+{
103+ const xs_dict *d1 = *(xs_val **)p1;
104+ const xs_dict *d2 = *(xs_val **)p2;
105+
106+ if (xs_type(d1) != XSTYPE_DICT || xs_type(d2) != XSTYPE_DICT)
107+ return 0;
108+
109+ return xs_cmp(xs_dict_get_def(d1, field, ""),
110+ xs_dict_get_def(d2, field, ""));
111+}
112+
113+
114+xs_list *xs_list_sort(const xs_list *l, int (*cmp)(const void *, const void *))
115+/* returns a sorted copy of l. cmp can be null for standard sorting */
116+{
117+ int sz;
118+ xs_val **a = xs_list_to_array(l, &sz);
119+ xs_list *nl = xs_dup(l);
120+ char *p = nl + 1 + _XS_TYPE_SIZE;
121+
122+ /* sort the array */
123+ qsort(a, sz, sizeof(xs_val *), cmp ? cmp : xs_list_sort_cmp);
124+
125+ /* transfer the sorted list over the copy */
126+ for (int n = 0; n < sz; n++) {
127+ /* get the litem */
128+ const char *e = a[n] - 1;
129+ int z = xs_size(e);
130+
131+ memcpy(p, e, z);
132+ p += z;
133+ }
134+
135+ xs_free(a);
136+
137+ return nl;
138+}
139+
140+
141+xs_list *xs_list_shuffle(const xs_list *l)
142+/* returns a shuffled list */
143+{
144+ int sz;
145+ xs_val **a = xs_list_to_array(l, &sz);
146+ xs_list *nl = xs_list_new();
147+ unsigned int seed = 0;
148+
149+ xs_rnd_buf(&seed, sizeof(seed));
150+
151+ /* shuffle */
152+ for (int n = sz - 1; n > 0; n--) {
153+ int m = xs_rnd_int32_d(&seed) % n;
154+ void *p = a[n];
155+ a[n] = a[m];
156+ a[m] = p;
157+ }
158+
159+ for (int n = 0; n < sz; n++)
160+ nl = xs_list_append(nl, a[n]);
161+
162+ xs_free(a);
163+
164+ return nl;
165+}
166+
167+
168+#endif /* XS_IMPLEMENTATION */
169+
170+#endif /* XS_LIST_TOOLS_H */
+1,
-1
1@@ -1 +1 @@
2-/* ad74258be9b1585840a5366cdb4b6ef707c0e95a 2026-01-01T16:58:39+01:00 */
3+/* 270f9376eabd4f8e0ed3ae22a1f8eb6e06ea8b8b 2026-01-10T20:39:12+01:00 */