summaryrefslogtreecommitdiffstats
path: root/generic/tclStringObj.c
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2009-02-18 18:31:36 (GMT)
committerdgp <dgp@users.sourceforge.net>2009-02-18 18:31:36 (GMT)
commit22bb1e220dfeb679e0f7985503d2ab229694e35a (patch)
tree4354bc2f40d49480e8eae961ca7085a75a20403c /generic/tclStringObj.c
parenta0395ee4d5dd6b0c16c1ed5ce76395a28572f407 (diff)
downloadtcl-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.
Diffstat (limited to 'generic/tclStringObj.c')
-rw-r--r--generic/tclStringObj.c39
1 files changed, 23 insertions, 16 deletions
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) {