TurtleBrains  0.3.1
High quality, portable, C++ framework for rapid 2D game development.
tb_dynamic_structure.h
1 
9 #ifndef _TurtleBrains_DynamicStructure_h_
10 #define _TurtleBrains_DynamicStructure_h_
11 
12 #include "tb_string.h"
13 #include "tb_types.h"
14 
15 #include <cmath>
16 #include <vector>
17 #include <map>
18 #include <string>
19 #include <limits>
20 
21 namespace TurtleBrains
22 {
23  //This is here to get around an issue where max is preprocessor defined in WinDef.h as comparing two value and returning
24  //the greater of the two, which prevented the call to numeric_limits<type>::max(). Calling maximum_value as a work-around.
25 #if defined(min)
26  #define tb_min_was_defined
27  #undef min
28 #endif /* min */
29 #if defined(max)
30  #define tb_max_was_defined
31  #undef max
32 #endif /* max */
33 
34  template <typename Type> Type MinimumValue(void)
35  {
36  return std::numeric_limits<Type>::min();
37  }
38  template <typename Type> Type MaximumValue(void)
39  {
40  return std::numeric_limits<Type>::max();
41  }
42 
43 #if defined(tb_min_was_defined)
44  #define min(a,b) ((a) < (b)) ? (a) : (b)
45 #endif /* tb_min_was_defined */
46 #if defined(tb_max_was_defined)
47  #define max(a, b) ((a) < (b)) ? (b) : (a)
48 #endif /* tb_max_was_defined */
49 
50  namespace Core
51  {
52 
58  {
59  public:
63  typedef std::vector<DynamicStructure> ArrayContainer;
64 
68  typedef std::map<tbCore::tbString, DynamicStructure> StructureContainer;
69 
73  DynamicStructure(void);
74 
79  DynamicStructure(const int& integerValue);
80  DynamicStructure(const tbCore::int64& integerValue);
81 
86  DynamicStructure(const float& floatValue);
87 
92  DynamicStructure(const bool& booleanValue);
93 
98  DynamicStructure(const tbCore::tbString& stringValue);
99 
104  DynamicStructure(const DynamicStructure& other);
105 
111 
117  ~DynamicStructure(void);
118 
119 
126  bool IsNil(void) const;
127 
131  bool IsArray(void) const;
132 
137  bool IsStructure(void) const;
138 
142  bool IsInteger(void) const;
143 
147  bool IsFloat(void) const;
148 
152  bool IsBoolean(void) const;
153 
157  bool IsString(void) const;
158 
159 
168  tbCore::int64 AsInteger(bool implicitConversion = kImplicitConversions) const;
169 
188  // template <typename Type> typename std::enable_if<std::is_unsigned<Type>::value, Type>::type
189  // AsRangedInteger(const tbCore::tbString& errorMessage,
190  // const Type minimumValue = MinimumValue<Type>(), const Type maximumValue = MaximumValue<Type>(),
191  // bool implicitConversion = kImplicitConversions) const
192  // {
193  // const tbCore::int64 intValue = AsInteger(implicitConversion);
194 
195  // tb_error_if(std::is_unsigned<Type>::value && intValue < 0, "%s (Expected _value(%d) to be greater than 0 for unsigned ranges.",
196  // errorMessage.c_str(), intValue);
197 
198  // //int32 intValue = -1 : 0x0001FFFF //131k
199 
200  // //uint16 min 0 : 0x00000000
201  // //uint16 max 65 : 0x0000FFFF
202 
203 
204  // //int64 value 0x00000000-FFFFFFFF
205  // //int64 min 0x00000000-00000000
206  // //int64 max 0x00000000-FFFFFFFF
207 
208  // //int32 to uint32 65xxx : 0xFFFFFFFF
209 
210 
211  // tb_error_if(static_cast<Type>(intValue) < (minimumValue) || static_cast<Type>(intValue) > (maximumValue),
212  // "%s (Expected: %d <= _value(%d)_ <= %d", errorMessage.c_str(), minimumValue, intValue, maximumValue);
213  // return static_cast<Type>(intValue);
214  // }
215  template <typename Type> Type AsRangedInteger(const tbCore::tbString& errorMessage,
216  const Type minimumValue = MinimumValue<Type>(), const Type maximumValue = MaximumValue<Type>(),
217  bool implicitConversion = kImplicitConversions) const
218  {
219  const tbCore::int64 intValue = AsInteger(implicitConversion);
220 
221  if (std::is_unsigned<Type>::value)
222  { //If type is unsigned, ensure it is not less than 0, then cast to an unsigned to compare vs other unsigned values.
223  tb_error_if(std::is_unsigned<Type>::value && intValue < 0, "%s (Expected _value(%d) to be greater than 0 for unsigned ranges.",
224  errorMessage.c_str(), intValue);
225  tb_error_if(static_cast<uint64>(intValue) < minimumValue || static_cast<uint64>(intValue) > maximumValue,
226  "%s (Expected: %d <= _value(%d)_ <= %d", errorMessage.c_str(), minimumValue, intValue, maximumValue);
227  }
228  else
229  {
230  tb_error_if(intValue < static_cast<int64>(minimumValue) ||intValue > static_cast<int64>(maximumValue),
231  "%s (Expected: %d <= _value(%d)_ <= %d", errorMessage.c_str(), minimumValue, intValue, maximumValue);
232  }
233 
234  return static_cast<Type>(intValue);
235  }
236 
245  float AsFloat(bool implicitConversion = kImplicitConversions) const;
246 
255  bool AsBoolean(bool implicitConversion = kImplicitConversions) const;
256 
265  tbCore::tbString AsString(bool implicitConversion = kImplicitConversions) const;
266 
267  //
268  // TODO: TIM: Planning: Do we want to support this? If so implement and document.
269  // @note Cannot implicitly convert to a string, will assert if type is not a string.
270  //
271  //const tbCore::tbString& AsStringRef(void) const;
272 
273 
287  tbCore::int64 AsIntegerWithDefault(const tbCore::int64& defaultValue, bool implicitConversion = true) const;
288 
306  template <typename Type> Type AsRangedIntegerWithDefault(const Type& defaultValue, const tbCore::tbString& errorMessage,
307  const Type minimumValue = MinimumValue<Type>(), const Type maximumValue = MaximumValue<Type>()) const
308  {
309  const tbCore::int64 intValue = AsIntegerWithDefault(defaultValue);
310 
311  if (std::is_unsigned<Type>::value)
312  { //If type is unsigned, ensure it is not less than 0, then cast to an unsigned to compare vs other unsigned values.
313  tb_error_if(std::is_unsigned<Type>::value && intValue < 0, "%s (Expected _value(%d) to be greater than 0 for unsigned ranges.",
314  errorMessage.c_str(), intValue);
315  tb_error_if(static_cast<uint64>(intValue) < minimumValue || static_cast<uint64>(intValue) > maximumValue,
316  "%s (Expected: %d <= _value(%d)_ <= %d", errorMessage.c_str(), minimumValue, intValue, maximumValue);
317  }
318  else
319  {
320  tb_error_if(intValue < static_cast<int64>(minimumValue) ||intValue > static_cast<int64>(maximumValue),
321  "%s (Expected: %d <= _value(%d)_ <= %d", errorMessage.c_str(), minimumValue, intValue, maximumValue);
322  }
323 
324  return static_cast<Type>(intValue);
325  }
326 
340  float AsFloatWithDefault(const float defaultValue, bool implicitConversion = true) const;
341 
355  bool AsBooleanWithDefault(const bool defaultValue, bool implicitConversion = true) const;
356 
370  tbCore::tbString AsStringWithDefault(const tbCore::tbString& defaultValue, bool implicitConversion = true) const;
371 
372 
382  void SetValue(const int& integerValue, bool implicitTypeChange = kImplicitTypeChange);
383  void SetValue(const tbCore::int64& integerValue, bool implicitTypeChange = kImplicitTypeChange);
384 
394  void SetValue(const float& floatValue, bool implicitTypeChange = kImplicitTypeChange);
395 
405  void SetValue(const bool& booleanValue, bool implicitTypeChange = kImplicitTypeChange);
406 
416  void SetValue(const tbCore::tbString& stringValue, bool implicitTypeChange = kImplicitTypeChange);
417 
418  //-------------------------------------------------------------------------------------------------------//
419  // Used ONLY for Array Values. Type must be kArrayType or kNilType to PushValue
420  //-------------------------------------------------------------------------------------------------------//
421 
432 
443  const DynamicStructure& GetValue(const size_t& arrayIndex) const;
444 
455  DynamicStructure& GetValue(const size_t& arrayIndex);
456 
467  const DynamicStructure& operator[](const size_t& arrayIndex) const;
468 
479  DynamicStructure& operator[](const size_t& arrayIndex);
480 
481  //
482  // TODO: TIM: Planning: Do we need to support int too? Teach the user how to use this.
483  //
484  //const DynamicStructure& operator[](const int& arrayIndex) const;
485 
486  //
487  // TODO: TIM: Planning: Do wee need to support int too? Teach the user how to use this.
488  //
489  //DynamicStructure& operator[](const int& arrayIndex);
490 
491 
492  //-------------------------------------------------------------------------------------------------------//
493  // Used ONLY for Structure Values. Type must be kStructureType or kNilType to AddMember
494  //-------------------------------------------------------------------------------------------------------//
495 
506  DynamicStructure& AddMember(const tbCore::tbString& memberName, const DynamicStructure& memberValue);
507 
518  DynamicStructure& SetMember(const tbCore::tbString& memberName, const DynamicStructure& memberValue);
519 
529  const DynamicStructure& GetMember(const tbCore::tbString& memberName) const;
530 
534  DynamicStructure& GetMember(const tbCore::tbString& memberName);
535 
539  const DynamicStructure& operator[](const tbCore::tbString& memberName) const;
540 
544  DynamicStructure& operator[](const tbCore::tbString& memberName);
545 
549  const DynamicStructure& operator[](const char* const memberName) const;
550 
554  DynamicStructure& operator[](const char* const memberName);
555 
560  StructureContainer::const_iterator BeginStructure(void) const;
561 
566  StructureContainer::const_iterator EndStructure(void) const;
567 
572  StructureContainer::iterator BeginStructure(void);
573 
578  StructureContainer::iterator EndStructure(void);
579 
580  //TODO: TIM: Implementation: (Test) Add a way to iterate over all Members in a structure.
581 
582  //-------------------------------------------------------------------------------------------------------//
583  // Used ONLY for Structure or Array Values.
584  //-------------------------------------------------------------------------------------------------------//
585 
593  size_t size(void) const;
594 
595  //Acceptable Inputs:
596  // "engine.pistons[0].isDamaged"
597  //const DynamicStructure& FromPath(const tbCore::tbString& path) const;
598 
602  operator tbCore::int64() const { return AsInteger(true); }
603 
607  operator float() const { return AsFloat(true); }
608 
612  operator bool() const { return AsBoolean(true); }
613 
617  operator tbCore::tbString() const { return AsString(true); }
618 
626  bool operator==(const DynamicStructure& rightSide) const;
627 
635  bool operator!=(const DynamicStructure& rightSide) const;
636 
637  private:
641  void SetToNil(void);
642 
646  tbCore::int64 ConvertToInteger(void) const;
647 
651  float ConvertToFloat(void) const;
652 
656  bool ConvertToBoolean(void) const;
657 
661  tbCore::tbString ConvertToString(void) const;
662 
666  enum DynamicStructureValueType
667  {
668  kNilType,
669 
670  kIntegerType,
671  kFloatType,
672  kBooleanType,
673  kStringType,
674 
675  kArrayType,
676  kStructureType,
677  };
678 
679 // ///
680 // /// TODO: TIM: InternalDoc: This is a TurtleBrains implementation detail, and should be documented as such.
681 // ///
682 // typedef std::vector<DynamicStructure> ArrayContainer;
683 //
684 // ///
685 // /// TODO: TIM: InternalDoc: This is a TurtleBrains implementation detail, and should be documented as such.
686 // ///
687 // typedef std::map<tbCore::tbString, DynamicStructure> StructureContainer;
688 
692  DynamicStructureValueType mValueType;
693 
694  union
695  { //Unnamed anonymous union so DynamicStrucure contains the contents as its own members, "this->mRawBytes".
696  char mRawBytes[8]; //Reserve 64-bits for whatever types follow.
697  tbCore::int64 mInteger;
698  bool mBoolean;
699  float mFloat;
700 
701  tbCore::tbString* mString;
702  ArrayContainer* mArray;
703  StructureContainer* mStructure;
704  };
705 
706  public:
711  static const unsigned int kInvalidSize;
712  static const bool kImplicitConversions;
713  static const bool kImplicitTypeChange;
714  static const float kFloatElipson;
715  };
716 
718 
719  std::ostream& operator<<(std::ostream& outputStream, const DynamicStructure& data);
720 
721  /* Overloads to make the DynamicStructure behave like a built in Integer */
722  inline bool operator==(const DynamicStructure& leftSide, const int& rightSide) { return (leftSide.AsInteger() == rightSide) ? true : false; }
723  inline bool operator==(const int& leftSide, const DynamicStructure& rightSide) { return (rightSide.AsInteger() == leftSide) ? true : false; }
724  inline bool operator!=(const DynamicStructure& leftSide, const int& rightSide) { return (leftSide.AsInteger() != rightSide) ? true : false; }
725  inline bool operator!=(const int& leftSide, const DynamicStructure& rightSide) { return (rightSide.AsInteger() != leftSide) ? true : false; }
726 
727  inline bool operator==(const DynamicStructure& leftSide, const tbCore::int64& rightSide) { return (leftSide.AsInteger() == rightSide) ? true : false; }
728  inline bool operator==(const tbCore::int64& leftSide, const DynamicStructure& rightSide) { return (rightSide.AsInteger() == leftSide) ? true : false; }
729  inline bool operator!=(const DynamicStructure& leftSide, const tbCore::int64& rightSide) { return (leftSide.AsInteger() != rightSide) ? true : false; }
730  inline bool operator!=(const tbCore::int64& leftSide, const DynamicStructure& rightSide) { return (rightSide.AsInteger() != leftSide) ? true : false; }
731 
732  inline bool operator==(const DynamicStructure& leftSide, const float& rightSide) { return (fabs(leftSide.AsFloat() - rightSide) <= DynamicStructure::kFloatElipson) ? true : false; }
733  inline bool operator==(const float& leftSide, const DynamicStructure& rightSide) { return (fabs(rightSide.AsFloat() - leftSide) <= DynamicStructure::kFloatElipson) ? true : false; }
734  inline bool operator!=(const DynamicStructure& leftSide, const float& rightSide) { return (fabs(leftSide.AsFloat() - rightSide) > DynamicStructure::kFloatElipson) ? true : false; }
735  inline bool operator!=(const float& leftSide, const DynamicStructure& rightSide) { return (fabs(rightSide.AsFloat() - leftSide) > DynamicStructure::kFloatElipson) ? true : false; }
736 
737  inline bool operator==(const DynamicStructure& leftSide, const bool& rightSide) { return (leftSide.AsBoolean() == rightSide) ? true : false; }
738  inline bool operator==(const bool& leftSide, const DynamicStructure& rightSide) { return (rightSide.AsBoolean() == leftSide) ? true : false; }
739  inline bool operator!=(const DynamicStructure& leftSide, const bool& rightSide) { return (leftSide.AsBoolean() != rightSide) ? true : false; }
740  inline bool operator!=(const bool& leftSide, const DynamicStructure& rightSide) { return (rightSide.AsBoolean() != leftSide) ? true : false; }
741 
742  inline bool operator==(const DynamicStructure& leftSide, const tbCore::tbString& rightSide) { return (leftSide.AsString() == rightSide) ? true : false; }
743  inline bool operator==(const tbCore::tbString& leftSide, const DynamicStructure& rightSide) { return (rightSide.AsString() == leftSide) ? true : false; }
744  inline bool operator!=(const DynamicStructure& leftSide, const tbCore::tbString& rightSide) { return (leftSide.AsString() != rightSide) ? true : false; }
745  inline bool operator!=(const tbCore::tbString& leftSide, const DynamicStructure& rightSide) { return (rightSide.AsString() != leftSide) ? true : false; }
746 
748 
749  }; /* namespace Core */
750 }; /* namespace TurtleBrains */
751 
752 namespace tbCore = TurtleBrains::Core;
753 
754 #endif /* _TurtleBrains_DynamicStructure_h_ */
int64_t int64
Signed integer with a size of 64 bits. Supports values from -(2^63) to (2^63 - 1).
Definition: tb_types.h:29
const DynamicStructure & GetMember(const tbCore::tbString &memberName) const
tbCore::tbString AsStringWithDefault(const tbCore::tbString &defaultValue, bool implicitConversion=true) const
tbCore::int64 AsIntegerWithDefault(const tbCore::int64 &defaultValue, bool implicitConversion=true) const
DynamicStructure & PushValue(const DynamicStructure &value)
static const bool kImplicitConversions
Definition: tb_dynamic_structure.h:712
static const DynamicStructure kNullValue
Definition: tb_dynamic_structure.h:707
tbCore::tbString AsString(bool implicitConversion=kImplicitConversions) const
StructureContainer::const_iterator EndStructure(void) const
Type AsRangedInteger(const tbCore::tbString &errorMessage, const Type minimumValue=MinimumValue< Type >(), const Type maximumValue=MaximumValue< Type >(), bool implicitConversion=kImplicitConversions) const
Definition: tb_dynamic_structure.h:215
static const float kFloatElipson
Definition: tb_dynamic_structure.h:714
Here is some information about the primary namespace.
Definition: tb_application_dialog.h:21
float AsFloat(bool implicitConversion=kImplicitConversions) const
static const tbCore::tbString kTrueAsString
Definition: tb_dynamic_structure.h:709
const DynamicStructure & operator[](const size_t &arrayIndex) const
static const unsigned int kInvalidSize
Definition: tb_dynamic_structure.h:711
const DynamicStructure & GetValue(const size_t &arrayIndex) const
bool operator!=(const DynamicStructure &rightSide) const
static const tbCore::tbString kNullAsString
Definition: tb_dynamic_structure.h:708
Type AsRangedIntegerWithDefault(const Type &defaultValue, const tbCore::tbString &errorMessage, const Type minimumValue=MinimumValue< Type >(), const Type maximumValue=MaximumValue< Type >()) const
Definition: tb_dynamic_structure.h:306
bool AsBooleanWithDefault(const bool defaultValue, bool implicitConversion=true) const
Definition: tb_dynamic_structure.h:57
float AsFloatWithDefault(const float defaultValue, bool implicitConversion=true) const
std::map< tbCore::tbString, DynamicStructure > StructureContainer
Definition: tb_dynamic_structure.h:68
static const tbCore::tbString kFalseAsString
Definition: tb_dynamic_structure.h:710
bool operator==(const DynamicStructure &rightSide) const
bool AsBoolean(bool implicitConversion=kImplicitConversions) const
std::vector< DynamicStructure > ArrayContainer
Definition: tb_dynamic_structure.h:63
StructureContainer::const_iterator BeginStructure(void) const
DynamicStructure & AddMember(const tbCore::tbString &memberName, const DynamicStructure &memberValue)
void SetValue(const int &integerValue, bool implicitTypeChange=kImplicitTypeChange)
Contains core functionality for each component of the API.
Definition: tb_debug_logger.h:91
tbCore::int64 AsInteger(bool implicitConversion=kImplicitConversions) const
#define tb_error_if(errorTest, message,...)
Definition: tb_error.h:37
std::string tbString
Definition: tb_string.h:335
DynamicStructure & operator=(const DynamicStructure &other)
static const bool kImplicitTypeChange
Definition: tb_dynamic_structure.h:713
DynamicStructure & SetMember(const tbCore::tbString &memberName, const DynamicStructure &memberValue)