aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvan Hunter <evan@ozhiker.com>2016-10-06 22:19:26 +0100
committerSteve Bennett <steveb@workware.net.au>2016-10-12 09:26:58 +1000
commit80032e22c35eb24d2df11843a723caa7c7160d29 (patch)
treef813e53f67fb094ae43b8be64331e9a35ed523a0
parent73176c908b681a9500af84abfa2f7f6234f3f913 (diff)
downloadjimtcl-80032e22c35eb24d2df11843a723caa7c7160d29.zip
jimtcl-80032e22c35eb24d2df11843a723caa7c7160d29.tar.gz
jimtcl-80032e22c35eb24d2df11843a723caa7c7160d29.tar.bz2
Array fixes and tests
Changed 'array exists' to actually check if the variable is an array (matches tclsh) Fix Jim_DictInfo to avoid using printf() and make output match tclsh Added some more tests for array command - checked these work with tclsh
-rw-r--r--jim-array.c11
-rw-r--r--jim.c39
-rw-r--r--jim_tcl.txt3
-rw-r--r--tests/array.test46
4 files changed, 84 insertions, 15 deletions
diff --git a/jim-array.c b/jim-array.c
index 39cd168..cd3e784 100644
--- a/jim-array.c
+++ b/jim-array.c
@@ -54,7 +54,8 @@
static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
/* Just a regular [info exists] */
- Jim_SetResultInt(interp, Jim_GetVariable(interp, argv[0], 0) != 0);
+ Jim_Obj *dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED);
+ Jim_SetResultInt(interp, dictObj && Jim_DictSize(interp, dictObj) != -1);
return JIM_OK;
}
@@ -115,7 +116,9 @@ static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) {
- return JIM_ERR;
+ /* Variable is not an array - tclsh ignores this and returns nothing - be compatible */
+ Jim_SetResultString(interp, "", -1);
+ return JIM_OK;
}
/* Create a new object with the values which don't match */
@@ -142,7 +145,9 @@ static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
if (objPtr) {
len = Jim_DictSize(interp, objPtr);
if (len < 0) {
- return JIM_ERR;
+ /* Variable is not an array - tclsh ignores this and returns 0 - be compatible */
+ Jim_SetResultInt(interp, 0);
+ return JIM_OK;
}
}
diff --git a/jim.c b/jim.c
index 04eedc6..443da61 100644
--- a/jim.c
+++ b/jim.c
@@ -14365,6 +14365,9 @@ int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr)
{
Jim_HashTable *ht;
unsigned int i;
+ char buffer[100];
+ int sum = 0;
+ int nonzero_count = 0;
if (SetDictFromAny(interp, objPtr) != JIM_OK) {
return JIM_ERR;
@@ -14373,21 +14376,37 @@ int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr)
ht = (Jim_HashTable *)objPtr->internalRep.ptr;
/* Note that this uses internal knowledge of the hash table */
- printf("%d entries in table, %d buckets\n", ht->used, ht->size);
+ snprintf(buffer, sizeof(buffer), "%d entries in table, %d buckets\n", ht->used, ht->size);
+ Jim_Obj *output = Jim_NewStringObj(interp, buffer, -1);
+ int bucket_counts[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
for (i = 0; i < ht->size; i++) {
Jim_HashEntry *he = ht->table[i];
-
- if (he) {
- printf("%d: ", i);
-
- while (he) {
- printf(" %s", Jim_String(he->key));
- he = he->next;
- }
- printf("\n");
+ int entries = 0;
+ while (he) {
+ entries++;
+ he = he->next;
}
+ if (entries > 9) {
+ bucket_counts[10]++;
+ }
+ else {
+ bucket_counts[entries]++;
+ }
+ if (entries) {
+ sum += entries;
+ nonzero_count++;
+ }
+ }
+ for (i = 0; i < 10; i++) {
+ snprintf(buffer, sizeof(buffer), "number of buckets with %d entries: %d\n", i, bucket_counts[i]);
+ Jim_AppendString(interp, output, buffer, -1);
}
+ snprintf(buffer, sizeof(buffer), "number of buckets with 10 or more entries: %d\n", bucket_counts[10]);
+ Jim_AppendString(interp, output, buffer, -1);
+ snprintf(buffer, sizeof(buffer), "average search distance for entry: %.1f", nonzero_count ? (double)sum / nonzero_count : 0.0);
+ Jim_AppendString(interp, output, buffer, -1);
+ Jim_SetResult(interp, output);
return JIM_OK;
}
diff --git a/jim_tcl.txt b/jim_tcl.txt
index af95d66..28dc317 100644
--- a/jim_tcl.txt
+++ b/jim_tcl.txt
@@ -1664,8 +1664,7 @@ command. The legal +'options'+ (which may be abbreviated) are:
+*array exists* 'arrayName'+::
Returns 1 if arrayName is an array variable, 0 if there is
- no variable by that name. This command is essentially
- identical to `info exists`
+ no variable by that name.
+*array get* 'arrayName ?pattern?'+::
Returns a list containing pairs of elements. The first
diff --git a/tests/array.test b/tests/array.test
index ba88147..423276b 100644
--- a/tests/array.test
+++ b/tests/array.test
@@ -85,4 +85,50 @@ test array-1.14 "access array via unset var" -body {
expr {$a($b) + 4}
} -returnCodes error -result {can't read "b": no such variable}
+test array-1.15 "array unset non-variable" -body {
+ array unset nonvariable 4
+} -result {}
+
+test array-1.16 "array names non-variable" -body {
+ array names nonvariable
+} -result {}
+
+test array-1.17 "array get non-variable" -body {
+ array get nonvariable
+} -result {}
+
+# This seems like incorrect behaviour, but it matches tclsh
+test array-1.18 "array size non-array" -body {
+ set x 1
+ array size x
+} -result {0}
+
+# This seems like incorrect behaviour, but it matches tclsh
+test array-1.19 "array unset non-array" -body {
+ set x 6
+ array unset x 4
+} -result {}
+
+test array-1.20 "array stat" -body {
+ set output [array stat a]
+ regexp "1 entries in table.*number of buckets with 1 entries: 1" $output
+} -result {1}
+
+test array-1.21 "array stat non-array" -body {
+ array stat badvariable
+} -returnCodes error -result {"badvariable" isn't an array}
+
+test array-1.22 "array set non-even args" -body {
+ array set x {
+ 1 one
+ 2 two
+ 3
+}
+} -returnCodes error -result {list must have an even number of elements}
+
+test array-1.23 "array exists non-array" -body {
+ set x 4
+ array exists x
+} -result {0}
+
testreport