Xml.h 6.3 KB

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