disable OM2.3.1 by default, enable with make bertw OM231=1
[nedit-bw.git] / guaranty-order-for-numeric-keys.patch
blob0f6775667ecf93ad6615c2f3a6c1fa3b036cb5bc
1 Subject: Quaranty order for numeric array keys
3 Currently ther is no order guaranty for array keys in the for loops, this is
4 for numeric keys a little amberressing.
6 Use a new compare routine that is taking care of numeric keys. This works also
7 for multi-dimensional keys with sub dimensional numeric keys.
9 Therefore, this do the right thing:
11 arr[10] = "ten"
12 arr[ 2] = "two"
13 arr[ 1] = "one"
15 for (k in arr) {
16 t_print(k "\n")
19 And this too:
21 arr[10,10] = "ten,ten"
22 arr[10, 2] = "ten,two"
23 arr[10, 1] = "ten,one"
24 arr[ 2,10] = "two,ten"
25 arr[ 2, 2] = "two,two"
26 arr[ 2, 1] = "two,one"
27 arr[ 1,10] = "one,ten"
28 arr[ 1, 2] = "one,two"
29 arr[ 1, 1] = "one,one"
31 for (k in arr) {
32 t_print(k "\n")
35 And this too:
37 arr["c",10] = "c,ten"
38 arr["c", 2] = "c,two"
39 arr["c", 1] = "c,one"
40 arr["b",10] = "b,ten"
41 arr["b", 2] = "b,two"
42 arr["b", 1] = "b,one"
43 arr["a",10] = "a,ten"
44 arr["a", 2] = "a,two"
45 arr["a", 1] = "a,one"
47 for (k in arr) {
48 t_print(k "\n")
51 There is one semantic change with this:
53 arr[1] = "one"
55 would be overridden by this:
57 arr["01"] = "zeroone"
59 ---
61 source/interpret.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
62 1 file changed, 67 insertions(+), 1 deletion(-)
64 diff --quilt old/source/interpret.c new/source/interpret.c
65 --- old/source/interpret.c
66 +++ new/source/interpret.c
67 @@ -2369,14 +2369,80 @@ static int arrayEntryCopyToNode(rbTreeNo
68 return(1);
72 ** compare two array nodes returning an integer value similar to strcmp()
73 +**
74 +** take care of numeric keys and sort them right, also with multi dimensions
76 static int arrayEntryCompare(rbTreeNode *left, rbTreeNode *right)
78 - return(strcmp(((SparseArrayEntry *)left)->key, ((SparseArrayEntry *)right)->key));
79 + const char *keya = ((SparseArrayEntry *)left)->key;
80 + const char *keya_end = keya + strlen(keya);
81 + const char *keyb = ((SparseArrayEntry *)right)->key;
82 + const char *keyb_end = keyb + strlen(keyb);
83 + int cmp;
84 + int state = 0;
86 + /*
87 + ** alternate bewteen non-numeric and numeric parts
88 + */
89 + while (1) {
90 + long a_len;
91 + long b_len;
93 + if (state == 0) {
94 + a_len = strcspn(keya, "0123456789");
95 + b_len = strcspn(keyb, "0123456789");
97 + /*
98 + ** a_len/b_len are the length of the next non-numeric parts
99 + ** if theses length differ, just compare the remainder
100 + */
101 + if (a_len != b_len) {
102 + return strcmp(keya, keyb);
105 + /* compare the non-numeric parts */
106 + cmp = strncmp(keya, keyb, a_len);
108 + } else {
109 + long a_num = 0, b_num = 0;
111 + /*
112 + ** try to parse a number
113 + ** if this fails, a_num/b_num are previously set to 0
114 + */
115 + sscanf(keya, "%ld%ln", &a_num, &a_len);
116 + sscanf(keyb, "%ld%ln", &b_num, &b_len);
118 + /* "a" and "a0" should differ, is cought by break condition */
119 + if ((a_len == 0 && b_len > 0) || (a_len > 0 && b_len == 0)) {
120 + return strcmp(keya, keyb);
123 + /* compare the numbers */
124 + cmp = (a_num > b_num) - (a_num < b_num);
127 + if (cmp != 0) {
128 + return cmp;
131 + keya += a_len;
132 + keyb += b_len;
134 + state ^= 1;
136 + /*
137 + ** break condition:
138 + ** at least one key is fully eaten, compare the remainder
139 + */
140 + if (keya == keya_end || keyb == keyb_end) {
141 + return strcmp(keya, keyb);
147 ** dispose an array node, garbage collection handles this, so we mark it
148 ** to allow iterators in macro language to determine they have been unlinked