Browse Source

Address SonarLint findings in XmlParser class

Patrick-Christopher Mattulat 1 year ago
parent
commit
20828d4803

+ 15 - 13
include/ls-std/io/xml/XmlParser.hpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-11-25
- * Changed:         2023-02-22
+ * Changed:         2023-05-16
  *
  * */
 
@@ -17,6 +17,7 @@
 #include <ls-std/core/Class.hpp>
 #include <ls-std/core/type/Types.hpp>
 #include <ls-std/os/dynamic-goal.hpp>
+#include <string_view>
 
 namespace ls::std::io
 {
@@ -27,7 +28,7 @@ namespace ls::std::io
       explicit XmlParser(const ::std::shared_ptr<ls::std::io::XmlDocument> &_document);
       ~XmlParser() noexcept override;
 
-      [[nodiscard]] ::std::shared_ptr<ls::std::io::XmlDocument> getDocument();
+      [[nodiscard]] ::std::shared_ptr<ls::std::io::XmlDocument> getDocument() const;
       void parse(const ls::std::core::type::byte_field &_data);
       void setDocument(const ::std::shared_ptr<ls::std::io::XmlDocument> &_document);
 
@@ -46,28 +47,29 @@ namespace ls::std::io
 
       void _analyze(const ls::std::core::type::byte_field &_data, ::std::string::size_type _index);
       void _assignDocument(const ::std::shared_ptr<ls::std::io::XmlDocument> &_document);
-      [[nodiscard]] static bool _contains(const ::std::string &_text, const ::std::string &_searchText);
+      [[nodiscard]] static bool _contains(::std::string_view _text, ::std::string_view _searchText);
       [[nodiscard]] static ::std::shared_ptr<ls::std::io::XmlDeclaration> _createDeclaration(const ::std::list<::std::pair<::std::string, ::std::string>> &_attributes);
-      [[nodiscard]] static ::std::shared_ptr<ls::std::io::XmlNode> _createNode(const ::std::list<::std::pair<::std::string, ::std::string>> &_attributes, const ::std::string &_name);
-      [[nodiscard]] static bool _endsWith(const ::std::string &_text, const ::std::string &_ending);
+      [[nodiscard]] static ::std::shared_ptr<ls::std::io::XmlNode> _createNode(const ::std::list<::std::pair<::std::string, ::std::string>> &_attributes, ::std::string_view _name);
+      [[nodiscard]] static bool _endsWith(::std::string_view _text, ::std::string_view _ending);
       [[nodiscard]] static ::std::pair<::std::string, ::std::string> _findAttribute(const ::std::list<::std::pair<::std::string, ::std::string>> &_attributes, const ::std::string &_name);
       [[nodiscard]] static size_t _findAttributeEndPosition(const ls::std::core::type::byte_field &_data);
-      [[nodiscard]] static ls::std::core::type::byte_field _getNextTagString(const ls::std::core::type::byte_field &_data, ::std::string::size_type _index);
-      void _isClosingTag(const ls::std::core::type::byte_field &_data, ::std::string::size_type _index);
-      void _isDeclaration(const ls::std::core::type::byte_field &_data, ::std::string::size_type _index);
-      void _isOpeningTag(const ls::std::core::type::byte_field &_data, ::std::string::size_type _index);
+      [[nodiscard]] static ls::std::core::type::byte_field _getNextTagString(::std::string_view _data, ::std::string::size_type _index);
+      void _isClosingTag(::std::string_view _data, ::std::string::size_type _index);
+      void _isDeclaration(::std::string_view _data, ::std::string::size_type _index);
+      void _isOpeningTag(::std::string_view _data, ::std::string::size_type _index);
       void _isValue(const ls::std::core::type::byte_field &_data, ::std::string::size_type _index);
       void _mergeNodes();
       void _mergeChildrenToParentNode(const ::std::shared_ptr<ls::std::io::XmlNode> &_parent, ::std::list<ls::std::io::XmlParseParameter>::iterator &_iterator, uint8_t _parentLevel);
       void _mergeNodesOnCurrentLevel();
       void _parse(const ls::std::core::type::byte_field &_data);
-      [[nodiscard]] static ::std::pair<::std::string, ::std::string> _parseAttribute(const ls::std::core::type::byte_field &_data);
+      [[nodiscard]] static ::std::pair<::std::string, ::std::string> _parseAttribute(::std::string_view _data);
       [[nodiscard]] static ::std::list<::std::pair<::std::string, ::std::string>> _parseAttributes(ls::std::core::type::byte_field _data);
       [[nodiscard]] size_t _parseClosingTag(const ls::std::core::type::byte_field &_data, ::std::string::size_type _index);
-      [[nodiscard]] size_t _parseDeclaration(const ls::std::core::type::byte_field &_data, ::std::string::size_type _index);
+      [[nodiscard]] size_t _parseDeclaration(const ls::std::core::type::byte_field &_data, ::std::string::size_type _index) const;
+      [[nodiscard]] ::std::string::size_type _parseMode(::std::string::size_type _index, const ls::std::core::type::byte_field &_data);
       [[nodiscard]] size_t _parseOpeningTag(const ls::std::core::type::byte_field &_data, ::std::string::size_type _index);
-      [[nodiscard]] static ls::std::core::type::byte_field _parseTagName(const ls::std::core::type::byte_field &_data);
-      [[nodiscard]] size_t _parseValue(const ls::std::core::type::byte_field &_data, ::std::string::size_type _index);
+      [[nodiscard]] static ::std::string_view _parseTagName(::std::string_view _data);
+      [[nodiscard]] size_t _parseValue(::std::string_view _data, ::std::string::size_type _index);
       void _reset();
       void _setMaxLevel();
   };

+ 70 - 61
source/ls-std/io/xml/XmlParser.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-11-26
- * Changed:         2023-02-24
+ * Changed:         2023-05-16
  *
  * */
 
@@ -27,6 +27,7 @@ using std::move;
 using std::pair;
 using std::shared_ptr;
 using std::string;
+using std::string_view;
 
 XmlParser::XmlParser(const shared_ptr<XmlDocument> &_document) : Class("XmlParser")
 {
@@ -36,7 +37,7 @@ XmlParser::XmlParser(const shared_ptr<XmlDocument> &_document) : Class("XmlParse
 
 XmlParser::~XmlParser() noexcept = default;
 
-shared_ptr<XmlDocument> XmlParser::getDocument()
+shared_ptr<XmlDocument> XmlParser::getDocument() const
 {
   return this->document;
 }
@@ -77,14 +78,14 @@ void XmlParser::_assignDocument(const shared_ptr<XmlDocument> &_document)
   this->document = _document;
 }
 
-bool XmlParser::_contains(const string &_text, const string &_searchText)
+bool XmlParser::_contains(string_view _text, string_view _searchText)
 {
   return _text.find(_searchText) != string::npos;
 }
 
 shared_ptr<XmlDeclaration> XmlParser::_createDeclaration(const list<pair<string, string>> &_attributes)
 {
-  shared_ptr<XmlDeclaration> declaration = make_shared<XmlDeclaration>("1.0");
+  auto declaration = make_shared<XmlDeclaration>("1.0");
   pair<string, string> attribute = XmlParser::_findAttribute(_attributes, "version");
 
   if (!attribute.first.empty())
@@ -109,29 +110,29 @@ shared_ptr<XmlDeclaration> XmlParser::_createDeclaration(const list<pair<string,
   return declaration;
 }
 
-shared_ptr<XmlNode> XmlParser::_createNode(const list<pair<string, string>> &_attributes, const string &_name)
+shared_ptr<XmlNode> XmlParser::_createNode(const list<pair<string, string>> &_attributes, string_view _name)
 {
-  shared_ptr<XmlNode> node = make_shared<XmlNode>(_name);
+  auto node = make_shared<XmlNode>(string{_name});
   shared_ptr<XmlAttribute> attribute{};
 
-  for (const auto &parsedAttribute : _attributes)
+  for (const auto &[attributeName, attributeValue] : _attributes)
   {
-    attribute = make_shared<XmlAttribute>(parsedAttribute.first);
-    attribute->setValue(parsedAttribute.second);
+    attribute = make_shared<XmlAttribute>(attributeName);
+    attribute->setValue(attributeValue);
     node->addAttributeToEnd(attribute);
   }
 
   return node;
 }
 
-bool XmlParser::_endsWith(const string &_text, const string &_ending)
+bool XmlParser::_endsWith(string_view _text, string_view _ending)
 {
   return _text.rfind(_ending) == (_text.size() - _ending.size());
 }
 
 pair<string, string> XmlParser::_findAttribute(const list<pair<string, string>> &_attributes, const string &_name)
 {
-  const auto &iterator = find_if(_attributes.begin(), _attributes.end(), [_name](const pair<string, string> &_attribute) { return _attribute.first == _name; });
+  const auto &iterator = find_if(_attributes.begin(), _attributes.end(), [&_name](const pair<string, string> &_attribute) { return _attribute.first == _name; });
   return iterator != _attributes.end() ? *iterator : pair<string, string>{};
 }
 
@@ -158,12 +159,11 @@ size_t XmlParser::_findAttributeEndPosition(const byte_field &_data)
   return position;
 }
 
-byte_field XmlParser::_getNextTagString(const byte_field &_data, string::size_type _index)
+byte_field XmlParser::_getNextTagString(string_view _data, string::size_type _index)
 {
   byte_field tag{};
-  size_t closingCharacterPosition = _index + _data.substr(_index).find('>');
 
-  if (closingCharacterPosition != string::npos)
+  if (size_t closingCharacterPosition = _index + _data.substr(_index).find('>'); closingCharacterPosition != string::npos)
   {
     tag = _data.substr(_index, (closingCharacterPosition - _index) + 1);
   }
@@ -171,7 +171,7 @@ byte_field XmlParser::_getNextTagString(const byte_field &_data, string::size_ty
   return tag;
 }
 
-void XmlParser::_isClosingTag(const byte_field &_data, string::size_type _index)
+void XmlParser::_isClosingTag(string_view _data, string::size_type _index)
 {
   if (this->mode == XmlParseMode::XML_PARSE_MODE_ANALYZE && _data.substr(_index, 2) == "</")
   {
@@ -179,7 +179,7 @@ void XmlParser::_isClosingTag(const byte_field &_data, string::size_type _index)
   }
 }
 
-void XmlParser::_isDeclaration(const byte_field &_data, string::size_type _index)
+void XmlParser::_isDeclaration(string_view _data, string::size_type _index)
 {
   if (_data.substr(_index, 5) == "<?xml")
   {
@@ -187,7 +187,7 @@ void XmlParser::_isDeclaration(const byte_field &_data, string::size_type _index
   }
 }
 
-void XmlParser::_isOpeningTag(const byte_field &_data, string::size_type _index)
+void XmlParser::_isOpeningTag(string_view _data, string::size_type _index)
 {
   if (this->mode == XmlParseMode::XML_PARSE_MODE_ANALYZE && _data.substr(_index, 1) == "<")
   {
@@ -206,7 +206,7 @@ void XmlParser::_isValue(const byte_field &_data, string::size_type _index)
     {
       string value{_data.substr(_index, end)};
 
-      if (!XmlParser::_contains(value, "\n") && !XmlParser::_contains(value, "\r\n"))
+      if (!XmlParser::_contains(string_view{value}, string_view{"\n"}) && !XmlParser::_contains(string_view{value}, string_view{"\r\n"}))
       {
         this->mode = XmlParseMode::XML_PARSE_MODE_VALUE;
       }
@@ -267,46 +267,11 @@ void XmlParser::_parse(const byte_field &_data)
 {
   for (string::size_type index = 0; index < _data.size(); index++)
   {
-    switch (this->mode)
-    {
-      case XmlParseMode::XML_PARSE_MODE_ANALYZE:
-      {
-        this->_analyze(_data, index);
-      }
-      break;
-      case XmlParseMode::XML_PARSE_MODE_DECLARATION:
-      {
-        --index;
-        index = this->_parseDeclaration(_data, index);
-        this->mode = XmlParseMode::XML_PARSE_MODE_ANALYZE;
-      }
-      break;
-      case XmlParseMode::XML_PARSE_MODE_OPENING_TAG:
-      {
-        --index;
-        index = XmlParser::_parseOpeningTag(_data, index);
-        this->mode = XmlParseMode::XML_PARSE_MODE_ANALYZE;
-      }
-      break;
-      case XmlParseMode::XML_PARSE_MODE_VALUE:
-      {
-        --index;
-        index = XmlParser::_parseValue(_data, index);
-        this->mode = XmlParseMode::XML_PARSE_MODE_ANALYZE;
-      }
-      break;
-      case XmlParseMode::XML_PARSE_MODE_CLOSING_TAG:
-      {
-        --index;
-        index = XmlParser::_parseClosingTag(_data, index);
-        this->mode = XmlParseMode::XML_PARSE_MODE_ANALYZE;
-      }
-      break;
-    }
+    index = this->_parseMode(index, _data);
   }
 }
 
-pair<string, string> XmlParser::_parseAttribute(const byte_field &_data)
+pair<string, string> XmlParser::_parseAttribute(string_view _data)
 {
   pair<string, string> parsedAttribute{};
   parsedAttribute.first = _data.substr(0, _data.find('='));
@@ -329,7 +294,7 @@ list<pair<string, string>> XmlParser::_parseAttributes(byte_field _data)
       position = _data.find(' ') + 1;
     } while (_data[position] == ' ');
 
-    if (_data.size() <= 3 && XmlParser::_endsWith(string{_data}, ">"))
+    if (_data.size() <= 3 && XmlParser::_endsWith(string_view{_data}, ">"))
     {
       break;
     }
@@ -349,7 +314,7 @@ size_t XmlParser::_parseClosingTag(const byte_field &_data, string::size_type _i
   return tagString.empty() ? _index : _index + (tagString.size() - 1);
 }
 
-size_t XmlParser::_parseDeclaration(const byte_field &_data, string::size_type _index)
+size_t XmlParser::_parseDeclaration(const byte_field &_data, string::size_type _index) const
 {
   string tagString = XmlParser::_getNextTagString(_data, _index);
   bool isValidTagString = !tagString.empty();
@@ -363,6 +328,50 @@ size_t XmlParser::_parseDeclaration(const byte_field &_data, string::size_type _
   return !isValidTagString ? _index : _index + (tagString.size() - 1);
 }
 
+string::size_type XmlParser::_parseMode(string::size_type _index, const byte_field &_data)
+{
+  string::size_type index = _index;
+
+  switch (this->mode)
+  {
+    case XmlParseMode::XML_PARSE_MODE_ANALYZE:
+    {
+      this->_analyze(_data, index);
+    }
+    break;
+    case XmlParseMode::XML_PARSE_MODE_DECLARATION:
+    {
+      --index;
+      index = this->_parseDeclaration(_data, index);
+      this->mode = XmlParseMode::XML_PARSE_MODE_ANALYZE;
+    }
+    break;
+    case XmlParseMode::XML_PARSE_MODE_OPENING_TAG:
+    {
+      --index;
+      index = XmlParser::_parseOpeningTag(_data, index);
+      this->mode = XmlParseMode::XML_PARSE_MODE_ANALYZE;
+    }
+    break;
+    case XmlParseMode::XML_PARSE_MODE_VALUE:
+    {
+      --index;
+      index = XmlParser::_parseValue(_data, index);
+      this->mode = XmlParseMode::XML_PARSE_MODE_ANALYZE;
+    }
+    break;
+    case XmlParseMode::XML_PARSE_MODE_CLOSING_TAG:
+    {
+      --index;
+      index = XmlParser::_parseClosingTag(_data, index);
+      this->mode = XmlParseMode::XML_PARSE_MODE_ANALYZE;
+    }
+    break;
+  }
+
+  return index;
+}
+
 size_t XmlParser::_parseOpeningTag(const byte_field &_data, string::size_type _index)
 {
   string tagString{XmlParser::_getNextTagString(_data, _index)};
@@ -387,7 +396,7 @@ size_t XmlParser::_parseOpeningTag(const byte_field &_data, string::size_type _i
   return !isValidTagString ? _index : _index + (tagString.size() - 1);
 }
 
-byte_field XmlParser::_parseTagName(const byte_field &_data)
+string_view XmlParser::_parseTagName(string_view _data)
 {
   string::size_type position = _data.find(' ');
 
@@ -399,10 +408,10 @@ byte_field XmlParser::_parseTagName(const byte_field &_data)
   return _data.substr(1, position - 1);
 }
 
-size_t XmlParser::_parseValue(const byte_field &_data, string::size_type _index)
+size_t XmlParser::_parseValue(string_view _data, string::size_type _index)
 {
-  byte_field value = _data.substr(_index, _data.substr(_index).find('<'));
-  this->parseParameters.back().getNode()->setValue(value);
+  string_view value = _data.substr(_index, _data.substr(_index).find('<'));
+  this->parseParameters.back().getNode()->setValue(string{value});
 
   return _index + (value.size() - 1);
 }

+ 7 - 4
test/cases/io/xml/XmlParserTest.cpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-11-26
- * Changed:         2023-03-25
+ * Changed:         2023-05-16
  *
  * */
 
@@ -113,7 +113,10 @@ namespace
   TEST_F(XmlParserTest, read)
   {
     XmlParser xmlParser{make_shared<XmlDocument>()};
-    list<shared_ptr<XmlNode>> children, statesChildren, memoryChildren, connectionChildren{};
+    list<shared_ptr<XmlNode>> children{};
+    list<shared_ptr<XmlNode>> statesChildren{};
+    list<shared_ptr<XmlNode>> memoryChildren{};
+    list<shared_ptr<XmlNode>> connectionChildren{};
     list<shared_ptr<XmlAttribute>> attributes{};
 
     byte_field data = readXmlStateMachine();
@@ -285,7 +288,7 @@ namespace
 
   TEST_F(XmlParserTest, setDocument)
   {
-    shared_ptr<XmlDocument> document = make_shared<XmlDocument>();
+    auto document = make_shared<XmlDocument>();
     XmlParser xmlParser{document};
     ASSERT_TRUE(xmlParser.getDocument() == document);
 
@@ -296,7 +299,7 @@ namespace
 
   TEST_F(XmlParserTest, setDocument_no_reference)
   {
-    shared_ptr<XmlDocument> document = make_shared<XmlDocument>();
+    auto document = make_shared<XmlDocument>();
     XmlParser xmlParser{document};
 
     EXPECT_THROW(