Xml.h 6.3 KB

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