Object.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2013-2016 Imperial College London
5  * Copyright 2013-2016 Andreas Schuh
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifndef MIRTK_Object_H
21 #define MIRTK_Object_H
22 
23 #include "mirtk/Array.h"
24 #include "mirtk/Exception.h"
25 #include "mirtk/Pair.h"
26 #include "mirtk/String.h"
27 #include "mirtk/Stream.h"
28 
29 
30 namespace mirtk {
31 
32 
33 // =============================================================================
34 // Basic object interface
35 // =============================================================================
36 
37 /// Ordered list of parameter name/value pairs
38 typedef Array<Pair<string, string> > ParameterList;
39 typedef ParameterList::iterator ParameterIterator;
40 typedef ParameterList::const_iterator ParameterConstIterator;
41 
42 
43 /**
44  * Base class for all MIRTK object classes
45  *
46  * \note This base class must be a virtual interface without any own data
47  * members to not change the type size of subclasses! Derive another
48  * intermediate abstract base class from it to add data members shared
49  * by a more specific class of objects.
50  */
51 class Object
52 {
53 public:
54 
55  /// Get name of this class type
56  static const char *NameOfType();
57 
58  /// Get name of class, which this object is an instance of
59  virtual const char *NameOfClass() const = 0;
60 
61  /// Destructor
62  virtual ~Object();
63 
64  /// Set parameter value from string
65  ///
66  /// \param[in] name Parameter name.
67  /// \param[in] value Parameter value.
68  ///
69  /// \returns Whether the named parameter is valid and a valid value was
70  /// set from the provided string representation of the value.
71  virtual bool Set(const char *name, const char *value);
72 
73  /// Get parameter name/value pairs
74  virtual ParameterList Parameter() const;
75 
76  /// Set parameters from name/value pairs
77  bool Parameter(const ParameterList &);
78 
79  // ---------------------------------------------------------------------------
80  // Error handling
81 protected:
82 
83  /// Raise error in member function
84  ///
85  /// The current implementation prints the error message to STDERR and terminates
86  /// the program with exit code 1. In future releases, when all library code has
87  /// been rewritten to use this function, a suitable runtime exception may be
88  /// thrown instead.
89  ///
90  /// \param[in] err Error type. Unused at the moment, but may be used in
91  /// future releases to throw the appropriate exception type.
92  /// \param[in] cls Name of class that defines the member function.
93  /// \param[in] func Name of member function which is throwing the error (i.e., __func__).
94  /// \param[in] args Error message. The given arguments are converted to strings
95  /// using the ToString template function. These strings are then
96  /// concatenated to produce the complete error message.
97  template <typename... Args>
98  static void ThrowStatic(ErrorType err, const char *cls, const char *func, Args... args);
99 
100  /// Raise error in member function
101  ///
102  /// The current implementation prints the error message to STDERR and terminates
103  /// the program with exit code 1. In future releases, when all library code has
104  /// been rewritten to use this function, a suitable runtime exception may be
105  /// thrown instead.
106  ///
107  /// \param[in] err Error type. Unused at the moment, but may be used in
108  /// future releases to throw the appropriate exception type.
109  /// \param[in] func Name of member function which is throwing the error (i.e., __func__).
110  /// \param[in] args Error message. The given arguments are converted to strings
111  /// using the ToString template function. These strings are then
112  /// concatenated to produce the complete error message.
113  template <typename... Args>
114  void Throw(ErrorType err, const char *func, Args... args) const;
115 };
116 
117 // =============================================================================
118 // Inline definitions
119 // =============================================================================
120 
121 // -----------------------------------------------------------------------------
123 {
124 }
125 
126 // -----------------------------------------------------------------------------
127 inline const char *Object::NameOfType()
128 {
129  return "mirtk::Object";
130 }
131 
132 // -----------------------------------------------------------------------------
133 inline bool Object::Set(const char *, const char *)
134 {
135  return false;
136 }
137 
138 // -----------------------------------------------------------------------------
139 inline ParameterList Object::Parameter() const
140 {
141  return ParameterList();
142 }
143 
144 // -----------------------------------------------------------------------------
145 inline bool Object::Parameter(const ParameterList &param)
146 {
147  bool ok = true;
148  for (ParameterConstIterator it = param.begin(); it != param.end(); ++it) {
149  ok = this->Set(it->first.c_str(), it->second.c_str()) && ok;
150  }
151  return ok;
152 }
153 
154 // -----------------------------------------------------------------------------
155 template <typename... Args>
156 void Object::ThrowStatic(ErrorType err, const char *cls, const char *func, Args... args)
157 {
158  string member(cls);
159  member += "::";
160  member += func;
161  mirtk::Throw(err, member.c_str(), args...);
162 }
163 
164 // -----------------------------------------------------------------------------
165 template <typename... Args>
166 void Object::Throw(ErrorType err, const char *func, Args... args) const
167 {
168  ThrowStatic(err, this->NameOfClass(), func, args...);
169 }
170 
171 // =============================================================================
172 // Auxiliary functions for subclass implementation
173 // =============================================================================
174 
175 // -----------------------------------------------------------------------------
176 /// Find parameter in parameters list
177 inline ParameterConstIterator Find(const ParameterList &params, string name)
178 {
179  ParameterConstIterator it = params.begin();
180  while (it != params.end() && it->first != name) ++it;
181  return it;
182 }
183 
184 // -----------------------------------------------------------------------------
185 /// Find parameter in parameters list
186 inline ParameterIterator Find(ParameterList &params, string name)
187 {
188  ParameterIterator it = params.begin();
189  while (it != params.end() && it->first != name) ++it;
190  return it;
191 }
192 
193 // -----------------------------------------------------------------------------
194 /// Whether parameter is in parameters list
195 inline bool Contains(const ParameterList &params, string name)
196 {
197  return Find(params, name) != params.end();
198 }
199 
200 // -----------------------------------------------------------------------------
201 /// Get parameter value from parameters list
202 inline string Get(const ParameterList &params, string name)
203 {
204  ParameterConstIterator pos = Find(params, name);
205  if (pos == params.end()) return string("");
206  return pos->second;
207 }
208 
209 // -----------------------------------------------------------------------------
210 /// Insert/replace value into/in parameters list
211 template <class T>
212 inline ParameterList &Insert(ParameterList &params, string name, T value)
213 {
214  ParameterIterator pos = Find(params, name);
215  if (pos == params.end()) {
216  params.push_back(make_pair(name, ToString(value)));
217  } else {
218  pos->second = ToString(value);
219  }
220  return params;
221 }
222 
223 // -----------------------------------------------------------------------------
224 /// Insert/replace string value into/in parameters list
225 template <>
226 inline ParameterList &Insert(ParameterList &params, string name, const char *value)
227 {
228  ParameterIterator pos = Find(params, name);
229  if (pos == params.end()) {
230  params.push_back(make_pair(name, string(value)));
231  } else {
232  pos->second = value;
233  }
234  return params;
235 }
236 
237 // -----------------------------------------------------------------------------
238 /// Insert/replace string value into/in parameters list
239 template <>
240 inline ParameterList &Insert(ParameterList &params, string name, string value)
241 {
242  ParameterIterator pos = Find(params, name);
243  if (pos == params.end()) {
244  params.push_back(make_pair(name, value));
245  } else {
246  pos->second = value;
247  }
248  return params;
249 }
250 
251 // -----------------------------------------------------------------------------
252 /// Insert/replace values into/in parameters list
253 inline ParameterList &Insert(ParameterList &params,
254  const ParameterList &other,
255  const char *prefix = NULL)
256 {
257  if (prefix) {
258  string name;
259  for (ParameterConstIterator it = other.begin(); it != other.end(); ++it) {
260  name = it->first;
261  name[0] = ::tolower(name[0]);
262  Insert(params, string(prefix) + " " + name, it->second);
263  }
264  } else {
265  for (ParameterConstIterator it = other.begin(); it != other.end(); ++it) {
266  Insert(params, it->first, it->second);
267  }
268  }
269  return params;
270 }
271 
272 // -----------------------------------------------------------------------------
273 /// Remove parameter from parameters list
274 inline ParameterList &Remove(ParameterList &params, string name)
275 {
276  ParameterIterator pos = Find(params, name);
277  if (pos != params.end()) params.erase(pos);
278  return params;
279 }
280 
281 // =============================================================================
282 // Auxiliary macros for subclass implementation
283 // =============================================================================
284 
285 // -----------------------------------------------------------------------------
286 /// Declare abstract base class derived from Object
287 #define mirtkAbstractMacro(name) \
288  public: \
289  /** Get name of this class type */ \
290  inline static const char *NameOfType() { return #name; } \
291  /** Get name of class, which this object is an instance of */ \
292  virtual const char *NameOfClass() const = 0; \
293  private:
294 
295 // -----------------------------------------------------------------------------
296 /// Declare class derived from Object
297 #define mirtkObjectMacro(name) \
298  public: \
299  /** Get name of this class type */ \
300  inline static const char *NameOfType() { return #name; } \
301  /** Get name of class, which this object is an instance of */ \
302  inline virtual const char *NameOfClass() const { return #name; } \
303  private:
304 
305 // -----------------------------------------------------------------------------
306 /// Declare class of mutable objects, i.e., ones which define their own
307 /// NameOfClass implementation that returns a different type identifier
308 /// depending on the state of the object.
309 #define mirtkMutableObjectMacro(name) \
310  public: \
311  /** Get name of this class type */ \
312  inline static const char *NameOfType() { return #name; } \
313  /** Get name of class, which this object is an instance of */ \
314  virtual const char *NameOfClass() const; \
315  private:
316 
317 // -----------------------------------------------------------------------------
318 /// Define setter for class member variable
319 /// \sa mirtkPublicAttributeMacro
320 #define mirtkSetMacro(name, type) \
321  virtual void Set##name(type arg) { this->_##name = arg; }
322 
323 // -----------------------------------------------------------------------------
324 /// Define getter for class member variable
325 /// \sa mirtkPublicAttributeMacro, mirtkReadOnlyAttributeMacro
326 #define mirtkGetMacro(name, type) \
327  type Get##name() const { return this->_##name; }
328 
329 // -----------------------------------------------------------------------------
330 /// Define VTK-like On/Off setter for boolean class member variable
331 /// \sa mirtkPublicAttributeMacro
332 #define mirtkOnOffMacro(name) \
333  virtual void name##On() { this->_##name = true; } \
334  virtual void name##Off() { this->_##name = false; }
335 
336 // -----------------------------------------------------------------------------
337 /// Define read-only class attribute and corresponding accessors
338 #define mirtkDefineReadOnlyAttributeMacro(typedecl, type, name) \
339  protected: \
340  typedecl _##name; \
341  public: \
342  /** Get value of _##name attribute */ \
343  inline type &name() { return _##name; } \
344  /** Get value of _##name attribute */ \
345  inline const type &name() const { return _##name; } \
346  private:
347 
348 // -----------------------------------------------------------------------------
349 /// Define class attribute and corresponding accessors
350 #define mirtkDefineAttributeMacro(access, typedecl, type, name) \
351  protected: \
352  typedecl _##name; \
353  access: \
354  /** Set value of _##name attribute */ \
355  inline virtual void name(type arg) { _##name = arg; } \
356  /** Get value of _##name attribute */ \
357  inline type &name() { return _##name; } \
358  /** Get value of _##name attribute */ \
359  inline const type &name() const { return _##name; } \
360  private:
361 
362 // -----------------------------------------------------------------------------
363 /// Define public attribute
364 #define mirtkPublicAttributeMacro(type, name) \
365  mirtkDefineAttributeMacro(public, type, type, name)
366 /// Define public read-only attribute
367 #define mirtkReadOnlyAttributeMacro(type, name) \
368  mirtkDefineReadOnlyAttributeMacro(type, type, name)
369 /// Define public mutable attribute
370 #define mirtkPublicMutableAttributeMacro(type, name) \
371  mirtkDefineAttributeMacro(public, mutable type, type, name)
372 
373 // -----------------------------------------------------------------------------
374 /// Define protected attribute
375 #define mirtkAttributeMacro(type, name) \
376  mirtkDefineAttributeMacro(protected, type, type, name)
377 /// Define protected mutable attribute
378 #define mirtkMutableAttributeMacro(type, name) \
379  mirtkDefineAttributeMacro(protected, mutable type, type, name)
380 
381 // -----------------------------------------------------------------------------
382 /// Define pointer to aggregate (cf. UML aggregation) and corresponding accessors
383 #define mirtkDefineAggregateMacro(access, type, name) \
384  protected: \
385  type *_##name; \
386  access: \
387  /** Set value of _##name attribute */ \
388  inline virtual void name(type *arg) { _##name = arg; } \
389  /** Get value of _##name attribute */ \
390  inline type *name() const { return _##name; } \
391  private:
392 
393 // -----------------------------------------------------------------------------
394 /// Define pointer to aggregate (cf. UML aggregation) and corresponding accessors
395 #define mirtkDefineReadOnlyAggregateMacro(access, type, name) \
396  protected: \
397  type *_##name; \
398  access: \
399  /** Get value of _##name attribute */ \
400  inline type *name() const { return _##name; } \
401  private:
402 
403 // -----------------------------------------------------------------------------
404 /// Define public pointer to aggregate (cf. UML aggregation)
405 #define mirtkPublicAggregateMacro(type, name) \
406  mirtkDefineAggregateMacro(public, type, name)
407 /// Define public read-only pointer to aggregate (cf. UML aggregation)
408 #define mirtkReadOnlyAggregateMacro(type, name) \
409  mirtkDefineReadOnlyAggregateMacro(public, type, name)
410 
411 // -----------------------------------------------------------------------------
412 /// Define protected pointer to aggregate (cf. UML aggregation)
413 #define mirtkAggregateMacro(type, name) \
414  mirtkDefineAggregateMacro(protected, type, name)
415 
416 // -----------------------------------------------------------------------------
417 /// Define pointer to component (cf. UML composition) and corresponding accessors
418 #define mirtkDefineComponentMacro(access, type, name) \
419  protected: \
420  type *_##name; \
421  access: \
422  /** Set pointer to _##name attribute */ \
423  inline virtual void name(type *arg) { delete _##name; _##name = arg; } \
424  /** Get pointer to _##name attribute */ \
425  inline type *name() { return _##name; } \
426  /** Get const pointer to _##name attribute */ \
427  inline const type *name() const { return _##name; } \
428  private:
429 
430 // -----------------------------------------------------------------------------
431 /// Define public pointer to component (cf. UML composition)
432 #define mirtkPublicComponentMacro(type, name) \
433  mirtkDefineComponentMacro(public, type, name)
434 /// Define public read-only pointer to component (cf. UML composition)
435 #define mirtkReadOnlyComponentMacro(type, name) \
436  mirtkDefineReadOnlyAggregateMacro(public, type, name)
437 
438 // -----------------------------------------------------------------------------
439 /// Define protected pointer to component (cf. UML composition)
440 #define mirtkComponentMacro(type, name) \
441  mirtkDefineComponentMacro(protected, type, name)
442 
443 // -----------------------------------------------------------------------------
444 /// Define pointer to component (cf. UML composition) which can also be set to
445 /// an externally managed instance instead using the corresponding accessors
446 ///
447 /// A loose component is a pointer that must never by a nullptr. It must be
448 /// initialized during construction of an instance of the class which this
449 /// component attribute belongs.
450 ///
451 /// Unlike a regular component, a loose component can alternatively be set to an
452 /// externally instantiated object of the component type. In this case, the class
453 /// revokes ownership of the object which must be deleted by the client code.
454 /// When a nullptr is given as argument to the setter of the loose component,
455 /// the current pointer is replaced by a new copy that is owned by this class.
456 /// It can thus be used to release the external object again before destruction
457 /// in cases where the class that the loose component belongs to remains in use.
458 #define mirtkLooseComponentMacro(type, name) \
459  protected: \
460  type *_##name; \
461  bool _##name##Owner; \
462  public: \
463  /** Set pointer to _##name attribute */ \
464  inline virtual void name(type *arg) { \
465  if (_##name##Owner) delete _##name; \
466  if (arg) { \
467  _##name = arg; \
468  _##name##Owner = false; \
469  } else { \
470  _##name = new type(*_##name); \
471  _##name##Owner = true; \
472  } \
473  } \
474  /** Get pointer to _##name attribute */ \
475  inline type *name() { return _##name; } \
476  /** Get const pointer to _##name attribute */ \
477  inline const type *name() const { return _##name; } \
478  private:
479 
480 
481 } // namespace mirtk
482 
483 #endif // MIRTK_Object_H
static void ThrowStatic(ErrorType err, const char *cls, const char *func, Args... args)
Definition: Object.h:156
static const char * NameOfType()
Get name of this class type.
Definition: Object.h:127
Array< T >::iterator Find(Array< T > &values, const T &value)
Find value in unsorted Array.
Definition: Algorithm.h:244
string Get(const ParameterList &params, string name)
Get parameter value from parameters list.
Definition: Object.h:202
bool Contains(const ParameterList &params, string name)
Whether parameter is in parameters list.
Definition: Object.h:195
Array< Pair< string, string > > ParameterList
Ordered list of parameter name/value pairs.
Definition: Object.h:38
Definition: IOConfig.h:41
virtual bool Set(const char *name, const char *value)
Definition: Object.h:133
virtual ~Object()
Destructor.
Definition: Object.h:122
string ToString(const EnergyMeasure &value, int w, char c, bool left)
Convert energy measure enumeration value to string.
ParameterList & Remove(ParameterList &params, string name)
Remove parameter from parameters list.
Definition: Object.h:274
void Throw(ErrorType err, const char *func, Args... args) const
Definition: Object.h:166
void Throw(ErrorType err, const char *func, Args... args)
Definition: Exception.h:74
virtual const char * NameOfClass() const =0
Get name of class, which this object is an instance of.
virtual ParameterList Parameter() const
Get parameter name/value pairs.
Definition: Object.h:139
ParameterList & Insert(ParameterList &params, string name, T value)
Insert/replace value into/in parameters list.
Definition: Object.h:212
ErrorType
Enumeration of error types / exit codes.
Definition: Exception.h:31