1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 13:18:13 +00:00

LibWeb: Make the CSS parser use the new double parser

This could potentially be sped up by tracking the up to three different
ranges of characters known to be digits. This would save the double
parser from checking whether these are digits and because it has the
size it can use the fast parsing method.
This commit is contained in:
davidot 2022-10-12 02:23:57 +02:00 committed by Linus Groh
parent 783b1a479d
commit 8abd4f6102

View file

@ -7,6 +7,7 @@
#include <AK/CharacterTypes.h>
#include <AK/Debug.h>
#include <AK/FloatingPointStringConversions.h>
#include <AK/SourceLocation.h>
#include <AK/Vector.h>
#include <LibTextCodec/Decoder.h>
@ -569,78 +570,9 @@ Number Tokenizer::consume_a_number()
// https://www.w3.org/TR/css-syntax-3/#convert-string-to-number
float Tokenizer::convert_a_string_to_a_number(StringView string)
{
auto code_point_at = [&](size_t index) -> u32 {
if (index < string.length())
return string[index];
return TOKENIZER_EOF;
};
// This algorithm does not do any verification to ensure that the string contains only a number.
// Ensure that the string contains only a valid CSS number before calling this algorithm.
// Divide the string into seven components, in order from left to right:
size_t position = 0;
// 1. A sign: a single U+002B PLUS SIGN (+) or U+002D HYPHEN-MINUS (-), or the empty string.
// Let s [sign] be the number -1 if the sign is U+002D HYPHEN-MINUS (-); otherwise, let s be the number 1.
int sign = 1;
if (is_plus_sign(code_point_at(position)) || is_hyphen_minus(code_point_at(position))) {
sign = is_hyphen_minus(code_point_at(position)) ? -1 : 1;
position++;
}
// 2. An integer part: zero or more digits.
// If there is at least one digit, let i [integer_part] be the number formed by interpreting the digits
// as a base-10 integer; otherwise, let i be the number 0.
i64 integer_part = 0;
while (is_ascii_digit(code_point_at(position))) {
integer_part = (integer_part * 10) + (code_point_at(position) - '0');
position++;
}
// 3. A decimal point: a single U+002E FULL STOP (.), or the empty string.
if (is_full_stop(code_point_at(position)))
position++;
// 4. A fractional part: zero or more digits.
// If there is at least one digit, let f [fractional_part] be the number formed by interpreting the digits
// as a base-10 integer and d [fractional_digits] be the number of digits; otherwise, let f and d be the number 0.
i64 fractional_part = 0;
int fractional_digits = 0;
while (is_ascii_digit(code_point_at(position))) {
fractional_part = (fractional_part * 10) + (code_point_at(position) - '0');
position++;
fractional_digits++;
}
// 5. An exponent indicator: a single U+0045 LATIN CAPITAL LETTER E (E) or U+0065 LATIN SMALL LETTER E (e),
// or the empty string.
if (is_e(code_point_at(position)) || is_E(code_point_at(position)))
position++;
// 6. An exponent sign: a single U+002B PLUS SIGN (+) or U+002D HYPHEN-MINUS (-), or the empty string.
// Let t [exponent_sign] be the number -1 if the sign is U+002D HYPHEN-MINUS (-); otherwise, let t be the number 1.
int exponent_sign = 1;
if (is_plus_sign(code_point_at(position)) || is_hyphen_minus(code_point_at(position))) {
exponent_sign = is_hyphen_minus(code_point_at(position)) ? -1 : 1;
position++;
}
// 7. An exponent: zero or more digits.
// If there is at least one digit, let e [exponent] be the number formed by interpreting the digits as a
// base-10 integer; otherwise, let e be the number 0.
i64 exponent = 0;
while (is_ascii_digit(code_point_at(position))) {
exponent = (exponent * 10) + (code_point_at(position) - '0');
position++;
}
// NOTE: We checked before calling this function that the string is a valid number,
// so if there is anything at the end, something has gone wrong!
VERIFY(position == string.length());
// Return the number s·(i + f·10^-d)·10^te.
return sign * (integer_part + fractional_part * powf(10, -fractional_digits)) * powf(10, exponent_sign * exponent);
// FIXME: We already found the whole part, fraction part and exponent during
// validation, we could probably skip
return string.to_float(AK::TrimWhitespace::No).release_value();
}
// https://www.w3.org/TR/css-syntax-3/#consume-name