mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-15 17:03:07 +09:00
Bug 1355479 - Remove isindex on the Java side and allow the C++ side to reduce malloc in attribute handling.
Tag UXP Issue #1344
This commit is contained in:
parent
81958be04f
commit
67a2c5cb06
10 changed files with 180 additions and 336 deletions
|
|
@ -33,7 +33,6 @@ import nu.validator.htmlparser.annotation.NsUri;
|
|||
import nu.validator.htmlparser.annotation.Prefix;
|
||||
import nu.validator.htmlparser.annotation.QName;
|
||||
import nu.validator.htmlparser.annotation.Unsigned;
|
||||
import nu.validator.htmlparser.annotation.Virtual;
|
||||
import nu.validator.htmlparser.common.Interner;
|
||||
|
||||
public final class AttributeName
|
||||
|
|
@ -275,35 +274,19 @@ public final class AttributeName
|
|||
*/
|
||||
static AttributeName nameByBuffer(@NoLength char[] buf, int offset,
|
||||
int length
|
||||
// [NOCPP[
|
||||
, boolean checkNcName
|
||||
// ]NOCPP]
|
||||
, Interner interner) {
|
||||
// XXX deal with offset
|
||||
@Unsigned int hash = AttributeName.bufToHash(buf, length);
|
||||
int index = Arrays.binarySearch(AttributeName.ATTRIBUTE_HASHES, hash);
|
||||
if (index < 0) {
|
||||
return AttributeName.createAttributeName(
|
||||
Portability.newLocalNameFromBuffer(buf, offset, length,
|
||||
interner)
|
||||
// [NOCPP[
|
||||
, checkNcName
|
||||
// ]NOCPP]
|
||||
);
|
||||
} else {
|
||||
AttributeName attributeName = AttributeName.ATTRIBUTE_NAMES[index];
|
||||
@Local String name = attributeName.getLocal(AttributeName.HTML);
|
||||
if (!Portability.localEqualsBuffer(name, buf, offset, length)) {
|
||||
return AttributeName.createAttributeName(
|
||||
Portability.newLocalNameFromBuffer(buf, offset, length,
|
||||
interner)
|
||||
// [NOCPP[
|
||||
, checkNcName
|
||||
// ]NOCPP]
|
||||
);
|
||||
}
|
||||
return attributeName;
|
||||
return null;
|
||||
}
|
||||
AttributeName attributeName = AttributeName.ATTRIBUTE_NAMES[index];
|
||||
@Local String name = attributeName.getLocal(AttributeName.HTML);
|
||||
if (!Portability.localEqualsBuffer(name, buf, offset, length)) {
|
||||
return null;
|
||||
}
|
||||
return attributeName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -385,6 +368,8 @@ public final class AttributeName
|
|||
*/
|
||||
private final @Prefix @NoLength String[] prefix;
|
||||
|
||||
// CPPONLY: private final boolean custom;
|
||||
|
||||
// [NOCPP[
|
||||
|
||||
private final int flags;
|
||||
|
|
@ -410,7 +395,7 @@ public final class AttributeName
|
|||
* @param xmlns
|
||||
* whether this is an xmlns attribute
|
||||
*/
|
||||
protected AttributeName(@NsUri @NoLength String[] uri,
|
||||
private AttributeName(@NsUri @NoLength String[] uri,
|
||||
@Local @NoLength String[] local, @Prefix @NoLength String[] prefix
|
||||
// [NOCPP[
|
||||
, int flags
|
||||
|
|
@ -423,8 +408,27 @@ public final class AttributeName
|
|||
this.qName = COMPUTE_QNAME(local, prefix);
|
||||
this.flags = flags;
|
||||
// ]NOCPP]
|
||||
// CPPONLY: this.custom = false;
|
||||
}
|
||||
|
||||
// CPPONLY: public AttributeName() {
|
||||
// CPPONLY: this.uri = AttributeName.ALL_NO_NS;
|
||||
// CPPONLY: this.local = AttributeName.SAME_LOCAL(null);
|
||||
// CPPONLY: this.prefix = ALL_NO_PREFIX;
|
||||
// CPPONLY: this.custom = true;
|
||||
// CPPONLY: }
|
||||
// CPPONLY:
|
||||
// CPPONLY: public boolean isInterned() {
|
||||
// CPPONLY: return !custom;
|
||||
// CPPONLY: }
|
||||
// CPPONLY:
|
||||
// CPPONLY: public void setNameForNonInterned(@Local String name) {
|
||||
// CPPONLY: assert custom;
|
||||
// CPPONLY: local[0] = name;
|
||||
// CPPONLY: local[1] = name;
|
||||
// CPPONLY: local[2] = name;
|
||||
// CPPONLY: }
|
||||
|
||||
/**
|
||||
* Creates an <code>AttributeName</code> for a local name.
|
||||
*
|
||||
|
|
@ -434,7 +438,7 @@ public final class AttributeName
|
|||
* whether to check ncnameness
|
||||
* @return an <code>AttributeName</code>
|
||||
*/
|
||||
private static AttributeName createAttributeName(@Local String name
|
||||
static AttributeName createAttributeName(@Local String name
|
||||
// [NOCPP[
|
||||
, boolean checkNcName
|
||||
// ]NOCPP]
|
||||
|
|
@ -451,33 +455,13 @@ public final class AttributeName
|
|||
AttributeName.SAME_LOCAL(name), ALL_NO_PREFIX, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes runtime-allocated instances in C++.
|
||||
*/
|
||||
@Virtual void release() {
|
||||
// No-op in Java.
|
||||
// Implement as |delete this;| in subclass.
|
||||
}
|
||||
|
||||
/**
|
||||
* The C++ destructor.
|
||||
*/
|
||||
@SuppressWarnings("unused") @Virtual private void destructor() {
|
||||
@SuppressWarnings("unused") private void destructor() {
|
||||
Portability.deleteArray(local);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones the attribute using an interner. Returns <code>this</code> in Java
|
||||
* and for non-dynamic instances in C++.
|
||||
*
|
||||
* @param interner
|
||||
* an interner
|
||||
* @return a clone
|
||||
*/
|
||||
@Virtual public AttributeName cloneAttributeName(Interner interner) {
|
||||
return this;
|
||||
}
|
||||
|
||||
// [NOCPP[
|
||||
/**
|
||||
* Creator for use when the XML violation policy requires an attribute name
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@
|
|||
|
||||
package nu.validator.htmlparser.impl;
|
||||
|
||||
import nu.validator.htmlparser.annotation.NoLength;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import nu.validator.htmlparser.annotation.NoLength;
|
||||
|
||||
/**
|
||||
* A common superclass for tree builders that coalesce their text nodes.
|
||||
*
|
||||
|
|
@ -48,13 +48,6 @@ public abstract class CoalescingTreeBuilder<T> extends TreeBuilder<T> {
|
|||
appendCharacters(parent, new String(buf, start, length));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see nu.validator.htmlparser.impl.TreeBuilder#appendIsindexPrompt(java.lang.Object)
|
||||
*/
|
||||
@Override protected void appendIsindexPrompt(T parent) throws SAXException {
|
||||
appendCharacters(parent, "This is a searchable index. Enter search keywords: ");
|
||||
}
|
||||
|
||||
protected abstract void appendCharacters(T parent, String text) throws SAXException;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -192,6 +192,11 @@ public final class ElementName
|
|||
assert this.flags == (TreeBuilder.OTHER | NOT_INTERNED);
|
||||
}
|
||||
|
||||
// CPPONLY: public static final ElementName ISINDEX = new ElementName("isindex", "isindex", TreeBuilder.ISINDEX | SPECIAL);
|
||||
// [NOCPP[
|
||||
public static final ElementName ISINDEX = new ElementName("isindex", "isindex", TreeBuilder.OTHER);
|
||||
// ]NOCPP]
|
||||
|
||||
// START CODE ONLY USED FOR GENERATING CODE uncomment and run to regenerate
|
||||
|
||||
// /**
|
||||
|
|
@ -421,6 +426,9 @@ public final class ElementName
|
|||
// }
|
||||
// for (int i = 0; i < ELEMENT_NAMES.length; i++) {
|
||||
// ElementName el = ELEMENT_NAMES[i];
|
||||
// if ("isindex".equals(el.name)) {
|
||||
// continue;
|
||||
// }
|
||||
// System.out.println("public static final ElementName "
|
||||
// + el.constName() + " = new ElementName" + el.toString()
|
||||
// + ";");
|
||||
|
|
@ -439,6 +447,7 @@ public final class ElementName
|
|||
// System.out.println("};");
|
||||
// }
|
||||
|
||||
|
||||
// START GENERATED CODE
|
||||
public static final ElementName AND = new ElementName("and", "and", TreeBuilder.OTHER);
|
||||
public static final ElementName ARG = new ElementName("arg", "arg", TreeBuilder.OTHER);
|
||||
|
|
@ -828,7 +837,6 @@ public final class ElementName
|
|||
public static final ElementName APPROX = new ElementName("approx", "approx", TreeBuilder.OTHER);
|
||||
public static final ElementName FECOLORMATRIX = new ElementName("fecolormatrix", "feColorMatrix", TreeBuilder.OTHER);
|
||||
public static final ElementName FECONVOLVEMATRIX = new ElementName("feconvolvematrix", "feConvolveMatrix", TreeBuilder.OTHER);
|
||||
public static final ElementName ISINDEX = new ElementName("isindex", "isindex", TreeBuilder.ISINDEX | SPECIAL);
|
||||
public static final ElementName MATRIX = new ElementName("matrix", "matrix", TreeBuilder.OTHER);
|
||||
public static final ElementName APPLY = new ElementName("apply", "apply", TreeBuilder.OTHER);
|
||||
public static final ElementName BODY = new ElementName("body", "body", TreeBuilder.BODY | SPECIAL | OPTIONAL_END_TAG);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@
|
|||
|
||||
package nu.validator.htmlparser.impl;
|
||||
|
||||
import nu.validator.htmlparser.annotation.Auto;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import nu.validator.htmlparser.annotation.IdType;
|
||||
import nu.validator.htmlparser.annotation.Local;
|
||||
import nu.validator.htmlparser.annotation.NsUri;
|
||||
|
|
@ -34,9 +36,6 @@ import nu.validator.htmlparser.annotation.QName;
|
|||
import nu.validator.htmlparser.common.Interner;
|
||||
import nu.validator.htmlparser.common.XmlViolationPolicy;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Be careful with this class. QName is the name in from HTML tokenization.
|
||||
* Otherwise, please refer to the interface doc.
|
||||
|
|
@ -46,14 +45,10 @@ import org.xml.sax.SAXException;
|
|||
*/
|
||||
public final class HtmlAttributes implements Attributes {
|
||||
|
||||
// [NOCPP[
|
||||
|
||||
private static final AttributeName[] EMPTY_ATTRIBUTENAMES = new AttributeName[0];
|
||||
|
||||
private static final String[] EMPTY_STRINGS = new String[0];
|
||||
|
||||
// ]NOCPP]
|
||||
|
||||
public static final HtmlAttributes EMPTY_ATTRIBUTES = new HtmlAttributes(
|
||||
AttributeName.HTML);
|
||||
|
||||
|
|
@ -61,13 +56,9 @@ public final class HtmlAttributes implements Attributes {
|
|||
|
||||
private int length;
|
||||
|
||||
private @Auto AttributeName[] names;
|
||||
private AttributeName[] names;
|
||||
|
||||
private @Auto String[] values; // XXX perhaps make this @NoLength?
|
||||
|
||||
// CPPONLY: private @Auto int[] lines; // XXX perhaps make this @NoLength?
|
||||
|
||||
// [NOCPP[
|
||||
private String[] values;
|
||||
|
||||
private String idValue;
|
||||
|
||||
|
|
@ -77,21 +68,15 @@ public final class HtmlAttributes implements Attributes {
|
|||
|
||||
private String[] xmlnsValues;
|
||||
|
||||
// ]NOCPP]
|
||||
|
||||
public HtmlAttributes(int mode) {
|
||||
this.mode = mode;
|
||||
this.length = 0;
|
||||
/*
|
||||
* The length of 5 covers covers 98.3% of elements
|
||||
* according to Hixie, but lets round to the next power of two for
|
||||
* jemalloc.
|
||||
* according to Hixie.
|
||||
*/
|
||||
this.names = new AttributeName[8];
|
||||
this.values = new String[8];
|
||||
// CPPONLY: this.lines = new int[8];
|
||||
|
||||
// [NOCPP[
|
||||
this.names = new AttributeName[5];
|
||||
this.values = new String[5];
|
||||
|
||||
this.idValue = null;
|
||||
|
||||
|
|
@ -101,25 +86,6 @@ public final class HtmlAttributes implements Attributes {
|
|||
|
||||
this.xmlnsValues = HtmlAttributes.EMPTY_STRINGS;
|
||||
|
||||
// ]NOCPP]
|
||||
}
|
||||
/*
|
||||
public HtmlAttributes(HtmlAttributes other) {
|
||||
this.mode = other.mode;
|
||||
this.length = other.length;
|
||||
this.names = new AttributeName[other.length];
|
||||
this.values = new String[other.length];
|
||||
// [NOCPP[
|
||||
this.idValue = other.idValue;
|
||||
this.xmlnsLength = other.xmlnsLength;
|
||||
this.xmlnsNames = new AttributeName[other.xmlnsLength];
|
||||
this.xmlnsValues = new String[other.xmlnsLength];
|
||||
// ]NOCPP]
|
||||
}
|
||||
*/
|
||||
|
||||
void destructor() {
|
||||
clear(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -161,7 +127,6 @@ public final class HtmlAttributes implements Attributes {
|
|||
* @return the local name at index
|
||||
*/
|
||||
public @Local String getLocalNameNoBoundsCheck(int index) {
|
||||
// CPPONLY: assert index < length && index >= 0: "Index out of bounds";
|
||||
return names[index].getLocal(mode);
|
||||
}
|
||||
|
||||
|
|
@ -171,7 +136,6 @@ public final class HtmlAttributes implements Attributes {
|
|||
* @return the namespace URI at index
|
||||
*/
|
||||
public @NsUri String getURINoBoundsCheck(int index) {
|
||||
// CPPONLY: assert index < length && index >= 0: "Index out of bounds";
|
||||
return names[index].getUri(mode);
|
||||
}
|
||||
|
||||
|
|
@ -181,7 +145,6 @@ public final class HtmlAttributes implements Attributes {
|
|||
* @return the namespace prefix at index
|
||||
*/
|
||||
public @Prefix String getPrefixNoBoundsCheck(int index) {
|
||||
// CPPONLY: assert index < length && index >= 0: "Index out of bounds";
|
||||
return names[index].getPrefix(mode);
|
||||
}
|
||||
|
||||
|
|
@ -191,7 +154,6 @@ public final class HtmlAttributes implements Attributes {
|
|||
* @return the attribute value at index
|
||||
*/
|
||||
public String getValueNoBoundsCheck(int index) {
|
||||
// CPPONLY: assert index < length && index >= 0: "Index out of bounds";
|
||||
return values[index];
|
||||
}
|
||||
|
||||
|
|
@ -201,21 +163,9 @@ public final class HtmlAttributes implements Attributes {
|
|||
* @return the attribute name at index
|
||||
*/
|
||||
public AttributeName getAttributeNameNoBoundsCheck(int index) {
|
||||
// CPPONLY: assert index < length && index >= 0: "Index out of bounds";
|
||||
return names[index];
|
||||
}
|
||||
|
||||
// CPPONLY: /**
|
||||
// CPPONLY: * Obtains a line number without bounds check.
|
||||
// CPPONLY: * @param index a valid attribute index
|
||||
// CPPONLY: * @return the line number at index or -1 if unknown
|
||||
// CPPONLY: */
|
||||
// CPPONLY: public int getLineNoBoundsCheck(int index) {
|
||||
// CPPONLY: assert index < length && index >= 0: "Index out of bounds";
|
||||
// CPPONLY: return lines[index];
|
||||
// CPPONLY: }
|
||||
|
||||
// [NOCPP[
|
||||
|
||||
/**
|
||||
* Variant of <code>getQName(int index)</code> without bounds check.
|
||||
|
|
@ -404,15 +354,9 @@ public final class HtmlAttributes implements Attributes {
|
|||
}
|
||||
}
|
||||
|
||||
// ]NOCPP]
|
||||
|
||||
void addAttribute(AttributeName name, String value
|
||||
// [NOCPP[
|
||||
, XmlViolationPolicy xmlnsPolicy
|
||||
// ]NOCPP]
|
||||
// CPPONLY: , int line
|
||||
) throws SAXException {
|
||||
// [NOCPP[
|
||||
if (name == AttributeName.ID) {
|
||||
idValue = value;
|
||||
}
|
||||
|
|
@ -441,8 +385,6 @@ public final class HtmlAttributes implements Attributes {
|
|||
}
|
||||
}
|
||||
|
||||
// ]NOCPP]
|
||||
|
||||
if (names.length == length) {
|
||||
int newLen = length << 1; // The first growth covers virtually
|
||||
// 100% of elements according to
|
||||
|
|
@ -453,53 +395,25 @@ public final class HtmlAttributes implements Attributes {
|
|||
String[] newValues = new String[newLen];
|
||||
System.arraycopy(values, 0, newValues, 0, values.length);
|
||||
values = newValues;
|
||||
// CPPONLY: int[] newLines = new int[newLen];
|
||||
// CPPONLY: System.arraycopy(lines, 0, newLines, 0, lines.length);
|
||||
// CPPONLY: lines = newLines;
|
||||
}
|
||||
names[length] = name;
|
||||
values[length] = value;
|
||||
// CPPONLY: lines[length] = line;
|
||||
length++;
|
||||
}
|
||||
|
||||
void clear(int m) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
names[i].release();
|
||||
names[i] = null;
|
||||
Portability.releaseString(values[i]);
|
||||
values[i] = null;
|
||||
}
|
||||
length = 0;
|
||||
mode = m;
|
||||
// [NOCPP[
|
||||
idValue = null;
|
||||
for (int i = 0; i < xmlnsLength; i++) {
|
||||
xmlnsNames[i] = null;
|
||||
xmlnsValues[i] = null;
|
||||
}
|
||||
xmlnsLength = 0;
|
||||
// ]NOCPP]
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used in C++ to release special <code>isindex</code>
|
||||
* attribute values whose ownership is not transferred.
|
||||
*/
|
||||
void releaseValue(int i) {
|
||||
Portability.releaseString(values[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is only used for <code>AttributeName</code> ownership transfer
|
||||
* in the isindex case to avoid freeing custom names twice in C++.
|
||||
*/
|
||||
void clearWithoutReleasingContents() {
|
||||
for (int i = 0; i < length; i++) {
|
||||
names[i] = null;
|
||||
values[i] = null;
|
||||
}
|
||||
length = 0;
|
||||
}
|
||||
|
||||
boolean contains(AttributeName name) {
|
||||
|
|
@ -508,13 +422,11 @@ public final class HtmlAttributes implements Attributes {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
// [NOCPP[
|
||||
for (int i = 0; i < xmlnsLength; i++) {
|
||||
if (name.equalsAnother(xmlnsNames[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// ]NOCPP]
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -529,27 +441,20 @@ public final class HtmlAttributes implements Attributes {
|
|||
public HtmlAttributes cloneAttributes(Interner interner)
|
||||
throws SAXException {
|
||||
assert (length == 0
|
||||
// [NOCPP[
|
||||
&& xmlnsLength == 0
|
||||
// ]NOCPP]
|
||||
)
|
||||
|| mode == 0 || mode == 3;
|
||||
HtmlAttributes clone = new HtmlAttributes(0);
|
||||
for (int i = 0; i < length; i++) {
|
||||
clone.addAttribute(names[i].cloneAttributeName(interner),
|
||||
Portability.newStringFromString(values[i])
|
||||
// [NOCPP[
|
||||
clone.addAttribute(names[i],
|
||||
values[i]
|
||||
, XmlViolationPolicy.ALLOW
|
||||
// ]NOCPP]
|
||||
// CPPONLY: , lines[i]
|
||||
);
|
||||
}
|
||||
// [NOCPP[
|
||||
for (int i = 0; i < xmlnsLength; i++) {
|
||||
clone.addAttribute(xmlnsNames[i], xmlnsValues[i],
|
||||
XmlViolationPolicy.ALLOW);
|
||||
}
|
||||
// ]NOCPP]
|
||||
return clone; // XXX!!!
|
||||
}
|
||||
|
||||
|
|
@ -568,9 +473,10 @@ public final class HtmlAttributes implements Attributes {
|
|||
for (int j = 0; j < otherLength; j++) {
|
||||
if (ownLocal == other.names[j].getLocal(AttributeName.HTML)) {
|
||||
found = true;
|
||||
if (!Portability.stringEqualsString(values[i], other.values[j])) {
|
||||
if (!values[i].equals(other.values[j])) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
|
|
@ -579,9 +485,7 @@ public final class HtmlAttributes implements Attributes {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// [NOCPP[
|
||||
|
||||
|
||||
void processNonNcNames(TreeBuilder<?> treeBuilder, XmlViolationPolicy namePolicy) throws SAXException {
|
||||
for (int i = 0; i < length; i++) {
|
||||
AttributeName attName = names[i];
|
||||
|
|
@ -613,8 +517,4 @@ public final class HtmlAttributes implements Attributes {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ]NOCPP]
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -434,6 +434,8 @@ public class Tokenizer implements Locator {
|
|||
*/
|
||||
protected AttributeName attributeName = null;
|
||||
|
||||
// CPPONLY: private AttributeName nonInternedAttributeName = null;
|
||||
|
||||
// [NOCPP[
|
||||
|
||||
/**
|
||||
|
|
@ -530,6 +532,7 @@ public class Tokenizer implements Locator {
|
|||
this.tagName = null;
|
||||
this.nonInternedTagName = new ElementName();
|
||||
this.attributeName = null;
|
||||
// CPPONLY: this.nonInternedAttributeName = new AttributeName();
|
||||
this.doctypeName = null;
|
||||
this.publicIdentifier = null;
|
||||
this.systemIdentifier = null;
|
||||
|
|
@ -560,6 +563,7 @@ public class Tokenizer implements Locator {
|
|||
this.tagName = null;
|
||||
this.nonInternedTagName = new ElementName();
|
||||
this.attributeName = null;
|
||||
// CPPONLY: this.nonInternedAttributeName = new AttributeName();
|
||||
this.doctypeName = null;
|
||||
this.publicIdentifier = null;
|
||||
this.systemIdentifier = null;
|
||||
|
|
@ -1174,11 +1178,17 @@ public class Tokenizer implements Locator {
|
|||
}
|
||||
|
||||
private void attributeNameComplete() throws SAXException {
|
||||
attributeName = AttributeName.nameByBuffer(strBuf, 0, strBufLen
|
||||
// [NOCPP[
|
||||
, namePolicy != XmlViolationPolicy.ALLOW
|
||||
// ]NOCPP]
|
||||
, interner);
|
||||
attributeName = AttributeName.nameByBuffer(strBuf, 0, strBufLen, interner);
|
||||
if (attributeName == null) {
|
||||
// [NOCPP[
|
||||
attributeName = AttributeName.createAttributeName(
|
||||
Portability.newLocalNameFromBuffer(strBuf, 0, strBufLen,
|
||||
interner),
|
||||
namePolicy != XmlViolationPolicy.ALLOW);
|
||||
// ]NOCPP]
|
||||
// CPPONLY: nonInternedAttributeName.setNameForNonInterned(Portability.newLocalNameFromBuffer(strBuf, 0, strBufLen, interner));
|
||||
// CPPONLY: attributeName = nonInternedAttributeName;
|
||||
}
|
||||
clearStrBufAfterUse();
|
||||
|
||||
if (attributes == null) {
|
||||
|
|
@ -1195,7 +1205,6 @@ public class Tokenizer implements Locator {
|
|||
*/
|
||||
if (attributes.contains(attributeName)) {
|
||||
errDuplicateAttribute();
|
||||
attributeName.release();
|
||||
attributeName = null;
|
||||
}
|
||||
}
|
||||
|
|
@ -1244,8 +1253,7 @@ public class Tokenizer implements Locator {
|
|||
// [NOCPP[
|
||||
}
|
||||
// ]NOCPP]
|
||||
attributeName = null; // attributeName has been adopted by the
|
||||
// |attributes| object
|
||||
attributeName = null;
|
||||
} else {
|
||||
clearStrBufAfterUse();
|
||||
}
|
||||
|
|
@ -1276,8 +1284,7 @@ public class Tokenizer implements Locator {
|
|||
// ]NOCPP]
|
||||
// CPPONLY: , attributeLine
|
||||
);
|
||||
attributeName = null; // attributeName has been adopted by the
|
||||
// |attributes| object
|
||||
attributeName = null;
|
||||
} else {
|
||||
// We have a duplicate attribute. Explicitly discard its value.
|
||||
clearStrBufAfterUse();
|
||||
|
|
@ -6667,10 +6674,8 @@ public class Tokenizer implements Locator {
|
|||
}
|
||||
tagName = null;
|
||||
nonInternedTagName.setNameForNonInterned(null);
|
||||
if (attributeName != null) {
|
||||
attributeName.release();
|
||||
attributeName = null;
|
||||
}
|
||||
attributeName = null;
|
||||
// CPPONLY: nonInternedAttributeName.setNameForNonInterned(null);
|
||||
tokenHandler.endTokenization();
|
||||
if (attributes != null) {
|
||||
// [NOCPP[
|
||||
|
|
@ -6747,13 +6752,8 @@ public class Tokenizer implements Locator {
|
|||
endTag = false;
|
||||
shouldSuspend = false;
|
||||
initDoctypeFields();
|
||||
if (tagName != null) {
|
||||
tagName = null;
|
||||
}
|
||||
if (attributeName != null) {
|
||||
attributeName.release();
|
||||
attributeName = null;
|
||||
}
|
||||
tagName = null;
|
||||
attributeName = null;
|
||||
if (newAttributesEachTime) {
|
||||
if (attributes != null) {
|
||||
Portability.delete(attributes);
|
||||
|
|
@ -6818,22 +6818,27 @@ public class Tokenizer implements Locator {
|
|||
} else if (other.tagName.isInterned()) {
|
||||
tagName = other.tagName;
|
||||
} else {
|
||||
// In the C++ case, We might be loading state from another
|
||||
// tokenizer that has atoms from a different tokenizer-scoped
|
||||
// atom table. Therefore, we have to obtain the correspoding
|
||||
// atom from our own atom table.
|
||||
// In the C++ case, the atoms in the other tokenizer are from a
|
||||
// different tokenizer-scoped atom table. Therefore, we have to
|
||||
// obtain the correspoding atom from our own atom table.
|
||||
nonInternedTagName.setNameForNonInterned(Portability.newLocalFromLocal(other.tagName.getName(), interner));
|
||||
tagName = nonInternedTagName;
|
||||
}
|
||||
|
||||
if (attributeName != null) {
|
||||
attributeName.release();
|
||||
}
|
||||
if (other.attributeName == null) {
|
||||
attributeName = null;
|
||||
} else {
|
||||
attributeName = other.attributeName.cloneAttributeName(interner);
|
||||
}
|
||||
// [NOCPP[
|
||||
attributeName = other.attributeName;
|
||||
// ]NOCPP]
|
||||
// CPPONLY: if (other.attributeName == null) {
|
||||
// CPPONLY: attributeName = null;
|
||||
// CPPONLY: } else if (other.attributeName.isInterned()) {
|
||||
// CPPONLY: attributeName = other.attributeName;
|
||||
// CPPONLY: } else {
|
||||
// CPPONLY: // In the C++ case, the atoms in the other tokenizer are from a
|
||||
// CPPONLY: // different tokenizer-scoped atom table. Therefore, we have to
|
||||
// CPPONLY: // obtain the correspoding atom from our own atom table.
|
||||
// CPPONLY: nonInternedAttributeName.setNameForNonInterned(Portability.newLocalFromLocal(other.attributeName.getLocal(AttributeName.HTML), interner));
|
||||
// CPPONLY: attributeName = nonInternedAttributeName;
|
||||
// CPPONLY: }
|
||||
|
||||
Portability.delete(attributes);
|
||||
if (other.attributes == null) {
|
||||
|
|
@ -7075,6 +7080,7 @@ public class Tokenizer implements Locator {
|
|||
|
||||
void destructor() {
|
||||
Portability.delete(nonInternedTagName);
|
||||
// CPPONLY: Portability.delete(nonInternedAttributeName);
|
||||
nonInternedTagName = null;
|
||||
// The translator will write refcount tracing stuff here
|
||||
Portability.delete(attributes);
|
||||
|
|
|
|||
|
|
@ -2326,85 +2326,74 @@ public abstract class TreeBuilder<T> implements TokenHandler,
|
|||
selfClosing = false;
|
||||
attributes = null; // CPP
|
||||
break starttagloop;
|
||||
case ISINDEX:
|
||||
errIsindex();
|
||||
if (formPointer != null && !isTemplateContents()) {
|
||||
break starttagloop;
|
||||
}
|
||||
implicitlyCloseP();
|
||||
HtmlAttributes formAttrs = new HtmlAttributes(0);
|
||||
int actionIndex = attributes.getIndex(AttributeName.ACTION);
|
||||
if (actionIndex > -1) {
|
||||
formAttrs.addAttribute(
|
||||
AttributeName.ACTION,
|
||||
attributes.getValueNoBoundsCheck(actionIndex)
|
||||
// [NOCPP[
|
||||
, XmlViolationPolicy.ALLOW
|
||||
// ]NOCPP]
|
||||
// CPPONLY: , attributes.getLineNoBoundsCheck(actionIndex)
|
||||
);
|
||||
}
|
||||
appendToCurrentNodeAndPushFormElementMayFoster(formAttrs);
|
||||
appendVoidElementToCurrentMayFoster(
|
||||
ElementName.HR,
|
||||
HtmlAttributes.EMPTY_ATTRIBUTES);
|
||||
appendToCurrentNodeAndPushElementMayFoster(
|
||||
ElementName.LABEL,
|
||||
HtmlAttributes.EMPTY_ATTRIBUTES);
|
||||
int promptIndex = attributes.getIndex(AttributeName.PROMPT);
|
||||
if (promptIndex > -1) {
|
||||
@Auto char[] prompt = Portability.newCharArrayFromString(attributes.getValueNoBoundsCheck(promptIndex));
|
||||
appendCharacters(stack[currentPtr].node,
|
||||
prompt, 0, prompt.length);
|
||||
} else {
|
||||
appendIsindexPrompt(stack[currentPtr].node);
|
||||
}
|
||||
HtmlAttributes inputAttributes = new HtmlAttributes(
|
||||
0);
|
||||
inputAttributes.addAttribute(
|
||||
AttributeName.NAME,
|
||||
Portability.newStringFromLiteral("isindex")
|
||||
// [NOCPP[
|
||||
, XmlViolationPolicy.ALLOW
|
||||
// ]NOCPP]
|
||||
// CPPONLY: , tokenizer.getLineNumber()
|
||||
);
|
||||
for (int i = 0; i < attributes.getLength(); i++) {
|
||||
AttributeName attributeQName = attributes.getAttributeNameNoBoundsCheck(i);
|
||||
if (AttributeName.NAME == attributeQName
|
||||
|| AttributeName.PROMPT == attributeQName) {
|
||||
attributes.releaseValue(i);
|
||||
} else if (AttributeName.ACTION != attributeQName) {
|
||||
inputAttributes.addAttribute(
|
||||
attributeQName,
|
||||
attributes.getValueNoBoundsCheck(i)
|
||||
// [NOCPP[
|
||||
, XmlViolationPolicy.ALLOW
|
||||
// ]NOCPP]
|
||||
// CPPONLY: , attributes.getLineNoBoundsCheck(i)
|
||||
);
|
||||
}
|
||||
}
|
||||
attributes.clearWithoutReleasingContents();
|
||||
appendVoidElementToCurrentMayFoster(
|
||||
"input",
|
||||
inputAttributes, formPointer);
|
||||
pop(); // label
|
||||
appendVoidElementToCurrentMayFoster(
|
||||
ElementName.HR,
|
||||
HtmlAttributes.EMPTY_ATTRIBUTES);
|
||||
pop(); // form
|
||||
|
||||
if (!isTemplateContents()) {
|
||||
formPointer = null;
|
||||
}
|
||||
|
||||
selfClosing = false;
|
||||
// Portability.delete(formAttrs);
|
||||
// Portability.delete(inputAttributes);
|
||||
// Don't delete attributes, they are deleted
|
||||
// later
|
||||
break starttagloop;
|
||||
// CPPONLY:case ISINDEX:
|
||||
// CPPONLY: errIsindex();
|
||||
// CPPONLY: if (formPointer != null && !isTemplateContents()) {
|
||||
// CPPONLY: break starttagloop;
|
||||
// CPPONLY: }
|
||||
// CPPONLY: implicitlyCloseP();
|
||||
// CPPONLY: HtmlAttributes formAttrs = new HtmlAttributes(0);
|
||||
// CPPONLY: int actionIndex = attributes.getIndex(AttributeName.ACTION);
|
||||
// CPPONLY: if (actionIndex > -1) {
|
||||
// CPPONLY: formAttrs.addAttribute(
|
||||
// CPPONLY: AttributeName.ACTION,
|
||||
// CPPONLY: attributes.getValueNoBoundsCheck(actionIndex),
|
||||
// CPPONLY: attributes.getLineNoBoundsCheck(actionIndex)
|
||||
// CPPONLY: );
|
||||
// CPPONLY: }
|
||||
// CPPONLY: appendToCurrentNodeAndPushFormElementMayFoster(formAttrs);
|
||||
// CPPONLY: appendVoidElementToCurrentMayFoster(
|
||||
// CPPONLY: ElementName.HR,
|
||||
// CPPONLY: HtmlAttributes.EMPTY_ATTRIBUTES);
|
||||
// CPPONLY: appendToCurrentNodeAndPushElementMayFoster(
|
||||
// CPPONLY: ElementName.LABEL,
|
||||
// CPPONLY: HtmlAttributes.EMPTY_ATTRIBUTES);
|
||||
// CPPONLY: int promptIndex = attributes.getIndex(AttributeName.PROMPT);
|
||||
// CPPONLY: if (promptIndex > -1) {
|
||||
// CPPONLY: @Auto char[] prompt = Portability.newCharArrayFromString(attributes.getValueNoBoundsCheck(promptIndex));
|
||||
// CPPONLY: appendCharacters(stack[currentPtr].node,
|
||||
// CPPONLY: prompt, 0, prompt.length);
|
||||
// CPPONLY: } else {
|
||||
// CPPONLY: appendIsindexPrompt(stack[currentPtr].node);
|
||||
// CPPONLY: }
|
||||
// CPPONLY: HtmlAttributes inputAttributes = new HtmlAttributes(
|
||||
// CPPONLY: 0);
|
||||
// CPPONLY: inputAttributes.addAttribute(
|
||||
// CPPONLY: AttributeName.NAME,
|
||||
// CPPONLY: Portability.newStringFromLiteral("isindex"),
|
||||
// CPPONLY: tokenizer.getLineNumber()
|
||||
// CPPONLY: );
|
||||
// CPPONLY: for (int i = 0; i < attributes.getLength(); i++) {
|
||||
// CPPONLY: @Local String attributeQName = attributes.getLocalNameNoBoundsCheck(i);
|
||||
// CPPONLY: if ("name" == attributeQName
|
||||
// CPPONLY: || "prompt" == attributeQName) {
|
||||
// CPPONLY: attributes.releaseValue(i);
|
||||
// CPPONLY: } else if ("action" != attributeQName) {
|
||||
// CPPONLY: inputAttributes.AddAttributeWithLocal(
|
||||
// CPPONLY: attributeQName,
|
||||
// CPPONLY: attributes.getValueNoBoundsCheck(i),
|
||||
// CPPONLY: attributes.getLineNoBoundsCheck(i)
|
||||
// CPPONLY: );
|
||||
// CPPONLY: }
|
||||
// CPPONLY: }
|
||||
// CPPONLY: attributes.clearWithoutReleasingContents();
|
||||
// CPPONLY: appendVoidElementToCurrentMayFoster(
|
||||
// CPPONLY: "input",
|
||||
// CPPONLY: inputAttributes, formPointer);
|
||||
// CPPONLY: pop(); // label
|
||||
// CPPONLY: appendVoidElementToCurrentMayFoster(
|
||||
// CPPONLY: ElementName.HR,
|
||||
// CPPONLY: HtmlAttributes.EMPTY_ATTRIBUTES);
|
||||
// CPPONLY: pop(); // form
|
||||
// CPPONLY:
|
||||
// CPPONLY: if (!isTemplateContents()) {
|
||||
// CPPONLY: formPointer = null;
|
||||
// CPPONLY: }
|
||||
// CPPONLY:
|
||||
// CPPONLY: selfClosing = false;
|
||||
// CPPONLY: // Don't delete attributes, they are deleted
|
||||
// CPPONLY: // later
|
||||
// CPPONLY: break starttagloop;
|
||||
case TEXTAREA:
|
||||
appendToCurrentNodeAndPushElementMayFoster(
|
||||
elementName,
|
||||
|
|
@ -3837,7 +3826,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
|
|||
case INPUT:
|
||||
case KEYGEN: // XXX??
|
||||
case HR:
|
||||
case ISINDEX:
|
||||
// CPPONLY: case ISINDEX:
|
||||
case IFRAME:
|
||||
case NOEMBED: // XXX???
|
||||
case NOFRAMES: // XXX??
|
||||
|
|
@ -5681,7 +5670,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
|
|||
protected abstract void appendCharacters(T parent, @NoLength char[] buf,
|
||||
int start, int length) throws SAXException;
|
||||
|
||||
protected abstract void appendIsindexPrompt(T parent) throws SAXException;
|
||||
// CPPONLY: protected abstract void appendIsindexPrompt(T parent) throws SAXException;
|
||||
|
||||
protected abstract void appendComment(T parent, @NoLength char[] buf,
|
||||
int start, int length) throws SAXException;
|
||||
|
|
@ -6377,9 +6366,9 @@ public abstract class TreeBuilder<T> implements TokenHandler,
|
|||
err("Saw a start tag \u201Cimage\u201D.");
|
||||
}
|
||||
|
||||
private void errIsindex() throws SAXException {
|
||||
err("\u201Cisindex\u201D seen.");
|
||||
}
|
||||
// CPPONLY: private void errIsindex() throws SAXException {
|
||||
// CPPONLY: err("\u201Cisindex\u201D seen.");
|
||||
// CPPONLY: }
|
||||
|
||||
private void errFooSeenWhenFooOpen(@Local String name) throws SAXException {
|
||||
if (errorHandler == null) {
|
||||
|
|
|
|||
|
|
@ -23,26 +23,24 @@
|
|||
|
||||
package nu.validator.htmlparser.sax;
|
||||
|
||||
import nu.validator.htmlparser.impl.HtmlAttributes;
|
||||
import nu.validator.htmlparser.impl.TreeBuilder;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
|
||||
class SAXStreamer extends TreeBuilder<Attributes>{
|
||||
import nu.validator.htmlparser.impl.HtmlAttributes;
|
||||
import nu.validator.htmlparser.impl.TreeBuilder;
|
||||
|
||||
private static final char[] ISINDEX_PROMPT = "This is a searchable index. Enter search keywords: ".toCharArray();
|
||||
class SAXStreamer extends TreeBuilder<Attributes>{
|
||||
|
||||
private ContentHandler contentHandler = null;
|
||||
private LexicalHandler lexicalHandler = null;
|
||||
|
||||
|
||||
SAXStreamer() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void addAttributesToElement(Attributes element, HtmlAttributes attributes) throws SAXException {
|
||||
Attributes existingAttrs = element;
|
||||
|
|
@ -59,14 +57,6 @@ class SAXStreamer extends TreeBuilder<Attributes>{
|
|||
contentHandler.characters(buf, start, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see nu.validator.htmlparser.impl.TreeBuilder#appendIsindexPrompt(java.lang.Object)
|
||||
*/
|
||||
@Override protected void appendIsindexPrompt(Attributes parent)
|
||||
throws SAXException {
|
||||
contentHandler.characters(ISINDEX_PROMPT, 0, ISINDEX_PROMPT.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendChildrenToNewParent(Attributes oldParent, Attributes newParent) throws SAXException {
|
||||
fatal();
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
package nu.validator.htmlparser.sax;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import nu.validator.htmlparser.impl.HtmlAttributes;
|
||||
import nu.validator.htmlparser.impl.TreeBuilder;
|
||||
import nu.validator.saxtree.Characters;
|
||||
|
|
@ -34,12 +36,8 @@ import nu.validator.saxtree.Element;
|
|||
import nu.validator.saxtree.Node;
|
||||
import nu.validator.saxtree.ParentNode;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
class SAXTreeBuilder extends TreeBuilder<Element> {
|
||||
|
||||
private static final char[] ISINDEX_PROMPT = "This is a searchable index. Enter search keywords: ".toCharArray();
|
||||
|
||||
private Document document;
|
||||
|
||||
private Node cachedTable = null;
|
||||
|
|
@ -65,14 +63,6 @@ class SAXTreeBuilder extends TreeBuilder<Element> {
|
|||
parent.appendChild(new Characters(tokenizer, buf, start, length));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see nu.validator.htmlparser.impl.TreeBuilder#appendIsindexPrompt(java.lang.Object)
|
||||
*/
|
||||
@Override protected void appendIsindexPrompt(Element parent)
|
||||
throws SAXException {
|
||||
parent.appendChild(new Characters(tokenizer, ISINDEX_PROMPT, 0, ISINDEX_PROMPT.length));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasChildren(Element element) {
|
||||
return element.getFirstChild() != null;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue