Currently ther is no order guaranty for array keys in the for loops, this is
for numeric keys a little amberressing.
Use a new compare routine that takes care of numeric keys. This works also
for multi-dimensional keys with sub dimensional numeric keys.
Therefore, this do the right thing:
arr[10] = "ten"
arr[ 2] = "two"
arr[ 1] = "one"
for (k in arr) {
t_print(k "\n")
}
And this too:
arr[10,10] = "ten,ten"
arr[10, 2] = "ten,two"
arr[10, 1] = "ten,one"
arr[ 2,10] = "two,ten"
arr[ 2, 2] = "two,two"
arr[ 2, 1] = "two,one"
arr[ 1,10] = "one,ten"
arr[ 1, 2] = "one,two"
arr[ 1, 1] = "one,one"
for (k in arr) {
t_print(k "\n")
}
And this too:
arr["c",10] = "c,ten"
arr["c", 2] = "c,two"
arr["c", 1] = "c,one"
arr["b",10] = "b,ten"
arr["b", 2] = "b,two"
arr["b", 1] = "b,one"
arr["a",10] = "a,ten"
arr["a", 2] = "a,two"
arr["a", 1] = "a,one"
for (k in arr) {
t_print(k "\n")
}
There is one semantic change with this:
arr[1] = "one"
would be overridden by this:
arr["01"] = "zeroone"
---
source/interpret.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 76 insertions(+), 1 deletion(-)
diff --quilt old/source/interpret.c new/source/interpret.c
--- old/source/interpret.c
+++ new/source/interpret.c
@@ -2294,14 +2294,89 @@ static int arrayEntryCopyToNode(rbTreeNo
return(1);
}
/*
** compare two array nodes returning an integer value similar to strcmp()
+**
+** take care of numeric keys and sort them right, also with multi dimensions
*/
static int arrayEntryCompare(rbTreeNode *left, rbTreeNode *right)
{
- return(strcmp(((SparseArrayEntry *)left)->key, ((SparseArrayEntry
*)right)->key));
+ const char *keya = ((SparseArrayEntry *)left)->key;
+ const char *keya_end = keya + strlen(keya);
+ const char *keyb = ((SparseArrayEntry *)right)->key;
+ const char *keyb_end = keyb + strlen(keyb);
+ size_t seplen = strlen(ARRAY_DIM_SEP);
+ int cmp;
+
+ while (1) {
+ long dima_len, numa;
+ long dimb_len, numb;
+ const char *dima_end = strstr(keya, ARRAY_DIM_SEP);
+ const char *dimb_end = strstr(keyb, ARRAY_DIM_SEP);
+ char *numa_end;
+ char *numb_end;
+
+ if (!dima_end) {
+ dima_end = keya_end;
+ }
+ dima_len = dima_end - keya;
+
+ if (!dimb_end) {
+ dimb_end = keyb_end;
+ }
+ dimb_len = dimb_end - keyb;
+
+ /* try to parse a number */
+ numa = strtol(keya, &numa_end, 10);
+ numb = strtol(keyb, &numb_end, 10);
+
+ /*
+ ** if both strtol's eaten up till ARRAY_DIM_SEP, we have
+ ** successfully parsded two numbers
+ */
+ if (numa_end == dima_end && numb_end == dimb_end) {
+ /* successfully parsed numbers
+ ** even empty parts
+ */
+
+ /* compare the numbers */
+ cmp = (numa > numb) - (numa < numb);
+ if (cmp != 0) {
+ return cmp;
+ }
+
+ } else {
+
+ /* if the length differ, just compare the remainder */
+ if (dima_len != dimb_len) {
+ return strcmp(keya, keyb);
+ }
+
+ /* compare this dimension */
+ cmp = strncmp(keya, keyb, dima_len);
+ if (cmp != 0) {
+ return cmp;
+ }
+ }
+
+ /* eat this dimension */
+ keya = dima_end;
+ keyb = dimb_end;
+
+ /*
+ ** break condition:
+ ** at least one key is fully eaten, compare the remainder
+ */
+ if (dima_end == keya_end || dimb_end == keyb_end) {
+ return strcmp(keya, keyb);
+ }
+
+ /* both dim ends point to a ARRAY_DIM_SEP => skip */
+ keya += seplen;
+ keyb += seplen;
+ }
}
/*
** dispose an array node, garbage collection handles this, so we mark it
** to allow iterators in macro language to determine they have been unlinked
--
NEdit Develop mailing list - [email protected]
http://www.nedit.org/mailman/listinfo/develop