Token.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. * Copyright (c) 2020-2021, the SerenityOS developers.
  3. * Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #pragma once
  8. #include <AK/FlyString.h>
  9. #include <AK/String.h>
  10. #include <AK/Utf8View.h>
  11. #include <math.h>
  12. namespace Web::CSS {
  13. class Token {
  14. friend class Tokenizer;
  15. public:
  16. enum class Type {
  17. Invalid,
  18. EndOfFile,
  19. Ident,
  20. Function,
  21. AtKeyword,
  22. Hash,
  23. String,
  24. BadString,
  25. Url,
  26. BadUrl,
  27. Delim,
  28. Number,
  29. Percentage,
  30. Dimension,
  31. Whitespace,
  32. CDO,
  33. CDC,
  34. Colon,
  35. Semicolon,
  36. Comma,
  37. OpenSquare,
  38. CloseSquare,
  39. OpenParen,
  40. CloseParen,
  41. OpenCurly,
  42. CloseCurly
  43. };
  44. enum class HashType {
  45. Id,
  46. Unrestricted,
  47. };
  48. enum class NumberType {
  49. Integer,
  50. Number,
  51. };
  52. struct Position {
  53. size_t line { 0 };
  54. size_t column { 0 };
  55. };
  56. Type type() const { return m_type; }
  57. bool is(Type type) const { return m_type == type; }
  58. StringView ident() const
  59. {
  60. VERIFY(m_type == Type::Ident);
  61. return m_value.view();
  62. }
  63. StringView function() const
  64. {
  65. VERIFY(m_type == Type::Function);
  66. return m_value.view();
  67. }
  68. u32 delim() const
  69. {
  70. VERIFY(m_type == Type::Delim);
  71. return *Utf8View(m_value.view()).begin();
  72. }
  73. StringView string() const
  74. {
  75. VERIFY(m_type == Type::String);
  76. return m_value.view();
  77. }
  78. StringView url() const
  79. {
  80. VERIFY(m_type == Type::Url);
  81. return m_value.view();
  82. }
  83. StringView at_keyword() const
  84. {
  85. VERIFY(m_type == Type::AtKeyword);
  86. return m_value.view();
  87. }
  88. HashType hash_type() const
  89. {
  90. VERIFY(m_type == Type::Hash);
  91. return m_hash_type;
  92. }
  93. StringView hash_value() const
  94. {
  95. VERIFY(m_type == Type::Hash);
  96. return m_value.view();
  97. }
  98. bool is(NumberType number_type) const { return is(Token::Type::Number) && m_number_type == number_type; }
  99. StringView number_string_value() const
  100. {
  101. VERIFY(m_type == Type::Number);
  102. return m_value.view();
  103. }
  104. double number_value() const
  105. {
  106. VERIFY(m_type == Type::Number);
  107. return m_number_value;
  108. }
  109. i64 to_integer() const
  110. {
  111. VERIFY(m_type == Type::Number && m_number_type == NumberType::Integer);
  112. return to_closest_integer(m_number_value);
  113. }
  114. bool is_integer_value_signed() const { return number_string_value().starts_with('-') || number_string_value().starts_with('+'); }
  115. StringView dimension_unit() const
  116. {
  117. VERIFY(m_type == Type::Dimension);
  118. return m_unit.view();
  119. }
  120. double dimension_value() const
  121. {
  122. VERIFY(m_type == Type::Dimension);
  123. return m_number_value;
  124. }
  125. i64 dimension_value_int() const { return to_closest_integer(dimension_value()); }
  126. double percentage() const
  127. {
  128. VERIFY(m_type == Type::Percentage);
  129. return m_number_value;
  130. }
  131. NumberType number_type() const
  132. {
  133. VERIFY((m_type == Type::Number) || (m_type == Type::Dimension) || (m_type == Type::Percentage));
  134. return m_number_type;
  135. }
  136. Type mirror_variant() const;
  137. String bracket_string() const;
  138. String bracket_mirror_string() const;
  139. String to_string() const;
  140. String to_debug_string() const;
  141. Position const& start_position() const { return m_start_position; }
  142. Position const& end_position() const { return m_end_position; }
  143. private:
  144. static i64 to_closest_integer(double value)
  145. {
  146. // https://www.w3.org/TR/css-values-4/#numeric-types
  147. // When a value cannot be explicitly supported due to range/precision limitations, it must be converted
  148. // to the closest value supported by the implementation, but how the implementation defines "closest"
  149. // is explicitly undefined as well.
  150. return static_cast<i64>(clamp(round(value), NumericLimits<i64>::min(), NumericLimits<i64>::max()));
  151. }
  152. Type m_type { Type::Invalid };
  153. FlyString m_value;
  154. FlyString m_unit;
  155. HashType m_hash_type { HashType::Unrestricted };
  156. NumberType m_number_type { NumberType::Integer };
  157. double m_number_value { 0 };
  158. Position m_start_position;
  159. Position m_end_position;
  160. };
  161. }