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 |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 return CSSParserToken(ColonToken); | 239 return CSSParserToken(ColonToken); |
240 } | 240 } |
241 | 241 |
242 CSSParserToken CSSTokenizer::semiColon(UChar cc) | 242 CSSParserToken CSSTokenizer::semiColon(UChar cc) |
243 { | 243 { |
244 return CSSParserToken(SemicolonToken); | 244 return CSSParserToken(SemicolonToken); |
245 } | 245 } |
246 | 246 |
247 CSSParserToken CSSTokenizer::hash(UChar cc) | 247 CSSParserToken CSSTokenizer::hash(UChar cc) |
248 { | 248 { |
249 UChar nextChar = m_input.nextInputChar(); | 249 UChar nextChar = m_input.peekWithoutReplacement(0); |
250 if (isNameCodePoint(nextChar) || twoCharsAreValidEscape(nextChar, m_input.pe
ekWithoutReplacement(1))) { | 250 if (isNameCodePoint(nextChar) || twoCharsAreValidEscape(nextChar, m_input.pe
ekWithoutReplacement(1))) { |
251 HashTokenType type = nextCharsAreIdentifier() ? HashTokenId : HashTokenU
nrestricted; | 251 HashTokenType type = nextCharsAreIdentifier() ? HashTokenId : HashTokenU
nrestricted; |
252 return CSSParserToken(type, consumeName()); | 252 return CSSParserToken(type, consumeName()); |
253 } | 253 } |
254 | 254 |
255 return CSSParserToken(DelimiterToken, cc); | 255 return CSSParserToken(DelimiterToken, cc); |
256 } | 256 } |
257 | 257 |
258 CSSParserToken CSSTokenizer::circumflexAccent(UChar cc) | 258 CSSParserToken CSSTokenizer::circumflexAccent(UChar cc) |
259 { | 259 { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 CSSParserToken CSSTokenizer::commercialAt(UChar cc) | 292 CSSParserToken CSSTokenizer::commercialAt(UChar cc) |
293 { | 293 { |
294 ASSERT(cc == '@'); | 294 ASSERT(cc == '@'); |
295 if (nextCharsAreIdentifier()) | 295 if (nextCharsAreIdentifier()) |
296 return CSSParserToken(AtKeywordToken, consumeName()); | 296 return CSSParserToken(AtKeywordToken, consumeName()); |
297 return CSSParserToken(DelimiterToken, '@'); | 297 return CSSParserToken(DelimiterToken, '@'); |
298 } | 298 } |
299 | 299 |
300 CSSParserToken CSSTokenizer::reverseSolidus(UChar cc) | 300 CSSParserToken CSSTokenizer::reverseSolidus(UChar cc) |
301 { | 301 { |
302 if (twoCharsAreValidEscape(cc, m_input.nextInputChar())) { | 302 if (twoCharsAreValidEscape(cc, m_input.peekWithoutReplacement(0))) { |
303 reconsume(cc); | 303 reconsume(cc); |
304 return consumeIdentLikeToken(); | 304 return consumeIdentLikeToken(); |
305 } | 305 } |
306 return CSSParserToken(DelimiterToken, cc); | 306 return CSSParserToken(DelimiterToken, cc); |
307 } | 307 } |
308 | 308 |
309 CSSParserToken CSSTokenizer::asciiDigit(UChar cc) | 309 CSSParserToken CSSTokenizer::asciiDigit(UChar cc) |
310 { | 310 { |
311 reconsume(cc); | 311 reconsume(cc); |
312 return consumeNumericToken(); | 312 return consumeNumericToken(); |
313 } | 313 } |
314 | 314 |
315 CSSParserToken CSSTokenizer::letterU(UChar cc) | 315 CSSParserToken CSSTokenizer::letterU(UChar cc) |
316 { | 316 { |
317 if (m_input.nextInputChar() == '+' | 317 if (m_input.peekWithoutReplacement(0) == '+' |
318 && (isASCIIHexDigit(m_input.peekWithoutReplacement(1)) | 318 && (isASCIIHexDigit(m_input.peekWithoutReplacement(1)) |
319 || m_input.peekWithoutReplacement(1) == '?')) { | 319 || m_input.peekWithoutReplacement(1) == '?')) { |
320 m_input.advance(); | 320 m_input.advance(); |
321 return consumeUnicodeRange(); | 321 return consumeUnicodeRange(); |
322 } | 322 } |
323 reconsume(cc); | 323 reconsume(cc); |
324 return consumeIdentLikeToken(); | 324 return consumeIdentLikeToken(); |
325 } | 325 } |
326 | 326 |
327 CSSParserToken CSSTokenizer::nameStart(UChar cc) | 327 CSSParserToken CSSTokenizer::nameStart(UChar cc) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 codePointFunc = &CSSTokenizer::nameStart; | 359 codePointFunc = &CSSTokenizer::nameStart; |
360 } | 360 } |
361 | 361 |
362 if (codePointFunc) | 362 if (codePointFunc) |
363 return ((this)->*(codePointFunc))(cc); | 363 return ((this)->*(codePointFunc))(cc); |
364 return CSSParserToken(DelimiterToken, cc); | 364 return CSSParserToken(DelimiterToken, cc); |
365 } | 365 } |
366 | 366 |
367 static NumericSign getSign(CSSTokenizerInputStream& input, unsigned& offset) | 367 static NumericSign getSign(CSSTokenizerInputStream& input, unsigned& offset) |
368 { | 368 { |
369 if (input.nextInputChar() == '+') { | 369 UChar next = input.peekWithoutReplacement(0); |
| 370 if (next == '+') { |
370 ++offset; | 371 ++offset; |
371 return PlusSign; | 372 return PlusSign; |
372 } | 373 } |
373 if (input.nextInputChar() == '-') { | 374 if (next == '-') { |
374 ++offset; | 375 ++offset; |
375 return MinusSign; | 376 return MinusSign; |
376 } | 377 } |
377 return NoSign; | 378 return NoSign; |
378 } | 379 } |
379 | 380 |
380 static double getInteger(CSSTokenizerInputStream& input, unsigned& offset) | 381 static double getInteger(CSSTokenizerInputStream& input, unsigned& offset) |
381 { | 382 { |
382 unsigned intStartPos = offset; | 383 unsigned intStartPos = offset; |
383 offset = input.skipWhilePredicate<isASCIIDigit>(offset); | 384 offset = input.skipWhilePredicate<isASCIIDigit>(offset); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 | 461 |
461 // http://dev.w3.org/csswg/css-syntax/#consume-ident-like-token | 462 // http://dev.w3.org/csswg/css-syntax/#consume-ident-like-token |
462 CSSParserToken CSSTokenizer::consumeIdentLikeToken() | 463 CSSParserToken CSSTokenizer::consumeIdentLikeToken() |
463 { | 464 { |
464 StringView name = consumeName(); | 465 StringView name = consumeName(); |
465 if (consumeIfNext('(')) { | 466 if (consumeIfNext('(')) { |
466 if (equalIgnoringASCIICase(name, "url")) { | 467 if (equalIgnoringASCIICase(name, "url")) { |
467 // The spec is slightly different so as to avoid dropping whitespace | 468 // The spec is slightly different so as to avoid dropping whitespace |
468 // tokens, but they wouldn't be used and this is easier. | 469 // tokens, but they wouldn't be used and this is easier. |
469 m_input.advanceUntilNonWhitespace(); | 470 m_input.advanceUntilNonWhitespace(); |
470 UChar next = m_input.nextInputChar(); | 471 UChar next = m_input.peekWithoutReplacement(0); |
471 if (next != '"' && next != '\'') | 472 if (next != '"' && next != '\'') |
472 return consumeUrlToken(); | 473 return consumeUrlToken(); |
473 } | 474 } |
474 return blockStart(LeftParenthesisToken, FunctionToken, name); | 475 return blockStart(LeftParenthesisToken, FunctionToken, name); |
475 } | 476 } |
476 return CSSParserToken(IdentToken, name); | 477 return CSSParserToken(IdentToken, name); |
477 } | 478 } |
478 | 479 |
479 // http://dev.w3.org/csswg/css-syntax/#consume-a-string-token | 480 // http://dev.w3.org/csswg/css-syntax/#consume-a-string-token |
480 CSSParserToken CSSTokenizer::consumeStringTokenUntil(UChar endingCodePoint) | 481 CSSParserToken CSSTokenizer::consumeStringTokenUntil(UChar endingCodePoint) |
(...skipping 19 matching lines...) Expand all Loading... |
500 UChar cc = consume(); | 501 UChar cc = consume(); |
501 if (cc == endingCodePoint || cc == kEndOfFileMarker) | 502 if (cc == endingCodePoint || cc == kEndOfFileMarker) |
502 return CSSParserToken(StringToken, registerString(output.toString())
); | 503 return CSSParserToken(StringToken, registerString(output.toString())
); |
503 if (isNewLine(cc)) { | 504 if (isNewLine(cc)) { |
504 reconsume(cc); | 505 reconsume(cc); |
505 return CSSParserToken(BadStringToken); | 506 return CSSParserToken(BadStringToken); |
506 } | 507 } |
507 if (cc == '\\') { | 508 if (cc == '\\') { |
508 if (m_input.nextInputChar() == kEndOfFileMarker) | 509 if (m_input.nextInputChar() == kEndOfFileMarker) |
509 continue; | 510 continue; |
510 if (isNewLine(m_input.nextInputChar())) | 511 if (isNewLine(m_input.peekWithoutReplacement(0))) |
511 consumeSingleWhitespaceIfNext(); // This handles \r\n for us | 512 consumeSingleWhitespaceIfNext(); // This handles \r\n for us |
512 else | 513 else |
513 output.append(consumeEscape()); | 514 output.append(consumeEscape()); |
514 } else { | 515 } else { |
515 output.append(cc); | 516 output.append(cc); |
516 } | 517 } |
517 } | 518 } |
518 } | 519 } |
519 | 520 |
520 CSSParserToken CSSTokenizer::consumeUnicodeRange() | 521 CSSParserToken CSSTokenizer::consumeUnicodeRange() |
521 { | 522 { |
522 ASSERT(isASCIIHexDigit(m_input.nextInputChar()) || m_input.nextInputChar() =
= '?'); | 523 DCHECK(isASCIIHexDigit(m_input.peekWithoutReplacement(0)) || m_input.peekWit
houtReplacement(0) == '?'); |
523 int lengthRemaining = 6; | 524 int lengthRemaining = 6; |
524 UChar32 start = 0; | 525 UChar32 start = 0; |
525 | 526 |
526 while (lengthRemaining && isASCIIHexDigit(m_input.nextInputChar())) { | 527 while (lengthRemaining && isASCIIHexDigit(m_input.peekWithoutReplacement(0))
) { |
527 start = start * 16 + toASCIIHexValue(consume()); | 528 start = start * 16 + toASCIIHexValue(consume()); |
528 --lengthRemaining; | 529 --lengthRemaining; |
529 } | 530 } |
530 | 531 |
531 UChar32 end = start; | 532 UChar32 end = start; |
532 if (lengthRemaining && consumeIfNext('?')) { | 533 if (lengthRemaining && consumeIfNext('?')) { |
533 do { | 534 do { |
534 start *= 16; | 535 start *= 16; |
535 end = end * 16 + 0xF; | 536 end = end * 16 + 0xF; |
536 --lengthRemaining; | 537 --lengthRemaining; |
537 } while (lengthRemaining && consumeIfNext('?')); | 538 } while (lengthRemaining && consumeIfNext('?')); |
538 } else if (m_input.nextInputChar() == '-' && isASCIIHexDigit(m_input.peekWit
houtReplacement(1))) { | 539 } else if (m_input.peekWithoutReplacement(0) == '-' && isASCIIHexDigit(m_inp
ut.peekWithoutReplacement(1))) { |
539 m_input.advance(); | 540 m_input.advance(); |
540 lengthRemaining = 6; | 541 lengthRemaining = 6; |
541 end = 0; | 542 end = 0; |
542 do { | 543 do { |
543 end = end * 16 + toASCIIHexValue(consume()); | 544 end = end * 16 + toASCIIHexValue(consume()); |
544 --lengthRemaining; | 545 --lengthRemaining; |
545 } while (lengthRemaining && isASCIIHexDigit(m_input.nextInputChar())); | 546 } while (lengthRemaining && isASCIIHexDigit(m_input.peekWithoutReplaceme
nt(0))); |
546 } | 547 } |
547 | 548 |
548 return CSSParserToken(UnicodeRangeToken, start, end); | 549 return CSSParserToken(UnicodeRangeToken, start, end); |
549 } | 550 } |
550 | 551 |
551 // http://dev.w3.org/csswg/css-syntax/#non-printable-code-point | 552 // http://dev.w3.org/csswg/css-syntax/#non-printable-code-point |
552 static bool isNonPrintableCodePoint(UChar cc) | 553 static bool isNonPrintableCodePoint(UChar cc) |
553 { | 554 { |
554 return (cc >= '\0' && cc <= '\x8') || cc == '\xb' || (cc >= '\xe' && cc <= '
\x1f') || cc == '\x7f'; | 555 return (cc >= '\0' && cc <= '\x8') || cc == '\xb' || (cc >= '\xe' && cc <= '
\x1f') || cc == '\x7f'; |
555 } | 556 } |
(...skipping 25 matching lines...) Expand all Loading... |
581 m_input.advanceUntilNonWhitespace(); | 582 m_input.advanceUntilNonWhitespace(); |
582 if (consumeIfNext(')') || m_input.nextInputChar() == kEndOfFileMarke
r) | 583 if (consumeIfNext(')') || m_input.nextInputChar() == kEndOfFileMarke
r) |
583 return CSSParserToken(UrlToken, registerString(result.toString()
)); | 584 return CSSParserToken(UrlToken, registerString(result.toString()
)); |
584 break; | 585 break; |
585 } | 586 } |
586 | 587 |
587 if (cc == '"' || cc == '\'' || cc == '(' || isNonPrintableCodePoint(cc)) | 588 if (cc == '"' || cc == '\'' || cc == '(' || isNonPrintableCodePoint(cc)) |
588 break; | 589 break; |
589 | 590 |
590 if (cc == '\\') { | 591 if (cc == '\\') { |
591 if (twoCharsAreValidEscape(cc, m_input.nextInputChar())) { | 592 if (twoCharsAreValidEscape(cc, m_input.peekWithoutReplacement(0))) { |
592 result.append(consumeEscape()); | 593 result.append(consumeEscape()); |
593 continue; | 594 continue; |
594 } | 595 } |
595 break; | 596 break; |
596 } | 597 } |
597 | 598 |
598 result.append(cc); | 599 result.append(cc); |
599 } | 600 } |
600 | 601 |
601 consumeBadUrlRemnants(); | 602 consumeBadUrlRemnants(); |
602 return CSSParserToken(BadUrlToken); | 603 return CSSParserToken(BadUrlToken); |
603 } | 604 } |
604 | 605 |
605 // http://dev.w3.org/csswg/css-syntax/#consume-the-remnants-of-a-bad-url | 606 // http://dev.w3.org/csswg/css-syntax/#consume-the-remnants-of-a-bad-url |
606 void CSSTokenizer::consumeBadUrlRemnants() | 607 void CSSTokenizer::consumeBadUrlRemnants() |
607 { | 608 { |
608 while (true) { | 609 while (true) { |
609 UChar cc = consume(); | 610 UChar cc = consume(); |
610 if (cc == ')' || cc == kEndOfFileMarker) | 611 if (cc == ')' || cc == kEndOfFileMarker) |
611 return; | 612 return; |
612 if (twoCharsAreValidEscape(cc, m_input.nextInputChar())) | 613 if (twoCharsAreValidEscape(cc, m_input.peekWithoutReplacement(0))) |
613 consumeEscape(); | 614 consumeEscape(); |
614 } | 615 } |
615 } | 616 } |
616 | 617 |
617 void CSSTokenizer::consumeSingleWhitespaceIfNext() | 618 void CSSTokenizer::consumeSingleWhitespaceIfNext() |
618 { | 619 { |
619 // We check for \r\n and HTML spaces since we don't do preprocessing | 620 // We check for \r\n and HTML spaces since we don't do preprocessing |
620 UChar c = m_input.nextInputChar(); | 621 UChar next = m_input.peekWithoutReplacement(0); |
621 if (c == '\r' && m_input.peekWithoutReplacement(1) == '\n') | 622 if (next == '\r' && m_input.peekWithoutReplacement(1) == '\n') |
622 m_input.advance(2); | 623 m_input.advance(2); |
623 else if (isHTMLSpace(c)) | 624 else if (isHTMLSpace(next)) |
624 m_input.advance(); | 625 m_input.advance(); |
625 } | 626 } |
626 | 627 |
627 void CSSTokenizer::consumeUntilCommentEndFound() | 628 void CSSTokenizer::consumeUntilCommentEndFound() |
628 { | 629 { |
629 UChar c = consume(); | 630 UChar c = consume(); |
630 while (true) { | 631 while (true) { |
631 if (c == kEndOfFileMarker) | 632 if (c == kEndOfFileMarker) |
632 return; | 633 return; |
633 if (c != '*') { | 634 if (c != '*') { |
634 c = consume(); | 635 c = consume(); |
635 continue; | 636 continue; |
636 } | 637 } |
637 c = consume(); | 638 c = consume(); |
638 if (c == '/') | 639 if (c == '/') |
639 return; | 640 return; |
640 } | 641 } |
641 } | 642 } |
642 | 643 |
643 bool CSSTokenizer::consumeIfNext(UChar character) | 644 bool CSSTokenizer::consumeIfNext(UChar character) |
644 { | 645 { |
645 if (m_input.nextInputChar() == character) { | 646 // Since we're not doing replacement we can't tell the difference from |
| 647 // a NUL in the middle and the kEndOfFileMarker, so character must not be |
| 648 // NUL. |
| 649 DCHECK(character); |
| 650 if (m_input.peekWithoutReplacement(0) == character) { |
646 m_input.advance(); | 651 m_input.advance(); |
647 return true; | 652 return true; |
648 } | 653 } |
649 return false; | 654 return false; |
650 } | 655 } |
651 | 656 |
652 // http://www.w3.org/TR/css3-syntax/#consume-a-name | 657 // http://www.w3.org/TR/css3-syntax/#consume-a-name |
653 StringView CSSTokenizer::consumeName() | 658 StringView CSSTokenizer::consumeName() |
654 { | 659 { |
655 // Names without escapes get handled without allocations | 660 // Names without escapes get handled without allocations |
(...skipping 13 matching lines...) Expand all Loading... |
669 return m_input.rangeAt(startOffset, size); | 674 return m_input.rangeAt(startOffset, size); |
670 } | 675 } |
671 | 676 |
672 StringBuilder result; | 677 StringBuilder result; |
673 while (true) { | 678 while (true) { |
674 UChar cc = consume(); | 679 UChar cc = consume(); |
675 if (isNameCodePoint(cc)) { | 680 if (isNameCodePoint(cc)) { |
676 result.append(cc); | 681 result.append(cc); |
677 continue; | 682 continue; |
678 } | 683 } |
679 if (twoCharsAreValidEscape(cc, m_input.nextInputChar())) { | 684 if (twoCharsAreValidEscape(cc, m_input.peekWithoutReplacement(0))) { |
680 result.append(consumeEscape()); | 685 result.append(consumeEscape()); |
681 continue; | 686 continue; |
682 } | 687 } |
683 reconsume(cc); | 688 reconsume(cc); |
684 return registerString(result.toString()); | 689 return registerString(result.toString()); |
685 } | 690 } |
686 } | 691 } |
687 | 692 |
688 // http://dev.w3.org/csswg/css-syntax/#consume-an-escaped-code-point | 693 // http://dev.w3.org/csswg/css-syntax/#consume-an-escaped-code-point |
689 UChar32 CSSTokenizer::consumeEscape() | 694 UChar32 CSSTokenizer::consumeEscape() |
690 { | 695 { |
691 UChar cc = consume(); | 696 UChar cc = consume(); |
692 ASSERT(!isNewLine(cc)); | 697 ASSERT(!isNewLine(cc)); |
693 if (isASCIIHexDigit(cc)) { | 698 if (isASCIIHexDigit(cc)) { |
694 unsigned consumedHexDigits = 1; | 699 unsigned consumedHexDigits = 1; |
695 StringBuilder hexChars; | 700 StringBuilder hexChars; |
696 hexChars.append(cc); | 701 hexChars.append(cc); |
697 while (consumedHexDigits < 6 && isASCIIHexDigit(m_input.nextInputChar())
) { | 702 while (consumedHexDigits < 6 && isASCIIHexDigit(m_input.peekWithoutRepla
cement(0))) { |
698 cc = consume(); | 703 cc = consume(); |
699 hexChars.append(cc); | 704 hexChars.append(cc); |
700 consumedHexDigits++; | 705 consumedHexDigits++; |
701 }; | 706 }; |
702 consumeSingleWhitespaceIfNext(); | 707 consumeSingleWhitespaceIfNext(); |
703 bool ok = false; | 708 bool ok = false; |
704 UChar32 codePoint = hexChars.toString().toUIntStrict(&ok, 16); | 709 UChar32 codePoint = hexChars.toString().toUIntStrict(&ok, 16); |
705 ASSERT(ok); | 710 ASSERT(ok); |
706 if (codePoint == 0 || (0xD800 <= codePoint && codePoint <= 0xDFFF) || co
dePoint > 0x10FFFF) | 711 if (codePoint == 0 || (0xD800 <= codePoint && codePoint <= 0xDFFF) || co
dePoint > 0x10FFFF) |
707 return replacementCharacter; | 712 return replacementCharacter; |
708 return codePoint; | 713 return codePoint; |
709 } | 714 } |
710 | 715 |
711 if (cc == kEndOfFileMarker) | 716 if (cc == kEndOfFileMarker) |
712 return replacementCharacter; | 717 return replacementCharacter; |
713 return cc; | 718 return cc; |
714 } | 719 } |
715 | 720 |
716 bool CSSTokenizer::nextTwoCharsAreValidEscape() | 721 bool CSSTokenizer::nextTwoCharsAreValidEscape() |
717 { | 722 { |
718 return twoCharsAreValidEscape(m_input.nextInputChar(), m_input.peekWithoutRe
placement(1)); | 723 return twoCharsAreValidEscape(m_input.peekWithoutReplacement(0), m_input.pee
kWithoutReplacement(1)); |
719 } | 724 } |
720 | 725 |
721 // http://www.w3.org/TR/css3-syntax/#starts-with-a-number | 726 // http://www.w3.org/TR/css3-syntax/#starts-with-a-number |
722 bool CSSTokenizer::nextCharsAreNumber(UChar first) | 727 bool CSSTokenizer::nextCharsAreNumber(UChar first) |
723 { | 728 { |
724 UChar second = m_input.nextInputChar(); | 729 UChar second = m_input.peekWithoutReplacement(0); |
725 if (isASCIIDigit(first)) | 730 if (isASCIIDigit(first)) |
726 return true; | 731 return true; |
727 if (first == '+' || first == '-') | 732 if (first == '+' || first == '-') |
728 return ((isASCIIDigit(second)) || (second == '.' && isASCIIDigit(m_input
.peekWithoutReplacement(1)))); | 733 return ((isASCIIDigit(second)) || (second == '.' && isASCIIDigit(m_input
.peekWithoutReplacement(1)))); |
729 if (first =='.') | 734 if (first =='.') |
730 return (isASCIIDigit(second)); | 735 return (isASCIIDigit(second)); |
731 return false; | 736 return false; |
732 } | 737 } |
733 | 738 |
734 bool CSSTokenizer::nextCharsAreNumber() | 739 bool CSSTokenizer::nextCharsAreNumber() |
735 { | 740 { |
736 UChar first = consume(); | 741 UChar first = consume(); |
737 bool areNumber = nextCharsAreNumber(first); | 742 bool areNumber = nextCharsAreNumber(first); |
738 reconsume(first); | 743 reconsume(first); |
739 return areNumber; | 744 return areNumber; |
740 } | 745 } |
741 | 746 |
742 // http://dev.w3.org/csswg/css-syntax/#would-start-an-identifier | 747 // http://dev.w3.org/csswg/css-syntax/#would-start-an-identifier |
743 bool CSSTokenizer::nextCharsAreIdentifier(UChar first) | 748 bool CSSTokenizer::nextCharsAreIdentifier(UChar first) |
744 { | 749 { |
745 UChar second = m_input.nextInputChar(); | 750 UChar second = m_input.peekWithoutReplacement(0); |
746 if (isNameStartCodePoint(first) || twoCharsAreValidEscape(first, second)) | 751 if (isNameStartCodePoint(first) || twoCharsAreValidEscape(first, second)) |
747 return true; | 752 return true; |
748 | 753 |
749 if (first == '-') | 754 if (first == '-') |
750 return isNameStartCodePoint(second) || second == '-' || nextTwoCharsAreV
alidEscape(); | 755 return isNameStartCodePoint(second) || second == '-' || nextTwoCharsAreV
alidEscape(); |
751 | 756 |
752 return false; | 757 return false; |
753 } | 758 } |
754 | 759 |
755 bool CSSTokenizer::nextCharsAreIdentifier() | 760 bool CSSTokenizer::nextCharsAreIdentifier() |
756 { | 761 { |
757 UChar first = consume(); | 762 UChar first = consume(); |
758 bool areIdentifier = nextCharsAreIdentifier(first); | 763 bool areIdentifier = nextCharsAreIdentifier(first); |
759 reconsume(first); | 764 reconsume(first); |
760 return areIdentifier; | 765 return areIdentifier; |
761 } | 766 } |
762 | 767 |
763 StringView CSSTokenizer::registerString(const String& string) | 768 StringView CSSTokenizer::registerString(const String& string) |
764 { | 769 { |
765 m_scope.storeString(string); | 770 m_scope.storeString(string); |
766 return string; | 771 return string; |
767 } | 772 } |
768 | 773 |
769 } // namespace blink | 774 } // namespace blink |
OLD | NEW |