Skip to content

Commit

Permalink
YmlTree parser (#686) (#1135)
Browse files Browse the repository at this point in the history
* YmlTree parser

Generic XmlTreeItem tree for YAML files 

---------
Co-authored-by: Evgueni Driouk <evgueni.driouk@arm.com>
Co-authored-by: Daniel Brondani <daniel.brondani@arm.com>
  • Loading branch information
grasci-arm authored Sep 27, 2023
1 parent 989adc4 commit 657a563
Show file tree
Hide file tree
Showing 24 changed files with 925 additions and 57 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ add_subdirectory(libs/rteutils)
add_subdirectory(libs/xmlreader)
add_subdirectory(libs/xmltree)
add_subdirectory(libs/xmltreeslim)
add_subdirectory(libs/ymltree)
add_subdirectory(libs/ymlschemachecker)
add_subdirectory(libs/xmlschemachecker)

Expand Down
8 changes: 5 additions & 3 deletions libs/rteutils/include/RteUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,13 +359,15 @@ class RteUtils
}

static const std::string EMPTY_STRING;
static const std::string ERROR_STRING;
static const std::string BASE_STRING;
static const std::string UPDATE_STRING;
static const std::string DASH_STRING;
static const std::string CRLF_STRING;
static const std::string CR_STRING;
static const std::string LF_STRING;

static const std::string ERROR_STRING;
static const std::string BASE_STRING;
static const std::string UPDATE_STRING;

static const char CatalogName[];
static const std::set<std::string> EMPTY_STRING_SET;
static const std::list<std::string> EMPTY_STRING_LIST;
Expand Down
8 changes: 5 additions & 3 deletions libs/rteutils/src/RteUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,20 @@
using namespace std;

const string RteUtils::EMPTY_STRING("");
const string RteUtils::BASE_STRING("base");
const string RteUtils::UPDATE_STRING("update");
const string RteUtils::DASH_STRING("-");

const string RteUtils::CRLF_STRING(RteConstants::CRLF);
const string RteUtils::CR_STRING(RteConstants::CR);
const string RteUtils::LF_STRING(RteConstants::LF);

const string RteUtils::ERROR_STRING("<ERROR>");
const string RteUtils::BASE_STRING("base");
const string RteUtils::UPDATE_STRING("update");

const set<string> RteUtils::EMPTY_STRING_SET;
const list<string> RteUtils::EMPTY_STRING_LIST;
const vector<string> RteUtils::EMPTY_STRING_VECTOR;

const string RteUtils::ERROR_STRING("<ERROR>");
const char RteUtils::CatalogName[] = "pack.idx";

string RteUtils::GetPrefix(const string& s, char delimiter, bool withDelimiter)
Expand Down
8 changes: 5 additions & 3 deletions libs/xmltree/include/AbstractFormatter.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <sstream>
#include <string>
#include <vector>

/**
* @brief base abstract class to generate formatted text from XMLTreeElement items in a buffer of type string
Expand Down Expand Up @@ -43,12 +44,12 @@ class AbstractFormatter {

/**
* @brief generate formatted text
* @param parentElement pointer to an instance of type XMLTreeElement
* @param rootElement pointer to an instance of type XMLTreeElement
* @param schemaFile name of a schema file
* @param schemaVersion version of a schema file
* @return string containing instance content as XML formatted text
*/
virtual std::string FormatElement(XMLTreeElement* parentElement,
virtual std::string FormatElement(XMLTreeElement* rootElement,
const std::string& schemaFile = XmlItem::EMPTY_STRING,
const std::string& schemaVersion = XmlItem::EMPTY_STRING);

Expand All @@ -65,7 +66,8 @@ class AbstractFormatter {
virtual std::string GetIndentString(int level) const;

protected:
virtual void FormatXmlElement(std::ostringstream& outStream, XMLTreeElement* element, int level = 0) = 0;
virtual void FormatXmlElement(std::ostringstream& outStream, XMLTreeElement* element, int level = 0) {}; // default does nothing
static void CollectSortedChildren(XMLTreeElement* element, std::vector< std::pair<std::string, std::vector<XMLTreeElement*> > >& sortedChildren);

protected:
std::string m_Content;
Expand Down
10 changes: 8 additions & 2 deletions libs/xmltree/include/IXmlItemBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/******************************************************************************/
/*
* Copyright (c) 2020-2021 Arm Limited. All rights reserved.
*
*
* SPDX-License-Identifier: Apache-2.0
*/
/******************************************************************************/
Expand All @@ -14,7 +14,7 @@
* @brief abstract factory interface class to create XmlItem derived objects
*/
class IXmlItemBuilder {
public:
public:
/**
* @brief destructor
*/
Expand Down Expand Up @@ -45,6 +45,12 @@ class IXmlItemBuilder {
*/
virtual bool CreateItem(const std::string& tag) = 0;

/**
* @brief check if the interface created member root item
* @return true if root item has been already created
*/
virtual bool HasRoot() const = 0;

/**
* @brief pure virtual function to add created item to parent's children
*/
Expand Down
4 changes: 0 additions & 4 deletions libs/xmltree/include/JsonFormatter.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
#include "AbstractFormatter.h"
#include "XMLTree.h"

#include <vector>

/**
* @brief class to generate XML formatted text from XMLTreeElement items in a buffer of type string
*/
Expand All @@ -27,8 +25,6 @@ class JsonFormatter : public AbstractFormatter
void FormatXmlElementBody(std::ostringstream& outStream, XMLTreeElement* element, int level, bool outputTag);

void FormatXmlElements(std::ostringstream& outStream, const std::string& tag, const std::vector<XMLTreeElement*>& elements, int level);
static void CollectSortedChildern(XMLTreeElement* element, std::vector< std::pair<std::string, std::vector<XMLTreeElement*> > >& sortedChildren);

};

#endif /* JSONFORMATTER_H */
8 changes: 4 additions & 4 deletions libs/xmltree/include/XMLTree.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,10 +233,10 @@ class XMLTree : public XMLTreeElement
void SetXmlValueAdjuster(XmlValueAdjuster* adjuster) { m_XmlValueAdjuster = adjuster; }

/**
* @brief getter for associated XML schema file name
* @return associated XML schema file name
* @brief getter for associated schema file name
* @return associated schema file name
*/
const std::string& GetSchemaFileName() const { return m_xsdFile; }
const std::string& GetSchemaFileName() const { return m_schemaFile; }

/**
* @brief getter for associated XML file name
Expand Down Expand Up @@ -388,7 +388,7 @@ class XMLTree : public XMLTreeElement
bool DoParse(const std::string& fileName, const std::string& xmlString);

protected:
std::string m_xsdFile; // schema file with path
std::string m_schemaFile; // schema file with path

std::list<std::string> m_fileNames; // XML files to parse
// errors for all docs
Expand Down
10 changes: 8 additions & 2 deletions libs/xmltree/include/XmlFormatter.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,18 @@ class XmlFormatter : public AbstractFormatter
public:
/**
* @brief default constructor
* @param bInsertEmptyLines insert extra space between children on the level 0
*/
XmlFormatter();
XmlFormatter(bool bInsertEmptyLines = true);

/**
* @brief constructor which generates XML formatted text
* @param xmlTree pointer to an instance derived from XMLTreeElement
* @param schemaFile name of XML schema file
* @param schemaVersion version of XML schema file
* @param bInsertEmptyLines insert extra space between children on the level 0
*/
XmlFormatter(XMLTree* xmlTree, const std::string& schemaFile, const std::string& schemaVersion);
XmlFormatter(XMLTree* xmlTree, const std::string& schemaFile, const std::string& schemaVersion, bool bInsertEmptyLines = true);

/**
* @brief generate XML formatted text
Expand Down Expand Up @@ -54,8 +56,12 @@ class XmlFormatter : public AbstractFormatter
*/
static std::string ConvertSpecialChars(const std::string& input);

static const std::string XMLHEADER;

protected:
void FormatXmlElement(std::ostringstream& xmlStream, XMLTreeElement* element, int level=0) override;

bool m_bInsertEmptyLines;
};

#endif /* XMLFORMATTER_H */
2 changes: 1 addition & 1 deletion libs/xmltree/include/XmlTreeItemBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class XmlTreeItemBuilder : public IXmlItemBuilder
* @brief check member m_pRoot
* @return true if member m_pRoot not equal 0
*/
virtual bool HasRoot() const { return m_pRoot != 0; }
bool HasRoot() const override { return m_pRoot != 0; }

/**
* @brief add child specified by member m_pCurrent to parent
Expand Down
23 changes: 22 additions & 1 deletion libs/xmltree/src/AbstractFormatter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* SPDX-License-Identifier: Apache-2.0
*/

#include "XMLTree.h"
#include "AbstractFormatter.h"

using namespace std;
Expand Down Expand Up @@ -43,5 +42,27 @@ string AbstractFormatter::GetIndentString(int level) const
return string(((std::size_t)level) << 1, ' ');
}

void AbstractFormatter::CollectSortedChildren(XMLTreeElement* element, std::vector< std::pair<std::string, std::vector<XMLTreeElement*> > >& sortedChildren)
{
if (!element || !element->HasChildren()) {
return;
}
auto& children = element->GetChildren();
for (auto child : children) {
const string& tag = child->GetTag();
auto it = sortedChildren.begin();
for (; it != sortedChildren.end(); it++) {
if (it->first == tag) {
break;
}
}
if (it == sortedChildren.end()) {
it = sortedChildren.insert(sortedChildren.end(), make_pair(tag, vector<XMLTreeElement*>()));
}
it->second.push_back(child);
}
}



// end of AbstractFormatter.cpp
23 changes: 1 addition & 22 deletions libs/xmltree/src/JsonFormatter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ void JsonFormatter::FormatXmlElement(ostringstream& outStream, XMLTreeElement* e
outStream << indent << " \"#text\": \"" << text << "\"" << EOL_STRING;
} else if (element->HasChildren()) {
vector< pair<string, vector<XMLTreeElement*> > > sortedChildren;
CollectSortedChildern(element, sortedChildren);
CollectSortedChildren(element, sortedChildren);
std::size_t count = sortedChildren.size() - 1;
for (auto [k, v] : sortedChildren) {
FormatXmlElements(outStream, k, v, level + 1);
Expand Down Expand Up @@ -113,25 +113,4 @@ void JsonFormatter::FormatXmlElements(ostringstream& outStream, const string& ta
}
}

void JsonFormatter::CollectSortedChildern(XMLTreeElement* element, std::vector< std::pair<std::string, std::vector<XMLTreeElement*> > >& sortedChildren)
{
if (!element || !element->HasChildren()) {
return;
}
auto& children = element->GetChildren();
for (auto child : children) {
const string& tag = child->GetTag();
auto it = sortedChildren.begin();
for (; it != sortedChildren.end(); it++) {
if (it->first == tag) {
break;
}
}
if (it == sortedChildren.end()) {
it = sortedChildren.insert(sortedChildren.end(), make_pair(tag, vector<XMLTreeElement*>()));
}
it->second.push_back(child);
}
}

// end of JsonFormatter.cpp
8 changes: 4 additions & 4 deletions libs/xmltree/src/XMLTree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,12 @@ void XMLTree::SetXmlItemBuilder(IXmlItemBuilder* itemBuilder, bool takeOnerschip
}


void XMLTree::SetSchemaFileName(const char* xsdFile)
void XMLTree::SetSchemaFileName(const char* schemaFile)
{
if (xsdFile) {
m_xsdFile = XmlValueAdjuster::SlashesToOsSlashes(xsdFile);
if (schemaFile) {
m_schemaFile = XmlValueAdjuster::SlashesToOsSlashes(schemaFile);
} else {
m_xsdFile.clear();
m_schemaFile.clear();
}
}

Expand Down
19 changes: 12 additions & 7 deletions libs/xmltree/src/XmlFormatter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,19 @@

using namespace std;

const string XMLHEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>";
const string SCHEMAATTR = "xmlns:xsi";
const string SCHEMAINSTANCE = "http://www.w3.org/2001/XMLSchema-instance";
const string OWNNAMESPACE = "xsi:noNamespaceSchemaLocation";
const string VERSIONATTR = "schemaVersion";

XmlFormatter::XmlFormatter() {
const string XmlFormatter::XMLHEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>";
XmlFormatter::XmlFormatter(bool bInsertEmptyLines):
m_bInsertEmptyLines(bInsertEmptyLines)
{
}

XmlFormatter::XmlFormatter(XMLTree* xmlTree, const string& schemaFile, const string& schemaVersion)
XmlFormatter::XmlFormatter(XMLTree* xmlTree, const string& schemaFile, const string& schemaVersion, bool bInsertEmptyLines):
m_bInsertEmptyLines(bInsertEmptyLines)
{
m_Content = XmlFormatter::Format(xmlTree, schemaFile, schemaVersion);
}
Expand All @@ -33,9 +36,11 @@ string XmlFormatter::FormatElement(XMLTreeElement* rootElement, const string& sc
return XMLTree::EMPTY_STRING;
}
// Add xml header attributes
rootElement->AddAttribute(SCHEMAATTR, SCHEMAINSTANCE);
rootElement->AddAttribute(OWNNAMESPACE, schemaFile);
rootElement->AddAttribute(VERSIONATTR, schemaVersion);
if (!schemaFile.empty()) {
rootElement->AddAttribute(SCHEMAATTR, SCHEMAINSTANCE);
rootElement->AddAttribute(OWNNAMESPACE, schemaFile);
rootElement->AddAttribute(VERSIONATTR, schemaVersion);
}
// Format elements recursively
ostringstream xmlStream;
xmlStream << XMLHEADER << EOL_STRING;
Expand Down Expand Up @@ -64,7 +69,7 @@ void XmlFormatter::FormatXmlElement(ostringstream& xmlStream, XMLTreeElement* el
xmlStream << '>' << EOL_STRING;
for (auto it = children.begin(); it != children.end(); it++) {
// insert extra space between children on the level 0
if ((level == 0) && (it != children.begin())) {
if (m_bInsertEmptyLines && (level == 0) && (it != children.begin())) {
xmlStream << EOL_STRING;
}
FormatXmlElement(xmlStream, *it, level + 1);
Expand Down
2 changes: 1 addition & 1 deletion libs/xmltreeslim/src/XmlTreeSlimInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ void XMLTreeSlimInterface::InitMessageTable()

void XMLTreeSlimInterface::Clear() // does not destroy XML parser!
{
// does nothing for undelying XML_Parser
// does nothing for underlying XML_Parser
}

bool XMLTreeSlimInterface::Parse(const std::string& fileName, const std::string& xmlString)
Expand Down
18 changes: 18 additions & 0 deletions libs/ymltree/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
project(YmlTree VERSION 1.0.0)

add_subdirectory("test")

SET(SOURCE_FILES YmlTree.cpp YmlFormatter.cpp YmlTreeParserInterface.cpp YmlTreeParserInterface.h)
SET(HEADER_FILES YmlTree.h YmlFormatter.h)

list(TRANSFORM SOURCE_FILES PREPEND src/)
list(TRANSFORM HEADER_FILES PREPEND include/)

add_library(YmlTree STATIC ${SOURCE_FILES} ${HEADER_FILES})

set_property(TARGET YmlTree PROPERTY
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

target_include_directories(YmlTree PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)

target_link_libraries(YmlTree ErrLog XmlTree RteFsUtils RteUtils yaml-cpp YmlSchemaChecker)
37 changes: 37 additions & 0 deletions libs/ymltree/include/YmlFormatter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2020-2023 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef YMLFORMATTER_H
#define YMLFORMATTER_H

#include "AbstractFormatter.h"
#include "YmlTree.h"


/**
* @brief class to generate XML formatted text from XMLTreeElement items in a buffer of type string
*/
class YmlFormatter : public AbstractFormatter
{
public:
/**
* @brief default constructor
*/
YmlFormatter();

/**
* @brief generate formatted text
* @param rootElement pointer to an instance of type XMLTreeElement
* @param schemaFile name of a schema file (not used)
* @param schemaVersion version of a schema file (not used)
* @return string containing instance content as XML formatted text
*/
std::string FormatElement(XMLTreeElement* rootElement,
const std::string& schemaFile = XmlItem::EMPTY_STRING,
const std::string& schemaVersion = XmlItem::EMPTY_STRING) override;

};

#endif /* YMLFORMATTER_H */
Loading

0 comments on commit 657a563

Please sign in to comment.