summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorapnadkarni <apnmbx-wits@yahoo.com>2023-05-19 16:47:58 (GMT)
committerapnadkarni <apnmbx-wits@yahoo.com>2023-05-19 16:47:58 (GMT)
commit16a75f3cbf8ba7ab30d4f5f1adcd658269d9ae8c (patch)
tree05034cc48612753645a36939be59d920c22055b8
parent6fa73194d556765f6a8dfe33c0f609377d5fb41c (diff)
downloadtcl-16a75f3cbf8ba7ab30d4f5f1adcd658269d9ae8c.zip
tcl-16a75f3cbf8ba7ab30d4f5f1adcd658269d9ae8c.tar.gz
tcl-16a75f3cbf8ba7ab30d4f5f1adcd658269d9ae8c.tar.bz2
More refactoring into common code
-rw-r--r--generic/tclBinary.c29
-rw-r--r--generic/tclCkalloc.c238
-rw-r--r--generic/tclInt.h43
-rw-r--r--generic/tclListObj.c61
-rw-r--r--generic/tclStringObj.c60
-rw-r--r--generic/tclUtil.c12
6 files changed, 234 insertions, 209 deletions
diff --git a/generic/tclBinary.c b/generic/tclBinary.c
index 4215913..81ea3f3 100644
--- a/generic/tclBinary.c
+++ b/generic/tclBinary.c
@@ -767,27 +767,14 @@ TclAppendBytesToByteArray(
}
needed = byteArrayPtr->used + len;
if (needed > byteArrayPtr->allocated) {
- ByteArray *ptr = NULL;
- Tcl_Size attempt;
-
- /* First try to overallocate, reducing overallocation on each fail */
- attempt =
- TclUpsizeAlloc(byteArrayPtr->allocated, needed, BYTEARRAY_MAX_LEN);
- while (attempt > needed) {
- ptr = (ByteArray *)Tcl_AttemptRealloc(byteArrayPtr,
- BYTEARRAY_SIZE(attempt));
- if (ptr)
- break;
- attempt = TclUpsizeRetry(needed, attempt);
- }
-
- if (ptr == NULL) {
- /* Last chance: Try to allocate exactly what is needed. */
- attempt = needed;
- ptr = (ByteArray *)Tcl_Realloc(byteArrayPtr, BYTEARRAY_SIZE(attempt));
- }
- byteArrayPtr = ptr;
- byteArrayPtr->allocated = attempt;
+ Tcl_Size newCapacity;
+ byteArrayPtr =
+ (ByteArray *)TclReallocElemsEx(byteArrayPtr,
+ needed,
+ 1,
+ offsetof(ByteArray, bytes),
+ &newCapacity);
+ byteArrayPtr->allocated = newCapacity;
SET_BYTEARRAY(irPtr, byteArrayPtr);
}
diff --git a/generic/tclCkalloc.c b/generic/tclCkalloc.c
index 1539f4f..6aabf9f 100644
--- a/generic/tclCkalloc.c
+++ b/generic/tclCkalloc.c
@@ -16,6 +16,7 @@
*/
#include "tclInt.h"
+#include <assert.h>
#define FALSE 0
#define TRUE 1
@@ -1194,40 +1195,99 @@ Tcl_DbCkfree(
}
/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_InitMemory --
+ *
+ * Dummy initialization for memory command, which is only available if
+ * TCL_MEM_DEBUG is on.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+Tcl_InitMemory(
+ TCL_UNUSED(Tcl_Interp *) /*interp*/)
+{
+}
+
+int
+Tcl_DumpActiveMemory(
+ TCL_UNUSED(const char *) /*fileName*/)
+{
+ return TCL_OK;
+}
+
+void
+Tcl_ValidateAllMemory(
+ TCL_UNUSED(const char *) /*file*/,
+ TCL_UNUSED(int) /*line*/)
+{
+}
+
+int
+TclDumpMemoryInfo(
+ TCL_UNUSED(void *),
+ TCL_UNUSED(int) /*flags*/)
+{
+ return 1;
+}
+
+#endif /* TCL_MEM_DEBUG */
+
+/*
*------------------------------------------------------------------------
*
- * TclAttemptOverAlloc --
+ * TclAttemptAllocElemsEx --
*
- * Attempts to allocates memory of the requested size plus some more for
- * future growth.
+ * Attempts to allocate memory of the requested size plus some more for
+ * future growth. The amount of allocation is adjusted depending on
+ * on failure.
*
* Results:
- * Pointer to allocated memory block which is at least as large
- * as the requested size or NULL if allocation failed.
+ * Pointer to allocated memory block which is at least large enough
+ * to hold elemCount elements or NULL if allocation failed.
*
*------------------------------------------------------------------------
*/
void *
-TclAttemptOverAlloc(
- Tcl_Size needed, /* Requested size */
- Tcl_Size *allocatedPtr) /* OUTPUT: Actual allocation size is stored
- here if non-NULL. Only modified on success */
+TclAttemptAllocElemsEx(
+ Tcl_Size elemCount, /* Allocation will store at least these many... */
+ Tcl_Size elemSize, /* ...elements of this size */
+ Tcl_Size leadSize, /* Additional leading space in bytes */
+ Tcl_Size *capacityPtr) /* OUTPUT: Actual capacity is stored
+ here if non-NULL. Only modified on success */
{
void *ptr;
- Tcl_Size attempt = TclUpsizeAlloc(0, needed, TCL_SIZE_MAX);
- while (attempt > needed) {
- ptr = Tcl_AttemptAlloc(attempt);
- if (ptr)
+ Tcl_Size limit;
+ Tcl_Size attempt;
+
+ assert(elemCount > 0);
+ assert(elemSize > 0);
+ assert(elemSize < TCL_SIZE_MAX);
+ assert(leadSize > 0);
+ assert(leadSize < TCL_SIZE_MAX);
+
+ limit = (TCL_SIZE_MAX - leadSize) / elemSize;
+ if (elemCount > limit) {
+ return NULL;
+ }
+ /* Loop trying for extra space, reducing request each time */
+ attempt = TclUpsizeAlloc(0, elemCount, limit);
+ ptr = NULL;
+ while (attempt > elemCount) {
+ ptr = Tcl_AttemptAlloc(leadSize + attempt*elemSize);
+ if (ptr) {
break;
- attempt = TclUpsizeRetry(needed, attempt);
+ }
+ attempt = TclUpsizeRetry(elemCount, attempt);
}
+ /* Try exact size as a last resort */
if (ptr == NULL) {
- /* Try exact size as a last resort */
- attempt = needed;
- ptr = Tcl_AttemptAlloc(attempt);
+ attempt = elemCount;
+ ptr = Tcl_AttemptAlloc(leadSize + attempt*elemSize);
}
- if (ptr && allocatedPtr) {
- *allocatedPtr = attempt;
+ if (ptr && capacityPtr) {
+ *capacityPtr = attempt;
}
return ptr;
}
@@ -1235,14 +1295,13 @@ TclAttemptOverAlloc(
/*
*------------------------------------------------------------------------
*
- * TclOverAlloc --
+ * TclAllocElemsEx --
*
- * Allocates memory of the requested size plus some more for future
- * growth.
+ * See TclAttemptAllocElemsEx. This function differs in that it panics
+ * on failure.
*
* Results:
- * Non-NULL pointer to allocated memory block which is at least as large
- * as the requested size.
+ * Non-NULL pointer to allocated memory block.
*
* Side effects:
* Panics if memory of at least the requested size could not be
@@ -1251,11 +1310,20 @@ TclAttemptOverAlloc(
*------------------------------------------------------------------------
*/
void *
-TclOverAlloc(Tcl_Size needed, Tcl_Size *allocatedPtr)
+TclAllocElemsEx(
+ Tcl_Size elemCount, /* Allocation will store at least these many... */
+ Tcl_Size elemSize, /* ...elements of this size */
+ Tcl_Size leadSize, /* Additional leading space in bytes */
+ Tcl_Size *capacityPtr) /* OUTPUT: Actual capacity is stored
+ here if non-NULL. Only modified on success */
{
- void *ptr = TclAttemptOverAlloc(needed, allocatedPtr);
+ void *ptr = TclAttemptAllocElemsEx(
+ elemCount, elemSize, leadSize, capacityPtr);
if (ptr == NULL) {
- Tcl_Panic("Failed to allocate %" TCL_SIZE_MODIFIER "d bytes.", needed);
+ Tcl_Panic("Failed to allocate %" TCL_SIZE_MODIFIER
+ "d elements of size %" TCL_SIZE_MODIFIER "d bytes.",
+ elemCount,
+ elemSize);
}
return ptr;
}
@@ -1263,10 +1331,11 @@ TclOverAlloc(Tcl_Size needed, Tcl_Size *allocatedPtr)
/*
*------------------------------------------------------------------------
*
- * TclAttemptOverRealloc --
+ * TclAttemptReallocElemsEx --
*
* Attempts to reallocate memory of the requested size plus some more for
- * future growth.
+ * future growth. The amount of reallocation is adjusted depending on
+ * on failure.
*
* Results:
* Pointer to allocated memory block which is at least as large
@@ -1275,28 +1344,45 @@ TclOverAlloc(Tcl_Size needed, Tcl_Size *allocatedPtr)
*------------------------------------------------------------------------
*/
void *
-TclAttemptOverRealloc(
- Tcl_Size needed, /* Requested size */
+TclAttemptReallocElemsEx(
void *oldPtr, /* Pointer to memory block to reallocate */
- Tcl_Size oldSize, /* Old size if known, or 0 if unknown */
- Tcl_Size *allocatedPtr) /* OUTPUT: Actual allocation size is stored
+ Tcl_Size elemCount, /* Allocation will store at least these many... */
+ Tcl_Size elemSize, /* ...elements of this size */
+ Tcl_Size leadSize, /* Additional leading space in bytes */
+ Tcl_Size *capacityPtr) /* OUTPUT: Actual capacity is stored
here if non-NULL. Only modified on success */
{
void *ptr;
- Tcl_Size attempt = TclUpsizeAlloc(oldSize, needed, TCL_SIZE_MAX);
- while (attempt > needed) {
- ptr = Tcl_AttemptRealloc(oldPtr, attempt);
- if (ptr)
+ Tcl_Size limit;
+ Tcl_Size attempt;
+
+ assert(elemCount > 0);
+ assert(elemSize > 0);
+ assert(elemSize < TCL_SIZE_MAX);
+ assert(leadSize > 0);
+ assert(leadSize < TCL_SIZE_MAX);
+
+ limit = (TCL_SIZE_MAX - leadSize) / elemSize;
+ if (elemCount > limit) {
+ return NULL;
+ }
+ /* Loop trying for extra space, reducing request each time */
+ attempt = TclUpsizeAlloc(0, elemCount, limit);
+ ptr = NULL;
+ while (attempt > elemCount) {
+ ptr = Tcl_AttemptRealloc(oldPtr, leadSize + attempt*elemSize);
+ if (ptr) {
break;
- attempt = TclUpsizeRetry(needed, attempt);
+ }
+ attempt = TclUpsizeRetry(elemCount, attempt);
}
+ /* Try exact size as a last resort */
if (ptr == NULL) {
- /* Try exact size as a last resort */
- attempt = needed;
- ptr = Tcl_AttemptRealloc(oldPtr, attempt);
+ attempt = elemCount;
+ ptr = Tcl_AttemptRealloc(oldPtr, leadSize + attempt*elemSize);
}
- if (ptr && allocatedPtr) {
- *allocatedPtr = attempt;
+ if (ptr && capacityPtr) {
+ *capacityPtr = attempt;
}
return ptr;
}
@@ -1304,14 +1390,13 @@ TclAttemptOverRealloc(
/*
*------------------------------------------------------------------------
*
- * TclOverRealloc --
+ * TclReallocElemsEx --
*
- * Reallocates memory of the requested size plus some more for future
- * growth.
+ * See TclAttemptReallocElemsEx. This function differs in that it panics
+ * on failure.
*
* Results:
- * Non-NULL pointer to allocated memory block which is at least as large
- * as the requested size.
+ * Non-NULL pointer to allocated memory block.
*
* Side effects:
* Panics if memory of at least the requested size could not be
@@ -1320,61 +1405,26 @@ TclAttemptOverRealloc(
*------------------------------------------------------------------------
*/
void *
-TclOverRealloc(
- Tcl_Size needed, /* Requested size */
+TclReallocElemsEx(
void *oldPtr, /* Pointer to memory block to reallocate */
- Tcl_Size oldSize, /* Old size if known, or 0 if unknown */
- Tcl_Size *allocatedPtr) /* OUTPUT: Actual allocation size is stored
+ Tcl_Size elemCount, /* Allocation will store at least these many... */
+ Tcl_Size elemSize, /* ...elements of this size */
+ Tcl_Size leadSize, /* Additional leading space in bytes */
+ Tcl_Size *capacityPtr) /* OUTPUT: Actual capacity is stored
here if non-NULL. Only modified on success */
{
- void *ptr = TclAttemptOverRealloc(needed, oldPtr, oldSize, allocatedPtr);
+ void *ptr = TclAttemptReallocElemsEx(
+ oldPtr, elemCount, elemSize, leadSize, capacityPtr);
if (ptr == NULL) {
- Tcl_Panic("Failed to reallocate %" TCL_SIZE_MODIFIER "d bytes.", needed);
+ Tcl_Panic("Failed to reallocate %" TCL_SIZE_MODIFIER
+ "d elements of size %" TCL_SIZE_MODIFIER "d bytes.",
+ elemCount,
+ elemSize);
}
return ptr;
}
/*
- *----------------------------------------------------------------------
- *
- * Tcl_InitMemory --
- *
- * Dummy initialization for memory command, which is only available if
- * TCL_MEM_DEBUG is on.
- *
- *----------------------------------------------------------------------
- */
-void
-Tcl_InitMemory(
- TCL_UNUSED(Tcl_Interp *) /*interp*/)
-{
-}
-
-int
-Tcl_DumpActiveMemory(
- TCL_UNUSED(const char *) /*fileName*/)
-{
- return TCL_OK;
-}
-
-void
-Tcl_ValidateAllMemory(
- TCL_UNUSED(const char *) /*file*/,
- TCL_UNUSED(int) /*line*/)
-{
-}
-
-int
-TclDumpMemoryInfo(
- TCL_UNUSED(void *),
- TCL_UNUSED(int) /*flags*/)
-{
- return 1;
-}
-
-#endif /* TCL_MEM_DEBUG */
-
-/*
*---------------------------------------------------------------------------
*
* TclFinalizeMemorySubsystem --
diff --git a/generic/tclInt.h b/generic/tclInt.h
index 56bef02..5a7c397 100644
--- a/generic/tclInt.h
+++ b/generic/tclInt.h
@@ -2873,18 +2873,19 @@ typedef struct ProcessGlobalValue {
/*
*----------------------------------------------------------------------
- * Common functions for growing allocations. Trivial but allows for
+ * Common functions for calculating overallocation. Trivial but allows for
* experimenting with growth factors without having to change code in
- * multiple places. See TclAttemptOverAlloc and TclAttemptOverRealloc for
- * usage examples. Best to use those functions if allocating in bytes.
- * Direct use of TclUpsizeAlloc / TclResizeAlloc is needed if allocating in other
- * units (say Tcl_UniChar), if there is a fixed size header involved or if
- * the max limit is something other than TCL_SIZE_MAX.
+ * multiple places. See TclAttemptAllocElemsEx and similar for usage
+ * examples. Best to use those functions. Direct use of TclUpsizeAlloc /
+ * TclResizeAlloc is needed in special cases such as when total size of
+ * memory block is limited to less than TCL_SIZE_MAX.
*
*----------------------------------------------------------------------
*/
static inline Tcl_Size
-TclUpsizeAlloc(TCL_UNUSED(Tcl_Size) /*oldSize*/,
+TclUpsizeAlloc(TCL_UNUSED(Tcl_Size) /* oldSize. For future experiments with
+ * some growth algorithms that use this
+ * information. */,
Tcl_Size needed,
Tcl_Size limit)
{
@@ -2905,12 +2906,28 @@ static inline Tcl_Size TclUpsizeRetry(Tcl_Size needed, Tcl_Size lastAttempt) {
return needed;
}
}
-MODULE_SCOPE void *TclOverAlloc(Tcl_Size needed, Tcl_Size *allocatedPtr);
-MODULE_SCOPE void *TclAttemptOverAlloc(Tcl_Size needed, Tcl_Size *allocatedPtr);
-MODULE_SCOPE void *TclOverRealloc(Tcl_Size needed, void *oldPtr,
- Tcl_Size oldSize, Tcl_Size *allocatedPtr);
-MODULE_SCOPE void *TclAttemptOverRealloc(Tcl_Size needed, void *oldPtr,
- Tcl_Size oldSize, Tcl_Size *allocatedPtr);
+MODULE_SCOPE void *TclAllocElemsEx(Tcl_Size elemCount, Tcl_Size elemSize,
+ Tcl_Size leadSize, Tcl_Size *capacityPtr);
+MODULE_SCOPE void *TclAttemptAllocElemsEx(Tcl_Size elemCount, Tcl_Size elemSize,
+ Tcl_Size leadSize, Tcl_Size *capacityPtr);
+MODULE_SCOPE void *TclReallocElemsEx(void *oldPtr, Tcl_Size elemCount,
+ Tcl_Size elemSize, Tcl_Size leadSize,
+ Tcl_Size *capacityPtr);
+MODULE_SCOPE void *TclAttemptReallocElemsEx(void *oldPtr,
+ Tcl_Size elemCount, Tcl_Size elemSize,
+ Tcl_Size leadSize, Tcl_Size *capacityPtr);
+static inline void *TclAllocEx(Tcl_Size numBytes, Tcl_Size *capacityPtr) {
+ return TclAllocElemsEx(numBytes, 1, 0, capacityPtr);
+}
+static inline void *TclAttemptAllocEx(Tcl_Size numBytes, Tcl_Size *capacityPtr) {
+ return TclAttemptAllocElemsEx(numBytes, 1, 0, capacityPtr);
+}
+static inline void *TclReallocEx(void *oldPtr, Tcl_Size numBytes, Tcl_Size *capacityPtr) {
+ return TclReallocElemsEx(oldPtr, numBytes, 1, 0, capacityPtr);
+}
+static inline void *TclAttemptReallocEx(void *oldPtr, Tcl_Size numBytes, Tcl_Size *capacityPtr) {
+ return TclAttemptReallocElemsEx(oldPtr, numBytes, 1, 0, capacityPtr);
+}
/*
*----------------------------------------------------------------
diff --git a/generic/tclListObj.c b/generic/tclListObj.c
index 4c7849d..c8464d5 100644
--- a/generic/tclListObj.c
+++ b/generic/tclListObj.c
@@ -748,29 +748,20 @@ ListStoreNew(
storePtr = NULL;
if (flags & LISTREP_SPACE_FLAGS) {
/* Caller requests extra space front, back or both */
- capacity = TclUpsizeAlloc(0, objc, LIST_MAX);
- while (capacity > objc) {
- storePtr = (ListStore *)Tcl_AttemptAlloc(LIST_SIZE(capacity));
- if (storePtr)
- break;
- capacity = TclUpsizeRetry(0, capacity);
- }
+ storePtr = (ListStore *)TclAttemptAllocElemsEx(
+ objc, sizeof(Tcl_Obj *), offsetof(ListStore, slots), &capacity);
} else {
/* Exact allocation */
capacity = objc;
+ storePtr = (ListStore *)Tcl_AttemptAlloc(LIST_SIZE(capacity));
}
if (storePtr == NULL) {
- /* Either overallocation failed or exact allocation */
- storePtr = (ListStore *)Tcl_AttemptAlloc(LIST_SIZE(capacity));
- if (storePtr == NULL) {
- if (flags & LISTREP_PANIC_ON_FAIL) {
- Tcl_Panic(
- "list creation failed: unable to alloc %" TCL_Z_MODIFIER
- "u bytes",
- LIST_SIZE(objc));
- }
- return NULL;
+ if (flags & LISTREP_PANIC_ON_FAIL) {
+ Tcl_Panic("list creation failed: unable to alloc %" TCL_Z_MODIFIER
+ "u bytes",
+ LIST_SIZE(objc));
}
+ return NULL;
}
storePtr->refCount = 0;
@@ -829,33 +820,23 @@ ListStoreNew(
ListStore *
ListStoreReallocate (ListStore *storePtr, Tcl_Size needed)
{
- Tcl_Size attempt;
- ListStore *newStorePtr;
-
- /* First try to overallocate, reducing overallocation on each fail */
- newStorePtr = NULL;
- attempt = TclUpsizeAlloc(storePtr->numAllocated, needed, LIST_MAX);
- while (attempt > needed) {
- newStorePtr =
- (ListStore *)Tcl_AttemptRealloc(storePtr, LIST_SIZE(attempt));
- if (newStorePtr)
- break;
- attempt = TclUpsizeRetry(needed, attempt);
- }
+ Tcl_Size capacity;
- if (newStorePtr == NULL) {
- /* Last resort - allcate what was asked */
- attempt = needed;
- newStorePtr = (ListStore *)Tcl_AttemptRealloc(storePtr,
- LIST_SIZE(attempt));
- if (newStorePtr == NULL)
- return NULL;
+ if (needed > LIST_MAX) {
+ return NULL;
}
+ storePtr = (ListStore *)TclAttemptReallocElemsEx(storePtr,
+ needed,
+ sizeof(Tcl_Obj *),
+ offsetof(ListStore, slots),
+ &capacity);
/* Only the capacity has changed, fix it in the header */
- newStorePtr->numAllocated = attempt;
- return newStorePtr;
+ if (storePtr) {
+ storePtr->numAllocated = capacity;
+ }
+ return storePtr;
}
-
+
/*
*----------------------------------------------------------------------
*
diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c
index 6553810..b846320 100644
--- a/generic/tclStringObj.c
+++ b/generic/tclStringObj.c
@@ -143,7 +143,7 @@ GrowStringBuffer(
String *stringPtr = GET_STRING(objPtr);
char *ptr;
- Tcl_Size attempt;
+ Tcl_Size capacity;
assert(needed <= TCL_SIZE_MAX - 1);
needed += 1; /* Include terminating nul */
@@ -152,27 +152,20 @@ GrowStringBuffer(
objPtr->bytes = NULL;
}
/*
- * In code below, note 'attempt' and 'needed' include terminating nul,
+ * In code below, note 'capacity' and 'needed' include terminating nul,
* while stringPtr->allocated does not.
*/
- ptr = NULL;
if (flag == 0 || stringPtr->allocated > 0) {
- attempt =
- TclUpsizeAlloc(stringPtr->allocated + 1, needed, TCL_SIZE_MAX);
- while (attempt > needed) {
- ptr = (char *)Tcl_AttemptRealloc(objPtr->bytes, attempt);
- if (ptr)
- break;
- attempt = TclUpsizeRetry(needed, attempt);
- }
+ ptr = (char *)TclReallocEx(objPtr->bytes, needed, &capacity);
}
- if (ptr == NULL) {
- /* First allocation - just big enough; or last chance fallback. */
- attempt = needed;
- ptr = (char *)Tcl_Realloc(objPtr->bytes, attempt);
+ else {
+ /* Allocate exact size */
+ ptr = (char *)Tcl_Realloc(objPtr->bytes, needed);
+ capacity = needed;
}
+
objPtr->bytes = ptr;
- stringPtr->allocated = attempt - 1; /* Does not include slot for end nul */
+ stringPtr->allocated = capacity - 1; /* Does not include slot for end nul */
}
static void
@@ -186,32 +179,29 @@ GrowUnicodeBuffer(
* needed > stringPtr->maxChars
*/
- String *ptr, *stringPtr = GET_STRING(objPtr);
- Tcl_Size attempt;
+ String *stringPtr = GET_STRING(objPtr);
+ Tcl_Size maxChars;
/* Note STRING_MAXCHARS already takes into account space for nul */
if (needed > STRING_MAXCHARS) {
Tcl_Panic("max size for a Tcl unicode rep (%" TCL_Z_MODIFIER "d bytes) exceeded",
STRING_MAXCHARS);
}
- ptr = NULL;
if (stringPtr->maxChars > 0) {
- /* Subsequent appends - apply the growth algorithm. */
- attempt = TclUpsizeAlloc(stringPtr->maxChars, needed, STRING_MAXCHARS);
- while (attempt > needed) {
- ptr = (String *)Tcl_AttemptRealloc(stringPtr, STRING_SIZE(attempt));
- if (ptr)
- break;
- attempt = TclUpsizeRetry(needed, attempt);
- }
- }
- if (ptr == NULL) {
- /* First allocation - just big enough; or last chance fallback. */
- attempt = needed;
- ptr = (String *)Tcl_Realloc(stringPtr, STRING_SIZE(attempt));
- }
- stringPtr = ptr;
- stringPtr->maxChars = attempt;
+ /* Expansion - try allocating extra space */
+ stringPtr = (String *)TclReallocElemsEx(stringPtr,
+ needed + 1, /* +1 for nul */
+ sizeof(Tcl_UniChar),
+ offsetof(String, unicode),
+ &maxChars);
+ maxChars -= 1; /* End nul not included */
+ }
+ else {
+ /* First allocation - just big enough */
+ stringPtr = (String *)Tcl_Realloc(stringPtr, STRING_SIZE(needed));
+ maxChars = needed;
+ }
+ stringPtr->maxChars = maxChars;
SET_STRING(objPtr, stringPtr);
}
diff --git a/generic/tclUtil.c b/generic/tclUtil.c
index e8cd164..046ba00 100644
--- a/generic/tclUtil.c
+++ b/generic/tclUtil.c
@@ -2615,7 +2615,7 @@ Tcl_DStringAppend(
if (newSize > dsPtr->spaceAvl) {
if (dsPtr->string == dsPtr->staticSpace) {
char *newString;
- newString = (char *) TclOverAlloc(newSize, &dsPtr->spaceAvl);
+ newString = (char *) TclAllocEx(newSize, &dsPtr->spaceAvl);
memcpy(newString, dsPtr->string, dsPtr->length);
dsPtr->string = newString;
} else {
@@ -2627,8 +2627,8 @@ Tcl_DStringAppend(
/* Source string is within this DString. Note offset */
offset = bytes - dsPtr->string;
}
- dsPtr->string = (char *) TclOverRealloc(
- newSize, dsPtr->string, dsPtr->spaceAvl, &dsPtr->spaceAvl);
+ dsPtr->string =
+ (char *)TclReallocEx(dsPtr->string, newSize, &dsPtr->spaceAvl);
if (offset >= 0) {
bytes = dsPtr->string + offset;
}
@@ -2746,7 +2746,7 @@ Tcl_DStringAppendElement(
if (newSize > dsPtr->spaceAvl) {
if (dsPtr->string == dsPtr->staticSpace) {
char *newString;
- newString = (char *) TclOverAlloc(newSize, &dsPtr->spaceAvl);
+ newString = (char *) TclAllocEx(newSize, &dsPtr->spaceAvl);
memcpy(newString, dsPtr->string, dsPtr->length);
dsPtr->string = newString;
} else {
@@ -2758,8 +2758,8 @@ Tcl_DStringAppendElement(
/* Source string is within this DString. Note offset */
offset = element - dsPtr->string;
}
- dsPtr->string = (char *) TclOverRealloc(
- newSize, dsPtr->string, dsPtr->spaceAvl, &dsPtr->spaceAvl);
+ dsPtr->string =
+ (char *)TclReallocEx(dsPtr->string, newSize, &dsPtr->spaceAvl);
if (offset >= 0) {
element = dsPtr->string + offset;
}