Lumiera  0.pre.03
»edit your freedom«
output-mapping.hpp
Go to the documentation of this file.
1 /*
2  OUTPUT-MAPPING.hpp - generic interface for translation of output designations
3 
4  Copyright (C)
5  2010, 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 
43 #ifndef STEAM_MOBJECT_OUTPUT_MAPPING_H
44 #define STEAM_MOBJECT_OUTPUT_MAPPING_H
45 
46 #include "lib/error.hpp"
47 #include "lib/util.hpp"
48 #include "lib/hash-value.h"
49 #include "steam/asset/pipe.hpp"
50 #include "common/query.hpp"
51 
52 #include <boost/operators.hpp>
53 #include <map>
54 
55 
56 
57 namespace steam {
58 namespace mobject {
59 
60  namespace { // Helper to extract and rebind definition types
61 
66  template<class DEF>
67  class _def
68  {
70 
71  template<typename FUN>
72  struct Rebind;
73 
74  template<typename RET>
75  struct Rebind<RET(DEF::*)(PId)>
76  {
77  typedef RET Res;
78  };
79 
80  using OutputMappingMemberFunc = decltype(&DEF::output) ;
82 
83  public:
84  using Target = typename Rebinder::Res;
85 
86  };
87  }//(End) type rebinding helper
88 
89  namespace error = lumiera::error;
90  using lumiera::Query;
91  using lib::HashVal;
92 
93 
94 
95 
120  template<class DEF>
122  : public DEF
123  {
124  typedef _def<DEF> Setup;
125 
126  using PId = asset::ID<asset::Pipe>;
127  using PPipe = asset::PPipe;
128 
129  /* == mapping table storage == */
130  std::map<HashVal,HashVal> table_;
131 
132  public:
133  using Target = typename Setup::Target;
134 
135  // using default ctor and copy operations
136 
137  size_t size() const { return table_.size(); }
138  bool empty() const { return 0 == size(); }
139  void clear() { table_.clear(); }
140 
141 
152  class Resolver
153  : public boost::equality_comparable<Resolver, Target // final mapping result can be compared to Target...
154  , boost::equality_comparable<Resolver>> // mapping values can be compared.
155  {
156  OutputMapping& thisMapping_;
157  HashVal& pID_;
158 
159  Resolver (OutputMapping& container, HashVal& resultVal)
160  : thisMapping_(container)
161  , pID_(resultVal)
162  { }
163 
164  friend class OutputMapping;
165 
166  /* copy by clients prohibited */
167  Resolver& operator= (Resolver const&);
168 
169 
170  Target
171  resolve() const
172  {
173  REQUIRE (pID_);
174  PId targetPipeID (pID_);
175  return thisMapping_.resolveTarget (targetPipeID);
176  }
177 
178  public:
183  void
184  operator= (PId newId2map)
185  {
186  pID_ = newId2map;
187  }
188 
189  void
190  operator= (PPipe newPipe2map)
191  {
192  REQUIRE (newPipe2map);
193  pID_ = newPipe2map->getID();
194  }
195 
196  void
197  disconnect()
198  {
199  pID_ = 0;
200  }
201 
208  operator Target()
209  {
210  if (not isValid())
211  throw error::Logic{"attempt to resolve an unconnected output mapping"
212  , LERR_(UNCONNECTED)};
213  return resolve();
214  }
215 
216  bool
217  isValid() const
218  {
219  return bool(pID_);
220  }
221 
222  explicit
223  operator bool() const
224  {
225  return isValid();
226  }
227 
228 
229  /* === equality comparisons (boost::operators) === */
230 
231  friend bool
232  operator== (Resolver const& a, Resolver const& b)
233  {
234  return a.pID_ == b.pID_;
235  } // note: Resolver depends on template parameter DEF
236  // All instances of DEF are considered equivalent!
237  friend bool
238  operator== (Resolver const& rr, Target const& tval)
239  {
240  return rr.resolve() == tval;
241  }
242  };
243 
244 
245 
246  /* === Map-style access for clients === */
247 
248  Resolver operator[] (PId sourcePipeID);
249  Resolver operator[] (PPipe const& pipe);
250  Resolver operator[] (Query<asset::Pipe> query4pipe);
251 
252  bool
253  contains (PId mapping4sourcePipeID)
254  {
255  return util::contains (table_, mapping4sourcePipeID);
256  }
257 
258  bool
259  contains (PPipe sourcePipe)
260  {
261  return !sourcePipe
262  or this->contains (sourcePipe->getID());
263  }
264 
265 
266 
267  private:
268  Target
269  resolveTarget (PId mappedPipeID)
270  {
271  return DEF::output (mappedPipeID);
272  }
273 
274  Resolver
275  buildResolutionWrapper (HashVal tableSlot)
276  {
277  ASSERT (this->contains (tableSlot));
278  return Resolver (*this, table_[tableSlot]);
279  }
280  };
281 
282 
283 
284 
285  /* ===== Implementation details ===== */
286 
287  namespace _mapping {
288 
290  HashVal slot (Query<asset::Pipe> const&);
291 
293  HashVal resolveQuery (Query<asset::Pipe> const&);
294 
297  uint is_defaults_query_with_channel (Query<asset::Pipe> const&);
298 
300  Query<asset::Pipe> build_corresponding_sourceQuery (Query<asset::Pipe> const&);
301  }
302 
303 
318  template<class DEF>
319  inline typename OutputMapping<DEF>::Resolver
321  {
322  if (not contains (sourcePipeID))
323  {
324  // issue a defaults query to resolve this mapping first
325  Query<asset::Pipe> query4pipe = DEF::buildQuery (sourcePipeID);
326  table_[sourcePipeID] = _mapping::resolveQuery (query4pipe);
327  }
328  return buildResolutionWrapper (sourcePipeID);
329  }
330 
331 
334  template<class DEF>
335  inline typename OutputMapping<DEF>::Resolver
337  {
338  REQUIRE (pipe);
339  return (*this) [pipe->getID()];
340  }
341 
342 
373  template<class DEF>
374  inline typename OutputMapping<DEF>::Resolver
376  {
377  HashVal hash4query = _mapping::slot (query4pipe);
378  if (not contains (hash4query))
379  {
380  // need to resolve this query first
381  auto addEntry = [&](auto query)
382  {
383  table_[hash4query] = _mapping::resolveQuery (query);
384  };
385 
386  if (uint seqNr = _mapping::is_defaults_query_with_channel (query4pipe))
387  {
388  // treat the special case
389  // when actually requesting the "Nth default of this kind"
390  PPipe corresponding_sourcePipe
392  _mapping::build_corresponding_sourceQuery (query4pipe));
393  ENSURE (corresponding_sourcePipe);
394 
395  PId sourcePipeID = corresponding_sourcePipe->getID();
396  addEntry (DEF::buildQuery (sourcePipeID, seqNr));
397  }
398  else
399  addEntry (query4pipe);
400  }
401 
402  ENSURE (this->contains (hash4query));
403  return buildResolutionWrapper (hash4query);
404  }
405 
406 
407 }} // namespace steam::mobject
408 #endif
A "processing pipe" represented as Asset.
Basic and generic representation of an internal query.
Definition: Setup.py:1
bool isValid() const
< is this a valid connected mapping?
Steam-Layer implementation namespace root.
static StructFactory retrieve
storage for the static StructFactory instance
Definition: struct.hpp:107
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:190
Resolver operator[](PId sourcePipeID)
standard map-style access to an OutputMapping.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
Lumiera error handling (C++ interface).
Hash value types and utilities.
size_t HashVal
a STL compatible hash value
Definition: hash-value.h:52
OutputMapping is a facility to resolve output designations.
Customised refcounting smart pointer template, built upon std::shared_ptr, but forwarding type relati...
Definition: trait.hpp:71
Generic interface to express a query for specifically typed result elements exposing some capabilitie...
Definition: query.hpp:270
string resolve(fsys::path iniSpec)
use the general mechanism for resolving a search path to get the absolute path of the setup...
Definition: basic-setup.cpp:56
thin wrapper around a size_t hash ID used as primary key for all Asset objects.
Definition: asset.hpp:99