summaryrefslogtreecommitdiffstats
path: root/generic/tclObj.c
diff options
context:
space:
mode:
authorpooryorick <com.digitalsmarties@pooryorick.com>2023-05-16 05:25:31 (GMT)
committerpooryorick <com.digitalsmarties@pooryorick.com>2023-05-16 05:25:31 (GMT)
commit50dde26caf2055ef3a7d925be870a923f20d1afd (patch)
tree4e3d41784a3ebeaf9dab2596b1778d71feead8c2 /generic/tclObj.c
parent49c4458a2581a68296335a427e1c67f5e7462983 (diff)
downloadtcl-50dde26caf2055ef3a7d925be870a923f20d1afd.zip
tcl-50dde26caf2055ef3a7d925be870a923f20d1afd.tar.gz
tcl-50dde26caf2055ef3a7d925be870a923f20d1afd.tar.bz2
New function, TclDuplicatePureObj(), doesn't duplicate the string
representation when duplicating an object, unless necessary. Remove TclListObjCopy() in favor of TclDuplicatePureObj(), allowing internal representation to change after the copy rather than before.
Diffstat (limited to 'generic/tclObj.c')
-rw-r--r--generic/tclObj.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/generic/tclObj.c b/generic/tclObj.c
index 2044b7e..18d3bf3 100644
--- a/generic/tclObj.c
+++ b/generic/tclObj.c
@@ -202,6 +202,7 @@ static void DupBignum(Tcl_Obj *objPtr, Tcl_Obj *copyPtr);
static void UpdateStringOfBignum(Tcl_Obj *objPtr);
static int GetBignumFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
int copy, mp_int *bignumValue);
+static void SetDuplicatePureObj(Tcl_Obj *dupPtr, Tcl_Obj *objPtr);
/*
* Prototypes for the array hash key methods.
@@ -1523,6 +1524,13 @@ TclObjBeingDeleted(
* Create and return a new object that is a duplicate of the argument
* object.
*
+ * Tcl_DuplicatePureObj --
+ * Like Tcl_DuplicateObj, except that it does not duplicate the 'bytes'
+ * field unless it is necessary, i.e. the duplicated Tcl_Obj provides no
+ * updateStringProc. This can avoid an expensive memory allocation since
+ * the data in the 'bytes' field of each Tcl_Obj must reside in allocated
+ * memory.
+ *
* Results:
* The return value is a pointer to a newly created Tcl_Obj. This object
* has reference count 0 and the same type, if any, as the source object
@@ -1563,6 +1571,39 @@ TclObjBeingDeleted(
} \
}
+void SetDuplicatePureObj(Tcl_Obj *dupPtr, Tcl_Obj *objPtr)
+{
+ const Tcl_ObjType *typePtr = objPtr->typePtr;
+ const char *bytes = objPtr->bytes;
+
+ /* Unfortunately, it is not documented that dupIntRepProc() must assign
+ * null to Tcl_Obj.typePtr if it does not assign any other value, so it
+ * must be done here. Maybe in the future it can be documented, and this
+ * assignment deleted */
+ dupPtr->typePtr = NULL;
+
+ if (typePtr) {
+ if (typePtr->dupIntRepProc) {
+ typePtr->dupIntRepProc(objPtr, dupPtr);
+ } else {
+ dupPtr->internalRep = objPtr->internalRep;
+ dupPtr->typePtr = typePtr;
+ }
+ if (bytes && (
+ dupPtr->typePtr == NULL
+ || dupPtr->typePtr->updateStringProc == NULL)
+ ) {
+ TclInitStringRep(dupPtr, bytes, objPtr->length);
+ } else {
+ dupPtr->bytes = NULL;
+ }
+ } else if (bytes) {
+ TclInitStringRep(dupPtr, bytes, objPtr->length);
+ }
+ return;
+}
+
+
Tcl_Obj *
Tcl_DuplicateObj(
Tcl_Obj *objPtr) /* The object to duplicate. */
@@ -1574,6 +1615,20 @@ Tcl_DuplicateObj(
return dupPtr;
}
+
+Tcl_Obj *
+TclDuplicatePureObj(
+ Tcl_Obj *objPtr) /* The object to duplicate. */
+{
+ Tcl_Obj *dupPtr;
+
+ TclNewObj(dupPtr);
+ SetDuplicatePureObj(dupPtr, objPtr);
+ return dupPtr;
+}
+
+
+
void
TclSetDuplicateObj(
Tcl_Obj *dupPtr,