Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
scope-path.cpp
Go to the documentation of this file.
1/*
2 ScopePath - logical access path down from Session root
3
4 Copyright (C)
5 2009, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12* *****************************************************************/
13
14
21#include "include/logging.h"
26#include "lib/itertools.hpp"
27#include "lib/symbol.hpp"
28#include "lib/error.hpp"
29#include "lib/util.hpp"
30
31#include <algorithm>
32
33namespace steam {
34namespace mobject {
35namespace session {
36
37 using std::reverse;
38 using lib::append_all;
40 using util::isnil;
41
42
43 namespace { // Helpers and shortcuts....
44
49 {
50 return ScopeLocator::instance().getRawPath (leaf);
51 }
52
53
54 void
55 ___check_notBottom (const ScopePath *path, lib::Literal operation_descr)
56 {
57 REQUIRE (path);
58 if (path->empty())
59 throw error::Logic (operation_descr+" an empty placement scope path"
60 , LERR_(EMPTY_SCOPE_PATH));
61 }
62 }//(End) helpers
63
64
65
66
75 : refcount_(0)
76 , path_()
77 {
78 clear();
79 }
80
81
93 : refcount_(0)
94 , path_()
95 {
96 if (leaf == Scope::INVALID) return; // invalid leaf defines invalid path....
97
98 clear();
99 navigate (leaf);
100 }
101
102
104 : refcount_(0)
105 , path_(o.path_)
106 { }
107
112 ScopePath&
114 {
115 if (0 < refcount_)
116 throw error::Logic ("Attempt to overwrite a ScopePath with nonzero refcount");
117
118 if (!isSameObject (*this, ref))
119 {
120 path_ = ref.path_;
121 ENSURE (0 == refcount_);
122 }
123 return *this;
124 }
125
126
128 {
129 WARN_IF (refcount_, session, "Destroying a scope path frame with ref-count=%zu", refcount_);
130 }
131
132
135
136
141 ScopePath::operator string() const
142 {
143 if (isnil (path_)) return "!";
144 if (1 == length()) return "/";
145
146 string res;
147 vector<Scope>::const_iterator node (path_.begin());
148 while (++node != path_.end())
149 {
150 res += "/";
151 res += string (*node);
152 }
153 return res;
154 }
155
156
160 bool
162 {
163 return (1 < length())
164#if NOBUG_MODE_ALPHA
165 and hasValidRoot()
166#endif
167 ;
168 }
169
170 bool
172 {
173 REQUIRE (0 < length());
174 return path_[0] == currModelRoot();
175 }
176
177 PlacementMO const&
182
183
184
185
186
187 /* == Relations == */
188
189 Scope const&
191 {
192 ___check_notBottom (this, "Inspecting");
193 return path_.back();
194 }
195
196
202 bool
203 ScopePath::endsAt(Scope const& aScope) const
204 {
205 return aScope == getLeaf();
206 }
207
208
209 bool
210 ScopePath::contains (Scope const& aScope) const
211 {
212 if (aScope == Scope::INVALID) return true; // bottom is contained everywhere
213
214 for (iterator ii = this->begin(); ii; ++ii)
215 if (aScope == *ii)
216 return true;
217
218 return false;
219 }
220
221
222 bool
223 ScopePath::contains (ScopePath const& otherPath) const
224 {
225 if (!otherPath.isValid()) return true;
226 if ( empty()) return false;
227 if (!isValid()) return false;
228
229 ASSERT (1 < length());
230 ASSERT (1 < otherPath.length());
231
232 for (iterator ii = otherPath.begin(); ii; ++ii)
233 if (!this->contains (*ii))
234 return false;
235
236 return true;
237 }
238
239
241 commonPrefix (ScopePath const& path1, ScopePath const& path2)
242 {
244 uint len = std::min (path1.length(), path2.length());
245 for (uint pos = 0; pos<len; ++pos)
246 if (path1.path_[pos] == path2.path_[pos])
247 prefix.appendScope (path1.path_[pos]);
248
249 return prefix;
250 }
251
252 bool
253 disjoint (ScopePath const& path1, ScopePath const& path2)
254 {
255 if (path1.empty() or path2.empty()) return false;
256
257 return (path1.isValid() and path2.isValid())
258 and (path1.path_[1] != path2.path_[1]) // no common prefix
259 ;
260 }
261
262
263
264
265 /* == Mutations == */
266
267 void
269 {
270 path_.clear();
271 path_.push_back (currModelRoot());
272
273 ENSURE (!empty());
274 ENSURE (!isValid());
275 ENSURE ( hasValidRoot());
276 }
277
278
279 Scope const&
281 {
282 ___check_notBottom (this, "Navigating");
283
284 path_.resize (length()-1);
285
286 if (empty()) return Scope::INVALID;
287 else return path_.back();
288 }
289
290
291 Scope const&
293 {
294 ___check_notBottom (this, "Navigating");
295 ENSURE (hasValidRoot());
296
297 path_.resize (1);
298 return path_.back();
299 }
300
301
302 void
304 {
305 ___check_notBottom (this, "Navigating");
306 if (!target.isValid())
307 throw error::Invalid ("can't navigate to a target scope outside the model"
308 , LERR_(INVALID_SCOPE));
309
310 std::vector<Scope> otherPath;
311 append_all (discoverScopePath(target), otherPath);
312 reverse (otherPath.begin(), otherPath.end());
314 ASSERT (path_[0] == otherPath[0]); // sharing the root element
315 this->path_ = otherPath; // TODO really relate the two paths, including a treatment for meta-clips
316 // - if both are in the same sequence (same head element): just attach the tail of the other
317 // - if the other path points into a sequence which is attached as meta-clip to the current sequence,
318 // then attach the other path below that meta-clip (problem: resolve multiple attachments)
319 // - otherwise use the first timeline, to which the other path's sequence is attached
320 // - otherwise, if all else fails, use the raw otherPath
321 }
322
323
324 void
326 {
327 path_.push_back (child);
328 }
329
330
331
332
333
334}}} // namespace mobject::session
Inline string literal.
Definition symbol.hpp:78
Accessing a STL element range through a Lumiera forward iterator, An instance of this iterator adapte...
static lib::Depend< ScopeLocator > instance
Storage holding the single ScopeLocator instance.
Sequence of nested scopes within the high-level model.
bool endsAt(Scope const &) const
verify the scope in question is equivalent to our leaf scope.
static const ScopePath INVALID
constant invalid path token.
PlacementMO const & currModelRoot() const
ScopePath & operator=(ScopePath const &)
Copy from existing path.
bool isValid() const
a valid path consists of more than just the root element.
bool empty() const
an empty path doesn't even contain a root element.
bool contains(Scope const &) const
ScopePath()
Create an empty path.
A Placement scope within the high-level-model.
Definition scope.hpp:70
bool isValid() const
check if this scope can be located.
Definition scope.cpp:231
static const Scope INVALID
constant invalid scope token.
Definition scope.hpp:83
Lumiera error handling (C++ interface).
#define LERR_(_NAME_)
Definition error.hpp:45
unsigned int uint
Definition integral.hpp:29
Helpers for working with iterators based on the pipeline model.
This header is for including and configuring NoBug.
Core abstraction of the Session model: a media object.
void append_all(IT iter, CON &container)
LumieraError< LERR_(LOGIC)> Logic
Definition error.hpp:207
LumieraError< LERR_(INVALID)> Invalid
Definition error.hpp:211
ScopeQuery< MObject >::iterator discoverScopePath(Scope const &leaf)
issue a query to discover the (raw) path to root, starting with the given scope
Namespace of Session and user visible high-level objects.
Definition sequence.hpp:65
bool disjoint(ScopePath const &path1, ScopePath const &path2)
ScopePath commonPrefix(ScopePath const &path1, ScopePath const &path2)
Steam-Layer implementation namespace root.
bool isSameObject(A const &a, B const &b)
compare plain object identity, based directly on the referee's memory identities.
Definition util.hpp:421
bool isnil(lib::time::Duration const &dur)
Service to build the notion of a current location within the Sesison model.
An Object representing a sequence of nested scopes within the Session.
Implementation level session API: query a scope.
Marker types to indicate a literal string and a Symbol.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...