ClassFactory.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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. #include "ClassFactory.h"
  24. using namespace dsr;
  25. // A global list of registered persistent classes
  26. struct ConstructorInfo {
  27. public:
  28. String type;
  29. decltype(&classConstructor) defaultConstructor;
  30. public:
  31. ConstructorInfo(String type, decltype(&classConstructor) defaultConstructor) : type(type), defaultConstructor(defaultConstructor) {}
  32. };
  33. static List<ConstructorInfo> persistentClasses;
  34. Handle<StructureDefinition> Persistent::getStructure() const {
  35. return Handle<StructureDefinition>();
  36. }
  37. static int findPersistentClass(const String &type) {
  38. for (int i = 0; i < persistentClasses.length(); i++) {
  39. if (string_match(persistentClasses[i].type, type)) {
  40. return i;
  41. }
  42. }
  43. return -1;
  44. }
  45. String Persistent::getClassName() const {
  46. return this->getStructure()->name;
  47. }
  48. void Persistent::registerPersistentClass() {
  49. int existingIndex = findPersistentClass(this->getClassName());
  50. // If a class of the name doesn't already exist
  51. if (existingIndex == -1) {
  52. // Register its constructor using the name
  53. persistentClasses.push(ConstructorInfo(this->getClassName(), this->getConstructor()));
  54. }
  55. }
  56. bool Persistent::addChild(Handle<Persistent> child) {
  57. return false;
  58. }
  59. int Persistent::getChildCount() const {
  60. return 0;
  61. }
  62. Handle<Persistent> Persistent::getChild(int index) const {
  63. return Handle<Persistent>();
  64. }
  65. void Persistent::setProperty(const ReadableString &key, const ReadableString &value, const ReadableString &fromPath) {
  66. Persistent* target = this->findAttribute(key);
  67. if (target == nullptr) {
  68. printText("setProperty: ", key, " in ", this->getClassName(), " could not be found.\n");
  69. } else {
  70. if (!target->assignValue(value, fromPath)) {
  71. printText("setProperty: The input ", value, " could not be assigned to property ", key, " because of incorrect format.\n");
  72. }
  73. }
  74. }
  75. Persistent* Persistent::findAttribute(const ReadableString &name) {
  76. return nullptr;
  77. }
  78. void Persistent::declareAttributes(StructureDefinition &target) const {}
  79. bool Persistent::assignValue(const ReadableString &content, const ReadableString &fromPath) {
  80. printText("Warning! assignValue is not implemented for ", this->getClassName(), ".\n");
  81. return false;
  82. }
  83. String& Persistent::toStreamIndented(String& out, const ReadableString& indentation) const {
  84. Handle<StructureDefinition> structure = this->getStructure();
  85. if (structure.isNull()) {
  86. throwError(U"Failed to get the structure of a class being serialized.\n");
  87. }
  88. string_append(out, indentation, U"Begin : ", structure->name, U"\n");
  89. String nextIndentation = indentation + U" ";
  90. // Save parameters
  91. for (int i = 0; i < structure->length(); i++) {
  92. String name = structure->attributes[i].name;
  93. Persistent* value = ((Persistent*)this)->findAttribute(name); // Override const
  94. if (value == nullptr) {
  95. printText("Warning! ", name, " in ", structure->name, " was declared but not found from findAttribute.\n");
  96. } else {
  97. string_append(out, nextIndentation, name, U" = ");
  98. value->toStream(out);
  99. string_append(out, U"\n");
  100. }
  101. }
  102. // Save child objects
  103. for (int c = 0; c < this->getChildCount(); c++) {
  104. this->getChild(c)->toStreamIndented(out, nextIndentation);
  105. }
  106. string_append(out, indentation, U"End\n");
  107. return out;
  108. }
  109. Handle<Persistent> dsr::createPersistentClass(const String &type, bool mustExist) {
  110. // Look for the component
  111. int existingIndex = findPersistentClass(type);
  112. if (existingIndex > -1) {
  113. return persistentClasses[existingIndex].defaultConstructor();
  114. }
  115. if (mustExist) {
  116. throwError(U"Failed to default create a class named ", type, U". Call registerPersistentClass on a temporary instance of the class to register the name.\n");
  117. }
  118. // Failed to load by name
  119. return Handle<Persistent>(); // Null
  120. }
  121. Handle<Persistent> dsr::createPersistentClassFromText(const ReadableString &text, const ReadableString &fromPath) {
  122. Handle<Persistent> rootObject, newObject;
  123. List<Handle<Persistent>> stack;
  124. string_split_callback([&rootObject, &newObject, &stack, &fromPath](ReadableString line) {
  125. int equalityIndex = string_findFirst(line, '=');
  126. if (equalityIndex > -1) {
  127. // Assignment
  128. String key = string_removeOuterWhiteSpace(string_before(line, equalityIndex));
  129. String value = string_removeOuterWhiteSpace(string_after(line, equalityIndex));
  130. stack.last()->setProperty(key, value, fromPath);
  131. } else {
  132. int colonIndex = string_findFirst(line, ':');
  133. if (colonIndex > -1) {
  134. // Declaration
  135. String keyword = string_removeOuterWhiteSpace(string_before(line, colonIndex));
  136. if (string_caseInsensitiveMatch(keyword, U"Begin")) {
  137. String type = string_removeOuterWhiteSpace(string_after(line, colonIndex));
  138. newObject = createPersistentClass(type);
  139. if (rootObject.isNull()) {
  140. rootObject = newObject;
  141. } else {
  142. if (!(stack.last()->addChild(newObject))) {
  143. throwError(U"Failed to add a child object!\n");
  144. }
  145. }
  146. stack.push(newObject);
  147. }
  148. } else {
  149. // Single keyword or empty line
  150. String keyword = string_removeOuterWhiteSpace(line);
  151. if (string_caseInsensitiveMatch(keyword, U"End")) {
  152. if (stack.length() > 0) {
  153. stack.pop();
  154. } else {
  155. throwError(U"Using end outside of root object!\n");
  156. }
  157. }
  158. }
  159. }
  160. }, text, U'\n');
  161. // Return the root component which is null on failure
  162. return rootObject;
  163. }