Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-Studio-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 : #pragma once
23 :
24 : #include "log.h"
25 :
26 : namespace mu::engraving {
27 : #define DECLARE_CLASSOF(Type) \
28 : public: \
29 : static bool classof(const ElementType type) noexcept { return type == Type; } \
30 : static bool classof(const EngravingObject * item) noexcept { return item->type() == Type; } \
31 :
32 : template<typename To, typename From>
33 : bool is_classof(From* p) noexcept
34 : {
35 : using ResultType = std::remove_pointer_t<To>;
36 : return p ? ResultType::classof(p) : false;
37 : }
38 :
39 : enum class CastMode {
40 : CHECK = 0, // should be correct; assert if still not
41 : BAD, // known to be bad; don’t assert, we’ll fix it later
42 : MAYBE_BAD // in this case it’s okay if type mismatch
43 : };
44 :
45 : template<typename To, typename From>
46 867107 : To item_cast(From from, CastMode mode = CastMode::CHECK) noexcept
47 : {
48 : if constexpr (std::is_same_v<From, void>) {
49 : return static_cast<To>(from);
50 : } else {
51 867107 : To casted = dynamic_cast<To>(from);
52 867107 : if (mode == CastMode::CHECK) {
53 413131 : if (!(casted || !from)) {
54 0 : LOGE() << "[BAD CAST] from: " << typeid(From).name() << ", to: " << typeid(To).name();
55 : }
56 413131 : assert(casted || !from);
57 : }
58 867107 : return casted;
59 : }
60 : }
61 : }
62 :
63 : namespace mu::engraving::rtti {
64 : /* ===============================================
65 : This visitor to foreaching the list of given types
66 : How to use:
67 : 1. Make types list:
68 : using SomeTypeList = TypeList<ItemA, ItemB>;
69 :
70 : 2. Create subclass like this, and implement the `doVisit` method:
71 : class FooVisitor : public rtti::Visitor<FooVisitor>
72 : {
73 : public:
74 : template<typename T>
75 : static bool doVisit(EngravingItem* item, ...)
76 : {
77 : if (T::classof(item)) {
78 : ...
79 : return true;
80 : }
81 : return false;
82 : }
83 : };
84 :
85 : 3. Call the `visit` method:
86 :
87 : FooVisitor::visit(SomeTypeList {}, item, ...);
88 :
89 : */
90 :
91 : template<typename ... Types> struct TypeList {};
92 :
93 : template<typename Impl>
94 : class Visitor
95 : {
96 : public:
97 : enum Policy {
98 : MayBeNotFound = 0,
99 : ShouldBeFound
100 : };
101 :
102 : template<typename ... Types, typename ... Args >
103 8831 : static bool visit(TypeList<Types...> types, Args&& ... args)
104 : {
105 8831 : return visit(Policy::MayBeNotFound, types, std::forward<Args>(args)...);
106 : }
107 :
108 : template<typename ... Types, typename ... Args >
109 8831 : static bool visit(Policy policy, TypeList<Types...> types, Args&& ... args)
110 : {
111 8831 : bool found = visit_helper(types, std::forward<Args>(args)...);
112 8831 : if (policy == Policy::ShouldBeFound) {
113 0 : DO_ASSERT(found);
114 : }
115 8831 : return found;
116 : }
117 :
118 : private:
119 : template<typename ... Args>
120 1059 : static bool visit_helper(TypeList<>, Args&&...) { return false; }
121 :
122 : template<class Head, class ... Tail, typename ... Args>
123 139692 : static bool visit_helper(TypeList<Head, Tail...>, Args&& ... args)
124 : {
125 139692 : bool found = Impl::template doVisit<Head>(args ...);
126 139692 : if (!found) {
127 131920 : found = visit_helper(TypeList<Tail...> {}, std::forward<Args>(args)...);
128 : }
129 139692 : return found;
130 : }
131 : };
132 : }
|