Long overdue update of string types in CSS.
First step towards writing unsafe string annotations is to stop
using unsafe forms.
-- introduce CFX_CSSNumber apart from CFX_CSSNumberValue.
-- avoid discrete pointer/length pairs.
-- use std::optional<> for results.
Change-Id: I338387acfeec26fcc233600394409d7efea3c915
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/117011
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
diff --git a/core/fxcrt/css/cfx_cssdata.cpp b/core/fxcrt/css/cfx_cssdata.cpp
index 0659a59..40aacf3 100644
--- a/core/fxcrt/css/cfx_cssdata.cpp
+++ b/core/fxcrt/css/cfx_cssdata.cpp
@@ -31,14 +31,14 @@
#undef CSS_PROP_VALUE____
const CFX_CSSData::LengthUnit kLengthUnitTable[] = {
- {L"cm", CFX_CSSNumberValue::Unit::kCentiMeters},
- {L"em", CFX_CSSNumberValue::Unit::kEMS},
- {L"ex", CFX_CSSNumberValue::Unit::kEXS},
- {L"in", CFX_CSSNumberValue::Unit::kInches},
- {L"mm", CFX_CSSNumberValue::Unit::kMilliMeters},
- {L"pc", CFX_CSSNumberValue::Unit::kPicas},
- {L"pt", CFX_CSSNumberValue::Unit::kPoints},
- {L"px", CFX_CSSNumberValue::Unit::kPixels},
+ {L"cm", CFX_CSSNumber::Unit::kCentiMeters},
+ {L"em", CFX_CSSNumber::Unit::kEMS},
+ {L"ex", CFX_CSSNumber::Unit::kEXS},
+ {L"in", CFX_CSSNumber::Unit::kInches},
+ {L"mm", CFX_CSSNumber::Unit::kMilliMeters},
+ {L"pc", CFX_CSSNumber::Unit::kPicas},
+ {L"pt", CFX_CSSNumber::Unit::kPoints},
+ {L"px", CFX_CSSNumber::Unit::kPixels},
};
// 16 colours from CSS 2.0 + alternate spelling of grey/gray.
diff --git a/core/fxcrt/css/cfx_cssdata.h b/core/fxcrt/css/cfx_cssdata.h
index c129cfe..af21c5a 100644
--- a/core/fxcrt/css/cfx_cssdata.h
+++ b/core/fxcrt/css/cfx_cssdata.h
@@ -28,7 +28,7 @@
struct LengthUnit {
const wchar_t* value; // Raw, POD struct.
- CFX_CSSNumberValue::Unit type;
+ CFX_CSSNumber::Unit type;
};
struct Color {
diff --git a/core/fxcrt/css/cfx_cssdeclaration.cpp b/core/fxcrt/css/cfx_cssdeclaration.cpp
index 7077bac..87aee28 100644
--- a/core/fxcrt/css/cfx_cssdeclaration.cpp
+++ b/core/fxcrt/css/cfx_cssdeclaration.cpp
@@ -30,115 +30,96 @@
return (FXSYS_HexCharToInt(hexHigh) << 4) + FXSYS_HexCharToInt(hexLow);
}
-bool ParseCSSNumber(const wchar_t* pszValue,
- size_t nValueLen,
- float* pValue,
- CFX_CSSNumberValue::Unit* pOutUnit) {
- DCHECK(pszValue);
- DCHECK_NE(nValueLen, 0);
+std::optional<CFX_CSSNumber> ParseCSSNumber(WideStringView view) {
+ DCHECK(!view.IsEmpty());
size_t nUsedLen = 0;
- *pValue = FXSYS_wcstof(pszValue, nValueLen, &nUsedLen);
- if (nUsedLen == 0 || !isfinite(*pValue))
- return false;
-
- nValueLen -= nUsedLen;
- pszValue += nUsedLen;
- *pOutUnit = CFX_CSSNumberValue::Unit::kNumber;
- if (nValueLen >= 1 && *pszValue == '%') {
- *pOutUnit = CFX_CSSNumberValue::Unit::kPercent;
- } else if (nValueLen == 2) {
- const CFX_CSSData::LengthUnit* pUnit =
- CFX_CSSData::GetLengthUnitByName(WideStringView(pszValue, 2));
- if (pUnit)
- *pOutUnit = pUnit->type;
+ float value =
+ FXSYS_wcstof(view.unterminated_c_str(), view.GetLength(), &nUsedLen);
+ if (nUsedLen == 0 || !isfinite(value)) {
+ return std::nullopt;
}
- return true;
+ view = view.Substr(nUsedLen);
+ if (view.Front() == '%') { // NOTE: empty-tolerant Front().
+ return CFX_CSSNumber{CFX_CSSNumber::Unit::kPercent, value};
+ }
+ if (view.GetLength() == 2) {
+ const CFX_CSSData::LengthUnit* pUnit =
+ CFX_CSSData::GetLengthUnitByName(view.First(2));
+ if (pUnit) {
+ return CFX_CSSNumber{pUnit->type, value};
+ }
+ }
+ return CFX_CSSNumber{CFX_CSSNumber::Unit::kNumber, value};
}
} // namespace
// static
-bool CFX_CSSDeclaration::ParseCSSString(const wchar_t* pszValue,
- size_t nValueLen,
- size_t* nOffset,
- size_t* nLength) {
- DCHECK(pszValue);
- DCHECK_NE(nValueLen, 0);
-
- *nOffset = 0;
- *nLength = nValueLen;
- if (nValueLen >= 2) {
- wchar_t first = pszValue[0];
- wchar_t last = pszValue[nValueLen - 1];
+std::optional<WideStringView> CFX_CSSDeclaration::ParseCSSString(
+ WideStringView value) {
+ if (value.GetLength() >= 2) {
+ wchar_t first = value.Front();
+ wchar_t last = value.Back();
if ((first == '\"' && last == '\"') || (first == '\'' && last == '\'')) {
- *nOffset = 1;
- *nLength -= 2;
+ value = value.Substr(1, value.GetLength() - 2);
}
}
- return nValueLen > 0;
+ if (value.IsEmpty()) {
+ return std::nullopt;
+ }
+ return value;
}
// static.
-bool CFX_CSSDeclaration::ParseCSSColor(const wchar_t* pszValue,
- size_t nValueLen,
- FX_ARGB* dwColor) {
- DCHECK_NE(nValueLen, 0);
- DCHECK(dwColor);
-
- if (*pszValue == '#') {
- switch (nValueLen) {
+std::optional<FX_ARGB> CFX_CSSDeclaration::ParseCSSColor(WideStringView value) {
+ if (value.Front() == '#') { // Note: empty-tolerant Front().
+ switch (value.GetLength()) {
case 4: {
- uint8_t red = Hex2Dec((uint8_t)pszValue[1], (uint8_t)pszValue[1]);
- uint8_t green = Hex2Dec((uint8_t)pszValue[2], (uint8_t)pszValue[2]);
- uint8_t blue = Hex2Dec((uint8_t)pszValue[3], (uint8_t)pszValue[3]);
- *dwColor = ArgbEncode(255, red, green, blue);
- return true;
+ uint8_t red = Hex2Dec((uint8_t)value[1], (uint8_t)value[1]);
+ uint8_t green = Hex2Dec((uint8_t)value[2], (uint8_t)value[2]);
+ uint8_t blue = Hex2Dec((uint8_t)value[3], (uint8_t)value[3]);
+ return ArgbEncode(255, red, green, blue);
}
case 7: {
- uint8_t red = Hex2Dec((uint8_t)pszValue[1], (uint8_t)pszValue[2]);
- uint8_t green = Hex2Dec((uint8_t)pszValue[3], (uint8_t)pszValue[4]);
- uint8_t blue = Hex2Dec((uint8_t)pszValue[5], (uint8_t)pszValue[6]);
- *dwColor = ArgbEncode(255, red, green, blue);
- return true;
+ uint8_t red = Hex2Dec((uint8_t)value[1], (uint8_t)value[2]);
+ uint8_t green = Hex2Dec((uint8_t)value[3], (uint8_t)value[4]);
+ uint8_t blue = Hex2Dec((uint8_t)value[5], (uint8_t)value[6]);
+ return ArgbEncode(255, red, green, blue);
}
default:
- return false;
+ return std::nullopt;
}
}
- if (nValueLen >= 10) {
- if (pszValue[nValueLen - 1] != ')' || FXSYS_wcsnicmp(L"rgb(", pszValue, 4))
- return false;
-
+ if (value.GetLength() >= 10) {
+ if (!value.First(4).EqualsASCIINoCase("rgb(") || value.Back() != ')') {
+ return std::nullopt;
+ }
uint8_t rgb[3] = {0};
- float fValue;
- CFX_CSSValue::PrimitiveType eType;
- CFX_CSSValueListParser list(pszValue + 4, nValueLen - 5, ',');
+ CFX_CSSValueListParser list(value.Substr(4, value.GetLength() - 5), ',');
for (int32_t i = 0; i < 3; ++i) {
- if (!list.NextValue(&eType, &pszValue, &nValueLen))
- return false;
- if (eType != CFX_CSSValue::PrimitiveType::kNumber)
- return false;
- CFX_CSSNumberValue::Unit eNumType;
- if (!ParseCSSNumber(pszValue, nValueLen, &fValue, &eNumType))
- return false;
-
- rgb[i] = eNumType == CFX_CSSNumberValue::Unit::kPercent
- ? FXSYS_roundf(fValue * 2.55f)
- : FXSYS_roundf(fValue);
+ auto maybe_value = list.NextValue();
+ if (!maybe_value.has_value() ||
+ maybe_value.value().type != CFX_CSSValue::PrimitiveType::kNumber) {
+ return std::nullopt;
+ }
+ auto maybe_number = ParseCSSNumber(maybe_value.value().string_view);
+ if (!maybe_number.has_value()) {
+ return std::nullopt;
+ }
+ rgb[i] = maybe_number.value().unit == CFX_CSSNumber::Unit::kPercent
+ ? FXSYS_roundf(maybe_number.value().value * 2.55f)
+ : FXSYS_roundf(maybe_number.value().value);
}
- *dwColor = ArgbEncode(255, rgb[0], rgb[1], rgb[2]);
- return true;
+ return ArgbEncode(255, rgb[0], rgb[1], rgb[2]);
}
- const CFX_CSSData::Color* pColor =
- CFX_CSSData::GetColorByName(WideStringView(pszValue, nValueLen));
- if (!pColor)
- return false;
-
- *dwColor = pColor->value;
- return true;
+ const CFX_CSSData::Color* pColor = CFX_CSSData::GetColorByName(value);
+ if (!pColor) {
+ return std::nullopt;
+ }
+ return pColor->value;
}
CFX_CSSDeclaration::CFX_CSSDeclaration() = default;
@@ -163,7 +144,7 @@
auto pHolder = std::make_unique<CFX_CSSPropertyHolder>();
pHolder->bImportant = bImportant;
pHolder->eProperty = eProperty;
- pHolder->pValue = pValue;
+ pHolder->pValue = std::move(pValue);
properties_.push_back(std::move(pHolder));
}
@@ -171,15 +152,13 @@
WideStringView value) {
DCHECK(!value.IsEmpty());
- const wchar_t* pszValue = value.unterminated_c_str();
- size_t nValueLen = value.GetLength();
bool bImportant = false;
- if (nValueLen >= 10 && pszValue[nValueLen - 10] == '!' &&
- FXSYS_wcsnicmp(L"important", pszValue + nValueLen - 9, 9) == 0) {
- nValueLen -= 10;
- if (nValueLen == 0)
+ WideStringView last_ten = value.Last(10); // NOTE: empty-tolerant Last().
+ if (last_ten.EqualsASCIINoCase("!important")) {
+ value = value.First(value.GetLength() - 10);
+ if (value.IsEmpty()) {
return;
-
+ }
bImportant = true;
}
const CFX_CSSValueTypeMask dwType = property->dwTypes;
@@ -193,22 +172,22 @@
};
for (CFX_CSSVALUETYPE guess : kValueGuessOrder) {
const CFX_CSSValueTypeMask dwMatch = dwType & guess;
- if (dwMatch == 0)
+ if (dwMatch == 0) {
continue;
-
+ }
RetainPtr<CFX_CSSValue> pCSSValue;
switch (dwMatch) {
case CFX_CSSVALUETYPE_MaybeNumber:
- pCSSValue = ParseNumber(pszValue, nValueLen);
+ pCSSValue = ParseNumber(value);
break;
case CFX_CSSVALUETYPE_MaybeEnum:
- pCSSValue = ParseEnum(pszValue, nValueLen);
+ pCSSValue = ParseEnum(value);
break;
case CFX_CSSVALUETYPE_MaybeColor:
- pCSSValue = ParseColor(pszValue, nValueLen);
+ pCSSValue = ParseColor(value);
break;
case CFX_CSSVALUETYPE_MaybeString:
- pCSSValue = ParseString(pszValue, nValueLen);
+ pCSSValue = ParseString(value);
break;
default:
break;
@@ -217,65 +196,57 @@
AddPropertyHolder(property->eName, pCSSValue, bImportant);
return;
}
-
- if ((dwType & ~guess) == CFX_CSSVALUETYPE_Primitive)
+ if ((dwType & ~guess) == CFX_CSSVALUETYPE_Primitive) {
return;
+ }
}
break;
}
case CFX_CSSVALUETYPE_Shorthand: {
- RetainPtr<CFX_CSSValue> pWidth;
switch (property->eName) {
- case CFX_CSSProperty::Font:
- ParseFontProperty(pszValue, nValueLen, bImportant);
+ case CFX_CSSProperty::Font: {
+ ParseFontProperty(value, bImportant);
return;
- case CFX_CSSProperty::Border:
- if (ParseBorderProperty(pszValue, nValueLen, pWidth)) {
- AddPropertyHolder(CFX_CSSProperty::BorderLeftWidth, pWidth,
- bImportant);
- AddPropertyHolder(CFX_CSSProperty::BorderTopWidth, pWidth,
- bImportant);
- AddPropertyHolder(CFX_CSSProperty::BorderRightWidth, pWidth,
- bImportant);
- AddPropertyHolder(CFX_CSSProperty::BorderBottomWidth, pWidth,
- bImportant);
- return;
- }
+ }
+ case CFX_CSSProperty::Border: {
+ RetainPtr<CFX_CSSValue> pWidth = ParseBorderProperty(value);
+ AddPropertyHolder(CFX_CSSProperty::BorderLeftWidth, pWidth,
+ bImportant);
+ AddPropertyHolder(CFX_CSSProperty::BorderTopWidth, pWidth,
+ bImportant);
+ AddPropertyHolder(CFX_CSSProperty::BorderRightWidth, pWidth,
+ bImportant);
+ AddPropertyHolder(CFX_CSSProperty::BorderBottomWidth, pWidth,
+ bImportant);
+ return;
+ }
+ case CFX_CSSProperty::BorderLeft: {
+ AddPropertyHolder(CFX_CSSProperty::BorderLeftWidth,
+ ParseBorderProperty(value), bImportant);
break;
- case CFX_CSSProperty::BorderLeft:
- if (ParseBorderProperty(pszValue, nValueLen, pWidth)) {
- AddPropertyHolder(CFX_CSSProperty::BorderLeftWidth, pWidth,
- bImportant);
- return;
- }
- break;
- case CFX_CSSProperty::BorderTop:
- if (ParseBorderProperty(pszValue, nValueLen, pWidth)) {
- AddPropertyHolder(CFX_CSSProperty::BorderTopWidth, pWidth,
- bImportant);
- return;
- }
- break;
- case CFX_CSSProperty::BorderRight:
- if (ParseBorderProperty(pszValue, nValueLen, pWidth)) {
- AddPropertyHolder(CFX_CSSProperty::BorderRightWidth, pWidth,
- bImportant);
- return;
- }
- break;
- case CFX_CSSProperty::BorderBottom:
- if (ParseBorderProperty(pszValue, nValueLen, pWidth)) {
- AddPropertyHolder(CFX_CSSProperty::BorderBottomWidth, pWidth,
- bImportant);
- return;
- }
- break;
+ }
+ case CFX_CSSProperty::BorderTop: {
+ AddPropertyHolder(CFX_CSSProperty::BorderTopWidth,
+ ParseBorderProperty(value), bImportant);
+ return;
+ }
+ case CFX_CSSProperty::BorderRight: {
+ AddPropertyHolder(CFX_CSSProperty::BorderRightWidth,
+ ParseBorderProperty(value), bImportant);
+ return;
+ }
+ case CFX_CSSProperty::BorderBottom: {
+ AddPropertyHolder(CFX_CSSProperty::BorderBottomWidth,
+ ParseBorderProperty(value), bImportant);
+ return;
+ }
default:
break;
}
- } break;
+ break;
+ }
case CFX_CSSVALUETYPE_List:
- ParseValueListProperty(property, pszValue, nValueLen, bImportant);
+ ParseValueListProperty(property, value, bImportant);
return;
default:
NOTREACHED_NORETURN();
@@ -288,103 +259,98 @@
std::make_unique<CFX_CSSCustomProperty>(prop, value));
}
-RetainPtr<CFX_CSSValue> CFX_CSSDeclaration::ParseNumber(const wchar_t* pszValue,
- size_t nValueLen) {
- float fValue;
- CFX_CSSNumberValue::Unit eUnit;
- if (!ParseCSSNumber(pszValue, nValueLen, &fValue, &eUnit))
+RetainPtr<CFX_CSSValue> CFX_CSSDeclaration::ParseNumber(WideStringView view) {
+ std::optional<CFX_CSSNumber> maybe_number = ParseCSSNumber(view);
+ if (!maybe_number.has_value()) {
return nullptr;
- return pdfium::MakeRetain<CFX_CSSNumberValue>(eUnit, fValue);
+ }
+ return pdfium::MakeRetain<CFX_CSSNumberValue>(maybe_number.value());
}
-RetainPtr<CFX_CSSValue> CFX_CSSDeclaration::ParseEnum(const wchar_t* pszValue,
- size_t nValueLen) {
+RetainPtr<CFX_CSSValue> CFX_CSSDeclaration::ParseEnum(WideStringView value) {
const CFX_CSSData::PropertyValue* pValue =
- CFX_CSSData::GetPropertyValueByName(WideStringView(pszValue, nValueLen));
+ CFX_CSSData::GetPropertyValueByName(value);
return pValue ? pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName) : nullptr;
}
-RetainPtr<CFX_CSSValue> CFX_CSSDeclaration::ParseColor(const wchar_t* pszValue,
- size_t nValueLen) {
- FX_ARGB dwColor;
- if (!ParseCSSColor(pszValue, nValueLen, &dwColor))
+RetainPtr<CFX_CSSValue> CFX_CSSDeclaration::ParseColor(WideStringView value) {
+ auto maybe_color = ParseCSSColor(value);
+ if (!maybe_color.has_value()) {
return nullptr;
- return pdfium::MakeRetain<CFX_CSSColorValue>(dwColor);
+ }
+ return pdfium::MakeRetain<CFX_CSSColorValue>(maybe_color.value());
}
-RetainPtr<CFX_CSSValue> CFX_CSSDeclaration::ParseString(const wchar_t* pszValue,
- size_t nValueLen) {
- size_t iOffset;
- if (!ParseCSSString(pszValue, nValueLen, &iOffset, &nValueLen))
+RetainPtr<CFX_CSSValue> CFX_CSSDeclaration::ParseString(WideStringView value) {
+ auto maybe_string = ParseCSSString(value);
+ if (!maybe_string.has_value() || maybe_string.value().IsEmpty()) {
return nullptr;
-
- if (nValueLen == 0)
- return nullptr;
-
- return pdfium::MakeRetain<CFX_CSSStringValue>(
- WideString(pszValue + iOffset, nValueLen));
+ }
+ return pdfium::MakeRetain<CFX_CSSStringValue>(maybe_string.value());
}
void CFX_CSSDeclaration::ParseValueListProperty(
const CFX_CSSData::Property* pProperty,
- const wchar_t* pszValue,
- size_t nValueLen,
+ WideStringView value,
bool bImportant) {
wchar_t separator =
(pProperty->eName == CFX_CSSProperty::FontFamily) ? ',' : ' ';
- CFX_CSSValueListParser parser(pszValue, nValueLen, separator);
-
+ CFX_CSSValueListParser parser(value, separator);
const CFX_CSSValueTypeMask dwType = pProperty->dwTypes;
- CFX_CSSValue::PrimitiveType eType;
std::vector<RetainPtr<CFX_CSSValue>> list;
- while (parser.NextValue(&eType, &pszValue, &nValueLen)) {
- switch (eType) {
+ while (1) {
+ auto maybe_next = parser.NextValue();
+ if (!maybe_next.has_value()) {
+ break;
+ }
+ switch (maybe_next.value().type) {
case CFX_CSSValue::PrimitiveType::kNumber:
if (dwType & CFX_CSSVALUETYPE_MaybeNumber) {
- float fValue;
- CFX_CSSNumberValue::Unit eNumType;
- if (ParseCSSNumber(pszValue, nValueLen, &fValue, &eNumType))
+ auto maybe_number = ParseCSSNumber(maybe_next.value().string_view);
+ if (maybe_number.has_value()) {
list.push_back(
- pdfium::MakeRetain<CFX_CSSNumberValue>(eNumType, fValue));
+ pdfium::MakeRetain<CFX_CSSNumberValue>(maybe_number.value()));
+ }
}
break;
case CFX_CSSValue::PrimitiveType::kString:
if (dwType & CFX_CSSVALUETYPE_MaybeColor) {
- FX_ARGB dwColor;
- if (ParseCSSColor(pszValue, nValueLen, &dwColor)) {
- list.push_back(pdfium::MakeRetain<CFX_CSSColorValue>(dwColor));
+ auto maybe_color = ParseCSSColor(maybe_next.value().string_view);
+ if (maybe_color.has_value()) {
+ list.push_back(
+ pdfium::MakeRetain<CFX_CSSColorValue>(maybe_color.value()));
continue;
}
}
if (dwType & CFX_CSSVALUETYPE_MaybeEnum) {
- const CFX_CSSData::PropertyValue* pValue =
+ const CFX_CSSData::PropertyValue* pPropValue =
CFX_CSSData::GetPropertyValueByName(
- WideStringView(pszValue, nValueLen));
- if (pValue) {
- list.push_back(pdfium::MakeRetain<CFX_CSSEnumValue>(pValue->eName));
+ maybe_next.value().string_view);
+ if (pPropValue) {
+ list.push_back(
+ pdfium::MakeRetain<CFX_CSSEnumValue>(pPropValue->eName));
continue;
}
}
if (dwType & CFX_CSSVALUETYPE_MaybeString) {
list.push_back(pdfium::MakeRetain<CFX_CSSStringValue>(
- WideString(pszValue, nValueLen)));
+ maybe_next.value().string_view));
}
break;
case CFX_CSSValue::PrimitiveType::kRGB:
if (dwType & CFX_CSSVALUETYPE_MaybeColor) {
- FX_ARGB dwColor;
- if (ParseCSSColor(pszValue, nValueLen, &dwColor)) {
- list.push_back(pdfium::MakeRetain<CFX_CSSColorValue>(dwColor));
- }
+ FX_ARGB color =
+ ParseCSSColor(maybe_next.value().string_view).value_or(0);
+ list.push_back(pdfium::MakeRetain<CFX_CSSColorValue>(color));
}
break;
default:
break;
}
}
- if (list.empty())
+ if (list.empty()) {
return;
-
+ }
switch (pProperty->eName) {
case CFX_CSSProperty::BorderWidth:
Add4ValuesProperty(list, bImportant, CFX_CSSProperty::BorderLeftWidth,
@@ -406,7 +372,7 @@
return;
default: {
auto value_list = pdfium::MakeRetain<CFX_CSSValueList>(std::move(list));
- AddPropertyHolder(pProperty->eName, value_list, bImportant);
+ AddPropertyHolder(pProperty->eName, std::move(value_list), bImportant);
return;
}
}
@@ -449,38 +415,37 @@
}
}
-bool CFX_CSSDeclaration::ParseBorderProperty(
- const wchar_t* pszValue,
- size_t nValueLen,
- RetainPtr<CFX_CSSValue>& pWidth) const {
- pWidth.Reset(nullptr);
-
- CFX_CSSValue::PrimitiveType eType;
- CFX_CSSValueListParser parser(pszValue, nValueLen, ' ');
- while (parser.NextValue(&eType, &pszValue, &nValueLen)) {
- switch (eType) {
+RetainPtr<CFX_CSSValue> CFX_CSSDeclaration::ParseBorderProperty(
+ WideStringView value) const {
+ RetainPtr<CFX_CSSValue> pWidth;
+ CFX_CSSValueListParser parser(value, ' ');
+ while (1) {
+ auto maybe_next = parser.NextValue();
+ if (!maybe_next.has_value()) {
+ break;
+ }
+ switch (maybe_next.value().type) {
case CFX_CSSValue::PrimitiveType::kNumber: {
- if (pWidth)
+ if (pWidth) {
continue;
-
- float fValue;
- CFX_CSSNumberValue::Unit eNumType;
- if (ParseCSSNumber(pszValue, nValueLen, &fValue, &eNumType))
- pWidth = pdfium::MakeRetain<CFX_CSSNumberValue>(eNumType, fValue);
+ }
+ auto maybe_number = ParseCSSNumber(maybe_next.value().string_view);
+ if (maybe_number.has_value()) {
+ pWidth = pdfium::MakeRetain<CFX_CSSNumberValue>(maybe_number.value());
+ }
break;
}
case CFX_CSSValue::PrimitiveType::kString: {
const CFX_CSSData::Color* pColorItem =
- CFX_CSSData::GetColorByName(WideStringView(pszValue, nValueLen));
- if (pColorItem)
+ CFX_CSSData::GetColorByName(maybe_next.value().string_view);
+ if (pColorItem) {
continue;
-
+ }
const CFX_CSSData::PropertyValue* pValue =
- CFX_CSSData::GetPropertyValueByName(
- WideStringView(pszValue, nValueLen));
- if (!pValue)
+ CFX_CSSData::GetPropertyValueByName(maybe_next.value().string_view);
+ if (!pValue) {
continue;
-
+ }
switch (pValue->eName) {
case CFX_CSSPropertyValue::Thin:
case CFX_CSSPropertyValue::Thick:
@@ -497,30 +462,31 @@
break;
}
}
- if (!pWidth) {
- pWidth = pdfium::MakeRetain<CFX_CSSNumberValue>(
- CFX_CSSNumberValue::Unit::kNumber, 0.0f);
+ if (pWidth) {
+ return pWidth;
}
- return true;
+ return pdfium::MakeRetain<CFX_CSSNumberValue>(
+ CFX_CSSNumber{CFX_CSSNumber::Unit::kNumber, 0.0f});
}
-void CFX_CSSDeclaration::ParseFontProperty(const wchar_t* pszValue,
- size_t nValueLen,
+void CFX_CSSDeclaration::ParseFontProperty(WideStringView value,
bool bImportant) {
- CFX_CSSValueListParser parser(pszValue, nValueLen, '/');
RetainPtr<CFX_CSSValue> pStyle;
RetainPtr<CFX_CSSValue> pVariant;
RetainPtr<CFX_CSSValue> pWeight;
RetainPtr<CFX_CSSValue> pFontSize;
RetainPtr<CFX_CSSValue> pLineHeight;
std::vector<RetainPtr<CFX_CSSValue>> family_list;
- CFX_CSSValue::PrimitiveType eType;
- while (parser.NextValue(&eType, &pszValue, &nValueLen)) {
- switch (eType) {
+ CFX_CSSValueListParser parser(value, '/');
+ while (1) {
+ auto maybe_next = parser.NextValue();
+ if (!maybe_next.has_value()) {
+ break;
+ }
+ switch (maybe_next.value().type) {
case CFX_CSSValue::PrimitiveType::kString: {
const CFX_CSSData::PropertyValue* pValue =
- CFX_CSSData::GetPropertyValueByName(
- WideStringView(pszValue, nValueLen));
+ CFX_CSSData::GetPropertyValueByName(maybe_next.value().string_view);
if (pValue) {
switch (pValue->eName) {
case CFX_CSSPropertyValue::XxSmall:
@@ -569,18 +535,18 @@
}
if (pFontSize) {
family_list.push_back(pdfium::MakeRetain<CFX_CSSStringValue>(
- WideString(pszValue, nValueLen)));
+ maybe_next.value().string_view));
}
parser.UseCommaSeparator();
break;
}
case CFX_CSSValue::PrimitiveType::kNumber: {
- float fValue;
- CFX_CSSNumberValue::Unit eNumType;
- if (!ParseCSSNumber(pszValue, nValueLen, &fValue, &eNumType))
+ auto maybe_number = ParseCSSNumber(maybe_next.value().string_view);
+ if (!maybe_number.has_value()) {
break;
- if (eType == CFX_CSSValue::PrimitiveType::kNumber) {
- switch (static_cast<int32_t>(fValue)) {
+ }
+ if (maybe_number.value().unit == CFX_CSSNumber::Unit::kNumber) {
+ switch (static_cast<int32_t>(maybe_number.value().value)) {
case 100:
case 200:
case 300:
@@ -592,16 +558,18 @@
case 900:
if (!pWeight) {
pWeight = pdfium::MakeRetain<CFX_CSSNumberValue>(
- CFX_CSSNumberValue::Unit::kNumber, fValue);
+ maybe_number.value());
}
continue;
}
}
- if (!pFontSize)
- pFontSize = pdfium::MakeRetain<CFX_CSSNumberValue>(eNumType, fValue);
- else if (!pLineHeight)
+ if (!pFontSize) {
+ pFontSize =
+ pdfium::MakeRetain<CFX_CSSNumberValue>(maybe_number.value());
+ } else if (!pLineHeight) {
pLineHeight =
- pdfium::MakeRetain<CFX_CSSNumberValue>(eNumType, fValue);
+ pdfium::MakeRetain<CFX_CSSNumberValue>(maybe_number.value());
+ }
break;
}
default:
diff --git a/core/fxcrt/css/cfx_cssdeclaration.h b/core/fxcrt/css/cfx_cssdeclaration.h
index eef58e0..21bce28 100644
--- a/core/fxcrt/css/cfx_cssdeclaration.h
+++ b/core/fxcrt/css/cfx_cssdeclaration.h
@@ -8,10 +8,12 @@
#define CORE_FXCRT_CSS_CFX_CSSDECLARATION_H_
#include <memory>
+#include <optional>
#include <vector>
#include "core/fxcrt/css/cfx_cssdata.h"
#include "core/fxcrt/retain_ptr.h"
+#include "core/fxcrt/widestring.h"
class CFX_CSSPropertyHolder;
class CFX_CSSCustomProperty;
@@ -23,13 +25,8 @@
using const_custom_iterator =
std::vector<std::unique_ptr<CFX_CSSCustomProperty>>::const_iterator;
- static bool ParseCSSString(const wchar_t* pszValue,
- size_t nValueLen,
- size_t* nOffset,
- size_t* nLength);
- static bool ParseCSSColor(const wchar_t* pszValue,
- size_t nValueLen,
- FX_ARGB* dwColor);
+ static std::optional<WideStringView> ParseCSSString(WideStringView value);
+ static std::optional<FX_ARGB> ParseCSSColor(WideStringView value);
CFX_CSSDeclaration();
~CFX_CSSDeclaration();
@@ -37,6 +34,7 @@
RetainPtr<CFX_CSSValue> GetProperty(CFX_CSSProperty eProperty,
bool* bImportant) const;
+ bool empty() const { return properties_.empty(); }
const_prop_iterator begin() const { return properties_.begin(); }
const_prop_iterator end() const { return properties_.end(); }
@@ -45,27 +43,21 @@
}
const_custom_iterator custom_end() const { return custom_properties_.end(); }
- bool empty() const { return properties_.empty(); }
-
void AddProperty(const CFX_CSSData::Property* property, WideStringView value);
void AddProperty(const WideString& prop, const WideString& value);
-
size_t PropertyCountForTesting() const;
- FX_ARGB ParseColorForTest(const wchar_t* pszValue,
- size_t nValueLen,
- FX_ARGB* dwColor) const;
+ std::optional<FX_ARGB> ParseColorForTest(WideStringView value);
private:
- void ParseFontProperty(const wchar_t* pszValue,
- size_t nValueLen,
- bool bImportant);
- bool ParseBorderProperty(const wchar_t* pszValue,
- size_t nValueLen,
- RetainPtr<CFX_CSSValue>& pWidth) const;
+ void ParseFontProperty(WideStringView value, bool bImportant);
+
+ // Never returns nullptr, instead returns a CSSValue representing zero
+ // if the input cannot be parsed.
+ RetainPtr<CFX_CSSValue> ParseBorderProperty(WideStringView value) const;
+
void ParseValueListProperty(const CFX_CSSData::Property* pProperty,
- const wchar_t* pszValue,
- size_t nValueLen,
+ WideStringView value,
bool bImportant);
void Add4ValuesProperty(const std::vector<RetainPtr<CFX_CSSValue>>& list,
bool bImportant,
@@ -73,12 +65,10 @@
CFX_CSSProperty eTop,
CFX_CSSProperty eRight,
CFX_CSSProperty eBottom);
- RetainPtr<CFX_CSSValue> ParseNumber(const wchar_t* pszValue,
- size_t nValueLen);
- RetainPtr<CFX_CSSValue> ParseEnum(const wchar_t* pszValue, size_t nValueLen);
- RetainPtr<CFX_CSSValue> ParseColor(const wchar_t* pszValue, size_t nValueLen);
- RetainPtr<CFX_CSSValue> ParseString(const wchar_t* pszValue,
- size_t nValueLen);
+ RetainPtr<CFX_CSSValue> ParseNumber(WideStringView value);
+ RetainPtr<CFX_CSSValue> ParseEnum(WideStringView value);
+ RetainPtr<CFX_CSSValue> ParseColor(WideStringView value);
+ RetainPtr<CFX_CSSValue> ParseString(WideStringView value);
void AddPropertyHolder(CFX_CSSProperty eProperty,
RetainPtr<CFX_CSSValue> pValue,
bool bImportant);
diff --git a/core/fxcrt/css/cfx_cssdeclaration_unittest.cpp b/core/fxcrt/css/cfx_cssdeclaration_unittest.cpp
index 5868063..aa4fd54 100644
--- a/core/fxcrt/css/cfx_cssdeclaration_unittest.cpp
+++ b/core/fxcrt/css/cfx_cssdeclaration_unittest.cpp
@@ -4,58 +4,66 @@
#include "core/fxcrt/css/cfx_cssdeclaration.h"
+#include <optional>
+
#include "testing/gtest/include/gtest/gtest.h"
TEST(CFX_CSSDeclarationTest, HexEncodingParsing) {
- FX_ARGB color;
+ std::optional<FX_ARGB> maybe_color;
// Length value invalid.
- EXPECT_FALSE(CFX_CSSDeclaration::ParseCSSColor(L"#000", 3, &color));
- EXPECT_FALSE(CFX_CSSDeclaration::ParseCSSColor(L"#000000", 5, &color));
- EXPECT_FALSE(CFX_CSSDeclaration::ParseCSSColor(L"#000000", 8, &color));
+ EXPECT_FALSE(CFX_CSSDeclaration::ParseCSSColor(L"#00"));
+ EXPECT_FALSE(CFX_CSSDeclaration::ParseCSSColor(L"#0000"));
+ EXPECT_FALSE(CFX_CSSDeclaration::ParseCSSColor(L"#0000000"));
// Invalid characters
- EXPECT_TRUE(CFX_CSSDeclaration::ParseCSSColor(L"#zxytlm", 7, &color));
- EXPECT_EQ(0, FXARGB_R(color));
- EXPECT_EQ(0, FXARGB_G(color));
- EXPECT_EQ(0, FXARGB_B(color));
+ maybe_color = CFX_CSSDeclaration::ParseCSSColor(L"#zxytlm");
+ ASSERT_TRUE(maybe_color.has_value());
+ EXPECT_EQ(0, FXARGB_R(maybe_color.value()));
+ EXPECT_EQ(0, FXARGB_G(maybe_color.value()));
+ EXPECT_EQ(0, FXARGB_B(maybe_color.value()));
- EXPECT_TRUE(CFX_CSSDeclaration::ParseCSSColor(L"#000", 4, &color));
- EXPECT_EQ(0, FXARGB_R(color));
- EXPECT_EQ(0, FXARGB_G(color));
- EXPECT_EQ(0, FXARGB_B(color));
+ maybe_color = CFX_CSSDeclaration::ParseCSSColor(L"#000");
+ ASSERT_TRUE(maybe_color.has_value());
+ EXPECT_EQ(0, FXARGB_R(maybe_color.value()));
+ EXPECT_EQ(0, FXARGB_G(maybe_color.value()));
+ EXPECT_EQ(0, FXARGB_B(maybe_color.value()));
- EXPECT_TRUE(CFX_CSSDeclaration::ParseCSSColor(L"#FFF", 4, &color));
- EXPECT_EQ(255, FXARGB_R(color));
- EXPECT_EQ(255, FXARGB_G(color));
- EXPECT_EQ(255, FXARGB_B(color));
+ maybe_color = CFX_CSSDeclaration::ParseCSSColor(L"#FFF");
+ ASSERT_TRUE(maybe_color.has_value());
+ EXPECT_EQ(255, FXARGB_R(maybe_color.value()));
+ EXPECT_EQ(255, FXARGB_G(maybe_color.value()));
+ EXPECT_EQ(255, FXARGB_B(maybe_color.value()));
- EXPECT_TRUE(CFX_CSSDeclaration::ParseCSSColor(L"#F0F0F0", 7, &color));
- EXPECT_EQ(240, FXARGB_R(color));
- EXPECT_EQ(240, FXARGB_G(color));
- EXPECT_EQ(240, FXARGB_B(color));
+ maybe_color = CFX_CSSDeclaration::ParseCSSColor(L"#F0F0F0");
+ ASSERT_TRUE(maybe_color.has_value());
+ EXPECT_EQ(240, FXARGB_R(maybe_color.value()));
+ EXPECT_EQ(240, FXARGB_G(maybe_color.value()));
+ EXPECT_EQ(240, FXARGB_B(maybe_color.value()));
// Upper and lower case characters.
- EXPECT_TRUE(CFX_CSSDeclaration::ParseCSSColor(L"#1b2F3c", 7, &color));
- EXPECT_EQ(27, FXARGB_R(color));
- EXPECT_EQ(47, FXARGB_G(color));
- EXPECT_EQ(60, FXARGB_B(color));
+ maybe_color = CFX_CSSDeclaration::ParseCSSColor(L"#1b2F3c");
+ ASSERT_TRUE(maybe_color.has_value());
+ EXPECT_EQ(27, FXARGB_R(maybe_color.value()));
+ EXPECT_EQ(47, FXARGB_G(maybe_color.value()));
+ EXPECT_EQ(60, FXARGB_B(maybe_color.value()));
}
TEST(CFX_CSSDeclarationTest, RGBEncodingParsing) {
- FX_ARGB color;
+ std::optional<FX_ARGB> maybe_color;
// Invalid input for rgb() syntax.
- EXPECT_FALSE(CFX_CSSDeclaration::ParseCSSColor(L"blahblahblah", 11, &color));
+ EXPECT_FALSE(CFX_CSSDeclaration::ParseCSSColor(L"blahblahblah"));
- EXPECT_TRUE(CFX_CSSDeclaration::ParseCSSColor(L"rgb(0, 0, 0)", 12, &color));
- EXPECT_EQ(0, FXARGB_R(color));
- EXPECT_EQ(0, FXARGB_G(color));
- EXPECT_EQ(0, FXARGB_B(color));
+ maybe_color = CFX_CSSDeclaration::ParseCSSColor(L"rgb(0, 0, 0)");
+ ASSERT_TRUE(maybe_color.has_value());
+ EXPECT_EQ(0, FXARGB_R(maybe_color.value()));
+ EXPECT_EQ(0, FXARGB_G(maybe_color.value()));
+ EXPECT_EQ(0, FXARGB_B(maybe_color.value()));
- EXPECT_TRUE(
- CFX_CSSDeclaration::ParseCSSColor(L"rgb(128,255,48)", 15, &color));
- EXPECT_EQ(128, FXARGB_R(color));
- EXPECT_EQ(255, FXARGB_G(color));
- EXPECT_EQ(48, FXARGB_B(color));
+ maybe_color = CFX_CSSDeclaration::ParseCSSColor(L"rgb(128,255,48)");
+ ASSERT_TRUE(maybe_color.has_value());
+ EXPECT_EQ(128, FXARGB_R(maybe_color.value()));
+ EXPECT_EQ(255, FXARGB_G(maybe_color.value()));
+ EXPECT_EQ(48, FXARGB_B(maybe_color.value()));
}
diff --git a/core/fxcrt/css/cfx_cssnumbervalue.cpp b/core/fxcrt/css/cfx_cssnumbervalue.cpp
index 72ae775..665257f 100644
--- a/core/fxcrt/css/cfx_cssnumbervalue.cpp
+++ b/core/fxcrt/css/cfx_cssnumbervalue.cpp
@@ -8,34 +8,35 @@
#include <math.h>
-CFX_CSSNumberValue::CFX_CSSNumberValue(Unit unit, float value)
- : CFX_CSSValue(PrimitiveType::kNumber), unit_(unit), value_(value) {
- if (unit_ == Unit::kNumber && fabs(value_) < 0.001f)
- value_ = 0.0f;
+CFX_CSSNumberValue::CFX_CSSNumberValue(CFX_CSSNumber number)
+ : CFX_CSSValue(PrimitiveType::kNumber), number_(number) {
+ if (number_.unit == CFX_CSSNumber::Unit::kNumber &&
+ fabs(number_.value) < 0.001f) {
+ number_.value = 0.0f;
+ }
}
CFX_CSSNumberValue::~CFX_CSSNumberValue() = default;
float CFX_CSSNumberValue::Apply(float percentBase) const {
- switch (unit_) {
- case Unit::kPixels:
- case Unit::kNumber:
- return value_ * 72 / 96;
- case Unit::kEMS:
- case Unit::kEXS:
- return value_ * percentBase;
- case Unit::kPercent:
- return value_ * percentBase / 100.0f;
- case Unit::kCentiMeters:
- return value_ * 28.3464f;
- case Unit::kMilliMeters:
- return value_ * 2.8346f;
- case Unit::kInches:
- return value_ * 72.0f;
- case Unit::kPicas:
- return value_ / 12.0f;
- case Unit::kPoints:
- return value_;
+ switch (number_.unit) {
+ case CFX_CSSNumber::Unit::kPixels:
+ case CFX_CSSNumber::Unit::kNumber:
+ return number_.value * 72 / 96;
+ case CFX_CSSNumber::Unit::kEMS:
+ case CFX_CSSNumber::Unit::kEXS:
+ return number_.value * percentBase;
+ case CFX_CSSNumber::Unit::kPercent:
+ return number_.value * percentBase / 100.0f;
+ case CFX_CSSNumber::Unit::kCentiMeters:
+ return number_.value * 28.3464f;
+ case CFX_CSSNumber::Unit::kMilliMeters:
+ return number_.value * 2.8346f;
+ case CFX_CSSNumber::Unit::kInches:
+ return number_.value * 72.0f;
+ case CFX_CSSNumber::Unit::kPicas:
+ return number_.value / 12.0f;
+ case CFX_CSSNumber::Unit::kPoints:
+ return number_.value;
}
- return value_;
}
diff --git a/core/fxcrt/css/cfx_cssnumbervalue.h b/core/fxcrt/css/cfx_cssnumbervalue.h
index 3b2556b..a1a4861 100644
--- a/core/fxcrt/css/cfx_cssnumbervalue.h
+++ b/core/fxcrt/css/cfx_cssnumbervalue.h
@@ -9,8 +9,7 @@
#include "core/fxcrt/css/cfx_cssvalue.h"
-class CFX_CSSNumberValue final : public CFX_CSSValue {
- public:
+struct CFX_CSSNumber {
enum class Unit {
kNumber,
kPercent,
@@ -24,16 +23,21 @@
kPicas,
};
- CFX_CSSNumberValue(Unit unit, float value);
+ Unit unit;
+ float value;
+};
+
+class CFX_CSSNumberValue final : public CFX_CSSValue {
+ public:
+ explicit CFX_CSSNumberValue(CFX_CSSNumber number);
~CFX_CSSNumberValue() override;
- Unit unit() const { return unit_; }
- float value() const { return value_; }
+ CFX_CSSNumber::Unit unit() const { return number_.unit; }
+ float value() const { return number_.value; }
float Apply(float percentBase) const;
private:
- Unit unit_;
- float value_;
+ CFX_CSSNumber number_;
};
#endif // CORE_FXCRT_CSS_CFX_CSSNUMBERVALUE_H_
diff --git a/core/fxcrt/css/cfx_cssstringvalue.cpp b/core/fxcrt/css/cfx_cssstringvalue.cpp
index 7fbb6b0..ce60f80 100644
--- a/core/fxcrt/css/cfx_cssstringvalue.cpp
+++ b/core/fxcrt/css/cfx_cssstringvalue.cpp
@@ -6,7 +6,7 @@
#include "core/fxcrt/css/cfx_cssstringvalue.h"
-CFX_CSSStringValue::CFX_CSSStringValue(const WideString& value)
+CFX_CSSStringValue::CFX_CSSStringValue(WideStringView value)
: CFX_CSSValue(PrimitiveType::kString), value_(value) {}
CFX_CSSStringValue::~CFX_CSSStringValue() = default;
diff --git a/core/fxcrt/css/cfx_cssstringvalue.h b/core/fxcrt/css/cfx_cssstringvalue.h
index afc2d31..1d014ba 100644
--- a/core/fxcrt/css/cfx_cssstringvalue.h
+++ b/core/fxcrt/css/cfx_cssstringvalue.h
@@ -12,7 +12,9 @@
class CFX_CSSStringValue final : public CFX_CSSValue {
public:
- explicit CFX_CSSStringValue(const WideString& value);
+ // Callers always have views, so do the copy here instead of requiring
+ // each of them to create a WideString.
+ explicit CFX_CSSStringValue(WideStringView value);
~CFX_CSSStringValue() override;
const WideString Value() const { return value_; }
diff --git a/core/fxcrt/css/cfx_cssstyleselector.cpp b/core/fxcrt/css/cfx_cssstyleselector.cpp
index a835410..6458eb7 100644
--- a/core/fxcrt/css/cfx_cssstyleselector.cpp
+++ b/core/fxcrt/css/cfx_cssstyleselector.cpp
@@ -209,7 +209,7 @@
case CFX_CSSProperty::LineHeight:
if (eType == CFX_CSSValue::PrimitiveType::kNumber) {
RetainPtr<CFX_CSSNumberValue> v = pValue.As<CFX_CSSNumberValue>();
- if (v->unit() == CFX_CSSNumberValue::Unit::kNumber) {
+ if (v->unit() == CFX_CSSNumber::Unit::kNumber) {
pComputedStyle->m_InheritedData.m_fLineHeight =
v->value() * pComputedStyle->m_InheritedData.m_fFontSize;
} else {
@@ -361,7 +361,7 @@
CFX_CSSLengthUnit::Normal);
} else if (eType == CFX_CSSValue::PrimitiveType::kNumber) {
if (pValue.AsRaw<CFX_CSSNumberValue>()->unit() ==
- CFX_CSSNumberValue::Unit::kPercent) {
+ CFX_CSSNumber::Unit::kPercent) {
break;
}
@@ -376,7 +376,7 @@
CFX_CSSLengthUnit::Normal);
} else if (eType == CFX_CSSValue::PrimitiveType::kNumber) {
if (pValue.AsRaw<CFX_CSSNumberValue>()->unit() ==
- CFX_CSSNumberValue::Unit::kPercent) {
+ CFX_CSSNumber::Unit::kPercent) {
break;
}
SetLengthWithPercent(pComputedStyle->m_InheritedData.m_WordSpacing,
@@ -470,7 +470,7 @@
float fFontSize) {
if (eType == CFX_CSSValue::PrimitiveType::kNumber) {
RetainPtr<CFX_CSSNumberValue> v = pValue.As<CFX_CSSNumberValue>();
- if (v->unit() == CFX_CSSNumberValue::Unit::kPercent) {
+ if (v->unit() == CFX_CSSNumber::Unit::kPercent) {
width.Set(CFX_CSSLengthUnit::Percent,
pValue.AsRaw<CFX_CSSNumberValue>()->value() / 100.0f);
return width.NonZero();
diff --git a/core/fxcrt/css/cfx_cssstylesheet_unittest.cpp b/core/fxcrt/css/cfx_cssstylesheet_unittest.cpp
index 77ba6a0..4457024 100644
--- a/core/fxcrt/css/cfx_cssstylesheet_unittest.cpp
+++ b/core/fxcrt/css/cfx_cssstylesheet_unittest.cpp
@@ -55,9 +55,7 @@
EXPECT_EQ(decl_->PropertyCountForTesting(), decl_count);
}
- void VerifyFloat(CFX_CSSProperty prop,
- float val,
- CFX_CSSNumberValue::Unit unit) {
+ void VerifyFloat(CFX_CSSProperty prop, float val, CFX_CSSNumber::Unit unit) {
DCHECK(decl_);
bool important;
@@ -153,13 +151,13 @@
EXPECT_EQ(4u, decl_->PropertyCountForTesting());
VerifyFloat(CFX_CSSProperty::BorderLeftWidth, 10.0f,
- CFX_CSSNumberValue::Unit::kPixels);
+ CFX_CSSNumber::Unit::kPixels);
VerifyFloat(CFX_CSSProperty::BorderRightWidth, 10.0f,
- CFX_CSSNumberValue::Unit::kPixels);
+ CFX_CSSNumber::Unit::kPixels);
VerifyFloat(CFX_CSSProperty::BorderTopWidth, 10.0f,
- CFX_CSSNumberValue::Unit::kPixels);
+ CFX_CSSNumber::Unit::kPixels);
VerifyFloat(CFX_CSSProperty::BorderBottomWidth, 10.0f,
- CFX_CSSNumberValue::Unit::kPixels);
+ CFX_CSSNumber::Unit::kPixels);
style = sheet_->GetRule(1);
ASSERT_TRUE(style);
@@ -181,14 +179,12 @@
decl_ = style->GetDeclaration();
ASSERT_TRUE(decl_);
EXPECT_EQ(4u, decl_->PropertyCountForTesting());
- VerifyFloat(CFX_CSSProperty::PaddingLeft, 0.0f,
- CFX_CSSNumberValue::Unit::kNumber);
+ VerifyFloat(CFX_CSSProperty::PaddingLeft, 0.0f, CFX_CSSNumber::Unit::kNumber);
VerifyFloat(CFX_CSSProperty::PaddingRight, 0.0f,
- CFX_CSSNumberValue::Unit::kNumber);
- VerifyFloat(CFX_CSSProperty::PaddingTop, 0.0f,
- CFX_CSSNumberValue::Unit::kNumber);
+ CFX_CSSNumber::Unit::kNumber);
+ VerifyFloat(CFX_CSSProperty::PaddingTop, 0.0f, CFX_CSSNumber::Unit::kNumber);
VerifyFloat(CFX_CSSProperty::PaddingBottom, 0.0f,
- CFX_CSSNumberValue::Unit::kNumber);
+ CFX_CSSNumber::Unit::kNumber);
}
TEST_F(CFX_CSSStyleSheetTest, ParseChildSelectors) {
@@ -220,13 +216,13 @@
EXPECT_EQ(4u, decl_->PropertyCountForTesting());
VerifyFloat(CFX_CSSProperty::BorderLeftWidth, 10.0f,
- CFX_CSSNumberValue::Unit::kPixels);
+ CFX_CSSNumber::Unit::kPixels);
VerifyFloat(CFX_CSSProperty::BorderRightWidth, 10.0f,
- CFX_CSSNumberValue::Unit::kPixels);
+ CFX_CSSNumber::Unit::kPixels);
VerifyFloat(CFX_CSSProperty::BorderTopWidth, 10.0f,
- CFX_CSSNumberValue::Unit::kPixels);
+ CFX_CSSNumber::Unit::kPixels);
VerifyFloat(CFX_CSSProperty::BorderBottomWidth, 10.0f,
- CFX_CSSNumberValue::Unit::kPixels);
+ CFX_CSSNumber::Unit::kPixels);
}
TEST_F(CFX_CSSStyleSheetTest, ParseUnhandledSelectors) {
@@ -254,31 +250,31 @@
TEST_F(CFX_CSSStyleSheetTest, ParseBorder) {
LoadAndVerifyDecl(L"a { border: 5px; }", {L"a"}, 4);
VerifyFloat(CFX_CSSProperty::BorderLeftWidth, 5.0,
- CFX_CSSNumberValue::Unit::kPixels);
+ CFX_CSSNumber::Unit::kPixels);
VerifyFloat(CFX_CSSProperty::BorderRightWidth, 5.0,
- CFX_CSSNumberValue::Unit::kPixels);
+ CFX_CSSNumber::Unit::kPixels);
VerifyFloat(CFX_CSSProperty::BorderTopWidth, 5.0,
- CFX_CSSNumberValue::Unit::kPixels);
+ CFX_CSSNumber::Unit::kPixels);
VerifyFloat(CFX_CSSProperty::BorderBottomWidth, 5.0,
- CFX_CSSNumberValue::Unit::kPixels);
+ CFX_CSSNumber::Unit::kPixels);
}
TEST_F(CFX_CSSStyleSheetTest, ParseBorderFull) {
LoadAndVerifyDecl(L"a { border: 5px solid red; }", {L"a"}, 4);
VerifyFloat(CFX_CSSProperty::BorderLeftWidth, 5.0,
- CFX_CSSNumberValue::Unit::kPixels);
+ CFX_CSSNumber::Unit::kPixels);
VerifyFloat(CFX_CSSProperty::BorderRightWidth, 5.0,
- CFX_CSSNumberValue::Unit::kPixels);
+ CFX_CSSNumber::Unit::kPixels);
VerifyFloat(CFX_CSSProperty::BorderTopWidth, 5.0,
- CFX_CSSNumberValue::Unit::kPixels);
+ CFX_CSSNumber::Unit::kPixels);
VerifyFloat(CFX_CSSProperty::BorderBottomWidth, 5.0,
- CFX_CSSNumberValue::Unit::kPixels);
+ CFX_CSSNumber::Unit::kPixels);
}
TEST_F(CFX_CSSStyleSheetTest, ParseBorderLeft) {
LoadAndVerifyDecl(L"a { border-left: 2.5pc; }", {L"a"}, 1);
VerifyFloat(CFX_CSSProperty::BorderLeftWidth, 2.5,
- CFX_CSSNumberValue::Unit::kPicas);
+ CFX_CSSNumber::Unit::kPicas);
}
TEST_F(CFX_CSSStyleSheetTest, ParseBorderLeftThick) {
@@ -289,38 +285,38 @@
TEST_F(CFX_CSSStyleSheetTest, ParseBorderRight) {
LoadAndVerifyDecl(L"a { border-right: 2.5pc; }", {L"a"}, 1);
VerifyFloat(CFX_CSSProperty::BorderRightWidth, 2.5,
- CFX_CSSNumberValue::Unit::kPicas);
+ CFX_CSSNumber::Unit::kPicas);
}
TEST_F(CFX_CSSStyleSheetTest, ParseBorderTop) {
LoadAndVerifyDecl(L"a { border-top: 2.5pc; }", {L"a"}, 1);
VerifyFloat(CFX_CSSProperty::BorderTopWidth, 2.5,
- CFX_CSSNumberValue::Unit::kPicas);
+ CFX_CSSNumber::Unit::kPicas);
}
TEST_F(CFX_CSSStyleSheetTest, ParseBorderBottom) {
LoadAndVerifyDecl(L"a { border-bottom: 2.5pc; }", {L"a"}, 1);
VerifyFloat(CFX_CSSProperty::BorderBottomWidth, 2.5,
- CFX_CSSNumberValue::Unit::kPicas);
+ CFX_CSSNumber::Unit::kPicas);
}
TEST_F(CFX_CSSStyleSheetTest, ParseWithCommentsInSelector) {
LoadAndVerifyDecl(L"/**{*/a/**}*/ { border-bottom: 2.5pc; }", {L"a"}, 1);
VerifyFloat(CFX_CSSProperty::BorderBottomWidth, 2.5,
- CFX_CSSNumberValue::Unit::kPicas);
+ CFX_CSSNumber::Unit::kPicas);
}
TEST_F(CFX_CSSStyleSheetTest, ParseWithCommentsInProperty) {
LoadAndVerifyDecl(L"a { /*}*/border-bottom: 2.5pc; }", {L"a"}, 1);
VerifyFloat(CFX_CSSProperty::BorderBottomWidth, 2.5,
- CFX_CSSNumberValue::Unit::kPicas);
+ CFX_CSSNumber::Unit::kPicas);
}
TEST_F(CFX_CSSStyleSheetTest, ParseWithCommentsInValue) {
LoadAndVerifyDecl(L"a { border-bottom: /*;*/2.5pc;/* color:red;*/ }", {L"a"},
1);
VerifyFloat(CFX_CSSProperty::BorderBottomWidth, 2.5,
- CFX_CSSNumberValue::Unit::kPicas);
+ CFX_CSSNumber::Unit::kPicas);
}
TEST_F(CFX_CSSStyleSheetTest, ParseWithUnterminatedCommentInSelector) {
diff --git a/core/fxcrt/css/cfx_cssvaluelistparser.cpp b/core/fxcrt/css/cfx_cssvaluelistparser.cpp
index 9c6dce8..ac5471e 100644
--- a/core/fxcrt/css/cfx_cssvaluelistparser.cpp
+++ b/core/fxcrt/css/cfx_cssvaluelistparser.cpp
@@ -11,55 +11,58 @@
#include "core/fxcrt/fx_extension.h"
#include "core/fxcrt/fx_system.h"
-CFX_CSSValueListParser::CFX_CSSValueListParser(const wchar_t* psz,
- size_t nLen,
+CFX_CSSValueListParser::CFX_CSSValueListParser(WideStringView list,
wchar_t separator)
- : m_Separator(separator), m_pCur(psz), m_pEnd(psz + nLen) {
- DCHECK(psz);
- DCHECK_NE(nLen, 0);
+ : m_Separator(separator),
+ m_pCur(list.unterminated_c_str()),
+ m_pEnd(list.unterminated_c_str() + list.GetLength()) {
+ DCHECK_NE(m_pCur, m_pEnd);
}
-bool CFX_CSSValueListParser::NextValue(CFX_CSSValue::PrimitiveType* eType,
- const wchar_t** pStart,
- size_t* nLength) {
- while (m_pCur < m_pEnd && (*m_pCur <= ' ' || *m_pCur == m_Separator))
+std::optional<CFX_CSSValueListParser::Result>
+CFX_CSSValueListParser::NextValue() {
+ while (m_pCur < m_pEnd && (*m_pCur <= ' ' || *m_pCur == m_Separator)) {
++m_pCur;
-
- if (m_pCur >= m_pEnd)
- return false;
-
- *eType = CFX_CSSValue::PrimitiveType::kUnknown;
- *pStart = m_pCur;
- *nLength = 0;
+ }
+ if (m_pCur >= m_pEnd) {
+ return std::nullopt;
+ }
+ auto eType = CFX_CSSValue::PrimitiveType::kUnknown;
+ const wchar_t* pStart = m_pCur;
+ size_t nLength = 0;
wchar_t wch = *m_pCur;
if (wch == '#') {
- *nLength = SkipToChar(' ');
- if (*nLength == 4 || *nLength == 7)
- *eType = CFX_CSSValue::PrimitiveType::kRGB;
+ nLength = SkipToChar(' ');
+ if (nLength == 4 || nLength == 7) {
+ eType = CFX_CSSValue::PrimitiveType::kRGB;
+ }
} else if (FXSYS_IsDecimalDigit(wch) || wch == '.' || wch == '-' ||
wch == '+') {
- while (m_pCur < m_pEnd && (*m_pCur > ' ' && *m_pCur != m_Separator))
+ while (m_pCur < m_pEnd && (*m_pCur > ' ' && *m_pCur != m_Separator)) {
++m_pCur;
-
- *nLength = m_pCur - *pStart;
- *eType = CFX_CSSValue::PrimitiveType::kNumber;
+ }
+ nLength = m_pCur - pStart;
+ eType = CFX_CSSValue::PrimitiveType::kNumber;
} else if (wch == '\"' || wch == '\'') {
- ++(*pStart);
- m_pCur++;
- *nLength = SkipToChar(wch);
- m_pCur++;
- *eType = CFX_CSSValue::PrimitiveType::kString;
+ ++pStart;
+ ++m_pCur;
+ nLength = SkipToChar(wch);
+ ++m_pCur;
+ eType = CFX_CSSValue::PrimitiveType::kString;
} else if (m_pEnd - m_pCur > 5 && m_pCur[3] == '(') {
if (FXSYS_wcsnicmp(L"rgb", m_pCur, 3) == 0) {
- *nLength = SkipToChar(')') + 1;
- m_pCur++;
- *eType = CFX_CSSValue::PrimitiveType::kRGB;
+ nLength = SkipToChar(')') + 1;
+ ++m_pCur;
+ eType = CFX_CSSValue::PrimitiveType::kRGB;
}
} else {
- *nLength = SkipToCharMatchingParens(m_Separator);
- *eType = CFX_CSSValue::PrimitiveType::kString;
+ nLength = SkipToCharMatchingParens(m_Separator);
+ eType = CFX_CSSValue::PrimitiveType::kString;
}
- return m_pCur <= m_pEnd && *nLength > 0;
+ if (m_pCur <= m_pEnd && nLength > 0) {
+ return Result{eType, WideStringView(pStart, nLength)};
+ }
+ return std::nullopt;
}
size_t CFX_CSSValueListParser::SkipToChar(wchar_t wch) {
diff --git a/core/fxcrt/css/cfx_cssvaluelistparser.h b/core/fxcrt/css/cfx_cssvaluelistparser.h
index 050d002..e6deb88 100644
--- a/core/fxcrt/css/cfx_cssvaluelistparser.h
+++ b/core/fxcrt/css/cfx_cssvaluelistparser.h
@@ -9,15 +9,21 @@
#include <stdint.h>
+#include <optional>
+
#include "core/fxcrt/css/cfx_cssvalue.h"
+#include "core/fxcrt/widestring.h"
class CFX_CSSValueListParser {
public:
- CFX_CSSValueListParser(const wchar_t* psz, size_t nLen, wchar_t separator);
+ struct Result {
+ CFX_CSSValue::PrimitiveType type = CFX_CSSValue::PrimitiveType::kUnknown;
+ WideStringView string_view;
+ };
- bool NextValue(CFX_CSSValue::PrimitiveType* eType,
- const wchar_t** pStart,
- size_t* nLength);
+ CFX_CSSValueListParser(WideStringView list, wchar_t separator);
+
+ std::optional<Result> NextValue();
void UseCommaSeparator() { m_Separator = ','; }
private:
diff --git a/core/fxcrt/css/cfx_cssvaluelistparser_unittest.cpp b/core/fxcrt/css/cfx_cssvaluelistparser_unittest.cpp
index 93d0e4a..f8e6e60 100644
--- a/core/fxcrt/css/cfx_cssvaluelistparser_unittest.cpp
+++ b/core/fxcrt/css/cfx_cssvaluelistparser_unittest.cpp
@@ -12,130 +12,132 @@
#include "testing/gtest/include/gtest/gtest.h"
TEST(CFX_CSSValueListParserTest, rgb_short) {
- CFX_CSSValue::PrimitiveType type;
- const wchar_t* start;
- size_t len;
+ auto parser = std::make_unique<CFX_CSSValueListParser>(L"#abc", L' ');
+ auto maybe_next = parser->NextValue();
+ ASSERT_TRUE(maybe_next.has_value());
+ EXPECT_EQ(CFX_CSSValue::PrimitiveType::kRGB, maybe_next.value().type);
+ EXPECT_EQ(L"#abc", maybe_next.value().string_view);
+ EXPECT_FALSE(parser->NextValue());
- auto parser = std::make_unique<CFX_CSSValueListParser>(L"#abc", 4, L' ');
- EXPECT_TRUE(parser->NextValue(&type, &start, &len));
- EXPECT_EQ(CFX_CSSValue::PrimitiveType::kRGB, type);
- EXPECT_EQ(L"#abc", WideString(start, len));
- EXPECT_FALSE(parser->NextValue(&type, &start, &len));
+ parser = std::make_unique<CFX_CSSValueListParser>(L"#abcdef", L' ');
+ maybe_next = parser->NextValue();
+ ASSERT_TRUE(maybe_next.has_value());
+ EXPECT_EQ(CFX_CSSValue::PrimitiveType::kRGB, maybe_next.value().type);
+ EXPECT_EQ(L"#abcdef", maybe_next.value().string_view);
- parser = std::make_unique<CFX_CSSValueListParser>(L"#abcdef", 7, L' ');
- EXPECT_TRUE(parser->NextValue(&type, &start, &len));
- EXPECT_EQ(CFX_CSSValue::PrimitiveType::kRGB, type);
- EXPECT_EQ(L"#abcdef", WideString(start, len));
- EXPECT_FALSE(parser->NextValue(&type, &start, &len));
+ parser = std::make_unique<CFX_CSSValueListParser>(L"rgb(1, 255, 4)", L' ');
+ maybe_next = parser->NextValue();
+ ASSERT_TRUE(maybe_next.has_value());
+ EXPECT_EQ(CFX_CSSValue::PrimitiveType::kRGB, maybe_next.value().type);
+ EXPECT_EQ(L"rgb(1, 255, 4)", maybe_next.value().string_view);
- parser =
- std::make_unique<CFX_CSSValueListParser>(L"rgb(1, 255, 4)", 14, L' ');
- EXPECT_TRUE(parser->NextValue(&type, &start, &len));
- EXPECT_EQ(CFX_CSSValue::PrimitiveType::kRGB, type);
- EXPECT_EQ(L"rgb(1, 255, 4)", WideString(start, len));
-
- parser = std::make_unique<CFX_CSSValueListParser>(L"#abcdefghij", 11, L' ');
- EXPECT_TRUE(parser->NextValue(&type, &start, &len));
- EXPECT_EQ(CFX_CSSValue::PrimitiveType::kUnknown, type);
- EXPECT_EQ(L"#abcdefghij", WideString(start, len));
- EXPECT_FALSE(parser->NextValue(&type, &start, &len));
+ parser = std::make_unique<CFX_CSSValueListParser>(L"#abcdefghij", L' ');
+ maybe_next = parser->NextValue();
+ ASSERT_TRUE(maybe_next.has_value());
+ EXPECT_EQ(CFX_CSSValue::PrimitiveType::kUnknown, maybe_next.value().type);
+ EXPECT_EQ(L"#abcdefghij", maybe_next.value().string_view);
+ EXPECT_FALSE(parser->NextValue());
}
TEST(CFX_CSSValueListParserTest, number_parsing) {
- CFX_CSSValue::PrimitiveType type;
- const wchar_t* start;
- size_t len;
+ auto parser = std::make_unique<CFX_CSSValueListParser>(L"1234", L' ');
+ auto maybe_next = parser->NextValue();
+ ASSERT_TRUE(maybe_next.has_value());
+ EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, maybe_next.value().type);
+ EXPECT_EQ(L"1234", maybe_next.value().string_view);
- auto parser = std::make_unique<CFX_CSSValueListParser>(L"1234", 4, L' ');
- EXPECT_TRUE(parser->NextValue(&type, &start, &len));
- EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, type);
- EXPECT_EQ(L"1234", WideString(start, len));
+ parser = std::make_unique<CFX_CSSValueListParser>(L"-1234", L' ');
+ maybe_next = parser->NextValue();
+ ASSERT_TRUE(maybe_next.has_value());
+ EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, maybe_next.value().type);
+ EXPECT_EQ(L"-1234", maybe_next.value().string_view);
- parser = std::make_unique<CFX_CSSValueListParser>(L"-1234", 5, L' ');
- EXPECT_TRUE(parser->NextValue(&type, &start, &len));
- EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, type);
- EXPECT_EQ(L"-1234", WideString(start, len));
+ parser = std::make_unique<CFX_CSSValueListParser>(L"+1234", L' ');
+ maybe_next = parser->NextValue();
+ ASSERT_TRUE(maybe_next.has_value());
+ EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, maybe_next.value().type);
+ EXPECT_EQ(L"+1234", maybe_next.value().string_view);
- parser = std::make_unique<CFX_CSSValueListParser>(L"+1234", 5, L' ');
- EXPECT_TRUE(parser->NextValue(&type, &start, &len));
- EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, type);
- EXPECT_EQ(L"+1234", WideString(start, len));
+ parser = std::make_unique<CFX_CSSValueListParser>(L".1234", L' ');
+ maybe_next = parser->NextValue();
+ ASSERT_TRUE(maybe_next.has_value());
+ EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, maybe_next.value().type);
+ EXPECT_EQ(L".1234", maybe_next.value().string_view);
- parser = std::make_unique<CFX_CSSValueListParser>(L".1234", 5, L' ');
- EXPECT_TRUE(parser->NextValue(&type, &start, &len));
- EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, type);
- EXPECT_EQ(L".1234", WideString(start, len));
-
- parser = std::make_unique<CFX_CSSValueListParser>(L"4321.1234", 9, L' ');
- EXPECT_TRUE(parser->NextValue(&type, &start, &len));
- EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, type);
- EXPECT_EQ(L"4321.1234", WideString(start, len));
+ parser = std::make_unique<CFX_CSSValueListParser>(L"4321.1234", L' ');
+ maybe_next = parser->NextValue();
+ ASSERT_TRUE(maybe_next.has_value());
+ EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, maybe_next.value().type);
+ EXPECT_EQ(L"4321.1234", maybe_next.value().string_view);
// TODO(dsinclair): These should probably fail but currently don't.
- parser = std::make_unique<CFX_CSSValueListParser>(L"4321.12.34", 10, L' ');
- EXPECT_TRUE(parser->NextValue(&type, &start, &len));
- EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, type);
- EXPECT_EQ(L"4321.12.34", WideString(start, len));
+ parser = std::make_unique<CFX_CSSValueListParser>(L"4321.12.34", L' ');
+ maybe_next = parser->NextValue();
+ ASSERT_TRUE(maybe_next.has_value());
+ EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, maybe_next.value().type);
+ EXPECT_EQ(L"4321.12.34", maybe_next.value().string_view);
- parser = std::make_unique<CFX_CSSValueListParser>(L"43a1.12.34", 10, L' ');
- EXPECT_TRUE(parser->NextValue(&type, &start, &len));
- EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, type);
- EXPECT_EQ(L"43a1.12.34", WideString(start, len));
+ parser = std::make_unique<CFX_CSSValueListParser>(L"43a1.12.34", L' ');
+ maybe_next = parser->NextValue();
+ ASSERT_TRUE(maybe_next.has_value());
+ EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, maybe_next.value().type);
+ EXPECT_EQ(L"43a1.12.34", maybe_next.value().string_view);
}
TEST(CFX_CSSValueListParserTest, string_parsing) {
- CFX_CSSValue::PrimitiveType type;
- const wchar_t* start;
- size_t len;
-
- auto parser = std::make_unique<CFX_CSSValueListParser>(L"'string'", 8, L' ');
- EXPECT_TRUE(parser->NextValue(&type, &start, &len));
- EXPECT_EQ(CFX_CSSValue::PrimitiveType::kString, type);
- EXPECT_EQ(L"string", WideString(start, len));
+ auto parser = std::make_unique<CFX_CSSValueListParser>(L"'string'", L' ');
+ auto maybe_next = parser->NextValue();
+ ASSERT_TRUE(maybe_next.has_value());
+ EXPECT_EQ(CFX_CSSValue::PrimitiveType::kString, maybe_next.value().type);
+ EXPECT_EQ(L"string", maybe_next.value().string_view);
parser =
- std::make_unique<CFX_CSSValueListParser>(L"\"another string\"", 16, L' ');
- EXPECT_TRUE(parser->NextValue(&type, &start, &len));
- EXPECT_EQ(CFX_CSSValue::PrimitiveType::kString, type);
- EXPECT_EQ(L"another string", WideString(start, len));
+ std::make_unique<CFX_CSSValueListParser>(L"\"another string\"", L' ');
+ maybe_next = parser->NextValue();
+ ASSERT_TRUE(maybe_next.has_value());
+ EXPECT_EQ(CFX_CSSValue::PrimitiveType::kString, maybe_next.value().type);
+ EXPECT_EQ(L"another string", maybe_next.value().string_view);
- parser = std::make_unique<CFX_CSSValueListParser>(L"standalone", 10, L' ');
- EXPECT_TRUE(parser->NextValue(&type, &start, &len));
- EXPECT_EQ(CFX_CSSValue::PrimitiveType::kString, type);
- EXPECT_EQ(L"standalone", WideString(start, len));
+ parser = std::make_unique<CFX_CSSValueListParser>(L"standalone", L' ');
+ maybe_next = parser->NextValue();
+ ASSERT_TRUE(maybe_next.has_value());
+ EXPECT_EQ(CFX_CSSValue::PrimitiveType::kString, maybe_next.value().type);
+ EXPECT_EQ(L"standalone", maybe_next.value().string_view);
}
TEST(CFX_CSSValueListParserTest, multiparsing) {
- CFX_CSSValue::PrimitiveType type;
- const wchar_t* start;
- size_t len;
+ auto parser = std::make_unique<CFX_CSSValueListParser>(L"1, 2, 3", L',');
+ auto maybe_next = parser->NextValue();
+ ASSERT_TRUE(maybe_next.has_value());
+ EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, maybe_next.value().type);
+ EXPECT_EQ(L"1", maybe_next.value().string_view);
- auto parser = std::make_unique<CFX_CSSValueListParser>(L"1, 2, 3", 7, L',');
- EXPECT_TRUE(parser->NextValue(&type, &start, &len));
- EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, type);
- EXPECT_EQ(L"1", WideString(start, len));
+ maybe_next = parser->NextValue();
+ ASSERT_TRUE(maybe_next.has_value());
+ EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, maybe_next.value().type);
+ EXPECT_EQ(L"2", maybe_next.value().string_view);
- EXPECT_TRUE(parser->NextValue(&type, &start, &len));
- EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, type);
- EXPECT_EQ(L"2", WideString(start, len));
+ maybe_next = parser->NextValue();
+ ASSERT_TRUE(maybe_next.has_value());
+ EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, maybe_next.value().type);
+ EXPECT_EQ(L"3", maybe_next.value().string_view);
- EXPECT_TRUE(parser->NextValue(&type, &start, &len));
- EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, type);
- EXPECT_EQ(L"3", WideString(start, len));
+ EXPECT_FALSE(parser->NextValue());
- EXPECT_FALSE(parser->NextValue(&type, &start, &len));
+ parser =
+ std::make_unique<CFX_CSSValueListParser>(L"'str', rgb(1, 2, 3), 4", L',');
+ maybe_next = parser->NextValue();
+ ASSERT_TRUE(maybe_next.has_value());
+ EXPECT_EQ(CFX_CSSValue::PrimitiveType::kString, maybe_next.value().type);
+ EXPECT_EQ(L"str", maybe_next.value().string_view);
- parser = std::make_unique<CFX_CSSValueListParser>(L"'str', rgb(1, 2, 3), 4",
- 22, L',');
- EXPECT_TRUE(parser->NextValue(&type, &start, &len));
- EXPECT_EQ(CFX_CSSValue::PrimitiveType::kString, type);
- EXPECT_EQ(L"str", WideString(start, len));
+ maybe_next = parser->NextValue();
+ ASSERT_TRUE(maybe_next.has_value());
+ EXPECT_EQ(CFX_CSSValue::PrimitiveType::kRGB, maybe_next.value().type);
+ EXPECT_EQ(L"rgb(1, 2, 3)", maybe_next.value().string_view);
- EXPECT_TRUE(parser->NextValue(&type, &start, &len));
- EXPECT_EQ(CFX_CSSValue::PrimitiveType::kRGB, type);
- EXPECT_EQ(L"rgb(1, 2, 3)", WideString(start, len));
-
- EXPECT_TRUE(parser->NextValue(&type, &start, &len));
- EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, type);
- EXPECT_EQ(L"4", WideString(start, len));
+ maybe_next = parser->NextValue();
+ ASSERT_TRUE(maybe_next.has_value());
+ EXPECT_EQ(CFX_CSSValue::PrimitiveType::kNumber, maybe_next.value().type);
+ EXPECT_EQ(L"4", maybe_next.value().string_view);
}