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

Reply via email to