summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Estabrook <jestabro@vyos.io>2026-08-07 15:01:32 -0500
committerJohn Estabrook <jestabro@vyos.io>2026-08-09 19:22:12 -0500
commit70f21a8ebdbfe375155a71e1c29f3e548b3e255f (patch)
tree1ff113d895ec1dd8b2b135e7f6d85a9cc2100e10 /src
parent61d74382573fdeb959c708baa9388b40a864e143 (diff)
downloadvyos1x-config-70f21a8ebdbfe375155a71e1c29f3e548b3e255f.tar.gz
vyos1x-config-70f21a8ebdbfe375155a71e1c29f3e548b3e255f.zip
T9182: simplify lexical_numeric_compare and catch corner case
With bugs resolved, behavior remains as before, distinguishing numerical substrings containing leading 0's: this is to allow distinction in the case of arbitrary node name practices, such as "name1" and "name01". Equality of integer values is a matter for parsing/validation, not the comparator.
Diffstat (limited to 'src')
-rw-r--r--src/lexical_numeric_compare.c92
1 files changed, 28 insertions, 64 deletions
diff --git a/src/lexical_numeric_compare.c b/src/lexical_numeric_compare.c
index 3905f3f..41910ed 100644
--- a/src/lexical_numeric_compare.c
+++ b/src/lexical_numeric_compare.c
@@ -1,79 +1,43 @@
/*
* lexicographical-numeric compare
*/
-#include <string.h>
+
+#include <stdlib.h>
#include <ctype.h>
+#include <string.h>
#include <caml/mlvalues.h>
-#include <caml/fail.h>
+
+static int normalize(int v) {
+ return v == 0 ? 0 : (v / abs(v));
+}
CAMLprim value caml_lex_numeric_compare(value str1, value str2) {
- const char* inconsistent = "internal indexing error";
- mlsize_t len, len1, len2;
- int pos, pos1, pos2;
const char * s1, * s2;
- const char * p1, * p2;
- int n1, n2;
- int res;
- if (str1 == str2) return Val_int(0);
- len1 = caml_string_length(str1);
- len2 = caml_string_length(str2);
- len = len1 <= len2 ? len1 : len2;
s1 = String_val(str1);
s2 = String_val(str2);
- p1 = s1;
- p2 = s2;
- pos = 0;
- do {
- while ((pos < len) && (!isdigit(*s1) || !isdigit(*s2))) {
- s1++;
- s2++;
- pos++;
- }
- if (pos > 0) {
- res = memcmp(p1, p2, pos);
- if (res < 0) return Val_int(-1);
- if (res > 0) return Val_int(1);
- if (pos == len) {
- if (len1 < len2) return Val_int(-1);
- if (len2 < len1) return Val_int(1);
- return Val_int(0);
- }
- }
- p1 = s1;
- p2 = s2;
- len = len - pos;
- len1 = len1 - pos;
- len2 = len2 - pos;
- pos1 = pos2 = 0;
- n1 = n2 = 0;
- while ((pos1 < len1) && isdigit(*s1)) {
- n1 = n1 * 10 + *s1 - '0';
- s1++;
- pos1++;
- }
- while ((pos2 < len2) && isdigit(*s2)) {
- n2 = n2 * 10 + *s2 - '0';
- s2++;
- pos2++;
- }
- if (n1 < n2) return Val_int(-1);
- if (n2 < n1) return Val_int(1);
- if ((pos1 == len1) || (pos2 == len2)) {
- if (len1 < len2) return Val_int(-1);
- if (len2 < len1) return Val_int(1);
- return Val_int(0);
+ while (*s1 && *s2) {
+ if (isdigit((unsigned char)*s1) && isdigit((unsigned char)*s2)) {
+ const char *ps1 = s1, *ps2 = s2;
+
+ while (isdigit((unsigned char)*s1)) s1++;
+ while (isdigit((unsigned char)*s2)) s2++;
+ size_t ls1 = s1 - ps1, ls2 = s2 - ps2;
+ if (ls1 != ls2) return ls1 < ls2 ? Val_int(-1) : Val_int(1);
+
+ int c = memcmp(ps1, ps2, ls1);
+ if (c) return Val_int(normalize(c));
+
+ } else {
+ if (*s1 != *s2) {
+ int res = (int)((unsigned char)*s1 - (unsigned char)*s2);
+ return Val_int(normalize(res));
+ }
+ s1++; s2++;
}
- // if a sequence of 0's were encountered, it is possible that
- // pos1 != pos2; adjust
- pos = pos1 > pos2 ? pos2 : pos1;
- p1 = s1;
- p2 = s2;
- len = len - pos;
- len1 = len1 - pos;
- len2 = len2 - pos;
- pos = 0;
- } while (*s1 && *s2);
+ }
+ int res = (int)((unsigned char)*s1 - (unsigned char)*s2);
+ return Val_int(normalize(res));
}