XMLReader.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*
  2. * Author: Patrick-Christopher Mattulat
  3. * Company: Lynar Studios
  4. * E-Mail: webmaster@lynarstudios.com
  5. * Created: 2020-10-10
  6. * Changed: 2020-10-16
  7. *
  8. * */
  9. #include "XMLReader.hpp"
  10. #include "../../exception/IllegalArgumentException.hpp"
  11. #include "../FileReader.hpp"
  12. #include "../../boxing/String.hpp"
  13. #include <vector>
  14. ls_std::XMLReader::XMLReader(const std::shared_ptr<ls_std::XMLDocument>& _document, const std::string& _absolutePath) :
  15. Class("XMLReader"),
  16. xmlFile(ls_std::File {_absolutePath}),
  17. document(_document)
  18. {
  19. XMLReader::_checkDocumentExistence(_document);
  20. XMLReader::_checkFileExistence(this->xmlFile);
  21. }
  22. ls_std::byte_field ls_std::XMLReader::read()
  23. {
  24. ls_std::byte_field data = ls_std::FileReader {this->xmlFile}.read();
  25. this->_read(data);
  26. return data;
  27. }
  28. std::shared_ptr<ls_std::XMLDocument> ls_std::XMLReader::getDocument()
  29. {
  30. return this->document;
  31. }
  32. void ls_std::XMLReader::setFile(const ls_std::File &_xmlFile)
  33. {
  34. XMLReader::_checkFileExistence(_xmlFile);
  35. this->xmlFile = _xmlFile;
  36. }
  37. void ls_std::XMLReader::_checkDocumentExistence(const std::shared_ptr<ls_std::XMLDocument>& _document)
  38. {
  39. if(_document == nullptr) {
  40. throw ls_std::IllegalArgumentException {};
  41. }
  42. }
  43. void ls_std::XMLReader::_checkFileExistence(ls_std::File _xmlFile)
  44. {
  45. if(!_xmlFile.exists()) {
  46. throw ls_std::IllegalArgumentException {};
  47. }
  48. }
  49. std::shared_ptr<ls_std::XMLDeclaration> ls_std::XMLReader::_createDeclaration(const std::list<std::pair<std::string, std::string>>& _attributes)
  50. {
  51. std::shared_ptr<ls_std::XMLDeclaration> declaration = std::make_shared<ls_std::XMLDeclaration>("1.0");
  52. std::pair<std::string, std::string> attribute = ls_std::XMLReader::_findAttribute(_attributes, "version");
  53. if(!attribute.first.empty()) {
  54. declaration->setVersion(attribute.second);
  55. }
  56. attribute = ls_std::XMLReader::_findAttribute(_attributes, "encoding");
  57. if(!attribute.first.empty()) {
  58. declaration->setEncoding(attribute.second);
  59. }
  60. attribute = ls_std::XMLReader::_findAttribute(_attributes, "standalone");
  61. if(!attribute.first.empty()) {
  62. declaration->setStandalone(attribute.second);
  63. }
  64. return declaration;
  65. }
  66. std::pair<std::string, std::string> ls_std::XMLReader::_findAttribute(const std::list<std::pair<std::string, std::string>> &_attributes, const std::string &_name)
  67. {
  68. std::pair<std::string, std::string> attribute {};
  69. for(const auto& currentAttribute : _attributes) {
  70. if(currentAttribute.first == _name) {
  71. attribute = currentAttribute;
  72. break;
  73. }
  74. }
  75. return attribute;
  76. }
  77. void ls_std::XMLReader::_isClosingTag(const ls_std::byte_field &_data, std::string::size_type _index)
  78. {
  79. if(this->mode == XML_PARSE_MODE_ANALYZE && _data.substr(_index, 2) == "</") {
  80. this->mode = XML_PARSE_MODE_CLOSING_TAG;
  81. }
  82. }
  83. void ls_std::XMLReader::_isDeclaration(const ls_std::byte_field& _data, std::string::size_type _index)
  84. {
  85. if(_data.substr(_index, 5) == "<?xml") {
  86. this->mode = XML_PARSE_MODE_DECLARATION;
  87. }
  88. }
  89. void ls_std::XMLReader::_isOpeningTag(const ls_std::byte_field &_data, std::string::size_type _index)
  90. {
  91. if(this->mode == XML_PARSE_MODE_ANALYZE && _data.substr(_index, 1) == "<") {
  92. this->mode = XML_PARSE_MODE_OPENING_TAG;
  93. }
  94. }
  95. void ls_std::XMLReader::_read(const ls_std::byte_field &_data)
  96. {
  97. for(std::string::size_type index = 0 ; index < _data.size() ; index++) {
  98. switch(this->mode) {
  99. case XML_PARSE_MODE_ANALYZE:
  100. {
  101. this->_isDeclaration(_data, index);
  102. this->_isClosingTag(_data, index);
  103. this->_isOpeningTag(_data, index);
  104. } break;
  105. case XML_PARSE_MODE_DECLARATION:
  106. {
  107. --index;
  108. index = ls_std::XMLReader::_readDeclaration(_data, index);
  109. this->mode = XML_PARSE_MODE_ANALYZE;
  110. } break;
  111. case XML_PARSE_MODE_OPENING_TAG:
  112. {
  113. } break;
  114. case XML_PARSE_MODE_CLOSING_TAG:
  115. {
  116. } break;
  117. }
  118. }
  119. }
  120. std::pair<std::string, std::string> ls_std::XMLReader::_readAttribute(const ls_std::byte_field &_data)
  121. {
  122. std::pair<std::string, std::string> parsedAttribute {};
  123. parsedAttribute.first = _data.substr(0, _data.find('='));
  124. parsedAttribute.second = _data.substr(_data.find('"') + 1);
  125. parsedAttribute.second.pop_back();
  126. return parsedAttribute;
  127. }
  128. std::list<std::pair<std::string, std::string>> ls_std::XMLReader::_readAttributes(ls_std::byte_field _data)
  129. {
  130. std::list<std::pair<std::string, std::string>> attributes {};
  131. size_t attributePosition;
  132. _data = _data.substr(5);
  133. while(!_data.empty()) {
  134. do {
  135. attributePosition = _data.find(' ') + 1;
  136. }
  137. while(_data[attributePosition] == ' ');
  138. if(_data.size() <= 3 && ls_std::String {_data}.endsWith(">")) {
  139. break;
  140. }
  141. std::string attributeString = _data.substr(attributePosition, _data.find(R"(" )"));
  142. attributes.push_back(ls_std::XMLReader::_readAttribute(attributeString));
  143. _data = _data.substr(attributePosition + attributeString.size());
  144. }
  145. return attributes;
  146. }
  147. size_t ls_std::XMLReader::_readDeclaration(const ls_std::byte_field &_data, std::string::size_type _index)
  148. {
  149. size_t closingTagPosition = _data.find('>');
  150. if(closingTagPosition != std::string::npos) {
  151. std::string declarationString = _data.substr(_index, (closingTagPosition - _index) + 1);
  152. std::shared_ptr<ls_std::XMLDeclaration> declaration = this->_createDeclaration(ls_std::XMLReader::_readAttributes(declarationString));
  153. this->document->setDeclaration(declaration);
  154. }
  155. return (closingTagPosition == std::string::npos) ? _index : closingTagPosition;
  156. }