summaryrefslogtreecommitdiffstats
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
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.
-rw-r--r--ChangeLog7
-rw-r--r--generic/tclStringObj.c39
2 files changed, 30 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index f852e57..00dc9c4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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) {