1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
#include <stdlib.h>
#include <string.h>
#include "vlist.h"
static const char *const SORT_NAMES[VSORT_COUNT] = {
"number", "number-desc", "date", "date-desc",
};
static const char *const SORT_LABELS[VSORT_COUNT] = {
"nummer, stigande", "nummer, fallande", "datum, stigande",
"datum, fallande",
};
static int cmp_i64(int64_t a, int64_t b)
{
return a < b ? -1 : a > b;
}
static int cmp_number(const struct vlist_item *a, const struct vlist_item *b)
{
int c = strcmp(a->series, b->series);
if (c)
return c;
return cmp_i64(a->number, b->number);
}
static int g_mode; /* qsort has no context argument in C11 */
static int cmp_items(const void *pa, const void *pb)
{
const struct vlist_item *a = pa, *b = pb;
int desc = g_mode == VSORT_NUMBER_DESC || g_mode == VSORT_DATE_DESC;
int c = 0;
if (g_mode == VSORT_DATE || g_mode == VSORT_DATE_DESC)
c = strcmp(a->date, b->date);
if (!c)
c = cmp_number(a, b);
if (!c)
c = cmp_i64(a->id, b->id);
return desc ? -c : c;
}
void vlist_sort(struct vlist_item *v, size_t n, int mode)
{
if (!v || n < 2)
return;
g_mode = mode >= 0 && mode < VSORT_COUNT ? mode : VSORT_NUMBER;
qsort(v, n, sizeof *v, cmp_items);
}
const char *vlist_sort_label(int mode)
{
return SORT_LABELS[mode >= 0 && mode < VSORT_COUNT ? mode : 0];
}
const char *vlist_sort_name(int mode)
{
return SORT_NAMES[mode >= 0 && mode < VSORT_COUNT ? mode : 0];
}
int vlist_sort_parse(const char *name)
{
for (int i = 0; name && i < VSORT_COUNT; i++)
if (strcmp(name, SORT_NAMES[i]) == 0)
return i;
return VSORT_NUMBER;
}
int vlist_index(const struct vlist_item *v, size_t n, int64_t id)
{
for (size_t i = 0; i < n; i++)
if (v[i].id == id)
return (int)i;
return -1;
}
int vlist_step(size_t n, int idx, int dir)
{
if (idx < 0 || (size_t)idx >= n)
return -1;
int next = idx + (dir < 0 ? -1 : 1);
return next >= 0 && (size_t)next < n ? next : -1;
}
|