OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
585 return std::numeric_limits<double>::quiet_NaN(); | 585 return std::numeric_limits<double>::quiet_NaN(); |
586 } | 586 } |
587 return 0; | 587 return 0; |
588 } | 588 } |
589 | 589 |
590 const RefPtrWillBeMember<CSSCalcExpressionNode> m_leftSide; | 590 const RefPtrWillBeMember<CSSCalcExpressionNode> m_leftSide; |
591 const RefPtrWillBeMember<CSSCalcExpressionNode> m_rightSide; | 591 const RefPtrWillBeMember<CSSCalcExpressionNode> m_rightSide; |
592 const CalcOperator m_operator; | 592 const CalcOperator m_operator; |
593 }; | 593 }; |
594 | 594 |
595 static ParseState checkDepthAndIndex(int* depth, unsigned index, CSSParserValueL ist* tokens) | 595 static ParseState checkDepthAndIndex(int* depth, CSSParserTokenRange tokens) |
596 { | 596 { |
597 (*depth)++; | 597 (*depth)++; |
598 if (tokens.atEnd()) | |
599 return NoMoreTokens; | |
598 if (*depth > maxExpressionDepth) | 600 if (*depth > maxExpressionDepth) |
599 return TooDeep; | 601 return TooDeep; |
600 if (index >= tokens->size()) | |
601 return NoMoreTokens; | |
602 return OK; | 602 return OK; |
603 } | 603 } |
604 | 604 |
605 class CSSCalcExpressionNodeParser { | 605 class CSSCalcExpressionNodeParser { |
606 STACK_ALLOCATED(); | 606 STACK_ALLOCATED(); |
607 public: | 607 public: |
608 PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> parseCalc(CSSParserValueList* tokens) | 608 PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> parseCalc(CSSParserTokenRange tokens) |
609 { | 609 { |
610 unsigned index = 0; | |
611 Value result; | 610 Value result; |
612 bool ok = parseValueExpression(tokens, 0, &index, &result); | 611 tokens.consumeWhitespace(); |
613 ASSERT_WITH_SECURITY_IMPLICATION(index <= tokens->size()); | 612 bool ok = parseValueExpression(tokens, 0, &result); |
614 if (!ok || index != tokens->size()) | 613 if (!ok || !tokens.atEnd()) |
615 return nullptr; | 614 return nullptr; |
616 return result.value; | 615 return result.value; |
617 } | 616 } |
618 | 617 |
619 private: | 618 private: |
620 struct Value { | 619 struct Value { |
621 STACK_ALLOCATED(); | 620 STACK_ALLOCATED(); |
622 public: | 621 public: |
623 RefPtrWillBeMember<CSSCalcExpressionNode> value; | 622 RefPtrWillBeMember<CSSCalcExpressionNode> value; |
624 }; | 623 }; |
625 | 624 |
626 char operatorValue(CSSParserValueList* tokens, unsigned index) | 625 char operatorValue(const CSSParserToken& token) |
627 { | 626 { |
628 if (index >= tokens->size()) | 627 if (token.type() == DelimiterToken) |
629 return 0; | 628 return token.delimiter(); |
630 CSSParserValue* value = tokens->valueAt(index); | 629 return 0; |
631 if (value->unit != CSSParserValue::Operator) | |
632 return 0; | |
633 | |
634 return value->iValue; | |
635 } | 630 } |
636 | 631 |
637 bool parseValue(CSSParserValueList* tokens, unsigned* index, Value* result) | 632 bool parseValue(CSSParserTokenRange& tokens, Value* result) |
638 { | 633 { |
639 CSSParserValue* parserValue = tokens->valueAt(*index); | 634 CSSParserToken token = tokens.consumeIncludingWhitespace(); |
640 if (parserValue->unit >= CSSParserValue::Operator) | 635 if (!(token.type() == NumberToken || token.type() == PercentageToken || token.type() == DimensionToken)) |
641 return false; | 636 return false; |
642 | 637 |
643 CSSPrimitiveValue::UnitType type = static_cast<CSSPrimitiveValue::UnitTy pe>(parserValue->unit); | 638 CSSPrimitiveValue::UnitType type = token.unitType(); |
644 if (unitCategory(type) == CalcOther) | 639 if (unitCategory(type) == CalcOther) |
645 return false; | 640 return false; |
646 | 641 |
647 result->value = CSSCalcPrimitiveValue::create( | 642 result->value = CSSCalcPrimitiveValue::create( |
648 CSSPrimitiveValue::create(parserValue->fValue, type), parserValue->i sInt); | 643 CSSPrimitiveValue::create(token.numericValue(), type), token.numeric ValueType() == IntegerValueType); |
649 | 644 |
650 ++*index; | |
651 return true; | 645 return true; |
652 } | 646 } |
653 | 647 |
654 bool parseValueTerm(CSSParserValueList* tokens, int depth, unsigned* index, Value* result) | 648 bool parseValueTerm(CSSParserTokenRange& tokens, int depth, Value* result) |
655 { | 649 { |
656 if (checkDepthAndIndex(&depth, *index, tokens) != OK) | 650 if (checkDepthAndIndex(&depth, tokens) != OK) |
657 return false; | 651 return false; |
658 | 652 |
659 if (operatorValue(tokens, *index) == '(') { | 653 if (tokens.peek().type() == LeftParenthesisToken) { |
660 unsigned currentIndex = *index + 1; | 654 CSSParserTokenRange innerRange = tokens.consumeBlock(); |
661 if (!parseValueExpression(tokens, depth, ¤tIndex, result)) | 655 tokens.consumeWhitespace(); |
662 return false; | 656 return parseValueExpression(innerRange, depth, result); |
663 | |
664 if (operatorValue(tokens, currentIndex) != ')') | |
665 return false; | |
666 *index = currentIndex + 1; | |
667 return true; | |
668 } | 657 } |
669 | 658 |
670 return parseValue(tokens, index, result); | 659 return parseValue(tokens, result); |
671 } | 660 } |
672 | 661 |
673 bool parseValueMultiplicativeExpression(CSSParserValueList* tokens, int dept h, unsigned* index, Value* result) | 662 bool parseValueMultiplicativeExpression(CSSParserTokenRange& tokens, int dep th, Value* result) |
674 { | 663 { |
675 if (checkDepthAndIndex(&depth, *index, tokens) != OK) | 664 if (checkDepthAndIndex(&depth, tokens) != OK) |
676 return false; | 665 return false; |
677 | 666 |
678 if (!parseValueTerm(tokens, depth, index, result)) | 667 if (!parseValueTerm(tokens, depth, result)) |
679 return false; | 668 return false; |
680 | 669 |
681 while (*index < tokens->size() - 1) { | 670 while (!tokens.atEnd()) { |
682 char operatorCharacter = operatorValue(tokens, *index); | 671 char operatorCharacter = operatorValue(tokens.peek()); |
683 if (operatorCharacter != CalcMultiply && operatorCharacter != CalcDi vide) | 672 if (operatorCharacter != CalcMultiply && operatorCharacter != CalcDi vide) |
684 break; | 673 break; |
685 ++*index; | 674 tokens.consumeIncludingWhitespace(); |
686 | 675 |
687 Value rhs; | 676 Value rhs; |
688 if (!parseValueTerm(tokens, depth, index, &rhs)) | 677 if (!parseValueTerm(tokens, depth, &rhs)) |
689 return false; | 678 return false; |
690 | 679 |
691 result->value = CSSCalcBinaryOperation::createSimplified(result->val ue, rhs.value, static_cast<CalcOperator>(operatorCharacter)); | 680 result->value = CSSCalcBinaryOperation::createSimplified(result->val ue, rhs.value, static_cast<CalcOperator>(operatorCharacter)); |
692 if (!result->value) | 681 if (!result->value) |
693 return false; | 682 return false; |
694 } | 683 } |
695 | 684 |
696 ASSERT_WITH_SECURITY_IMPLICATION(*index <= tokens->size()); | |
697 return true; | 685 return true; |
698 } | 686 } |
699 | 687 |
700 bool parseAdditiveValueExpression(CSSParserValueList* tokens, int depth, uns igned* index, Value* result) | 688 bool parseAdditiveValueExpression(CSSParserTokenRange& tokens, int depth, Va lue* result) |
701 { | 689 { |
702 if (checkDepthAndIndex(&depth, *index, tokens) != OK) | 690 if (checkDepthAndIndex(&depth, tokens) != OK) |
703 return false; | 691 return false; |
704 | 692 |
705 if (!parseValueMultiplicativeExpression(tokens, depth, index, result)) | 693 if (!parseValueMultiplicativeExpression(tokens, depth, result)) |
706 return false; | 694 return false; |
707 | 695 |
708 while (*index < tokens->size() - 1) { | 696 while (!tokens.atEnd()) { |
709 char operatorCharacter = operatorValue(tokens, *index); | 697 char operatorCharacter = operatorValue(tokens.peek()); |
710 if (operatorCharacter != CalcAdd && operatorCharacter != CalcSubtrac t) | 698 if (operatorCharacter != CalcAdd && operatorCharacter != CalcSubtrac t) |
711 break; | 699 break; |
712 ++*index; | 700 if ((&tokens.peek() - 1)->type() != WhitespaceToken) |
701 return false; // calc(1px+ 2px) is invalid | |
702 tokens.consumeIncludingWhitespace(); | |
Timothy Loh
2015/07/29 03:52:03
tokens.peek() will return a static eof token if we
rwlbuis
2015/07/29 21:33:26
Done.
| |
703 if ((&tokens.peek() - 1)->type() != WhitespaceToken) | |
704 return false; // calc(1px +2px) is invalid | |
713 | 705 |
714 Value rhs; | 706 Value rhs; |
715 if (!parseValueMultiplicativeExpression(tokens, depth, index, &rhs)) | 707 if (!parseValueMultiplicativeExpression(tokens, depth, &rhs)) |
716 return false; | 708 return false; |
717 | 709 |
718 result->value = CSSCalcBinaryOperation::createSimplified(result->val ue, rhs.value, static_cast<CalcOperator>(operatorCharacter)); | 710 result->value = CSSCalcBinaryOperation::createSimplified(result->val ue, rhs.value, static_cast<CalcOperator>(operatorCharacter)); |
719 if (!result->value) | 711 if (!result->value) |
720 return false; | 712 return false; |
721 } | 713 } |
722 | 714 |
723 ASSERT_WITH_SECURITY_IMPLICATION(*index <= tokens->size()); | |
724 return true; | 715 return true; |
725 } | 716 } |
726 | 717 |
727 bool parseValueExpression(CSSParserValueList* tokens, int depth, unsigned* i ndex, Value* result) | 718 bool parseValueExpression(CSSParserTokenRange& tokens, int depth, Value* res ult) |
728 { | 719 { |
729 return parseAdditiveValueExpression(tokens, depth, index, result); | 720 return parseAdditiveValueExpression(tokens, depth, result); |
730 } | 721 } |
731 }; | 722 }; |
732 | 723 |
733 PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode (PassRefPtrWillBeRawPtr<CSSPrimitiveValue> value, bool isInteger) | 724 PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode (PassRefPtrWillBeRawPtr<CSSPrimitiveValue> value, bool isInteger) |
734 { | 725 { |
735 return CSSCalcPrimitiveValue::create(value, isInteger); | 726 return CSSCalcPrimitiveValue::create(value, isInteger); |
736 } | 727 } |
737 | 728 |
738 PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode (PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> leftSide, PassRefPtrWillBeRawPtr< CSSCalcExpressionNode> rightSide, CalcOperator op) | 729 PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode (PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> leftSide, PassRefPtrWillBeRawPtr< CSSCalcExpressionNode> rightSide, CalcOperator op) |
739 { | 730 { |
740 return CSSCalcBinaryOperation::create(leftSide, rightSide, op); | 731 return CSSCalcBinaryOperation::create(leftSide, rightSide, op); |
741 } | 732 } |
742 | 733 |
743 PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode (double pixels, double percent) | 734 PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode (double pixels, double percent) |
744 { | 735 { |
745 return createExpressionNode( | 736 return createExpressionNode( |
746 createExpressionNode(CSSPrimitiveValue::create(pixels, CSSPrimitiveValue ::CSS_PX), pixels == trunc(pixels)), | 737 createExpressionNode(CSSPrimitiveValue::create(pixels, CSSPrimitiveValue ::CSS_PX), pixels == trunc(pixels)), |
747 createExpressionNode(CSSPrimitiveValue::create(percent, CSSPrimitiveValu e::CSS_PERCENTAGE), percent == trunc(percent)), | 738 createExpressionNode(CSSPrimitiveValue::create(percent, CSSPrimitiveValu e::CSS_PERCENTAGE), percent == trunc(percent)), |
748 CalcAdd); | 739 CalcAdd); |
749 } | 740 } |
750 | 741 |
751 PassRefPtrWillBeRawPtr<CSSCalcValue> CSSCalcValue::create(CSSParserValueList* pa rserValueList, ValueRange range) | 742 PassRefPtrWillBeRawPtr<CSSCalcValue> CSSCalcValue::create(const CSSParserTokenRa nge& tokens, ValueRange range) |
752 { | 743 { |
753 CSSCalcExpressionNodeParser parser; | 744 CSSCalcExpressionNodeParser parser; |
754 RefPtrWillBeRawPtr<CSSCalcExpressionNode> expression = parser.parseCalc(pars erValueList); | 745 RefPtrWillBeRawPtr<CSSCalcExpressionNode> expression = parser.parseCalc(toke ns); |
755 | 746 |
756 return expression ? adoptRefWillBeNoop(new CSSCalcValue(expression, range)) : nullptr; | 747 return expression ? adoptRefWillBeNoop(new CSSCalcValue(expression, range)) : nullptr; |
757 } | 748 } |
758 | 749 |
759 PassRefPtrWillBeRawPtr<CSSCalcValue> CSSCalcValue::create(PassRefPtrWillBeRawPtr <CSSCalcExpressionNode> expression, ValueRange range) | 750 PassRefPtrWillBeRawPtr<CSSCalcValue> CSSCalcValue::create(PassRefPtrWillBeRawPtr <CSSCalcExpressionNode> expression, ValueRange range) |
760 { | 751 { |
761 return adoptRefWillBeNoop(new CSSCalcValue(expression, range)); | 752 return adoptRefWillBeNoop(new CSSCalcValue(expression, range)); |
762 } | 753 } |
763 | 754 |
764 DEFINE_TRACE_AFTER_DISPATCH(CSSCalcValue) | 755 DEFINE_TRACE_AFTER_DISPATCH(CSSCalcValue) |
765 { | 756 { |
766 visitor->trace(m_expression); | 757 visitor->trace(m_expression); |
767 CSSValue::traceAfterDispatch(visitor); | 758 CSSValue::traceAfterDispatch(visitor); |
768 } | 759 } |
769 | 760 |
770 } // namespace blink | 761 } // namespace blink |
OLD | NEW |