From 0cf833840b19e603f480dead5ca211f947503f9b Mon Sep 17 00:00:00 2001 From: Thomas Schmucker Date: Sun, 9 Mar 2025 22:26:25 +0100 Subject: Initial commit --- src/xml.cpp | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/xml_test.cpp | 58 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 src/xml.cpp create mode 100644 src/xml_test.cpp (limited to 'src') diff --git a/src/xml.cpp b/src/xml.cpp new file mode 100644 index 0000000..44b423a --- /dev/null +++ b/src/xml.cpp @@ -0,0 +1,75 @@ +// Standard C++ +#include +#include + +// Projekt +#include "xml.hpp" + +// Expat XML Parser +#define XML_STATIC // force static linkage +#include "expat.h" + +using namespace std; + +void +XML::parse(istream& in) +{ + unique_ptr parser(XML_ParserCreate(nullptr), XML_ParserFree); + + // setup expat + XML_SetUserData(parser.get(), this); + XML_SetElementHandler(parser.get(), tag_start, tag_end); + XML_SetCdataSectionHandler(parser.get(), cdata_start, cdata_end); + XML_SetCharacterDataHandler(parser.get(), data); + + char buffer[2048]; + for ( bool done = false; !done ; ) { + in.read(buffer, sizeof buffer); + done = (in.gcount() < sizeof buffer); + + if ( XML_Parse(parser.get(), buffer, static_cast(in.gcount()), done) != XML_STATUS_OK ) { + stringstream msg; + + msg << XML_ErrorString(XML_GetErrorCode(parser.get())); + msg << " in line " << XML_GetCurrentLineNumber(parser.get()); + + throw runtime_error( msg.str() ); + } + } +} + +void +XML::tag_start(void* me, const char* name, const char* attr[]) +{ + vector> attr_temp; + + for ( size_t i = 0; attr[i]; i += 2 ) + attr_temp.push_back( make_pair(attr[i], attr[i+1]) ); + + reinterpret_cast(me)->handle_start(name, attr_temp); +} + +void +XML::tag_end(void* me, const char* name) +{ + reinterpret_cast(me)->handle_end(name); +} + +void +XML::cdata_start(void* me) +{ + reinterpret_cast(me)->handle_cdata_start(); +} + +void +XML::cdata_end(void* me) +{ + reinterpret_cast(me)->handle_cdata_end(); +} + +void +XML::data(void* me, const char* dat, int len) +{ + reinterpret_cast(me)->handle_data(vector(dat, dat+len)); +} + diff --git a/src/xml_test.cpp b/src/xml_test.cpp new file mode 100644 index 0000000..0af5b51 --- /dev/null +++ b/src/xml_test.cpp @@ -0,0 +1,58 @@ +#include +#include +using namespace std; + +#include "xml.hpp" + +class MyXML : public XML { + public: + explicit MyXML(ostream& out, size_t indent = 4) + : pout_(&out) + , depth_(0) + , indent_(indent) + { + } + + protected: + void handle_start(const string& name, const vector>& attr) + { + *pout_ << string(depth_++ * indent_, ' ') + << "<" << name; + + auto it = cbegin(attr); + auto end = cend(attr); + if ( it != end ) { + *pout_ << " " << it->first << "=\"" << it->second << "\""; + + ++it; // skip first Element + for ( ; it != end; ++it ) + *pout_ << ", " << it->first << "=\"" << it->second << "\""; + } + + *pout_ << ">" << endl; + } + + void handle_end(const string& name) + { + *pout_ << string(--depth_ * indent_, ' ') + << "" + << endl; + } + + private: + ostream* pout_; + size_t depth_; + size_t indent_; +}; + +int +main() +{ + try { + MyXML myxml(cout); + myxml.parse(cin); + } + catch ( exception& e ) { + cerr << "Fehler: " << e.what() << endl; + } +} -- cgit v1.3