NAP
path.h
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4 
5 #pragma once
6 
7 // Local Includes
8 #include "typeinfo.h"
9 
10 // External Includes
11 #include <utility/dllexport.h>
12 #include <string>
13 #include <assert.h>
14 
15 namespace nap
16 {
17  namespace rtti
18  {
19  class Object;
20  class ResolvedPath;
21 
29  class NAPAPI PathElement
30  {
31  public:
35  enum class Type
36  {
37  INVALID, // Not a valid element
38  ATTRIBUTE, // Attribute
39  ARRAY_ELEMENT // Array index (element)
40  };
41 
45  bool operator==(const PathElement& lhs) const
46  {
47  // Check type first
48  if (mType != lhs.mType)
49  return false;
50 
51  // Compare properties
52  if (mType == Type::ATTRIBUTE)
53  return strcmp(Attribute.Name, lhs.Attribute.Name) == 0;
54  else if (mType == Type::ARRAY_ELEMENT)
55  return ArrayElement.Index == lhs.ArrayElement.Index;
56 
57  assert(false);
58  return false;
59  }
60 
64  bool operator!=(const PathElement& lhs) const
65  {
66  return !(*this == lhs);
67  }
68 
69  Type mType = Type::INVALID; // The type of this element
70  union
71  {
72  struct
73  {
74  const char* Name; // The name of the attribute we're representing
75  } Attribute;
76 
77  struct
78  {
79  int Index; // The index of the array element we're representing
80  } ArrayElement;
81  };
82 
83  private:
84  friend class Path;
85 
89  PathElement() :
90  mType(Type::INVALID)
91  {
92  }
93 
100  PathElement(const char* attributeName) :
101  mType(Type::ATTRIBUTE)
102  {
103  Attribute.Name = attributeName;
104  }
105 
113  PathElement(const std::string& attributeName) :
114  mType(Type::ATTRIBUTE)
115  {
116  mAttributeNameStorage = std::make_unique<std::string>(attributeName);
117  Attribute.Name = mAttributeNameStorage->data();
118  }
119 
125  PathElement(int arrayIndex) :
126  mType(Type::ARRAY_ELEMENT)
127  {
128  ArrayElement.Index = arrayIndex;
129  }
130 
134  PathElement(const PathElement& other)
135  {
136  copyFrom(other);
137  }
138 
142  PathElement& operator=(const PathElement& other)
143  {
144  // Prevent self-assignment
145  if (&other == this)
146  return *this;
147 
148  // Destroy current value and copy over new data
149  copyFrom(other);
150 
151  return *this;
152  }
153 
157  inline void copyFrom(const PathElement& other)
158  {
159  mType = other.mType;
160  if (mType == Type::ATTRIBUTE)
161  {
162  if (other.mAttributeNameStorage == nullptr)
163  {
164  Attribute.Name = other.Attribute.Name;
165  }
166  else
167  {
168  mAttributeNameStorage = std::make_unique<std::string>(*other.mAttributeNameStorage);
169  Attribute.Name = mAttributeNameStorage->data();
170  }
171  }
172  else if (mType == Type::ARRAY_ELEMENT)
173  {
174  ArrayElement.Index = other.ArrayElement.Index;
175  }
176  }
177 
178  private:
179  std::unique_ptr<std::string> mAttributeNameStorage;
180  };
181 
186  {
187  private:
188  friend class ResolvedPath;
192  enum class Type
193  {
194  INVALID, // Invalid type
195  ROOT, // Root
196  ATTRIBUTE, // Attribute
197  ARRAY_ELEMENT // Array index
198  };
199 
204  mType(Type::INVALID)
205  {
206  }
207 
214  ResolvedRTTIPathElement(const rtti::Instance& instance, const rtti::Property& property) :
215  mType(Type::ROOT)
216  {
217  initNonPOD(Root.Instance, instance);
218  initNonPOD(Root.Property, property);
219  }
220 
227  ResolvedRTTIPathElement(const rtti::Variant& variant, const rtti::Property& property) :
228  mType(Type::ATTRIBUTE)
229  {
230  initNonPOD(Attribute.Variant, variant);
231  initNonPOD(Attribute.Property, property);
232  }
233 
240  ResolvedRTTIPathElement(const rtti::Variant& array, int index) :
241  mType(Type::ARRAY_ELEMENT)
242  {
243  initNonPOD(ArrayElement.Array, array);
244  ArrayElement.Index = index;
245  }
246 
250  ResolvedRTTIPathElement(const ResolvedRTTIPathElement& other)
251  {
252  copyFrom(other);
253  }
254 
258  ~ResolvedRTTIPathElement()
259  {
260  destroy();
261  }
262 
266  ResolvedRTTIPathElement& operator=(const ResolvedRTTIPathElement& other)
267  {
268  if (&other == this)
269  return *this;
270 
271  destroy();
272  copyFrom(other);
273 
274  return *this;
275  }
276 
283  template <typename T>
284  inline void initNonPOD(T& member, const T& val)
285  {
286  new (&member) T(val);
287  }
288 
292  inline void destroy()
293  {
294  // Because all data is placement new'd, we have to call destructors manually
295  if (mType == Type::ROOT)
296  {
297  Root.Instance.~instance();
298  Root.Property.~property();
299  }
300  else if (mType == Type::ATTRIBUTE)
301  {
302  Attribute.Variant.~variant();
303  Attribute.Property.~property();
304  }
305  else if (mType == Type::ARRAY_ELEMENT)
306  {
307  ArrayElement.Array.~variant();
308  }
309  }
310 
314  inline void copyFrom(const ResolvedRTTIPathElement& other)
315  {
316  mType = other.mType;
317  if (mType == Type::ROOT)
318  {
319  initNonPOD(Root.Instance, other.Root.Instance);
320  initNonPOD(Root.Property, other.Root.Property);
321  }
322  else if (mType == Type::ATTRIBUTE)
323  {
324  initNonPOD(Attribute.Variant, other.Attribute.Variant);
325  initNonPOD(Attribute.Property, other.Attribute.Property);
326  }
327  else if (mType == Type::ARRAY_ELEMENT)
328  {
329  initNonPOD(ArrayElement.Array, other.ArrayElement.Array);
330  ArrayElement.Index = other.ArrayElement.Index;
331  }
332  }
333 
334  Type mType; // The type of this element
335  union
336  {
337  struct
338  {
339  rtti::Instance Instance; // The root object (i.e. pointer) that this path was resolved against
340  rtti::Property Property; // The property on the root object that we're setting
341  } Root;
342 
343  struct
344  {
345  rtti::Variant Variant; // The object (can be a nested compound) that the attribute we're representing is on
346  rtti::Property Property; // The property on the root object we're representing
347  } Attribute;
348 
349  struct
350  {
351  rtti::Variant Array; // The array that the array element we're representing is in
352  int Index; // The index in the array
353  } ArrayElement;
354  };
355  };
356 
409  class NAPAPI Path
410  {
411  public:
418  inline void pushAttribute(const char* attributeName)
419  {
420  assert(mLength < RTTIPATH_MAX_LENGTH);
421  mElements[mLength++] = PathElement(attributeName);
422  }
423 
431  inline void pushAttribute(const std::string& attributeName)
432  {
433  assert(mLength < RTTIPATH_MAX_LENGTH);
434  mElements[mLength++] = PathElement(attributeName);
435  }
436 
442  inline void pushArrayElement(int index)
443  {
444  assert(mLength < RTTIPATH_MAX_LENGTH);
445  mElements[mLength++] = PathElement(index);
446  }
447 
451  inline void popBack()
452  {
453  assert(mLength > 0);
454  mElements[--mLength] = PathElement();
455  }
456 
462  inline int getLength() const
463  {
464  return mLength;
465  }
466 
473  inline const PathElement& getElement(int index) const
474  {
475  assert(index < mLength);
476  return mElements[index];
477  }
478 
482  bool operator==(const Path& lhs) const
483  {
484  if (mLength != lhs.mLength)
485  return false;
486 
487  for (int index = 0; index < mLength; ++index)
488  if (mElements[index] != lhs.mElements[index])
489  return false;
490 
491  return true;
492  }
493 
497  bool operator!=(const Path& lhs) const
498  {
499  return !(*this == lhs);
500  }
501 
507  const std::string toString() const;
508 
514  static const Path fromString(const std::string& path);
515 
523  bool resolve(const rtti::Object* object, ResolvedPath& resolvedPath) const;
524 
525 
526  int length() const { return mLength; }
527 
528  private:
529  static const int RTTIPATH_MAX_LENGTH = 16; // Maximum number of elements on a Path
530  PathElement mElements[RTTIPATH_MAX_LENGTH]; // The elements on the path
531  int mLength = 0; // Current length of the path
532  };
533 
538  class NAPAPI ResolvedPath
539  {
540  public:
547  const rtti::Variant getValue() const;
548 
555  bool setValue(const rtti::Variant& value);
556 
562  const rtti::TypeInfo getType() const;
563 
569  const rtti::Property& getProperty() const;
570 
576  bool isEmpty() const
577  {
578  return mLength == 0;
579  }
580 
586  bool isValid() const { return !isEmpty(); }
587 
588  private:
589  friend class Path;
590 
594  inline void pushRoot(const rtti::Instance& instance, const rtti::Property& property)
595  {
596  assert(mLength < RTTIPATH_MAX_LENGTH);
597  mElements[mLength++] = ResolvedRTTIPathElement(instance, property);
598  }
599 
603  inline void pushAttribute(const rtti::Variant& variant, const rtti::Property& property)
604  {
605  assert(mLength < RTTIPATH_MAX_LENGTH);
606  mElements[mLength++] = ResolvedRTTIPathElement(variant, property);
607  }
608 
612  inline void pushArrayElement(const rtti::Variant& array, int index)
613  {
614  assert(mLength < RTTIPATH_MAX_LENGTH);
615  mElements[mLength++] = ResolvedRTTIPathElement(array, index);
616  }
617 
618  private:
619  static const int RTTIPATH_MAX_LENGTH = 16; // Maximum number of elements on a Path
620  ResolvedRTTIPathElement mElements[RTTIPATH_MAX_LENGTH]; // The elements on the path
621  int mLength = 0; // Current length of the path
622  };
623  }
624 }
nap::toString
NAPAPI std::string toString(EDay day)
nap::rtti::Path::operator==
bool operator==(const Path &lhs) const
Definition: path.h:482
nap::rtti::PathElement::Index
int Index
Definition: path.h:79
nap::rtti::ResolvedRTTIPathElement::Array
rtti::Variant Array
Definition: path.h:351
nap::rtti::Path::length
int length() const
Definition: path.h:526
nap::rtti::PathElement::ArrayElement
struct nap::rtti::PathElement::@4::@7 ArrayElement
nap::rtti::ResolvedRTTIPathElement::Property
rtti::Property Property
Definition: path.h:340
nap::rtti::Path::pushAttribute
void pushAttribute(const char *attributeName)
Definition: path.h:418
nap::rtti::Object
Definition: object.h:30
nap::rtti::Path::pushArrayElement
void pushArrayElement(int index)
Definition: path.h:442
nap::rtti::Path::getLength
int getLength() const
Definition: path.h:462
nap::rtti::Path::pushAttribute
void pushAttribute(const std::string &attributeName)
Definition: path.h:431
nap::rtti::ResolvedRTTIPathElement::Instance
rtti::Instance Instance
Definition: path.h:339
nap::rtti::PathElement
Definition: path.h:29
nap::rtti::PathElement::Attribute
struct nap::rtti::PathElement::@4::@6 Attribute
nap::rtti::PathElement::Name
const char * Name
Definition: path.h:74
nap::rtti::Property
rttr::property Property
Definition: typeinfo.h:142
nap::rtti::ResolvedPath::isValid
bool isValid() const
Definition: path.h:586
nap::rtti::PathElement::operator==
bool operator==(const PathElement &lhs) const
Definition: path.h:45
nap::rtti::PathElement::mType
Type mType
Definition: path.h:69
nap::rtti::ResolvedPath::isEmpty
bool isEmpty() const
Definition: path.h:576
nap::rtti::Path::popBack
void popBack()
Definition: path.h:451
nap::rtti::ResolvedPath
Definition: path.h:538
nap::rtti::PathElement::Type
Type
Definition: path.h:35
nap
Definition: templateapp.h:17
nap::rtti::Instance
rttr::instance Instance
Definition: typeinfo.h:144
nap::rtti::Path
Definition: path.h:409
nap::rtti::Variant
rttr::variant Variant
Definition: typeinfo.h:143
nap::rtti::ResolvedRTTIPathElement::Variant
rtti::Variant Variant
Definition: path.h:345
nap::rtti::TypeInfo
rttr::type TypeInfo
Definition: typeinfo.h:140
nap::rtti::Path::getElement
const PathElement & getElement(int index) const
Definition: path.h:473
nap::rtti::ResolvedRTTIPathElement::Index
int Index
Definition: path.h:352
nap::rtti::ResolvedRTTIPathElement
Definition: path.h:185
nap::rtti::Path::operator!=
bool operator!=(const Path &lhs) const
Definition: path.h:497
nap::rtti::PathElement::operator!=
bool operator!=(const PathElement &lhs) const
Definition: path.h:64