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