Make dimension units case insensitive (#44639)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/44639

https://www.w3.org/TR/css-values-4/#dimensions

> Like keywords, unit identifiers are ASCII case-insensitive.

Changelog: [Internal]

Reviewed By: joevilches

Differential Revision: D57620806

fbshipit-source-id: 26946ed4031f379888651c08b1b0895ac701a320
This commit is contained in:
Nick Gerleman
2024-05-21 11:25:57 -07:00
committed by Facebook GitHub Bot
parent fb23470483
commit 644facd19d
5 changed files with 25 additions and 12 deletions
@@ -31,7 +31,7 @@ enum class CSSAngleUnit : uint8_t {
* Parses a unit from a dimension token into a CSS angle unit.
*/
constexpr std::optional<CSSAngleUnit> parseCSSAngleUnit(std::string_view unit) {
switch (fnv1a(unit)) {
switch (fnv1aLowercase(unit)) {
case fnv1a("deg"):
return CSSAngleUnit::Deg;
case fnv1a("grad"):
@@ -175,16 +175,7 @@ CSS_DEFINE_KEYWORD_CONEPTS(WrapReverse)
*/
template <CSSKeywordSet KeywordT>
constexpr std::optional<KeywordT> parseCSSKeyword(std::string_view ident) {
struct LowerCaseTransform {
constexpr char operator()(char c) const {
if (c >= 'A' && c <= 'Z') {
return c + static_cast<char>('a' - 'A');
}
return c;
}
};
switch (fnv1a<LowerCaseTransform>(ident)) {
switch (fnv1aLowercase(ident)) {
case fnv1a("absolute"):
if constexpr (detail::hasAbsolute<KeywordT>) {
return KeywordT::Absolute;
@@ -70,7 +70,7 @@ enum class CSSLengthUnit : uint8_t {
*/
constexpr std::optional<CSSLengthUnit> parseCSSLengthUnit(
std::string_view unit) {
switch (fnv1a(unit)) {
switch (fnv1aLowercase(unit)) {
case fnv1a("cap"):
return CSSLengthUnit::Cap;
case fnv1a("ch"):
@@ -59,6 +59,11 @@ TEST(CSSValueParser, length_values) {
EXPECT_EQ(pxValue.getLength().value, 20.0f);
EXPECT_EQ(pxValue.getLength().unit, CSSLengthUnit::Px);
auto capsValue = parseCSSValue<CSSWideKeyword, CSSLength>("50PX");
EXPECT_EQ(capsValue.type(), CSSValueType::Length);
EXPECT_EQ(capsValue.getLength().value, 50.0f);
EXPECT_EQ(capsValue.getLength().unit, CSSLengthUnit::Px);
auto cmValue = parseCSSValue<CSSWideKeyword, CSSLength>("453cm");
EXPECT_EQ(cmValue.type(), CSSValueType::Length);
EXPECT_EQ(cmValue.getLength().value, 453.0f);
@@ -258,6 +263,10 @@ TEST(CSSValueParser, angle_values) {
EXPECT_EQ(degreeValue.type(), CSSValueType::Angle);
EXPECT_EQ(degreeValue.getAngle().degrees, 10.0f);
auto spongebobCaseValue = parseCSSValue<CSSWideKeyword, CSSAngle>("20dEg");
EXPECT_EQ(spongebobCaseValue.type(), CSSValueType::Angle);
EXPECT_EQ(spongebobCaseValue.getAngle().degrees, 20.0f);
auto radianValue = parseCSSValue<CSSWideKeyword, CSSAngle>("10rad");
EXPECT_EQ(radianValue.type(), CSSValueType::Angle);
EXPECT_NEAR(radianValue.getAngle().degrees, 572.958f, 0.001f);
@@ -38,4 +38,17 @@ constexpr uint32_t fnv1a(std::string_view string) noexcept {
return hash;
}
constexpr uint32_t fnv1aLowercase(std::string_view string) {
struct LowerCaseTransform {
constexpr char operator()(char c) const {
if (c >= 'A' && c <= 'Z') {
return c + static_cast<char>('a' - 'A');
}
return c;
}
};
return fnv1a<LowerCaseTransform>(string);
}
} // namespace facebook::react