| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2013 Google, Inc. All Rights Reserved. | |
| 3 * | |
| 4 * Redistribution and use in source and binary forms, with or without | |
| 5 * modification, are permitted provided that the following conditions | |
| 6 * are met: | |
| 7 * 1. Redistributions of source code must retain the above copyright | |
| 8 * notice, this list of conditions and the following disclaimer. | |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | |
| 10 * notice, this list of conditions and the following disclaimer in the | |
| 11 * documentation and/or other materials provided with the distribution. | |
| 12 * | |
| 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | |
| 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | |
| 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
| 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 24 */ | |
| 25 | |
| 26 #ifndef SKY_ENGINE_CORE_HTML_PARSER_HTMLTOKEN_H_ | |
| 27 #define SKY_ENGINE_CORE_HTML_PARSER_HTMLTOKEN_H_ | |
| 28 | |
| 29 #include "sky/engine/core/dom/Attribute.h" | |
| 30 #include "sky/engine/wtf/PassOwnPtr.h" | |
| 31 #include "sky/engine/wtf/RefCounted.h" | |
| 32 #include "sky/engine/wtf/RefPtr.h" | |
| 33 | |
| 34 namespace blink { | |
| 35 | |
| 36 static inline Attribute* findAttributeInVector(Vector<Attribute>& attributes, co
nst QualifiedName& name) | |
| 37 { | |
| 38 for (unsigned i = 0; i < attributes.size(); ++i) { | |
| 39 if (attributes.at(i).name() == name) | |
| 40 return &attributes.at(i); | |
| 41 } | |
| 42 return 0; | |
| 43 } | |
| 44 | |
| 45 class HTMLToken { | |
| 46 WTF_MAKE_NONCOPYABLE(HTMLToken); | |
| 47 WTF_MAKE_FAST_ALLOCATED; | |
| 48 public: | |
| 49 enum Type { | |
| 50 Uninitialized, | |
| 51 StartTag, | |
| 52 EndTag, | |
| 53 Character, | |
| 54 EndOfFile, | |
| 55 }; | |
| 56 | |
| 57 class Attribute { | |
| 58 public: | |
| 59 class Range { | |
| 60 public: | |
| 61 int start; | |
| 62 int end; | |
| 63 }; | |
| 64 | |
| 65 Range nameRange; | |
| 66 Range valueRange; | |
| 67 Vector<UChar, 32> name; | |
| 68 Vector<UChar, 32> value; | |
| 69 }; | |
| 70 | |
| 71 typedef Vector<Attribute, 10> AttributeList; | |
| 72 | |
| 73 // By using an inline capacity of 256, we avoid spilling over into an malloc
ed buffer | |
| 74 // approximately 99% of the time based on a non-scientific browse around a n
umber of | |
| 75 // popular web sites on 23 May 2013. | |
| 76 typedef Vector<UChar, 256> DataVector; | |
| 77 | |
| 78 HTMLToken() { clear(); } | |
| 79 | |
| 80 void clear() | |
| 81 { | |
| 82 m_type = Uninitialized; | |
| 83 m_range.start = 0; | |
| 84 m_range.end = 0; | |
| 85 m_baseOffset = 0; | |
| 86 // Don't call Vector::clear() as that would destroy the | |
| 87 // alloced VectorBuffer. If the innerHTML'd content has | |
| 88 // two 257 character text nodes in a row, we'll needlessly | |
| 89 // thrash malloc. When we finally finish the parse the | |
| 90 // HTMLToken will be destroyed and the VectorBuffer released. | |
| 91 m_data.shrink(0); | |
| 92 m_orAllData = 0; | |
| 93 } | |
| 94 | |
| 95 bool isUninitialized() { return m_type == Uninitialized; } | |
| 96 Type type() const { return m_type; } | |
| 97 | |
| 98 void makeEndOfFile() | |
| 99 { | |
| 100 ASSERT(m_type == Uninitialized); | |
| 101 m_type = EndOfFile; | |
| 102 } | |
| 103 | |
| 104 void setBaseOffset(int offset) | |
| 105 { | |
| 106 m_baseOffset = offset; | |
| 107 } | |
| 108 | |
| 109 void end(int endOffset) | |
| 110 { | |
| 111 m_range.end = endOffset - m_baseOffset; | |
| 112 } | |
| 113 | |
| 114 const DataVector& data() const | |
| 115 { | |
| 116 ASSERT(m_type == Character || m_type == StartTag || m_type == EndTag); | |
| 117 return m_data; | |
| 118 } | |
| 119 | |
| 120 bool isAll8BitData() const | |
| 121 { | |
| 122 return (m_orAllData <= 0xff); | |
| 123 } | |
| 124 | |
| 125 const DataVector& name() const | |
| 126 { | |
| 127 ASSERT(m_type == StartTag || m_type == EndTag); | |
| 128 return m_data; | |
| 129 } | |
| 130 | |
| 131 void appendToName(UChar character) | |
| 132 { | |
| 133 ASSERT(m_type == StartTag || m_type == EndTag); | |
| 134 ASSERT(character); | |
| 135 m_data.append(character); | |
| 136 m_orAllData |= character; | |
| 137 } | |
| 138 | |
| 139 /* Start/End Tag Tokens */ | |
| 140 | |
| 141 bool selfClosing() const | |
| 142 { | |
| 143 ASSERT(m_type == StartTag || m_type == EndTag); | |
| 144 return m_selfClosing; | |
| 145 } | |
| 146 | |
| 147 void setSelfClosing() | |
| 148 { | |
| 149 ASSERT(m_type == StartTag || m_type == EndTag); | |
| 150 m_selfClosing = true; | |
| 151 } | |
| 152 | |
| 153 void beginStartTag(LChar character) | |
| 154 { | |
| 155 ASSERT(character); | |
| 156 ASSERT(m_type == Uninitialized); | |
| 157 m_type = StartTag; | |
| 158 m_selfClosing = false; | |
| 159 m_currentAttribute = 0; | |
| 160 m_attributes.clear(); | |
| 161 | |
| 162 m_data.append(character); | |
| 163 } | |
| 164 | |
| 165 void beginEndTag(LChar character) | |
| 166 { | |
| 167 ASSERT(m_type == Uninitialized); | |
| 168 m_type = EndTag; | |
| 169 m_selfClosing = false; | |
| 170 m_currentAttribute = 0; | |
| 171 m_attributes.clear(); | |
| 172 | |
| 173 m_data.append(character); | |
| 174 } | |
| 175 | |
| 176 void beginEndTag(const Vector<LChar, 32>& characters) | |
| 177 { | |
| 178 ASSERT(m_type == Uninitialized); | |
| 179 m_type = EndTag; | |
| 180 m_selfClosing = false; | |
| 181 m_currentAttribute = 0; | |
| 182 m_attributes.clear(); | |
| 183 | |
| 184 m_data.appendVector(characters); | |
| 185 } | |
| 186 | |
| 187 void addNewAttribute() | |
| 188 { | |
| 189 ASSERT(m_type == StartTag || m_type == EndTag); | |
| 190 m_attributes.grow(m_attributes.size() + 1); | |
| 191 m_currentAttribute = &m_attributes.last(); | |
| 192 #if ENABLE(ASSERT) | |
| 193 m_currentAttribute->nameRange.start = 0; | |
| 194 m_currentAttribute->nameRange.end = 0; | |
| 195 m_currentAttribute->valueRange.start = 0; | |
| 196 m_currentAttribute->valueRange.end = 0; | |
| 197 #endif | |
| 198 } | |
| 199 | |
| 200 void beginAttributeName(int offset) | |
| 201 { | |
| 202 m_currentAttribute->nameRange.start = offset - m_baseOffset; | |
| 203 } | |
| 204 | |
| 205 void endAttributeName(int offset) | |
| 206 { | |
| 207 int index = offset - m_baseOffset; | |
| 208 m_currentAttribute->nameRange.end = index; | |
| 209 m_currentAttribute->valueRange.start = index; | |
| 210 m_currentAttribute->valueRange.end = index; | |
| 211 } | |
| 212 | |
| 213 void beginAttributeValue(int offset) | |
| 214 { | |
| 215 m_currentAttribute->valueRange.start = offset - m_baseOffset; | |
| 216 #if ENABLE(ASSERT) | |
| 217 m_currentAttribute->valueRange.end = 0; | |
| 218 #endif | |
| 219 } | |
| 220 | |
| 221 void endAttributeValue(int offset) | |
| 222 { | |
| 223 m_currentAttribute->valueRange.end = offset - m_baseOffset; | |
| 224 } | |
| 225 | |
| 226 void appendToAttributeName(UChar character) | |
| 227 { | |
| 228 ASSERT(character); | |
| 229 ASSERT(m_type == StartTag || m_type == EndTag); | |
| 230 ASSERT(m_currentAttribute->nameRange.start); | |
| 231 m_currentAttribute->name.append(character); | |
| 232 } | |
| 233 | |
| 234 void appendToAttributeValue(UChar character) | |
| 235 { | |
| 236 ASSERT(character); | |
| 237 ASSERT(m_type == StartTag || m_type == EndTag); | |
| 238 ASSERT(m_currentAttribute->valueRange.start); | |
| 239 m_currentAttribute->value.append(character); | |
| 240 } | |
| 241 | |
| 242 void appendToAttributeValue(size_t i, const String& value) | |
| 243 { | |
| 244 ASSERT(!value.isEmpty()); | |
| 245 ASSERT(m_type == StartTag || m_type == EndTag); | |
| 246 append(m_attributes[i].value, value); | |
| 247 } | |
| 248 | |
| 249 const AttributeList& attributes() const | |
| 250 { | |
| 251 ASSERT(m_type == StartTag || m_type == EndTag); | |
| 252 return m_attributes; | |
| 253 } | |
| 254 | |
| 255 const Attribute* getAttributeItem(const QualifiedName& name) const | |
| 256 { | |
| 257 for (unsigned i = 0; i < m_attributes.size(); ++i) { | |
| 258 if (AtomicString(m_attributes.at(i).name) == name.localName()) | |
| 259 return &m_attributes.at(i); | |
| 260 } | |
| 261 return 0; | |
| 262 } | |
| 263 | |
| 264 /* Character Tokens */ | |
| 265 | |
| 266 // Starting a character token works slightly differently than starting | |
| 267 // other types of tokens because we want to save a per-character branch. | |
| 268 void ensureIsCharacterToken() | |
| 269 { | |
| 270 ASSERT(m_type == Uninitialized || m_type == Character); | |
| 271 m_type = Character; | |
| 272 } | |
| 273 | |
| 274 const DataVector& characters() const | |
| 275 { | |
| 276 ASSERT(m_type == Character); | |
| 277 return m_data; | |
| 278 } | |
| 279 | |
| 280 void appendToCharacter(char character) | |
| 281 { | |
| 282 ASSERT(m_type == Character); | |
| 283 m_data.append(character); | |
| 284 } | |
| 285 | |
| 286 void appendToCharacter(UChar character) | |
| 287 { | |
| 288 ASSERT(m_type == Character); | |
| 289 m_data.append(character); | |
| 290 m_orAllData |= character; | |
| 291 } | |
| 292 | |
| 293 void appendToCharacter(const Vector<LChar, 32>& characters) | |
| 294 { | |
| 295 ASSERT(m_type == Character); | |
| 296 m_data.appendVector(characters); | |
| 297 } | |
| 298 | |
| 299 private: | |
| 300 Type m_type; | |
| 301 Attribute::Range m_range; // Always starts at zero. | |
| 302 int m_baseOffset; | |
| 303 DataVector m_data; | |
| 304 UChar m_orAllData; | |
| 305 | |
| 306 // For StartTag and EndTag | |
| 307 bool m_selfClosing; | |
| 308 AttributeList m_attributes; | |
| 309 | |
| 310 // A pointer into m_attributes used during lexing. | |
| 311 Attribute* m_currentAttribute; | |
| 312 }; | |
| 313 | |
| 314 } | |
| 315 | |
| 316 #endif // SKY_ENGINE_CORE_HTML_PARSER_HTMLTOKEN_H_ | |
| OLD | NEW |