Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 28 additions & 12 deletions lib/xml/xmlparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

#include <algorithm>
#include <atomic>
#include <generator>
#include <cstring>
#include <memory>
#include <type_traits>
#include <utility>

#include <xercesc/dom/DOM.hpp>
Expand Down Expand Up @@ -69,13 +69,18 @@ std::string getElementText(DOMElement* Element)
return trimCopy(Value);
}

std::generator<DOMElement*> iterateElementChildren(DOMElement* Parent)
template <typename Callback>
void iterateElementChildren(DOMElement* Parent, Callback&& Handler)
{
static_assert(
std::is_void_v<std::invoke_result_t<Callback, DOMElement*>>,
"iterateElementChildren callback must return void"
);
DOMNodeList* Children = Parent->getChildNodes();
for (XMLSize_t Index = 0; Index < Children->getLength(); ++Index) {
DOMNode* Child = Children->item(Index);
if (Child->getNodeType() == DOMNode::ELEMENT_NODE) {
co_yield static_cast<DOMElement*>(Child);
Handler(static_cast<DOMElement*>(Child));
}
}
}
Expand All @@ -85,7 +90,8 @@ struct MessageSlice
std::string_view Slice;
};

std::generator<MessageSlice> splitMessages(std::string_view Input, bool& FramingError)
template <typename Callback>
void splitMessages(std::string_view Input, bool& FramingError, Callback&& Handler)
{
std::size_t Cursor = 0;
std::size_t LastEnd = std::string_view::npos;
Expand All @@ -98,7 +104,7 @@ std::generator<MessageSlice> splitMessages(std::string_view Input, bool& Framing

if (LastEnd != std::string_view::npos && Start != LastEnd) {
FramingError = true;
co_return;
return;
}

const std::size_t End = Input.find(NLAP_XML_END_MARKER, Start);
Expand All @@ -107,7 +113,10 @@ std::generator<MessageSlice> splitMessages(std::string_view Input, bool& Framing
}

const std::size_t MessageEnd = End + NLAP_XML_END_MARKER.size();
co_yield MessageSlice{Input.substr(Start, MessageEnd - Start)};
// Handler must return true to continue iterating and false to stop.
if (!Handler(MessageSlice{Input.substr(Start, MessageEnd - Start)})) {
return;
}

Cursor = MessageEnd;
LastEnd = MessageEnd;
Expand Down Expand Up @@ -197,12 +206,12 @@ void populateTree(DOMElement* Element, XMLNode& Node, std::string_view RawMessag
{
bool HasElementChildren = false;

for (DOMElement* Child : iterateElementChildren(Element)) {
iterateElementChildren(Element, [&](DOMElement* Child) {
HasElementChildren = true;
const std::string ChildName = transcodeXMLCh(Child->getTagName());
XMLNode& ChildNode = Node[ChildName];
populateTree(Child, ChildNode, RawMessage, SearchOffset);
}
});

if (HasElementChildren) {
return;
Expand Down Expand Up @@ -297,11 +306,11 @@ uint16_t parseMessage(
XMLNode& RootNode = OutputTree[RootName];

std::size_t SearchOffset = 0;
for (DOMElement* Child : iterateElementChildren(Root)) {
iterateElementChildren(Root, [&](DOMElement* Child) {
const std::string ChildName = transcodeXMLCh(Child->getTagName());
XMLNode& ChildNode = RootNode[ChildName];
populateTree(Child, ChildNode, RawMessage, SearchOffset);
}
});

return 0;
}
Expand Down Expand Up @@ -372,17 +381,24 @@ ParseResult_t XMLParser::parse(char* InputBuffer) const
}

bool FramingError = false;
for (const MessageSlice& Slice : splitMessages(InputBufferSV, FramingError)) {
bool HasMessageError = false;
splitMessages(InputBufferSV, FramingError, [&](const MessageSlice& Slice) {
ResultTree_t Tree;
const uint16_t MessageError = parseMessage(_GrammarPool, Slice.Slice, Tree);

if (MessageError != 0) {
Result.ErrorCode = MessageError;
Result.Results.clear();
return Result;
HasMessageError = true;
return false;
}

Result.Results.push_back(std::move(Tree));
return true;
});

if (HasMessageError) {
return Result;
}

if (FramingError) {
Expand Down
Loading