persistenceManager.h 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _PERSISTENCEMANAGER_H_
  23. #define _PERSISTENCEMANAGER_H_
  24. #ifndef _SIMOBJECT_H_
  25. #include "console/simObject.h"
  26. #endif
  27. #ifndef _SIMOBJECTLIST_H_
  28. #include "console/simObjectList.h"
  29. #endif
  30. #ifndef _TOKENIZER_H_
  31. #include "core/tokenizer.h"
  32. #endif
  33. class PersistenceManager : public SimObject
  34. {
  35. public:
  36. struct ParsedProperty
  37. {
  38. StringTableEntry name;
  39. const char* value;
  40. U32 arrayPos;
  41. S32 startLine;
  42. S32 endLine;
  43. S32 startPosition;
  44. S32 endPosition;
  45. S32 valueLine;
  46. S32 valuePosition;
  47. ParsedProperty()
  48. {
  49. name = NULL;
  50. value = NULL;
  51. arrayPos = 0;
  52. startLine = -1;
  53. endLine = -1;
  54. startPosition = -1;
  55. endPosition = -1;
  56. valueLine = -1;
  57. valuePosition = -1;
  58. }
  59. };
  60. struct ParsedObject
  61. {
  62. StringTableEntry name;
  63. StringTableEntry className;
  64. ParsedObject* parentObject;
  65. SimObjectPtr<SimObject> simObject;
  66. S32 nameLine;
  67. S32 namePosition;
  68. S32 startLine;
  69. S32 endLine;
  70. S32 startPosition;
  71. S32 endPosition;
  72. bool hasBraces;
  73. bool updated;
  74. Vector<ParsedProperty> properties;
  75. ParsedObject()
  76. {
  77. name = NULL;
  78. className = NULL;
  79. parentObject = NULL;
  80. simObject = NULL;
  81. nameLine = -1;
  82. namePosition = -1;
  83. startLine = -1;
  84. endLine = -1;
  85. startPosition = -1;
  86. endPosition = -1;
  87. hasBraces = true;
  88. updated = false;
  89. }
  90. };
  91. struct DirtyObject
  92. {
  93. SimObjectPtr<SimObject> *object;
  94. StringTableEntry fileName;
  95. bool isNull() const { return object->isNull(); }
  96. void setObject( SimObject* newObject ) { *object = newObject; }
  97. SimObject* getObject() const { return object->getPointer(); }
  98. DirtyObject()
  99. {
  100. object = new SimObjectPtr<SimObject>();
  101. fileName = NULL;
  102. }
  103. ~DirtyObject()
  104. {
  105. SAFE_DELETE( object );
  106. }
  107. };
  108. struct RemoveField
  109. {
  110. SimObjectPtr<SimObject> object;
  111. StringTableEntry fieldName;
  112. U32 arrayPos;
  113. RemoveField()
  114. {
  115. object = NULL;
  116. fieldName = NULL;
  117. arrayPos = 0;
  118. }
  119. };
  120. typedef Vector<DirtyObject> DirtyList;
  121. protected:
  122. typedef SimObject Parent;
  123. // Used to walk through the file and read out
  124. // the SimObject's and their properties
  125. Tokenizer mParser;
  126. // List of the objects that are flagged as dirty
  127. DirtyList mDirtyObjects;
  128. // List of fields to be removed from the objects declaration in the file
  129. Vector<RemoveField> mRemoveFields;
  130. // Temp buffers used during file parsing
  131. ParsedObject* mCurrentObject;
  132. Vector<ParsedObject*> mObjectStack;
  133. // Buffers used on a per-file basis
  134. Vector<const char*> mLineBuffer;
  135. Vector<ParsedObject*> mObjectBuffer;
  136. // Name of the currently open file
  137. const char* mCurrentFile;
  138. // Sort by filename
  139. static S32 QSORT_CALLBACK compareFiles(const void* a, const void* b);
  140. // Deletes and clears the line buffer
  141. void clearLineBuffer();
  142. // Deletes the objects and its properties
  143. void deleteObject(ParsedObject* object);
  144. // Deletes and clears the object buffer,
  145. // the object stack, and the current object
  146. void clearObjects();
  147. // Clears all of the data related to the
  148. // currently loaded file
  149. void clearFileData();
  150. // Updates the changed values of a dirty object
  151. // Also handles a new object
  152. void updateObject(SimObject* object, ParsedObject* parentObject = NULL);
  153. // Removes the current object without saving it
  154. void killObject();
  155. // Saves the current object and restores the last object in the stack (if any)
  156. void saveObject();
  157. // Parses an object from the current position in the parser
  158. void parseObject();
  159. // Reads the file into the line buffer
  160. bool readFile(const char* fileName);
  161. // Parses the ParsedObjects out of the file
  162. bool parseFile(const char* fileName);
  163. // Writes the line buffer out to the current file
  164. bool saveDirtyFile();
  165. // Attempts to look up the property in the ParsedObject
  166. S32 getPropertyIndex(ParsedObject* parsedObject, const char* fieldName, U32 arrayPos = 0);
  167. // Gets the amount of indent on the ParsedObject.
  168. char* getObjectIndent(ParsedObject* object);
  169. // Loops through all of the objects and properties that are on the same
  170. // line after the startPos and updates their position offests accordingly
  171. void updatePositions(U32 lineNumber, U32 startPos, S32 diff);
  172. // Loops thought all of the objects and updates their line offsets
  173. void updateLineOffsets(U32 startLine, S32 diff, ParsedObject* skipObject = NULL);
  174. // Replaces a token on a given line with a new value
  175. // This also calls updatePositions() to account for size
  176. // differences between the old token and the new token
  177. void updateToken(const U32 lineNumber, const U32 linePosition, const U32 oldValueLen, const char* newValue, bool addQuotes = false);
  178. // Gets the field value from the SimObject. Note that this does
  179. // allocate memory that needs to be cleaned up elsewhere
  180. const char* getFieldValue(SimObject* object, const char* fieldName, U32 arrayPos);
  181. // Attempt to find the parent object
  182. ParsedObject* findParentObject(SimObject* object, ParsedObject* parentObject = NULL);
  183. // Attempt to find the matching ParsedObject in our object buffer
  184. ParsedObject* findParsedObject(SimObject* object, ParsedObject* parentObject = NULL);
  185. // Attempt to find the matching DirtyObject for a passed SimObject in our DirtyItems list.
  186. DirtyObject* findDirtyObject(SimObject* object);
  187. // Is this field on the remove list
  188. bool findRemoveField(SimObject* object, const char* fieldName, U32 arrayPos = 0);
  189. // Helper function that allocates a new string and properly formats the data into it
  190. // Note that this allocates memory that needs to be cleaned up elsewhere
  191. const char* createNewProperty(const char* name, const char* value, bool isArray = false, U32 arrayPos = 0);
  192. // Test to see if there is anything valid on the line
  193. bool isEmptyLine(const char* line);
  194. // Removes a line safely from the line buffer
  195. void removeLine(U32 lineNumber);
  196. // Remove a block of text from the line buffer. It returns
  197. // the number of lines removed if removeEmptyLines is set to true.
  198. void removeTextBlock(U32 startLine, U32 endLine, U32 startPos, U32 endPos, bool removeEmptyLines);
  199. // Removes a ParsedObject from the line buffer
  200. // (everything from the startLine to the endLine)
  201. void removeParsedObject(ParsedObject* parsedObject);
  202. // Removes a property from the line buffer
  203. void removeField(const ParsedProperty& prop);
  204. // Write out properties
  205. // Returns the number of new lines added
  206. U32 writeProperties(const Vector<const char*>& properties, const U32 insertLine, const char* objectIndent);
  207. // Write out a new object
  208. ParsedObject* writeNewObject(SimObject* object, const Vector<const char*>& properties, const U32 insertLine, ParsedObject* parentObject = NULL);
  209. public:
  210. PersistenceManager();
  211. virtual ~PersistenceManager();
  212. bool onAdd();
  213. void onRemove();
  214. // Adds an object to the dirty list
  215. // Optionally changes the object's filename
  216. bool setDirty(SimObject* object, const char* fileName = NULL);
  217. // Removes the object from the dirty list
  218. void removeDirty(SimObject* object);
  219. // Add a field to the remove list to cut it out of the object's declaration
  220. void addRemoveField(SimObject* object, const char* fieldName);
  221. // Test to see if an object is on the dirty list
  222. bool isDirty(SimObject* object);
  223. // Returns whether or not there are dirty objects
  224. bool hasDirty() const { return !mDirtyObjects.empty(); }
  225. // Saves the dirty objects out to their respective files
  226. // and clears the dirty object data
  227. bool saveDirty();
  228. // Saves out a single object, if it's dirty
  229. bool saveDirtyObject(SimObject* object);
  230. // Clears all of the dirty object data
  231. void clearAll();
  232. // Removes the object from the file
  233. void removeObjectFromFile(SimObject* object, const char* fileName = NULL);
  234. // Deletes all of the objects that were created from this file
  235. void deleteObjectsFromFile(const char* fileName);
  236. // Returns a list of the dirty objects
  237. const DirtyList& getDirtyList() { return mDirtyObjects; }
  238. DECLARE_CONOBJECT(PersistenceManager);
  239. };
  240. #endif