Loading...
Searching...
No Matches
Path.hpp
1#pragma once
2#include <score/document/DocumentInterface.hpp>
3#include <score/tools/Metadata.hpp>
4
8template <typename T, typename U>
10{
11 static const constexpr bool value
12 = std::is_base_of<T, U>::value || std::is_base_of<U, T>::value;
13};
14
15// These forward declarations are required
16// because Path<T>(Object&) calls score::IDocument::path()
17// which in turns calls another constructor of Path<T>.
18template <typename Object>
19class Path;
20template <typename T>
22
23namespace score
24{
25class DocumentPlugin;
26namespace IDocument
27{
28template <typename T>
29Path<T> path(const IdentifiedObject<T>& obj);
30}
31}
32
50template <typename Object>
51class Path
52{
53 friend bool operator==(const Path& lhs, const Path& rhs) noexcept
54 {
55 return lhs.m_impl == rhs.m_impl;
56 }
57
58 friend bool operator!=(const Path& lhs, const Path& rhs) noexcept
59 {
60 return lhs.m_impl != rhs.m_impl;
61 }
62
63 friend uint qHash(const Path& obj, uint seed) noexcept
64 {
65 return qHash(obj.m_impl, seed);
66 }
67
68 template <typename U>
69 friend class Path;
70 friend class ObjectPath;
71
72public:
79 {
80 UnsafeDynamicCreation() = default;
81 };
82
83 Path(const ObjectPath& obj, UnsafeDynamicCreation) noexcept
84 : m_impl{obj.vec()}
85 {
86 }
87 Path(ObjectPath&& obj, UnsafeDynamicCreation) noexcept
88 : m_impl{std::move(obj.vec())}
89 {
90 }
91
92 Path(const Object& obj) noexcept
93 : Path(score::IDocument::path(obj))
94 {
95 }
96
97 ~Path() = default;
98
100 template <typename U>
101 auto extend(const QString& name, const Id<U>& id) const& noexcept
102 {
103 Path<U> p{this->m_impl.vec()};
104 p.m_impl.vec().push_back({name, id});
105 return p;
106 }
107
110 template <typename U>
111 auto extend(const QString& name, const Id<U>& id) && noexcept
112 {
113 Path<U> p{std::move(this->m_impl.vec())};
114 p.m_impl.vec().push_back({name, id});
115 return p;
116 }
117
119 template <typename U>
120 auto extend(const Id<U>& id) const& noexcept
121 {
122 Path<U> p{this->m_impl.vec()};
123 p.m_impl.vec().push_back({Metadata<ObjectKey_k, U>::get(), id});
124 return p;
125 }
126
129 template <typename U>
130 auto extend(const Id<U>& id) && noexcept
131 {
132 Path<U> p{std::move(this->m_impl.vec())};
133 p.m_impl.vec().push_back({Metadata<ObjectKey_k, U>::get(), id});
134 return p;
135 }
136
138 template <typename U>
139 auto splitLast() const&
140 {
141 SCORE_ASSERT(m_impl.vec().size() > 0);
142 auto vec = m_impl.vec();
143 auto last = vec.back();
144 vec.pop_back();
145 return std::make_pair(Path<U>{std::move(vec)}, std::move(last));
146 }
147
150 template <typename U>
151 auto splitLast() &&
152 {
153 // Note : we *must not* move directly m_impl
154 // because it carries a cache that becomes wrong.
155 SCORE_ASSERT(!m_impl.vec().empty());
156 auto last = m_impl.vec().back();
157 m_impl.vec().pop_back();
158 return std::make_pair(Path<U>{std::move(m_impl.vec())}, std::move(last));
159 }
160
161 // TODO do the same for ids
162 // TODO make it work only for upcasts
163 template <typename U>
165 Path(const Path<U>& other) noexcept
166 : m_impl{other.m_impl.vec()}
167 {
168 }
169
170 template <typename U>
172 Path(Path<U>&& other) noexcept
173 : m_impl{std::move(other.m_impl.vec())}
174 {
175 }
176
177 template <typename U>
179 Path& operator=(const Path<U>& other) noexcept
180 {
181 m_impl = other.m_impl;
182 return *this;
183 }
184
185 template <typename U>
187 Path& operator=(Path<U>&& other) noexcept
188 {
189 m_impl = std::move(other.m_impl);
190 return *this;
191 }
192
193 Path() noexcept = default;
194 Path(const Path&) noexcept = default;
195 Path(Path&&) noexcept = default;
196 Path& operator=(const Path&) noexcept = default;
197 Path& operator=(Path&&) noexcept = default;
198
199 Object& find(const score::DocumentContext& ctx) const
200 {
201 SCORE_ASSERT(valid());
202 return m_impl.find<Object>(ctx);
203 }
204 Object* try_find(const score::DocumentContext& ctx) const noexcept
205 {
206 if(!valid())
207 return nullptr;
208 return m_impl.try_find<Object>(ctx);
209 }
210
211 const auto& unsafePath() const& noexcept { return m_impl; }
212 auto& unsafePath() & noexcept { return m_impl; }
213 auto&& unsafePath() && noexcept { return std::move(m_impl); }
214
215 bool valid() const noexcept { return !m_impl.vec().empty(); }
216
217private:
218 Path(const ObjectPath& path) noexcept
219 : m_impl{path.vec()}
220 {
221 }
222 Path(ObjectPath&& path) noexcept
223 : m_impl{std::move(path.vec())}
224 {
225 }
226 Path(const std::vector<ObjectIdentifier>& vec) noexcept
227 : m_impl{vec}
228 {
229 }
230 Path(std::vector<ObjectIdentifier>&& vec) noexcept
231 : m_impl{std::move(vec)}
232 {
233 }
234
235 ObjectPath m_impl;
236};
237
238template <typename T>
239Path<T> make_path(const T& t)
240{
241 return t;
242}
243namespace std
244{
245template <typename tag>
246struct hash<Path<tag>>
247{
248 std::size_t operator()(const Path<tag>& path) const
249 {
250 return std::hash<ObjectPath>{}(path.unsafePath());
251 }
252};
253}
254
255namespace score
256{
257template <typename T>
258auto id(const Path<T>& path)
259{
260 SCORE_ASSERT(path.valid());
261 SCORE_ASSERT(bool(path.unsafePath().vec().back().id()));
262
263 return Id<T>(path.unsafePath().vec().back().id());
264}
265}
The IdentifiedObject class.
Definition IdentifiedObject.hpp:19
The ObjectPath class.
Definition ObjectPath.hpp:37
T * try_find(const score::DocumentContext &ctx) const noexcept
Tries to find an object.
Definition ObjectPath.hpp:131
T & find(const score::DocumentContext &ctx) const
find the object described by the ObjectPath
Definition ObjectPath.hpp:110
The Path class is a typesafe wrapper around ObjectPath.
Definition Path.hpp:52
auto extend(const QString &name, const Id< U > &id) &&noexcept
Definition Path.hpp:111
auto splitLast() &&
Definition Path.hpp:151
auto extend(const Id< U > &id) &&noexcept
Definition Path.hpp:130
auto splitLast() const &
Return a new path without the last element of this one.
Definition Path.hpp:139
auto extend(const QString &name, const Id< U > &id) const &noexcept
Add a new ObjectIdentifier at the end of the path and return a new path.
Definition Path.hpp:101
auto extend(const Id< U > &id) const &noexcept
Add a new ObjectIdentifier at the end of the path and return a new path.
Definition Path.hpp:120
The id_base_t class.
Definition Identifier.hpp:57
Base toolkit upon which the software is built.
Definition Application.cpp:97
STL namespace.
Static metadata implementation.
Definition lib/score/tools/Metadata.hpp:36
Use this if it is not possible to get a path.
Definition Path.hpp:79
Used to know if two types are in an inheritance relationship.
Definition Path.hpp:10
Definition DocumentContext.hpp:18