summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2009-02-17 06:52:05 (GMT)
committerdgp <dgp@users.sourceforge.net>2009-02-17 06:52:05 (GMT)
commit28f3aa0a8e86ea3ecd2e2699fa20fd08c6c22763 (patch)
tree8dd7fb6f7376bd56e7e06287edde8a430e34a016
parent6c8a61b4c4ced636c66d653d11459edac7232d74 (diff)
downloadtcl-28f3aa0a8e86ea3ecd2e2699fa20fd08c6c22763.zip
tcl-28f3aa0a8e86ea3ecd2e2699fa20fd08c6c22763.tar.gz
tcl-28f3aa0a8e86ea3ecd2e2699fa20fd08c6c22763.tar.bz2
* generic/tclStringObj.c: Revise buffer growth implementation
in ExtendStringRepWithUnicode. Use cheap checks to determine that no reallocation is necessary without cost of computing the precise number of bytes needed. Also make use of the string growth algortihm in the case of repeated appends.
-rw-r--r--ChangeLog22
-rw-r--r--generic/tclStringObj.c45
2 files changed, 46 insertions, 21 deletions
diff --git a/ChangeLog b/ChangeLog
index b896f98..a51a52c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,15 +1,21 @@
-2009-02-16 Jan Nijtmans <nijtmans@users.sf.net>
+2009-02-17 Don Porter <dgp@users.sourceforge.net>
- * generic/tclZlib.c hack needed for official zlib1.dll build.
- * win/configure.in fix [Feature Request 2605263] use official
- * win/Makefile.in zlib build.
- * win/configure (regenerated)
- * compat/zlib/zdll.lib new files
- * compat/zlib/zlib1.dll
+ * generic/tclStringObj.c: Revise buffer growth implementation
+ in ExtendStringRepWithUnicode. Use cheap checks to determine that
+ no reallocation is necessary without cost of computing the precise
+ number of bytes needed. Also make use of the string growth algortihm
+ in the case of repeated appends.
2009-02-16 Jan Nijtmans <nijtmans@users.sf.net>
- * win/Makefile.in fix [Bug 2605232] tdbc doesn't build when
+ * generic/tclZlib.c: hack needed for official zlib1.dll build.
+ * win/configure.in: fix [Feature Request 2605263] use official
+ * win/Makefile.in: zlib build.
+ * win/configure: (regenerated)
+ * compat/zlib/zdll.lib: new files
+ * compat/zlib/zlib1.dll:
+
+ * win/Makefile.in: fix [Bug 2605232] tdbc doesn't build when
Tcl is compiled with --disable-shared.
2009-02-15 Don Porter <dgp@users.sourceforge.net>
diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c
index ecea7be..52e6019 100644
--- a/generic/tclStringObj.c
+++ b/generic/tclStringObj.c
@@ -33,7 +33,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclStringObj.c,v 1.109 2009/02/16 04:06:07 dgp Exp $ */
+ * RCS: @(#) $Id: tclStringObj.c,v 1.110 2009/02/17 06:52:05 dgp Exp $ */
#include "tclInt.h"
#include "tommath.h"
@@ -2897,7 +2897,7 @@ ExtendStringRepWithUnicode(
const Tcl_UniChar *unicode,
int numChars)
{
- int i, size = 0;
+ int i, origLength, size = 0;
char *dst, buf[TCL_UTF_MAX];
/* Pre-condition: this is the "string" Tcl_ObjType */
@@ -2918,12 +2918,13 @@ ExtendStringRepWithUnicode(
} else {
objPtr->length = 0;
}
+ origLength = objPtr->length;
- /*
- * TODO: Consider fast overallocation of numChars*TCL_UTF_MAX bytes.
- * Then we could make one pass instead of two. Trade away memory
- * efficiency for speed.
- */
+ /* Quick cheap check in case we have more than enough room. */
+ if (numChars <= (INT_MAX - size)/TCL_UTF_MAX
+ && stringPtr->allocated >= size + numChars * TCL_UTF_MAX) {
+ goto copyBytes;
+ }
for (i = 0; i < numChars && size >= 0; i++) {
size += Tcl_UniCharToUtf((int) unicode[i], buf);
@@ -2934,16 +2935,34 @@ ExtendStringRepWithUnicode(
/* Grow space if needed */
if (size > stringPtr->allocated) {
- /* TODO: Growth algorithm for appends ? */
- objPtr->bytes = ckrealloc(objPtr->bytes, (unsigned) size+1);
- stringPtr->allocated = size;
+ if (stringPtr->allocated == 0) {
+ /* First allocation - just big enough */
+ objPtr->bytes = ckrealloc(objPtr->bytes, (unsigned) size+1);
+ stringPtr->allocated = size;
+ } else {
+ /* Subsequent appends - apply the growth algorithm. */
+ if (Tcl_AttemptSetObjLength(objPtr, 2 * size) == 0) {
+ /*
+ * Take care computing the amount of modest growth to avoid
+ * overflow into invalid argument values for Tcl_SetObjLength.
+ */
+ unsigned int limit = INT_MAX - size;
+ unsigned int extra = size - objPtr->length
+ + TCL_GROWTH_MIN_ALLOC;
+ int growth = (int) ((extra > limit) ? limit : extra);
+
+ Tcl_SetObjLength(objPtr, size + growth);
+ }
+ }
}
- dst = objPtr->bytes + objPtr->length;
+
+ copyBytes:
+ dst = objPtr->bytes + origLength;
for (i = 0; i < numChars; i++) {
dst += Tcl_UniCharToUtf((int) unicode[i], dst);
}
- objPtr->length = size;
- objPtr->bytes[size] = '\0';
+ *dst = '\0';
+ objPtr->length = dst - objPtr->bytes;
return numChars;
}