diff options
author | dgp <dgp@users.sourceforge.net> | 2009-02-17 06:52:05 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2009-02-17 06:52:05 (GMT) |
commit | 28f3aa0a8e86ea3ecd2e2699fa20fd08c6c22763 (patch) | |
tree | 8dd7fb6f7376bd56e7e06287edde8a430e34a016 | |
parent | 6c8a61b4c4ced636c66d653d11459edac7232d74 (diff) | |
download | tcl-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-- | ChangeLog | 22 | ||||
-rw-r--r-- | generic/tclStringObj.c | 45 |
2 files changed, 46 insertions, 21 deletions
@@ -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; } |