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) Lumiera.org
5  2010, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 
52 #ifndef STEAM_MOBJECT_OUTPUT_MAPPING_H
53 #define STEAM_MOBJECT_OUTPUT_MAPPING_H
54 
55 #include "lib/error.hpp"
56 #include "lib/util.hpp"
57 #include "lib/hash-value.h"
58 #include "steam/asset/pipe.hpp"
59 #include "common/query.hpp"
60 
61 #include <boost/operators.hpp>
62 #include <map>
63 
64 
65 
66 namespace steam {
67 namespace mobject {
68 
69  namespace { // Helper to extract and rebind definition types
70 
75  template<class DEF>
76  class _def
77  {
79 
80  template<typename FUN>
81  struct Rebind;
82 
83  template<typename RET>
84  struct Rebind<RET(DEF::*)(PId)>
85  {
86  typedef RET Res;
87  };
88 
89  using OutputMappingMemberFunc = decltype(&DEF::output) ;
91 
92  public:
93  using Target = typename Rebinder::Res;
94 
95  };
96  }//(End) type rebinding helper
97 
98  namespace error = lumiera::error;
99  using lumiera::Query;
100  using lib::HashVal;
101 
102 
103 
104 
129  template<class DEF>
131  : public DEF
132  {
133  typedef _def<DEF> Setup;
134 
135  using PId = asset::ID<asset::Pipe>;
136  using PPipe = asset::PPipe;
137 
138  /* == mapping table storage == */
139  std::map<HashVal,HashVal> table_;
140 
141  public:
142  using Target = typename Setup::Target;
143 
144  // using default ctor and copy operations
145 
146  size_t size() const { return table_.size(); }
147  bool empty() const { return 0 == size(); }
148  void clear() { table_.clear(); }
149 
150 
161  class Resolver
162  : public boost::equality_comparable<Resolver, Target // final mapping result can be compared to Target...
163  , boost::equality_comparable<Resolver>> // mapping values can be compared.
164  {
165  OutputMapping& thisMapping_;
166  HashVal& pID_;
167 
168  Resolver (OutputMapping& container, HashVal& resultVal)
169  : thisMapping_(container)
170  , pID_(resultVal)
171  { }
172 
173  friend class OutputMapping;
174 
175  /* copy by clients prohibited */
176  Resolver& operator= (Resolver const&);
177 
178 
179  Target
180  resolve() const
181  {
182  REQUIRE (pID_);
183  PId targetPipeID (pID_);
184  return thisMapping_.resolveTarget (targetPipeID);
185  }
186 
187  public:
192  void
193  operator= (PId newId2map)
194  {
195  pID_ = newId2map;
196  }
197 
198  void
199  operator= (PPipe newPipe2map)
200  {
201  REQUIRE (newPipe2map);
202  pID_ = newPipe2map->getID();
203  }
204 
205  void
206  disconnect()
207  {
208  pID_ = 0;
209  }
210 
217  operator Target()
218  {
219  if (not isValid())
220  throw error::Logic{"attempt to resolve an unconnected output mapping"
221  , LERR_(UNCONNECTED)};
222  return resolve();
223  }
224 
225  bool
226  isValid() const
227  {
228  return bool(pID_);
229  }
230 
231  explicit
232  operator bool() const
233  {
234  return isValid();
235  }
236 
237 
238  /* === equality comparisons (boost::operators) === */
239 
240  friend bool
241  operator== (Resolver const& a, Resolver const& b)
242  {
243  return a.pID_ == b.pID_;
244  } // note: Resolver depends on template parameter DEF
245  // All instances of DEF are considered equivalent!
246  friend bool
247  operator== (Resolver const& rr, Target const& tval)
248  {
249  return rr.resolve() == tval;
250  }
251  };
252 
253 
254 
255  /* === Map-style access for clients === */
256 
257  Resolver operator[] (PId sourcePipeID);
258  Resolver operator[] (PPipe const& pipe);
259  Resolver operator[] (Query<asset::Pipe> query4pipe);
260 
261  bool
262  contains (PId mapping4sourcePipeID)
263  {
264  return util::contains (table_, mapping4sourcePipeID);
265  }
266 
267  bool
268  contains (PPipe sourcePipe)
269  {
270  return !sourcePipe
271  or this->contains (sourcePipe->getID());
272  }
273 
274 
275 
276  private:
277  Target
278  resolveTarget (PId mappedPipeID)
279  {
280  return DEF::output (mappedPipeID);
281  }
282 
283  Resolver
284  buildResolutionWrapper (HashVal tableSlot)
285  {
286  ASSERT (this->contains (tableSlot));
287  return Resolver (*this, table_[tableSlot]);
288  }
289  };
290 
291 
292 
293 
294  /* ===== Implementation details ===== */
295 
296  namespace _mapping {
297 
299  HashVal slot (Query<asset::Pipe> const&);
300 
302  HashVal resolveQuery (Query<asset::Pipe> const&);
303 
306  uint is_defaults_query_with_channel (Query<asset::Pipe> const&);
307 
309  Query<asset::Pipe> build_corresponding_sourceQuery (Query<asset::Pipe> const&);
310  }
311 
312 
327  template<class DEF>
328  inline typename OutputMapping<DEF>::Resolver
330  {
331  if (not contains (sourcePipeID))
332  {
333  // issue a defaults query to resolve this mapping first
334  Query<asset::Pipe> query4pipe = DEF::buildQuery (sourcePipeID);
335  table_[sourcePipeID] = _mapping::resolveQuery (query4pipe);
336  }
337  return buildResolutionWrapper (sourcePipeID);
338  }
339 
340 
343  template<class DEF>
344  inline typename OutputMapping<DEF>::Resolver
346  {
347  REQUIRE (pipe);
348  return (*this) [pipe->getID()];
349  }
350 
351 
382  template<class DEF>
383  inline typename OutputMapping<DEF>::Resolver
385  {
386  HashVal hash4query = _mapping::slot (query4pipe);
387  if (not contains (hash4query))
388  {
389  // need to resolve this query first
390  auto addEntry = [&](auto query)
391  {
392  table_[hash4query] = _mapping::resolveQuery (query);
393  };
394 
395  if (uint seqNr = _mapping::is_defaults_query_with_channel (query4pipe))
396  {
397  // treat the special case
398  // when actually requesting the "Nth default of this kind"
399  PPipe corresponding_sourcePipe
401  _mapping::build_corresponding_sourceQuery (query4pipe));
402  ENSURE (corresponding_sourcePipe);
403 
404  PId sourcePipeID = corresponding_sourcePipe->getID();
405  addEntry (DEF::buildQuery (sourcePipeID, seqNr));
406  }
407  else
408  addEntry (query4pipe);
409  }
410 
411  ENSURE (this->contains (hash4query));
412  return buildResolutionWrapper (hash4query);
413  }
414 
415 
416 }} // namespace steam::mobject
417 #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:116
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:199
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:56
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:80
Generic interface to express a query for specifically typed result elements exposing some capabilitie...
Definition: query.hpp:279
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:65
thin wrapper around a size_t hash ID used as primary key for all Asset objects.
Definition: asset.hpp:108