const_config.h - Engine C API Reference

const_config.h
  1. #pragma once
  2. #include <string.h>
  3. #include "assert.h"
  4. #include "platform.h"
  5. // This file is the runtime representation of a config data structure. A config data structure
  6. // is a JSON-like object for representing generic data. This format is suitable when the
  7. // development cost of creating a custom binary format is big and the benefits are small.
  8. // (I.e. for any data that is not massive bulk data -- such as small configuration files.)
  9. //
  10. // The runtime format is essential (type, data) where type is a four-byte type identifier
  11. // and data is four bytes of data. We use four bytes for the type identifier for alignment
  12. // purposes. Note that the runtime format represent an entire config object as a single
  13. // memory block. Local pointers inside the memory block are used to build structure.
  14. //
  15. // Note that it is possible to optimize this format further to squeeze out a few more bytes.
  16. namespace stingray_plugin_foundation {
  17. struct ConstConfigArray;
  18. struct ConstConfigObject;
  19. namespace const_config
  20. {
  21. // Type used for offset parameters
  22. typedef unsigned offset_t;
  23. // The supported value types
  24. enum ValueType {NIL, BOOL, INTEGER, FLOAT, STRING, ARRAY, OBJECT};
  25. // Generic representation of a value of one of the types.
  26. union Value {
  27. int b;
  28. int i;
  29. float f;
  30. offset_t s; // Offset to char *
  31. offset_t a; // Offset to ConstConfigArray *
  32. offset_t o; // Offset toConstConfigObject *
  33. };
  34. }
  35. // Represents the root object (the first item in the memory block).
  36. struct ConstConfigRoot
  37. {
  38. int type; // ValueType
  39. const_config::Value value;
  40. };
  41. // Represents an array. Note that the type is only stored once, all objects in an array
  42. // must have the same type. In the memory layout, the ConstConfigArray block is followed
  43. // by *size* data items (which are bool, int, float, etc) depending on type.
  44. struct ConstConfigArray
  45. {
  46. int type; // ValueType
  47. int size;
  48. const_config::Value first_item; // size data items follows in memory
  49. };
  50. // Represents an entry in a ConstConfigObject. Stores the key (always a string), the
  51. // type of the entry and the value.
  52. struct ConstConfigObjectEntry
  53. {
  54. const_config::offset_t name; // Offset to name
  55. int type; // ValueType
  56. const_config::Value value;
  57. };
  58. // Represents an object. In the memory layout, ConstConfigObject is followed by
  59. // *size* ConstConfigObjectEntry structures that contain the actual objects.
  60. struct ConstConfigObject
  61. {
  62. int size;
  63. ConstConfigObjectEntry first_entry;
  64. };
  65. // Convenience class used to access config data.
  66. class ConstConfigItem
  67. {
  68. public:
  69. // Creates a nil config item.
  70. ConstConfigItem() : _base(nullptr), _type(const_config::NIL) {}
  71. // Creates a config item from the specified root.
  72. ConstConfigItem(const ConstConfigRoot &root) : _base((const char *)&root), _type(root.type), _value(root.value) {}
  73. // Creates a config item with the specified base, type and data.
  74. ConstConfigItem(const char *base, const_config::ValueType t, const_config::Value v) : _base(base), _type(t), _value(v) {}
  75. bool is_nil() const {return _type == const_config::NIL;}
  76. bool is_bool() const {return _type == const_config::BOOL;}
  77. bool is_false() const {return _type == const_config::BOOL && !_value.b;}
  78. bool is_true() const {return _type == const_config::BOOL && _value.b;}
  79. bool is_integer() const {return _type == const_config::INTEGER;}
  80. bool is_float() const {return _type == const_config::FLOAT;}
  81. bool is_number() const {return is_integer() || is_float();}
  82. bool is_string() const {return _type == const_config::STRING;}
  83. bool is_resource() const { return is_string() || is_object() && (*this)["$resource_name"].is_string(); }
  84. bool is_resource(const char *type) const { return is_resource() && (is_string() || (*this)["$resource_type"].is_string() && strcmp((*this)["$resource_type"].to_string(),type)==0); }
  85. bool is_array() const { return _type == const_config::ARRAY; }
  86. bool is_object() const {return _type == const_config::OBJECT;}
  87. bool to_bool() const {XENSURE(is_bool()); return _value.b != 0;}
  88. int to_integer() const {XENSURE(is_integer()); return _value.i;}
  89. float to_float() const {return is_float() ? _value.f : float(to_integer());}
  90. const char *to_string() const {XENSURE(is_string()); return raw_s();}
  91. const char *to_resource(const char *type) const {
  92. XENSURE(is_resource(type));
  93. if (is_string()) {
  94. return to_string();
  95. }
  96. return (*this)["$resource_name"].to_string();
  97. }
  98. bool operator||(bool b) const {return is_bool() ? to_bool() : b;}
  99. int operator||(int i) const {return is_integer() ? _value.i : i;}
  100. unsigned operator||(unsigned i) const {return is_integer() ? unsigned(_value.i) : i;}
  101. float operator||(float f) const {return is_float() ? _value.f : (is_integer() ? _value.i : f);}
  102. const char *operator||(const char *s) const {return is_string() ? raw_s() : s;}
  103. ConstConfigItem operator||(ConstConfigItem o) {return is_nil() ? o : *this;}
  104. int size() const {return is_array() ? raw_a()->size : 0;}
  105. int n_items() const {return is_object() ? raw_o()->size : 0;}
  106. ConstConfigItem operator[](int i) const {
  107. if (!is_array())
  108. return ConstConfigItem();
  109. if (i<0 || i>=raw_a()->size)
  110. return ConstConfigItem();
  111. const ConstConfigArray &arr = *raw_a();
  112. return ConstConfigItem(_base, (const_config::ValueType)arr.type, *(&arr.first_item + i));
  113. }
  114. ConstConfigItem operator[](const char *s) const {
  115. if (!is_object())
  116. return ConstConfigItem();
  117. const ConstConfigObject &obj = *raw_o();
  118. for (int i=0; i<obj.size; ++i) {
  119. const ConstConfigObjectEntry &e = *(&obj.first_entry + i);
  120. if (strcmp(_base + e.name, s) == 0)
  121. return ConstConfigItem(_base, (const_config::ValueType)e.type, e.value);
  122. }
  123. return ConstConfigItem();
  124. }
  125. ConstConfigItem item(int i, const char **s = 0) const {
  126. if (!is_object())
  127. return ConstConfigItem();
  128. const ConstConfigObject &obj = *raw_o();
  129. if (i<0 || i>=obj.size)
  130. return ConstConfigItem();
  131. const ConstConfigObjectEntry &e = *(&obj.first_entry + i);
  132. if(s) *s = _base + e.name;
  133. return ConstConfigItem(_base, (const_config::ValueType)e.type, e.value);
  134. }
  135. private:
  136. const char *raw_s() const {return _base + _value.s;}
  137. const ConstConfigArray *raw_a() const {return (ConstConfigArray *)(_base + _value.a);}
  138. const ConstConfigObject *raw_o() const {return (ConstConfigObject *)(_base + _value.o);}
  139. const char *_base; // Base for offsets
  140. int _type; // ValueType
  141. const_config::Value _value;
  142. };
  143. } // namespace stingray_plugin_foundation