diff options
-rw-r--r-- | Userland/Libraries/LibPDF/ColorSpace.cpp | 4 | ||||
-rw-r--r-- | Userland/Libraries/LibPDF/Document.cpp | 35 | ||||
-rw-r--r-- | Userland/Libraries/LibPDF/Document.h | 8 | ||||
-rw-r--r-- | Userland/Libraries/LibPDF/Parser.cpp | 86 | ||||
-rw-r--r-- | Userland/Libraries/LibPDF/Renderer.cpp | 21 | ||||
-rw-r--r-- | Userland/Libraries/LibPDF/Value.cpp | 67 | ||||
-rw-r--r-- | Userland/Libraries/LibPDF/Value.h | 150 |
7 files changed, 130 insertions, 241 deletions
diff --git a/Userland/Libraries/LibPDF/ColorSpace.cpp b/Userland/Libraries/LibPDF/ColorSpace.cpp index ccb487e20f..b290740a96 100644 --- a/Userland/Libraries/LibPDF/ColorSpace.cpp +++ b/Userland/Libraries/LibPDF/ColorSpace.cpp @@ -60,10 +60,10 @@ RefPtr<CalRGBColorSpace> CalRGBColorSpace::create(RefPtr<Document> document, Vec return {}; auto param = parameters[0]; - if (!param.is_object() || !param.as_object()->is_dict()) + if (!param.has<NonnullRefPtr<Object>>() || !param.get<NonnullRefPtr<Object>>()->is_dict()) return {}; - auto dict = object_cast<DictObject>(param.as_object()); + auto dict = object_cast<DictObject>(param.get<NonnullRefPtr<Object>>()); if (!dict->contains(CommonNames::WhitePoint)) return {}; diff --git a/Userland/Libraries/LibPDF/Document.cpp b/Userland/Libraries/LibPDF/Document.cpp index 3705ee30e4..b80b24b0f3 100644 --- a/Userland/Libraries/LibPDF/Document.cpp +++ b/Userland/Libraries/LibPDF/Document.cpp @@ -58,7 +58,7 @@ Document::Document(NonnullRefPtr<Parser> const& parser) Value Document::get_or_load_value(u32 index) { auto value = get_value(index); - if (value) + if (!value.has<Empty>()) // FIXME: Use Optional instead? return value; auto object = m_parser->parse_object_with_index(index); @@ -122,7 +122,7 @@ Page Document::get_page(u32 index) int rotate = 0; if (raw_page_object->contains(CommonNames::Rotate)) { - rotate = raw_page_object->get_value(CommonNames::Rotate).as_int(); + rotate = raw_page_object->get_value(CommonNames::Rotate).get<int>(); VERIFY(rotate % 90 == 0); } @@ -133,22 +133,22 @@ Page Document::get_page(u32 index) Value Document::resolve(Value const& value) { - if (value.is_ref()) { + if (value.has<Reference>()) { // FIXME: Surely indirect PDF objects can't contain another indirect PDF object, // right? Unsure from the spec, but if they can, these return values would have // to be wrapped with another resolve() call. return get_or_load_value(value.as_ref_index()); } - if (!value.is_object()) + if (!value.has<NonnullRefPtr<Object>>()) return value; - auto obj = value.as_object(); + auto& obj = value.get<NonnullRefPtr<Object>>(); if (obj->is_indirect_value()) return static_ptr_cast<IndirectValue>(obj)->value(); - return obj; + return value; } bool Document::build_page_tree() @@ -165,7 +165,7 @@ bool Document::add_page_tree_node_to_page_tree(NonnullRefPtr<DictObject> const& return false; auto kids_array = page_tree->get_array(this, CommonNames::Kids); - auto page_count = page_tree->get(CommonNames::Count).value().as_int(); + auto page_count = page_tree->get(CommonNames::Count).value().get<int>(); if (static_cast<size_t>(page_count) != kids_array->elements().size()) { // This page tree contains child page trees, so we recursively add @@ -213,7 +213,7 @@ void Document::build_outline() m_outline->children = move(children); if (outline_dict->contains(CommonNames::Count)) - m_outline->count = outline_dict->get_value(CommonNames::Count).as_int(); + m_outline->count = outline_dict->get_value(CommonNames::Count).get<int>(); } NonnullRefPtr<OutlineItem> Document::build_outline_item(NonnullRefPtr<DictObject> const& outline_item_dict) @@ -232,7 +232,7 @@ NonnullRefPtr<OutlineItem> Document::build_outline_item(NonnullRefPtr<DictObject outline_item->title = outline_item_dict->get_string(this, CommonNames::Title)->string(); if (outline_item_dict->contains(CommonNames::Count)) - outline_item->count = outline_item_dict->get_value(CommonNames::Count).as_int(); + outline_item->count = outline_item_dict->get_value(CommonNames::Count).get<int>(); if (outline_item_dict->contains(CommonNames::Dest)) { auto dest_arr = outline_item_dict->get_array(this, CommonNames::Dest); @@ -269,14 +269,14 @@ NonnullRefPtr<OutlineItem> Document::build_outline_item(NonnullRefPtr<DictObject if (outline_item_dict->contains(CommonNames::C)) { auto color_array = outline_item_dict->get_array(this, CommonNames::C); - auto r = static_cast<int>(255.0f * color_array->at(0).as_float()); - auto g = static_cast<int>(255.0f * color_array->at(1).as_float()); - auto b = static_cast<int>(255.0f * color_array->at(2).as_float()); + auto r = static_cast<int>(255.0f * color_array->at(0).get<float>()); + auto g = static_cast<int>(255.0f * color_array->at(1).get<float>()); + auto b = static_cast<int>(255.0f * color_array->at(2).get<float>()); outline_item->color = Color(r, g, b); } if (outline_item_dict->contains(CommonNames::F)) { - auto bitfield = outline_item_dict->get_value(CommonNames::F).as_int(); + auto bitfield = outline_item_dict->get_value(CommonNames::F).get<int>(); outline_item->italic = bitfield & 0x1; outline_item->bold = bitfield & 0x2; } @@ -286,12 +286,13 @@ NonnullRefPtr<OutlineItem> Document::build_outline_item(NonnullRefPtr<DictObject NonnullRefPtrVector<OutlineItem> Document::build_outline_item_chain(Value const& first_ref, Value const& last_ref) { - VERIFY(first_ref.is_ref()); - VERIFY(last_ref.is_ref()); + VERIFY(first_ref.has<Reference>()); + VERIFY(last_ref.has<Reference>()); NonnullRefPtrVector<OutlineItem> children; - auto first_dict = object_cast<DictObject>(get_or_load_value(first_ref.as_ref_index()).as_object()); + auto first_dict = object_cast<DictObject>( + get_or_load_value(first_ref.as_ref_index()).get<NonnullRefPtr<Object>>()); auto first = build_outline_item(first_dict); children.append(first); @@ -301,7 +302,7 @@ NonnullRefPtrVector<OutlineItem> Document::build_outline_item_chain(Value const& while (current_child_dict->contains(CommonNames::Next)) { auto next_child_dict_ref = current_child_dict->get_value(CommonNames::Next); current_child_index = next_child_dict_ref.as_ref_index(); - auto next_child_dict = object_cast<DictObject>(get_or_load_value(current_child_index).as_object()); + auto next_child_dict = object_cast<DictObject>(get_or_load_value(current_child_index).get<NonnullRefPtr<Object>>()); auto next_child = build_outline_item(next_child_dict); children.append(next_child); diff --git a/Userland/Libraries/LibPDF/Document.h b/Userland/Libraries/LibPDF/Document.h index 7a4fc14a6f..194b081e27 100644 --- a/Userland/Libraries/LibPDF/Document.h +++ b/Userland/Libraries/LibPDF/Document.h @@ -102,13 +102,13 @@ public: auto resolved = resolve(value); if constexpr (IsSame<T, bool>) - return resolved.as_bool(); + return resolved.get<bool>(); if constexpr (IsSame<T, int>) - return resolved.as_int(); + return resolved.get<int>(); if constexpr (IsSame<T, float>) - return resolved.as_float(); + return resolved.get<float>(); if constexpr (IsObject<T>) - return object_cast<T>(resolved.as_object()); + return object_cast<T>(resolved.get<NonnullRefPtr<Object>>()); VERIFY_NOT_REACHED(); } diff --git a/Userland/Libraries/LibPDF/Parser.cpp b/Userland/Libraries/LibPDF/Parser.cpp index d0c54afb2c..2242ac61ac 100644 --- a/Userland/Libraries/LibPDF/Parser.cpp +++ b/Userland/Libraries/LibPDF/Parser.cpp @@ -125,10 +125,10 @@ Parser::LinearizationResult Parser::initialize_linearization_dict() { // parse_header() is called immediately before this, so we are at the right location auto dict_value = m_document->resolve(parse_indirect_value()); - if (!dict_value || !dict_value.is_object()) + if (!dict_value.has<NonnullRefPtr<Object>>()) return LinearizationResult::Error; - auto dict_object = dict_value.as_object(); + auto dict_object = dict_value.get<NonnullRefPtr<Object>>(); if (!dict_object->is_dict()) return LinearizationResult::NotLinearized; @@ -149,16 +149,16 @@ Parser::LinearizationResult Parser::initialize_linearization_dict() auto first_page = dict->get(CommonNames::P).value_or({}); // Validation - if (!length_of_file.is_int_type<u32>() - || !hint_table.is_object() - || !first_page_object_number.is_int_type<u32>() - || !number_of_pages.is_int_type<u16>() - || !offset_of_main_xref_table.is_int_type<u32>() - || (first_page && !first_page.is_int_type<u32>())) { + if (!length_of_file.has_u32() + || !hint_table.has<NonnullRefPtr<Object>>() + || !first_page_object_number.has_u32() + || !number_of_pages.has_u16() + || !offset_of_main_xref_table.has_u32() + || (!first_page.has<Empty>() && !first_page.has_u32())) { return LinearizationResult::Error; } - auto hint_table_object = hint_table.as_object(); + auto hint_table_object = hint_table.get<NonnullRefPtr<Object>>(); if (!hint_table_object->is_array()) return LinearizationResult::Error; @@ -177,24 +177,24 @@ Parser::LinearizationResult Parser::initialize_linearization_dict() overflow_hint_stream_length = hint_table_array->at(3); } - if (!primary_hint_stream_offset.is_int_type<u32>() - || !primary_hint_stream_length.is_int_type<u32>() - || (overflow_hint_stream_offset && !overflow_hint_stream_offset.is_int_type<u32>()) - || (overflow_hint_stream_length && !overflow_hint_stream_length.is_int_type<u32>())) { + if (!primary_hint_stream_offset.has_u32() + || !primary_hint_stream_length.has_u32() + || (!overflow_hint_stream_offset.has<Empty>() && !overflow_hint_stream_offset.has_u32()) + || (!overflow_hint_stream_length.has<Empty>() && !overflow_hint_stream_length.has_u32())) { return LinearizationResult::Error; } m_linearization_dictionary = LinearizationDictionary { - length_of_file.as_int_type<u32>(), - primary_hint_stream_offset.as_int_type<u32>(), - primary_hint_stream_length.as_int_type<u32>(), - overflow_hint_stream_offset ? overflow_hint_stream_offset.as_int_type<u32>() : NumericLimits<u32>::max(), - overflow_hint_stream_length ? overflow_hint_stream_length.as_int_type<u32>() : NumericLimits<u32>::max(), - first_page_object_number.as_int_type<u32>(), - offset_of_first_page_end.as_int_type<u32>(), - number_of_pages.as_int_type<u16>(), - offset_of_main_xref_table.as_int_type<u32>(), - first_page ? first_page.as_int_type<u32>() : NumericLimits<u32>::max(), + length_of_file.get_u32(), + primary_hint_stream_offset.get_u32(), + primary_hint_stream_length.get_u32(), + overflow_hint_stream_offset.has<Empty>() ? NumericLimits<u32>::max() : overflow_hint_stream_offset.get_u32(), + overflow_hint_stream_length.has<Empty>() ? NumericLimits<u32>::max() : overflow_hint_stream_length.get_u32(), + first_page_object_number.get_u32(), + offset_of_first_page_end.get_u32(), + number_of_pages.get_u16(), + offset_of_main_xref_table.get_u32(), + first_page.has<Empty>() ? NumericLimits<u32>::max() : first_page.get_u32(), }; return LinearizationResult::Linearized; @@ -241,10 +241,10 @@ bool Parser::initialize_hint_tables() return {}; auto stream_value = stream_indirect_value->value(); - if (!stream_value.is_object()) + if (!stream_value.has<NonnullRefPtr<Object>>()) return {}; - auto stream_object = stream_value.as_object(); + auto stream_object = stream_value.get<NonnullRefPtr<Object>>(); if (!stream_object->is_stream()) return {}; @@ -310,9 +310,9 @@ bool Parser::initialize_non_linearized_xref_table() m_reader.set_reading_forwards(); auto xref_offset_value = parse_number(); - if (!xref_offset_value.is_int()) + if (!xref_offset_value.has<int>()) return false; - auto xref_offset = xref_offset_value.as_int(); + auto xref_offset = xref_offset_value.get<int>(); m_reader.move_to(xref_offset); m_xref_table = parse_xref_table(); @@ -339,9 +339,9 @@ RefPtr<XRefTable> Parser::parse_xref_table() Vector<XRefEntry> entries; auto starting_index_value = parse_number(); - auto starting_index = starting_index_value.as_int(); + auto starting_index = starting_index_value.get<int>(); auto object_count_value = parse_number(); - auto object_count = object_count_value.as_int(); + auto object_count = object_count_value.get<int>(); for (int i = 0; i < object_count; i++) { auto offset_string = String(m_reader.bytes().slice(m_reader.offset(), 10)); @@ -603,7 +603,7 @@ Value Parser::parse_value() if (m_reader.matches("null")) { m_reader.move_by(4); consume_whitespace(); - return Value(Value::NullTag {}); + return Value(nullptr); } if (m_reader.matches("true")) { @@ -646,12 +646,12 @@ Value Parser::parse_value() Value Parser::parse_possible_indirect_value_or_ref() { auto first_number = parse_number(); - if (!first_number.is_int() || !matches_number()) + if (!first_number.has<int>() || !matches_number()) return first_number; m_reader.save(); auto second_number = parse_number(); - if (!second_number.is_int()) { + if (!second_number.has<int>()) { m_reader.load(); return first_number; } @@ -660,12 +660,12 @@ Value Parser::parse_possible_indirect_value_or_ref() m_reader.discard(); consume(); consume_whitespace(); - return Value(Reference(first_number.as_int(), second_number.as_int())); + return Value(Reference(first_number.get<int>(), second_number.get<int>())); } if (m_reader.matches("obj")) { m_reader.discard(); - return parse_indirect_value(first_number.as_int(), second_number.as_int()); + return parse_indirect_value(first_number.get<int>(), second_number.get<int>()); } m_reader.load(); @@ -692,12 +692,12 @@ RefPtr<IndirectValue> Parser::parse_indirect_value(int index, int generation) RefPtr<IndirectValue> Parser::parse_indirect_value() { auto first_number = parse_number(); - if (!first_number.is_int()) + if (!first_number.has<int>()) return {}; auto second_number = parse_number(); - if (!second_number.is_int()) + if (!second_number.has<int>()) return {}; - return parse_indirect_value(first_number.as_int(), second_number.as_int()); + return parse_indirect_value(first_number.get<int>(), second_number.get<int>()); } Value Parser::parse_number() @@ -928,7 +928,7 @@ RefPtr<ArrayObject> Parser::parse_array() while (!m_reader.matches(']')) { auto value = parse_value(); - if (!value) + if (value.has<Empty>()) return {}; values.append(value); } @@ -954,7 +954,7 @@ RefPtr<DictObject> Parser::parse_dict() if (!name) return {}; auto value = parse_value(); - if (!value) + if (value.has<Empty>()) return {}; map.set(name->name(), value); } @@ -1004,14 +1004,14 @@ RefPtr<DictObject> Parser::conditionally_parse_page_tree_node(u32 object_index, return {}; } auto value = parse_value(); - if (!value) { + if (value.has<Empty>()) { ok = false; return {}; } if (name_string == CommonNames::Type) { - if (!value.is_object()) + if (!value.has<NonnullRefPtr<Object>>()) return {}; - auto type_object = value.as_object(); + auto type_object = value.get<NonnullRefPtr<Object>>(); if (!type_object->is_name()) return {}; auto type_name = object_cast<NameObject>(type_object); @@ -1039,7 +1039,7 @@ RefPtr<StreamObject> Parser::parse_stream(NonnullRefPtr<DictObject> dict) ReadonlyBytes bytes; auto maybe_length = dict->get(CommonNames::Length); - if (maybe_length.has_value() && (!maybe_length->is_ref() || m_xref_table)) { + if (maybe_length.has_value() && (!maybe_length->has<Reference>() || m_xref_table)) { // The PDF writer has kindly provided us with the direct length of the stream m_reader.save(); auto length = m_document->resolve_to<int>(maybe_length.value()); diff --git a/Userland/Libraries/LibPDF/Renderer.cpp b/Userland/Libraries/LibPDF/Renderer.cpp index cacb122f38..016663995f 100644 --- a/Userland/Libraries/LibPDF/Renderer.cpp +++ b/Userland/Libraries/LibPDF/Renderer.cpp @@ -132,12 +132,12 @@ RENDERER_HANDLER(set_line_width) RENDERER_HANDLER(set_line_cap) { - state().line_cap_style = static_cast<LineCapStyle>(args[0].as_int()); + state().line_cap_style = static_cast<LineCapStyle>(args[0].get<int>()); } RENDERER_HANDLER(set_line_join) { - state().line_join_style = static_cast<LineJoinStyle>(args[0].as_int()); + state().line_join_style = static_cast<LineJoinStyle>(args[0].get<int>()); } RENDERER_HANDLER(set_miter_limit) @@ -150,8 +150,8 @@ RENDERER_HANDLER(set_dash_pattern) auto dash_array = m_document->resolve_to<ArrayObject>(args[0]); Vector<int> pattern; for (auto& element : *dash_array) - pattern.append(element.as_int()); - state().line_dash_pattern = LineDashPattern { pattern, args[1].as_int() }; + pattern.append(element.get<int>()); + state().line_dash_pattern = LineDashPattern { pattern, args[1].get<int>() }; } RENDERER_TODO(set_color_rendering_intent); @@ -335,7 +335,7 @@ RENDERER_HANDLER(text_set_font) RENDERER_HANDLER(text_set_rendering_mode) { - text_state().rendering_mode = static_cast<TextRenderingMode>(args[0].as_int()); + text_state().rendering_mode = static_cast<TextRenderingMode>(args[0].get<int>()); } RENDERER_HANDLER(text_set_rise) @@ -398,11 +398,12 @@ RENDERER_HANDLER(text_show_string_array) float next_shift = 0.0f; for (auto& element : elements) { - if (element.is_number()) { - next_shift = element.to_float(); + if (element.has<int>()) { + next_shift = element.get<int>(); + } else if (element.has<float>()) { + next_shift = element.get<float>(); } else { - VERIFY(element.is_object()); - auto obj = element.as_object(); + auto& obj = element.get<NonnullRefPtr<Object>>(); VERIFY(obj->is_string()); auto str = object_cast<StringObject>(obj)->string(); show_text(str, next_shift); @@ -568,7 +569,7 @@ void Renderer::show_text(String const& string, float shift) RefPtr<ColorSpace> Renderer::get_color_space(Value const& value) { - auto name = object_cast<NameObject>(value.as_object())->name(); + auto name = object_cast<NameObject>(value.get<NonnullRefPtr<Object>>())->name(); // Simple color spaces with no parameters, which can be specified directly if (name == CommonNames::DeviceGray) diff --git a/Userland/Libraries/LibPDF/Value.cpp b/Userland/Libraries/LibPDF/Value.cpp index 63a699c295..7af1c1d7ea 100644 --- a/Userland/Libraries/LibPDF/Value.cpp +++ b/Userland/Libraries/LibPDF/Value.cpp @@ -9,52 +9,31 @@ namespace PDF { -Value& Value::operator=(Value const& other) -{ - m_type = other.m_type; - switch (m_type) { - case Type::Empty: - case Type::Null: - break; - case Type::Bool: - m_as_bool = other.m_as_bool; - break; - case Type::Int: - m_as_int = other.m_as_int; - break; - case Type::Float: - m_as_float = other.m_as_float; - break; - case Type::Ref: - m_as_ref = other.m_as_ref; - break; - case Type::Object: - m_as_object = other.m_as_object; - break; - } - return *this; -} - String Value::to_string(int indent) const { - switch (m_type) { - case Type::Empty: - return "<empty>"; - case Type::Null: - return "null"; - case Type::Bool: - return as_bool() ? "true" : "false"; - case Type::Int: - return String::number(as_int()); - case Type::Float: - return String::number(as_float()); - case Type::Ref: - return String::formatted("{} {} R", as_ref_index(), as_ref_generation_index()); - case Type::Object: - return as_object()->to_string(indent); - } - - VERIFY_NOT_REACHED(); + return visit( + [&](Empty const&) -> String { + // Return type deduction means that we can't use implicit conversions. + return "<empty>"; + }, + [&](std::nullptr_t const&) -> String { + return "null"; + }, + [&](bool const& b) -> String { + return b ? "true" : "false"; + }, + [&](int const& i) { + return String::number(i); + }, + [&](float const& f) { + return String::number(f); + }, + [&](Reference const& ref) { + return String::formatted("{} {} R", ref.as_ref_index(), ref.as_ref_generation_index()); + }, + [&](NonnullRefPtr<Object> const& object) { + return object->to_string(indent); + }); } } diff --git a/Userland/Libraries/LibPDF/Value.h b/Userland/Libraries/LibPDF/Value.h index e0e3e740c0..66db482bf1 100644 --- a/Userland/Libraries/LibPDF/Value.h +++ b/Userland/Libraries/LibPDF/Value.h @@ -9,171 +9,79 @@ #include <AK/Format.h> #include <AK/RefPtr.h> #include <AK/String.h> +#include <AK/Variant.h> #include <LibPDF/Forward.h> #include <LibPDF/Object.h> #include <LibPDF/Reference.h> namespace PDF { -class Value { +class Value : public Variant<Empty, std::nullptr_t, bool, int, float, Reference, NonnullRefPtr<Object>> { public: - Value() - : m_type(Type::Empty) - { - } - - struct NullTag { - }; - - Value(NullTag) - : m_type(Type::Null) - { - } - - Value(bool b) - : m_type(Type::Bool) - { - m_as_bool = b; - } - - Value(int i) - : m_type(Type::Int) - { - m_as_int = i; - } - - Value(float f) - : m_type(Type::Float) - { - m_as_float = f; - } - - Value(Reference ref) - : m_type(Type::Ref) - { - m_as_ref = ref; - } + using Variant::Variant; - template<IsObject T> - Value(RefPtr<T> obj) - : m_type(obj ? Type::Object : Type::Empty) + Value() + : Variant(Empty()) { - if (obj) { - m_as_object = obj; - } } template<IsObject T> - Value(NonnullRefPtr<T> obj) - : m_type(Type::Object) + Value(RefPtr<T> const& refptr) + : Variant(nullptr) { - m_as_object = obj; + if (refptr) + set<NonnullRefPtr<Object>>(*refptr); } - Value(Value const& other) - { - *this = other; - } - - ~Value() = default; - - Value& operator=(Value const& other); + [[nodiscard]] String to_string(int indent = 0) const; - [[nodiscard]] ALWAYS_INLINE bool is_empty() const { return m_type == Type::Empty; } - [[nodiscard]] ALWAYS_INLINE bool is_null() const { return m_type == Type::Null; } - [[nodiscard]] ALWAYS_INLINE bool is_bool() const { return m_type == Type::Bool; } - [[nodiscard]] ALWAYS_INLINE bool is_int() const { return m_type == Type::Int; } - [[nodiscard]] ALWAYS_INLINE bool is_float() const { return m_type == Type::Float; } - [[nodiscard]] ALWAYS_INLINE bool is_number() const { return is_int() || is_float(); } - [[nodiscard]] ALWAYS_INLINE bool is_ref() const { return m_type == Type::Ref; } - [[nodiscard]] ALWAYS_INLINE bool is_object() const { return m_type == Type::Object; } + [[nodiscard]] ALWAYS_INLINE bool has_number() const { return has<int>() || has<float>(); } - [[nodiscard]] ALWAYS_INLINE bool as_bool() const + [[nodiscard]] ALWAYS_INLINE bool has_u32() const { - VERIFY(is_bool()); - return m_as_bool; + return has<int>() && get<int>() >= 0; } - [[nodiscard]] ALWAYS_INLINE int as_int() const + [[nodiscard]] ALWAYS_INLINE bool has_u16() const { - VERIFY(is_int()); - return m_as_int; + return has<int>() && get<int>() >= 0 && get<int>() < 65536; } - template<typename T> - [[nodiscard]] ALWAYS_INLINE bool is_int_type() const + [[nodiscard]] ALWAYS_INLINE u32 get_u32() const { - if (!is_int()) - return false; - auto as_int = static_cast<T>(m_as_int); - return as_int >= NumericLimits<T>::min() && as_int <= NumericLimits<T>::max(); + VERIFY(has_u32()); + return get<int>(); } - template<typename T> - [[nodiscard]] ALWAYS_INLINE T as_int_type() const + [[nodiscard]] ALWAYS_INLINE u16 get_u16() const { - VERIFY(is_int_type<T>()); - return static_cast<T>(m_as_int); + VERIFY(has_u16()); + return get<int>(); } [[nodiscard]] ALWAYS_INLINE int to_int() const { - if (is_int()) - return as_int(); - return static_cast<int>(as_float()); - } - - [[nodiscard]] ALWAYS_INLINE float as_float() const - { - VERIFY(is_float()); - return m_as_float; + if (has<int>()) + return get<int>(); + return static_cast<int>(get<float>()); } [[nodiscard]] ALWAYS_INLINE float to_float() const { - if (is_float()) - return as_float(); - return static_cast<float>(as_int()); + if (has<float>()) + return get<float>(); + return static_cast<float>(get<int>()); } [[nodiscard]] ALWAYS_INLINE u32 as_ref_index() const { - VERIFY(is_ref()); - return m_as_ref.as_ref_index(); + return get<Reference>().as_ref_index(); } [[nodiscard]] ALWAYS_INLINE u32 as_ref_generation_index() const { - VERIFY(is_ref()); - return m_as_ref.as_ref_generation_index(); + return get<Reference>().as_ref_generation_index(); } - - [[nodiscard]] ALWAYS_INLINE NonnullRefPtr<Object> as_object() const { return *m_as_object; } - - [[nodiscard]] ALWAYS_INLINE explicit operator bool() const { return !is_empty(); } - - [[nodiscard]] String to_string(int indent = 0) const; - -private: - enum class Type { - Empty, - Null, - Bool, - Int, - Float, - Ref, - Object, - }; - - union { - bool m_as_bool; - int m_as_int; - Reference m_as_ref; - float m_as_float; - }; - - RefPtr<Object> m_as_object; - Type m_type; }; } |