Xml.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Util/DynamicArray.h>
  7. #include <AnKi/Util/String.h>
  8. #include <TinyXml2/tinyxml2.h>
  9. #if !ANKI_TINYXML2
  10. # error "Wrong tinyxml2 included"
  11. #endif
  12. namespace anki {
  13. /// @addtogroup util_file
  14. /// @{
  15. /// XML element.
  16. class XmlElement
  17. {
  18. template<typename>
  19. friend class XmlDocument;
  20. public:
  21. XmlElement() = default;
  22. /// Copy.
  23. XmlElement(const XmlElement& b)
  24. : m_el(b.m_el)
  25. , m_pool(b.m_pool)
  26. {
  27. }
  28. /// If element has something return true
  29. explicit operator Bool() const
  30. {
  31. return m_el != nullptr;
  32. }
  33. /// Copy
  34. XmlElement& operator=(const XmlElement& b)
  35. {
  36. m_el = b.m_el;
  37. m_pool = b.m_pool;
  38. return *this;
  39. }
  40. /// Return the text inside a tag. May return empty string.
  41. Error getText(CString& out) const;
  42. /// Return the text inside as a number.
  43. template<typename T>
  44. Error getNumber(T& out) const;
  45. /// Get a number of numbers.
  46. template<typename T, typename TMemoryPool>
  47. Error getNumbers(DynamicArray<T, TMemoryPool>& out) const;
  48. /// Get a fixed number of numbers.
  49. /// @tparam TArray A type that should have operator[] and getSize() methods implemented.
  50. template<typename TArray>
  51. Error getNumbers(TArray& out) const;
  52. /// Get a child element quietly
  53. Error getChildElementOptional(CString name, XmlElement& out) const;
  54. /// Get a child element and print error if not found
  55. Error getChildElement(CString name, XmlElement& out) const;
  56. /// Get the next element with the same name. Returns empty XmlElement if it reached the end of the list.
  57. Error getNextSiblingElement(CString name, XmlElement& out) const;
  58. /// Get the number of sibling elements of this node.
  59. /// @note The sibling elements share the same name.
  60. Error getSiblingElementsCount(U32& out) const;
  61. /// @name Get attributes optional
  62. /// @{
  63. /// Get value of a string attribute. May return empty string.
  64. /// @param name The name of the attribute.
  65. /// @param out The value of the attribute.
  66. /// @param attribPresent True if the attribute exists. If it doesn't the @a out is undefined.
  67. Error getAttributeTextOptional(CString name, CString& out, Bool& attribPresent) const;
  68. /// Get the attribute's value as a series of numbers.
  69. /// @param name The name of the attribute.
  70. /// @param out The value of the attribute.
  71. /// @param attribPresent True if the attribute exists. If it doesn't the @a out is undefined.
  72. template<typename T, typename TMemoryPool>
  73. Error getAttributeNumbersOptional(CString name, DynamicArray<T, TMemoryPool>& out, Bool& attribPresent) const;
  74. /// Get the attribute's value as a series of numbers.
  75. /// @tparam TArray A type that should have operator[] and getSize() methods implemented.
  76. /// @param name The name of the attribute.
  77. /// @param out The value of the attribute.
  78. /// @param attribPresent True if the attribute exists. If it doesn't the @a out is undefined.
  79. template<typename TArray>
  80. Error getAttributeNumbersOptional(CString name, TArray& out, Bool& attribPresent) const;
  81. /// Get the attribute's value as a number.
  82. /// @param name The name of the attribute.
  83. /// @param out The value of the attribute.
  84. /// @param attribPresent True if the attribute exists. If it doesn't the @a out is undefined.
  85. template<typename T>
  86. Error getAttributeNumberOptional(CString name, T& out, Bool& attribPresent) const;
  87. /// @}
  88. /// @name Get attributes
  89. /// @{
  90. /// Get value of a string attribute. May return empty string.
  91. /// @param name The name of the attribute.
  92. /// @param out The value of the attribute.
  93. Error getAttributeText(CString name, CString& out) const
  94. {
  95. Bool found;
  96. ANKI_CHECK(getAttributeTextOptional(name, out, found));
  97. return throwAttribNotFoundError(name, found);
  98. }
  99. /// Get the attribute's value as a series of numbers.
  100. /// @param name The name of the attribute.
  101. /// @param out The value of the attribute.
  102. template<typename T, typename TMemoryPool>
  103. Error getAttributeNumbers(CString name, DynamicArray<T, TMemoryPool>& out) const
  104. {
  105. Bool found;
  106. ANKI_CHECK(getAttributeNumbersOptional(name, out, found));
  107. return throwAttribNotFoundError(name, found);
  108. }
  109. /// Get the attribute's value as a series of numbers.
  110. /// @tparam TArray A type that should have operator[] and getSize() methods implemented.
  111. /// @param name The name of the attribute.
  112. /// @param out The value of the attribute.
  113. template<typename TArray>
  114. Error getAttributeNumbers(CString name, TArray& out) const
  115. {
  116. Bool found;
  117. ANKI_CHECK(getAttributeNumbersOptional(name, out, found));
  118. return throwAttribNotFoundError(name, found);
  119. }
  120. /// Get the attribute's value as a number.
  121. /// @param name The name of the attribute.
  122. /// @param out The value of the attribute.
  123. template<typename T>
  124. Error getAttributeNumber(CString name, T& out) const
  125. {
  126. Bool found;
  127. ANKI_CHECK(getAttributeNumberOptional(name, out, found));
  128. return throwAttribNotFoundError(name, found);
  129. }
  130. /// @}
  131. private:
  132. const tinyxml2::XMLElement* m_el = nullptr;
  133. BaseMemoryPool* m_pool = nullptr;
  134. XmlElement(const tinyxml2::XMLElement* el, BaseMemoryPool* pool)
  135. : m_el(el)
  136. , m_pool(pool)
  137. {
  138. }
  139. Error check() const;
  140. template<typename T, typename TMemoryPool>
  141. Error parseNumbers(CString txt, DynamicArray<T, TMemoryPool>& out) const;
  142. template<typename TArray>
  143. Error parseNumbers(CString txt, TArray& out) const;
  144. Error throwAttribNotFoundError(CString attrib, Bool found) const
  145. {
  146. if(!found)
  147. {
  148. ANKI_UTIL_LOGE("Attribute not found \"%s\"", &attrib[0]);
  149. return Error::kUserData;
  150. }
  151. else
  152. {
  153. return Error::kNone;
  154. }
  155. }
  156. };
  157. /// XML document.
  158. template<typename TMemoryPool>
  159. class XmlDocument
  160. {
  161. public:
  162. static constexpr CString kXmlHeader = R"(<?xml version="1.0" encoding="UTF-8" ?>)";
  163. XmlDocument(const TMemoryPool& pool = TMemoryPool())
  164. : m_pool(pool)
  165. {
  166. }
  167. /// Parse from a file.
  168. Error loadFile(CString filename);
  169. /// Parse from a CString.
  170. Error parse(CString xmlText);
  171. Error getChildElement(CString name, XmlElement& out) const;
  172. Error getChildElementOptional(CString name, XmlElement& out) const;
  173. private:
  174. mutable TMemoryPool m_pool;
  175. tinyxml2::XMLDocument m_doc;
  176. };
  177. /// @}
  178. } // end namespace anki
  179. #include <AnKi/Util/Xml.inl.h>