summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2016-10-28 14:59:27 (GMT)
committerdgp <dgp@users.sourceforge.net>2016-10-28 14:59:27 (GMT)
commita9497530c8d6a3166c99286d27718957d5962261 (patch)
tree621a76c0c89e7d0b4ae0674c690157a692b463e9 /generic
parent7939b4cf6cc04a3b282df315b7d1827c47e0d61a (diff)
parent335716b81d99c7476e68979fe48b20b0f2bfeeee (diff)
downloadtcl-a9497530c8d6a3166c99286d27718957d5962261.zip
tcl-a9497530c8d6a3166c99286d27718957d5962261.tar.gz
tcl-a9497530c8d6a3166c99286d27718957d5962261.tar.bz2
When appropriate, implement [join] with the common [string cat] engine.
Diffstat (limited to 'generic')
-rw-r--r--generic/tclCmdIL.c51
1 files changed, 36 insertions, 15 deletions
diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c
index bb3c9b7..09adc8d 100644
--- a/generic/tclCmdIL.c
+++ b/generic/tclCmdIL.c
@@ -2155,8 +2155,8 @@ Tcl_JoinObjCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* The argument objects. */
{
- int listLen, i;
- Tcl_Obj *resObjPtr, *joinObjPtr, **elemPtrs;
+ int listLen;
+ Tcl_Obj *resObjPtr = NULL, *joinObjPtr, **elemPtrs;
if ((objc < 2) || (objc > 3)) {
Tcl_WrongNumArgs(interp, 1, objv, "list ?joinString?");
@@ -2173,27 +2173,48 @@ Tcl_JoinObjCmd(
return TCL_ERROR;
}
+ if (listLen == 0) {
+ /* No elements to join; default empty result is correct. */
+ return TCL_OK;
+ }
+ if (listLen == 1) {
+ /* One element; return it */
+ Tcl_SetObjResult(interp, elemPtrs[0]);
+ return TCL_OK;
+ }
+
joinObjPtr = (objc == 2) ? Tcl_NewStringObj(" ", 1) : objv[2];
Tcl_IncrRefCount(joinObjPtr);
- resObjPtr = Tcl_NewObj();
- for (i = 0; i < listLen; i++) {
- if (i > 0) {
+ if (Tcl_GetCharLength(joinObjPtr) == 0) {
+ Tcl_IncrRefCount(elemPtrs[0]);
+ TclStringCatObjv(interp, listLen, elemPtrs, &resObjPtr);
+ Tcl_DecrRefCount(elemPtrs[0]);
+ } else {
+ int i;
- /*
- * NOTE: This code is relying on Tcl_AppendObjToObj() **NOT**
- * to shimmer joinObjPtr. If it did, then the case where
- * objv[1] and objv[2] are the same value would not be safe.
- * Accessing elemPtrs would crash.
- */
+ resObjPtr = Tcl_NewObj();
+ for (i = 0; i < listLen; i++) {
+ if (i > 0) {
- Tcl_AppendObjToObj(resObjPtr, joinObjPtr);
+ /*
+ * NOTE: This code is relying on Tcl_AppendObjToObj() **NOT**
+ * to shimmer joinObjPtr. If it did, then the case where
+ * objv[1] and objv[2] are the same value would not be safe.
+ * Accessing elemPtrs would crash.
+ */
+
+ Tcl_AppendObjToObj(resObjPtr, joinObjPtr);
+ }
+ Tcl_AppendObjToObj(resObjPtr, elemPtrs[i]);
}
- Tcl_AppendObjToObj(resObjPtr, elemPtrs[i]);
}
Tcl_DecrRefCount(joinObjPtr);
- Tcl_SetObjResult(interp, resObjPtr);
- return TCL_OK;
+ if (resObjPtr) {
+ Tcl_SetObjResult(interp, resObjPtr);
+ return TCL_OK;
+ }
+ return TCL_ERROR;
}
/*