OSDN Git Service

libgo: Update to weekly.2011-11-01.
[pf3gnuchains/gcc-fork.git] / libgo / go / html / node.go
1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package html
6
7 // A NodeType is the type of a Node.
8 type NodeType int
9
10 const (
11         ErrorNode NodeType = iota
12         TextNode
13         DocumentNode
14         ElementNode
15         CommentNode
16         DoctypeNode
17         scopeMarkerNode
18 )
19
20 // Section 11.2.3.3 says "scope markers are inserted when entering applet
21 // elements, buttons, object elements, marquees, table cells, and table
22 // captions, and are used to prevent formatting from 'leaking'".
23 var scopeMarker = Node{Type: scopeMarkerNode}
24
25 // A Node consists of a NodeType and some Data (tag name for element nodes,
26 // content for text) and are part of a tree of Nodes. Element nodes may also
27 // contain a slice of Attributes. Data is unescaped, so that it looks like
28 // "a<b" rather than "a&lt;b".
29 type Node struct {
30         Parent *Node
31         Child  []*Node
32         Type   NodeType
33         Data   string
34         Attr   []Attribute
35 }
36
37 // Add adds a node as a child of n.
38 // It will panic if the child's parent is not nil.
39 func (n *Node) Add(child *Node) {
40         if child.Parent != nil {
41                 panic("html: Node.Add called for a child Node that already has a parent")
42         }
43         child.Parent = n
44         n.Child = append(n.Child, child)
45 }
46
47 // Remove removes a node as a child of n.
48 // It will panic if the child's parent is not n.
49 func (n *Node) Remove(child *Node) {
50         if child.Parent == n {
51                 child.Parent = nil
52                 for i, m := range n.Child {
53                         if m == child {
54                                 copy(n.Child[i:], n.Child[i+1:])
55                                 j := len(n.Child) - 1
56                                 n.Child[j] = nil
57                                 n.Child = n.Child[:j]
58                                 return
59                         }
60                 }
61         }
62         panic("html: Node.Remove called for a non-child Node")
63 }
64
65 // reparentChildren reparents all of src's child nodes to dst.
66 func reparentChildren(dst, src *Node) {
67         for _, n := range src.Child {
68                 if n.Parent != src {
69                         panic("html: nodes have an inconsistent parent/child relationship")
70                 }
71                 n.Parent = dst
72         }
73         dst.Child = append(dst.Child, src.Child...)
74         src.Child = nil
75 }
76
77 // clone returns a new node with the same type, data and attributes.
78 // The clone has no parent and no children.
79 func (n *Node) clone() *Node {
80         m := &Node{
81                 Type: n.Type,
82                 Data: n.Data,
83                 Attr: make([]Attribute, len(n.Attr)),
84         }
85         copy(m.Attr, n.Attr)
86         return m
87 }
88
89 // nodeStack is a stack of nodes.
90 type nodeStack []*Node
91
92 // pop pops the stack. It will panic if s is empty.
93 func (s *nodeStack) pop() *Node {
94         i := len(*s)
95         n := (*s)[i-1]
96         *s = (*s)[:i-1]
97         return n
98 }
99
100 // top returns the most recently pushed node, or nil if s is empty.
101 func (s *nodeStack) top() *Node {
102         if i := len(*s); i > 0 {
103                 return (*s)[i-1]
104         }
105         return nil
106 }
107
108 // index returns the index of the top-most occurence of n in the stack, or -1
109 // if n is not present.
110 func (s *nodeStack) index(n *Node) int {
111         for i := len(*s) - 1; i >= 0; i-- {
112                 if (*s)[i] == n {
113                         return i
114                 }
115         }
116         return -1
117 }
118
119 // insert inserts a node at the given index.
120 func (s *nodeStack) insert(i int, n *Node) {
121         (*s) = append(*s, nil)
122         copy((*s)[i+1:], (*s)[i:])
123         (*s)[i] = n
124 }
125
126 // remove removes a node from the stack. It is a no-op if n is not present.
127 func (s *nodeStack) remove(n *Node) {
128         i := s.index(n)
129         if i == -1 {
130                 return
131         }
132         copy((*s)[i:], (*s)[i+1:])
133         j := len(*s) - 1
134         (*s)[j] = nil
135         *s = (*s)[:j]
136 }
137
138 // TODO(nigeltao): forTag no longer used. Should it be deleted?
139
140 // forTag returns the top-most element node with the given tag.
141 func (s *nodeStack) forTag(tag string) *Node {
142         for i := len(*s) - 1; i >= 0; i-- {
143                 n := (*s)[i]
144                 if n.Type == ElementNode && n.Data == tag {
145                         return n
146                 }
147         }
148         return nil
149 }