diff options
-rw-r--r-- | doc/dict.n | 13 | ||||
-rw-r--r-- | generic/tclDictObj.c | 69 | ||||
-rw-r--r-- | tests/dict.test | 28 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/encoding/ebcdic.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/encoding/tis-620.txt | 0 |
5 files changed, 110 insertions, 0 deletions
@@ -120,6 +120,19 @@ It is an error to attempt to retrieve a value for a key that is not present in the dictionary. .RE .TP +\fBdict getwithdefault \fIdictionaryValue \fR?\fIkey ...\fR? \fIkey default\fR +.VS "8.7, TIP342" +This behaves the same as \fBdict get\fR (with at least one \fIkey\fR +argument), returning the value that the key path maps to in the +dictionary \fIdictionaryValue\fR, except that instead of producing an +error because the \fIkey\fR (or one of the \fIkey\fRs on the key path) +is absent, it returns the \fIdefault\fR argument instead. +.RS +.PP +Note that there must always be at least one \fIkey\fR provided. +.RE +.VE "8.7, TIP342" +.TP \fBdict incr \fIdictionaryVariable key \fR?\fIincrement\fR? . This adds the given increment value (an integer that defaults to 1 if diff --git a/generic/tclDictObj.c b/generic/tclDictObj.c index baf96a8..75dcd09 100644 --- a/generic/tclDictObj.c +++ b/generic/tclDictObj.c @@ -34,6 +34,9 @@ static int DictFilterCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int DictGetCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); +static int DictGetWithDefaultCmd(ClientData dummy, + Tcl_Interp *interp, int objc, + Tcl_Obj *const *objv); static int DictIncrCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int DictInfoCmd(ClientData dummy, Tcl_Interp *interp, @@ -89,6 +92,7 @@ static const EnsembleImplMap implementationMap[] = { {"filter", DictFilterCmd, NULL, NULL, NULL, 0 }, {"for", NULL, TclCompileDictForCmd, DictForNRCmd, NULL, 0 }, {"get", DictGetCmd, TclCompileDictGetCmd, NULL, NULL, 0 }, + {"getwithdefault", DictGetWithDefaultCmd, NULL, NULL, NULL, 0 }, {"incr", DictIncrCmd, TclCompileDictIncrCmd, NULL, NULL, 0 }, {"info", DictInfoCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0 }, {"keys", DictKeysCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 }, @@ -1627,6 +1631,71 @@ DictGetCmd( /* *---------------------------------------------------------------------- * + * DictGetWithDefaultCmd -- + * + * This function implements the "dict getwithdefault" Tcl command. See + * the user documentation for details on what it does, and TIP#342 for + * the formal specification. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +DictGetWithDefaultCmd( + ClientData dummy, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const *objv) +{ + Tcl_Obj *dictPtr, *keyPtr, *valuePtr, *defaultPtr; + Tcl_Obj *const *keyPath; + int numKeys; + + if (objc < 4) { + Tcl_WrongNumArgs(interp, 1, objv, "dictionary ?key ...? key default"); + return TCL_ERROR; + } + + /* + * Give the bits of arguments names for clarity. + */ + + dictPtr = objv[1]; + keyPath = &objv[2]; + numKeys = objc - 4; /* Number of keys in keyPath; there's always + * one extra key afterwards too. */ + keyPtr = objv[objc - 2]; + defaultPtr = objv[objc - 1]; + + /* + * Implement the getting-with-default operation. + */ + + dictPtr = TclTraceDictPath(interp, dictPtr, numKeys, keyPath, + DICT_PATH_EXISTS); + if (dictPtr == NULL) { + return TCL_ERROR; + } else if (dictPtr == DICT_PATH_NON_EXISTENT) { + Tcl_SetObjResult(interp, defaultPtr); + } else if (Tcl_DictObjGet(interp, dictPtr, keyPtr, &valuePtr) != TCL_OK) { + return TCL_ERROR; + } else if (valuePtr == NULL) { + Tcl_SetObjResult(interp, defaultPtr); + } else { + Tcl_SetObjResult(interp, valuePtr); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * * DictReplaceCmd -- * * This function implements the "dict replace" Tcl command. See the user diff --git a/tests/dict.test b/tests/dict.test index 904ec53..50e4db7 100644 --- a/tests/dict.test +++ b/tests/dict.test @@ -2047,6 +2047,34 @@ test dict-25.1 {compiled dict update with low-refcount values [Bug d553228d9f]} dict update item item item two two {} }} } {} + +test dict-26.1 {dict getwithdefault command} -body { + dict getwithdefault {a b} a c +} -result b +test dict-26.2 {dict getwithdefault command} -body { + dict getwithdefault {a b} b c +} -result c +test dict-26.3 {dict getwithdefault command} -body { + dict getwithdefault {a {b c}} a b d +} -result c +test dict-26.4 {dict getwithdefault command} -body { + dict getwithdefault {a {b c}} a c d +} -result d +test dict-26.5 {dict getwithdefault command} -body { + dict getwithdefault {a {b c}} b c d +} -result d +test dict-26.6 {dict getwithdefault command} -returnCodes error -body { + dict getwithdefault {a {b c d}} a b d +} -result {missing value to go with key} +test dict-26.7 {dict getwithdefault command} -returnCodes error -body { + dict getwithdefault +} -result {wrong # args: should be "dict getwithdefault dictionary ?key ...? key default"} +test dict-26.8 {dict getwithdefault command} -returnCodes error -body { + dict getwithdefault {} +} -result {wrong # args: should be "dict getwithdefault dictionary ?key ...? key default"} +test dict-26.9 {dict getwithdefault command} -returnCodes error -body { + dict getwithdefault {} {} +} -result {wrong # args: should be "dict getwithdefault dictionary ?key ...? key default"} # cleanup ::tcltest::cleanupTests diff --git a/tools/encoding/ebcdic.txt b/tools/encoding/ebcdic.txt index d9fa42e..d9fa42e 100644..100755 --- a/tools/encoding/ebcdic.txt +++ b/tools/encoding/ebcdic.txt diff --git a/tools/encoding/tis-620.txt b/tools/encoding/tis-620.txt index d3656c5..d3656c5 100644..100755 --- a/tools/encoding/tis-620.txt +++ b/tools/encoding/tis-620.txt |