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:
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"
51 There is one semantic change with this:
55 would be overridden by this:
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
72 ** compare two array nodes returning an integer value similar to strcmp()
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);
87 + ** alternate bewteen non-numeric and numeric parts
94 + a_len = strcspn(keya, "0123456789");
95 + b_len = strcspn(keyb, "0123456789");
98 + ** a_len/b_len are the length of the next non-numeric parts
99 + ** if theses length differ, just compare the remainder
101 + if (a_len != b_len) {
102 + return strcmp(keya, keyb);
105 + /* compare the non-numeric parts */
106 + cmp = strncmp(keya, keyb, a_len);
109 + long a_num = 0, b_num = 0;
112 + ** try to parse a number
113 + ** if this fails, a_num/b_num are previously set to 0
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);
137 + ** break condition:
138 + ** at least one key is fully eaten, compare the remainder
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