Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(497)

Side by Side Diff: Source/core/css/CSSCalculationValue.cpp

Issue 1239983004: Make CSSCalcValue work with CSSParserTokenRange (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Address review comments and add subtests Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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, &currentIndex, 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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698