Skip to content

Commit 9c8e0e4

Browse files
committed
tmp
1 parent e8726ba commit 9c8e0e4

4 files changed

Lines changed: 164 additions & 32 deletions

File tree

src/main/java/ch/digitalfondue/jfiveparse/AttributeNode.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ public final class AttributeNode {
2323
String originalName;
2424

2525
private String value;
26-
private ResizableCharBuilder valueBuilder;
26+
private char[] valueBuilder;
27+
private int valueBuilderLen;
2728

2829
//
2930
String prefix;
@@ -38,9 +39,10 @@ public AttributeNode(String name, String value) {
3839
this.value = value;
3940
}
4041

41-
AttributeNode(String name, String originalName, ResizableCharBuilder value, int attributeQuoteType) {
42+
AttributeNode(String name, String originalName, char[] value, int valueLen, int attributeQuoteType) {
4243
this.name = name;
4344
this.valueBuilder = value;
45+
this.valueBuilderLen = valueLen;
4446
this.originalName = originalName;
4547
this.attributeQuoteType = attributeQuoteType;
4648
}
@@ -50,6 +52,7 @@ public AttributeNode(String name, String value) {
5052
this.originalName = a.originalName;
5153
this.value = a.value;
5254
this.valueBuilder = a.valueBuilder;
55+
this.valueBuilderLen = a.valueBuilderLen;
5356
this.prefix = a.prefix;
5457
this.namespace = a.namespace;
5558
this.attributeQuoteType = a.attributeQuoteType;
@@ -63,7 +66,7 @@ public AttributeNode(String name, String value, String prefix, String namespace)
6366

6467
public String getValue() {
6568
if (value == null && valueBuilder != null) {
66-
value = valueBuilder.toString();
69+
value = new String(valueBuilder, 0, valueBuilderLen);
6770
valueBuilder = null;
6871
}
6972
return value;

src/main/java/ch/digitalfondue/jfiveparse/Attributes.java

Lines changed: 135 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
public final class Attributes implements Iterable<AttributeNode> {
2121

22+
private AttributeNode[] smallAttributes;
23+
private int size;
2224
private Map<String, AttributeNode> attributes;
2325

2426
public Attributes() {
@@ -29,7 +31,17 @@ public Attributes(Map<String, AttributeNode> attributes) {
2931
}
3032

3133
public boolean containsKey(String key) {
32-
return attributes != null && attributes.containsKey(key);
34+
if (attributes != null) {
35+
return attributes.containsKey(key);
36+
}
37+
if (smallAttributes != null) {
38+
for (int i = 0; i < size; i++) {
39+
if (smallAttributes[i].name.equals(key)) {
40+
return true;
41+
}
42+
}
43+
}
44+
return false;
3345
}
3446

3547
@Override
@@ -39,67 +51,172 @@ public boolean equals(Object obj) {
3951
}
4052

4153
if (obj instanceof Attributes a) {
42-
return Objects.equals(attributes, a.attributes);
54+
if (attributes != null || a.attributes != null) {
55+
return Objects.equals(asMap(), a.asMap());
56+
}
57+
if (size != a.size) {
58+
return false;
59+
}
60+
for (int i = 0; i < size; i++) {
61+
if (!smallAttributes[i].equals(a.smallAttributes[i])) {
62+
return false;
63+
}
64+
}
65+
return true;
4366
}
4467
return false;
4568
}
4669

70+
private Map<String, AttributeNode> asMap() {
71+
if (attributes != null) {
72+
return attributes;
73+
}
74+
if (size == 0) {
75+
return Collections.emptyMap();
76+
}
77+
Map<String, AttributeNode> m = new LinkedHashMap<>();
78+
for (int i = 0; i < size; i++) {
79+
m.put(smallAttributes[i].name, smallAttributes[i]);
80+
}
81+
return m;
82+
}
83+
4784
@Override
4885
public int hashCode() {
49-
return Objects.hashCode(attributes);
86+
if (attributes != null) {
87+
return Objects.hashCode(attributes);
88+
}
89+
int hash = 7;
90+
for (int i = 0; i < size; i++) {
91+
hash = 31 * hash + smallAttributes[i].hashCode();
92+
}
93+
return hash;
5094
}
5195

5296
public Attributes copy() {
5397
Attributes a = new Attributes();
5498
if (attributes != null) {
99+
a.attributes = new LinkedHashMap<>();
55100
for (var v : attributes.values()) {
56101
a.put(new AttributeNode(v));
57102
}
58-
return a;
103+
} else if (smallAttributes != null) {
104+
a.smallAttributes = new AttributeNode[smallAttributes.length];
105+
a.size = size;
106+
for (int i = 0; i < size; i++) {
107+
a.smallAttributes[i] = new AttributeNode(smallAttributes[i]);
108+
}
59109
}
60110
return a;
61111
}
62112

63113
public AttributeNode get(String key) {
64-
return attributes == null ? null : attributes.get(key);
114+
if (attributes != null) {
115+
return attributes.get(key);
116+
}
117+
if (smallAttributes != null) {
118+
for (int i = 0; i < size; i++) {
119+
if (smallAttributes[i].name.equals(key)) {
120+
return smallAttributes[i];
121+
}
122+
}
123+
}
124+
return null;
65125
}
66126

67127
Set<String> keySet() {
68-
return attributes == null ? Set.of() : attributes.keySet();
69-
}
70-
71-
private void ensureMap() {
72-
if (attributes == null) {
73-
attributes = new LinkedHashMap<>();
128+
if (attributes != null) {
129+
return attributes.keySet();
130+
}
131+
if (size == 0) {
132+
return Collections.emptySet();
74133
}
134+
Set<String> s = new LinkedHashSet<>();
135+
for (int i = 0; i < size; i++) {
136+
s.add(smallAttributes[i].name);
137+
}
138+
return s;
75139
}
76140

77141
public void put(AttributeNode attribute) {
78-
ensureMap();
79-
attributes.put(attribute.getName(), attribute);
142+
if (attributes != null) {
143+
attributes.put(attribute.getName(), attribute);
144+
return;
145+
}
146+
147+
if (smallAttributes == null) {
148+
smallAttributes = new AttributeNode[2];
149+
}
150+
151+
for (int i = 0; i < size; i++) {
152+
if (smallAttributes[i].name.equals(attribute.name)) {
153+
smallAttributes[i] = attribute;
154+
return;
155+
}
156+
}
157+
158+
if (size < 8) {
159+
if (size == smallAttributes.length) {
160+
smallAttributes = Arrays.copyOf(smallAttributes, smallAttributes.length * 2);
161+
}
162+
smallAttributes[size++] = attribute;
163+
} else {
164+
attributes = new LinkedHashMap<>();
165+
for (int i = 0; i < size; i++) {
166+
attributes.put(smallAttributes[i].name, smallAttributes[i]);
167+
}
168+
attributes.put(attribute.name, attribute);
169+
smallAttributes = null;
170+
}
80171
}
81172

82173
public void put(String key, String value) {
83-
ensureMap();
84-
attributes.put(key, new AttributeNode(key, value));
174+
put(new AttributeNode(key, value));
85175
}
86176

87177
public void remove(String key) {
88178
if (attributes != null) {
89179
attributes.remove(key);
180+
} else if (smallAttributes != null) {
181+
for (int i = 0; i < size; i++) {
182+
if (smallAttributes[i].name.equals(key)) {
183+
System.arraycopy(smallAttributes, i + 1, smallAttributes, i, size - i - 1);
184+
smallAttributes[--size] = null;
185+
return;
186+
}
187+
}
90188
}
91189
}
92190

93191
public boolean isEmpty() {
94-
return attributes == null || attributes.isEmpty();
192+
return (attributes == null || attributes.isEmpty()) && size == 0;
95193
}
96194

97195
@Override
98196
public Iterator<AttributeNode> iterator() {
99-
return attributes == null ? Collections.emptyIterator() : attributes.values().iterator();
197+
if (attributes != null) {
198+
return attributes.values().iterator();
199+
}
200+
if (size == 0) {
201+
return Collections.emptyIterator();
202+
}
203+
return new Iterator<>() {
204+
int i = 0;
205+
206+
@Override
207+
public boolean hasNext() {
208+
return i < size;
209+
}
210+
211+
@Override
212+
public AttributeNode next() {
213+
return smallAttributes[i++];
214+
}
215+
};
100216
}
101217

102218
public String getNamedItem(String name) {
103-
return attributes != null && attributes.containsKey(name) ? attributes.get(name).getValue() : null;
219+
AttributeNode a = get(name);
220+
return a != null ? a.getValue() : null;
104221
}
105222
}

src/main/java/ch/digitalfondue/jfiveparse/Tokenizer.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ final class Tokenizer {
3737
// tag related
3838
private Attributes attributes;
3939
private final ResizableCharBuilder currentAttributeName = new ResizableCharBuilder();
40-
private ResizableCharBuilder currentAttributeValue;
40+
private final ResizableCharBuilder currentAttributeValue = new ResizableCharBuilder();
4141
private int currentAttributeQuoteType;
4242
private boolean selfClosing;
4343
final ResizableCharBuilder tagName = new ResizableCharBuilder();
@@ -405,7 +405,8 @@ void addCurrentAttributeInAttributes() {
405405
attributes.put(new AttributeNode(
406406
curAttrName,
407407
currentAttributeName.containsUpperCase ? currentAttributeName.toString() : curAttrName,
408-
currentAttributeValue,
408+
currentAttributeValue.copyBackingCharArray(),
409+
currentAttributeValue.pos(),
409410
currentAttributeQuoteType
410411
));
411412
}
@@ -416,7 +417,7 @@ void addCurrentAttributeInAttributes() {
416417
tokenHandler.emitParseError();
417418
} finally {
418419
currentAttributeName.reset();
419-
currentAttributeValue = null;
420+
currentAttributeValue.reset();
420421
}
421422
}
422423

@@ -426,7 +427,7 @@ void startNewAttributeAndAppendToName(int chr) {
426427
}
427428
addCurrentAttributeInAttributes();
428429
currentAttributeName.reset();
429-
currentAttributeValue = new ResizableCharBuilder();
430+
currentAttributeValue.reset();
430431
currentAttributeQuoteType = TokenizerState.ATTRIBUTE_VALUE_UNQUOTED_STATE;
431432
appendCurrentAttributeName(chr);
432433
}
@@ -440,7 +441,7 @@ void newEndTokenTag() {
440441
isEndTagToken = true;
441442
attributes = null;
442443
currentAttributeName.reset();
443-
currentAttributeValue = null;
444+
currentAttributeValue.reset();
444445
}
445446

446447

@@ -454,7 +455,7 @@ void createNewStartTagToken(int chr) {
454455
isEndTagToken = false;
455456
attributes = null;
456457
currentAttributeName.reset();
457-
currentAttributeValue = null;
458+
currentAttributeValue.reset();
458459
selfClosing = false;
459460
}
460461

src/main/java/ch/digitalfondue/jfiveparse/TreeConstructor.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ class TreeConstructor {
9797
//
9898
private boolean quirksMode;
9999
private boolean inHtmlContent;
100+
private final Node[] insertionBase = new Node[2];
100101

101102
// ----
102103

@@ -625,23 +626,33 @@ Node[] findAppropriatePlaceForInsertingNode(Element overrideTarget) {
625626
// 3
626627
if (lastTemplatePos != -1 && ((lastTablePos == -1) || (lastTemplatePos > lastTablePos))) {
627628
// inside the template
628-
return new Node[] { openElements.get(lastTemplatePos), null };
629+
insertionBase[0] = openElements.get(lastTemplatePos);
630+
insertionBase[1] = null;
631+
return insertionBase;
629632
}
630633
// 4
631634
if (lastTablePos == -1) {
632-
return new Node[] { openElements.get(0), null };
635+
insertionBase[0] = openElements.get(0);
636+
insertionBase[1] = null;
637+
return insertionBase;
633638
}
634639
// 5
635640
Element lastTable = openElements.get(lastTablePos);
636641
if (lastTable.getParentNode() != null) {
637-
return new Node[] { lastTable.getParentNode(), lastTable };
642+
insertionBase[0] = lastTable.getParentNode();
643+
insertionBase[1] = lastTable;
644+
return insertionBase;
638645
}
639646
// 6
640647
Element previous = openElements.get(lastTablePos - 1);
641648
// 7
642-
return new Node[] { previous, null };
649+
insertionBase[0] = previous;
650+
insertionBase[1] = null;
651+
return insertionBase;
643652
} else {
644-
return new Node[] { target, null };
653+
insertionBase[0] = target;
654+
insertionBase[1] = null;
655+
return insertionBase;
645656
}
646657
}
647658

0 commit comments

Comments
 (0)