diff options
author | Miguel Sofer <miguel.sofer@gmail.com> | 2007-10-28 03:16:58 (GMT) |
---|---|---|
committer | Miguel Sofer <miguel.sofer@gmail.com> | 2007-10-28 03:16:58 (GMT) |
commit | 8ffb8fa76d0d34283e491044dd28385674ba113e (patch) | |
tree | 50acad715b96fb0ad0e4ef8f93ba47de420c91ba /generic | |
parent | 6875fa13ed77ee3b9fbd8277365f570919300bc5 (diff) | |
download | tcl-8ffb8fa76d0d34283e491044dd28385674ba113e.zip tcl-8ffb8fa76d0d34283e491044dd28385674ba113e.tar.gz tcl-8ffb8fa76d0d34283e491044dd28385674ba113e.tar.bz2 |
* generic/tclUtil.c (Tcl_ConcatObj): optimise for some of the
concatenees being empty objs [Bug 1447328]
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclUtil.c | 51 |
1 files changed, 38 insertions, 13 deletions
diff --git a/generic/tclUtil.c b/generic/tclUtil.c index 6a25141..54e8a04 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclUtil.c,v 1.83 2007/10/15 21:27:48 dgp Exp $ + * RCS: @(#) $Id: tclUtil.c,v 1.84 2007/10/28 03:17:00 msofer Exp $ */ #include "tclInt.h" @@ -1145,14 +1145,15 @@ Tcl_ConcatObj( char *p; char *element; char *concatStr; - Tcl_Obj *objPtr; + Tcl_Obj *objPtr, *resPtr; /* - * Check first to see if all the items are of list type. If so, we will - * concat them together as lists, and return a list object. This is only - * valid when the lists have no current string representation, since we - * don't know what the original type was. An original string rep may have - * lost some whitespace info when converted which could be important. + * Check first to see if all the items are of list type or empty. If so, + * we will concat them together as lists, and return a list object. This + * is only valid when the lists have no current string representation, + * since we don't know what the original type was. An original string rep + * may have lost some whitespace info when converted which could be + * important. */ for (i = 0; i < objc; i++) { @@ -1160,7 +1161,12 @@ Tcl_ConcatObj( objPtr = objv[i]; if (objPtr->typePtr != &tclListType) { - break; + Tcl_GetString(objPtr); + if (objPtr->length) { + break; + } else { + continue; + } } listRepPtr = (List *) objPtr->internalRep.twoPtrValue.ptr1; if (objPtr->bytes != NULL && !listRepPtr->canonicalFlag) { @@ -1171,19 +1177,38 @@ Tcl_ConcatObj( Tcl_Obj **listv; int listc; - objPtr = Tcl_NewListObj(0, NULL); + resPtr = NULL; for (i = 0; i < objc; i++) { /* * Tcl_ListObjAppendList could be used here, but this saves us a * bit of type checking (since we've already done it). Use of * INT_MAX tells us to always put the new stuff on the end. It * will be set right in Tcl_ListObjReplace. + * Note that all objs at this point are either lists or have an + * empty string rep. */ - - Tcl_ListObjGetElements(NULL, objv[i], &listc, &listv); - Tcl_ListObjReplace(NULL, objPtr, INT_MAX, 0, listc, listv); + + objPtr = objv[i]; + if (objPtr->bytes && !objPtr->length) { + continue; + } + Tcl_ListObjGetElements(NULL, objPtr, &listc, &listv); + if (listc) { + if (resPtr) { + Tcl_ListObjReplace(NULL, resPtr, INT_MAX, 0, listc, listv); + } else { + if (Tcl_IsShared(objPtr)) { + resPtr = TclListObjCopy(NULL, objPtr); + } else { + resPtr = objPtr; + } + } + } + } + if (!resPtr) { + resPtr = Tcl_NewObj(); } - return objPtr; + return resPtr; } /* |