summaryrefslogtreecommitdiff
path: root/src/util/sort.c
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2026-08-25 19:38:29 -0400
committerAndrew Opalach <andrew@akon.city> 2026-08-25 19:39:21 -0400
commit87a93623126c41cdfdbdb62878efb3f1d33b819e (patch)
tree053c4ced4f09461839c16826ff48c205cf2817cd /src/util/sort.c
parentd2d8e2fa52c5633f6376e4d3b1d7aca9a9ea14b0 (diff)
downloadlibnaunet-87a93623126c41cdfdbdb62878efb3f1d33b819e.tar.gz
libnaunet-87a93623126c41cdfdbdb62878efb3f1d33b819e.tar.bz2
libnaunet-87a93623126c41cdfdbdb62878efb3f1d33b819e.zip
Add numerical sort for files
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src/util/sort.c')
-rw-r--r--src/util/sort.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/src/util/sort.c b/src/util/sort.c
new file mode 100644
index 0000000..8d306a8
--- /dev/null
+++ b/src/util/sort.c
@@ -0,0 +1,61 @@
+#include <al/str.h>
+
+static inline u32 find_number(str *s)
+{
+ u32 i = 0;
+ while (i < s->length && !al_isnumber(al_str_at(s, i))) { i++; }
+ return (i == s->length) ? AL_STR_NO_POS : i;
+}
+
+static inline u32 find_non_number(str *s)
+{
+ u32 i = 0;
+ while (i < s->length && al_isnumber(al_str_at(s, i))) { i++; }
+ return i;
+}
+
+s32 nn_numerical_compare(const void *a, const void *b)
+{
+ str s1 = *(str *)a, s2 = *(str *)b;
+ s32 ret;
+ str sub1, sub2;
+ bool error;
+ s64 n1, n2;
+ u32 nn1 = find_number(&s1);
+ u32 nn2 = find_number(&s2);
+ if (nn1 != nn2) {
+ goto compare_remainder;
+ }
+ s1 = al_str_substr(&s1, nn1, s1.length);
+ s2 = al_str_substr(&s2, nn2, s2.length);
+ do {
+ nn1 = find_non_number(&s1);
+ nn2 = find_non_number(&s2);
+ sub1 = al_str_substr(&s1, 0, nn1);
+ sub2 = al_str_substr(&s2, 0, nn2);
+ n1 = al_str_to_long(&sub1, 10, &error);
+ al_assert(!error);
+ n2 = al_str_to_long(&sub2, 10, &error);
+ al_assert(!error);
+ if (n1 > n2) return 1;
+ else if (n1 < n2) return -1;
+ s1 = al_str_substr(&s1, nn1, s1.length);
+ s2 = al_str_substr(&s2, nn2, s2.length);
+ nn1 = find_number(&s1);
+ nn2 = find_number(&s2);
+ if (nn1 == AL_STR_NO_POS || nn2 == AL_STR_NO_POS) {
+ goto compare_remainder;
+ }
+ sub1 = al_str_substr(&s1, 0, nn1);
+ sub2 = al_str_substr(&s2, 0, nn2);
+ if (!al_str_eq(&sub1, &sub2)) {
+ goto compare_remainder;
+ }
+ s1 = al_str_substr(&s1, nn1, s1.length);
+ s2 = al_str_substr(&s2, nn2, s2.length);
+ } while (1);
+compare_remainder:
+ ret = al_str_cmp(&s1, &s2, 0, MIN(s1.length, s2.length));
+ if (ret == 0) return s1.length - s2.length;
+ return ret;
+}