diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2010-04-29 15:08:03 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2010-04-29 15:08:03 (GMT) |
commit | b84b65f49a83dd2409278f59c82fc6c79d466819 (patch) | |
tree | c5befe02e5adfaceea2503a125a5d93d52e1f063 /generic/tclBinary.c | |
parent | 4e1cb8f323af8a2dbf67db4528b5da18cdfbe4ca (diff) | |
download | tcl-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.c | 77 |
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 |