diff options
author | dgp <dgp@users.sourceforge.net> | 2017-06-08 21:15:25 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2017-06-08 21:15:25 (GMT) |
commit | 9858231309132643a953411c3305a979d329a248 (patch) | |
tree | e13ed16b360eaf1e67674e6d31071cee64b87b68 | |
parent | 6e4aac3d59436016f5fe349d8e8c7e141640c425 (diff) | |
parent | d6fff27296f668ac9cb89dda2fc6732634c19424 (diff) | |
download | tcl-9858231309132643a953411c3305a979d329a248.zip tcl-9858231309132643a953411c3305a979d329a248.tar.gz tcl-9858231309132643a953411c3305a979d329a248.tar.bz2 |
Another TclStringCatObjv optimization to delay/avoid string rep generation.
-rw-r--r-- | generic/tclStringObj.c | 38 | ||||
-rw-r--r-- | tests/string.test | 30 |
2 files changed, 57 insertions, 11 deletions
diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index aae52ba..aa99545 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -2916,10 +2916,10 @@ TclStringCatObjv( last = objc - oc; if (length == 0) { first = last; - } - if ((length += numBytes) < 0) { + } else if (numBytes > INT_MAX - length) { goto overflow; } + length += numBytes; } } } while (--oc); @@ -2937,14 +2937,16 @@ TclStringCatObjv( last = objc - oc; if (length == 0) { first = last; - } - if ((length += numChars) < 0) { + } else if (numChars > INT_MAX - length) { goto overflow; } + length += numChars; } } } while (--oc); } else { + Tcl_Obj *pendingPtr = NULL; + /* Result will be concat of string reps. Pre-size it. */ ov = objv; oc = objc; do { @@ -2952,15 +2954,29 @@ TclStringCatObjv( objPtr = *ov++; - Tcl_GetStringFromObj(objPtr, &numBytes); /* PANIC? */ - if (numBytes) { + if ((length == 0) && (objPtr->bytes == NULL) && !pendingPtr) { + /* No string rep; Take the chance we can avoid making it */ + + last = objc - oc; + first = last; + pendingPtr = objPtr; + } else { + + Tcl_GetStringFromObj(objPtr, &numBytes); /* PANIC? */ + if (numBytes == 0) { + continue; + } last = objc - oc; + if (pendingPtr) { + Tcl_GetStringFromObj(pendingPtr, &length); /* PANIC? */ + pendingPtr = NULL; + } if (length == 0) { first = last; - } - if ((length += numBytes) < 0) { + } else if (numBytes > INT_MAX - length) { goto overflow; } + length += numBytes; } } while (--oc); } @@ -3073,9 +3089,9 @@ TclStringCatObjv( return TCL_ERROR; } dst = Tcl_GetString(objResultPtr) + start; - if (length > start) { - TclFreeIntRep(objResultPtr); - } + + /* assert ( length > start ) */ + TclFreeIntRep(objResultPtr); } else { objResultPtr = Tcl_NewObj(); /* PANIC? */ if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) { diff --git a/tests/string.test b/tests/string.test index fa7f8fb..9c43f29 100644 --- a/tests/string.test +++ b/tests/string.test @@ -1994,6 +1994,36 @@ test string-29.4 {string cat, many args} { set r2 [string compare $xx [eval "string cat $vvs"]] list $r1 $r2 } {0 0} +test string-29.5 {string cat, efficiency} -body { + tcl::unsupported::representation [string cat [list x] [list]] +} -match glob -result {*no string representation} +test string-29.6 {string cat, efficiency} -body { + tcl::unsupported::representation [string cat [list] [list x]] +} -match glob -result {*no string representation} +test string-29.7 {string cat, efficiency} -body { + tcl::unsupported::representation [string cat [list x] [list] [list]] +} -match glob -result {*no string representation} +test string-29.8 {string cat, efficiency} -body { + tcl::unsupported::representation [string cat [list] [list x] [list]] +} -match glob -result {*no string representation} +test string-29.9 {string cat, efficiency} -body { + tcl::unsupported::representation [string cat [list] [list] [list x]] +} -match glob -result {*no string representation} +test string-29.10 {string cat, efficiency} -body { + tcl::unsupported::representation [string cat [list x] [list x]] +} -match glob -result {*, string representation "xx"} +test string-29.11 {string cat, efficiency} -body { + tcl::unsupported::representation \ + [string cat [list x] [encoding convertto utf-8 {}]] +} -match glob -result {*no string representation} +test string-29.12 {string cat, efficiency} -body { + tcl::unsupported::representation \ + [string cat [encoding convertto utf-8 {}] [list x]] +} -match glob -result {*, string representation "x"} +test string-29.13 {string cat, efficiency} -body { + tcl::unsupported::representation [string cat \ + [encoding convertto utf-8 {}] [encoding convertto utf-8 {}] [list x]] +} -match glob -result {*, string representation "x"} |