From 5c57bce0a0440c73bd76ec096ffa1c3d0f525b9f Mon Sep 17 00:00:00 2001 From: dkf Date: Fri, 12 Mar 2004 23:21:04 +0000 Subject: Implementation of [dict merge] subcommand, based on [FRQ 745851] --- ChangeLog | 7 ++++ doc/dict.n | 9 ++++- generic/tclDictObj.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++--- tests/dict.test | 35 +++++++++++++++++-- 4 files changed, 139 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index ea3c72a..bb7e880 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2004-03-12 Donal K. Fellows + + IMPLEMENTATION OF TIP#163 + * generic/tclDictObj.c (DictMergeCmd): This is based on work by Joe + * tests/dict.test (dict-20.*): English in Tcl [FRQ 745851] + * doc/dict.n: but not exactly. + 2004-03-10 Kevin B. Kenny * generic/tclGetDate.y (TclGetDate): Fix so that diff --git a/doc/dict.n b/doc/dict.n index d0098cb..bea4ee8 100644 --- a/doc/dict.n +++ b/doc/dict.n @@ -4,7 +4,7 @@ '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" -'\" RCS: @(#) $Id: dict.n,v 1.2 2003/04/10 13:11:06 dkf Exp $ +'\" RCS: @(#) $Id: dict.n,v 1.3 2004/03/12 23:21:05 dkf Exp $ '\" .so man.macros .TH dict n 8.5 Tcl "Tcl Built-In Commands" @@ -133,6 +133,13 @@ keys are treated as if they map to an empty list, and it is legal for there to be no items to append to the list. It is an error for the value that the key maps to to not be representable as a list. .TP +\fBdict merge \fR?\fIdictionaryValue ...\fR? +Return a dictionary that contains the contents of each of the +\fIdictionaryValue\fR arguments. Where two (or more) dictionaries +contain a mapping for the same key, the resulting dictionary maps that +key to the value according to the last dictionary on the command line +containing a mapping for that key. +.TP \fBdict remove \fIdictionaryValue \fR?\fIkey ...\fR? Return a new dictionary that is a copy of an old one passed in as first argument except without mappings for each of the keys listed. diff --git a/generic/tclDictObj.c b/generic/tclDictObj.c index 8755d4e..bbbc156 100644 --- a/generic/tclDictObj.c +++ b/generic/tclDictObj.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclDictObj.c,v 1.14 2004/01/14 22:07:43 dkf Exp $ + * RCS: @(#) $Id: tclDictObj.c,v 1.15 2004/03/12 23:21:05 dkf Exp $ */ #include "tclInt.h" @@ -56,6 +56,8 @@ static int DictKeysCmd _ANSI_ARGS_((Tcl_Interp *interp, int objc, Tcl_Obj *CONST *objv)); static int DictLappendCmd _ANSI_ARGS_((Tcl_Interp *interp, int objc, Tcl_Obj *CONST *objv)); +static int DictMergeCmd _ANSI_ARGS_((Tcl_Interp *interp, + int objc, Tcl_Obj *CONST *objv)); static int DictRemoveCmd _ANSI_ARGS_((Tcl_Interp *interp, int objc, Tcl_Obj *CONST *objv)); static int DictReplaceCmd _ANSI_ARGS_((Tcl_Interp *interp, @@ -1467,6 +1469,89 @@ DictRemoveCmd(interp, objc, objv) /* *---------------------------------------------------------------------- * + * DictMergeCmd -- + * + * This function implements the "dict merge" Tcl command. + * See the user documentation for details on what it does, and + * TIP#163 for the formal specification. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +DictMergeCmd(interp, objc, objv) + Tcl_Interp *interp; + int objc; + Tcl_Obj *CONST *objv; +{ + Tcl_Obj *targetObj, *keyObj, *valueObj; + int allocatedDict = 0; + int i, done; + Tcl_DictSearch search; + + if (objc == 2) { + /* + * No dictionary arguments; return default (empty value). + */ + return TCL_OK; + } + + if (objc == 3) { + /* + * Single argument, make sure it is a dictionary, but + * otherwise return it. + */ + if (objv[2]->typePtr != &tclDictType) { + if (SetDictFromAny(interp, objv[2]) != TCL_OK) { + return TCL_ERROR; + } + } + Tcl_SetObjResult(interp, objv[2]); + return TCL_OK; + } + + /* + * Normal behaviour: combining two (or more) dictionaries. + */ + + targetObj = objv[2]; + if (Tcl_IsShared(targetObj)) { + targetObj = Tcl_DuplicateObj(targetObj); + allocatedDict = 1; + } + for (i=3 ; i