From a3380d8151e2791d70300455b60e8a6a73948c0c Mon Sep 17 00:00:00 2001 From: pooryorick Date: Fri, 21 Apr 2023 20:32:38 +0000 Subject: Make Tcl_AppendObjToObj more efficient and avoid unnecessarily generating a string representation when the object to append to is the empty string. --- doc/StringObj.3 | 2 +- generic/tclStringObj.c | 61 +++++++++++++++++++++++--------------------------- 2 files changed, 29 insertions(+), 34 deletions(-) diff --git a/doc/StringObj.3 b/doc/StringObj.3 index d835140..b708298 100644 --- a/doc/StringObj.3 +++ b/doc/StringObj.3 @@ -115,7 +115,7 @@ The index of the last Unicode character in the Unicode range to be returned as a new value. If negative, take all characters up to the last one available. .AP Tcl_Obj *objPtr in/out -Points to a value to manipulate. +A pointer to a value to read, or to an unshared value to modify. .AP Tcl_Obj *appendObjPtr in The value to append to \fIobjPtr\fR in \fBTcl_AppendObjToObj\fR. .AP "Tcl_Size \&| int" *lengthPtr out diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 2bbc4bc..48344d7 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -551,9 +551,8 @@ TclCheckEmptyString( int Tcl_GetUniChar( - Tcl_Obj *objPtr, /* The object to get the Unicode charater - * from. */ - Tcl_Size index) /* Get the index'th Unicode character. */ + Tcl_Obj *objPtr, /* The object to get the Unicode character from. */ + Tcl_Size index) /* Get the index'th Unicode character. */ { String *stringPtr; int ch; @@ -563,8 +562,8 @@ Tcl_GetUniChar( } /* - * Optimize the case where we're really dealing with a ByteArray object - * we don't need to convert to a string to perform the indexing operation. + * For a ByteArray object there is no need to convert to a string to + * perform the indexing operation. */ if (TclIsPureByteArray(objPtr)) { @@ -578,7 +577,7 @@ Tcl_GetUniChar( } /* - * OK, need to work with the object as a string. + * Must work with the object as a string. */ SetStringFromAny(NULL, objPtr); @@ -624,9 +623,8 @@ Tcl_GetUniChar( int TclGetUniChar( - Tcl_Obj *objPtr, /* The object to get the Unicode charater - * from. */ - Tcl_Size index) /* Get the index'th Unicode character. */ + Tcl_Obj *objPtr, /* The object to get the Unicode character from. */ + Tcl_Size index) /* Get the index'th Unicode character. */ { int ch = 0; @@ -1405,17 +1403,13 @@ Tcl_AppendUnicodeToObj( *---------------------------------------------------------------------- * * Tcl_AppendObjToObj -- - * - * This function appends the string rep of one object to another. - * "objPtr" cannot be a shared object. + * Appends the value of apppendObjPtr to objPtr, which must not be shared. * * Results: * None. * * Side effects: - * The string rep of appendObjPtr is appended to the string - * representation of objPtr. - * IMPORTANT: This routine does not and MUST NOT shimmer appendObjPtr. + * IMPORTANT: Does not and MUST NOT shimmer appendObjPtr. * Callers are counting on that. * *---------------------------------------------------------------------- @@ -1423,34 +1417,35 @@ Tcl_AppendUnicodeToObj( void Tcl_AppendObjToObj( - Tcl_Obj *objPtr, /* Points to the object to append to. */ - Tcl_Obj *appendObjPtr) /* Object to append. */ + Tcl_Obj *objPtr, /* Points to the value to append to. */ + Tcl_Obj *appendObjPtr) /* The value to append. */ { String *stringPtr; Tcl_Size length = 0, numChars; Tcl_Size appendNumChars = TCL_INDEX_NONE; const char *bytes; - /* - * Special case: second object is standard-empty is fast case. We know - * that appending nothing to anything leaves that starting anything... - */ - if (appendObjPtr->bytes == &tclEmptyString) { return; } - /* - * Handle append of one ByteArray object to another as a special case. - * Note that we only do this when the objects are pure so that the - * bytearray faithfully represent the true value; Otherwise appending the - * byte arrays together could lose information; - */ + if (objPtr->bytes == &tclEmptyString) { + TclSetDuplicateObj(objPtr, appendObjPtr); + return; + } + + if ( + TclIsPureByteArray(appendObjPtr) + && (TclIsPureByteArray(objPtr) || objPtr->bytes == &tclEmptyString) + ) { + /* + * Both bytearray objects are pure. Therefore they faithfully + * represent the true values, making it safe to append the second + * bytearray to the first. + */ - if ((TclIsPureByteArray(objPtr) || objPtr->bytes == &tclEmptyString) - && TclIsPureByteArray(appendObjPtr)) { /* - * You might expect the code here to be + * One might expect the code here to be * * bytes = Tcl_GetByteArrayFromObj(appendObjPtr, &length); * TclAppendBytesToByteArray(objPtr, bytes, length); @@ -3375,7 +3370,7 @@ TclStringCat( objResultPtr = *objv++; objc--; - /* Ugly interface! Force resize of the unicode array. */ + /* Ugly interface! Force resize of the Unicode array. */ (void)Tcl_GetUnicodeFromObj(objResultPtr, &start); Tcl_InvalidateStringRep(objResultPtr); if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) { @@ -4214,7 +4209,7 @@ TclStringReplace( static void FillUnicodeRep( - Tcl_Obj *objPtr) /* The object in which to fill the unicode + Tcl_Obj *objPtr) /* The object in which to fill the Unicode * rep. */ { String *stringPtr = GET_STRING(objPtr); -- cgit v0.12