summaryrefslogtreecommitdiff
path: root/Source/WebCore/css/CSSParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/css/CSSParser.cpp')
-rw-r--r--Source/WebCore/css/CSSParser.cpp1235
1 files changed, 772 insertions, 463 deletions
diff --git a/Source/WebCore/css/CSSParser.cpp b/Source/WebCore/css/CSSParser.cpp
index 7a5ea37d3..28ce13157 100644
--- a/Source/WebCore/css/CSSParser.cpp
+++ b/Source/WebCore/css/CSSParser.cpp
@@ -27,6 +27,7 @@
#include "CSSParser.h"
#include "CSSAspectRatioValue.h"
+#include "CSSBasicShapes.h"
#include "CSSBorderImage.h"
#include "CSSCanvasValue.h"
#include "CSSCrossfadeValue.h"
@@ -56,7 +57,6 @@
#if ENABLE(CSS_VARIABLES)
#include "CSSVariableValue.h"
#endif
-#include "CSSWrapShapes.h"
#include "Counter.h"
#include "Document.h"
#include "FloatConversion.h"
@@ -91,6 +91,7 @@
#include <wtf/dtoa.h>
#include <wtf/text/StringBuffer.h>
#include <wtf/text/StringBuilder.h>
+#include <wtf/text/StringImpl.h>
#if ENABLE(CSS_IMAGE_SET)
#include "CSSImageSetValue.h"
@@ -104,6 +105,7 @@
#endif
#if ENABLE(CSS_SHADERS)
+#include "WebKitCSSArrayFunctionValue.h"
#include "WebKitCSSMixFunctionValue.h"
#include "WebKitCSSShaderValue.h"
#endif
@@ -155,27 +157,24 @@ namespace WebCore {
static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX;
static const double MAX_SCALE = 1000000;
-static bool equal(const CSSParserString& a, const char* b)
+template <unsigned N>
+static bool equal(const CSSParserString& a, const char (&b)[N])
{
- for (int i = 0; i < a.length; ++i) {
- if (!b[i])
- return false;
- if (a.characters[i] != b[i])
- return false;
- }
- return !b[a.length];
+ unsigned length = N - 1; // Ignore the trailing null character
+ if (a.length() != length)
+ return false;
+
+ return a.is8Bit() ? WTF::equal(a.characters8(), reinterpret_cast<const LChar*>(b), length) : WTF::equal(a.characters16(), reinterpret_cast<const LChar*>(b), length);
}
-static bool equalIgnoringCase(const CSSParserString& a, const char* b)
+template <unsigned N>
+static bool equalIgnoringCase(const CSSParserString& a, const char (&b)[N])
{
- for (int i = 0; i < a.length; ++i) {
- if (!b[i])
- return false;
- ASSERT(!isASCIIUpper(b[i]));
- if (toASCIILower(a.characters[i]) != b[i])
- return false;
- }
- return !b[a.length];
+ unsigned length = N - 1; // Ignore the trailing null character
+ if (a.length() != length)
+ return false;
+
+ return a.is8Bit() ? WTF::equalIgnoringCase(b, a.characters8(), length) : WTF::equalIgnoringCase(b, a.characters16(), length);
}
static bool hasPrefix(const char* string, unsigned length, const char* prefix)
@@ -260,8 +259,10 @@ CSSParser::CSSParser(const CSSParserContext& context)
, m_propertyRange(UINT_MAX, UINT_MAX)
, m_ruleSourceDataResult(0)
, m_parsingMode(NormalMode)
- , m_currentCharacter(0)
- , m_tokenStart(0)
+ , m_is8BitSource(false)
+ , m_currentCharacter8(0)
+ , m_currentCharacter16(0)
+ , m_length(0)
, m_token(0)
, m_lineNumber(0)
, m_lastSelectorLineNumber(0)
@@ -272,6 +273,7 @@ CSSParser::CSSParser(const CSSParserContext& context)
#if YYDEBUG > 0
cssyydebug = 1;
#endif
+ m_tokenStart.ptr8 = 0;
CSSPropertySourceData::init();
}
@@ -285,7 +287,8 @@ CSSParser::~CSSParser()
deleteAllValues(m_floatingFunctions);
}
-void CSSParserString::lower()
+template <typename CharacterType>
+ALWAYS_INLINE static void makeLower(CharacterType* characters, unsigned length)
{
// FIXME: If we need Unicode lowercasing here, then we probably want the real kind
// that can potentially change the length of the string rather than the character
@@ -294,33 +297,73 @@ void CSSParserString::lower()
if (charactersAreAllASCII(characters, length)) {
// Fast case for all-ASCII.
- for (int i = 0; i < length; i++)
+ for (unsigned i = 0; i < length; i++)
characters[i] = toASCIILower(characters[i]);
} else {
- for (int i = 0; i < length; i++)
+ for (unsigned i = 0; i < length; i++)
characters[i] = Unicode::toLower(characters[i]);
}
}
+void CSSParserString::lower()
+{
+ if (is8Bit()) {
+ makeLower(characters8(), length());
+ return;
+ }
+
+ makeLower(characters16(), length());
+}
+
void CSSParser::setupParser(const char* prefix, const String& string, const char* suffix)
{
m_parsedTextPrefixLength = strlen(prefix);
- int length = string.length() + m_parsedTextPrefixLength + strlen(suffix) + 1;
+ unsigned stringLength = string.length();
+ unsigned length = stringLength + m_parsedTextPrefixLength + strlen(suffix) + 1;
+
+ if (!stringLength || string.is8Bit()) {
+ m_dataStart8 = adoptArrayPtr(new LChar[length]);
+ for (unsigned i = 0; i < m_parsedTextPrefixLength; i++)
+ m_dataStart8[i] = prefix[i];
+
+ if (stringLength)
+ memcpy(m_dataStart8.get() + m_parsedTextPrefixLength, string.characters8(), stringLength * sizeof(LChar));
+
+ unsigned start = m_parsedTextPrefixLength + stringLength;
+ unsigned end = start + strlen(suffix);
+ for (unsigned i = start; i < end; i++)
+ m_dataStart8[i] = suffix[i - start];
+
+ m_dataStart8[length - 1] = 0;
+
+ m_is8BitSource = true;
+ m_currentCharacter8 = m_dataStart8.get();
+ m_currentCharacter16 = 0;
+ setTokenStart<LChar>(m_currentCharacter8);
+ m_length = length;
+ m_lexFunc = &CSSParser::realLex<LChar>;
+ return;
+ }
- m_dataStart = adoptArrayPtr(new UChar[length]);
+ m_dataStart16 = adoptArrayPtr(new UChar[length]);
for (unsigned i = 0; i < m_parsedTextPrefixLength; i++)
- m_dataStart[i] = prefix[i];
+ m_dataStart16[i] = prefix[i];
- memcpy(m_dataStart.get() + m_parsedTextPrefixLength, string.characters(), string.length() * sizeof(UChar));
+ memcpy(m_dataStart16.get() + m_parsedTextPrefixLength, string.characters(), stringLength * sizeof(UChar));
- unsigned start = m_parsedTextPrefixLength + string.length();
+ unsigned start = m_parsedTextPrefixLength + stringLength;
unsigned end = start + strlen(suffix);
for (unsigned i = start; i < end; i++)
- m_dataStart[i] = suffix[i - start];
+ m_dataStart16[i] = suffix[i - start];
- m_dataStart[length - 1] = 0;
+ m_dataStart16[length - 1] = 0;
- m_currentCharacter = m_tokenStart = m_dataStart.get();
+ m_is8BitSource = false;
+ m_currentCharacter8 = 0;
+ m_currentCharacter16 = m_dataStart16.get();
+ setTokenStart<UChar>(m_currentCharacter16);
+ m_length = length;
+ m_lexFunc = &CSSParser::realLex<UChar>;
}
void CSSParser::parseSheet(StyleSheetContents* sheet, const String& string, int startLineNumber, RuleSourceDataList* ruleSourceDataResult)
@@ -390,8 +433,7 @@ static bool parseColorValue(StylePropertySet* declaration, CSSPropertyID propert
if (!isColorPropertyID(propertyId))
return false;
CSSParserString cssString;
- cssString.characters = const_cast<UChar*>(string.characters());
- cssString.length = string.length();
+ cssString.init(string);
int valueID = cssValueKeywordID(cssString);
bool validPrimitive = false;
if (valueID == CSSValueWebkitText)
@@ -464,8 +506,8 @@ static inline bool isSimpleLengthPropertyID(CSSPropertyID propertyId, bool& acce
}
}
-template <typename CharType>
-static inline bool parseSimpleLength(const CharType* characters, unsigned& length, CSSPrimitiveValue::UnitTypes& unit, double& number)
+template <typename CharacterType>
+static inline bool parseSimpleLength(const CharacterType* characters, unsigned& length, CSSPrimitiveValue::UnitTypes& unit, double& number)
{
if (length > 2 && (characters[length - 2] | 0x20) == 'p' && (characters[length - 1] | 0x20) == 'x') {
length -= 2;
@@ -558,12 +600,8 @@ static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int
// inline-table | table-row-group | table-header-group | table-footer-group | table-row |
// table-column-group | table-column | table-cell | table-caption | -webkit-box | -webkit-inline-box | none | inherit
// -webkit-flex | -webkit-inline-flex | -webkit-grid | -webkit-inline-grid
- if ((valueID >= CSSValueInline && valueID <= CSSValueWebkitInlineBox) || valueID == CSSValueNone)
+ if ((valueID >= CSSValueInline && valueID <= CSSValueWebkitInlineFlex) || valueID == CSSValueNone)
return true;
-#if ENABLE(CSS3_FLEXBOX)
- if (valueID == CSSValueWebkitFlex || valueID == CSSValueWebkitInlineFlex)
- return true;
-#endif
if (parserContext.isCSSGridLayoutEnabled && (valueID == CSSValueWebkitGrid || valueID == CSSValueWebkitInlineGrid))
return true;
break;
@@ -598,6 +636,11 @@ static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int
if (valueID == CSSValueAuto || valueID == CSSValueNone || (valueID >= CSSValueInset && valueID <= CSSValueDouble))
return true;
break;
+ case CSSPropertyOverflowWrap: // normal | break-word
+ case CSSPropertyWordWrap:
+ if (valueID == CSSValueNormal || valueID == CSSValueBreakWord)
+ return true;
+ break;
case CSSPropertyOverflowX: // visible | hidden | scroll | auto | marquee | overlay | inherit
if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay || valueID == CSSValueWebkitMarquee)
return true;
@@ -723,7 +766,6 @@ static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int
if (valueID == CSSValueSrgb || valueID == CSSValueDefault)
return true;
break;
-#if ENABLE(CSS3_FLEXBOX)
case CSSPropertyWebkitAlignContent:
if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround || valueID == CSSValueStretch)
return true;
@@ -748,7 +790,6 @@ static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int
if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround)
return true;
break;
-#endif
case CSSPropertyWebkitFontKerning:
if (valueID == CSSValueAuto || valueID == CSSValueNormal || valueID == CSSValueNone)
return true;
@@ -881,10 +922,6 @@ static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int
if (valueID == CSSValueNormal || valueID == CSSValueBreakAll || valueID == CSSValueBreakWord)
return true;
break;
- case CSSPropertyWordWrap: // normal | break-word
- if (valueID == CSSValueNormal || valueID == CSSValueBreakWord)
- return true;
- break;
default:
ASSERT_NOT_REACHED();
return false;
@@ -912,6 +949,7 @@ static inline bool isKeywordPropertyID(CSSPropertyID propertyId)
case CSSPropertyListStylePosition:
case CSSPropertyListStyleType:
case CSSPropertyOutlineStyle:
+ case CSSPropertyOverflowWrap:
case CSSPropertyOverflowX:
case CSSPropertyOverflowY:
case CSSPropertyPageBreakAfter:
@@ -955,14 +993,12 @@ static inline bool isKeywordPropertyID(CSSPropertyID propertyId)
case CSSPropertyWebkitColumnBreakBefore:
case CSSPropertyWebkitColumnBreakInside:
case CSSPropertyWebkitColumnRuleStyle:
-#if ENABLE(CSS3_FLEXBOX)
case CSSPropertyWebkitAlignContent:
case CSSPropertyWebkitAlignItems:
case CSSPropertyWebkitAlignSelf:
case CSSPropertyWebkitFlexDirection:
case CSSPropertyWebkitFlexWrap:
case CSSPropertyWebkitJustifyContent:
-#endif
case CSSPropertyWebkitFontKerning:
case CSSPropertyWebkitFontSmoothing:
case CSSPropertyWebkitHyphens:
@@ -1017,8 +1053,7 @@ static bool parseKeywordValue(StylePropertySet* declaration, CSSPropertyID prope
return false;
CSSParserString cssString;
- cssString.characters = const_cast<UChar*>(string.characters());
- cssString.length = string.length();
+ cssString.init(string);
int valueID = cssValueKeywordID(cssString);
if (!valueID)
@@ -1038,8 +1073,8 @@ static bool parseKeywordValue(StylePropertySet* declaration, CSSPropertyID prope
return true;
}
-template <typename CharType>
-static bool parseTransformArguments(WebKitCSSTransformValue* transformValue, CharType* characters, unsigned length, unsigned start, unsigned expectedCount)
+template <typename CharacterType>
+static bool parseTransformArguments(WebKitCSSTransformValue* transformValue, CharacterType* characters, unsigned length, unsigned start, unsigned expectedCount)
{
while (expectedCount) {
size_t end = WTF::find(characters, length, expectedCount == 1 ? ')' : ',', start);
@@ -1222,8 +1257,7 @@ bool CSSParser::parseSystemColor(RGBA32& color, const String& string, Document*
return false;
CSSParserString cssColor;
- cssColor.characters = const_cast<UChar*>(string.characters());
- cssColor.length = string.length();
+ cssColor.init(string);
int id = cssValueKeywordID(cssColor);
if (id <= 0)
return false;
@@ -1443,6 +1477,11 @@ bool CSSParser::validCalculationUnit(CSSParserValue* value, Units unitflags)
case CalcPercentNumber:
b = (unitflags & FPercent) && (unitflags & FNumber);
break;
+#if ENABLE(CSS_VARIABLES)
+ case CalcVariable:
+ b = true;
+ break;
+#endif
case CalcOther:
break;
}
@@ -2304,7 +2343,6 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important)
validPrimitive = true;
break;
#endif
-#if ENABLE(CSS3_FLEXBOX)
case CSSPropertyWebkitFlex: {
ShorthandScope scope(this, propId);
if (id == CSSValueNone) {
@@ -2334,7 +2372,6 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important)
m_valueList->next();
}
break;
-#endif
case CSSPropertyWebkitMarquee:
return parseShorthand(propId, webkitMarqueeShorthand(), important);
case CSSPropertyWebkitMarqueeIncrement:
@@ -2656,10 +2693,8 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important)
case CSSPropertyPadding:
// <padding-width>{1,4} | inherit
return parse4Values(propId, paddingShorthand().properties(), important);
-#if ENABLE(CSS3_FLEXBOX)
case CSSPropertyWebkitFlexFlow:
return parseShorthand(propId, webkitFlexFlowShorthand(), important);
-#endif
case CSSPropertyFont:
// [ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]?
// 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
@@ -2721,6 +2756,12 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important)
else
return parseFontVariantLigatures(important);
break;
+ case CSSPropertyWebkitClipPath:
+ if (id == CSSValueNone)
+ validPrimitive = true;
+ else if (value->unit == CSSParserValue::Function)
+ return parseBasicShape(propId, important);
+ break;
#if ENABLE(CSS_EXCLUSIONS)
case CSSPropertyWebkitShapeInside:
case CSSPropertyWebkitShapeOutside:
@@ -2729,7 +2770,7 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important)
if (id == CSSValueAuto)
validPrimitive = true;
else if (value->unit == CSSParserValue::Function)
- return parseExclusionShape((propId == CSSPropertyWebkitShapeInside), important);
+ return parseBasicShape(propId, important);
break;
case CSSPropertyWebkitWrapMargin:
case CSSPropertyWebkitWrapPadding:
@@ -2768,6 +2809,7 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important)
case CSSPropertyListStylePosition:
case CSSPropertyListStyleType:
case CSSPropertyOutlineStyle:
+ case CSSPropertyOverflowWrap:
case CSSPropertyOverflowX:
case CSSPropertyOverflowY:
case CSSPropertyPageBreakAfter:
@@ -2811,14 +2853,12 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important)
case CSSPropertyWebkitColumnBreakBefore:
case CSSPropertyWebkitColumnBreakInside:
case CSSPropertyWebkitColumnRuleStyle:
-#if ENABLE(CSS3_FLEXBOX)
case CSSPropertyWebkitAlignContent:
case CSSPropertyWebkitAlignItems:
case CSSPropertyWebkitAlignSelf:
case CSSPropertyWebkitFlexDirection:
case CSSPropertyWebkitFlexWrap:
case CSSPropertyWebkitJustifyContent:
-#endif
case CSSPropertyWebkitFontKerning:
case CSSPropertyWebkitFontSmoothing:
case CSSPropertyWebkitHyphens:
@@ -3065,8 +3105,8 @@ void CSSParser::storeVariableDeclaration(const CSSParserString& name, PassOwnPtr
if (!value)
return;
- ASSERT(name.length > 12);
- AtomicString variableName = String(name.characters + 12, name.length - 12);
+ ASSERT(name.length() > 12);
+ AtomicString variableName = name.is8Bit() ? AtomicString(name.characters8() + 12, name.length() - 12) : AtomicString(name.characters16() + 12, name.length() - 12);
StringBuilder builder;
for (unsigned i = 0, size = value->size(); i < size; i++) {
@@ -4307,7 +4347,7 @@ bool CSSParser::parseDashboardRegions(CSSPropertyID propId, bool important)
}
bool validFunctionName = false;
#if ENABLE(DASHBOARD_SUPPORT)
- static const char* const dashboardRegionFunctionName = "dashboard-region(";
+ static const char dashboardRegionFunctionName[] = "dashboard-region(";
if (equalIgnoringCase(value->function->name, dashboardRegionFunctionName)) {
validFunctionName = true;
#if ENABLE(DASHBOARD_SUPPORT) && ENABLE(WIDGET_REGION)
@@ -4317,7 +4357,7 @@ bool CSSParser::parseDashboardRegions(CSSPropertyID propId, bool important)
}
#endif
#if ENABLE(WIDGET_REGION)
- static const char* const widgetRegionFunctionName = "region(";
+ static const char widgetRegionFunctionName[] = "region(";
if (equalIgnoringCase(value->function->name, widgetRegionFunctionName)) {
validFunctionName = true;
#if ENABLE(DASHBOARD_SUPPORT) && ENABLE(WIDGET_REGION)
@@ -4515,9 +4555,7 @@ bool CSSParser::parseClipShape(CSSPropertyID propId, bool important)
return false;
}
-#if ENABLE(CSS_EXCLUSIONS)
-
-PassRefPtr<CSSWrapShape> CSSParser::parseExclusionShapeRectangle(CSSParserValueList* args)
+PassRefPtr<CSSBasicShape> CSSParser::parseBasicShapeRectangle(CSSParserValueList* args)
{
ASSERT(args);
@@ -4525,7 +4563,7 @@ PassRefPtr<CSSWrapShape> CSSParser::parseExclusionShapeRectangle(CSSParserValueL
if (args->size() != 7 && args->size() != 9 && args->size() != 11)
return 0;
- RefPtr<CSSWrapShapeRectangle> shape = CSSWrapShapeRectangle::create();
+ RefPtr<CSSBasicShapeRectangle> shape = CSSBasicShapeRectangle::create();
unsigned argumentNumber = 0;
CSSParserValue* argument = args->current();
@@ -4575,7 +4613,7 @@ PassRefPtr<CSSWrapShape> CSSParser::parseExclusionShapeRectangle(CSSParserValueL
return shape;
}
-PassRefPtr<CSSWrapShape> CSSParser::parseExclusionShapeCircle(CSSParserValueList* args)
+PassRefPtr<CSSBasicShape> CSSParser::parseBasicShapeCircle(CSSParserValueList* args)
{
ASSERT(args);
@@ -4583,7 +4621,7 @@ PassRefPtr<CSSWrapShape> CSSParser::parseExclusionShapeCircle(CSSParserValueList
if (args->size() != 5)
return 0;
- RefPtr<CSSWrapShapeCircle> shape = CSSWrapShapeCircle::create();
+ RefPtr<CSSBasicShapeCircle> shape = CSSBasicShapeCircle::create();
unsigned argumentNumber = 0;
CSSParserValue* argument = args->current();
@@ -4625,7 +4663,7 @@ PassRefPtr<CSSWrapShape> CSSParser::parseExclusionShapeCircle(CSSParserValueList
return shape;
}
-PassRefPtr<CSSWrapShape> CSSParser::parseExclusionShapeEllipse(CSSParserValueList* args)
+PassRefPtr<CSSBasicShape> CSSParser::parseBasicShapeEllipse(CSSParserValueList* args)
{
ASSERT(args);
@@ -4633,7 +4671,7 @@ PassRefPtr<CSSWrapShape> CSSParser::parseExclusionShapeEllipse(CSSParserValueLis
if (args->size() != 7)
return 0;
- RefPtr<CSSWrapShapeEllipse> shape = CSSWrapShapeEllipse::create();
+ RefPtr<CSSBasicShapeEllipse> shape = CSSBasicShapeEllipse::create();
unsigned argumentNumber = 0;
CSSParserValue* argument = args->current();
while (argument) {
@@ -4676,7 +4714,7 @@ PassRefPtr<CSSWrapShape> CSSParser::parseExclusionShapeEllipse(CSSParserValueLis
return shape;
}
-PassRefPtr<CSSWrapShape> CSSParser::parseExclusionShapePolygon(CSSParserValueList* args)
+PassRefPtr<CSSBasicShape> CSSParser::parseBasicShapePolygon(CSSParserValueList* args)
{
ASSERT(args);
@@ -4684,7 +4722,7 @@ PassRefPtr<CSSWrapShape> CSSParser::parseExclusionShapePolygon(CSSParserValueLis
if (!size)
return 0;
- RefPtr<CSSWrapShapePolygon> shape = CSSWrapShapePolygon::create();
+ RefPtr<CSSBasicShapePolygon> shape = CSSBasicShapePolygon::create();
CSSParserValue* argument = args->current();
if (argument->id == CSSValueEvenodd || argument->id == CSSValueNonzero) {
@@ -4727,36 +4765,33 @@ PassRefPtr<CSSWrapShape> CSSParser::parseExclusionShapePolygon(CSSParserValueLis
return shape;
}
-bool CSSParser::parseExclusionShape(bool shapeInside, bool important)
+bool CSSParser::parseBasicShape(CSSPropertyID propId, bool important)
{
CSSParserValue* value = m_valueList->current();
+ ASSERT(value->unit == CSSParserValue::Function);
CSSParserValueList* args = value->function->args.get();
if (!args)
return false;
- RefPtr<CSSWrapShape> shape;
-
+ RefPtr<CSSBasicShape> shape;
if (equalIgnoringCase(value->function->name, "rectangle("))
- shape = parseExclusionShapeRectangle(args);
+ shape = parseBasicShapeRectangle(args);
else if (equalIgnoringCase(value->function->name, "circle("))
- shape = parseExclusionShapeCircle(args);
+ shape = parseBasicShapeCircle(args);
else if (equalIgnoringCase(value->function->name, "ellipse("))
- shape = parseExclusionShapeEllipse(args);
+ shape = parseBasicShapeEllipse(args);
else if (equalIgnoringCase(value->function->name, "polygon("))
- shape = parseExclusionShapePolygon(args);
+ shape = parseBasicShapePolygon(args);
- if (shape) {
- addProperty(shapeInside ? CSSPropertyWebkitShapeInside : CSSPropertyWebkitShapeOutside, cssValuePool().createValue(shape.release()), important);
- m_valueList->next();
- return true;
- }
+ if (!shape)
+ return false;
- return false;
+ addProperty(propId, cssValuePool().createValue(shape.release()), important);
+ m_valueList->next();
+ return true;
}
-#endif
-
// [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]? 'font-family'
bool CSSParser::parseFont(bool important)
{
@@ -4843,7 +4878,13 @@ public:
{
if (!m_builder.isEmpty())
m_builder.append(' ');
- m_builder.append(string.characters, string.length);
+
+ if (string.is8Bit()) {
+ m_builder.append(string.characters8(), string.length());
+ return;
+ }
+
+ m_builder.append(string.characters16(), string.length());
}
void commit()
@@ -5196,7 +5237,8 @@ bool CSSParser::parseFontFaceUnicodeRange()
// Returns the number of characters which form a valid double
// and are terminated by the given terminator character
-static int checkForValidDouble(const UChar* string, const UChar* end, const char terminator)
+template <typename CharacterType>
+static int checkForValidDouble(const CharacterType* string, const CharacterType* end, const char terminator)
{
int length = end - string;
if (length < 1)
@@ -5226,7 +5268,8 @@ static int checkForValidDouble(const UChar* string, const UChar* end, const char
// Returns the number of characters consumed for parsing a valid double
// terminated by the given terminator character
-static int parseDouble(const UChar* string, const UChar* end, const char terminator, double& value)
+template <typename CharacterType>
+static int parseDouble(const CharacterType* string, const CharacterType* end, const char terminator, double& value)
{
int length = checkForValidDouble(string, end, terminator);
if (!length)
@@ -5260,9 +5303,10 @@ static int parseDouble(const UChar* string, const UChar* end, const char termina
return length;
}
-static bool parseColorIntOrPercentage(const UChar*& string, const UChar* end, const char terminator, CSSPrimitiveValue::UnitTypes& expect, int& value)
+template <typename CharacterType>
+static bool parseColorIntOrPercentage(const CharacterType*& string, const CharacterType* end, const char terminator, CSSPrimitiveValue::UnitTypes& expect, int& value)
{
- const UChar* current = string;
+ const CharacterType* current = string;
double localValue = 0;
bool negative = false;
while (current != end && isHTMLSpace(*current))
@@ -5327,7 +5371,8 @@ static bool parseColorIntOrPercentage(const UChar*& string, const UChar* end, co
return true;
}
-static inline bool isTenthAlpha(const UChar* string, const int length)
+template <typename CharacterType>
+static inline bool isTenthAlpha(const CharacterType* string, const int length)
{
// "0.X"
if (length == 3 && string[0] == '0' && string[1] == '.' && isASCIIDigit(string[2]))
@@ -5340,7 +5385,8 @@ static inline bool isTenthAlpha(const UChar* string, const int length)
return false;
}
-static inline bool parseAlphaValue(const UChar*& string, const UChar* end, const char terminator, int& value)
+template <typename CharacterType>
+static inline bool parseAlphaValue(const CharacterType*& string, const CharacterType* end, const char terminator, int& value)
{
while (string != end && isHTMLSpace(*string))
string++;
@@ -5391,7 +5437,8 @@ static inline bool parseAlphaValue(const UChar*& string, const UChar* end, const
return true;
}
-static inline bool mightBeRGBA(const UChar* characters, unsigned length)
+template <typename CharacterType>
+static inline bool mightBeRGBA(const CharacterType* characters, unsigned length)
{
if (length < 5)
return false;
@@ -5402,7 +5449,8 @@ static inline bool mightBeRGBA(const UChar* characters, unsigned length)
&& isASCIIAlphaCaselessEqual(characters[3], 'a');
}
-static inline bool mightBeRGB(const UChar* characters, unsigned length)
+template <typename CharacterType>
+static inline bool mightBeRGB(const CharacterType* characters, unsigned length)
{
if (length < 4)
return false;
@@ -5412,14 +5460,13 @@ static inline bool mightBeRGB(const UChar* characters, unsigned length)
&& isASCIIAlphaCaselessEqual(characters[2], 'b');
}
-bool CSSParser::fastParseColor(RGBA32& rgb, const String& name, bool strict)
+template <typename CharacterType>
+static inline bool fastParseColorInternal(RGBA32& rgb, const CharacterType* characters, unsigned length , bool strict)
{
- const UChar* characters = name.characters();
- unsigned length = name.length();
CSSPrimitiveValue::UnitTypes expect = CSSPrimitiveValue::CSS_UNKNOWN;
-
+
if (!strict && length >= 3) {
- if (name[0] == '#') {
+ if (characters[0] == '#') {
if (Color::parseHexColor(characters + 1, length - 1, rgb))
return true;
} else {
@@ -5430,13 +5477,13 @@ bool CSSParser::fastParseColor(RGBA32& rgb, const String& name, bool strict)
// Try rgba() syntax.
if (mightBeRGBA(characters, length)) {
- const UChar* current = characters + 5;
- const UChar* end = characters + length;
+ const CharacterType* current = characters + 5;
+ const CharacterType* end = characters + length;
int red;
int green;
int blue;
int alpha;
-
+
if (!parseColorIntOrPercentage(current, end, ',', expect, red))
return false;
if (!parseColorIntOrPercentage(current, end, ',', expect, green))
@@ -5453,8 +5500,8 @@ bool CSSParser::fastParseColor(RGBA32& rgb, const String& name, bool strict)
// Try rgb() syntax.
if (mightBeRGB(characters, length)) {
- const UChar* current = characters + 4;
- const UChar* end = characters + length;
+ const CharacterType* current = characters + 4;
+ const CharacterType* end = characters + length;
int red;
int green;
int blue;
@@ -5470,6 +5517,25 @@ bool CSSParser::fastParseColor(RGBA32& rgb, const String& name, bool strict)
return true;
}
+ return false;
+}
+
+bool CSSParser::fastParseColor(RGBA32& rgb, const String& name, bool strict)
+{
+ unsigned length = name.length();
+ bool parseResult;
+
+ if (!length)
+ return false;
+
+ if (name.is8Bit())
+ parseResult = fastParseColorInternal(rgb, name.characters8(), length, strict);
+ else
+ parseResult = fastParseColorInternal(rgb, name.characters(), length, strict);
+
+ if (parseResult)
+ return true;
+
// Try named colors.
Color tc;
tc.setNamedColor(name);
@@ -5478,6 +5544,7 @@ bool CSSParser::fastParseColor(RGBA32& rgb, const String& name, bool strict)
return true;
}
return false;
+
}
inline double CSSParser::parsedDouble(CSSParserValue *v, ReleaseParsedCalcValueCondition releaseCalc)
@@ -5891,8 +5958,6 @@ bool CSSParser::parseReflect(CSSPropertyID propId, bool important)
return true;
}
-#if ENABLE(CSS3_FLEXBOX)
-
bool CSSParser::parseFlex(CSSParserValueList* args, bool important)
{
if (!args || !args->size() || args->size() > 3)
@@ -5937,8 +6002,6 @@ bool CSSParser::parseFlex(CSSParserValueList* args, bool important)
return true;
}
-#endif
-
struct BorderImageParseContext {
BorderImageParseContext()
: m_canAdvance(false)
@@ -7180,9 +7243,16 @@ PassRefPtr<CSSValue> CSSParser::parseImageSet(CSSParserValueList* valueList)
double imageScaleFactor = 0;
const String& string = arg->string;
- const UChar* current = string.characters();
- const UChar* end = current + string.length();
- parseDouble(current, end, 'x', imageScaleFactor);
+ unsigned length = string.length();
+ if (!length)
+ return 0;
+ if (string.is8Bit()) {
+ const LChar* start = string.characters8();
+ parseDouble(start, start + length, 'x', imageScaleFactor);
+ } else {
+ const UChar* start = string.characters();
+ parseDouble(start, start + length, 'x', imageScaleFactor);
+ }
if (imageScaleFactor <= 0)
return 0;
imageSet->append(cssValuePool().createValue(imageScaleFactor, CSSPrimitiveValue::CSS_NUMBER));
@@ -7207,10 +7277,10 @@ PassRefPtr<CSSValue> CSSParser::parseImageSet(CSSParserValueList* valueList)
class TransformOperationInfo {
public:
TransformOperationInfo(const CSSParserString& name)
- : m_type(WebKitCSSTransformValue::UnknownTransformOperation)
- , m_argCount(1)
- , m_allowSingleArgument(false)
- , m_unit(CSSParser::FUnknown)
+ : m_type(WebKitCSSTransformValue::UnknownTransformOperation)
+ , m_argCount(1)
+ , m_allowSingleArgument(false)
+ , m_unit(CSSParser::FUnknown)
{
if (equalIgnoringCase(name, "scale(") || equalIgnoringCase(name, "scalex(") || equalIgnoringCase(name, "scaley(") || equalIgnoringCase(name, "scalez(")) {
m_unit = CSSParser::FNumber;
@@ -7437,6 +7507,41 @@ static bool acceptCommaOperator(CSSParserValueList* argsList)
return true;
}
+PassRefPtr<WebKitCSSArrayFunctionValue> CSSParser::parseCustomFilterArrayFunction(CSSParserValue* value)
+{
+ ASSERT(value->unit == CSSParserValue::Function && value->function);
+
+ if (!equalIgnoringCase(value->function->name, "array("))
+ return 0;
+
+ CSSParserValueList* arrayArgsParserValueList = value->function->args.get();
+ if (!arrayArgsParserValueList || !arrayArgsParserValueList->size())
+ return 0;
+
+ // array() values are comma separated.
+ RefPtr<WebKitCSSArrayFunctionValue> arrayFunction = WebKitCSSArrayFunctionValue::create();
+ while (true) {
+ // We parse pairs <Value, Comma> at each step.
+ CSSParserValue* currentParserValue = arrayArgsParserValueList->current();
+ if (!currentParserValue || !validUnit(currentParserValue, FNumber, CSSStrictMode))
+ return 0;
+
+ RefPtr<CSSValue> arrayValue = cssValuePool().createValue(currentParserValue->fValue, CSSPrimitiveValue::CSS_NUMBER);
+ arrayFunction->append(arrayValue.release());
+
+ CSSParserValue* nextParserValue = arrayArgsParserValueList->next();
+ if (!nextParserValue)
+ break;
+
+ if (!isComma(nextParserValue))
+ return 0;
+
+ arrayArgsParserValueList->next();
+ }
+
+ return arrayFunction;
+}
+
PassRefPtr<WebKitCSSMixFunctionValue> CSSParser::parseMixFunction(CSSParserValue* value)
{
ASSERT(value->unit == CSSParserValue::Function && value->function);
@@ -7445,6 +7550,9 @@ PassRefPtr<WebKitCSSMixFunctionValue> CSSParser::parseMixFunction(CSSParserValue
return 0;
CSSParserValueList* argsList = value->function->args.get();
+ if (!argsList)
+ return 0;
+
unsigned numArgs = argsList->size();
if (numArgs < 1 || numArgs > 3)
return 0;
@@ -7602,13 +7710,19 @@ PassRefPtr<WebKitCSSFilterValue> CSSParser::parseCustomFilter(CSSParserValue* va
RefPtr<CSSValue> parameterValue;
- if (arg->unit == CSSParserValue::Function && arg->function)
+ if (arg->unit == CSSParserValue::Function && arg->function) {
// TODO: Implement other parameters types parsing.
// textures: https://bugs.webkit.org/show_bug.cgi?id=71442
// mat2, mat3, mat4: https://bugs.webkit.org/show_bug.cgi?id=71444
- // array: https://bugs.webkit.org/show_bug.cgi?id=94226
// 3d-transform shall be the last to be checked
- parameterValue = parseCustomFilterTransform(argsList);
+ if (equalIgnoringCase(arg->function->name, "array(")) {
+ parameterValue = parseCustomFilterArrayFunction(arg);
+ // This parsing step only consumes function arguments,
+ // argsList is therefore moved forward explicitely.
+ argsList->next();
+ } else
+ parameterValue = parseCustomFilterTransform(argsList);
+ }
else {
RefPtr<CSSValueList> paramValueList = CSSValueList::createSpaceSeparated();
while ((arg = argsList->current())) {
@@ -8143,17 +8257,17 @@ bool CSSParser::parseLineBoxContain(bool important)
bool CSSParser::parseFontFeatureTag(CSSValueList* settings)
{
// Feature tag name consists of 4-letter characters.
- static const int tagNameLength = 4;
+ static const unsigned tagNameLength = 4;
CSSParserValue* value = m_valueList->current();
// Feature tag name comes first
if (value->unit != CSSPrimitiveValue::CSS_STRING)
return false;
- if (value->string.length != tagNameLength)
+ if (value->string.length() != tagNameLength)
return false;
- for (int i = 0; i < tagNameLength; ++i) {
+ for (unsigned i = 0; i < tagNameLength; ++i) {
// Limits the range of characters to 0x20-0x7E, following the tag name rules defiend in the OpenType specification.
- UChar character = value->string.characters[i];
+ UChar character = value->string[i];
if (character < 0x20 || character > 0x7E)
return false;
}
@@ -8434,30 +8548,35 @@ static const CharacterType typesOfASCIICharacters[128] = {
// Utility functions for the CSS tokenizer.
-static inline bool isCSSLetter(UChar character)
+template <typename CharacterType>
+static inline bool isCSSLetter(CharacterType character)
{
return character >= 128 || typesOfASCIICharacters[character] <= CharacterDash;
}
-static inline bool isCSSEscape(UChar character)
+template <typename CharacterType>
+static inline bool isCSSEscape(CharacterType character)
{
return character >= ' ' && character != 127;
}
-static inline bool isURILetter(UChar character)
+template <typename CharacterType>
+static inline bool isURILetter(CharacterType character)
{
return (character >= '*' && character != 127) || (character >= '#' && character <= '&') || character == '!';
}
-static inline bool isIdentifierStartAfterDash(UChar* currentCharacter)
+template <typename CharacterType>
+static inline bool isIdentifierStartAfterDash(CharacterType* currentCharacter)
{
return isASCIIAlpha(currentCharacter[0]) || currentCharacter[0] == '_' || currentCharacter[0] >= 128
|| (currentCharacter[0] == '\\' && isCSSEscape(currentCharacter[1]));
}
-static inline bool isEqualToCSSIdentifier(UChar* cssString, const char* constantString)
+template <typename CharacterType>
+static inline bool isEqualToCSSIdentifier(CharacterType* cssString, const char* constantString)
{
- // Compare an UChar memory data with a zero terminated string.
+ // Compare an character memory data with a zero terminated string.
do {
// The input must be part of an identifier if constantChar or constString
// contains '-'. Otherwise toASCIILowerUnchecked('\r') would be equal to '-'.
@@ -8469,7 +8588,8 @@ static inline bool isEqualToCSSIdentifier(UChar* cssString, const char* constant
return true;
}
-static UChar* checkAndSkipEscape(UChar* currentCharacter)
+template <typename CharacterType>
+static CharacterType* checkAndSkipEscape(CharacterType* currentCharacter)
{
// Returns with 0, if escape check is failed. Otherwise
// it returns with the following character.
@@ -8494,7 +8614,8 @@ static UChar* checkAndSkipEscape(UChar* currentCharacter)
return currentCharacter + 1;
}
-static inline UChar* skipWhiteSpace(UChar* currentCharacter)
+template <typename CharacterType>
+static inline CharacterType* skipWhiteSpace(CharacterType* currentCharacter)
{
while (isHTMLSpace(*currentCharacter))
++currentCharacter;
@@ -8503,13 +8624,55 @@ static inline UChar* skipWhiteSpace(UChar* currentCharacter)
// Main CSS tokenizer functions.
+template <>
+LChar* CSSParserString::characters<LChar>() const { return characters8(); }
+
+template <>
+UChar* CSSParserString::characters<UChar>() const { return characters16(); }
+
+template <>
+inline LChar*& CSSParser::currentCharacter<LChar>()
+{
+ return m_currentCharacter8;
+}
+
+template <>
+inline UChar*& CSSParser::currentCharacter<UChar>()
+{
+ return m_currentCharacter16;
+}
+
+UChar*& CSSParser::currentCharacter16()
+{
+ if (!m_currentCharacter16) {
+ m_dataStart16 = adoptArrayPtr(new UChar[m_length]);
+ m_currentCharacter16 = m_dataStart16.get();
+ }
+
+ return m_currentCharacter16;
+}
+
+template <>
+inline LChar* CSSParser::tokenStart<LChar>()
+{
+ return m_tokenStart.ptr8;
+}
+
+template <>
+inline UChar* CSSParser::tokenStart<UChar>()
+{
+ return m_tokenStart.ptr16;
+}
+
+template <typename CharacterType>
inline bool CSSParser::isIdentifierStart()
{
// Check whether an identifier is started.
- return isIdentifierStartAfterDash((*m_currentCharacter != '-') ? m_currentCharacter : m_currentCharacter + 1);
+ return isIdentifierStartAfterDash((*currentCharacter<CharacterType>() != '-') ? currentCharacter<CharacterType>() : currentCharacter<CharacterType>() + 1);
}
-inline UChar* CSSParser::checkAndSkipString(UChar* currentCharacter, UChar quote)
+template <typename CharacterType>
+inline CharacterType* CSSParser::checkAndSkipString(CharacterType* currentCharacter, int quote)
{
// Returns with 0, if string check is failed. Otherwise
// it returns with the following character. This is necessary
@@ -8543,101 +8706,194 @@ inline UChar* CSSParser::checkAndSkipString(UChar* currentCharacter, UChar quote
}
}
-void CSSParser::parseEscape(UChar*& result)
+template <typename CharacterType>
+unsigned CSSParser::parseEscape(CharacterType*& src)
{
- ASSERT(*m_currentCharacter == '\\' && isCSSEscape(m_currentCharacter[1]));
+ ASSERT(*src == '\\' && isCSSEscape(src[1]));
+
+ unsigned unicode = 0;
+
+ ++src;
+ if (isASCIIHexDigit(*src)) {
- ++m_currentCharacter;
- if (isASCIIHexDigit(*m_currentCharacter)) {
- unsigned unicode = 0;
int length = 6;
do {
- unicode = (unicode << 4) + toASCIIHexValue(*m_currentCharacter++);
- } while (--length && isASCIIHexDigit(*m_currentCharacter));
+ unicode = (unicode << 4) + toASCIIHexValue(*src++);
+ } while (--length && isASCIIHexDigit(*src));
// Characters above 0x10ffff are not handled.
if (unicode > 0x10ffff)
unicode = 0xfffd;
// Optional space after the escape sequence.
- if (isHTMLSpace(*m_currentCharacter))
- ++m_currentCharacter;
+ if (isHTMLSpace(*src))
+ ++src;
- // Replace unicode with a surrogate pairs when it is bigger than 0xffff
- if (U16_LENGTH(unicode) == 2) {
- *result++ = U16_LEAD(unicode);
- *result = U16_TRAIL(unicode);
- } else
- *result = unicode;
+ return unicode;
+ }
+
+ return *currentCharacter<CharacterType>()++;
+}
+
+template <>
+inline void CSSParser::UnicodeToChars<LChar>(LChar*& result, unsigned unicode)
+{
+ ASSERT(unicode <= 0xff);
+ *result = unicode;
+
+ ++result;
+}
+
+template <>
+inline void CSSParser::UnicodeToChars<UChar>(UChar*& result, unsigned unicode)
+{
+ // Replace unicode with a surrogate pairs when it is bigger than 0xffff
+ if (U16_LENGTH(unicode) == 2) {
+ *result++ = U16_LEAD(unicode);
+ *result = U16_TRAIL(unicode);
} else
- *result = *m_currentCharacter++;
+ *result = unicode;
+
++result;
}
-inline void CSSParser::parseIdentifier(UChar*& result, bool& hasEscape)
+template <typename SrcCharacterType, typename DestCharacterType>
+inline bool CSSParser::parseIdentifierInternal(SrcCharacterType*& src, DestCharacterType*& result, bool& hasEscape)
{
- // If a valid identifier start is found, we can safely
- // parse the identifier until the next invalid character.
- ASSERT(isIdentifierStart());
hasEscape = false;
do {
- if (LIKELY(*m_currentCharacter != '\\'))
- *result++ = *m_currentCharacter++;
+ if (LIKELY(*src != '\\'))
+ *result++ = *src++;
else {
hasEscape = true;
- parseEscape(result);
+ SrcCharacterType* savedEscapeStart = src;
+ unsigned unicode = parseEscape<SrcCharacterType>(src);
+ if (unicode > 0xff && sizeof(DestCharacterType) == 1) {
+ src = savedEscapeStart;
+ return false;
+ }
+ UnicodeToChars(result, unicode);
}
- } while (isCSSLetter(m_currentCharacter[0]) || (m_currentCharacter[0] == '\\' && isCSSEscape(m_currentCharacter[1])));
+ } while (isCSSLetter(src[0]) || (src[0] == '\\' && isCSSEscape(src[1])));
+
+ return true;
+}
+
+template <typename CharacterType>
+inline void CSSParser::parseIdentifier(CharacterType*& result, CSSParserString& resultString, bool& hasEscape)
+{
+ // If a valid identifier start is found, we can safely
+ // parse the identifier until the next invalid character.
+ ASSERT(isIdentifierStart<CharacterType>());
+
+ CharacterType* start = currentCharacter<CharacterType>();
+ if (UNLIKELY(!parseIdentifierInternal(currentCharacter<CharacterType>(), result, hasEscape))) {
+ // Found an escape we couldn't handle with 8 bits, copy what has been recognized and continue
+ ASSERT(is8BitSource());
+ UChar*& result16 = currentCharacter16();
+ UChar* start16 = result16;
+ int i = 0;
+ for (; i < result - start; i++)
+ result16[i] = start[i];
+
+ result16 += i;
+
+ parseIdentifierInternal(currentCharacter<CharacterType>(), result16, hasEscape);
+
+ resultString.init(start16, result16 - start16);
+
+ return;
+ }
+
+ resultString.init(start, result - start);
}
-inline void CSSParser::parseString(UChar*& result, UChar quote)
+template <typename SrcCharacterType, typename DestCharacterType>
+inline bool CSSParser::parseStringInternal(SrcCharacterType*& src, DestCharacterType*& result, UChar quote)
{
while (true) {
- if (UNLIKELY(*m_currentCharacter == quote)) {
+ if (UNLIKELY(*src == quote)) {
// String parsing is done.
- ++m_currentCharacter;
- return;
+ ++src;
+ return true;
}
- if (UNLIKELY(!*m_currentCharacter)) {
+ if (UNLIKELY(!*src)) {
// String parsing is done, but don't advance pointer if at the end of input.
- return;
+ return true;
}
- ASSERT(*m_currentCharacter > '\r' || (*m_currentCharacter < '\n' && *m_currentCharacter) || *m_currentCharacter == '\v');
+ ASSERT(*src > '\r' || (*src < '\n' && *src) || *src == '\v');
- if (LIKELY(m_currentCharacter[0] != '\\'))
- *result++ = *m_currentCharacter++;
- else if (m_currentCharacter[1] == '\n' || m_currentCharacter[1] == '\f')
- m_currentCharacter += 2;
- else if (m_currentCharacter[1] == '\r')
- m_currentCharacter += m_currentCharacter[2] == '\n' ? 3 : 2;
- else
- parseEscape(result);
+ if (LIKELY(src[0] != '\\'))
+ *result++ = *src++;
+ else if (src[1] == '\n' || src[1] == '\f')
+ src += 2;
+ else if (src[1] == '\r')
+ src += src[2] == '\n' ? 3 : 2;
+ else {
+ SrcCharacterType* savedEscapeStart = src;
+ unsigned unicode = parseEscape<SrcCharacterType>(src);
+ if (unicode > 0xff && sizeof(DestCharacterType) == 1) {
+ src = savedEscapeStart;
+ return false;
+ }
+ UnicodeToChars(result, unicode);
+ }
+ }
+
+ return true;
+}
+
+template <typename CharacterType>
+inline void CSSParser::parseString(CharacterType*& result, CSSParserString& resultString, UChar quote)
+{
+ CharacterType* start = currentCharacter<CharacterType>();
+
+ if (UNLIKELY(!parseStringInternal(currentCharacter<CharacterType>(), result, quote))) {
+ // Found an escape we couldn't handle with 8 bits, copy what has been recognized and continue
+ ASSERT(is8BitSource());
+ UChar*& result16 = currentCharacter16();
+ UChar* start16 = result16;
+ int i = 0;
+ for (; i < result - start; i++)
+ result16[i] = start[i];
+
+ result16 += i;
+
+ parseStringInternal(currentCharacter<CharacterType>(), result16, quote);
+
+ resultString.init(start16, result16 - start16);
+ return;
}
+
+ resultString.init(start, result - start);
}
-inline void CSSParser::parseURI(UChar*& start, UChar*& result)
+template <typename CharacterType>
+inline bool CSSParser::parseURIInternal(CharacterType*& start, CharacterType*& result)
{
- UChar* uriStart = skipWhiteSpace(m_currentCharacter);
+ CharacterType* uriStart = skipWhiteSpace(currentCharacter<CharacterType>());
+ CharacterType* savedResult = result;
if (*uriStart == '"' || *uriStart == '\'') {
- UChar quote = *uriStart;
+ CharacterType quote = *uriStart;
++uriStart;
- UChar* stringEnd = checkAndSkipString(uriStart, quote);
+ CharacterType* stringEnd = checkAndSkipString(uriStart, quote);
if (!stringEnd)
- return;
+ return true;
stringEnd = skipWhiteSpace(stringEnd);
if (*stringEnd != ')')
- return;
+ return true;
- start = result = m_currentCharacter = uriStart;
- parseString(result, quote);
+ start = result = currentCharacter<CharacterType>() = uriStart;
+ if (!parseStringInternal(currentCharacter<CharacterType>(), result, quote))
+ return false;
- m_currentCharacter = stringEnd + 1;
+ currentCharacter<CharacterType>() = stringEnd + 1;
m_token = URI;
} else {
- UChar* stringEnd = uriStart;
+ CharacterType* stringEnd = uriStart;
while (isURILetter(*stringEnd)) {
if (*stringEnd != '\\')
@@ -8645,99 +8901,124 @@ inline void CSSParser::parseURI(UChar*& start, UChar*& result)
else {
stringEnd = checkAndSkipEscape(stringEnd);
if (!stringEnd)
- return;
+ return true;
}
}
stringEnd = skipWhiteSpace(stringEnd);
if (*stringEnd != ')')
- return;
+ return true;
- start = result = m_currentCharacter = uriStart;
- while (isURILetter(*m_currentCharacter)) {
- if (LIKELY(*m_currentCharacter != '\\'))
- *result++ = *m_currentCharacter++;
- else
- parseEscape(result);
+ start = result = currentCharacter<CharacterType>() = uriStart;
+ while (isURILetter(*currentCharacter<CharacterType>())) {
+ if (LIKELY(*currentCharacter<CharacterType>() != '\\'))
+ *result++ = *currentCharacter<CharacterType>()++;
+ else {
+ unsigned unicode = parseEscape<CharacterType>(currentCharacter<CharacterType>());
+ if (unicode > 0xff && sizeof(CharacterType) == 1) {
+ result = savedResult;
+ return false;
+ }
+ UnicodeToChars(result, unicode);
+ }
}
- m_currentCharacter = stringEnd + 1;
+ currentCharacter<CharacterType>() = stringEnd + 1;
m_token = URI;
}
+
+ return true;
+}
+
+template <typename CharacterType>
+inline void CSSParser::parseURI(CSSParserString& string)
+{
+ CharacterType* uriStart = string.characters<CharacterType>();
+ CharacterType* result = uriStart + string.length();
+ bool parseResult = parseURIInternal(uriStart, result);
+
+ // parseIdentifier() parsed and created the string, therefore there shouldn't be any unhandled escapses.
+ ASSERT_UNUSED(parseResult, parseResult);
+
+ string.init(uriStart, result - uriStart);
}
+template <typename CharacterType>
inline bool CSSParser::parseUnicodeRange()
{
- UChar* currentCharacter = m_currentCharacter + 1;
+ CharacterType* character = currentCharacter<CharacterType>() + 1;
int length = 6;
- ASSERT(*m_currentCharacter == '+');
+ ASSERT(*currentCharacter<CharacterType>() == '+');
- while (isASCIIHexDigit(*currentCharacter) && length) {
- ++currentCharacter;
+ while (isASCIIHexDigit(*character) && length) {
+ ++character;
--length;
}
- if (length && *currentCharacter == '?') {
+ if (length && *character == '?') {
// At most 5 hex digit followed by a question mark.
do {
- ++currentCharacter;
+ ++character;
--length;
- } while (*currentCharacter == '?' && length);
- m_currentCharacter = currentCharacter;
+ } while (*character == '?' && length);
+ currentCharacter<CharacterType>() = character;
return true;
}
if (length < 6) {
// At least one hex digit.
- if (currentCharacter[0] == '-' && isASCIIHexDigit(currentCharacter[1])) {
+ if (character[0] == '-' && isASCIIHexDigit(character[1])) {
// Followed by a dash and a hex digit.
- ++currentCharacter;
+ ++character;
length = 6;
do {
- ++currentCharacter;
- } while (--length && isASCIIHexDigit(*currentCharacter));
+ ++character;
+ } while (--length && isASCIIHexDigit(*character));
}
- m_currentCharacter = currentCharacter;
+ currentCharacter<CharacterType>() = character;
return true;
}
return false;
}
+template <typename CharacterType>
bool CSSParser::parseNthChild()
{
- UChar* currentCharacter = m_currentCharacter;
+ CharacterType* character = currentCharacter<CharacterType>();
- while (isASCIIDigit(*currentCharacter))
- ++currentCharacter;
- if (isASCIIAlphaCaselessEqual(*currentCharacter, 'n')) {
- m_currentCharacter = currentCharacter + 1;
+ while (isASCIIDigit(*character))
+ ++character;
+ if (isASCIIAlphaCaselessEqual(*character, 'n')) {
+ currentCharacter<CharacterType>() = character + 1;
return true;
}
return false;
}
+template <typename CharacterType>
bool CSSParser::parseNthChildExtra()
{
- UChar* currentCharacter = skipWhiteSpace(m_currentCharacter);
- if (*currentCharacter != '+' && *currentCharacter != '-')
+ CharacterType* character = skipWhiteSpace(currentCharacter<CharacterType>());
+ if (*character != '+' && *character != '-')
return false;
- currentCharacter = skipWhiteSpace(currentCharacter + 1);
- if (!isASCIIDigit(*currentCharacter))
+ character = skipWhiteSpace(character + 1);
+ if (!isASCIIDigit(*character))
return false;
do {
- ++currentCharacter;
- } while (isASCIIDigit(*currentCharacter));
+ ++character;
+ } while (isASCIIDigit(*character));
- m_currentCharacter = currentCharacter;
+ currentCharacter<CharacterType>() = character;
return true;
}
+template <typename CharacterType>
inline void CSSParser::detectFunctionTypeToken(int length)
{
ASSERT(length > 0);
- UChar* name = m_tokenStart;
+ CharacterType* name = tokenStart<CharacterType>();
switch (length) {
case 3:
@@ -8769,10 +9050,11 @@ inline void CSSParser::detectFunctionTypeToken(int length)
}
}
+template <typename CharacterType>
inline void CSSParser::detectMediaQueryToken(int length)
{
ASSERT(m_parsingMode == MediaQueryMode);
- UChar* name = m_tokenStart;
+ CharacterType* name = tokenStart<CharacterType>();
if (length == 3) {
if (isASCIIAlphaCaselessEqual(name[0], 'a') && isASCIIAlphaCaselessEqual(name[1], 'n') && isASCIIAlphaCaselessEqual(name[2], 'd'))
@@ -8786,7 +9068,8 @@ inline void CSSParser::detectMediaQueryToken(int length)
}
}
-inline void CSSParser::detectNumberToken(UChar* type, int length)
+template <typename CharacterType>
+inline void CSSParser::detectNumberToken(CharacterType* type, int length)
{
ASSERT(length > 0);
@@ -8903,9 +9186,10 @@ inline void CSSParser::detectNumberToken(UChar* type, int length)
}
}
+template <typename CharacterType>
inline void CSSParser::detectDashToken(int length)
{
- UChar* name = m_tokenStart;
+ CharacterType* name = tokenStart<CharacterType>();
if (length == 11) {
if (isASCIIAlphaCaselessEqual(name[10], 'y') && isEqualToCSSIdentifier(name + 1, "webkit-an"))
@@ -8922,9 +9206,10 @@ inline void CSSParser::detectDashToken(int length)
m_token = CALCFUNCTION;
}
+template <typename CharacterType>
inline void CSSParser::detectAtToken(int length, bool hasEscape)
{
- UChar* name = m_tokenStart;
+ CharacterType* name = tokenStart<CharacterType>();
ASSERT(name[0] == '@' && length >= 2);
// charset, font-face, import, media, namespace, page,
@@ -9110,81 +9395,80 @@ inline void CSSParser::detectAtToken(int length, bool hasEscape)
}
}
-int CSSParser::lex(void* yylvalWithoutType)
+template <typename SrcCharacterType>
+int CSSParser::realLex(void* yylvalWithoutType)
{
YYSTYPE* yylval = static_cast<YYSTYPE*>(yylvalWithoutType);
// Write pointer for the next character.
- UChar* result;
+ SrcCharacterType* result;
+ CSSParserString resultString;
bool hasEscape;
// The input buffer is terminated by a \0 character, so
// it is safe to read one character ahead of a known non-null.
-
#ifndef NDEBUG
// In debug we check with an ASSERT that the length is > 0 for string types.
- yylval->string.characters = 0;
- yylval->string.length = 0;
+ yylval->string.clear();
#endif
restartAfterComment:
- m_tokenStart = result = m_currentCharacter;
- m_token = *m_currentCharacter;
- ++m_currentCharacter;
+ result = currentCharacter<SrcCharacterType>();
+ setTokenStart(result);
+ m_token = *currentCharacter<SrcCharacterType>();
+ ++currentCharacter<SrcCharacterType>();
switch ((m_token <= 127) ? typesOfASCIICharacters[m_token] : CharacterIdentifierStart) {
case CharacterCaselessU:
- if (UNLIKELY(*m_currentCharacter == '+'))
- if (parseUnicodeRange()) {
+ if (UNLIKELY(*currentCharacter<SrcCharacterType>() == '+'))
+ if (parseUnicodeRange<SrcCharacterType>()) {
m_token = UNICODERANGE;
- yylval->string.characters = m_tokenStart;
- yylval->string.length = m_currentCharacter - m_tokenStart;
+ yylval->string.init(tokenStart<SrcCharacterType>(), currentCharacter<SrcCharacterType>() - tokenStart<SrcCharacterType>());
break;
}
// Fall through to CharacterIdentifierStart.
case CharacterIdentifierStart:
- --m_currentCharacter;
- parseIdentifier(result, hasEscape);
+ --currentCharacter<SrcCharacterType>();
+ parseIdentifier(result, yylval->string, hasEscape);
m_token = IDENT;
- yylval->string.characters = m_tokenStart;
- yylval->string.length = result - m_tokenStart;
-
- if (UNLIKELY(*m_currentCharacter == '(')) {
+ if (UNLIKELY(*currentCharacter<SrcCharacterType>() == '(')) {
m_token = FUNCTION;
if (!hasEscape)
- detectFunctionTypeToken(result - m_tokenStart);
- ++m_currentCharacter;
+ detectFunctionTypeToken<SrcCharacterType>(result - tokenStart<SrcCharacterType>());
+ ++currentCharacter<SrcCharacterType>();
++result;
- ++yylval->string.length;
+ ++yylval->string.m_length;
if (token() == URI) {
m_token = FUNCTION;
// Check whether it is really an URI.
- parseURI(yylval->string.characters, result);
- yylval->string.length = result - yylval->string.characters;
+ if (yylval->string.is8Bit())
+ parseURI<LChar>(yylval->string);
+ else
+ parseURI<UChar>(yylval->string);
}
} else if (UNLIKELY(m_parsingMode != NormalMode) && !hasEscape) {
if (m_parsingMode == MediaQueryMode)
- detectMediaQueryToken(result - m_tokenStart);
- else if (m_parsingMode == NthChildMode && isASCIIAlphaCaselessEqual(m_tokenStart[0], 'n')) {
- if (result - m_tokenStart == 1) {
+ detectMediaQueryToken<SrcCharacterType>(result - tokenStart<SrcCharacterType>());
+ else if (m_parsingMode == NthChildMode && isASCIIAlphaCaselessEqual(tokenStart<SrcCharacterType>()[0], 'n')) {
+ if (result - tokenStart<SrcCharacterType>() == 1) {
// String "n" is IDENT but "n+1" is NTH.
- if (parseNthChildExtra()) {
+ if (parseNthChildExtra<SrcCharacterType>()) {
m_token = NTH;
- yylval->string.length = m_currentCharacter - m_tokenStart;
+ yylval->string.m_length = currentCharacter<SrcCharacterType>() - tokenStart<SrcCharacterType>();
}
- } else if (result - m_tokenStart >= 2 && m_tokenStart[1] == '-') {
+ } else if (result - tokenStart<SrcCharacterType>() >= 2 && tokenStart<SrcCharacterType>()[1] == '-') {
// String "n-" is IDENT but "n-1" is NTH.
- // Set m_currentCharacter to '-' to continue parsing.
- UChar* nextCharacter = result;
- m_currentCharacter = m_tokenStart + 1;
- if (parseNthChildExtra()) {
+ // Set currentCharacter to '-' to continue parsing.
+ SrcCharacterType* nextCharacter = result;
+ currentCharacter<SrcCharacterType>() = tokenStart<SrcCharacterType>() + 1;
+ if (parseNthChildExtra<SrcCharacterType>()) {
m_token = NTH;
- yylval->string.length = m_currentCharacter - m_tokenStart;
+ yylval->string.setLength(currentCharacter<SrcCharacterType>() - tokenStart<SrcCharacterType>());
} else {
- // Revert the change to m_currentCharacter if unsuccessful.
- m_currentCharacter = nextCharacter;
+ // Revert the change to currentCharacter if unsuccessful.
+ currentCharacter<SrcCharacterType>() = nextCharacter;
}
}
}
@@ -9192,7 +9476,7 @@ restartAfterComment:
break;
case CharacterDot:
- if (!isASCIIDigit(m_currentCharacter[0]))
+ if (!isASCIIDigit(currentCharacter<SrcCharacterType>()[0]))
break;
// Fall through to CharacterNumber.
@@ -9200,23 +9484,22 @@ restartAfterComment:
bool dotSeen = (m_token == '.');
while (true) {
- if (!isASCIIDigit(m_currentCharacter[0])) {
+ if (!isASCIIDigit(currentCharacter<SrcCharacterType>()[0])) {
// Only one dot is allowed for a number,
// and it must be followed by a digit.
- if (m_currentCharacter[0] != '.' || dotSeen || !isASCIIDigit(m_currentCharacter[1]))
+ if (currentCharacter<SrcCharacterType>()[0] != '.' || dotSeen || !isASCIIDigit(currentCharacter<SrcCharacterType>()[1]))
break;
dotSeen = true;
}
- ++m_currentCharacter;
+ ++currentCharacter<SrcCharacterType>();
}
- if (UNLIKELY(m_parsingMode == NthChildMode) && !dotSeen && isASCIIAlphaCaselessEqual(*m_currentCharacter, 'n')) {
+ if (UNLIKELY(m_parsingMode == NthChildMode) && !dotSeen && isASCIIAlphaCaselessEqual(*currentCharacter<SrcCharacterType>(), 'n')) {
// "[0-9]+n" is always an NthChild.
- ++m_currentCharacter;
- parseNthChildExtra();
+ ++currentCharacter<SrcCharacterType>();
+ parseNthChildExtra<SrcCharacterType>();
m_token = NTH;
- yylval->string.characters = m_tokenStart;
- yylval->string.length = m_currentCharacter - m_tokenStart;
+ yylval->string.init(tokenStart<SrcCharacterType>(), currentCharacter<SrcCharacterType>() - tokenStart<SrcCharacterType>());
break;
}
@@ -9224,52 +9507,51 @@ restartAfterComment:
// Use SVG parser for numbers on SVG presentation attributes.
if (m_context.mode == SVGAttributeMode) {
// We need to take care of units like 'em' or 'ex'.
- UChar* currentCharacter = m_currentCharacter;
- if (isASCIIAlphaCaselessEqual(*currentCharacter, 'e')) {
- ASSERT(currentCharacter - m_tokenStart > 0);
- ++currentCharacter;
- if (*currentCharacter == '-' || *currentCharacter == '+' || isASCIIDigit(*currentCharacter)) {
- ++currentCharacter;
- while (isASCIIDigit(*currentCharacter))
- ++currentCharacter;
+ SrcCharacterType* character = currentCharacter<SrcCharacterType>();
+ if (isASCIIAlphaCaselessEqual(*character, 'e')) {
+ ASSERT(character - tokenStart<SrcCharacterType>() > 0);
+ ++character;
+ if (*character == '-' || *character == '+' || isASCIIDigit(*character)) {
+ ++character;
+ while (isASCIIDigit(*character))
+ ++character;
// Use FLOATTOKEN if the string contains exponents.
dotSeen = true;
- m_currentCharacter = currentCharacter;
+ currentCharacter<SrcCharacterType>() = character;
}
}
- if (!parseSVGNumber(m_tokenStart, currentCharacter - m_tokenStart, yylval->number))
+ if (!parseSVGNumber(tokenStart<SrcCharacterType>(), character - tokenStart<SrcCharacterType>(), yylval->number))
break;
} else
#endif
- yylval->number = charactersToDouble(m_tokenStart, m_currentCharacter - m_tokenStart);
+ yylval->number = charactersToDouble(tokenStart<SrcCharacterType>(), currentCharacter<SrcCharacterType>() - tokenStart<SrcCharacterType>());
// Type of the function.
- if (isIdentifierStart()) {
- UChar* type = m_currentCharacter;
- result = m_currentCharacter;
+ if (isIdentifierStart<SrcCharacterType>()) {
+ SrcCharacterType* type = currentCharacter<SrcCharacterType>();
+ result = currentCharacter<SrcCharacterType>();
- parseIdentifier(result, hasEscape);
- if (*m_currentCharacter == '+') {
+ parseIdentifier(result, resultString, hasEscape);
+ if (*currentCharacter<SrcCharacterType>() == '+') {
// Any identifier followed by a '+' sign is an invalid dimension.
- ++m_currentCharacter;
+ ++currentCharacter<SrcCharacterType>();
m_token = INVALIDDIMEN;
} else {
m_token = DIMEN;
if (!hasEscape)
- detectNumberToken(type, m_currentCharacter - type);
+ detectNumberToken(type, currentCharacter<SrcCharacterType>() - type);
if (m_token == DIMEN) {
// The decoded number is overwritten, but this is intentional.
- yylval->string.characters = m_tokenStart;
- yylval->string.length = m_currentCharacter - m_tokenStart;
+ yylval->string.init(tokenStart<SrcCharacterType>(), currentCharacter<SrcCharacterType>() - tokenStart<SrcCharacterType>());
}
}
- } else if (*m_currentCharacter == '%') {
+ } else if (*currentCharacter<SrcCharacterType>() == '%') {
// Although the CSS grammar says {num}% we follow
// webkit at the moment which uses {num}%+.
do {
- ++m_currentCharacter;
- } while (*m_currentCharacter == '%');
+ ++currentCharacter<SrcCharacterType>();
+ } while (*currentCharacter<SrcCharacterType>() == '%');
m_token = PERCENTAGE;
} else
m_token = dotSeen ? FLOATTOKEN : INTEGER;
@@ -9277,55 +9559,54 @@ restartAfterComment:
}
case CharacterDash:
- if (isIdentifierStartAfterDash(m_currentCharacter)) {
- --m_currentCharacter;
- parseIdentifier(result, hasEscape);
+ if (isIdentifierStartAfterDash(currentCharacter<SrcCharacterType>())) {
+ --currentCharacter<SrcCharacterType>();
+ parseIdentifier(result, resultString, hasEscape);
m_token = IDENT;
#if ENABLE(CSS_VARIABLES)
- if (cssVariablesEnabled() && isEqualToCSSIdentifier(m_tokenStart + 1, "webkit-var") && m_tokenStart[11] == '-' && isIdentifierStartAfterDash(m_tokenStart + 12))
+ if (cssVariablesEnabled() && isEqualToCSSIdentifier(tokenStart<SrcCharacterType>() + 1, "webkit-var") && tokenStart<SrcCharacterType>()[11] == '-' && isIdentifierStartAfterDash(tokenStart<SrcCharacterType>() + 12))
m_token = VAR_DEFINITION;
else
#endif
- if (*m_currentCharacter == '(') {
+ if (*currentCharacter<SrcCharacterType>() == '(') {
m_token = FUNCTION;
if (!hasEscape)
- detectDashToken(result - m_tokenStart);
- ++m_currentCharacter;
+ detectDashToken<SrcCharacterType>(result - tokenStart<SrcCharacterType>());
+ ++currentCharacter<SrcCharacterType>();
++result;
- } else if (UNLIKELY(m_parsingMode == NthChildMode) && !hasEscape && isASCIIAlphaCaselessEqual(m_tokenStart[1], 'n')) {
- if (result - m_tokenStart == 2) {
+ } else if (UNLIKELY(m_parsingMode == NthChildMode) && !hasEscape && isASCIIAlphaCaselessEqual(tokenStart<SrcCharacterType>()[1], 'n')) {
+ if (result - tokenStart<SrcCharacterType>() == 2) {
// String "-n" is IDENT but "-n+1" is NTH.
- if (parseNthChildExtra()) {
+ if (parseNthChildExtra<SrcCharacterType>()) {
m_token = NTH;
- result = m_currentCharacter;
+ result = currentCharacter<SrcCharacterType>();
}
- } else if (result - m_tokenStart >= 3 && m_tokenStart[2] == '-') {
+ } else if (result - tokenStart<SrcCharacterType>() >= 3 && tokenStart<SrcCharacterType>()[2] == '-') {
// String "-n-" is IDENT but "-n-1" is NTH.
- // Set m_currentCharacter to second '-' of '-n-' to continue parsing.
- UChar* nextCharacter = result;
- m_currentCharacter = m_tokenStart + 2;
- if (parseNthChildExtra()) {
+ // Set currentCharacter to second '-' of '-n-' to continue parsing.
+ SrcCharacterType* nextCharacter = result;
+ currentCharacter<SrcCharacterType>() = tokenStart<SrcCharacterType>() + 2;
+ if (parseNthChildExtra<SrcCharacterType>()) {
m_token = NTH;
- result = m_currentCharacter;
+ result = currentCharacter<SrcCharacterType>();
} else {
- // Revert the change to m_currentCharacter if unsuccessful.
- m_currentCharacter = nextCharacter;
+ // Revert the change to currentCharacter if unsuccessful.
+ currentCharacter<SrcCharacterType>() = nextCharacter;
}
}
}
- yylval->string.characters = m_tokenStart;
- yylval->string.length = result - m_tokenStart;
- } else if (m_currentCharacter[0] == '-' && m_currentCharacter[1] == '>') {
- m_currentCharacter += 2;
+ resultString.setLength(result - tokenStart<SrcCharacterType>());
+ yylval->string = resultString;
+ } else if (currentCharacter<SrcCharacterType>()[0] == '-' && currentCharacter<SrcCharacterType>()[1] == '>') {
+ currentCharacter<SrcCharacterType>() += 2;
m_token = SGML_CD;
} else if (UNLIKELY(m_parsingMode == NthChildMode)) {
// "-[0-9]+n" is always an NthChild.
- if (parseNthChild()) {
- parseNthChildExtra();
+ if (parseNthChild<SrcCharacterType>()) {
+ parseNthChildExtra<SrcCharacterType>();
m_token = NTH;
- yylval->string.characters = m_tokenStart;
- yylval->string.length = m_currentCharacter - m_tokenStart;
+ yylval->string.init(tokenStart<SrcCharacterType>(), currentCharacter<SrcCharacterType>() - tokenStart<SrcCharacterType>());
}
}
break;
@@ -9336,18 +9617,18 @@ restartAfterComment:
case CharacterNull:
// Do not advance pointer at the end of input.
- --m_currentCharacter;
+ --currentCharacter<SrcCharacterType>();
break;
case CharacterWhiteSpace:
m_token = WHITESPACE;
// Might start with a '\n'.
- --m_currentCharacter;
+ --currentCharacter<SrcCharacterType>();
do {
- if (*m_currentCharacter == '\n')
+ if (*currentCharacter<SrcCharacterType>() == '\n')
++m_lineNumber;
- ++m_currentCharacter;
- } while (*m_currentCharacter <= ' ' && (typesOfASCIICharacters[*m_currentCharacter] == CharacterWhiteSpace));
+ ++currentCharacter<SrcCharacterType>();
+ } while (*currentCharacter<SrcCharacterType>() <= ' ' && (typesOfASCIICharacters[*currentCharacter<SrcCharacterType>()] == CharacterWhiteSpace));
break;
case CharacterEndMediaQuery:
@@ -9361,42 +9642,39 @@ restartAfterComment:
break;
case CharacterQuote:
- if (checkAndSkipString(m_currentCharacter, m_token)) {
+ if (checkAndSkipString(currentCharacter<SrcCharacterType>(), m_token)) {
++result;
- parseString(result, m_token);
+ parseString<SrcCharacterType>(result, yylval->string, m_token);
m_token = STRING;
- yylval->string.characters = m_tokenStart + 1;
- yylval->string.length = result - (m_tokenStart + 1);
}
break;
case CharacterExclamationMark: {
- UChar* start = skipWhiteSpace(m_currentCharacter);
+ SrcCharacterType* start = skipWhiteSpace(currentCharacter<SrcCharacterType>());
if (isEqualToCSSIdentifier(start, "important")) {
m_token = IMPORTANT_SYM;
- m_currentCharacter = start + 9;
+ currentCharacter<SrcCharacterType>() = start + 9;
}
break;
}
case CharacterHashmark: {
- UChar* start = m_currentCharacter;
- result = m_currentCharacter;
+ SrcCharacterType* start = currentCharacter<SrcCharacterType>();
+ result = currentCharacter<SrcCharacterType>();
- if (isASCIIDigit(*m_currentCharacter)) {
+ if (isASCIIDigit(*currentCharacter<SrcCharacterType>())) {
// This must be a valid hex number token.
do {
- ++m_currentCharacter;
- } while (isASCIIHexDigit(*m_currentCharacter));
+ ++currentCharacter<SrcCharacterType>();
+ } while (isASCIIHexDigit(*currentCharacter<SrcCharacterType>()));
m_token = HEX;
- yylval->string.characters = start;
- yylval->string.length = m_currentCharacter - start;
- } else if (isIdentifierStart()) {
+ yylval->string.init(start, currentCharacter<SrcCharacterType>() - start);
+ } else if (isIdentifierStart<SrcCharacterType>()) {
m_token = IDSEL;
- parseIdentifier(result, hasEscape);
+ parseIdentifier(result, yylval->string, hasEscape);
if (!hasEscape) {
// Check whether the identifier is also a valid hex number.
- UChar* current = start;
+ SrcCharacterType* current = start;
m_token = HEX;
do {
if (!isASCIIHexDigit(*current)) {
@@ -9406,41 +9684,39 @@ restartAfterComment:
++current;
} while (current < result);
}
- yylval->string.characters = start;
- yylval->string.length = result - start;
}
break;
}
case CharacterSlash:
// Ignore comments. They are not even considered as white spaces.
- if (*m_currentCharacter == '*') {
- ++m_currentCharacter;
- while (m_currentCharacter[0] != '*' || m_currentCharacter[1] != '/') {
- if (*m_currentCharacter == '\n')
+ if (*currentCharacter<SrcCharacterType>() == '*') {
+ ++currentCharacter<SrcCharacterType>();
+ while (currentCharacter<SrcCharacterType>()[0] != '*' || currentCharacter<SrcCharacterType>()[1] != '/') {
+ if (*currentCharacter<SrcCharacterType>() == '\n')
++m_lineNumber;
- if (*m_currentCharacter == '\0') {
+ if (*currentCharacter<SrcCharacterType>() == '\0') {
// Unterminated comments are simply ignored.
- m_currentCharacter -= 2;
+ currentCharacter<SrcCharacterType>() -= 2;
break;
}
- ++m_currentCharacter;
+ ++currentCharacter<SrcCharacterType>();
}
- m_currentCharacter += 2;
+ currentCharacter<SrcCharacterType>() += 2;
goto restartAfterComment;
}
break;
case CharacterDollar:
- if (*m_currentCharacter == '=') {
- ++m_currentCharacter;
+ if (*currentCharacter<SrcCharacterType>() == '=') {
+ ++currentCharacter<SrcCharacterType>();
m_token = ENDSWITH;
}
break;
case CharacterAsterisk:
- if (*m_currentCharacter == '=') {
- ++m_currentCharacter;
+ if (*currentCharacter<SrcCharacterType>() == '=') {
+ ++currentCharacter<SrcCharacterType>();
m_token = CONTAINS;
}
break;
@@ -9448,58 +9724,55 @@ restartAfterComment:
case CharacterPlus:
if (UNLIKELY(m_parsingMode == NthChildMode)) {
// Simplest case. "+[0-9]*n" is always NthChild.
- if (parseNthChild()) {
- parseNthChildExtra();
+ if (parseNthChild<SrcCharacterType>()) {
+ parseNthChildExtra<SrcCharacterType>();
m_token = NTH;
- yylval->string.characters = m_tokenStart;
- yylval->string.length = m_currentCharacter - m_tokenStart;
+ yylval->string.init(tokenStart<SrcCharacterType>(), currentCharacter<SrcCharacterType>() - tokenStart<SrcCharacterType>());
}
}
break;
case CharacterLess:
- if (m_currentCharacter[0] == '!' && m_currentCharacter[1] == '-' && m_currentCharacter[2] == '-') {
- m_currentCharacter += 3;
+ if (currentCharacter<SrcCharacterType>()[0] == '!' && currentCharacter<SrcCharacterType>()[1] == '-' && currentCharacter<SrcCharacterType>()[2] == '-') {
+ currentCharacter<SrcCharacterType>() += 3;
m_token = SGML_CD;
}
break;
case CharacterAt:
- if (isIdentifierStart()) {
+ if (isIdentifierStart<SrcCharacterType>()) {
m_token = ATKEYWORD;
++result;
- parseIdentifier(result, hasEscape);
- detectAtToken(result - m_tokenStart, hasEscape);
+ parseIdentifier(result, resultString, hasEscape);
+ detectAtToken<SrcCharacterType>(result - tokenStart<SrcCharacterType>(), hasEscape);
}
break;
case CharacterBackSlash:
- if (isCSSEscape(*m_currentCharacter)) {
- --m_currentCharacter;
- parseIdentifier(result, hasEscape);
+ if (isCSSEscape(*currentCharacter<SrcCharacterType>())) {
+ --currentCharacter<SrcCharacterType>();
+ parseIdentifier(result, yylval->string, hasEscape);
m_token = IDENT;
- yylval->string.characters = m_tokenStart;
- yylval->string.length = result - m_tokenStart;
}
break;
case CharacterXor:
- if (*m_currentCharacter == '=') {
- ++m_currentCharacter;
+ if (*currentCharacter<SrcCharacterType>() == '=') {
+ ++currentCharacter<SrcCharacterType>();
m_token = BEGINSWITH;
}
break;
case CharacterVerticalBar:
- if (*m_currentCharacter == '=') {
- ++m_currentCharacter;
+ if (*currentCharacter<SrcCharacterType>() == '=') {
+ ++currentCharacter<SrcCharacterType>();
m_token = DASHMATCH;
}
break;
case CharacterTilde:
- if (*m_currentCharacter == '=') {
- ++m_currentCharacter;
+ if (*currentCharacter<SrcCharacterType>() == '=') {
+ ++currentCharacter<SrcCharacterType>();
m_token = INCLUDES;
}
break;
@@ -9509,36 +9782,6 @@ restartAfterComment:
break;
}
-#ifndef NDEBUG
- switch (token()) {
- case STRING:
- ASSERT(yylval->string.characters == m_tokenStart + 1);
- break;
-
- case IDENT:
- case NTH:
- case DIMEN:
- case UNICODERANGE:
- case FUNCTION:
- case ANYFUNCTION:
- case NOTFUNCTION:
- case CALCFUNCTION:
- case MINFUNCTION:
- case MAXFUNCTION:
- ASSERT(yylval->string.characters == m_tokenStart && yylval->string.length > 0);
- break;
-
- case URI:
- ASSERT(yylval->string.characters && yylval->string.characters != m_tokenStart);
- break;
-
- case HEX:
- case IDSEL:
- ASSERT(yylval->string.characters == m_tokenStart + 1 && yylval->string.length > 0);
- break;
- }
-#endif
-
return token();
}
@@ -9945,17 +10188,17 @@ void CSSParser::deleteFontFaceOnlyValues()
StyleKeyframe* CSSParser::createKeyframe(CSSParserValueList* keys)
{
// Create a key string from the passed keys
- String keyString;
+ StringBuilder keyString;
for (unsigned i = 0; i < keys->size(); ++i) {
float key = static_cast<float>(keys->valueAt(i)->fValue);
if (i != 0)
- keyString += ",";
- keyString += String::number(key);
- keyString += "%";
+ keyString.append(',');
+ keyString.append(String::number(key));
+ keyString.append('%');
}
RefPtr<StyleKeyframe> keyframe = StyleKeyframe::create();
- keyframe->setKeyText(keyString);
+ keyframe->setKeyText(keyString.toString());
keyframe->setProperties(createStylePropertySet());
clearProperties();
@@ -9981,17 +10224,15 @@ void CSSParser::updateLastMediaLine(MediaQuerySet* media)
media->setLastLine(m_lineNumber);
}
-void CSSParser::fixUnparsedPropertyRanges(CSSRuleSourceData* ruleData)
+template <typename CharacterType>
+static inline void fixUnparsedProperties(const CharacterType* characters, CSSRuleSourceData* ruleData)
{
- if (!ruleData->styleSourceData)
- return;
Vector<CSSPropertySourceData>& propertyData = ruleData->styleSourceData->propertyData;
unsigned size = propertyData.size();
if (!size)
return;
unsigned styleStart = ruleData->ruleBodyRange.start;
- const UChar* characters = m_dataStart.get() + m_parsedTextPrefixLength;
CSSPropertySourceData* nextData = &(propertyData.at(0));
for (unsigned i = 0; i < size; ++i) {
CSSPropertySourceData* currentData = nextData;
@@ -10028,36 +10269,60 @@ void CSSParser::fixUnparsedPropertyRanges(CSSRuleSourceData* ruleData)
}
}
+void CSSParser::fixUnparsedPropertyRanges(CSSRuleSourceData* ruleData)
+{
+ if (!ruleData->styleSourceData)
+ return;
+
+ if (is8BitSource()) {
+ fixUnparsedProperties<LChar>(m_dataStart8.get() + m_parsedTextPrefixLength, ruleData);
+ return;
+ }
+
+ fixUnparsedProperties<UChar>(m_dataStart16.get() + m_parsedTextPrefixLength, ruleData);
+}
+
void CSSParser::markRuleHeaderStart(CSSRuleSourceData::Type ruleType)
{
if (!isExtractingSourceData())
return;
RefPtr<CSSRuleSourceData> data = CSSRuleSourceData::create(ruleType);
- data->ruleHeaderRange.start = m_tokenStart - m_dataStart.get();
+ data->ruleHeaderRange.start = tokenStartOffset();
m_currentRuleDataStack->append(data.release());
}
-void CSSParser::markRuleHeaderEnd()
+template <typename CharacterType>
+inline void CSSParser::setRuleHeaderEnd(const CharacterType* dataStart)
{
- if (!isExtractingSourceData())
- return;
- ASSERT(!m_currentRuleDataStack->isEmpty());
- UChar* listEnd = m_tokenStart;
- while (listEnd > m_dataStart.get() + 1) {
+ CharacterType* listEnd = tokenStart<CharacterType>();
+ while (listEnd > dataStart + 1) {
if (isHTMLSpace(*(listEnd - 1)))
--listEnd;
else
break;
}
- m_currentRuleDataStack->last()->ruleHeaderRange.end = listEnd - m_dataStart.get();
+
+ m_currentRuleDataStack->last()->ruleHeaderRange.end = listEnd - dataStart;
+}
+
+void CSSParser::markRuleHeaderEnd()
+{
+ if (!isExtractingSourceData())
+ return;
+ ASSERT(!m_currentRuleDataStack->isEmpty());
+
+ if (is8BitSource())
+ setRuleHeaderEnd<LChar>(m_dataStart8.get());
+ else
+ setRuleHeaderEnd<UChar>(m_dataStart16.get());
}
void CSSParser::markRuleBodyStart()
{
if (!isExtractingSourceData())
return;
- unsigned offset = m_tokenStart - m_dataStart.get();
- if (*m_tokenStart == '{')
+ unsigned offset = tokenStartOffset();
+ if (tokenStartChar() == '{')
++offset; // Skip the rule body opening brace.
ASSERT(!m_currentRuleDataStack->isEmpty());
m_currentRuleDataStack->last()->ruleBodyRange.start = offset;
@@ -10066,7 +10331,7 @@ void CSSParser::markRuleBodyStart()
void CSSParser::markRuleBodyEnd()
{
// Precondition: (!isExtractingSourceData())
- unsigned offset = m_tokenStart - m_dataStart.get();
+ unsigned offset = tokenStartOffset();
ASSERT(!m_currentRuleDataStack->isEmpty());
m_currentRuleDataStack->last()->ruleBodyRange.end = offset;
}
@@ -10078,7 +10343,7 @@ void CSSParser::markPropertyStart()
if (m_currentRuleDataStack->isEmpty() || !m_currentRuleDataStack->last()->styleSourceData)
return;
- m_propertyRange.start = m_tokenStart - m_dataStart.get();
+ m_propertyRange.start = tokenStartOffset();
}
void CSSParser::markPropertyEnd(bool isImportantFound, bool isPropertyParsed)
@@ -10088,8 +10353,8 @@ void CSSParser::markPropertyEnd(bool isImportantFound, bool isPropertyParsed)
if (m_currentRuleDataStack->isEmpty() || !m_currentRuleDataStack->last()->styleSourceData)
return;
- unsigned offset = m_tokenStart - m_dataStart.get();
- if (*m_tokenStart == ';') // Include semicolon into the property text.
+ unsigned offset = tokenStartOffset();
+ if (tokenStartChar() == ';') // Include semicolon into the property text.
++offset;
m_propertyRange.end = offset;
if (m_propertyRange.start != UINT_MAX && !m_currentRuleDataStack->isEmpty()) {
@@ -10097,7 +10362,11 @@ void CSSParser::markPropertyEnd(bool isImportantFound, bool isPropertyParsed)
const unsigned start = m_propertyRange.start;
const unsigned end = m_propertyRange.end;
ASSERT(start < end);
- String propertyString = String(m_dataStart.get() + start, end - start).stripWhiteSpace();
+ String propertyString;
+ if (is8BitSource())
+ propertyString = String(m_dataStart8.get() + start, end - start).stripWhiteSpace();
+ else
+ propertyString = String(m_dataStart16.get() + start, end - start).stripWhiteSpace();
if (propertyString.endsWith(';'))
propertyString = propertyString.left(propertyString.length() - 1);
size_t colonIndex = propertyString.find(':');
@@ -10113,17 +10382,13 @@ void CSSParser::markPropertyEnd(bool isImportantFound, bool isPropertyParsed)
resetPropertyRange();
}
-static CSSPropertyID cssPropertyID(const UChar* propertyName, unsigned length)
+template <typename CharacterType>
+static CSSPropertyID cssPropertyID(const CharacterType* propertyName, unsigned length)
{
- if (!length)
- return CSSPropertyInvalid;
- if (length > maxCSSPropertyNameLength)
- return CSSPropertyInvalid;
-
char buffer[maxCSSPropertyNameLength + 1 + 1]; // 1 to turn "apple"/"khtml" into "webkit", 1 for null character
for (unsigned i = 0; i != length; ++i) {
- UChar c = propertyName[i];
+ CharacterType c = propertyName[i];
if (c == 0 || c >= 0x7F)
return CSSPropertyInvalid; // illegal character
buffer[i] = toASCIILower(c);
@@ -10161,12 +10426,26 @@ static CSSPropertyID cssPropertyID(const UChar* propertyName, unsigned length)
CSSPropertyID cssPropertyID(const String& string)
{
- return cssPropertyID(string.characters(), string.length());
+ unsigned length = string.length();
+
+ if (!length)
+ return CSSPropertyInvalid;
+ if (length > maxCSSPropertyNameLength)
+ return CSSPropertyInvalid;
+
+ return string.is8Bit() ? cssPropertyID(string.characters8(), length) : cssPropertyID(string.characters(), length);
}
CSSPropertyID cssPropertyID(const CSSParserString& string)
{
- return cssPropertyID(string.characters, string.length);
+ unsigned length = string.length();
+
+ if (!length)
+ return CSSPropertyInvalid;
+ if (length > maxCSSPropertyNameLength)
+ return CSSPropertyInvalid;
+
+ return string.is8Bit() ? cssPropertyID(string.characters8(), length) : cssPropertyID(string.characters16(), length);
}
#if PLATFORM(IOS)
@@ -10181,18 +10460,13 @@ void cssPropertyNameIOSAliasing(const char* propertyName, const char*& propertyN
}
#endif
-int cssValueKeywordID(const CSSParserString& string)
+template <typename CharacterType>
+static int cssValueKeywordID(const CharacterType* valueKeyword, unsigned length)
{
- unsigned length = string.length;
- if (!length)
- return 0;
- if (length > maxCSSValueKeywordLength)
- return 0;
-
char buffer[maxCSSValueKeywordLength + 1 + 1]; // 1 to turn "apple"/"khtml" into "webkit", 1 for null character
for (unsigned i = 0; i != length; ++i) {
- UChar c = string.characters[i];
+ CharacterType c = valueKeyword[i];
if (c == 0 || c >= 0x7F)
return 0; // illegal character
buffer[i] = WTF::toASCIILower(c);
@@ -10213,38 +10487,60 @@ int cssValueKeywordID(const CSSParserString& string)
return hashTableEntry ? hashTableEntry->id : 0;
}
-// "ident" from the CSS tokenizer, minus backslash-escape sequences
-static bool isCSSTokenizerIdentifier(const String& string)
+int cssValueKeywordID(const CSSParserString& string)
+{
+ unsigned length = string.length();
+ if (!length)
+ return 0;
+ if (length > maxCSSValueKeywordLength)
+ return 0;
+
+ return string.is8Bit() ? cssValueKeywordID(string.characters8(), length) : cssValueKeywordID(string.characters16(), length);
+}
+
+template <typename CharacterType>
+static inline bool isCSSTokenizerIdentifier(const CharacterType* characters, unsigned length)
{
- const UChar* p = string.characters();
- const UChar* end = p + string.length();
+ const CharacterType* end = characters + length;
// -?
- if (p != end && p[0] == '-')
- ++p;
+ if (characters != end && characters[0] == '-')
+ ++characters;
// {nmstart}
- if (p == end || !(p[0] == '_' || p[0] >= 128 || isASCIIAlpha(p[0])))
+ if (characters == end || !(characters[0] == '_' || characters[0] >= 128 || isASCIIAlpha(characters[0])))
return false;
- ++p;
+ ++characters;
// {nmchar}*
- for (; p != end; ++p) {
- if (!(p[0] == '_' || p[0] == '-' || p[0] >= 128 || isASCIIAlphanumeric(p[0])))
+ for (; characters != end; ++characters) {
+ if (!(characters[0] == '_' || characters[0] == '-' || characters[0] >= 128 || isASCIIAlphanumeric(characters[0])))
return false;
}
return true;
}
-// "url" from the CSS tokenizer, minus backslash-escape sequences
-static bool isCSSTokenizerURL(const String& string)
+// "ident" from the CSS tokenizer, minus backslash-escape sequences
+static bool isCSSTokenizerIdentifier(const String& string)
{
- const UChar* p = string.characters();
- const UChar* end = p + string.length();
+ unsigned length = string.length();
- for (; p != end; ++p) {
- UChar c = p[0];
+ if (!length)
+ return false;
+
+ if (string.is8Bit())
+ return isCSSTokenizerIdentifier(string.characters8(), length);
+ return isCSSTokenizerIdentifier(string.characters(), length);
+}
+
+template <typename CharacterType>
+static inline bool isCSSTokenizerURL(const CharacterType* characters, unsigned length)
+{
+ const CharacterType* end = characters + length;
+
+ for (; characters != end; ++characters) {
+ CharacterType c = characters[0];
switch (c) {
case '!':
case '#':
@@ -10261,10 +10557,23 @@ static bool isCSSTokenizerURL(const String& string)
return false;
}
}
-
+
return true;
}
+// "url" from the CSS tokenizer, minus backslash-escape sequences
+static bool isCSSTokenizerURL(const String& string)
+{
+ unsigned length = string.length();
+
+ if (!length)
+ return true;
+
+ if (string.is8Bit())
+ return isCSSTokenizerURL(string.characters8(), length);
+ return isCSSTokenizerURL(string.characters(), length);
+}
+
// We use single quotes for now because markup.cpp uses double quotes.
String quoteCSSString(const String& string)
{