2 * Copyright (c) 2007 Henri Sivonen
3 * Copyright (c) 2007-2011 Mozilla Foundation
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 package nu
.validator
.htmlparser
.impl
;
26 import nu
.validator
.htmlparser
.annotation
.Inline
;
27 import nu
.validator
.htmlparser
.annotation
.Local
;
28 import nu
.validator
.htmlparser
.annotation
.NsUri
;
30 final class StackNode
<T
> {
31 // Index where this stack node is stored in the tree builder's list of stack nodes.
32 // A value of -1 indicates that the stack node is not owned by a tree builder and
33 // must delete itself when its refcount reaches 0.
34 final int idxInTreeBuilder
;
40 @Local String popName
;
46 // Only used on the list of formatting elements
47 HtmlAttributes attributes
;
49 private int refcount
= 0;
52 * Only valid for formatting elements
54 // CPPONLY: private @HtmlCreator Object htmlCreator;
58 private TaintableLocatorImpl locator
;
60 public TaintableLocatorImpl
getLocator() {
66 @Inline public int getFlags() {
70 public int getGroup() {
71 return flags
& ElementName
.GROUP_MASK
;
74 public boolean isScoping() {
75 return (flags
& ElementName
.SCOPING
) != 0;
78 public boolean isSpecial() {
79 return (flags
& ElementName
.SPECIAL
) != 0;
82 public boolean isFosterParenting() {
83 return (flags
& ElementName
.FOSTER_PARENTING
) != 0;
86 public boolean isHtmlIntegrationPoint() {
87 return (flags
& ElementName
.HTML_INTEGRATION_POINT
) != 0;
92 public boolean isOptionalEndTag() {
93 return (flags
& ElementName
.OPTIONAL_END_TAG
) != 0;
98 StackNode(int idxInTreeBuilder
) {
99 this.idxInTreeBuilder
= idxInTreeBuilder
;
103 // CPPONLY: this.ns = 0;
105 this.attributes
= null;
107 // CPPONLY: this.htmlCreator = null;
110 // CPPONLY: public @HtmlCreator Object getHtmlCreator() {
111 // CPPONLY: return htmlCreator;
115 * Setter for copying. This doesn't take another <code>StackNode</code>
116 * because in C++ the caller is responsible for reobtaining the local names
117 * from another interner.
126 void setValues(int flags
, @NsUri String ns
, @Local String name
, T node
,
127 @Local String popName
, HtmlAttributes attributes
,
128 // CPPONLY: @HtmlCreator Object htmlCreator
130 TaintableLocatorImpl locator
136 this.popName
= popName
;
139 this.attributes
= attributes
;
142 * Need to track creator for formatting elements when copying.
144 // CPPONLY: this.htmlCreator = htmlCreator;
146 this.locator
= locator
;
151 * Short hand for well-known HTML elements.
156 void setValues(ElementName elementName
, T node
158 , TaintableLocatorImpl locator
162 this.flags
= elementName
.getFlags();
163 this.name
= elementName
.getName();
164 this.popName
= elementName
.getName();
165 this.ns
= "http://www.w3.org/1999/xhtml";
167 this.attributes
= null;
169 assert elementName
.isInterned() : "Don't use this constructor for custom elements.";
171 * Not used for formatting elements, so no need to track creator.
173 // CPPONLY: this.htmlCreator = null;
175 this.locator
= locator
;
180 * Setter for HTML formatting elements.
186 void setValues(ElementName elementName
, T node
, HtmlAttributes attributes
188 , TaintableLocatorImpl locator
192 this.flags
= elementName
.getFlags();
193 this.name
= elementName
.getName();
194 this.popName
= elementName
.getName();
195 this.ns
= "http://www.w3.org/1999/xhtml";
197 this.attributes
= attributes
;
199 assert elementName
.isInterned() : "Don't use this constructor for custom elements.";
201 * Need to track creator for formatting elements in order to be able
204 // CPPONLY: this.htmlCreator = elementName.getHtmlCreator();
206 this.locator
= locator
;
211 * The common-case HTML setter.
217 void setValues(ElementName elementName
, T node
, @Local String popName
219 , TaintableLocatorImpl locator
223 this.flags
= elementName
.getFlags();
224 this.name
= elementName
.getName();
225 this.popName
= popName
;
226 this.ns
= "http://www.w3.org/1999/xhtml";
228 this.attributes
= null;
231 * Not used for formatting elements, so no need to track creator.
233 // CPPONLY: this.htmlCreator = null;
235 this.locator
= locator
;
240 * Setter for SVG elements. Note that the order of the arguments is
241 * what distinguishes this from the HTML setter. This is ugly, but
242 * AFAICT the least disruptive way to make this work with Java's generics
243 * and without unnecessary branches. :-(
249 void setValues(ElementName elementName
, @Local String popName
, T node
251 , TaintableLocatorImpl locator
255 this.flags
= prepareSvgFlags(elementName
.getFlags());
256 this.name
= elementName
.getName();
257 this.popName
= popName
;
258 this.ns
= "http://www.w3.org/2000/svg";
260 this.attributes
= null;
263 * Not used for formatting elements, so no need to track creator.
265 // CPPONLY: this.htmlCreator = null;
267 this.locator
= locator
;
277 * @param markAsIntegrationPoint
279 void setValues(ElementName elementName
, T node
, @Local String popName
,
280 boolean markAsIntegrationPoint
282 , TaintableLocatorImpl locator
286 this.flags
= prepareMathFlags(elementName
.getFlags(),
287 markAsIntegrationPoint
);
288 this.name
= elementName
.getName();
289 this.popName
= popName
;
290 this.ns
= "http://www.w3.org/1998/Math/MathML";
292 this.attributes
= null;
295 * Not used for formatting elements, so no need to track creator.
297 // CPPONLY: this.htmlCreator = null;
299 this.locator
= locator
;
303 private static int prepareSvgFlags(int flags
) {
304 flags
&= ~
(ElementName
.FOSTER_PARENTING
| ElementName
.SCOPING
305 | ElementName
.SPECIAL
| ElementName
.OPTIONAL_END_TAG
);
306 if ((flags
& ElementName
.SCOPING_AS_SVG
) != 0) {
307 flags
|= (ElementName
.SCOPING
| ElementName
.SPECIAL
| ElementName
.HTML_INTEGRATION_POINT
);
312 private static int prepareMathFlags(int flags
,
313 boolean markAsIntegrationPoint
) {
314 flags
&= ~
(ElementName
.FOSTER_PARENTING
| ElementName
.SCOPING
315 | ElementName
.SPECIAL
| ElementName
.OPTIONAL_END_TAG
);
316 if ((flags
& ElementName
.SCOPING_AS_MATHML
) != 0) {
317 flags
|= (ElementName
.SCOPING
| ElementName
.SPECIAL
);
319 if (markAsIntegrationPoint
) {
320 flags
|= ElementName
.HTML_INTEGRATION_POINT
;
325 @SuppressWarnings("unused") private void destructor() {
326 // The translator adds refcount debug code here.
329 public void dropAttributes() {
335 * @see java.lang.Object#toString()
337 @Override public @Local String
toString() {
343 public void retain() {
347 public void release(TreeBuilder
<T
> owningTreeBuilder
) {
349 assert refcount
>= 0;
351 Portability
.delete(attributes
);
352 if (idxInTreeBuilder
>= 0) {
353 owningTreeBuilder
.notifyUnusedStackNode(idxInTreeBuilder
);
355 assert owningTreeBuilder
== null;
356 Portability
.delete(this);
362 return refcount
== 0;