Index: Source/core/css/parser/CSSParserValues.cpp |
diff --git a/Source/core/css/parser/CSSParserValues.cpp b/Source/core/css/parser/CSSParserValues.cpp |
index 565112bf85c75f19340b3bf76dbb64f59e803d67..db68d66cc2d76ce028445013246ad52d577c879e 100644 |
--- a/Source/core/css/parser/CSSParserValues.cpp |
+++ b/Source/core/css/parser/CSSParserValues.cpp |
@@ -23,12 +23,179 @@ |
#include "core/css/CSSFunctionValue.h" |
#include "core/css/CSSSelectorList.h" |
+#include "core/css/parser/CSSPropertyParser.h" |
#include "core/html/parser/HTMLParserIdioms.h" |
namespace blink { |
using namespace WTF; |
+CSSParserValueList::CSSParserValueList(CSSParserTokenIterator start, CSSParserTokenIterator end) |
+: m_current(0) |
+{ |
+ Vector<CSSParserValueList*> stack; |
+ Vector<int> bracketCounts; |
+ stack.append(this); |
+ bracketCounts.append(0); |
+ unsigned calcDepth = 0; |
+ for (CSSParserTokenIterator it = start; it != end; ++it) { |
+ ASSERT(stack.size() == bracketCounts.size()); |
+ ASSERT(!stack.isEmpty()); |
+ const CSSParserToken& token = *it; |
+ CSSParserValue value; |
+ switch (token.type()) { |
+ case FunctionToken: { |
+ if (token.value() == "url" && it + 2 < end && (it + 2)->type() == RightParenthesisToken) { |
+ ++it; |
+ if (it->type() == BadStringToken) { |
+ destroyAndClear(); |
+ return; |
+ } |
+ ASSERT(it->type() == StringToken); |
+ CSSParserString string; |
+ string.init(it->value()); |
+ value.id = CSSValueInvalid; |
+ value.isInt = false; |
+ value.unit = CSSPrimitiveValue::CSS_URI; |
+ value.string = string; |
+ ++it; |
+ } |
+ |
+ CSSParserFunction* function = new CSSParserFunction; |
+ CSSParserString name; |
+ name.init(token.value()); |
+ function->id = cssValueKeywordID(name); |
+ CSSParserValueList* list = new CSSParserValueList; |
+ function->args = adoptPtr(list); |
+ |
+ value.id = CSSValueInvalid; |
+ value.isInt = false; |
+ value.unit = CSSParserValue::Function; |
+ value.function = function; |
+ |
+ stack.last()->addValue(value); |
+ stack.append(list); |
+ bracketCounts.append(0); |
+ calcDepth += (function->id == CSSValueCalc || function->id == CSSValueWebkitCalc); |
+ continue; |
+ } |
+ case LeftParenthesisToken: { |
+ if (calcDepth == 0) { |
+ CSSParserValueList* list = new CSSParserValueList; |
+ value.setFromValueList(adoptPtr(list)); |
+ stack.last()->addValue(value); |
+ stack.append(list); |
+ bracketCounts.append(0); |
+ continue; |
+ } |
+ bracketCounts.last()++; |
+ value.setFromOperator('('); |
+ break; |
+ } |
+ case RightParenthesisToken: { |
+ if (bracketCounts.last() == 0) { |
+ stack.removeLast(); |
+ bracketCounts.removeLast(); |
+ if (bracketCounts.isEmpty()) { |
+ destroyAndClear(); |
+ return; |
+ } |
+ CSSParserValueList* currentList = stack.last(); |
+ CSSParserValue* current = currentList->valueAt(currentList->size()-1); |
+ if (current->unit == CSSParserValue::Function) { |
+ CSSValueID id = current->function->id; |
+ calcDepth -= (id == CSSValueCalc || id == CSSValueWebkitCalc); |
+ } |
+ continue; |
+ } |
+ ASSERT(calcDepth > 0); |
+ bracketCounts.last()--; |
+ value.setFromOperator(')'); |
+ break; |
+ } |
+ case IdentToken: { |
+ CSSParserString string; |
+ string.init(token.value()); |
+ value.id = cssValueKeywordID(string); |
+ value.isInt = false; |
+ value.unit = CSSPrimitiveValue::CSS_IDENT; |
+ value.string = string; |
+ break; |
+ } |
+ case DimensionToken: |
+ case NumberToken: |
+ case PercentageToken: |
+ value.setFromNumber(token.numericValue(), token.unitType()); |
+ value.isInt = (token.numericValueType() == IntegerValueType); |
+ break; |
+ case HashToken: |
+ case StringToken: |
+ case UnicodeRangeToken: |
+ case UrlToken: { |
+ CSSParserString string; |
+ string.init(token.value()); |
+ value.id = CSSValueInvalid; |
+ value.isInt = false; |
+ if (token.type() == HashToken) |
+ value.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; |
+ else if (token.type() == StringToken) |
+ value.unit = CSSPrimitiveValue::CSS_STRING; |
+ else if (token.type() == UnicodeRangeToken) |
+ value.unit = CSSPrimitiveValue::CSS_UNICODE_RANGE; |
+ else |
+ value.unit = CSSPrimitiveValue::CSS_URI; |
+ value.string = string; |
+ break; |
+ } |
+ case DelimiterToken: |
+ value.setFromOperator(token.delimiter()); |
+ if (calcDepth && token.delimiter() == '+' && (it - 1)->type() != WhitespaceToken) { |
+ // calc(1px+ 2px) is invalid |
+ destroyAndClear(); |
+ return; |
+ } |
+ break; |
+ case CommaToken: |
+ value.setFromOperator(','); |
+ break; |
+ case LeftBracketToken: |
+ value.setFromOperator('['); |
+ break; |
+ case RightBracketToken: |
+ value.setFromOperator(']'); |
+ break; |
+ case LeftBraceToken: |
+ value.setFromOperator('{'); |
+ break; |
+ case RightBraceToken: |
+ value.setFromOperator('}'); |
+ break; |
+ case WhitespaceToken: |
+ case CommentToken: |
+ continue; |
+ case BadStringToken: |
+ case BadUrlToken: |
+ case ColonToken: |
+ case EOFToken: |
+ case SemicolonToken: |
+ destroyAndClear(); |
+ return; |
+ } |
+ stack.last()->addValue(value); |
+ } |
+ |
+ CSSParserValue rightParenthesis; |
+ rightParenthesis.setFromOperator(')'); |
+ while (!stack.isEmpty()) { |
+ while (bracketCounts.last() > 0) { |
+ bracketCounts.last()--; |
+ stack.last()->addValue(rightParenthesis); |
+ } |
+ stack.removeLast(); |
+ bracketCounts.removeLast(); |
+ } |
+} |
+ |
static void destroy(Vector<CSSParserValue, 4>& values) |
{ |
size_t numValues = values.size(); |