TurtleBrains  0.3.0
High quality, portable, C++ API for native application and 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 
85  DynamicStructure(const float& floatValue);
86 
91  DynamicStructure(const bool& booleanValue);
92 
97  DynamicStructure(const tbCore::tbString& stringValue);
98 
103  DynamicStructure(const DynamicStructure& other);
104 
110 
116  ~DynamicStructure(void);
117 
118 
125  bool IsNil(void) const;
126 
130  bool IsArray(void) const;
131 
136  bool IsStructure(void) const;
137 
141  bool IsInteger(void) const;
142 
146  bool IsFloat(void) const;
147 
151  bool IsBoolean(void) const;
152 
156  bool IsString(void) const;
157 
158 
167  tbCore::int64 AsInteger(bool implicitConversion = kImplicitConversions) const;
168 
189  template <typename Type> Type 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  tb_error_if(intValue < static_cast<tbCore::int64>(minimumValue) || intValue > static_cast<tbCore::int64>(maximumValue),
195  "%s (Expected: %d <= _value(%d)_ <= %d", errorMessage.c_str(), minimumValue, intValue, maximumValue);
196  return static_cast<Type>(intValue);
197  }
198 
207  float AsFloat(bool implicitConversion = kImplicitConversions) const;
208 
217  bool AsBoolean(bool implicitConversion = kImplicitConversions) const;
218 
227  tbCore::tbString AsString(bool implicitConversion = kImplicitConversions) const;
228 
229  //
230  // TODO: TIM: Planning: Do we want to support this? If so implement and document.
231  // @note Cannot implicitly convert to a string, will assert if type is not a string.
232  //
233  //const tbCore::tbString& AsStringRef(void) const;
234 
235 
246  tbCore::int64 AsIntegerWithDefault(const int defaultValue) const;
247 
265  template <typename Type> Type AsRangedIntegerWithDefault(const Type& defaultValue, const tbCore::tbString& errorMessage,
266  const Type minimumValue = MinimumValue<Type>(), const Type maximumValue = MaximumValue<Type>()) const
267  {
268  const tbCore::int64 intValue = AsIntegerWithDefault(defaultValue);
269  tb_error_if(intValue < minimumValue || intValue > maximumValue, "%s (Expected: %d <= _value_ <= %d",
270  errorMessage.c_str(), minimumValue, maximumValue);
271  return static_cast<Type>(intValue);
272  }
273 
284  float AsFloatWithDefault(const float defaultValue) const;
285 
296  bool AsBooleanWithDefault(const bool defaultValue) const;
297 
308  tbCore::tbString AsStringWithDefault(const tbCore::tbString& defaultValue) const;
309 
310 
320  void SetValue(const int& integerValue, bool implicitTypeChange = kImplicitTypeChange);
321 
331  void SetValue(const float& floatValue, bool implicitTypeChange = kImplicitTypeChange);
332 
342  void SetValue(const bool& booleanValue, bool implicitTypeChange = kImplicitTypeChange);
343 
353  void SetValue(const tbCore::tbString& stringValue, bool implicitTypeChange = kImplicitTypeChange);
354 
355  //-------------------------------------------------------------------------------------------------------//
356  // Used ONLY for Array Values. Type must be kArrayType or kNilType to PushValue
357  //-------------------------------------------------------------------------------------------------------//
358 
372 
383  const DynamicStructure& GetValue(const size_t& arrayIndex) const;
384 
395  DynamicStructure& GetValue(const size_t& arrayIndex);
396 
407  const DynamicStructure& operator[](const size_t& arrayIndex) const;
408 
419  DynamicStructure& operator[](const size_t& arrayIndex);
420 
421  //
422  // TODO: TIM: Planning: Do we need to support int too? Teach the user how to use this.
423  //
424  //const DynamicStructure& operator[](const int& arrayIndex) const;
425 
426  //
427  // TODO: TIM: Planning: Do wee need to support int too? Teach the user how to use this.
428  //
429  //DynamicStructure& operator[](const int& arrayIndex);
430 
431 
432  //-------------------------------------------------------------------------------------------------------//
433  // Used ONLY for Structure Values. Type must be kStructureType or kNilType to AddMember
434  //-------------------------------------------------------------------------------------------------------//
435 
446  DynamicStructure& AddMember(const tbCore::tbString& memberName, const DynamicStructure& memberValue);
447 
458  DynamicStructure& SetMember(const tbCore::tbString& memberName, const DynamicStructure& memberValue);
459 
469  const DynamicStructure& GetMember(const tbCore::tbString& memberName) const;
470 
474  DynamicStructure& GetMember(const tbCore::tbString& memberName);
475 
479  const DynamicStructure& operator[](const tbCore::tbString& memberName) const;
480 
484  DynamicStructure& operator[](const tbCore::tbString& memberName);
485 
489  const DynamicStructure& operator[](const char* const memberName) const;
490 
494  DynamicStructure& operator[](const char* const memberName);
495 
500  StructureContainer::const_iterator BeginStructure(void) const;
501 
506  StructureContainer::const_iterator EndStructure(void) const;
507 
512  StructureContainer::iterator BeginStructure(void);
513 
518  StructureContainer::iterator EndStructure(void);
519 
520  //TODO: TIM: Implementation: (Test) Add a way to iterate over all Members in a structure.
521 
522  //-------------------------------------------------------------------------------------------------------//
523  // Used ONLY for Structure or Array Values.
524  //-------------------------------------------------------------------------------------------------------//
525 
533  size_t size(void) const;
534 
535  //Acceptable Inputs:
536  // "engine.pistons[0].isDamaged"
537  //const MagicValue& FromPath(const tbCore::tbString& path) const;
538 
542  operator tbCore::int64() const { return AsInteger(true); }
543 
547  operator float() const { return AsFloat(true); }
548 
552  operator bool() const { return AsBoolean(true); }
553 
557  operator tbCore::tbString() const { return AsString(true); }
558 
566  bool operator==(const DynamicStructure& rightSide) const;
567 
568  private:
572  void SetToNil(void);
573 
577  tbCore::int64 ConvertToInteger(void) const;
578 
582  float ConvertToFloat(void) const;
583 
587  bool ConvertToBoolean(void) const;
588 
592  tbCore::tbString ConvertToString(void) const;
593 
597  enum DynamicStructureValueType
598  {
599  kNilType,
600 
601  kIntegerType,
602  kFloatType,
603  kBooleanType,
604  kStringType,
605 
606  kArrayType,
607  kStructureType,
608  };
609 
610 // ///
611 // /// TODO: TIM: InternalDoc: This is a TurtleBrains implementation detail, and should be documented as such.
612 // ///
613 // typedef std::vector<DynamicStructure> ArrayContainer;
614 //
615 // ///
616 // /// TODO: TIM: InternalDoc: This is a TurtleBrains implementation detail, and should be documented as such.
617 // ///
618 // typedef std::map<tbCore::tbString, DynamicStructure> StructureContainer;
619 
623  DynamicStructureValueType mValueType;
624 
625  union
626  { //Unnamed anonymous union so DynamicStrucure contains the contents as its own members, "this->mRawBytes".
627  char mRawBytes[8]; //Reserve 64-bits for whatever types follow.
628  tbCore::int64 mInteger;
629  bool mBoolean;
630  float mFloat;
631 
632  tbCore::tbString* mString;
633  ArrayContainer* mArray;
634  StructureContainer* mStructure;
635  };
636 
637  public:
642  static const unsigned int kInvalidSize;
643  static const bool kTypeSafeArrays;
644  static const bool kImplicitConversions;
645  static const bool kImplicitTypeChange;
646  static const float kFloatElipson;
647  };
648 
650 
651  std::ostream& operator<<(std::ostream& outputStream, const DynamicStructure& data);
652 
653  /* Overloads to make the DynamicStructure behave like a built in Integer */
654  inline bool operator==(const DynamicStructure& leftSide, const int& rightSide) { return (leftSide.AsInteger() == rightSide) ? true : false; }
655  inline bool operator==(const int& leftSide, const DynamicStructure& rightSide) { return (rightSide.AsInteger() == leftSide) ? true : false; }
656  inline bool operator!=(const DynamicStructure& leftSide, const int& rightSide) { return (leftSide.AsInteger() != rightSide) ? true : false; }
657  inline bool operator!=(const int& leftSide, const DynamicStructure& rightSide) { return (rightSide.AsInteger() != leftSide) ? true : false; }
658 
659  inline bool operator==(const DynamicStructure& leftSide, const float& rightSide) { return (fabs(leftSide.AsFloat() - rightSide) <= DynamicStructure::kFloatElipson) ? true : false; }
660  inline bool operator==(const float& leftSide, const DynamicStructure& rightSide) { return (fabs(rightSide.AsFloat() - leftSide) <= DynamicStructure::kFloatElipson) ? true : false; }
661  inline bool operator!=(const DynamicStructure& leftSide, const float& rightSide) { return (fabs(leftSide.AsFloat() - rightSide) > DynamicStructure::kFloatElipson) ? true : false; }
662  inline bool operator!=(const float& leftSide, const DynamicStructure& rightSide) { return (fabs(rightSide.AsFloat() - leftSide) > DynamicStructure::kFloatElipson) ? true : false; }
663 
664  inline bool operator==(const DynamicStructure& leftSide, const bool& rightSide) { return (leftSide.AsBoolean() == rightSide) ? true : false; }
665  inline bool operator==(const bool& leftSide, const DynamicStructure& rightSide) { return (rightSide.AsBoolean() == leftSide) ? true : false; }
666  inline bool operator!=(const DynamicStructure& leftSide, const bool& rightSide) { return (leftSide.AsBoolean() != rightSide) ? true : false; }
667  inline bool operator!=(const bool& leftSide, const DynamicStructure& rightSide) { return (rightSide.AsBoolean() != leftSide) ? true : false; }
668 
669  inline bool operator==(const DynamicStructure& leftSide, const tbCore::tbString& rightSide) { return (leftSide.AsString() == rightSide) ? true : false; }
670  inline bool operator==(const tbCore::tbString& leftSide, const DynamicStructure& rightSide) { return (rightSide.AsString() == leftSide) ? true : false; }
671  inline bool operator!=(const DynamicStructure& leftSide, const tbCore::tbString& rightSide) { return (leftSide.AsString() != rightSide) ? true : false; }
672  inline bool operator!=(const tbCore::tbString& leftSide, const DynamicStructure& rightSide) { return (rightSide.AsString() != leftSide) ? true : false; }
673 
675 
676  }; /* namespace Core */
677 }; /* namespace TurtleBrains */
678 
679 namespace tbCore = TurtleBrains::Core;
680 
681 #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
DynamicStructure & PushValue(const DynamicStructure &value)
static const bool kImplicitConversions
Definition: tb_dynamic_structure.h:644
static const DynamicStructure kNullValue
Definition: tb_dynamic_structure.h:638
tbCore::tbString AsString(bool implicitConversion=kImplicitConversions) const
tbCore::tbString AsStringWithDefault(const tbCore::tbString &defaultValue) 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:189
static const float kFloatElipson
Definition: tb_dynamic_structure.h:646
Contains all functions, classes and helpers related to game/application development written by Tim "B...
Definition: tb_application_dialog.h:21
float AsFloat(bool implicitConversion=kImplicitConversions) const
static const tbCore::tbString kTrueAsString
Definition: tb_dynamic_structure.h:640
float AsFloatWithDefault(const float defaultValue) const
const DynamicStructure & operator[](const size_t &arrayIndex) const
static const unsigned int kInvalidSize
Definition: tb_dynamic_structure.h:642
const DynamicStructure & GetValue(const size_t &arrayIndex) const
static const bool kTypeSafeArrays
Definition: tb_dynamic_structure.h:643
static const tbCore::tbString kNullAsString
Definition: tb_dynamic_structure.h:639
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:265
Definition: tb_dynamic_structure.h:57
std::map< tbCore::tbString, DynamicStructure > StructureContainer
Definition: tb_dynamic_structure.h:68
static const tbCore::tbString kFalseAsString
Definition: tb_dynamic_structure.h:641
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)
tbCore::int64 AsIntegerWithDefault(const int defaultValue) const
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)
bool AsBooleanWithDefault(const bool defaultValue) const
static const bool kImplicitTypeChange
Definition: tb_dynamic_structure.h:645
DynamicStructure & SetMember(const tbCore::tbString &memberName, const DynamicStructure &memberValue)