xml.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #pragma once
  9. #include <algorithm>
  10. #include <stack>
  11. #include "IXml.h"
  12. // track some XML stats. only to find persistent XML nodes in the system
  13. // slow, so disable by default
  14. //#define CRY_COLLECT_XML_NODE_STATS
  15. //#undef CRY_COLLECT_XML_NODE_STATS
  16. struct IXmlStringPool
  17. {
  18. public:
  19. IXmlStringPool() { m_refCount = 0; }
  20. virtual ~IXmlStringPool() {};
  21. void AddRef() { m_refCount++; };
  22. void Release()
  23. {
  24. if (--m_refCount <= 0)
  25. {
  26. delete this;
  27. }
  28. };
  29. virtual const char* AddString(const char* str) = 0;
  30. private:
  31. int m_refCount;
  32. };
  33. /************************************************************************/
  34. /* XmlParser class, Parse xml and return root xml node if success. */
  35. /************************************************************************/
  36. class XmlParser
  37. : public IXmlParser
  38. {
  39. public:
  40. explicit XmlParser(bool bReuseStrings);
  41. ~XmlParser() override;
  42. void AddRef() override
  43. {
  44. ++m_nRefCount;
  45. }
  46. void Release() override
  47. {
  48. if (--m_nRefCount <= 0)
  49. {
  50. delete this;
  51. }
  52. }
  53. XmlNodeRef ParseFile(const char* filename, bool bCleanPools) override;
  54. XmlNodeRef ParseBuffer(const char* buffer, int nBufLen, bool bCleanPools, bool bSuppressWarnings = false) override;
  55. const char* getErrorString() const { return m_errorString; }
  56. private:
  57. int m_nRefCount;
  58. XmlString m_errorString;
  59. class XmlParserImp* m_pImpl;
  60. };
  61. // Compare function for string comparasion, can be strcmp or _stricmp
  62. typedef int (__cdecl * XmlStrCmpFunc)(const char* str1, const char* str2);
  63. extern XmlStrCmpFunc g_pXmlStrCmp;
  64. //////////////////////////////////////////////////////////////////////////
  65. // XmlAttribute class
  66. //////////////////////////////////////////////////////////////////////////
  67. struct XmlAttribute
  68. {
  69. const char* key;
  70. const char* value;
  71. bool operator<(const XmlAttribute& attr) const { return g_pXmlStrCmp(key, attr.key) < 0; }
  72. bool operator>(const XmlAttribute& attr) const { return g_pXmlStrCmp(key, attr.key) > 0; }
  73. bool operator==(const XmlAttribute& attr) const { return g_pXmlStrCmp(key, attr.key) == 0; }
  74. bool operator!=(const XmlAttribute& attr) const { return g_pXmlStrCmp(key, attr.key) != 0; }
  75. };
  76. //! Xml node attributes class.
  77. typedef std::vector<XmlAttribute> XmlAttributes;
  78. typedef XmlAttributes::iterator XmlAttrIter;
  79. typedef XmlAttributes::const_iterator XmlAttrConstIter;
  80. /**
  81. ******************************************************************************
  82. * CXmlNode class
  83. * Never use CXmlNode directly instead use reference counted XmlNodeRef.
  84. ******************************************************************************
  85. */
  86. class CXmlNode
  87. : public IXmlNode
  88. {
  89. public:
  90. //! Constructor.
  91. CXmlNode();
  92. CXmlNode(const char* tag, bool bReuseStrings, bool bIsProcessingInstruction = false);
  93. //! Destructor.
  94. ~CXmlNode() override;
  95. //////////////////////////////////////////////////////////////////////////
  96. // Custom new/delete with pool allocator.
  97. //////////////////////////////////////////////////////////////////////////
  98. //void* operator new( size_t nSize );
  99. //void operator delete( void *ptr );
  100. void DeleteThis() override;
  101. //! Create new XML node.
  102. XmlNodeRef createNode(const char* tag) override;
  103. //! Get XML node tag.
  104. const char* getTag() const override
  105. { return m_tag; };
  106. void setTag(const char* tag) override;
  107. //! Return true if given tag equal to node tag.
  108. bool isTag(const char* tag) const override;
  109. //! Get XML Node attributes.
  110. int getNumAttributes() const override
  111. { return m_pAttributes ? (int)m_pAttributes->size() : 0; };
  112. //! Return attribute key and value by attribute index.
  113. bool getAttributeByIndex(int index, const char** key, const char** value) override;
  114. //! Return attribute key and value by attribute index, string version.
  115. virtual bool getAttributeByIndex(int index, XmlString& key, XmlString& value);
  116. void copyAttributes(XmlNodeRef fromNode) override;
  117. //! Get XML Node attribute for specified key.
  118. const char* getAttr(const char* key) const override;
  119. //! Get XML Node attribute for specified key.
  120. // Returns true if the attribute existes, alse otherwise.
  121. bool getAttr(const char* key, const char** value) const override;
  122. //! Check if attributes with specified key exist.
  123. bool haveAttr(const char* key) const override;
  124. //! Creates new xml node and add it to childs list.
  125. XmlNodeRef newChild(const char* tagName) override;
  126. //! Adds new child node.
  127. void addChild(const XmlNodeRef& node) override;
  128. //! Remove child node.
  129. void removeChild(const XmlNodeRef& node) override;
  130. //! Remove all child nodes.
  131. void removeAllChilds() override;
  132. //! Get number of child XML nodes.
  133. int getChildCount() const override { return m_pChilds ? (int)m_pChilds->size() : 0; }
  134. //! Get XML Node child nodes.
  135. XmlNodeRef getChild(int i) const override;
  136. //! Find node with specified tag.
  137. XmlNodeRef findChild(const char* tag) const override;
  138. void deleteChild(const char* tag);
  139. //! Get parent XML node.
  140. XmlNodeRef getParent() const override { return m_parent; }
  141. void setParent(const XmlNodeRef& inRef) override;
  142. //! Returns content of this node.
  143. const char* getContent() const override
  144. { return m_content; };
  145. void setContent(const char* str) override;
  146. //! Set line number in xml.
  147. void setLine(int line) override { m_line = line; }
  148. //! Returns XML of this node and sub nodes.
  149. IXmlStringData* getXMLData(int nReserveMem = 0) const override;
  150. XmlString getXML(int level = 0) const override;
  151. bool saveToFile(const char* fileName) override; // saves in one huge chunk
  152. bool saveToFile(const char* fileName, size_t chunkSizeBytes, AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle) override; // save in small memory chunks
  153. //! Set new XML Node attribute (or override attribute with same key).
  154. using IXmlNode::setAttr;
  155. void setAttr(const char* key, const char* value) override;
  156. void setAttr(const char* key, int value) override;
  157. void setAttr(const char* key, unsigned int value) override;
  158. void setAttr(const char* key, int64 value) override;
  159. void setAttr(const char* key, uint64 value, bool useHexFormat = true) override;
  160. void setAttr(const char* key, float value) override;
  161. void setAttr(const char* key, double value) override;
  162. void setAttr(const char* key, const Vec2& value) override;
  163. void setAttr(const char* key, const Ang3& value) override;
  164. void setAttr(const char* key, const Vec3& value) override;
  165. void setAttr(const char* key, const Vec4& value) override;
  166. void setAttr(const char* key, const Quat& value) override;
  167. //! Delete attrbute.
  168. void delAttr(const char* key) override;
  169. //! Remove all node attributes.
  170. void removeAllAttributes() override;
  171. //! Get attribute value of node.
  172. bool getAttr(const char* key, int& value) const override;
  173. bool getAttr(const char* key, unsigned int& value) const override;
  174. bool getAttr(const char* key, int64& value) const override;
  175. bool getAttr(const char* key, uint64& value, bool useHexFormat = true /*ignored*/) const override;
  176. bool getAttr(const char* key, float& value) const override;
  177. bool getAttr(const char* key, double& value) const override;
  178. bool getAttr(const char* key, bool& value) const override;
  179. bool getAttr(const char* key, XmlString& value) const override
  180. {const char* v(NULL); bool boHasAttribute(getAttr(key, &v)); value = v; return boHasAttribute; }
  181. bool getAttr(const char* key, Vec2& value) const override;
  182. bool getAttr(const char* key, Ang3& value) const override;
  183. bool getAttr(const char* key, Vec3& value) const override;
  184. bool getAttr(const char* key, Vec4& value) const override;
  185. bool getAttr(const char* key, Quat& value) const override;
  186. bool getAttr(const char* key, ColorB& value) const override;
  187. protected:
  188. private:
  189. CXmlNode(const CXmlNode&);
  190. CXmlNode& operator = (const CXmlNode&);
  191. private:
  192. void ReleaseChild(IXmlNode* pChild);
  193. void removeAllChildsImpl();
  194. void AddToXmlString(XmlString& xml, int level, AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle, size_t chunkSizeBytes = 0) const;
  195. char* AddToXmlStringUnsafe(char* xml, int level, char* endPtr, AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle, size_t chunkSizeBytes = 0) const;
  196. XmlString MakeValidXmlString(const XmlString& xml) const;
  197. bool IsValidXmlString(const char* str) const;
  198. XmlAttrConstIter GetAttrConstIterator(const char* key) const
  199. {
  200. assert(m_pAttributes);
  201. XmlAttribute tempAttr;
  202. tempAttr.key = key;
  203. XmlAttributes::const_iterator it = std::find(m_pAttributes->begin(), m_pAttributes->end(), tempAttr);
  204. return it;
  205. /*
  206. XmlAttributes::const_iterator it = std::lower_bound( m_attributes.begin(),m_attributes.end(),tempAttr );
  207. if (it != m_attributes.end() && _stricmp(it->key,key) == 0)
  208. return it;
  209. return m_attributes.end();
  210. */
  211. }
  212. XmlAttrIter GetAttrIterator(const char* key)
  213. {
  214. assert(m_pAttributes);
  215. XmlAttribute tempAttr;
  216. tempAttr.key = key;
  217. XmlAttributes::iterator it = std::find(m_pAttributes->begin(), m_pAttributes->end(), tempAttr);
  218. return it;
  219. // XmlAttributes::iterator it = std::lower_bound( m_attributes.begin(),m_attributes.end(),tempAttr );
  220. //if (it != m_attributes.end() && _stricmp(it->key,key) == 0)
  221. //return it;
  222. //return m_attributes.end();
  223. }
  224. const char* GetValue(const char* key) const
  225. {
  226. if (m_pAttributes)
  227. {
  228. XmlAttrConstIter it = GetAttrConstIterator(key);
  229. if (it != m_pAttributes->end())
  230. {
  231. return it->value;
  232. }
  233. }
  234. return 0;
  235. }
  236. protected:
  237. // String pool used by this node.
  238. IXmlStringPool* m_pStringPool;
  239. //! Tag of XML node.
  240. const char* m_tag;
  241. private:
  242. //! Content of XML node.
  243. const char* m_content;
  244. //! Parent XML node.
  245. IXmlNode* m_parent;
  246. //typedef DynArray<CXmlNode*,XmlDynArrayAlloc> XmlNodes;
  247. typedef std::vector<IXmlNode*> XmlNodes;
  248. //XmlNodes m_childs;
  249. XmlNodes* m_pChilds;
  250. //! Xml node attributes.
  251. //XmlAttributes m_attributes;
  252. XmlAttributes* m_pAttributes;
  253. //! Line in XML file where this node firstly appeared (useful for debugging).
  254. int m_line;
  255. bool m_isProcessingInstruction;
  256. friend class XmlParserImp;
  257. };
  258. #ifdef CRY_COLLECT_XML_NODE_STATS
  259. typedef std::set<CXmlNode*> TXmlNodeSet; // yes, slow, but really only for one-shot debugging
  260. struct SXmlNodeStats
  261. {
  262. SXmlNodeStats()
  263. : nAllocs(0)
  264. , nFrees(0) {}
  265. TXmlNodeSet nodeSet;
  266. uint32 nAllocs;
  267. uint32 nFrees;
  268. };
  269. extern SXmlNodeStats* g_pCXmlNode_Stats;
  270. #endif
  271. //////////////////////////////////////////////////////////////////////////
  272. //
  273. // Reusable XmlNode for XmlNode pool with shared xml string pool
  274. //
  275. //////////////////////////////////////////////////////////////////////////
  276. class CXmlNodePool;
  277. class CXmlNodeReuse
  278. : public CXmlNode
  279. {
  280. public:
  281. CXmlNodeReuse(const char* tag, CXmlNodePool* pPool);
  282. void Release() override;
  283. protected:
  284. CXmlNodePool* m_pPool;
  285. };
  286. //////////////////////////////////////////////////////////////////////////
  287. //
  288. // Pool of reusable XML nodes with shared string pool
  289. //
  290. //////////////////////////////////////////////////////////////////////////
  291. class CXmlNodePool
  292. {
  293. public:
  294. CXmlNodePool(unsigned int nBlockSize, bool bReuseStrings);
  295. virtual ~CXmlNodePool();
  296. XmlNodeRef GetXmlNode(const char* sNodeName);
  297. bool empty() const { return (m_nAllocated == 0); }
  298. protected:
  299. virtual void OnRelease(int iRefCount, void* pThis);
  300. IXmlStringPool* GetStringPool() { return m_pStringPool; }
  301. private:
  302. friend class CXmlNodeReuse;
  303. IXmlStringPool* m_pStringPool;
  304. unsigned int m_nAllocated;
  305. std::stack<CXmlNodeReuse*> m_pNodePool;
  306. };