diff options
author | dgp <dgp@users.sourceforge.net> | 2009-02-18 18:31:36 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2009-02-18 18:31:36 (GMT) |
commit | 22bb1e220dfeb679e0f7985503d2ab229694e35a (patch) | |
tree | 4354bc2f40d49480e8eae961ca7085a75a20403c | |
parent | a0395ee4d5dd6b0c16c1ed5ce76395a28572f407 (diff) | |
download | tcl-22bb1e220dfeb679e0f7985503d2ab229694e35a.zip tcl-22bb1e220dfeb679e0f7985503d2ab229694e35a.tar.gz tcl-22bb1e220dfeb679e0f7985503d2ab229694e35a.tar.bz2 |
* generic/tclStringObj.c: Rewrite GrowStringBuffer() so that it
has parallel structure with GrowUnicodeBuffer(). The revision permits
allocation attempts to continue all the way up to failure, with no gap.
It also directly manipulates the String and Tcl_Obj internals instead
of inefficiently operating via Tcl_*SetObjLength() with all of its
extra protections and underdocumented special cases.
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | generic/tclStringObj.c | 39 |
2 files changed, 30 insertions, 16 deletions
@@ -1,5 +1,12 @@ 2009-02-18 Don Porter <dgp@users.sourceforge.net> + * generic/tclStringObj.c: Rewrite GrowStringBuffer() so that it + has parallel structure with GrowUnicodeBuffer(). The revision permits + allocation attempts to continue all the way up to failure, with no gap. + It also directly manipulates the String and Tcl_Obj internals instead + of inefficiently operating via Tcl_*SetObjLength() with all of its + extra protections and underdocumented special cases. + * generic/tclStringObj.c: Another round of simplification on the allocation macros. diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 5707c50..24ae5ef 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.115 2009/02/18 17:45:35 dgp Exp $ */ + * RCS: @(#) $Id: tclStringObj.c,v 1.116 2009/02/18 18:31:55 dgp Exp $ */ #include "tclInt.h" #include "tommath.h" @@ -198,29 +198,36 @@ GrowStringBuffer( * flag || objPtr->bytes != NULL */ String *stringPtr = GET_STRING(objPtr); + char *ptr = NULL; + int attempt; - if (flag && stringPtr->allocated == 0) { - /* First allocation - just big enough */ - if (objPtr->bytes == tclEmptyStringRep) { - objPtr->bytes = ckalloc((unsigned) needed + 1); - } else { - objPtr->bytes = ckrealloc(objPtr->bytes, (unsigned) needed + 1); + if (objPtr->bytes == tclEmptyStringRep) { + objPtr->bytes = NULL; + } + if (flag == 0 || stringPtr->allocated > 0) { + attempt = 2 * needed; + if (attempt >= 0) { + ptr = attemptckrealloc(objPtr->bytes, (unsigned) attempt + 1); } - stringPtr->allocated = needed; - } else { - /* Subsequent appends - apply the growth algorithm. */ - if (Tcl_AttemptSetObjLength(objPtr, 2 * needed) == 0) { + if (ptr == NULL) { /* * Take care computing the amount of modest growth to avoid - * overflow into invalid argument values for Tcl_SetObjLength. + * overflow into invalid argument values for attempt. */ unsigned int limit = INT_MAX - needed; unsigned int extra = needed - objPtr->length + TCL_GROWTH_MIN_ALLOC; int growth = (int) ((extra > limit) ? limit : extra); - - Tcl_SetObjLength(objPtr, needed + growth); + attempt = needed + growth; + ptr = attemptckrealloc(objPtr->bytes, (unsigned) attempt + 1); } } + if (ptr == NULL) { + /* First allocation - just big enough; or last chance fallback. */ + attempt = needed; + ptr = ckrealloc(objPtr->bytes, (unsigned) attempt + 1); + } + objPtr->bytes = ptr; + stringPtr->allocated = attempt; } static void @@ -1548,10 +1555,10 @@ AppendUtfToUtfRep( */ oldLength = objPtr->length; - if (numBytes > INT_MAX - oldLength) { + newLength = numBytes + oldLength; + if (newLength < 0) { Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX); } - newLength = numBytes + oldLength; stringPtr = GET_STRING(objPtr); if (newLength > stringPtr->allocated) { |