Initial commit.

This commit is contained in:
jmsgrogan 2020-05-02 08:31:03 +01:00
commit 59c6161fdb
134 changed files with 4751 additions and 0 deletions

380
src/web/xml/XmlParser.cpp Normal file
View file

@ -0,0 +1,380 @@
#include "XmlParser.h"
#include "StringUtils.h"
#include <iostream>
using LS = XmlParser::LineState;
using DS = XmlParser::DocumentState;
XmlParser::XmlParser()
: mDocument(XmlDocument::Create()),
mDocumentState(XmlParser::DocumentState::Await_Prolog),
mLineState(XmlParser::LineState::Await_Tag_Open)
{
}
void XmlParser::ProcessLine(const std::string& input)
{
for(std::size_t idx; idx<input.size(); idx++)
{
switch (input[idx])
{
case StringUtils::LEFT_BRACKET:
OnLeftBracket();
break;
case StringUtils::RIGHT_BRACKET:
OnRightBracket();
break;
case StringUtils::QUESTION_MARK:
OnQuestionMark();
break;
case StringUtils::FORWARD_SLASH:
OnForwardSlash();
break;
case StringUtils::EQUALS:
OnEquals();
break;
case StringUtils::DOUBLE_QUOTE:
OnDoubleQuote();
break;
default:
OnChar(input[idx]);
break;
}
}
}
void XmlParser::OnChar(char c)
{
if(StringUtils::IsAlphaNumeric(c))
{
OnAlphaNumeric(c);
}
else if(StringUtils::IsSpace(c))
{
OnSpace(c);
}
else
{
OnNonAlphaNumeric(c);
}
}
void XmlParser::OnAlphaNumeric(char c)
{
switch(mLineState)
{
case LS::Await_Tag_Open:
OnTextStart(c);
break;
case LS::Await_Tag_Follower:
case LS::Await_Tag_Name:
{
OnTagNameStart(c);
break;
}
case LS::Await_Tag_Name_End:
{
mWorkingTagName.push_back(c);
break;
}
case LS::Await_Attribute_Name:
{
OnAttributeNameStart(c);
break;
}
case LS::Await_Attribute_Name_End:
{
mWorkingAttributeName.push_back(c);
break;
}
case LS::Await_Attribute_Value:
{
break;
}
case LS::Await_Attribute_Value_End:
{
mWorkingAttributeValue.push_back(c);
break;
}
case LS::Await_Text_End:
{
mWorkingText.push_back(c);
break;
}
default:
break;
}
}
void XmlParser::OnNonAlphaNumeric(char c)
{
switch(mLineState)
{
case LS::Await_Tag_Name_End:
{
mWorkingTagName.push_back(c);
break;
}
case LS::Await_Attribute_Name_End:
{
mWorkingAttributeName.push_back(c);
break;
}
case LS::Await_Attribute_Value_End:
{
mWorkingAttributeValue.push_back(c);
break;
}
case LS::Await_Text_End:
{
mWorkingText.push_back(c);
break;
}
default:
break;
}
}
void XmlParser::OnSpace(char c)
{
switch(mLineState)
{
case LS::Await_Tag_Name_End:
OnTagNameEnd();
break;
case LS::Await_Attribute_Name_End:
OnAttributeNameEnd();
break;
case LS::Await_Text_End:
mWorkingText.push_back(c);
break;
case LS::Await_Attribute_Value_End:
mWorkingAttributeValue.push_back(c);
break;
default:
break;
}
}
void XmlParser::OnLeftBracket()
{
switch(mLineState)
{
case LS::Await_Tag_Open:
{
OnTagOpen();
break;
}
case LS::Await_Text_End:
{
OnTextEnd();
OnTagOpen();
break;
}
default:
OnNonAlphaNumeric(StringUtils::LEFT_BRACKET);
break;
}
}
void XmlParser::OnRightBracket()
{
switch(mLineState)
{
case LS::Await_Tag_Name_End:
case LS::Await_Attribute_Name:
case LS::Await_Attribute_Name_End:
case LS::Await_Attribute_Value:
{
OnTagClose();
break;
}
default:
OnNonAlphaNumeric(StringUtils::RIGHT_BRACKET);
break;
}
}
void XmlParser::OnQuestionMark()
{
if(mLineState == LS::Await_Tag_Follower)
{
if(mDocumentState == DS::Await_Prolog)
{
OnStartProlog();
}
}
else if(mDocumentState != DS::Build_Prolog)
{
OnNonAlphaNumeric(StringUtils::QUESTION_MARK);
}
}
void XmlParser::OnForwardSlash()
{
if(mLineState == LS::Await_Tag_Follower)
{
if(mDocumentState == DS::Await_Element || mDocumentState == DS::Build_Element)
{
mDocumentState = DS::Close_Element;
}
}
}
void XmlParser::OnEquals()
{
if(mLineState == LS::Await_Attribute_Name_End)
{
OnAttributeNameEnd();
}
else
{
OnNonAlphaNumeric(StringUtils::EQUALS);
}
}
void XmlParser::OnDoubleQuote()
{
if(mLineState == LS::Await_Attribute_Value)
{
OnAttributeValueStart();
}
else if(mLineState == LS::Await_Attribute_Value_End)
{
OnAttributeValueEnd();
}
}
void XmlParser::OnTagOpen()
{
mLineState = LS::Await_Tag_Follower;
}
void XmlParser::OnTagClose()
{
if(mDocumentState == DS::Build_Prolog)
{
onFinishProlog();
}
else if(mDocumentState == DS::Build_Element)
{
if(mLineState == LS::Await_Tag_Name_End)
{
OnTagNameEnd();
}
onElementTagEnd();
}
else if(mDocumentState == DS::Close_Element)
{
if(mWorkingElement->GetTagName() == mWorkingTagName)
{
mDocumentState = DS::Await_Element;
mLineState = LS::Await_Tag_Open;
if(mParentElement)
{
mWorkingElement = mParentElement;
}
}
}
}
void XmlParser::OnTextStart(char c)
{
mWorkingText = c;
mLineState = LS::Await_Text_End;
}
void XmlParser::OnTextEnd()
{
mWorkingElement->SetText(mWorkingText);
}
void XmlParser::onElementTagEnd()
{
mDocumentState = DS::Await_Element;
mLineState = LS::Await_Tag_Open;
}
void XmlParser::OnTagNameStart(char c)
{
mWorkingTagName = c;
mLineState = LS::Await_Tag_Name_End;
if(mDocumentState != DS::Build_Prolog && mDocumentState != DS::Close_Element)
{
mDocumentState = DS::Build_Element;
}
}
void XmlParser::OnTagNameEnd()
{
if(mDocumentState == DS::Build_Prolog)
{
mWorkingProlog = XmlProlog::Create(mWorkingTagName);
mLineState = LS::Await_Attribute_Name;
}
else if(mDocumentState == DS::Build_Element)
{
auto new_element = XmlElement::Create(mWorkingTagName);
mParentElement = mWorkingElement;
mWorkingElement = new_element;
if(!mDocument->GetRoot())
{
mDocument->SetRoot(mWorkingElement);
}
mLineState = LS::Await_Attribute_Name;
}
}
void XmlParser::OnAttributeNameStart(char c)
{
mWorkingAttributeName = c;
mLineState = LS::Await_Attribute_Name_End;
}
void XmlParser::OnAttributeNameEnd()
{
mWorkingAttribute = XmlAttribute::Create(mWorkingAttributeName);
if(mDocumentState == DS::Build_Prolog)
{
mWorkingProlog->AddAttribute(mWorkingAttribute);
}
else if(mDocumentState == DS::Build_Element)
{
mWorkingElement->AddAttribute(mWorkingAttribute);
}
mLineState = LS::Await_Attribute_Value;
}
void XmlParser::OnAttributeValueStart()
{
mWorkingAttributeValue = "";
mLineState = LS::Await_Attribute_Value_End;
}
void XmlParser::OnAttributeValueEnd()
{
mWorkingAttribute->SetValue(mWorkingAttributeValue);
mLineState = LS::Await_Attribute_Name;
}
void XmlParser::OnStartProlog()
{
mDocumentState = DS::Build_Prolog;
mLineState = LS::Await_Tag_Name_End;
}
void XmlParser::onFinishProlog()
{
mWorkingProlog->Update();
mDocument->SetProlog(mWorkingProlog);
mWorkingProlog = nullptr;
mDocumentState = DS::Await_Element;
mLineState = LS::Await_Tag_Open;
}
XmlDocumentPtr XmlParser::GetDocument() const
{
return mDocument;
}