Lumiera  0.pre.03
»edit your freedom«
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 
33 namespace steam {
34 namespace mobject {
35 namespace session {
36 
37  using std::reverse;
38  using lib::append_all;
39  using util::isSameObject;
40  using util::isnil;
41 
42 
43  namespace { // Helpers and shortcuts....
44 
48  discoverScopePath (Scope const& leaf)
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 
127  ScopePath::~ScopePath()
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  && hasValidRoot()
166 #endif
167  ;
168  }
169 
170  bool
171  ScopePath::hasValidRoot() const
172  {
173  REQUIRE (0 < length());
174  return path_[0] == currModelRoot();
175  }
176 
177  PlacementMO const&
178  ScopePath::currModelRoot() const
179  {
181  }
182 
183 
184 
185 
186 
187  /* == Relations == */
188 
189  Scope const&
190  ScopePath::getLeaf() 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 
240  ScopePath
241  commonPrefix (ScopePath const& path1, ScopePath const& path2)
242  {
243  ScopePath prefix (ScopePath::INVALID);
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() || path2.empty()) return false;
256 
257  return (path1.isValid() && path2.isValid())
258  && (path1.path_[1] != path2.path_[1]) // no common prefix
259  ;
260  }
261 
262 
263 
264 
265  /* == Mutations == */
266 
267  void
268  ScopePath::clear()
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&
280  ScopePath::moveUp()
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&
292  ScopePath::goRoot()
293  {
294  ___check_notBottom (this, "Navigating");
295  ENSURE (hasValidRoot());
296 
297  path_.resize (1);
298  return path_.back();
299  }
300 
301 
302  void
303  ScopePath::navigate (Scope const& target)
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
Implementation level session API: query a scope.
ScopePath & operator=(ScopePath const &)
Copy from existing path.
Definition: scope-path.cpp:113
bool endsAt(Scope const &) const
verify the scope in question is equivalent to our leaf scope.
Definition: scope-path.cpp:203
bool empty() const
an empty path doesn&#39;t even contain a root element.
Definition: scope-path.hpp:256
static const ScopePath INVALID
constant invalid path token.
Definition: scope-path.hpp:144
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:76
ScopeQuery< MObject >::iterator discoverScopePath(Scope const &leaf)
issue a query to discover the (raw) path to root, starting with the given scope
Definition: scope-path.cpp:48
This header is for including and configuring NoBug.
Core abstraction of the Session model: a media object.
Steam-Layer implementation namespace root.
Namespace of Session and user visible high-level objects.
Definition: sequence.hpp:65
Sequence of nested scopes within the high-level model.
Definition: scope-path.hpp:126
A Placement scope within the high-level-model.
Definition: scope.hpp:69
bool isValid() const
check if this scope can be located.
Definition: scope.cpp:231
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:190
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...
bool isValid() const
a valid path consists of more than just the root element.
Definition: scope-path.cpp:161
static const Scope INVALID
constant invalid scope token.
Definition: scope.hpp:83
Lumiera error handling (C++ interface).
Service to build the notion of a current location within the Sesison model.
An Object representing a sequence of nested scopes within the Session.
static lib::Depend< ScopeLocator > instance
Storage holding the single ScopeLocator instance.
Helpers for working with iterators based on the pipeline model.
Accessing a STL element range through a Lumiera forward iterator, An instance of this iterator adapte...
Adapter for building an implementation of the »Lumiera Forward Iterator« concept. ...
ScopePath()
Create an empty path.
Definition: scope-path.cpp:74
bool isSameObject(A const &a, B const &b)
compare plain object identity, based directly on the referee&#39;s memory identities. ...
Definition: util.hpp:421