| // Copyright 2011 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package html | |
| import ( | |
| "template/parse" | |
| ) | |
| // clone clones a template Node. | |
| func clone(n parse.Node) parse.Node { | |
| switch t := n.(type) { | |
| case *parse.ActionNode: | |
| return cloneAction(t) | |
| case *parse.IfNode: | |
| b := new(parse.IfNode) | |
| copyBranch(&b.BranchNode, &t.BranchNode) | |
| return b | |
| case *parse.ListNode: | |
| return cloneList(t) | |
| case *parse.RangeNode: | |
| b := new(parse.RangeNode) | |
| copyBranch(&b.BranchNode, &t.BranchNode) | |
| return b | |
| case *parse.TemplateNode: | |
| return cloneTemplate(t) | |
| case *parse.TextNode: | |
| return cloneText(t) | |
| case *parse.WithNode: | |
| b := new(parse.WithNode) | |
| copyBranch(&b.BranchNode, &t.BranchNode) | |
| return b | |
| } | |
| panic("cloning " + n.String() + " is unimplemented") | |
| } | |
| // cloneAction returns a deep clone of n. | |
| func cloneAction(n *parse.ActionNode) *parse.ActionNode { | |
| // We use keyless fields because they won't compile if a field is added. | |
| return &parse.ActionNode{n.NodeType, n.Line, clonePipe(n.Pipe)} | |
| } | |
| // cloneList returns a deep clone of n. | |
| func cloneList(n *parse.ListNode) *parse.ListNode { | |
| if n == nil { | |
| return nil | |
| } | |
| // We use keyless fields because they won't compile if a field is added. | |
| c := parse.ListNode{n.NodeType, make([]parse.Node, len(n.Nodes))} | |
| for i, child := range n.Nodes { | |
| c.Nodes[i] = clone(child) | |
| } | |
| return &c | |
| } | |
| // clonePipe returns a shallow clone of n. | |
| // The escaper does not modify pipe descendants in place so there's no need to | |
| // clone deeply. | |
| func clonePipe(n *parse.PipeNode) *parse.PipeNode { | |
| if n == nil { | |
| return nil | |
| } | |
| // We use keyless fields because they won't compile if a field is added. | |
| return &parse.PipeNode{n.NodeType, n.Line, n.Decl, n.Cmds} | |
| } | |
| // cloneTemplate returns a deep clone of n. | |
| func cloneTemplate(n *parse.TemplateNode) *parse.TemplateNode { | |
| // We use keyless fields because they won't compile if a field is added. | |
| return &parse.TemplateNode{n.NodeType, n.Line, n.Name, clonePipe(n.Pipe)} | |
| } | |
| // cloneText clones the given node sharing its []byte. | |
| func cloneText(n *parse.TextNode) *parse.TextNode { | |
| // We use keyless fields because they won't compile if a field is added. | |
| return &parse.TextNode{n.NodeType, n.Text} | |
| } | |
| // copyBranch clones src into dst. | |
| func copyBranch(dst, src *parse.BranchNode) { | |
| // We use keyless fields because they won't compile if a field is added. | |
| *dst = parse.BranchNode{ | |
| src.NodeType, | |
| src.Line, | |
| clonePipe(src.Pipe), | |
| cloneList(src.List), | |
| cloneList(src.ElseList), | |
| } | |
| } |