connection between 2 systems and bug fixes (#14)

This commit is contained in:
tompzf
2026-07-03 14:53:48 +02:00
committed by GitHub
parent 0fb5660d27
commit 46842200f1
284 changed files with 35200 additions and 8265 deletions

View File

@@ -37,7 +37,8 @@ namespace toml_parser
TTokenListIterator it = m_lstTokens.begin();
bool bCommaAvailable = false;
bool bPrintableCharsAvailable = false;
bool bLastTokenIsComment = false;
bool bLastTokenIsCommentOrForceNewline = false;
bool bNewlineAllowed = rContext.NewlineAllowed() || (eMode == EComposeMode::compose_behind && rContext.FinalNewline());
while (it != m_lstTokens.end() && it->Category() != ETokenCategory::token_comment)
{
// Add comma only when needed.
@@ -53,12 +54,12 @@ namespace toml_parser
bCommaAvailable = true;
break;
case ETokenCategory::token_comment:
bSkip = !rContext.CommentAndNewlineAllowed();
if (!bSkip) bLastTokenIsComment = true;
bSkip = !bNewlineAllowed;
if (!bSkip) bLastTokenIsCommentOrForceNewline = true;
break;
case ETokenCategory::token_syntax_new_line:
bSkip = !rContext.NewlineAllowed();
if (!bSkip) bLastTokenIsComment = false;
bSkip = !bNewlineAllowed;
if (!bSkip) bLastTokenIsCommentOrForceNewline = false;
break;
default:
break;
@@ -107,11 +108,11 @@ namespace toml_parser
break;
case ETokenCategory::token_comment:
bSkip = !rContext.CommentAndNewlineAllowed();
if (!bSkip) bLastTokenIsComment = true;
if (!bSkip) bLastTokenIsCommentOrForceNewline = true;
break;
case ETokenCategory::token_syntax_new_line:
bSkip = !rContext.NewlineAllowed();
if (!bSkip) bLastTokenIsComment = false;
bSkip = !bNewlineAllowed;
if (!bSkip) bLastTokenIsCommentOrForceNewline = false;
break;
default:
break;
@@ -210,11 +211,11 @@ namespace toml_parser
break;
case ETokenCategory::token_comment:
bSkip = !rContext.CommentAndNewlineAllowed();
if (!bSkip) bLastTokenIsComment = true;
if (!bSkip) bLastTokenIsCommentOrForceNewline = true;
break;
case ETokenCategory::token_syntax_new_line:
bSkip = !rContext.NewlineAllowed();
if (!bSkip) bLastTokenIsComment = false;
bSkip = !bNewlineAllowed;
if (!bSkip) bLastTokenIsCommentOrForceNewline = false;
break;
default:
break;
@@ -239,7 +240,7 @@ namespace toml_parser
}
// Default newline needed
if (rContext.FinalNewline() && ((m_lstTokens.empty() && m_ssComment.empty()) || bLastTokenIsComment))
if (rContext.FinalNewline() && ((m_lstTokens.empty() && m_ssComment.empty()) || bLastTokenIsCommentOrForceNewline))
sstream << std::endl;
break;
case EComposeMode::compose_before:

View File

@@ -16,6 +16,8 @@
#include "exception.h"
#include <sstream>
#include <limits>
#include <support/toml.h>
#include "parser_toml.h"
namespace toml_parser
{
@@ -560,4 +562,21 @@ namespace toml_parser
return sstreamQuotedText.str();
}
}
bool CompareEqual(const std::string& rssToml1, const std::string& rssToml2)
{
try
{
CParser parser1(rssToml1);
CParser parser2(rssToml2);
sdv::toml::CNodeCollection collection1(&parser1.Root());
sdv::toml::CNodeCollection collection2(&parser2.Root());
return sdv::toml::internal::CompareNodes(collection1, collection2) == sdv::toml::ECompareResult::compare_identical;
}
catch (const toml_parser::XTOMLParseException&)
{
return false;
}
}
} // namespace toml_parser

View File

@@ -108,6 +108,16 @@ namespace toml_parser
* @return The quoted key (if applicable); otherwise the key without quotes.
*/
std::string QuoteText(const std::string& rssText, EQuoteRequest eQuoteRequest = EQuoteRequest::smart_text);
/**
* @brief Compare the content of TOML string with the content of another TOML string. Use internal TOML parser for the
* comparison.
* @param[in] rssToml1 Reference to the first TOML string to compare with the second TOML string.
* @param[in] rssToml2 Reference to the second TOML string to compare with the first TOML string.
* @return The comparison result.
*/
bool CompareEqual(const std::string& rssToml1, const std::string& rssToml2);
} // namespace toml_parser
#endif // !defined MISCELLANEOUS_H

View File

@@ -0,0 +1,145 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#include "parser_node_indexer.h"
#include <interfaces/toml.h>
#include <iostream>
namespace toml_parser
{
CNodeIndex::CNodeIndex(CIndexList& rIndexList, CIndexListIterator itPos) : m_ptrPos(std::make_shared<CIteratorWrapper>(rIndexList, itPos))
{}
CNodeIndex::~CNodeIndex()
{
m_ptrPos.reset();
}
CNodeIndex::CNodeIndex(const CNodeIndex& rIndex) : m_ptrPos(rIndex.m_ptrPos)
{}
CNodeIndex::CNodeIndex(CNodeIndex&& rIndex) : m_ptrPos(std::move(rIndex.m_ptrPos))
{}
CNodeIndex& CNodeIndex::operator=(const CNodeIndex& rIndex)
{
m_ptrPos = rIndex.m_ptrPos;
return *this;
}
CNodeIndex& CNodeIndex::operator=(CNodeIndex&& rIndex)
{
m_ptrPos = std::move(rIndex.m_ptrPos);
return *this;
}
bool CNodeIndex::operator==(const CNodeIndex& rIndex) const
{
return rIndex.m_ptrPos == m_ptrPos;
}
bool CNodeIndex::operator!=(const CNodeIndex& rIndex) const
{
return !operator==(rIndex);
}
bool CNodeIndex::operator<(const CNodeIndex& rIndex) const
{
if (!m_ptrPos) return false;
if (!rIndex.m_ptrPos) return true;
return m_ptrPos->Index() < rIndex.m_ptrPos->Index();
}
bool CNodeIndex::operator<=(const CNodeIndex& rIndex) const
{
if (!m_ptrPos) return false;
if (!rIndex.m_ptrPos) return true;
return rIndex.m_ptrPos == m_ptrPos || m_ptrPos->Index() < rIndex.m_ptrPos->Index();
}
bool CNodeIndex::operator>(const CNodeIndex& rIndex) const
{
if (!m_ptrPos) return true;
if (!rIndex.m_ptrPos) return false;
return m_ptrPos->Index() > rIndex.m_ptrPos->Index();
}
bool CNodeIndex::operator>=(const CNodeIndex& rIndex) const
{
if (!m_ptrPos) return true;
if (!rIndex.m_ptrPos) return false;
return rIndex.m_ptrPos == m_ptrPos || m_ptrPos->Index() > rIndex.m_ptrPos->Index();
}
CNodeIndex::operator bool() const
{
return m_ptrPos ? true : false;
}
void CNodeIndex::MoveBefore(const CNodeIndex& rIndex)
{
if (m_ptrPos && rIndex.m_ptrPos)
m_ptrPos->MoveBeforeIndex(*rIndex.m_ptrPos);
}
uint32_t CNodeIndex::Index() const
{
if (!m_ptrPos) return sdv::toml::npos;
return m_ptrPos->Index();
}
CNodeIndex::CIteratorWrapper::CIteratorWrapper(CIndexList& rIndexList, CIndexListIterator itPos) :
m_rIndexList(rIndexList), m_itPos(itPos)
{}
CNodeIndex::CIteratorWrapper ::~CIteratorWrapper()
{
m_rIndexList.erase(m_itPos);
}
uint32_t CNodeIndex::CIteratorWrapper::Index() const
{
return static_cast<uint32_t>(std::distance(m_rIndexList.cbegin(), m_itPos));
}
void CNodeIndex::CIteratorWrapper::MoveBeforeIndex(const CIteratorWrapper& ritTarget)
{
m_rIndexList.splice(ritTarget.m_itPos, m_rIndexList, m_itPos);
}
// Global index list
CIndexList CNodeIndexer::m_lstIndexList;
CNodeIndexer::CNodeIndexer()
{}
CNodeIndex CNodeIndexer::CreateIndex()
{
auto itPos = m_lstIndexList.insert(m_lstIndexList.end(), SNodeIndexElement());
CNodeIndex index(m_lstIndexList, itPos);
return index;
}
CNodeIndex CNodeIndexer::CreateIndex(const CNodeIndex& rInsertBefore)
{
CNodeIndex node_index = CreateIndex();
node_index.MoveBefore(rInsertBefore);
return node_index;
}
size_t CNodeIndexer::Count()
{
return m_lstIndexList.size();
}
} // namespace toml_parser

View File

@@ -0,0 +1,227 @@
/********************************************************************************
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Erik Verhoeven - initial API and implementation
********************************************************************************/
#ifndef PARSER_NODE_INDEXER_H
#define PARSER_NODE_INDEXER_H
#include <list>
#include <memory>
#include <cstdint>
namespace toml_parser
{
class CNodeIndex;
class CNodeIndexer;
/// Placeholder index element
struct SNodeIndexElement {};
/// Index list
using CIndexList = std::list<SNodeIndexElement>;
/// Const iterator to an element in the index list
using CIndexListIterator = CIndexList::const_iterator;
/**
* @brief Node index object used to manage the node order.
*/
class CNodeIndex
{
friend CNodeIndexer; ///< CNodeIndex uses friend access to create the node index and assign the iterator holding the
///< the position within the index list.
private:
/**
* @brief Constructor of the node index object. Use the CNodeIndexer::CreateIndex function to create the object.
* @param[in] rIndexList Reference to the index list.
* @param[in] itPos Iterator to the position in the index list.
*/
CNodeIndex(CIndexList& rIndexList, CIndexListIterator itPos);
public:
/**
* @brief Destructor
*/
virtual ~CNodeIndex();
/**
* @brief Copy constructor of the node index object.
* @param[in] rIndex Reference to the index object to copy from.
*/
CNodeIndex(const CNodeIndex& rIndex);
/**
* @brief Move constructor of the node index object.
* @param[in] rIndex Reference to the index object to move from.
*/
CNodeIndex(CNodeIndex&& rIndex);
/**
* @brief Copy assignment operator of the node index object.
* @param[in] rIndex Reference to the index object to copy from.
* @return Returns a reference to this object.
*/
CNodeIndex& operator=(const CNodeIndex& rIndex);
/**
* @brief Move assignment operator of the node index object.
* @param[in] rIndex Reference to the index object to move from.
* @return Returns a reference to this object.
*/
CNodeIndex& operator=(CNodeIndex&& rIndex);
/**
* @brief Compare this node index object to the supplied index object and return whether the position of this object is
* identical to the position of the supplied object.
* @param[in] rIndex Reference to the node index object to compare with.
* @return Returns whether the provided index is identical to this index.
*/
bool operator==(const CNodeIndex& rIndex) const;
/**
* @brief Compare this node index object to the supplied index object and return whether the position of this object is
* not identical to the position of the supplied object.
* @param[in] rIndex Reference to the node index object to compare with.
* @return Returns whether the provided index is different than this index.
*/
bool operator!=(const CNodeIndex& rIndex) const;
/**
* @brief Compare this node index object to the supplied index object and return whether the position of this object is
* smaller than the position of the supplied object.
* @param[in] rIndex Reference to the node index object to compare with.
* @return Returns whether the provided index is smaller than this index.
*/
bool operator<(const CNodeIndex& rIndex) const;
/**
* @brief Compare this node index object to the supplied index object and return whether the position of this object is
* smaller than or equal to the position of the supplied object.
* @param[in] rIndex Reference to the node index object to compare with.
* @return Returns whether the provided index is smaller than or equal to this index.
*/
bool operator<=(const CNodeIndex& rIndex) const;
/**
* @brief Compare this node index object to the supplied index object and return whether the position of this object is
* larger than the position of the supplied object.
* @param[in] rIndex Reference to the node index object to compare with.
* @return Returns whether the provided index is larger than this index.
*/
bool operator>(const CNodeIndex& rIndex) const;
/**
* @brief Compare this node index object to the supplied index object and return whether the position of this object is
* larger than or equal to the position of the supplied object.
* @param[in] rIndex Reference to the node index object to compare with.
* @return Returns whether the provided index is larger than or equal to this index.
*/
bool operator>=(const CNodeIndex& rIndex) const;
/**
* @brief Check for validity.
* @return Returns whether the index object contains a valid index.
*/
operator bool() const;
/**
* @brief Move the node index object before the index object provided as an argument.
* @param[in] rIndex Reference to the node index object to move the object before.
*/
void MoveBefore(const CNodeIndex& rIndex);
/**
* @brief Get the index in the list. Returns sdv::toml::npos if the index is not in the list any more.
* @remarks This index os calculated dynamically and can change if indices are added, removed or swapped.
* @return The current index in the list.
*/
uint32_t Index() const;
private:
/**
* @brief Iterator wrapper object with lifetime management.
* @remarks The wrapper keeps track of the shared index list as well. It is possible that the parser is deleted before the
* nodes are deleted, causing an issue when accessing the index list.
*/
struct CIteratorWrapper
{
/**
* @brief Constructor
* @param[in] rIndexList Reference to the index list.
* @param[in] itPos Position of this index in the index list.
*/
CIteratorWrapper(CIndexList& rIndexList, CIndexListIterator itPos);
/**
* @brief Destructor removing the index object from the index list.
*/
~CIteratorWrapper();
/**
* @brief Get the index in the list.
* @remarks This index os calculated dynamically and can change if indices are added, removed or swapped.
* @return The current index in the list.
*/
uint32_t Index() const;
/**
* @brief Move the index object before the supplied index object.
* @param[in] ritTarget Reference to the index object to move the object before.
*/
void MoveBeforeIndex(const CIteratorWrapper& ritTarget);
private:
CIndexList& m_rIndexList; ///< Reference to the index list.
CIndexListIterator m_itPos; ///< Iterator in the list
};
std::shared_ptr<CIteratorWrapper> m_ptrPos; ///< Position in the index list
};
/**
* @brief Node indexer object managing the node index objects allowing determining and changing the order of nodes.
*/
class CNodeIndexer
{
friend CNodeIndex; ///< CNodeIndex has friend relationship allowing access to specific indexing functions using the
///< index iterator from the index list.
public:
/**
* @brief Constructor
*/
CNodeIndexer();
/**
* @brief Create a node index object.
* @return The new node index object.
*/
CNodeIndex CreateIndex();
/**
* @brief Create a new node index object and insert this object before the supplied object.
* @attention There is no protection for supplying an invalid iterator or an iterator from a different indexer.
* @param[in] rInsertBefore Insert the index object before the supplied iterator position.
* @return The new node index object.
*/
CNodeIndex CreateIndex(const CNodeIndex& rInsertBefore);
/**
* @brief Return the amount of indices allocated.
* @return The amount of indices allocated in the index list.
*/
static size_t Count();
private:
static CIndexList m_lstIndexList; ///< List of all node indices. This list is global to allow nodes from one
///< parser to be inserted into the list of another parser.
};
} // namespace toml_parser
#endif // !defined PARSER_NODE_INDEXER_H

File diff suppressed because it is too large Load Diff

View File

@@ -26,6 +26,7 @@
#include <support/interface_ptr.h>
#include "miscellaneous.h"
#include "code_snippet.h"
#include "parser_node_indexer.h"
/// The TOML parser namespace
namespace toml_parser
@@ -72,11 +73,12 @@ namespace toml_parser
void InitTopMostNode(const std::shared_ptr<const CNode>& rptrNode);
/**
* @brief Check whether the provided node is a parent of the top most node.
* @param[in] rptrNode Reference to the node to use for the checking.
* @return Returns true if the node is a parent of the top most node, false otherwise.
* @brief A node is part of the view if either it is an inline node, or it is a standard node and the current parent is the
* root view.
* @param[in] rptrNode Reference to the smart pointer to the node to check for.
* @return Returns whether the node is part of the view.
*/
bool PartOfExcludedParents(const std::shared_ptr<const CNode>& rptrNode) const;
bool IsPartOfView(const std::shared_ptr<const CNode>& rptrNode) const;
/**
* @brief Create a copy of the context class with a new key context.
@@ -289,10 +291,42 @@ namespace toml_parser
END_SDV_INTERFACE_MAP()
/**
* @{
* @brief Get a reference to the TOML parser that generated this node.
* @return Reference to the TOML parse.
*/
CParser& Parser();
const CParser& Parser() const;
/**
* @}
*/
/**
* @{
* @brief Return the index object of the node.
* @return Reference to the node index object.
*/
const CNodeIndex& NodeIndex() const;
CNodeIndex& NodeIndex();
/**
* @}
*/
/**
* @brief Compare the index position of this node with the position of another node and return whether this node occurs
* before the other node.
* @param[in] rNode Reference to the node to compare the position with.
* @return Returns whether this node occurs before the other node.
*/
bool operator<(const CNode& rNode) const;
/**
* @brief Compare the index position of this node with the position of another node and return whether this node occurs
* before the other node.
* @param[in] rptrNode Reference to the node to compare the position with.
* @return Returns whether this node occurs before the other node.
*/
bool operator<(const std::shared_ptr<CNode>& rptrNode) const;
/**
* @brief Get the node name (no conversion to a literal or quoted key is made). Overload of sdv::toml::INodeInfo::GetName.
@@ -328,9 +362,8 @@ namespace toml_parser
virtual sdv::any_t GetValue() const override;
/**
* @brief Get the index of this node within the view collection (either the assigned view or the parent). Overload of
* sdv::toml::INodeInfo::GetIndex.
* @return The index of the node within the view collection node or npos when no parent is available.
* @brief Get the index of this node within the parent collection. Overload of sdv::toml::INodeInfo::GetIndex.
* @return The index of the node within the parent collection node or npos when no parent is available.
*/
virtual uint32_t GetIndex() const override;
@@ -370,10 +403,10 @@ namespace toml_parser
virtual sdv::u8string GetComment(sdv::toml::INodeInfo::ECommentType eType) override;
/**
* @brief Format the node automatically. This will remove the whitespace between the elements within the node. Comments
* will not be changed. Overload of sdv::toml::INodeInfo::AutomaticFormat.
* @brief Format the node automatically, remove redundant whitespace. Overload of sdv::toml::INodeInfo::AutomaticFormat.
* @param[in] bRemoveComments When set, the comments are removed from the node.
*/
virtual void AutomaticFormat() override;
virtual void AutomaticFormat(/*in*/ bool bRemoveComments) override;
/**
* @brief Is the node inline? Overload of sdv::toml::INodeInfo::IsInline.
@@ -457,10 +490,11 @@ namespace toml_parser
std::shared_ptr<const TNodeType> Cast() const;
/**
* @brief Set the parent node.
* @brief Reassign the parent node and if necessary the parser reference.
* @details This function allows shifting nodes from one parser to another.
* @param[in] rptrParent Reference to the node to assign to this node as a parent.
*/
void SetParentPtr(const std::shared_ptr<CNodeCollection>& rptrParent);
virtual void SetParentPtr(const std::shared_ptr<CNodeCollection>& rptrParent);
/**
* @brief Gets the parent node pointer.
@@ -475,29 +509,6 @@ namespace toml_parser
*/
std::string GetParentPath() const;
/**
* @brief Set the view definition node. The view definition node is a parent or grand parent that presents the node when
* generating TOML code. When not set, the parent node is taking over this role.
* @param[in] rptrView Reference to the node to assign to this node as a parent or grand parent.
*/
void SetViewPtr(const std::shared_ptr<CNodeCollection>& rptrView);
/**
* @brief Gets the view definition node pointer.
* @return Returns the store view definition node pointer or an empty pointer when no view was assigned.
*/
std::shared_ptr<CNodeCollection> GetViewPtr() const;
/**
* @brief Checks whether the node is part of the view.
* @details The node is part of the view if the supplied pointer is identical to the view definition pointer, when the view
* definition pointer is not part of a parent of the topmost node. In all other cases, the node is part of the view.
* @param[in] rContext Reference to the context class to use during TOML code generation.
* @param[in] rptrNode Reference to the node to check whether it registered for a view.
* @return Returns whether this node is part of the view with the supplied pointer.
*/
bool IsPartOfView(const CGenContext& rContext, const std::shared_ptr<const CNodeCollection>& rptrNode) const;
/**
* @brief Accesses a node by its key in the parse tree.
* @details Elements of tables can be accessed and traversed by using '.' to separated the parent name from child name.
@@ -507,7 +518,7 @@ namespace toml_parser
* @attention Array indexing starts with 0!
* @attention For an array, when no indexing is supplied, the latest entry will be returned.
* @param[in] rssPath The path of the node to searched for.
* @return Returns a shared pointer to the wanted Node if it was found or a node with invalid content if it was not found.
* @return Returns a shared pointer to the wanted node if it was found or a node with invalid content if it was not found.
*/
virtual std::shared_ptr<CNode> Direct(const std::string& rssPath) const = 0;
@@ -577,13 +588,20 @@ namespace toml_parser
*/
std::string GetCustomPath(const std::string& rssPrefixKey, const std::string& rssContext) const;
/**
* @brief When the parent changes (e.g. when moving items from one parser to the other), the items and all its sub-items
* need to reasign the parser.
* @param[in] rParser Reference to the parser to assign.
*/
virtual void ReassignParser(CParser& rParser);
private:
std::weak_ptr<CNodeCollection> m_ptrParent; ///< Weak pointer to the parent node (if existing).
std::weak_ptr<CNodeCollection> m_ptrView; ///< Weak pointer to the view node (if existing and explicitly set).
std::string m_ssName; ///< Name of the node.
std::string m_ssRawName; ///< Raw name of the node.
bool m_bDeleted = false; ///< Enabled when the node was marked for deletion.
CParser& m_rParser; ///< Reference to the TOML parser.
CNodeIndex m_index; ///< Node index object holding the overall node position.
std::weak_ptr<CNodeCollection> m_ptrParent; ///< Weak pointer to the parent node (if existing).
std::string m_ssName; ///< Name of the node.
std::string m_ssRawName; ///< Raw name of the node.
bool m_bDeleted = false; ///< Enabled when the node was marked for deletion.
std::reference_wrapper<CParser> m_refParser; ///< Reference to the TOML parser.
std::vector<std::map<std::string, CCodeSnippet>> m_vecCodeSnippets; ///< Vector with comments/code snippets.
public:
@@ -596,11 +614,16 @@ namespace toml_parser
/**
* @brief With some node collections it is possible to switch between inline and normal.
* @remarks Additional node composition information will be removed and the order within the parent node might be changed.
* @remarks When made inline, all child nodes must be made inline as well. When made standard, only this node is made
* standard.
* @remarks Making this node a standard node, this is only possible when the parent is not an inline mode.
* @param[in] bInline When set, try to switch to inline. Otherwise try to switch to normal.
* @param[in] bIncludeChildren When set and bInline is not set, applicable child nodes are converted as well (only tables
* and table-arrays can be defined as standard). Making a node inline is always including the children.
* @return Returns whether the switch was successful. A switch to the same type (normal to normal or inline to inline is
* always successful). When returning false, the switching might not be supported for this type.
*/
virtual bool Inline(bool bInline) = 0;
virtual bool Inline(bool bInline, bool bIncludeChildren = true) = 0;
/**
* @brief Checks whether the table was explicitly defined.
@@ -654,10 +677,12 @@ namespace toml_parser
* @brief With some node collections it is possible to switch between inline and normal. Overload of CNode::Inline.
* @remarks Additional node composition information will be removed and the order within the parent node might be changed.
* @param[in] bInline When set, try to switch to inline. Otherwise try to switch to normal.
* @param[in] bIncludeChildren When set and bInline is not set, applicable child nodes are converted as well (only tables
* and table-arrays can be defined as standard). Making a node inline is always including the children.
* @return Returns whether the switch was successful. A switch to the same type (normal to normal or inline to inline is
* always successful). When returning false, the switching might not be supported for this type.
*/
virtual bool Inline(bool bInline) override;
virtual bool Inline(bool bInline, bool bIncludeChildren = true) override;
/**
* @brief Accesses a node by its key in the parse tree. Overload of CNode::Direct.
@@ -668,7 +693,7 @@ namespace toml_parser
* @attention Array indexing starts with 0!
* @attention For an array, when no indexing is supplied, the latest entry will be returned.
* @param[in] rssPath The path of the node to searched for.
* @return Returns a shared pointer to the wanted Node if it was found or a node with invalid content if it was not found.
* @return Returns a shared pointer to the wanted node if it was found or a node with invalid content if it was not found.
*/
virtual std::shared_ptr<CNode> Direct(const std::string& rssPath) const override;
@@ -943,10 +968,10 @@ namespace toml_parser
END_SDV_INTERFACE_MAP()
/**
* @brief Format the node automatically. This will remove the whitespace between the elements within the node. Comments
* will not be changed. Overload of sdv::toml::INodeInfo::AutomaticFormat.
* @brief Format the node automatically, remove redundant whitespace. Overload of sdv::toml::INodeInfo::AutomaticFormat.
* @param[in] bRemoveComments When set, the comments are removed from the node.
*/
virtual void AutomaticFormat() override;
virtual void AutomaticFormat(/*in*/ bool bRemoveComments) override;
/**
* @brief Returns the amount of nodes. Overload of sdv::toml::INodeCollection::GetCount.
@@ -966,7 +991,28 @@ namespace toml_parser
* @param[in] uiIndex Index of the node to get.
* @return Smart pointer to the node object.
*/
std::shared_ptr<CNode> Get(uint32_t uiIndex) const;
virtual std::shared_ptr<CNode> Get(uint32_t uiIndex) const;
/**
* @brief After every insert, deletion and shift, the node order of this and all sub- tables need to be rebuild.
* @param[in] bForce Force rebuild, even if locked.
*/
virtual void RebuildNodeOrder(bool bForce);
/**
* @brief After every insert, deletion and shift, the node order needs to be rebuild.
* @details Adding is done iteratively through the node list. In case the top level flag is set, all nodes are added that
* are marked explicit or if a node is implicit, the explicit sub-nodes are added. In case this is root view, all sub-nodes
* which are standard tables or standard table arrays are added. This flattens the hierarchy. When the root view is not set,
* only the tables and table arrays are added that are a direct child of the node collection. At the end of building the
* root view, the nodes are sorted using their index. Furthermore, inline nodes are moved to the beginning of the vector and
* standard nodes to the end.
* @param[in, out] rvecNodes Reference to the vector being filled with the nodes for the view.
* @param[in] bRootView Set when the count is top level.
* @param[in] bTopLevel Set when this is the top level node for adding sub nodes.
*/
virtual void FillNodeOrderVector(std::vector<std::shared_ptr<CNode>>& rvecNodes, bool bRootView = true,
bool bTopLevel = true);
/**
* @brief Accesses a node by its key in the parse tree. Overload of CNode::Direct.
@@ -977,7 +1023,7 @@ namespace toml_parser
* @attention Array indexing starts with 0!
* @attention For an array, when no indexing is supplied, the latest entry will be returned.
* @param[in] rssPath The path of the node to searched for.
* @return Returns a shared pointer to the wanted Node if it was found or a node with invalid content if it was not found.
* @return Returns a shared pointer to the wanted node if it was found or a node with invalid content if it was not found.
*/
virtual std::shared_ptr<CNode> Direct(const std::string& rssPath) const override;
@@ -993,85 +1039,124 @@ namespace toml_parser
*/
virtual sdv::IInterfaceAccess* GetNodeDirect(/*in*/ const sdv::u8string& ssPath) const override;
/**
* @brief Get or create the parent nodes automotatically from the path.
* @details Elements of tables can be accessed and traversed by using '.' to separated the parent name from child name.
* E.g. 'parent.child' would access the 'child' element of the 'parent' table. Elements of arrays can be accessed and
* traversed by using the index number in brackets. E.g. 'array[3]' would access the fourth element of the array 'array'.
* These access conventions can also be chained like 'table.array[2][1].subtable.integerElement'.
* @attention Array indexing starts with 0!
* @attention For an array, when no indexing or a too large index number is supplied, a new entry will be created and
* returned.
* @param[in] rssPath The path of the node to searched for.
* @param[in] bInsertTableArray Since a table array consists of an array and a table, this is different than the other
* insertions that only insert one element. Some special treatment is needed at certain points.
* @return Returns a pair with the shared pointer to the parent node and the leftover name. If the creation could not be
* done, a NULL pointer is returned.
*/
virtual std::pair<std::shared_ptr<CNodeCollection>, std::string> SmartParentCreate(const std::string& rssPath,
bool bInsertTableArray = false);
/**
* @brief Insert a value into the collection at the location before the supplied index. Overload of
* sdv::toml::INodeCollectionInsert::InsertValue.
* @param[in] uiIndex The insertion location to insert the node before. Can be npos or any value larger than the
* collection count to insert the node at the end of the collection. Value nodes cannot be inserted behind external
* tables and table arrays. If the index is referencing a position behind an external table or a table array, the index
* is automatically corrected.
* @param[in] ssName Name of the node to insert. Will be ignored for an array collection. The name must adhere to the
* key names defined by the TOML specification. Defining the key multiple times is not allowed. Quotation of key names
* is done automatically; the parser decides itself whether the key is bare-key, a literal key or a quoted key.
* @param[in] anyValue The value of the node, being either an integer, floating point number, virtual bool value or a string.
* @remarks In TOML, inline nodes are located before standard nodes. Since values are presented as inline node, they
* will be inserted before any standard node (table or table array if defined as standard node).
* @param[in] ssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
* square brackets. Can be empty, causing the node to be inserted at the end.
* @param[in] ssName Name of the node to insert. This name can contain parent nodes, which are automatically created if
* not existing. With arrays, since the value in TOML doesn't have a name, the name of the value must be an empty
* string and any names provided are considered parent nodes. The name must adhere to the key names defined by the TOML
* specification. Defining the key multiple times is not allowed. Quotation of key names is done automatically; the
* parser decides itself whether the key is bare-key, a literal key or a quoted key.
* @param[in] anyValue The value of the node, being either an integer, floating point number, virtual bool value or a
* string.
* Conversion is automatically done to int64, double float, bool or u8string.
* @return On success the interface to the newly inserted node is returned or NULL otherwise.
*/
virtual sdv::IInterfaceAccess* InsertValue(uint32_t uiIndex, const sdv::u8string& ssName, sdv::any_t anyValue) override;
virtual sdv::IInterfaceAccess* InsertValue(/*in*/ const sdv::u8string& ssInsertBefore, /*in*/ const sdv::u8string& ssName,
/*in*/ sdv::any_t anyValue) override;
/**
* @brief Insert an array into the collection at the location before the supplied index. Overload of
* sdv::toml::INodeCollectionInsert::InsertArray.
* @param[in] uiIndex The insertion location to insert the node before. Can be npos or any value larger than the
* collection count to insert the node at the end of the collection. Array nodes cannot be inserted behind external
* tables and table arrays. If the index is referencing a position behind an external table or a table array, the index
* is automatically corrected.
* @param[in] ssName Name of the array node to insert. Will be ignored if the current node is also an array collection.
* The name must adhere to the key names defined by the TOML specification. Defining the key multiple times is not
* allowed. Quotation of key names is done automatically; the parser decides itself whether the key is bare-key, a
* literal key or a quoted key.
* @remarks In TOML, inline nodes are located before standard nodes. Since arrays are presented as inline node, they
* will be inserted before any standard node (table or table array if defined as standard node).
* @param[in] ssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
* square brackets. Can be empty, causing the node to be inserted at the end.
* @param[in] ssName Name of the node to insert. This name can contain parent nodes, which are automatically created if
* not existing. With arrays, since the value in TOML doesn't have a name, the name of the value must be an empty
* string and any names provided are considered parent nodes. The name must adhere to the key names defined by the TOML
* specification. Defining the key multiple times is not allowed. Quotation of key names is done automatically; the
* parser decides itself whether the key is bare-key, a literal key or a quoted key.
* @return On success the interface to the newly inserted node is returned or NULL otherwise.
*/
virtual sdv::IInterfaceAccess* InsertArray(uint32_t uiIndex, const sdv::u8string& ssName) override;
virtual sdv::IInterfaceAccess* InsertArray(/*in*/ const sdv::u8string& ssInsertBefore,
/*in*/ const sdv::u8string& ssName) override;
/**
* @brief Insert a table into the collection at the location before the supplied index. Overload of
* sdv::toml::INodeCollectionInsert::InsertTable.
* @param[in] uiIndex The insertion location to insert the node before. Can be npos or any value larger than the
* collection count to insert the node at the end of the collection. Table nodes cannot be inserted before value nodes
* or arrays. If the index is referencing a position before a value node or an array, the index is automatically
* corrected.
* @param[in] ssName Name of the table node to insert. Will be ignored if the current node is an array collection.
* The name must adhere to the key names defined by the TOML specification. Defining the key multiple times is not
* allowed. Quotation of key names is done automatically; the parser decides itself whether the key is bare-key, a
* literal key or a quoted key.
* @remarks In TOML, inline nodes are located before standard nodes. Tables can be inserted as inline node, in which
* case they will be inserted before any standard node (table or table array if defined as standard node).
* @param[in] ssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
* square brackets. Can be empty, causing the node to be inserted at the end.
* @param[in] ssName Name of the node to insert. This name can contain parent nodes, which are automatically created if
* not existing. With arrays, since the value in TOML doesn't have a name, the name of the value must be an empty
* string and any names provided are considered parent nodes. The name must adhere to the key names defined by the TOML
* specification. Defining the key multiple times is not allowed. Quotation of key names is done automatically; the
* parser decides itself whether the key is bare-key, a literal key or a quoted key.
* @param[in] ePreference The preferred form of the node to be inserted.
* @return On success the interface to the newly inserted node is returned or NULL otherwise.
*/
virtual sdv::IInterfaceAccess* InsertTable(uint32_t uiIndex, const sdv::u8string& ssName,
sdv::toml::INodeCollectionInsert::EInsertPreference ePreference) override;
virtual sdv::IInterfaceAccess* InsertTable(/*in*/ const sdv::u8string& ssInsertBefore, /*in*/ const sdv::u8string& ssName,
/*in*/ sdv::toml::EInsertPreference ePreference) override;
/**
* @brief Insert a table array into the collection at the location before the supplied index. Overload of
* sdv::toml::INodeCollectionInsert::InsertTableArray.
* @param[in] uiIndex The insertion location to insert the node before. Can be npos or any value larger than the
* collection count to insert the node at the end of the collection. Table array nodes cannot be inserted before value
* nodes or arrays. If the index is referencing a position before a value node or an array, the index is automatically
* corrected.
* @param[in] ssName Name of the array node to insert. Will be ignored if the current node is also an array collection.
* The name must adhere to the key names defined by the TOML specification. Defining the key multiple times is not
* allowed. Quotation of key names is done automatically; the parser decides itself whether the key is bare-key, a
* literal key or a quoted key.
* @remarks In TOML, inline nodes are located before standard nodes. Table arrays can be inserted as inline node, in
* which case they will be inserted before any standard node (table or table array if defined as standard node).
* @param[in] ssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
* square brackets. Can be empty, causing the node to be inserted at the end.
* @param[in] ssName Name of the node to insert. This name can contain parent nodes, which are automatically created if
* not existing. With arrays, since the value in TOML doesn't have a name, the name of the value must be an empty
* string and any names provided are considered parent nodes. The name must adhere to the key names defined by the TOML
* specification. Defining the key multiple times is not allowed. Quotation of key names is done automatically; the
* parser decides itself whether the key is bare-key, a literal key or a quoted key.
* @param[in] ePreference The preferred form of the node to be inserted.
* @return On success the interface to the newly inserted node is returned or NULL otherwise.
*/
virtual sdv::IInterfaceAccess* InsertTableArray(uint32_t uiIndex, const sdv::u8string& ssName,
sdv::toml::INodeCollectionInsert::EInsertPreference ePreference) override;
virtual sdv::IInterfaceAccess* InsertTableArray(/*in*/ const sdv::u8string& ssInsertBefore, /*in*/ const sdv::u8string& ssName,
/*in*/ sdv::toml::EInsertPreference ePreference) override;
/**
* @brief Insert a TOML string as a child of the current collection node. If the collection is a table, the TOML string
* should contain values and inline/external/array-table nodes with names. If the collection is an array, the TOML
* string should contain and inline table nodes without names. Overload of sdv::toml::INodeCollectionInsert::InsertTOML.
* @param[in] uiIndex The insertion location to insert the node before. Can be npos or any value larger than the
* collection count to insert the node at the end of the collection. Table array nodes cannot be inserted before value
* nodes or arrays. If the index is referencing a position before a value node or an array, the index is automatically
* corrected.
* @remarks In TOML, inline nodes are located before standard nodes. Dependable on the nodes defined in the TOML they
* might be transferred to inline or they might be inserted at a different location.
* @param[in] ssInsertBefore Name of the node to insert the value before. In case of an array, can be an index between
* square brackets. Can be empty, causing the node to be inserted at the end.
* @param[in] ssTOML The TOML string to insert.
* @param[in] bRollbackOnPartly If only part of the nodes could be inserted, no node will be inserted.
* @return The result of the insertion.
*/
virtual sdv::toml::INodeCollectionInsert::EInsertResult InsertTOML(uint32_t uiIndex, const sdv::u8string& ssTOML,
bool bRollbackOnPartly) override;
virtual sdv::toml::INodeCollectionInsert::EInsertResult InsertTOML(/*in*/ const sdv::u8string& ssInsertBefore,
/*in*/ const sdv::u8string& ssTOML, /*in*/ bool bRollbackOnPartly) override;
/**
* @brief Insert a TOML string as a child of the current collection node. If the collection is a table, the TOML string
* should contain values and inline/external/array-table nodes with names. If the collection is an array, the TOML
* string should contain and inline table nodes without names.
* @param[in] rptrInsertBefore The node to insert the TOML nodes before (if possible). Can be NULL, causing the TOML nodes
* to be inserted at the end.
* @param[in] ssTOML The TOML string to insert.
* @param[in] bRollbackOnPartly If only part of the nodes could be inserted, no node will be inserted.
* @return A pair structure with the result of the insertion and a vector of all the inserted nodes.
*/
std::pair<sdv::toml::INodeCollectionInsert::EInsertResult, std::vector<std::shared_ptr<CNode>>> InsertTOML(
const std::shared_ptr<CNode>& rptrInsertBefore, const sdv::u8string& ssTOML, bool bRollbackOnPartly);
/**
* @brief Delete the current node. Overload of sdv::toml::INodeUpdate::DeleteNode.
@@ -1080,6 +1165,23 @@ namespace toml_parser
*/
virtual bool DeleteNode() override;
/**
* @brief The derived class from the node collection can be inline or not. Overload of CNode::Inline.
* @return Returns whether the node is an inline node.
*/
virtual bool Inline() const override;
/**
* @brief With some node collections it is possible to switch between inline and normal. Overload of CNode::Inline.
* @remarks Additional node composition information will be removed and the order within the parent node might be changed.
* @param[in] bInline When set, try to switch to inline. Otherwise try to switch to normal.
* @param[in] bIncludeChildren When set and bInline is not set, applicable child nodes are converted as well (only tables
* and table-arrays can be defined as standard). Making a node inline is always including the children.
* @return Returns whether the switch was successful. A switch to the same type (normal to normal or inline to inline is
* always successful). When returning false, the switching might not be supported for this type.
*/
virtual bool Inline(bool bInline, bool bIncludeChildren = true) override;
/**
* @brief Can the node convert to an inline definition? Overload of sdv::toml::INodeCollectionConvert::CanMakeInline.
* @return Returns whether the conversion to inline is possible. Returns 'true' when the node is already inline.
@@ -1101,10 +1203,12 @@ namespace toml_parser
/**
* @brief Convert the node to a standard node. Overload of sdv::toml::INodeCollectionConvert::MakeStandard.
* @param[in] bIncludeChildren When set, applicable child nodes are made are converted to standard nodes as well (only
* tables and table-arrays can be defined as standard).
* @return Returns whether the conversion was successful. Returns 'true' when the node was already defined as standard
* node.
*/
virtual bool MakeStandard() override;
virtual bool MakeStandard(/*in*/ bool bIncludeChildren) override;
/**
* @brief Delete a node from the collection.
@@ -1114,28 +1218,6 @@ namespace toml_parser
*/
bool DeleteNode(const std::shared_ptr<CNode>& rptrNode);
/**
* @brief Insert the node into the view.
* @remarks The node must be a descendant (direct child or an indirect child) of the node.
* @details Insert the node into the vector (and remove it from any previous vector if still assigned). Inline nodes can be
* assigned to stadard and inline nodes. Standard nodes can only be assigned to standard nodes. In the vector, first the
* inline nodes and then the standard nodes are located. This means that an inline node will be placed before standard nodes
* and standard nodes behind inline nodes, regardless of the index provided.
* @param[in] uiIndex Location within the vector to insert the node. Could be sdv::toml::npos to insert as last node.
* @param[in] rptrNode Reference to the smart pointer to the node to set the view for. If the node is not a direct child
* node, the view pointer of the node will be set.
* @return Returns true when the insertion was successful, false when node (likely because the node to insert is a standard
* node, whereas this node is an inline node.
*/
bool InsertIntoView(uint32_t uiIndex, const std::shared_ptr<CNode>& rptrNode);
/**
* @brief Remove a node from a view.
* @param[in] rptrNode Reference to the smart pointer pointing to the node to remove.
* @return Returns whether the removal was successful.
*/
bool RemoveFromView(const std::shared_ptr<CNode>& rptrNode);
/**
* @brief Find the index belonging to the provided node.
* @param[in] rptrNode Reference to the smart pointer holding the node to return the index for.
@@ -1151,7 +1233,7 @@ namespace toml_parser
bool IsDescendant(const std::shared_ptr<CNode>& rptrNode) const;
/**
* @brief Generic inserting function for nodes.
* @brief Generic add function for nodes.
* @details Elements of tables can be accessed and traversed by using '.' to separated the parent name from child name.
* E.g. 'parent.child' would access the 'child' element of the 'parent' table. Elements of arrays can be accessed and
* traversed by using the index number in brackets. E.g. 'array[3]' would access the fourth element of the array 'array'.
@@ -1160,10 +1242,6 @@ namespace toml_parser
* @attention For an array, when no indexing is supplied, the latest entry will be returned.
* @remarks If the node to insert exists already, but is marked implicit, the node will be returned and made explicit. In
* all other cases the an error will occur that the node already exists.
* @param[in] uiIndex The insertion location to insert the node before. Can be npos or any value larger than the
* collection count to insert the node at the end of the collection. Table array nodes cannot be inserted before value
* nodes or arrays. If the index is referencing a position before a value node or an array, the index is automatically
* corrected.
* @param[in] rrangeKeyPath Reference to the token range containing the path to the node to insert.
* @param[in] rtArgs Zero or more references to arguments passed to the constructor of the node classes being created by
* this function.
@@ -1171,7 +1249,7 @@ namespace toml_parser
* there the returned node is a table within the table array.
*/
template <typename TNodeType, typename... TArgs>
std::shared_ptr<CNode> Insert(uint32_t uiIndex, const CTokenRange& rrangeKeyPath, const TArgs&... rtArgs);
std::shared_ptr<CNode> AddNodeFromRange(const CTokenRange& rrangeKeyPath, const TArgs&... rtArgs);
/**
* @brief Combine the collection with the provided content (mathematical union).
@@ -1191,6 +1269,13 @@ namespace toml_parser
*/
virtual bool Reduce(const std::shared_ptr<CNodeCollection>& rptrCollection) = 0;
/**
* @brief When the parent changes (e.g. when moving items from one parser to the other), the items and all its sub-items
* need to reasign the parser. Overload of CNode::ReassignParser.
* @param[in] rParser Reference to the parser to assign.
*/
virtual void ReassignParser(CParser& rParser) override;
private:
/**
* @brief When set, the child nodes need grouping (values following each other, tables and table arrays at the end).
@@ -1228,8 +1313,6 @@ namespace toml_parser
// The child node uses the parent node pointer to indicate which node holds node.
// The child node uses the view node pointer to indicate which node displays the node content.
std::vector<std::shared_ptr<CNode>> m_vecNodeOrder; ///< Vector holding the child nodes (could contain grand children as
///< well).
std::list<std::shared_ptr<CNode>> m_lstNodes; ///< List holding the direct child nodes.
std::list<std::shared_ptr<CNode>> m_lstRecycleBin; ///< List holding the child elements that were deleted. This will
///< prevent destruction of the node class, which would otherwise
@@ -1283,6 +1366,26 @@ namespace toml_parser
*/
virtual sdv::toml::ENodeType GetType() const override;
/**
* @brief Returns the amount of nodes. Overload of sdv::toml::INodeCollection::GetCount.
* @return The amount of nodes.
*/
virtual uint32_t GetCount() const override;
/**
* @brief Get the node. Overload of CNodeCollection::Get.
* @param[in] uiIndex Index of the node to get.
* @return Smart pointer to the node object.
*/
virtual std::shared_ptr<CNode> Get(uint32_t uiIndex) const override;
/**
* @brief Delete the current node. Overload of sdv::toml::INodeUpdate::DeleteNode.
* @attention A successful deletion will cause all interfaces to the current node to become inoperable.
* @return Returns whether the deletion was successful.
*/
virtual bool DeleteNode() override;
/**
* @brief Create the TOML text based on the content using an optional prefix node. Overload of CNode::GenerateTOML.
* @param[in] rContext Reference to the context class to use during TOML code generation.
@@ -1308,10 +1411,12 @@ namespace toml_parser
* table doesn't have a name.
* @remarks Additional node composition information will be removed and the order within the parent node might be changed.
* @param[in] bInline When set, try to switch to inline. Otherwise try to switch to normal.
* @param[in] bIncludeChildren When set and bInline is not set, applicable child nodes are converted as well (only tables
* and table-arrays can be defined as standard). Making a node inline is always including the children.
* @return Returns whether the switch was successful. A switch to the same type (normal to normal or inline to inline is
* always successful). When returning false, the switching might not be supported for this type.
*/
virtual bool Inline(bool bInline) override;
virtual bool Inline(bool bInline, bool bIncludeChildren = true) override;
/**
* @brief Checks whether the table was explicitly defined. Overload of CNodeCollection::ExplicitlyDefined.
@@ -1342,9 +1447,17 @@ namespace toml_parser
*/
virtual bool Reduce(const std::shared_ptr<CNodeCollection>& rptrCollection) override;
/**
* @brief After every insert, deletion and shift, the node order of this and all sub- tables need to be rebuild.
* @param[in] bForce Force rebuild, even if locked.
*/
virtual void RebuildNodeOrder(bool bForce) override;
private:
bool m_bDefinedExplicitly = true; ///< When set, the table is defined explicitly.
bool m_bInline = false; ///< Flag determining whether the table is inline or not.
bool m_bDefinedExplicitly = true; ///< When set, the table is defined explicitly.
bool m_bInline = false; ///< Flag determining whether the table is inline or not.
std::vector<std::shared_ptr<CNode>> m_vecNodeOrder; ///< Vector holding the child nodes (could contain grand children as
///< well).
};
/**
@@ -1426,10 +1539,28 @@ namespace toml_parser
* @attention Array element access indices starts with 0!
* @attention For an array element inserting, when no indexing is supplied, the latest entry will be returned.
* @param[in] rssPath Reference to the path of the node to searched for.
* @return Returns a shared pointer to the wanted Node if it was found or a node with invalid content if it was not found.
* @return Returns a shared pointer to the wanted node if it was found or a node with invalid content if it was not found.
*/
virtual std::shared_ptr<CNode> Direct(const std::string& rssPath) const override;
/**
* @brief Get or create the parent nodes automotatically from the path. Overload of CNodeCollection::SmartParentCreate.
* @details Elements of tables can be accessed and traversed by using '.' to separated the parent name from child name.
* E.g. 'parent.child' would access the 'child' element of the 'parent' table. Elements of arrays can be accessed and
* traversed by using the index number in brackets. E.g. 'array[3]' would access the fourth element of the array 'array'.
* These access conventions can also be chained like 'table.array[2][1].subtable.integerElement'.
* @attention Array indexing starts with 0!
* @attention For an array, when no indexing or a too large index number is supplied, a new entry will be created and
* returned.
* @param[in] rssPath The path of the node to searched for.
* @param[in] bInsertTableArray Since a table array consists of an array and a table, this is different than the other
* insertions that only insert one element. Some special treatment is needed at certain points.
* @return Returns a pair with the shared pointer to the parent node and the leftover name. If the creation could not be
* done, a NULL pointer is returned.
*/
virtual std::pair<std::shared_ptr<CNodeCollection>, std::string> SmartParentCreate(const std::string& rssPath,
bool bInsertTableArray = false) override;
/**
* @brief Create the TOML text based on the content using an optional prefix node. Overload of CNode::GenerateTOML.
* @param[in] rContext Reference to the context class to use during TOML code generation.
@@ -1450,13 +1581,6 @@ namespace toml_parser
*/
bool TableArray() const;
/**
* @brief Can the node convert to a standard definition? Overload of sdv::toml::INodeCollectionConvert::CanMakeStandard.
* @return Returns whether the conversion to standard is possible. Returns 'true' when the node is already defined as
* standard node.
*/
virtual bool CanMakeStandard() const override;
/**
* @brief The derived class from the node collection can be inline or not. Overload of CNode::Inline.
* @return Returns whether the node is an inline node.
@@ -1472,10 +1596,19 @@ namespace toml_parser
* doesn't have a name that can be used to define the explicit table array.
* @remarks Additional node composition information will be removed and the order within the parent node might be changed.
* @param[in] bInline When set, try to switch to inline. Otherwise try to switch to normal.
* @param[in] bIncludeChildren When set and bInline is not set, applicable child nodes are converted as well (only tables
* and table-arrays can be defined as standard). Making a node inline is always including the children.
* @return Returns whether the switch was successful. A switch to the same type (normal to normal or inline to inline is
* always successful). When returning false, the switching might not be supported for this type.
*/
virtual bool Inline(bool bInline) override;
virtual bool Inline(bool bInline, bool bIncludeChildren = true) override;
/**
* @brief Can the node convert to a standard definition? Overload of sdv::toml::INodeCollectionConvert::CanMakeStandard.
* @return Returns whether the conversion to standard is possible. Returns 'true' when the node is already defined as
* standard node.
*/
virtual bool CanMakeStandard() const override;
/**
* @brief Does the last child node need a comma following the node?
@@ -1534,7 +1667,7 @@ namespace toml_parser
* @brief Constructor
* @param[in] rparser Reference to the TOML parser.
*/
CRootTable(CParser& rparser) : CTable(rparser, "root", "", false)
CRootTable(CParser& rparser) : CTable(rparser, "root", "", false, true)
{}
/**
@@ -1550,20 +1683,25 @@ namespace toml_parser
*/
virtual bool Inline() const override
{
// The root node can never be inline.
return false;
}
/**
* @brief With some node collections it is possible to switch between inline and normal. Overload of
* CNodeCollection::Inline.
* @brief Switch between inline and explicit table definition. Overload of CNodeCollection::Inline.
* @attention It is not possible to switch to an explicit table definition if the table is part of an array, since the
* table doesn't have a name.
* @remarks Additional node composition information will be removed and the order within the parent node might be changed.
* @param[in] bInline When set, try to switch to inline. Otherwise try to switch to normal.
* @param[in] bIncludeChildren When set and bInline is not set, applicable child nodes are converted as well (only tables
* and table-arrays can be defined as standard). Making a node inline is always including the children.
* @return Returns whether the switch was successful. A switch to the same type (normal to normal or inline to inline is
* always successful). When returning false, the switching might not be supported for this type.
*/
virtual bool Inline(bool bInline) override
virtual bool Inline(bool bInline, bool bIncludeChildren = true) override
{
return bInline == false;
// Pass call to table implementation.
return CTable::Inline(bInline, bIncludeChildren);
}
};
@@ -1580,7 +1718,7 @@ namespace toml_parser
}
template <typename TNodeType, typename... TArgs>
inline std::shared_ptr<CNode> CNodeCollection::Insert(uint32_t uiIndex, const CTokenRange& rrangeKeyPath, const TArgs&... rtArgs)
inline std::shared_ptr<CNode> CNodeCollection::AddNodeFromRange(const CTokenRange& rrangeKeyPath, const TArgs&... rtArgs)
{
// Get the first part of the node
auto prKey = SplitNodeKey(rrangeKeyPath);
@@ -1613,9 +1751,8 @@ namespace toml_parser
"' exists already, but is not a table array.");
// Create the table.
ptrNode = ptrTableArray->Insert<CTable>(sdv::toml::npos, CTokenRange(prKey.first, prKey.first.get().Next()),
ptrNode = ptrTableArray->AddNodeFromRange<CTable>(CTokenRange(prKey.first, prKey.first.get().Next()),
false, true);
ptrNode->SetViewPtr(Cast<CNodeCollection>());
} else if (!Cast<CArray>() && itNode != m_lstNodes.end())
{
// If existing... this might be a duplicate if not explicitly defined before.
@@ -1644,7 +1781,7 @@ namespace toml_parser
// If the current node is implicit, take over the inline flag (this determines whether a sub-table definition is
// allowed or not).
if (!ExplicitlyDefined())
Inline(ptrNode->Inline());
Inline(ptrNode->Inline(), false);
}
}
else // Intermediate node
@@ -1663,6 +1800,9 @@ namespace toml_parser
auto prNextKey = SplitNodeKey(prKey.second);
if (prNextKey.first.get().Category() != ETokenCategory::token_integer)
{
// The table array should have an ordered vector. This is not the case yet. Rebuild the table array.
ptrNode->Cast<CTableArray>()->RebuildNodeOrder(true);
// Get the last table
if (!ptrNode->Cast<CTableArray>()->GetCount())
throw XTOMLParseException("The parent table array node '" + prKey.first.get().StringValue() +
@@ -1700,23 +1840,14 @@ namespace toml_parser
std::shared_ptr<CNodeCollection> ptrNodeCollection = ptrNode->Cast<CNodeCollection>();
if (!ptrNodeCollection)
throw XTOMLParseException("Parent node is not an array or table '" + ptrNode->GetPath(true) + "'.");
ptrNode = ptrNodeCollection->Insert<TNodeType>(sdv::toml::npos, prKey.second, rtArgs...);
ptrNode = ptrNodeCollection->AddNodeFromRange<TNodeType>(prKey.second, rtArgs...);
if (!ptrNode)
throw XTOMLParseException("Could not create the node '" + prKey.first.get().StringValue() + "'.");
}
// Insert the node at the requested location if this node is inline or this is the view of the node.
auto itPos = (static_cast<size_t>(uiIndex) >= m_vecNodeOrder.size()) ? m_vecNodeOrder.end() :
m_vecNodeOrder.begin() + static_cast<size_t>(uiIndex);
m_vecNodeOrder.insert(itPos, ptrNode);
if (ptrNode->GetParentPtr() != Cast<CNodeCollection>())
ptrNode->SetViewPtr(Cast<CNodeCollection>());
// Return the result
return ptrNode;
}
} // namespace toml_parser
#endif // !defined PARSER_NODE_TOML_H

View File

@@ -54,6 +54,9 @@ namespace toml_parser
try
{
// Lock the rebuild of the node order
auto lock = CreateRebuildLockObject();
// Run through all tokens of the lexer and process the tokens.
bool bEOF = false; // Explicit test, since the peek could return EOF, but the cursor might not be at the end yet.
while (!bEOF && !m_lexer.IsEnd())
@@ -95,7 +98,7 @@ namespace toml_parser
}
catch (const sdv::toml::XTOMLParseException& e)
{
std::cout << e.what() << '\n';
std::cerr << e.what() << std::endl;
throw;
}
@@ -115,6 +118,11 @@ namespace toml_parser
return m_lexer;
}
CNodeIndexer& CParser::Indexer()
{
return m_indexer;
}
const CNodeCollection& CParser::Root() const
{
auto ptrCollection = m_ptrRoot->Cast<CTable>();
@@ -139,6 +147,49 @@ namespace toml_parser
return m_ptrRoot->GenerateTOML(rssPrefixKey);
}
CParser::CLockRebuild::CLockRebuild(CParser& rParser) : m_rParser(rParser)
{
rParser.IncrRebuildLockCnt();
}
CParser::CLockRebuild::CLockRebuild(const CLockRebuild& rLockRebuild) : m_rParser(rLockRebuild.m_rParser)
{
m_rParser.IncrRebuildLockCnt();
}
CParser::CLockRebuild::CLockRebuild(CLockRebuild&& rLockRebuild) : m_rParser(rLockRebuild.m_rParser)
{
m_rParser.IncrRebuildLockCnt();
}
CParser::CLockRebuild::~CLockRebuild()
{
m_rParser.DecrRebuildLockCnt();
}
CParser::CLockRebuild CParser::CreateRebuildLockObject()
{
return CLockRebuild(*this);
}
bool CParser::RebuildLocked() const
{
return m_nRebuildLockCnt ? true : false;
}
void CParser::IncrRebuildLockCnt()
{
++m_nRebuildLockCnt;
}
void CParser::DecrRebuildLockCnt()
{
if (!m_nRebuildLockCnt)
return; // Should not occur
--m_nRebuildLockCnt;
if (!m_nRebuildLockCnt) Root().RebuildNodeOrder(false);
}
void CParser::ProcessTable(CNodeTokenRange& rNodeRange)
{
// Get the table path (table name preceded by parent tables separated with dots).
@@ -154,7 +205,7 @@ namespace toml_parser
m_lexer.SmartExtendNodeRange(rNodeRange);
// Add the table to the root
auto ptrTable = m_ptrRoot->Insert<CTable>(sdv::toml::npos, rangeKeyPath, false);
auto ptrTable = m_ptrRoot->AddNodeFromRange<CTable>(rangeKeyPath, false);
if (ptrTable)
{
m_ptrCurrentCollection = ptrTable->Cast<CTable>();
@@ -176,7 +227,7 @@ namespace toml_parser
m_lexer.SmartExtendNodeRange(rNodeRange);
// Add the table array to the root
auto ptrTableArray = m_ptrRoot->Insert<CTableArray>(sdv::toml::npos, rangeKeyPath);
auto ptrTableArray = m_ptrRoot->AddNodeFromRange<CTableArray>(rangeKeyPath);
if (ptrTableArray)
{
m_ptrCurrentCollection = ptrTableArray->Cast<CNodeCollection>();
@@ -226,46 +277,43 @@ namespace toml_parser
switch (rAssignmentValue.Category())
{
case ETokenCategory::token_boolean:
ptrNode = m_ptrCurrentCollection->Insert<CBooleanNode>(sdv::toml::npos, rrangeKeyPath, rAssignmentValue.BooleanValue(),
ptrNode = m_ptrCurrentCollection->AddNodeFromRange<CBooleanNode>(rrangeKeyPath, rAssignmentValue.BooleanValue(),
rAssignmentValue.RawString());
break;
case ETokenCategory::token_integer:
ptrNode = m_ptrCurrentCollection->Insert<CIntegerNode>(sdv::toml::npos, rrangeKeyPath, rAssignmentValue.IntegerValue(),
ptrNode = m_ptrCurrentCollection->AddNodeFromRange<CIntegerNode>(rrangeKeyPath, rAssignmentValue.IntegerValue(),
rAssignmentValue.RawString());
break;
case ETokenCategory::token_float:
ptrNode = m_ptrCurrentCollection->Insert<CFloatingPointNode>(sdv::toml::npos, rrangeKeyPath, rAssignmentValue.FloatValue(),
ptrNode = m_ptrCurrentCollection->AddNodeFromRange<CFloatingPointNode>(rrangeKeyPath, rAssignmentValue.FloatValue(),
rAssignmentValue.RawString());
break;
case ETokenCategory::token_string:
switch (rAssignmentValue.StringType())
{
case ETokenStringType::literal_string:
ptrNode = m_ptrCurrentCollection->Insert<CStringNode>(sdv::toml::npos, rrangeKeyPath, rAssignmentValue.StringValue(),
ptrNode = m_ptrCurrentCollection->AddNodeFromRange<CStringNode>(rrangeKeyPath, rAssignmentValue.StringValue(),
CStringNode::EQuotationType::literal_string, rAssignmentValue.RawString());
break;
case ETokenStringType::multi_line_literal:
ptrNode = m_ptrCurrentCollection->Insert<CStringNode>(
sdv::toml::npos, rrangeKeyPath, rAssignmentValue.StringValue(), CStringNode::EQuotationType::multi_line_literal,
rAssignmentValue.RawString());
ptrNode = m_ptrCurrentCollection->AddNodeFromRange<CStringNode>(rrangeKeyPath, rAssignmentValue.StringValue(),
CStringNode::EQuotationType::multi_line_literal, rAssignmentValue.RawString());
break;
case ETokenStringType::multi_line_quoted:
ptrNode = m_ptrCurrentCollection->Insert<CStringNode>(
sdv::toml::npos, rrangeKeyPath, rAssignmentValue.StringValue(), CStringNode::EQuotationType::multi_line_quoted,
rAssignmentValue.RawString());
ptrNode = m_ptrCurrentCollection->AddNodeFromRange<CStringNode>(rrangeKeyPath, rAssignmentValue.StringValue(),
CStringNode::EQuotationType::multi_line_quoted, rAssignmentValue.RawString());
break;
case ETokenStringType::quoted_string:
default:
ptrNode = m_ptrCurrentCollection->Insert<CStringNode>(
sdv::toml::npos, rrangeKeyPath, rAssignmentValue.StringValue(), CStringNode::EQuotationType::quoted_string,
rAssignmentValue.RawString());
ptrNode = m_ptrCurrentCollection->AddNodeFromRange<CStringNode>(rrangeKeyPath, rAssignmentValue.StringValue(),
CStringNode::EQuotationType::quoted_string, rAssignmentValue.RawString());
break;
}
break;
case ETokenCategory::token_syntax_array_open:
{
auto ptrCurrentCollectionStored = m_ptrCurrentCollection;
ptrNode = m_ptrCurrentCollection->Insert<CArray>(sdv::toml::npos, rrangeKeyPath);
ptrNode = m_ptrCurrentCollection->AddNodeFromRange<CArray>(rrangeKeyPath);
m_ptrCurrentCollection = ptrNode->Cast<CNodeCollection>();
m_stackEnvironment.push(EEnvironment::array);
ProcessArray(rNodeRange);
@@ -276,7 +324,7 @@ namespace toml_parser
case ETokenCategory::token_syntax_inline_table_open:
{
auto ptrCurrentCollectionStored = m_ptrCurrentCollection;
ptrNode = m_ptrCurrentCollection->Insert<CTable>(sdv::toml::npos, rrangeKeyPath, true);
ptrNode = m_ptrCurrentCollection->AddNodeFromRange<CTable>(rrangeKeyPath, true);
m_ptrCurrentCollection = ptrNode->Cast<CNodeCollection>();
m_stackEnvironment.push(EEnvironment::inline_table);
ProcessInlineTable(rNodeRange);

View File

@@ -18,6 +18,7 @@
#include "lexer_toml.h"
#include "parser_node_toml.h"
#include "miscellaneous.h"
#include "parser_node_indexer.h"
#include <stack>
#include <memory>
#include <string>
@@ -25,7 +26,9 @@
/// The TOML parser namespace
namespace toml_parser
{
// Forward declarations
class CNode;
class CNodeCollection;
/**
* @brief Creates a tree structure from input of UTF-8 encoded TOML source data
@@ -33,6 +36,10 @@ namespace toml_parser
class CParser : public sdv::IInterfaceAccess, public sdv::toml::ITOMLParser
{
public:
// Forward declaration
class CLockRebuild;
friend CLockRebuild; ///< Friend class can trigger manage rebuild lock counter.
/**
* @brief Construct a new Parser object
* @param[in] rssString UTF-8 encoded data of a TOML source
@@ -66,6 +73,12 @@ namespace toml_parser
*/
CLexer& Lexer();
/**
* @brief Get the indexer object managing the overall order of the nodes.
* @return Reference to the index object.
*/
CNodeIndexer& Indexer();
/**
* @{
* @brief Return the root node.
@@ -85,7 +98,65 @@ namespace toml_parser
*/
std::string GenerateTOML(const std::string& rssPrefixKey = std::string()) const;
/**
* @brief Lock rebuild object preventing rebuilding the node order of all the tables.
*/
class CLockRebuild
{
friend CParser; ///< Parser can access the constructor
/**
* @brief Constructor
* @param[in] rParser Reference to the parser object
*/
CLockRebuild(CParser& rParser);
public:
/**
* @brief Copy constructor
* @param[in] rLockRebuild Reference to another rebuild lock object.
*/
CLockRebuild(const CLockRebuild& rLockRebuild);
/**
* @brief Move constructor
* @param[in] rLockRebuild Reference to another rebuild lock object.
*/
CLockRebuild(CLockRebuild&& rLockRebuild);
/**
* @brief Destructor
*/
~CLockRebuild();
private:
CParser& m_rParser; ///< Reference to the parser object
};
/**
* @brief Create a rebuild lock object. During the lifetime of the object rebuilding the node order is locked using the lock
* counter method.
* @return An instance of the rebuild lock object.
*/
CLockRebuild CreateRebuildLockObject();
/**
* @brief Returns whether rebuild is locked at the moment.
* @return Set when rebuild is locked.
*/
bool RebuildLocked() const;
private:
/**
* @brief Increase the rebuild lock counter. A lock count larger than 0 will prevent a rebuild.
*/
void IncrRebuildLockCnt();
/**
* @brief Decrease the rebuild lock counter. A lock count of 0 will trigger the rebuild.
*/
void DecrRebuildLockCnt();
/**
* @brief Process a table declaration.
* @param[in, out] rNodeRange Reference to the extended token range of the node.
@@ -139,10 +210,13 @@ namespace toml_parser
inline_table ///< Environment for a table
};
enum_stack<EEnvironment, EEnvironment::none> m_stackEnvironment; ///< Tracking of environments in nested structures.
std::shared_ptr<CRootTable> m_ptrRoot; ///< The one root node.
std::shared_ptr<CNodeCollection> m_ptrCurrentCollection; ///< The current collection node.
CLexer m_lexer; ///< Lexer.
enum_stack<EEnvironment, EEnvironment::none> m_stackEnvironment; ///< Tracking of environments in nested structures.
std::shared_ptr<CRootTable> m_ptrRoot; ///< The one root node.
std::shared_ptr<CNodeCollection> m_ptrCurrentCollection; ///< The current collection node.
CLexer m_lexer; ///< Lexer object user for lexing the TOML code.
CNodeIndexer m_indexer; ///< Indexer managing the oberall order of the nodes.
size_t m_nRebuildLockCnt = 0; ///< A lock counter > 0 will prevent the node order
///< rebuild.
};
} // namespace toml_parser