Serenity Operating System
1/*
2 * Copyright (c) 2021-2022, Matthew Olsson <mattco@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#pragma once
8
9#include <AK/Debug.h>
10#include <AK/DeprecatedFlyString.h>
11#include <AK/Format.h>
12#include <AK/RefCounted.h>
13#include <AK/SourceLocation.h>
14#include <LibPDF/Error.h>
15#include <LibPDF/Forward.h>
16
17#ifdef PDF_DEBUG
18namespace {
19
20template<PDF::IsObject T>
21char const* object_name()
22{
23# define ENUMERATE_TYPE(class_name, snake_name) \
24 if constexpr (IsSame<PDF::class_name, T>) { \
25 return #class_name; \
26 }
27 ENUMERATE_OBJECT_TYPES(ENUMERATE_TYPE)
28# undef ENUMERATE_TYPE
29
30 VERIFY_NOT_REACHED();
31}
32
33}
34#endif
35
36namespace PDF {
37
38class Object : public RefCounted<Object> {
39public:
40 virtual ~Object() = default;
41
42 [[nodiscard]] ALWAYS_INLINE u32 generation_index() const { return m_generation_index; }
43 ALWAYS_INLINE void set_generation_index(u32 generation_index) { m_generation_index = generation_index; }
44
45 template<IsObject T>
46 bool is() const
47 requires(!IsSame<T, Object>)
48 {
49#define ENUMERATE_TYPE(class_name, snake_name) \
50 if constexpr (IsSame<class_name, T>) { \
51 return is_##snake_name(); \
52 }
53 ENUMERATE_OBJECT_TYPES(ENUMERATE_TYPE)
54#undef ENUMERATE_TYPE
55
56 VERIFY_NOT_REACHED();
57 }
58
59 template<IsObject T>
60 [[nodiscard]] ALWAYS_INLINE NonnullRefPtr<T> cast(
61#ifdef PDF_DEBUG
62 SourceLocation loc = SourceLocation::current()
63#endif
64 )
65 requires(!IsSame<T, Object>)
66 {
67#ifdef PDF_DEBUG
68 if (!is<T>()) {
69 dbgln("{} invalid cast from {} to {}", loc, type_name(), object_name<T>());
70 VERIFY_NOT_REACHED();
71 }
72#endif
73
74 return NonnullRefPtr<T>(static_cast<T&>(*this));
75 }
76
77 virtual char const* type_name() const = 0;
78 virtual DeprecatedString to_deprecated_string(int indent) const = 0;
79
80protected:
81#define ENUMERATE_TYPE(_, name) \
82 virtual bool is_##name() const \
83 { \
84 return false; \
85 }
86 ENUMERATE_OBJECT_TYPES(ENUMERATE_TYPE)
87#undef ENUMERATE_TYPE
88
89private:
90 u32 m_generation_index { 0 };
91};
92
93}
94
95namespace AK {
96
97template<PDF::IsObject T>
98struct Formatter<T> : Formatter<StringView> {
99 ErrorOr<void> format(FormatBuilder& builder, T const& object)
100 {
101 return Formatter<StringView>::format(builder, object.to_deprecated_string(0));
102 }
103};
104
105template<PDF::IsObject T>
106struct Formatter<NonnullRefPtr<T>> : Formatter<T> {
107 ErrorOr<void> format(FormatBuilder& builder, NonnullRefPtr<T> const& object)
108 {
109 return Formatter<T>::format(builder, *object);
110 }
111};
112
113}