Xml.inl.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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. #include <AnKi/Util/Xml.h>
  6. #include <AnKi/Util/StringList.h>
  7. #include <AnKi/Util/File.h>
  8. #include <AnKi/Util/Logger.h>
  9. namespace anki {
  10. template<typename T>
  11. Error XmlElement::getNumber(T& out) const
  12. {
  13. ANKI_CHECK(check());
  14. const char* txt = m_el->GetText();
  15. if(txt != nullptr)
  16. {
  17. ANKI_CHECK(CString(txt).toNumber(out));
  18. }
  19. else
  20. {
  21. ANKI_UTIL_LOGE("Failed to return number. Element: %s", m_el->Value());
  22. return Error::kUserData;
  23. }
  24. return Error::kNone;
  25. }
  26. template<typename T, typename TMemoryPool>
  27. Error XmlElement::getNumbers(DynamicArray<T, TMemoryPool>& out) const
  28. {
  29. CString txt;
  30. ANKI_CHECK(getText(txt));
  31. if(txt)
  32. {
  33. return parseNumbers(txt, out);
  34. }
  35. else
  36. {
  37. out.destroy();
  38. return Error::kNone;
  39. }
  40. }
  41. template<typename TArray>
  42. Error XmlElement::getNumbers(TArray& out) const
  43. {
  44. CString txt;
  45. ANKI_CHECK(getText(txt));
  46. return parseNumbers(txt, out);
  47. }
  48. template<typename T, typename TMemoryPool>
  49. Error XmlElement::getAttributeNumbersOptional(CString name, DynamicArray<T, TMemoryPool>& out, Bool& attribPresent) const
  50. {
  51. CString txtVal;
  52. ANKI_CHECK(getAttributeTextOptional(name, txtVal, attribPresent));
  53. if(txtVal && attribPresent)
  54. {
  55. return parseNumbers(txtVal, out);
  56. }
  57. else
  58. {
  59. return Error::kNone;
  60. }
  61. }
  62. template<typename TArray>
  63. Error XmlElement::getAttributeNumbersOptional(CString name, TArray& out, Bool& attribPresent) const
  64. {
  65. CString txtVal;
  66. ANKI_CHECK(getAttributeTextOptional(name, txtVal, attribPresent));
  67. if(txtVal && attribPresent)
  68. {
  69. return parseNumbers(txtVal, out);
  70. }
  71. else
  72. {
  73. return Error::kNone;
  74. }
  75. }
  76. template<typename T>
  77. Error XmlElement::getAttributeNumberOptional(CString name, T& out, Bool& attribPresent) const
  78. {
  79. DynamicArray<T, MemoryPoolPtrWrapper<BaseMemoryPool>> arr(m_pool);
  80. ANKI_CHECK(getAttributeNumbersOptional(name, arr, attribPresent));
  81. if(attribPresent)
  82. {
  83. if(arr.getSize() != 1)
  84. {
  85. ANKI_UTIL_LOGE("Expecting one element for attrib: %s", &name[0]);
  86. return Error::kUserData;
  87. }
  88. out = arr[0];
  89. }
  90. return Error::kNone;
  91. }
  92. template<typename T, typename TMemoryPool>
  93. Error XmlElement::parseNumbers(CString txt, DynamicArray<T, TMemoryPool>& out) const
  94. {
  95. ANKI_ASSERT(txt);
  96. ANKI_ASSERT(m_el);
  97. BaseStringList<MemoryPoolPtrWrapper<BaseMemoryPool>> list(m_pool);
  98. list.splitString(txt, ' ');
  99. out.resize(U32(list.getSize()));
  100. Error err = Error::kNone;
  101. auto it = list.getBegin();
  102. auto end = list.getEnd();
  103. U32 i = 0;
  104. while(it != end && !err)
  105. {
  106. err = it->toNumber(out[i++]);
  107. ++it;
  108. }
  109. if(err)
  110. {
  111. ANKI_UTIL_LOGE("Failed to covert to numbers the element: %s", m_el->Value());
  112. }
  113. return err;
  114. }
  115. template<typename TArray>
  116. Error XmlElement::parseNumbers(CString txt, TArray& out) const
  117. {
  118. ANKI_ASSERT(!txt.isEmpty());
  119. ANKI_ASSERT(m_el);
  120. BaseStringList<MemoryPoolPtrWrapper<BaseMemoryPool>> list(m_pool);
  121. list.splitString(txt, ' ');
  122. const PtrSize listSize = list.getSize();
  123. if(listSize != out.getSize())
  124. {
  125. ANKI_UTIL_LOGE("Wrong number of elements for element: %s", m_el->Value());
  126. return Error::kUserData;
  127. }
  128. Error err = Error::kNone;
  129. auto it = list.getBegin();
  130. auto end = list.getEnd();
  131. U32 i = 0;
  132. while(it != end && !err)
  133. {
  134. err = it->toNumber(out[i++]);
  135. ++it;
  136. }
  137. if(err)
  138. {
  139. ANKI_UTIL_LOGE("Failed to covert to numbers the element: %s", m_el->Value());
  140. }
  141. return err;
  142. }
  143. template<typename TMemoryPool>
  144. Error XmlDocument<TMemoryPool>::loadFile(CString filename)
  145. {
  146. File file;
  147. ANKI_CHECK(file.open(filename, FileOpenFlag::kRead));
  148. BaseString<TMemoryPool> text(m_pool);
  149. ANKI_CHECK(file.readAllText(text));
  150. ANKI_CHECK(parse(text.toCString()));
  151. return Error::kNone;
  152. }
  153. template<typename TMemoryPool>
  154. Error XmlDocument<TMemoryPool>::parse(CString xmlText)
  155. {
  156. if(m_doc.Parse(&xmlText[0]))
  157. {
  158. ANKI_UTIL_LOGE("Cannot parse file. Reason: %s", ((m_doc.ErrorStr() == nullptr) ? "unknown" : m_doc.ErrorStr()));
  159. return Error::kUserData;
  160. }
  161. return Error::kNone;
  162. }
  163. template<typename TMemoryPool>
  164. Error XmlDocument<TMemoryPool>::getChildElementOptional(CString name, XmlElement& out) const
  165. {
  166. out = XmlElement(m_doc.FirstChildElement(&name[0]), &m_pool);
  167. return Error::kNone;
  168. }
  169. template<typename TMemoryPool>
  170. Error XmlDocument<TMemoryPool>::getChildElement(CString name, XmlElement& out) const
  171. {
  172. ANKI_CHECK(getChildElementOptional(name, out));
  173. if(!out)
  174. {
  175. ANKI_UTIL_LOGE("Cannot find tag \"%s\"", &name[0]);
  176. return Error::kUserData;
  177. }
  178. return Error::kNone;
  179. }
  180. } // end namespace anki