| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- /* 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_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_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 */
|