Tcl Source Code

Artifact [8c02d9e099]
Login

Artifact 8c02d9e0991e539e7dbcc91b08caa9cdab1080c3:

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.
      */