Attachment "tcllist.patch" to
ticket [2008248fff]
added by
ajpasadyn
2008-07-02 23:07:27.
--- old/tcl8.5.3/generic/tclListObj.c 2007-12-13 10:23:18.000000000 -0600
+++ new/tcl8.5.3/generic/tclListObj.c 2008-07-01 13:14:40.012985900 -0500
@@ -1657,6 +1657,63 @@
register Tcl_Obj *elemPtr;
List *listRepPtr;
+ if (objPtr->typePtr == &tclDictType) {
+ Tcl_Obj *keyPtr, *valuePtr;
+ Tcl_DictSearch search;
+ int done, result, size;
+ /*
+ * If the dict is shared its string rep must not be lost so it still
+ * is the same dict.
+ */
+ if (Tcl_IsShared(objPtr)) {
+ (void) TclGetString(objPtr);
+ }
+
+ result = Tcl_DictObjSize(interp, objPtr, &size);
+ if (result != TCL_OK) {
+ return result;
+ }
+ listRepPtr = NewListIntRep( (size > 0) ? (2 * size) : 1, NULL);
+ if (!listRepPtr) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "Not enough memory to allocate the list internal rep", -1));
+ return TCL_ERROR;
+ }
+ listRepPtr->elemCount = 2 * size;
+ elemPtrs = &listRepPtr->elements;
+ result = Tcl_DictObjFirst(interp, objPtr, &search,
+ &keyPtr, &valuePtr, &done);
+ if (result != TCL_OK) {
+ ckfree((char *) listRepPtr);
+ return result;
+ }
+ int i = 0;
+ while (!done) {
+ /*
+ * Assume these won't fail as we have complete control over the
+ * types of things here.
+ */
+ elemPtrs[i] = keyPtr;
+ elemPtrs[i+1] = valuePtr;
+ Tcl_IncrRefCount(keyPtr); /* Since list now holds ref to it. */
+ Tcl_IncrRefCount(valuePtr); /* Since list now holds ref to it. */
+ Tcl_DictObjNext(&search, &keyPtr, &valuePtr, &done);
+ i += 2;
+ }
+ if (i != 2 * size) {
+ Tcl_Panic("SetListFromAny: dict search size mismatch");
+ }
+ /*
+ * Free the old internalRep before setting the new one.
+ */
+ listRepPtr->refCount++;
+ TclFreeIntRep(objPtr);
+ objPtr->internalRep.twoPtrValue.ptr1 = (void *) listRepPtr;
+ objPtr->internalRep.twoPtrValue.ptr2 = NULL;
+ objPtr->typePtr = &tclListType;
+ return TCL_OK;
+ }
+
/*
* Get the string representation. Make it up-to-date if necessary.
*/