| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/css/parser/CSSTokenizer.h" | 5 #include "core/css/parser/CSSTokenizer.h" |
| 6 | 6 |
| 7 namespace blink { | 7 namespace blink { |
| 8 #include "core/CSSTokenizerCodepoints.cpp" | 8 #include "core/CSSTokenizerCodepoints.cpp" |
| 9 } | 9 } |
| 10 | 10 |
| 11 #include "core/css/parser/CSSParserIdioms.h" |
| 11 #include "core/css/parser/CSSParserObserverWrapper.h" | 12 #include "core/css/parser/CSSParserObserverWrapper.h" |
| 12 #include "core/css/parser/CSSParserTokenRange.h" | 13 #include "core/css/parser/CSSParserTokenRange.h" |
| 13 #include "core/css/parser/CSSTokenizerInputStream.h" | 14 #include "core/css/parser/CSSTokenizerInputStream.h" |
| 14 #include "core/html/parser/HTMLParserIdioms.h" | 15 #include "core/html/parser/HTMLParserIdioms.h" |
| 15 #include "wtf/text/CharacterNames.h" | 16 #include "wtf/text/CharacterNames.h" |
| 16 | 17 |
| 17 namespace blink { | 18 namespace blink { |
| 18 | 19 |
| 19 CSSTokenizer::Scope::Scope(const String& string) | 20 CSSTokenizer::Scope::Scope(const String& string) |
| 20 : m_string(string) | 21 : m_string(string) |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 CSSParserTokenRange CSSTokenizer::Scope::tokenRange() | 77 CSSParserTokenRange CSSTokenizer::Scope::tokenRange() |
| 77 { | 78 { |
| 78 return m_tokens; | 79 return m_tokens; |
| 79 } | 80 } |
| 80 | 81 |
| 81 unsigned CSSTokenizer::Scope::tokenCount() | 82 unsigned CSSTokenizer::Scope::tokenCount() |
| 82 { | 83 { |
| 83 return m_tokens.size(); | 84 return m_tokens.size(); |
| 84 } | 85 } |
| 85 | 86 |
| 86 // http://dev.w3.org/csswg/css-syntax/#name-start-code-point | |
| 87 static bool isNameStart(UChar c) | |
| 88 { | |
| 89 if (isASCIIAlpha(c)) | |
| 90 return true; | |
| 91 if (c == '_') | |
| 92 return true; | |
| 93 return !isASCII(c); | |
| 94 } | |
| 95 | |
| 96 // http://dev.w3.org/csswg/css-syntax/#name-code-point | |
| 97 static bool isNameChar(UChar c) | |
| 98 { | |
| 99 return isNameStart(c) || isASCIIDigit(c) || c == '-'; | |
| 100 } | |
| 101 | |
| 102 static bool isNewLine(UChar cc) | 87 static bool isNewLine(UChar cc) |
| 103 { | 88 { |
| 104 // We check \r and \f here, since we have no preprocessing stage | 89 // We check \r and \f here, since we have no preprocessing stage |
| 105 return (cc == '\r' || cc == '\n' || cc == '\f'); | 90 return (cc == '\r' || cc == '\n' || cc == '\f'); |
| 106 } | 91 } |
| 107 | 92 |
| 108 // http://dev.w3.org/csswg/css-syntax/#check-if-two-code-points-are-a-valid-esca
pe | 93 // http://dev.w3.org/csswg/css-syntax/#check-if-two-code-points-are-a-valid-esca
pe |
| 109 static bool twoCharsAreValidEscape(UChar first, UChar second) | 94 static bool twoCharsAreValidEscape(UChar first, UChar second) |
| 110 { | 95 { |
| 111 return first == '\\' && !isNewLine(second); | 96 return first == '\\' && !isNewLine(second); |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 } | 249 } |
| 265 | 250 |
| 266 CSSParserToken CSSTokenizer::semiColon(UChar cc) | 251 CSSParserToken CSSTokenizer::semiColon(UChar cc) |
| 267 { | 252 { |
| 268 return CSSParserToken(SemicolonToken); | 253 return CSSParserToken(SemicolonToken); |
| 269 } | 254 } |
| 270 | 255 |
| 271 CSSParserToken CSSTokenizer::hash(UChar cc) | 256 CSSParserToken CSSTokenizer::hash(UChar cc) |
| 272 { | 257 { |
| 273 UChar nextChar = m_input.nextInputChar(); | 258 UChar nextChar = m_input.nextInputChar(); |
| 274 if (isNameChar(nextChar) || twoCharsAreValidEscape(nextChar, m_input.peek(1)
)) { | 259 if (isNameCodePoint(nextChar) || twoCharsAreValidEscape(nextChar, m_input.pe
ek(1))) { |
| 275 HashTokenType type = nextCharsAreIdentifier() ? HashTokenId : HashTokenU
nrestricted; | 260 HashTokenType type = nextCharsAreIdentifier() ? HashTokenId : HashTokenU
nrestricted; |
| 276 return CSSParserToken(type, consumeName()); | 261 return CSSParserToken(type, consumeName()); |
| 277 } | 262 } |
| 278 | 263 |
| 279 return CSSParserToken(DelimiterToken, cc); | 264 return CSSParserToken(DelimiterToken, cc); |
| 280 } | 265 } |
| 281 | 266 |
| 282 CSSParserToken CSSTokenizer::circumflexAccent(UChar cc) | 267 CSSParserToken CSSTokenizer::circumflexAccent(UChar cc) |
| 283 { | 268 { |
| 284 ASSERT(cc == '^'); | 269 ASSERT(cc == '^'); |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 677 } | 662 } |
| 678 | 663 |
| 679 // http://www.w3.org/TR/css3-syntax/#consume-a-name | 664 // http://www.w3.org/TR/css3-syntax/#consume-a-name |
| 680 CSSParserString CSSTokenizer::consumeName() | 665 CSSParserString CSSTokenizer::consumeName() |
| 681 { | 666 { |
| 682 // Names without escapes get handled without allocations | 667 // Names without escapes get handled without allocations |
| 683 for (unsigned size = 0; ; ++size) { | 668 for (unsigned size = 0; ; ++size) { |
| 684 UChar cc = m_input.peekWithoutReplacement(size); | 669 UChar cc = m_input.peekWithoutReplacement(size); |
| 685 if (cc == '\0' || cc == '\\') | 670 if (cc == '\0' || cc == '\\') |
| 686 break; | 671 break; |
| 687 if (!isNameChar(cc)) { | 672 if (!isNameCodePoint(cc)) { |
| 688 unsigned startOffset = m_input.offset(); | 673 unsigned startOffset = m_input.offset(); |
| 689 m_input.advance(size); | 674 m_input.advance(size); |
| 690 return m_input.rangeAsCSSParserString(startOffset, size); | 675 return m_input.rangeAsCSSParserString(startOffset, size); |
| 691 } | 676 } |
| 692 } | 677 } |
| 693 | 678 |
| 694 StringBuilder result; | 679 StringBuilder result; |
| 695 while (true) { | 680 while (true) { |
| 696 UChar cc = consume(); | 681 UChar cc = consume(); |
| 697 if (isNameChar(cc)) { | 682 if (isNameCodePoint(cc)) { |
| 698 result.append(cc); | 683 result.append(cc); |
| 699 continue; | 684 continue; |
| 700 } | 685 } |
| 701 if (twoCharsAreValidEscape(cc, m_input.nextInputChar())) { | 686 if (twoCharsAreValidEscape(cc, m_input.nextInputChar())) { |
| 702 result.append(consumeEscape()); | 687 result.append(consumeEscape()); |
| 703 continue; | 688 continue; |
| 704 } | 689 } |
| 705 reconsume(cc); | 690 reconsume(cc); |
| 706 return registerString(result.toString()); | 691 return registerString(result.toString()); |
| 707 } | 692 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 758 UChar first = consume(); | 743 UChar first = consume(); |
| 759 bool areNumber = nextCharsAreNumber(first); | 744 bool areNumber = nextCharsAreNumber(first); |
| 760 reconsume(first); | 745 reconsume(first); |
| 761 return areNumber; | 746 return areNumber; |
| 762 } | 747 } |
| 763 | 748 |
| 764 // http://dev.w3.org/csswg/css-syntax/#would-start-an-identifier | 749 // http://dev.w3.org/csswg/css-syntax/#would-start-an-identifier |
| 765 bool CSSTokenizer::nextCharsAreIdentifier(UChar first) | 750 bool CSSTokenizer::nextCharsAreIdentifier(UChar first) |
| 766 { | 751 { |
| 767 UChar second = m_input.nextInputChar(); | 752 UChar second = m_input.nextInputChar(); |
| 768 if (isNameStart(first) || twoCharsAreValidEscape(first, second)) | 753 if (isNameStartCodePoint(first) || twoCharsAreValidEscape(first, second)) |
| 769 return true; | 754 return true; |
| 770 | 755 |
| 771 if (first == '-') | 756 if (first == '-') |
| 772 return isNameStart(second) || second == '-' || nextTwoCharsAreValidEscap
e(); | 757 return isNameStartCodePoint(second) || second == '-' || nextTwoCharsAreV
alidEscape(); |
| 773 | 758 |
| 774 return false; | 759 return false; |
| 775 } | 760 } |
| 776 | 761 |
| 777 bool CSSTokenizer::nextCharsAreIdentifier() | 762 bool CSSTokenizer::nextCharsAreIdentifier() |
| 778 { | 763 { |
| 779 UChar first = consume(); | 764 UChar first = consume(); |
| 780 bool areIdentifier = nextCharsAreIdentifier(first); | 765 bool areIdentifier = nextCharsAreIdentifier(first); |
| 781 reconsume(first); | 766 reconsume(first); |
| 782 return areIdentifier; | 767 return areIdentifier; |
| 783 } | 768 } |
| 784 | 769 |
| 785 CSSParserString CSSTokenizer::registerString(const String& string) | 770 CSSParserString CSSTokenizer::registerString(const String& string) |
| 786 { | 771 { |
| 787 m_scope.storeString(string); | 772 m_scope.storeString(string); |
| 788 CSSParserString result; | 773 CSSParserString result; |
| 789 result.init(string); | 774 result.init(string); |
| 790 return result; | 775 return result; |
| 791 } | 776 } |
| 792 | 777 |
| 793 } // namespace blink | 778 } // namespace blink |
| OLD | NEW |