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