Move xml and svg to lower levels.
This commit is contained in:
parent
942cc2539c
commit
7cab70f839
32 changed files with 35 additions and 33 deletions
|
@ -1,18 +1,6 @@
|
|||
set(MODULE_NAME web)
|
||||
|
||||
list(APPEND web_LIB_INCLUDES
|
||||
xml/XmlParser.h
|
||||
xml/XmlParser.cpp
|
||||
xml/XmlDocument.h
|
||||
xml/XmlDocument.cpp
|
||||
xml/XmlWriter.h
|
||||
xml/XmlWriter.cpp
|
||||
xml/xml-elements/XmlElement.h
|
||||
xml/xml-elements/XmlElement.cpp
|
||||
xml/xml-elements/XmlAttribute.h
|
||||
xml/xml-elements/XmlAttribute.cpp
|
||||
xml/xml-elements/XmlProlog.h
|
||||
xml/xml-elements/XmlProlog.cpp
|
||||
markdown/MarkdownParser.cpp
|
||||
markdown/MarkdownConverter.cpp
|
||||
markdown/MarkdownDocument.h
|
||||
|
@ -27,18 +15,6 @@ list(APPEND web_LIB_INCLUDES
|
|||
html/elements/HtmlHeadElement.cpp
|
||||
html/elements/HtmlBodyElement.cpp
|
||||
html/elements/HtmlParagraphElement.cpp
|
||||
svg/SvgDocument.h
|
||||
svg/SvgWriter.h
|
||||
svg/SvgReader.h
|
||||
svg/SvgShapeElement.h
|
||||
svg/SvgElement.h
|
||||
svg/elements/SvgShapeElements.h
|
||||
svg/SvgDocument.cpp
|
||||
svg/SvgReader.cpp
|
||||
svg/SvgWriter.cpp
|
||||
svg/SvgShapeElement.cpp
|
||||
svg/SvgElement.cpp
|
||||
svg/elements/SvgShapeElements.cpp
|
||||
)
|
||||
|
||||
# add the executable
|
||||
|
@ -46,14 +22,10 @@ add_library(${MODULE_NAME} SHARED ${web_LIB_INCLUDES})
|
|||
|
||||
target_include_directories(web PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/svg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/svg/elements
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/xml
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/xml/xml-elements
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/html
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/html/elements
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/markdown
|
||||
)
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER src)
|
||||
target_link_libraries(${MODULE_NAME} PUBLIC core compiler geometry)
|
||||
target_link_libraries(${MODULE_NAME} PUBLIC core compiler)
|
||||
set_target_properties( ${MODULE_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
|
|
@ -1,58 +0,0 @@
|
|||
#include "SvgDocument.h"
|
||||
|
||||
#include "XmlAttribute.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
SvgDocument::SvgDocument()
|
||||
: XmlDocument()
|
||||
{
|
||||
auto root = XmlElement::Create("svg");
|
||||
|
||||
auto xmlns = std::make_unique<XmlAttribute>("xmlns");
|
||||
xmlns->setValue("http://www.w3.org/2000/svg");
|
||||
|
||||
root->addAttribute(std::move(xmlns));
|
||||
|
||||
setRoot(std::move(root));
|
||||
}
|
||||
|
||||
void SvgDocument::setViewBox(double x, double y, double w, double h)
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << x << " " << y << " " << w << " " << h;
|
||||
setViewBox(sstr.str());
|
||||
}
|
||||
|
||||
void SvgDocument::setViewBox(const std::string& data)
|
||||
{
|
||||
auto viewbox = std::make_unique<XmlAttribute>("viewBox");
|
||||
viewbox->setValue(data);
|
||||
getRoot()->addAttribute(std::move(viewbox));
|
||||
}
|
||||
|
||||
SvgDocument::ViewBox SvgDocument::getViewBox() const
|
||||
{
|
||||
ViewBox viewBox;
|
||||
|
||||
if (!getRoot())
|
||||
{
|
||||
return viewBox;
|
||||
}
|
||||
|
||||
if (auto vb_attr = getRoot()->getAttribute("viewBox"); vb_attr)
|
||||
{
|
||||
auto entries = StringUtils::split(vb_attr->getValue());
|
||||
if (entries.size() != 4)
|
||||
{
|
||||
return viewBox;
|
||||
}
|
||||
|
||||
viewBox.mX = std::stod(entries[0]);
|
||||
viewBox.mY = std::stod(entries[1]);
|
||||
viewBox.mW = std::stod(entries[2]);
|
||||
viewBox.mH = std::stod(entries[3]);
|
||||
}
|
||||
return viewBox;
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "XmlDocument.h"
|
||||
|
||||
class SvgDocument : public XmlDocument
|
||||
{
|
||||
public:
|
||||
struct ViewBox
|
||||
{
|
||||
double mX{ 0 };
|
||||
double mY{ 0 };
|
||||
double mW{ 0 };
|
||||
double mH{ 0 };
|
||||
};
|
||||
|
||||
SvgDocument();
|
||||
|
||||
ViewBox getViewBox() const;
|
||||
|
||||
void setViewBox(const std::string& data);
|
||||
void setViewBox(double x, double y, double w, double h);
|
||||
};
|
|
@ -1,7 +0,0 @@
|
|||
#include "SvgElement.h"
|
||||
|
||||
SvgElement::SvgElement(const std::string& tagName)
|
||||
: XmlElement(tagName)
|
||||
{
|
||||
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "XmlElement.h"
|
||||
|
||||
class SvgElement : public XmlElement
|
||||
{
|
||||
public:
|
||||
SvgElement(const std::string& tagName);
|
||||
};
|
|
@ -1,76 +0,0 @@
|
|||
#include "SvgReader.h"
|
||||
|
||||
#include "File.h"
|
||||
#include "XmlParser.h"
|
||||
#include "XmlAttribute.h"
|
||||
|
||||
#include "SvgShapeElements.h"
|
||||
|
||||
#include "FileLogger.h"
|
||||
|
||||
std::unique_ptr<SvgDocument> SvgReader::read(const Path& path) const
|
||||
{
|
||||
auto svg_doc = std::make_unique<SvgDocument>();
|
||||
|
||||
File in_file(path);
|
||||
auto lines = in_file.readLines();
|
||||
|
||||
XmlParser parser;
|
||||
for (const auto& line : lines)
|
||||
{
|
||||
parser.processLine(line);
|
||||
}
|
||||
|
||||
auto xml_doc = parser.getDocument();
|
||||
|
||||
if (xml_doc->getRoot() && xml_doc->getRoot()->getTagName() == "svg")
|
||||
{
|
||||
onRoot(xml_doc->getRoot(), svg_doc.get());
|
||||
}
|
||||
return svg_doc;
|
||||
}
|
||||
|
||||
void SvgReader::onRoot(XmlElement* element, SvgDocument* doc) const
|
||||
{
|
||||
for (const auto& attr : element->getAttributes())
|
||||
{
|
||||
doc->getRoot()->addAttribute(attr.first, attr.second->getValue());
|
||||
}
|
||||
|
||||
for (const auto& child : element->getChildren())
|
||||
{
|
||||
onChild(child.get(), doc->getRoot());
|
||||
}
|
||||
}
|
||||
|
||||
void SvgReader::onChild(XmlElement* element, XmlElement* svg_parent) const
|
||||
{
|
||||
std::unique_ptr<XmlElement> new_svg;
|
||||
if (element->getTagName() == "circle")
|
||||
{
|
||||
new_svg = std::make_unique<SvgCircle>();
|
||||
}
|
||||
else if (element->getTagName() == "ellipse")
|
||||
{
|
||||
new_svg = std::make_unique<SvgCircle>(SvgCircle::Type::ELLIPSE);
|
||||
}
|
||||
else if (element->getTagName() == "rect")
|
||||
{
|
||||
new_svg = std::make_unique<SvgRectangle>();
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& attr : element->getAttributes())
|
||||
{
|
||||
new_svg->addAttribute(attr.first, attr.second->getValue());
|
||||
}
|
||||
|
||||
for (const auto& child : element->getChildren())
|
||||
{
|
||||
onChild(child.get(), new_svg.get());
|
||||
}
|
||||
svg_parent->addChild(std::move(new_svg));
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "SvgDocument.h"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
using Path = std::filesystem::path;
|
||||
|
||||
class SvgElement;
|
||||
|
||||
class SvgReader
|
||||
{
|
||||
public:
|
||||
std::unique_ptr<SvgDocument> read(const Path& path) const;
|
||||
|
||||
private:
|
||||
void onRoot(XmlElement* element, SvgDocument* doc) const;
|
||||
|
||||
void onChild(XmlElement* element, XmlElement* svg_parent) const;
|
||||
};
|
|
@ -1,146 +0,0 @@
|
|||
#include "SvgShapeElement.h"
|
||||
|
||||
#include "XmlAttribute.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
SvgShapeElement::SvgShapeElement(const std::string& tagName)
|
||||
: SvgElement(tagName)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Transform SvgShapeElement::getTransform() const
|
||||
{
|
||||
Transform transform;
|
||||
const std::string translate_key = "translate";
|
||||
const std::string scale_key = "scale";
|
||||
|
||||
if (auto attr = getAttribute("transform"); attr)
|
||||
{
|
||||
const auto val = attr->getValue();
|
||||
std::string working_string;
|
||||
bool in_translate = false;
|
||||
bool in_scale = false;
|
||||
for (auto c : val)
|
||||
{
|
||||
if (StringUtils::stripSurroundingWhitepsace(working_string) == translate_key)
|
||||
{
|
||||
in_translate = true;
|
||||
working_string.clear();
|
||||
continue;
|
||||
}
|
||||
else if (StringUtils::stripSurroundingWhitepsace(working_string) == scale_key)
|
||||
{
|
||||
in_scale = true;
|
||||
working_string.clear();
|
||||
continue;
|
||||
}
|
||||
else if (c == '(')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (c == ')')
|
||||
{
|
||||
if (in_translate)
|
||||
{
|
||||
const auto loc = parsePoint(working_string, 0.0);
|
||||
transform.setLocation(loc);
|
||||
in_translate = false;
|
||||
}
|
||||
else if (in_scale)
|
||||
{
|
||||
const auto loc = parsePoint(working_string, 1.0);
|
||||
transform.setScale(loc.getX(), loc.getY(), loc.getZ());
|
||||
in_scale = false;
|
||||
}
|
||||
working_string.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
working_string += c;
|
||||
}
|
||||
}
|
||||
}
|
||||
return transform;
|
||||
}
|
||||
|
||||
std::string SvgShapeElement::getLabelledContent(const std::string& key, const std::string& content) const
|
||||
{
|
||||
return content.substr(key.size(), content.size() - key.size() - 2);
|
||||
}
|
||||
|
||||
Point SvgShapeElement::parsePoint(const std::string& pointString, double defaultVal) const
|
||||
{
|
||||
double x = defaultVal;
|
||||
double y = defaultVal;
|
||||
double z = defaultVal;
|
||||
|
||||
const auto split = StringUtils::split(pointString);
|
||||
for (std::size_t idx = 0; idx < split.size(); idx++)
|
||||
{
|
||||
if (idx == 0)
|
||||
{
|
||||
x = std::stod(split[idx]);
|
||||
}
|
||||
else if (idx == 1)
|
||||
{
|
||||
y = std::stod(split[idx]);
|
||||
}
|
||||
else if (idx == 2)
|
||||
{
|
||||
z = std::stod(split[idx]);
|
||||
}
|
||||
}
|
||||
return { x, y, z };
|
||||
}
|
||||
|
||||
bool SvgShapeElement::hasTransform() const
|
||||
{
|
||||
return bool(getAttribute("transform"));
|
||||
}
|
||||
|
||||
void SvgShapeElement::setNoFill()
|
||||
{
|
||||
auto attr = std::make_unique<XmlAttribute>("fill");
|
||||
attr->setValue("none");
|
||||
addAttribute(std::move(attr));
|
||||
}
|
||||
|
||||
void SvgShapeElement::setNoStroke()
|
||||
{
|
||||
auto attr = std::make_unique<XmlAttribute>("stroke");
|
||||
attr->setValue("none");
|
||||
addAttribute(std::move(attr));
|
||||
}
|
||||
|
||||
void SvgShapeElement::setFill(const Color& fill)
|
||||
{
|
||||
auto attr = std::make_unique<XmlAttribute>("fill");
|
||||
|
||||
std::stringstream sstr;
|
||||
sstr << "rgb(" << fill.toString() << ")";
|
||||
attr->setValue(sstr.str());
|
||||
|
||||
addAttribute(std::move(attr));
|
||||
}
|
||||
|
||||
void SvgShapeElement::setStrokeWidth(double width)
|
||||
{
|
||||
auto attr = std::make_unique<XmlAttribute>("stroke-width");
|
||||
attr->setValue(std::to_string(width));
|
||||
|
||||
addAttribute(std::move(attr));
|
||||
}
|
||||
|
||||
void SvgShapeElement::setStrokeColor(const Color& stroke)
|
||||
{
|
||||
auto attr = std::make_unique<XmlAttribute>("stroke");
|
||||
|
||||
std::stringstream sstr;
|
||||
sstr << "rgb(" << stroke.toString() << ")";
|
||||
attr->setValue(sstr.str());
|
||||
|
||||
addAttribute(std::move(attr));
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "SvgElement.h"
|
||||
#include "Color.h"
|
||||
#include "Transform.h"
|
||||
|
||||
class SvgShapeElement : public SvgElement
|
||||
{
|
||||
public:
|
||||
SvgShapeElement(const std::string& tagName);
|
||||
|
||||
Transform getTransform() const;
|
||||
|
||||
bool hasTransform() const;
|
||||
|
||||
void setFill(const Color& fill);
|
||||
|
||||
void setNoFill();
|
||||
|
||||
void setStrokeWidth(double width);
|
||||
|
||||
void setStrokeColor(const Color& stroke);
|
||||
|
||||
void setNoStroke();
|
||||
|
||||
private:
|
||||
std::string getLabelledContent(const std::string& key, const std::string& content) const;
|
||||
Point parsePoint(const std::string& pointString, double defaultVal = 0.0) const;
|
||||
};
|
|
@ -1,20 +0,0 @@
|
|||
#include "SvgWriter.h"
|
||||
|
||||
#include "SvgDocument.h"
|
||||
#include "File.h"
|
||||
|
||||
std::string SvgWriter::toString(SvgDocument* document) const
|
||||
{
|
||||
std::string content = "";
|
||||
if (auto root = document->getRoot())
|
||||
{
|
||||
content += root->toString();
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
void SvgWriter::toFile(const Path& path, SvgDocument* document) const
|
||||
{
|
||||
File out_file(path);
|
||||
out_file.writeText(toString(document));
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
using Path = std::filesystem::path;
|
||||
|
||||
class SvgDocument;
|
||||
|
||||
class SvgWriter
|
||||
{
|
||||
public:
|
||||
std::string toString(SvgDocument* document) const;
|
||||
|
||||
void toFile(const Path& path, SvgDocument* document) const;
|
||||
};
|
|
@ -1,187 +0,0 @@
|
|||
#include "SvgShapeElements.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
SvgCircle::SvgCircle(Type type)
|
||||
: SvgShapeElement(type == Type::REGULAR ? "circle" : "ellipse"),
|
||||
mType(type)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Point SvgCircle::getLocation() const
|
||||
{
|
||||
double cx = 0.0;
|
||||
double cy = 0.0;
|
||||
if (auto attr = getAttribute("cx"); attr)
|
||||
{
|
||||
cx = std::stod(attr->getValue());
|
||||
}
|
||||
if (auto attr = getAttribute("cy"); attr)
|
||||
{
|
||||
cy = std::stod(attr->getValue());
|
||||
}
|
||||
return { cx, cy };
|
||||
}
|
||||
|
||||
double SvgCircle::getRadius() const
|
||||
{
|
||||
double radius = 1.0;
|
||||
if (auto attr = getAttribute("rx"); attr)
|
||||
{
|
||||
radius = std::stod(attr->getValue());
|
||||
}
|
||||
else if (auto attr = getAttribute("r"); attr)
|
||||
{
|
||||
radius = std::stod(attr->getValue());
|
||||
}
|
||||
return radius;
|
||||
}
|
||||
|
||||
SvgCircle::Type SvgCircle::getType() const
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
double SvgCircle::getMinorRadius() const
|
||||
{
|
||||
double radius = 0.0;
|
||||
if (auto attr = getAttribute("ry"); attr)
|
||||
{
|
||||
radius = std::stod(attr->getValue());
|
||||
}
|
||||
return radius;
|
||||
}
|
||||
|
||||
void SvgCircle::setLocation(const Point& loc)
|
||||
{
|
||||
auto cx = std::make_unique<XmlAttribute>("cx");
|
||||
auto cy = std::make_unique<XmlAttribute>("cy");
|
||||
|
||||
cx->setValue(std::to_string(loc.getX()));
|
||||
cy->setValue(std::to_string(loc.getY()));
|
||||
|
||||
addAttribute(std::move(cx));
|
||||
addAttribute(std::move(cy));
|
||||
}
|
||||
|
||||
void SvgCircle::setRadius(double rad)
|
||||
{
|
||||
if (mType == Type::REGULAR)
|
||||
{
|
||||
auto r = std::make_unique<XmlAttribute>("r");
|
||||
r->setValue(std::to_string(rad));
|
||||
addAttribute(std::move(r));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto r = std::make_unique<XmlAttribute>("rx");
|
||||
r->setValue(std::to_string(rad));
|
||||
addAttribute(std::move(r));
|
||||
}
|
||||
}
|
||||
|
||||
void SvgCircle::setMinorRadius(double rad)
|
||||
{
|
||||
auto r = std::make_unique<XmlAttribute>("ry");
|
||||
r->setValue(std::to_string(rad));
|
||||
addAttribute(std::move(r));
|
||||
}
|
||||
|
||||
SvgRectangle::SvgRectangle()
|
||||
: SvgShapeElement("rect")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SvgRectangle::setLocation(const Point& loc)
|
||||
{
|
||||
auto x = std::make_unique<XmlAttribute>("x");
|
||||
auto y = std::make_unique<XmlAttribute>("y");
|
||||
|
||||
x->setValue(std::to_string(loc.getX()));
|
||||
y->setValue(std::to_string(loc.getY()));
|
||||
|
||||
addAttribute(std::move(x));
|
||||
addAttribute(std::move(y));
|
||||
}
|
||||
|
||||
void SvgRectangle::setWidth(double w)
|
||||
{
|
||||
auto width = std::make_unique<XmlAttribute>("width");
|
||||
|
||||
width->setValue(std::to_string(w));
|
||||
|
||||
addAttribute(std::move(width));
|
||||
}
|
||||
|
||||
void SvgRectangle::setHeight(double h)
|
||||
{
|
||||
auto height = std::make_unique<XmlAttribute>("height");
|
||||
|
||||
height->setValue(std::to_string(h));
|
||||
|
||||
addAttribute(std::move(height));
|
||||
}
|
||||
|
||||
|
||||
SvgPolygon::SvgPolygon()
|
||||
: SvgShapeElement("polygon")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SvgPolygon::setPoints(const std::vector<Point>& locs)
|
||||
{
|
||||
auto points = std::make_unique<XmlAttribute>("points");
|
||||
|
||||
std::stringstream sstr;
|
||||
for (const auto& loc : locs)
|
||||
{
|
||||
sstr << loc.getX() << "," << loc.getY() << " ";
|
||||
}
|
||||
points->setValue(sstr.str());
|
||||
addAttribute(std::move(points));
|
||||
}
|
||||
|
||||
SvgPolyline::SvgPolyline()
|
||||
: SvgShapeElement("polyline")
|
||||
{
|
||||
auto fill = std::make_unique<XmlAttribute>("fill");
|
||||
fill->setValue("none");
|
||||
addAttribute(std::move(fill));
|
||||
}
|
||||
|
||||
void SvgPolyline::setPoints(const std::vector<Point>& locs)
|
||||
{
|
||||
auto points = std::make_unique<XmlAttribute>("points");
|
||||
|
||||
std::stringstream sstr;
|
||||
for (const auto& loc : locs)
|
||||
{
|
||||
sstr << loc.getX() << "," << loc.getY() << " ";
|
||||
}
|
||||
points->setValue(sstr.str());
|
||||
addAttribute(std::move(points));
|
||||
}
|
||||
|
||||
|
||||
SvgPath::SvgPath()
|
||||
: SvgShapeElement("path")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SvgPath::setPath(const std::string& mPath)
|
||||
{
|
||||
auto path = std::make_unique<XmlAttribute>("d");
|
||||
path->setValue(mPath);
|
||||
addAttribute(std::move(path));
|
||||
}
|
||||
|
||||
void SvgPath::setFillRule(const std::string& fillRule)
|
||||
{
|
||||
auto rule = std::make_unique<XmlAttribute>("fill-rule");
|
||||
rule->setValue(fillRule);
|
||||
addAttribute(std::move(rule));
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "SvgShapeElement.h"
|
||||
#include "Point.h"
|
||||
|
||||
#include "XmlAttribute.h"
|
||||
|
||||
class SvgCircle : public SvgShapeElement
|
||||
{
|
||||
public:
|
||||
enum class Type
|
||||
{
|
||||
REGULAR,
|
||||
ELLIPSE
|
||||
};
|
||||
|
||||
SvgCircle(Type type = Type::REGULAR);
|
||||
|
||||
Point getLocation() const;
|
||||
|
||||
double getRadius() const;
|
||||
|
||||
Type getType() const;
|
||||
|
||||
double getMinorRadius() const;
|
||||
|
||||
void setLocation(const Point& loc);
|
||||
|
||||
void setRadius(double rad);
|
||||
|
||||
void setMinorRadius(double rad);
|
||||
private:
|
||||
Type mType{ Type::REGULAR };
|
||||
};
|
||||
|
||||
class SvgRectangle : public SvgShapeElement
|
||||
{
|
||||
public:
|
||||
SvgRectangle();
|
||||
|
||||
void setLocation(const Point& loc);
|
||||
|
||||
void setWidth(double width);
|
||||
|
||||
void setHeight(double height);
|
||||
};
|
||||
|
||||
class SvgPolygon : public SvgShapeElement
|
||||
{
|
||||
public:
|
||||
SvgPolygon();
|
||||
|
||||
void setPoints(const std::vector<Point>& loc);
|
||||
};
|
||||
|
||||
class SvgPolyline : public SvgShapeElement
|
||||
{
|
||||
public:
|
||||
SvgPolyline();
|
||||
|
||||
void setPoints(const std::vector<Point>& loc);
|
||||
};
|
||||
|
||||
class SvgPath : public SvgShapeElement
|
||||
{
|
||||
public:
|
||||
SvgPath();
|
||||
|
||||
void setPath(const std::string& mPath);
|
||||
void setFillRule(const std::string& fillRule);
|
||||
};
|
|
@ -1,43 +0,0 @@
|
|||
#include "XmlDocument.h"
|
||||
|
||||
#include "XmlProlog.h"
|
||||
#include "XmlElement.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
XmlDocument::XmlDocument()
|
||||
:mProlog(XmlProlog::Create("xml"))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
XmlDocument::~XmlDocument()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
XmlDocumentPtr XmlDocument::Create()
|
||||
{
|
||||
return std::make_unique<XmlDocument>();
|
||||
}
|
||||
|
||||
void XmlDocument::setProlog(XmlPrologPtr prolog)
|
||||
{
|
||||
mProlog = std::move(prolog);
|
||||
}
|
||||
|
||||
XmlProlog* XmlDocument::getProlog() const
|
||||
{
|
||||
return mProlog.get();
|
||||
}
|
||||
|
||||
void XmlDocument::setRoot(XmlElementPtr root)
|
||||
{
|
||||
mRoot = std::move(root);
|
||||
}
|
||||
|
||||
XmlElement* XmlDocument::getRoot() const
|
||||
{
|
||||
return mRoot.get();
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
#pragma once
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "XmlElement.h"
|
||||
#include "XmlProlog.h"
|
||||
|
||||
class XmlElement;
|
||||
class XmlProlog;
|
||||
using XmlPrologPtr = std::unique_ptr<XmlProlog>;
|
||||
using XmlElementPtr = std::unique_ptr<XmlElement>;
|
||||
|
||||
class XmlDocument
|
||||
{
|
||||
public:
|
||||
XmlDocument();
|
||||
virtual ~XmlDocument();
|
||||
|
||||
static std::unique_ptr<XmlDocument> Create();
|
||||
|
||||
XmlProlog* getProlog() const;
|
||||
XmlElement* getRoot() const;
|
||||
|
||||
void setProlog(XmlPrologPtr prolog);
|
||||
void setRoot(XmlElementPtr root);
|
||||
private:
|
||||
XmlPrologPtr mProlog;
|
||||
XmlElementPtr mRoot;
|
||||
};
|
||||
|
||||
using XmlDocumentPtr = std::unique_ptr<XmlDocument>;
|
|
@ -1,409 +0,0 @@
|
|||
#include "XmlParser.h"
|
||||
|
||||
#include "StringUtils.h"
|
||||
|
||||
#include "XmlDocument.h"
|
||||
#include "XmlElement.h"
|
||||
#include "XmlAttribute.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),
|
||||
mWorkingElements()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void XmlParser::processLine(const std::string& input)
|
||||
{
|
||||
for (std::size_t idx=0; 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:
|
||||
case LS::Await_Tag_Inline_Close:
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
else if(mLineState == LS::Await_Attribute_Name)
|
||||
{
|
||||
mLineState = LS::Await_Tag_Inline_Close;
|
||||
}
|
||||
else
|
||||
{
|
||||
onNonAlphaNumeric(StringUtils::FORWARD_SLASH);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
else if (mLineState == LS::Await_Tag_Inline_Close)
|
||||
{
|
||||
if (!mWorkingElements.empty())
|
||||
{
|
||||
mWorkingElements.pop();
|
||||
}
|
||||
}
|
||||
onElementTagEnd();
|
||||
}
|
||||
else if(mDocumentState == DS::Close_Element)
|
||||
{
|
||||
mDocumentState = DS::Await_Element;
|
||||
mLineState = LS::Await_Tag_Open;
|
||||
if (!mWorkingElements.empty())
|
||||
{
|
||||
mWorkingElements.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void XmlParser::onTextStart(char c)
|
||||
{
|
||||
mWorkingText = c;
|
||||
mLineState = LS::Await_Text_End;
|
||||
}
|
||||
|
||||
void XmlParser::onTextEnd()
|
||||
{
|
||||
mWorkingElements.top()->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)
|
||||
{
|
||||
mDocument->getProlog()->setTagName(mWorkingTagName);
|
||||
mLineState = LS::Await_Attribute_Name;
|
||||
}
|
||||
else if(mDocumentState == DS::Build_Element)
|
||||
{
|
||||
auto new_element = XmlElement::Create(mWorkingTagName);
|
||||
auto working_element = new_element.get();
|
||||
|
||||
if (!mDocument->getRoot())
|
||||
{
|
||||
mDocument->setRoot(std::move(new_element));
|
||||
}
|
||||
else
|
||||
{
|
||||
mWorkingElements.top()->addChild(std::move(new_element));
|
||||
}
|
||||
mWorkingElements.push(working_element);
|
||||
mLineState = LS::Await_Attribute_Name;
|
||||
}
|
||||
}
|
||||
|
||||
void XmlParser::onAttributeNameStart(char c)
|
||||
{
|
||||
mWorkingAttributeName = c;
|
||||
mLineState = LS::Await_Attribute_Name_End;
|
||||
}
|
||||
|
||||
void XmlParser::onAttributeNameEnd()
|
||||
{
|
||||
auto attribute = XmlAttribute::Create(mWorkingAttributeName);
|
||||
if(mDocumentState == DS::Build_Prolog)
|
||||
{
|
||||
mDocument->getProlog()->addAttribute(std::move(attribute));
|
||||
}
|
||||
else if(mDocumentState == DS::Build_Element)
|
||||
{
|
||||
mWorkingElements.top()->addAttribute(std::move(attribute));
|
||||
}
|
||||
mLineState = LS::Await_Attribute_Value;
|
||||
}
|
||||
|
||||
void XmlParser::onAttributeValueStart()
|
||||
{
|
||||
mWorkingAttributeValue = "";
|
||||
mLineState = LS::Await_Attribute_Value_End;
|
||||
}
|
||||
|
||||
void XmlParser::onAttributeValueEnd()
|
||||
{
|
||||
if(mDocumentState == DS::Build_Prolog)
|
||||
{
|
||||
mDocument->getProlog()->getAttribute(mWorkingAttributeName)->setValue(mWorkingAttributeValue);
|
||||
}
|
||||
else if(mDocumentState == DS::Build_Element)
|
||||
{
|
||||
mWorkingElements.top()->getAttribute(mWorkingAttributeName)->setValue(mWorkingAttributeValue);
|
||||
}
|
||||
mLineState = LS::Await_Attribute_Name;
|
||||
}
|
||||
|
||||
void XmlParser::onStartProlog()
|
||||
{
|
||||
mDocumentState = DS::Build_Prolog;
|
||||
mLineState = LS::Await_Tag_Name_End;
|
||||
}
|
||||
|
||||
void XmlParser::onFinishProlog()
|
||||
{
|
||||
mDocument->getProlog()->update();
|
||||
mDocumentState = DS::Await_Element;
|
||||
mLineState = LS::Await_Tag_Open;
|
||||
}
|
||||
|
||||
XmlDocumentPtr XmlParser::getDocument()
|
||||
{
|
||||
return std::move(mDocument);
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <stack>
|
||||
#include <memory>
|
||||
|
||||
class XmlDocument;
|
||||
using XmlDocumentPtr = std::unique_ptr<XmlDocument>;
|
||||
|
||||
class XmlElement;
|
||||
|
||||
class XmlParser
|
||||
{
|
||||
public:
|
||||
enum class DocumentState
|
||||
{
|
||||
Await_Prolog,
|
||||
Build_Prolog,
|
||||
Await_Element,
|
||||
Build_Element,
|
||||
Close_Element
|
||||
};
|
||||
|
||||
enum class LineState
|
||||
{
|
||||
Await_Tag_Open,
|
||||
Await_Tag_Follower,
|
||||
Await_Tag_Name,
|
||||
Await_Tag_Name_End,
|
||||
Await_Tag_Inline_Close,
|
||||
Await_Attribute_Name,
|
||||
Await_Attribute_Name_End,
|
||||
Await_Attribute_Value,
|
||||
Await_Attribute_Value_End,
|
||||
Await_Text_End
|
||||
};
|
||||
|
||||
public:
|
||||
XmlParser();
|
||||
|
||||
void processLine(const std::string& input);
|
||||
|
||||
XmlDocumentPtr getDocument();
|
||||
|
||||
private:
|
||||
void onLeftBracket();
|
||||
|
||||
void onRightBracket();
|
||||
|
||||
void onQuestionMark();
|
||||
|
||||
void onForwardSlash();
|
||||
|
||||
void onChar(char c);
|
||||
|
||||
void onSpace(char c);
|
||||
|
||||
void onAlphaNumeric(char c);
|
||||
|
||||
void onNonAlphaNumeric(char c);
|
||||
|
||||
void onEquals();
|
||||
|
||||
void onDoubleQuote();
|
||||
|
||||
void onTagOpen();
|
||||
|
||||
void onTagNameStart(char c);
|
||||
|
||||
void onTagNameEnd();
|
||||
|
||||
void onTagClose();
|
||||
|
||||
void onTextStart(char c);
|
||||
|
||||
void onTextEnd();
|
||||
|
||||
void onAttributeNameStart(char c);
|
||||
|
||||
void onAttributeNameEnd();
|
||||
|
||||
void onAttributeValueStart();
|
||||
|
||||
void onAttributeValueEnd();
|
||||
|
||||
void onStartProlog();
|
||||
|
||||
void onFinishProlog();
|
||||
|
||||
void onElementTagEnd();
|
||||
|
||||
private:
|
||||
DocumentState mDocumentState;
|
||||
LineState mLineState;
|
||||
XmlDocumentPtr mDocument;
|
||||
std::stack<XmlElement*> mWorkingElements;
|
||||
|
||||
std::string mWorkingAttributeName;
|
||||
std::string mWorkingTagName;
|
||||
std::string mWorkingAttributeValue;
|
||||
std::string mWorkingText;
|
||||
};
|
|
@ -1,24 +0,0 @@
|
|||
#include "XmlWriter.h"
|
||||
|
||||
#include "XmlDocument.h"
|
||||
#include "XmlAttribute.h"
|
||||
|
||||
std::string XmlWriter::toString(XmlDocument* document)
|
||||
{
|
||||
std::string content;
|
||||
if (auto prolog = document->getProlog())
|
||||
{
|
||||
content += "<?xml";
|
||||
for (const auto& [key, attribute] : prolog->getAttributes())
|
||||
{
|
||||
content += " " + attribute->getName() + "=\"" + attribute->getValue() + "\"";
|
||||
}
|
||||
content += "?>\n";
|
||||
}
|
||||
|
||||
if (auto root = document->getRoot())
|
||||
{
|
||||
content += root->toString();
|
||||
}
|
||||
return content;
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class XmlDocument;
|
||||
class XmlElement;
|
||||
|
||||
class XmlWriter
|
||||
{
|
||||
public:
|
||||
XmlWriter() = default;
|
||||
|
||||
std::string toString(XmlDocument* document);
|
||||
};
|
|
@ -1,28 +0,0 @@
|
|||
#include "XmlAttribute.h"
|
||||
|
||||
XmlAttribute::XmlAttribute(const std::string& name)
|
||||
: mName(name),
|
||||
mValue()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
XmlAttributePtr XmlAttribute::Create(const std::string& name)
|
||||
{
|
||||
return std::make_unique<XmlAttribute>(name);
|
||||
}
|
||||
|
||||
const std::string& XmlAttribute::getName() const
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
const std::string& XmlAttribute::getValue() const
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
void XmlAttribute::setValue(const std::string& value)
|
||||
{
|
||||
mValue = value;
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
class XmlAttribute
|
||||
{
|
||||
public:
|
||||
XmlAttribute(const std::string& name);
|
||||
|
||||
static std::unique_ptr<XmlAttribute> Create(const std::string& name);
|
||||
|
||||
const std::string& getName() const;
|
||||
|
||||
const std::string& getValue() const;
|
||||
|
||||
void setValue(const std::string& value);
|
||||
private:
|
||||
std::string mName;
|
||||
std::string mValue;
|
||||
};
|
||||
|
||||
using XmlAttributePtr = std::unique_ptr<XmlAttribute>;
|
|
@ -1,140 +0,0 @@
|
|||
#include "XmlElement.h"
|
||||
|
||||
#include "XmlAttribute.h"
|
||||
|
||||
XmlElement::XmlElement(const std::string& tagName)
|
||||
: mTagName(tagName),
|
||||
mChildren()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
XmlElement::~XmlElement()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
XmlElementPtr XmlElement::Create(const std::string& tagName)
|
||||
{
|
||||
return std::make_unique<XmlElement>(tagName);
|
||||
}
|
||||
|
||||
void XmlElement::setTagName(const std::string& tagName)
|
||||
{
|
||||
mTagName = tagName;
|
||||
}
|
||||
|
||||
void XmlElement::addChild(XmlElementPtr child)
|
||||
{
|
||||
mChildren.push_back(std::move(child));
|
||||
}
|
||||
|
||||
void XmlElement::addAttribute(XmlAttributePtr attribute)
|
||||
{
|
||||
mAttributes[attribute->getName()] = std::move(attribute);
|
||||
}
|
||||
|
||||
void XmlElement::addAttribute(const std::string& name, const std::string& value)
|
||||
{
|
||||
auto attr = std::make_unique<XmlAttribute>(name);
|
||||
attr->setValue(value);
|
||||
addAttribute(std::move(attr));
|
||||
}
|
||||
|
||||
const std::string& XmlElement::getTagName() const
|
||||
{
|
||||
return mTagName;
|
||||
}
|
||||
|
||||
const std::string& XmlElement::getText() const
|
||||
{
|
||||
return mText;
|
||||
}
|
||||
|
||||
void XmlElement::setText(const std::string& text)
|
||||
{
|
||||
mText = text;
|
||||
}
|
||||
|
||||
XmlElement* XmlElement::getFirstChildWithTagName(const std::string& tag)
|
||||
{
|
||||
for(auto& child : mChildren)
|
||||
{
|
||||
if (child->getTagName() == tag)
|
||||
{
|
||||
return child.get();
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool XmlElement::hasAttribute(const std::string& attribute) const
|
||||
{
|
||||
return (bool)(getAttribute(attribute));
|
||||
}
|
||||
|
||||
XmlAttribute* XmlElement::getAttribute(const std::string& attributeName) const
|
||||
{
|
||||
if (auto iter = mAttributes.find(attributeName); iter != mAttributes.end())
|
||||
{
|
||||
return iter->second.get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::unordered_map<std::string, XmlAttributePtr>& XmlElement::getAttributes() const
|
||||
{
|
||||
return mAttributes;
|
||||
}
|
||||
|
||||
const std::vector<std::unique_ptr<XmlElement> >& XmlElement::getChildren() const
|
||||
{
|
||||
return mChildren;
|
||||
}
|
||||
|
||||
std::string XmlElement::toString(unsigned depth, bool keepInline) const
|
||||
{
|
||||
const auto prefix = std::string(2*depth, ' ');
|
||||
|
||||
std::string line_ending = keepInline ? "" : "\n";
|
||||
|
||||
auto content = prefix + "<" + getTagName();
|
||||
for (const auto& [key, attribute] : getAttributes())
|
||||
{
|
||||
content += " " + attribute->getName() + "=\"" + attribute->getValue() + "\"";
|
||||
}
|
||||
|
||||
const auto num_children = mChildren.size();
|
||||
if (num_children == 0 && getText().empty())
|
||||
{
|
||||
content += "/>" + line_ending;
|
||||
return content;
|
||||
}
|
||||
else
|
||||
{
|
||||
content += ">";
|
||||
}
|
||||
|
||||
if (!getText().empty())
|
||||
{
|
||||
content += getText();
|
||||
}
|
||||
|
||||
if (num_children>0)
|
||||
{
|
||||
content += line_ending;
|
||||
}
|
||||
|
||||
for(const auto& child : mChildren)
|
||||
{
|
||||
content += child->toString(depth+1, keepInline);
|
||||
}
|
||||
if (num_children>0)
|
||||
{
|
||||
content += prefix;
|
||||
}
|
||||
|
||||
content += "</" + getTagName() + ">" + line_ending;
|
||||
return content;
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
class XmlAttribute;
|
||||
using XmlAttributePtr = std::unique_ptr<XmlAttribute>;
|
||||
|
||||
class XmlElement
|
||||
{
|
||||
public:
|
||||
XmlElement(const std::string& tagName);
|
||||
virtual ~XmlElement();
|
||||
|
||||
static std::unique_ptr<XmlElement> Create(const std::string& tagName);
|
||||
|
||||
void addAttribute(XmlAttributePtr attribute);
|
||||
void addAttribute(const std::string& name, const std::string& value);
|
||||
void addChild(std::unique_ptr<XmlElement> child);
|
||||
|
||||
const std::string& getTagName() const;
|
||||
const std::string& getText() const;
|
||||
|
||||
bool hasAttribute(const std::string& attribute) const;
|
||||
XmlAttribute* getAttribute(const std::string& attribute) const;
|
||||
const std::unordered_map<std::string, XmlAttributePtr>& getAttributes() const;
|
||||
|
||||
const std::vector<std::unique_ptr<XmlElement> >& getChildren() const;
|
||||
|
||||
XmlElement* getFirstChildWithTagName(const std::string& tag);
|
||||
|
||||
void setText(const std::string& text);
|
||||
void setTagName(const std::string& tagName);
|
||||
|
||||
virtual std::string toString(unsigned depth = 0, bool keepInline = false) const;
|
||||
|
||||
protected:
|
||||
std::string mTagName;
|
||||
std::string mText;
|
||||
|
||||
std::unordered_map<std::string, XmlAttributePtr> mAttributes;
|
||||
std::vector<std::unique_ptr<XmlElement> > mChildren;
|
||||
};
|
||||
|
||||
using XmlElementPtr = std::unique_ptr<XmlElement>;
|
|
@ -1,55 +0,0 @@
|
|||
#include "XmlProlog.h"
|
||||
|
||||
#include "XmlAttribute.h"
|
||||
|
||||
XmlProlog::XmlProlog(const std::string& tagName)
|
||||
: XmlElement(tagName),
|
||||
mVersion(XmlProlog::Version::V1_0),
|
||||
mEncoding(XmlProlog::Encoding::UTF8)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
XmlPrologPtr XmlProlog::Create(const std::string& tagName)
|
||||
{
|
||||
return std::make_unique<XmlProlog>(tagName);
|
||||
}
|
||||
|
||||
XmlProlog::Encoding XmlProlog::getEncoding() const
|
||||
{
|
||||
return mEncoding;
|
||||
}
|
||||
|
||||
XmlProlog::Version XmlProlog::getVersion() const
|
||||
{
|
||||
return mVersion;
|
||||
}
|
||||
|
||||
void XmlProlog::setEncoding(const std::string& encoding)
|
||||
{
|
||||
if(encoding == "UTF-8")
|
||||
{
|
||||
mEncoding = XmlProlog::Encoding::UTF8;
|
||||
}
|
||||
}
|
||||
|
||||
void XmlProlog::setVersion(const std::string& version)
|
||||
{
|
||||
if(version == "1.0")
|
||||
{
|
||||
mVersion = XmlProlog::Version::V1_0;
|
||||
}
|
||||
}
|
||||
|
||||
void XmlProlog::update()
|
||||
{
|
||||
if(const auto version = getAttribute("version"))
|
||||
{
|
||||
setVersion(version->getValue());
|
||||
}
|
||||
|
||||
if(const auto encoding = getAttribute("encoding"))
|
||||
{
|
||||
setEncoding(encoding->getValue());
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "XmlElement.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
class XmlProlog : public XmlElement
|
||||
{
|
||||
public:
|
||||
enum class Version{
|
||||
V1_0
|
||||
};
|
||||
|
||||
enum class Encoding{
|
||||
UTF8
|
||||
};
|
||||
|
||||
public:
|
||||
XmlProlog(const std::string& tagName);
|
||||
|
||||
static std::unique_ptr<XmlProlog> Create(const std::string& tagName);
|
||||
|
||||
Encoding getEncoding() const;
|
||||
Version getVersion() const;
|
||||
|
||||
void setEncoding(const std::string& encoding);
|
||||
void setVersion(const std::string& version);
|
||||
void update();
|
||||
|
||||
private:
|
||||
Version mVersion;
|
||||
Encoding mEncoding;
|
||||
};
|
||||
|
||||
using XmlPrologPtr = std::unique_ptr<XmlProlog>;
|
Loading…
Add table
Add a link
Reference in a new issue