summaryrefslogtreecommitdiff
path: root/Libraries/LibHTML/Parser
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-11-18 16:54:03 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-11-18 16:54:03 +0100
commita14cc573b0fc4531e1d66c673ef0af61db3d7339 (patch)
treeac1ea0357f34f86bd827344a6f86e45dda9c9d23 /Libraries/LibHTML/Parser
parentb0f38c17337aed97508ed66d17af23d5b7acb69a (diff)
downloadserenity-a14cc573b0fc4531e1d66c673ef0af61db3d7339.zip
LibHTML: Implement some basic floating point CSS value parsing
Diffstat (limited to 'Libraries/LibHTML/Parser')
-rw-r--r--Libraries/LibHTML/Parser/CSSParser.cpp93
1 files changed, 86 insertions, 7 deletions
diff --git a/Libraries/LibHTML/Parser/CSSParser.cpp b/Libraries/LibHTML/Parser/CSSParser.cpp
index 7e09edb579..f21314e7dd 100644
--- a/Libraries/LibHTML/Parser/CSSParser.cpp
+++ b/Libraries/LibHTML/Parser/CSSParser.cpp
@@ -22,13 +22,92 @@ static Optional<Color> parse_css_color(const StringView& view)
return {};
}
-NonnullRefPtr<StyleValue> parse_css_value(const StringView& view)
+static Optional<float> try_parse_float(const StringView& string)
{
- String string(view);
- char* endptr = nullptr;
- long value = strtol(String(view).characters(), &endptr, 10);
- if (endptr && ((!*endptr) || (endptr[0] == 'p' && endptr[1] == 'x' && endptr[2] == '\0')))
- return LengthStyleValue::create(Length((float)value, Length::Type::Absolute));
+ const char* str = string.characters_without_null_termination();
+ size_t len = string.length();
+ size_t weight = 1;
+ int exp_val = 0;
+ float value = 0.0f;
+ float fraction = 0.0f;
+ bool has_sign = false;
+ bool is_negative = false;
+ bool is_fractional = false;
+ bool is_scientific = false;
+
+ if (str[0] == '-') {
+ is_negative = true;
+ has_sign = true;
+ }
+ if (str[0] == '+') {
+ has_sign = true;
+ }
+
+ for (size_t i = has_sign; i < len; i++) {
+
+ // Looks like we're about to start working on the fractional part
+ if (str[i] == '.') {
+ is_fractional = true;
+ continue;
+ }
+
+ if (str[i] == 'e' || str[i] == 'E') {
+ if (str[i + 1] == '-' || str[i + 1] == '+')
+ exp_val = atoi(str + i + 2);
+ else
+ exp_val = atoi(str + i + 1);
+
+ is_scientific = true;
+ continue;
+ }
+
+ if (str[i] < '0' || str[i] > '9' || exp_val != 0) {
+ return {};
+ continue;
+ }
+
+ if (is_fractional) {
+ fraction *= 10;
+ fraction += str[i] - '0';
+ weight *= 10;
+ } else {
+ value = value * 10;
+ value += str[i] - '0';
+ }
+ }
+
+ fraction /= weight;
+ value += fraction;
+
+ if (is_scientific) {
+ bool divide = exp_val < 0;
+ if (divide)
+ exp_val *= -1;
+
+ for (int i = 0; i < exp_val; i++) {
+ if (divide)
+ value /= 10;
+ else
+ value *= 10;
+ }
+ }
+
+ return is_negative ? -value : value;
+}
+
+static Optional<float> parse_number(const StringView& view)
+{
+ if (view.length() >= 2 && view[view.length() - 2] == 'p' && view[view.length() - 1] == 'x')
+ return parse_number(view.substring_view(0, view.length() - 2));
+
+ return try_parse_float(view);
+}
+
+NonnullRefPtr<StyleValue> parse_css_value(const StringView& string)
+{
+ auto number = parse_number(string);
+ if (number.has_value())
+ return LengthStyleValue::create(Length(number.value(), Length::Type::Absolute));
if (string == "inherit")
return InheritStyleValue::create();
if (string == "initial")
@@ -36,7 +115,7 @@ NonnullRefPtr<StyleValue> parse_css_value(const StringView& view)
if (string == "auto")
return LengthStyleValue::create(Length());
- auto color = parse_css_color(view);
+ auto color = parse_css_color(string);
if (color.has_value())
return ColorStyleValue::create(color.value());