summaryrefslogtreecommitdiffstats
path: root/generic/tclBinary.c
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2010-04-29 15:08:03 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2010-04-29 15:08:03 (GMT)
commitb84b65f49a83dd2409278f59c82fc6c79d466819 (patch)
treec5befe02e5adfaceea2503a125a5d93d52e1f063 /generic/tclBinary.c
parent4e1cb8f323af8a2dbf67db4528b5da18cdfbe4ca (diff)
downloadtcl-b84b65f49a83dd2409278f59c82fc6c79d466819.zip
tcl-b84b65f49a83dd2409278f59c82fc6c79d466819.tar.gz
tcl-b84b65f49a83dd2409278f59c82fc6c79d466819.tar.bz2
* generic/tclBinary.c (TclAppendBytesToByteArray): [Bug 2992970]: Make
* generic/tclStringObj.c (Tcl_AppendObjToObj): an append of a byte array to another into an efficent operation. The problem was the (lack of) a proper growth management strategy for the byte array.
Diffstat (limited to 'generic/tclBinary.c')
-rw-r--r--generic/tclBinary.c77
1 files changed, 76 insertions, 1 deletions
diff --git a/generic/tclBinary.c b/generic/tclBinary.c
index 62f8f46..1d46902 100644
--- a/generic/tclBinary.c
+++ b/generic/tclBinary.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclBinary.c,v 1.60 2010/03/05 14:34:03 dkf Exp $
+ * RCS: @(#) $Id: tclBinary.c,v 1.61 2010/04/29 15:08:05 dkf Exp $
*/
#include "tclInt.h"
@@ -577,6 +577,81 @@ UpdateStringOfByteArray(
/*
*----------------------------------------------------------------------
*
+ * TclAppendBytesToByteArray --
+ *
+ * This function appends an array of bytes to a byte array object. Note
+ * that the object *must* be unshared, and the array of bytes *must not*
+ * refer to the object being appended to.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Allocates enough memory for an array of bytes of the requested total
+ * size, or possibly larger. [Bug 2992970]
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclAppendBytesToByteArray(
+ Tcl_Obj *objPtr,
+ const unsigned char *bytes,
+ unsigned len)
+{
+ ByteArray *byteArrayPtr;
+
+ if (Tcl_IsShared(objPtr)) {
+ Tcl_Panic("%s called with shared object","TclAppendBytesToByteArray");
+ }
+ if (objPtr->typePtr != &tclByteArrayType) {
+ SetByteArrayFromAny(NULL, objPtr);
+ }
+ byteArrayPtr = GET_BYTEARRAY(objPtr);
+
+ /*
+ * If we need to, resize the allocated space in the byte array.
+ */
+
+ if (byteArrayPtr->used+len > byteArrayPtr->allocated) {
+ unsigned int attempt, used = byteArrayPtr->used;
+ ByteArray *tmpByteArrayPtr;
+
+ attempt = byteArrayPtr->allocated;
+ do {
+ attempt *= 2;
+ } while (attempt < used+len);
+
+ tmpByteArrayPtr = (ByteArray *)
+ attemptckrealloc((char *) byteArrayPtr,
+ BYTEARRAY_SIZE(attempt));
+
+ if (tmpByteArrayPtr == NULL) {
+ attempt = used + len;
+ tmpByteArrayPtr = (ByteArray *) ckrealloc((char *) byteArrayPtr,
+ BYTEARRAY_SIZE(attempt));
+ }
+
+ byteArrayPtr = tmpByteArrayPtr;
+ byteArrayPtr->allocated = attempt;
+ byteArrayPtr->used = used;
+ SET_BYTEARRAY(objPtr, byteArrayPtr);
+ }
+
+ /*
+ * Do the append if there's any point.
+ */
+
+ if (len > 0) {
+ memcpy(byteArrayPtr->bytes + byteArrayPtr->used, bytes, len);
+ byteArrayPtr->used += len;
+ Tcl_InvalidateStringRep(objPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TclInitBinaryCmd --
*
* This function is called to create the "binary" Tcl command. See the