From e8ab2dab111aa40af6843f98e8fee3ab4bc7e43e Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Mon, 21 Mar 2022 20:54:45 +0000 Subject: [PATCH] LibWeb: Implement a CSS::Number class We have the same "number and is-integer flag" structure in several places, so let's put that in a class. --- Userland/Libraries/LibWeb/CSS/Number.h | 84 ++++++++++++++++++++++++++ Userland/Libraries/LibWeb/Forward.h | 1 + 2 files changed, 85 insertions(+) create mode 100644 Userland/Libraries/LibWeb/CSS/Number.h diff --git a/Userland/Libraries/LibWeb/CSS/Number.h b/Userland/Libraries/LibWeb/CSS/Number.h new file mode 100644 index 0000000000..7b48a54881 --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/Number.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2022, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Web::CSS { + +class Tokenizer; + +class Number { + friend class Tokenizer; + +public: + enum class Type { + Number, + IntegerWithExplicitSign, // This only exists for the nightmarish An+B parsing algorithm + Integer + }; + + Number() + : m_value(0) + , m_type(Type::Number) + { + } + Number(Type type, float value) + : m_value(value) + , m_type(type) + { + } + + float value() const { return m_value; } + i64 integer_value() const + { + // https://www.w3.org/TR/css-values-4/#numeric-types + // When a value cannot be explicitly supported due to range/precision limitations, it must be converted + // to the closest value supported by the implementation, but how the implementation defines "closest" + // is explicitly undefined as well. + return llroundf(m_value); + } + bool is_integer() const { return m_type == Type::Integer || m_type == Type::IntegerWithExplicitSign; } + bool is_integer_with_explicit_sign() const { return m_type == Type::IntegerWithExplicitSign; } + + Number operator+(Number const& other) const + { + if (is_integer() && other.is_integer()) + return { Type::Integer, m_value + other.m_value }; + return { Type::Number, m_value + other.m_value }; + } + + Number operator-(Number const& other) const + { + if (is_integer() && other.is_integer()) + return { Type::Integer, m_value - other.m_value }; + return { Type::Number, m_value - other.m_value }; + } + + Number operator*(Number const& other) const + { + if (is_integer() && other.is_integer()) + return { Type::Integer, m_value * other.m_value }; + return { Type::Number, m_value * other.m_value }; + } + + Number operator/(Number const& other) const + { + return { Type::Number, m_value / other.m_value }; + } + + auto operator<=>(Number const& other) const + { + return m_value - other.m_value; + } + +private: + float m_value { 0 }; + Type m_type; +}; +} diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 981936578e..a065362ce7 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -59,6 +59,7 @@ class MediaList; class MediaQuery; class MediaQueryList; class MediaQueryListEvent; +class Number; class NumericStyleValue; class OverflowStyleValue; class Percentage;