coldfusioncoldfusion-7coldfusion-6

How to Deep Copy (clone) a structure while ignoring components


In versions of ColdFusion prior to 8 the duplicate function throws an error if there are any components in the structure. In 8 and beyond it will work, but there are issues when copying components.

So, What I need is a way to create a deep copy of a structure that ignores components. For my purposes it's for debugging, I need a snapshot of the variables scope at a particular point in the code, so efficiency doesn't really matter as this will never make it out of the development environment. Currently using CF 7, I would take what 8 offers if only to solve this immediate issue, but I don't control upgrade :(


Solution

  • While you were off killing brain cells, I took a stab at a recursive function ;) It excludes components and java/com objects. Neither of which MX7 can duplicate. I threw the functions into a component to avoid tampering with the variables scope. Then stored the instance in the request scope.

    It is not rigorously tested. So I am sure there is room for improvement.

    Usage

    <cfset request.util = createObject("component", "Util")>
    <cfset request.copy = request.util.duplicateStructMinusObjects(variables)>
    <cfdump var="#request.copy#">
    

    Util.cfc

    <cfcomponent>
        <cfscript>
                function duplicateArrayMinusObjects(input) {
                        var x      = "";
                        var value  = "";
                        var output = arrayNew(1);
    
                        for (x = 1; x lte arrayLen(arguments.input); x = x + 1) {
                                value = arguments.input[x];
    
                                // note components are considered structures
                                if (IsStruct(value) and not IsObject(value)) {
                                        arrayAppend(output, duplicateStructMinusObjects(value));
                                }
                                else if (IsArray(value)) {
                                        arrayAppend(output, duplicateArrayMinusObjects(value));                
                                }
                                else if (not IsObject(value)){        
                                        arrayAppend(output, duplicate(value));
                                }
                        }        
                        return output;
                }
    
                function duplicateStructMinusObjects(input) {
                        var key    = "";
                        var value  = "";
                        var output = structNew();
    
                        for (key in arguments.input) {
                                value = arguments.input[key];
    
                                // note components are considered structures
                                if (IsStruct(value) and not IsObject(value)) {
                                        output[key] = duplicateStructMinusObjects(value);
                                }
                                else if (IsArray(value)) {
                                        output[key] = duplicateArrayMinusObjects(value);
                                }
                                else if (not IsObject(value)){        
                                        output[key] = duplicate(value);
                                }
                        }
    
                        return output;
                }
        </cfscript>
    </cfcomponent>