blob: e1395d7c4394e8e35593d18d198ca1b867cf5b49 (
plain)
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
|
/*
* lexicographical-numeric compare
*/
#include <string.h>
#include <ctype.h>
#include <caml/mlvalues.h>
#include <caml/fail.h>
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);
}
// if here, pos1 == pos2, or something is horribly wrong
if (pos1 != pos2) caml_failwith(inconsistent);
pos = pos1;
p1 = s1;
p2 = s2;
len = len - pos;
len1 = len1 - pos;
len2 = len2 - pos;
pos = 0;
} while (*s1 && *s2);
}
|