Serenity Operating System
at master 96 lines 2.7 kB view raw
1/* 2 * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#pragma once 8 9#include <AK/String.h> 10#include <AK/Types.h> 11#include <math.h> 12 13namespace Web::CSS { 14 15class Number { 16public: 17 enum class Type { 18 Number, 19 IntegerWithExplicitSign, // This only exists for the nightmarish An+B parsing algorithm 20 Integer 21 }; 22 23 Number() 24 : m_value(0) 25 , m_type(Type::Number) 26 { 27 } 28 Number(Type type, float value) 29 : m_value(value) 30 , m_type(type) 31 { 32 } 33 34 float value() const { return m_value; } 35 i64 integer_value() const 36 { 37 // https://www.w3.org/TR/css-values-4/#numeric-types 38 // When a value cannot be explicitly supported due to range/precision limitations, it must be converted 39 // to the closest value supported by the implementation, but how the implementation defines "closest" 40 // is explicitly undefined as well. 41 return llroundf(m_value); 42 } 43 bool is_integer() const { return m_type == Type::Integer || m_type == Type::IntegerWithExplicitSign; } 44 bool is_integer_with_explicit_sign() const { return m_type == Type::IntegerWithExplicitSign; } 45 46 Number operator+(Number const& other) const 47 { 48 if (is_integer() && other.is_integer()) 49 return { Type::Integer, m_value + other.m_value }; 50 return { Type::Number, m_value + other.m_value }; 51 } 52 53 Number operator-(Number const& other) const 54 { 55 if (is_integer() && other.is_integer()) 56 return { Type::Integer, m_value - other.m_value }; 57 return { Type::Number, m_value - other.m_value }; 58 } 59 60 Number operator*(Number const& other) const 61 { 62 if (is_integer() && other.is_integer()) 63 return { Type::Integer, m_value * other.m_value }; 64 return { Type::Number, m_value * other.m_value }; 65 } 66 67 Number operator/(Number const& other) const 68 { 69 return { Type::Number, m_value / other.m_value }; 70 } 71 72 ErrorOr<String> to_string() const 73 { 74 if (m_type == Type::IntegerWithExplicitSign) 75 return String::formatted("{:+}", m_value); 76 return String::number(m_value); 77 } 78 79 bool operator==(Number const& other) const 80 { 81 return m_type == other.m_type && m_value == other.m_value; 82 } 83 84private: 85 float m_value { 0 }; 86 Type m_type; 87}; 88} 89 90template<> 91struct AK::Formatter<Web::CSS::Number> : Formatter<StringView> { 92 ErrorOr<void> format(FormatBuilder& builder, Web::CSS::Number const& number) 93 { 94 return Formatter<StringView>::format(builder, TRY(number.to_string())); 95 } 96};