ClassFactory.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // zlib open source license
  2. //
  3. // Copyright (c) 2018 to 2019 David Forsgren Piuva
  4. //
  5. // This software is provided 'as-is', without any express or implied
  6. // warranty. In no event will the authors be held liable for any damages
  7. // arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any purpose,
  10. // including commercial applications, and to alter it and redistribute it
  11. // freely, subject to the following restrictions:
  12. //
  13. // 1. The origin of this software must not be misrepresented; you must not
  14. // claim that you wrote the original software. If you use this software
  15. // in a product, an acknowledgment in the product documentation would be
  16. // appreciated but is not required.
  17. //
  18. // 2. Altered source versions must be plainly marked as such, and must not be
  19. // misrepresented as being the original software.
  20. //
  21. // 3. This notice may not be removed or altered from any source
  22. // distribution.
  23. #ifndef DFPSR_PERSISTENT_CLASSFACTORY
  24. #define DFPSR_PERSISTENT_CLASSFACTORY
  25. #include "../api/stringAPI.h"
  26. #include "../api/fileAPI.h"
  27. #include "../collection/List.h"
  28. #include <memory>
  29. namespace dsr {
  30. class Persistent;
  31. // Reference method for creating a persistent class
  32. inline dsr::Handle<Persistent> classConstructor() {
  33. return dsr::Handle<Persistent>(); // Null
  34. }
  35. // Must be used in each class inheriting from Persistent (both directly and indirectly)
  36. #define PERSISTENT_DECLARATION(CLASS) \
  37. dsr::Handle<dsr::StructureDefinition> getStructure() const override; \
  38. decltype(&dsr::classConstructor) getConstructor() const override; \
  39. explicit CLASS(const dsr::ReadableString &content, const dsr::ReadableString &fromPath);
  40. // Must be used in the implementation of each class inheriting from Persistent
  41. #define PERSISTENT_DEFINITION(CLASS) \
  42. dsr::Handle<dsr::StructureDefinition> CLASS##Type; \
  43. dsr::Handle<dsr::StructureDefinition> CLASS::getStructure() const { \
  44. if (CLASS##Type.isNull()) { \
  45. CLASS##Type = dsr::handle_create<dsr::StructureDefinition>(U ## #CLASS).setName("Persistent " #CLASS " StructureDefinition"); \
  46. this->declareAttributes((CLASS##Type).getReference()); \
  47. } \
  48. return CLASS##Type; \
  49. } \
  50. CLASS::CLASS(const dsr::ReadableString &content, const dsr::ReadableString &fromPath) { \
  51. this->assignValue(content, fromPath); \
  52. } \
  53. dsr::Handle<dsr::Persistent> CLASS##Constructor() { \
  54. return dsr::handle_dynamicCast<dsr::Persistent>(dsr::handle_create<CLASS>().setName("Persistent " #CLASS)); \
  55. } \
  56. decltype(&dsr::classConstructor) CLASS::getConstructor() const { \
  57. return &CLASS##Constructor; \
  58. }
  59. class PersistentAttribute {
  60. public:
  61. String name; // The name of the attribute
  62. public:
  63. PersistentAttribute() {}
  64. explicit PersistentAttribute(const String &name) : name(name) {}
  65. };
  66. class StructureDefinition {
  67. public:
  68. // The name of the class
  69. String name;
  70. // All attributes in the data structure, including attributes inherited from the parent class
  71. List<PersistentAttribute> attributes;
  72. public:
  73. StructureDefinition() {}
  74. explicit StructureDefinition(const String &name) : name(name) {}
  75. // TODO: Prevent adding the same name twice
  76. void declareAttribute(const String &name) {
  77. this->attributes.push(PersistentAttribute(name));
  78. }
  79. int length() {
  80. return this->attributes.length();
  81. }
  82. };
  83. class Persistent : public Printable {
  84. public:
  85. // Persistent attributes may not be write protected
  86. virtual Persistent* findAttribute(const ReadableString &name);
  87. virtual Handle<StructureDefinition> getStructure() const;
  88. virtual decltype(&classConstructor) getConstructor() const = 0;
  89. // Call from the start of main, to allow constructing the class by name
  90. void registerPersistentClass();
  91. void setProperty(const ReadableString &key, const ReadableString &value, const ReadableString &fromPath);
  92. String getClassName() const;
  93. public:
  94. // Override for non-atomic collection types
  95. // Each child object will be constructed using Begin and End keywords directly inside of the parent
  96. // For atomic collections, direct parsing and generation of comma separated lists would be more compact
  97. // Attempt to add another persistent object
  98. // Return false if the child object was rejected
  99. // Make sure that connections that would create an infinite loop are rejected
  100. virtual bool addChild(Handle<Persistent> child);
  101. virtual int getChildCount() const;
  102. virtual Handle<Persistent> getChild(int index) const;
  103. public:
  104. // Override for new compound types
  105. // Override declareAttributes if your persistent structure has any variables to register as persistent
  106. // Use the MAKE_PERSISTENT macro with the attribute name for each persistent member
  107. // Each persistent attribute's type must also inherit from Persistent and start with the PERSISTENT_IMPL macro
  108. virtual void declareAttributes(StructureDefinition &target) const;
  109. public:
  110. // Override for new atomic types
  111. // Assign content from a string
  112. // Returns true on success and false if no assigment was made
  113. virtual bool assignValue(const ReadableString &content, const ReadableString &fromPath);
  114. // Save to a stream using any indentation
  115. virtual String& toStreamIndented(String& out, const ReadableString& indentation) const override;
  116. };
  117. // Macro to be placed at the start of the global main function
  118. // The dsr namespace must be used to access registerPersistentClass
  119. #define REGISTER_PERSISTENT_CLASS(CLASS) \
  120. (CLASS().registerPersistentClass());
  121. // Create a single class instance without any content
  122. Handle<Persistent> createPersistentClass(const String &type, bool mustExist = true);
  123. // Create a class instance from text
  124. Handle<Persistent> createPersistentClassFromText(const ReadableString &text, const ReadableString &fromPath);
  125. }
  126. #endif