summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Schmucker <ts@its1.de>2026-07-15 21:05:19 +0200
committerThomas Schmucker <ts@its1.de>2026-07-15 21:05:19 +0200
commit4f3760fc3b647fa166da4ab777eb612b14ac500b (patch)
tree2f9faece24cac31f8dcb842572cdd9a486402637 /src
parent0cf833840b19e603f480dead5ca211f947503f9b (diff)
downloadexpat++-4f3760fc3b647fa166da4ab777eb612b14ac500b.tar.gz
expat++-4f3760fc3b647fa166da4ab777eb612b14ac500b.tar.bz2
expat++-4f3760fc3b647fa166da4ab777eb612b14ac500b.zip
Umbau auf modernes C++
Diffstat (limited to 'src')
-rw-r--r--src/xml.cpp50
-rw-r--r--src/xml_test.cpp92
2 files changed, 88 insertions, 54 deletions
diff --git a/src/xml.cpp b/src/xml.cpp
index 44b423a..451ee18 100644
--- a/src/xml.cpp
+++ b/src/xml.cpp
@@ -1,18 +1,19 @@
1// Standard C++ 1// Standard C++
2#include <array>
2#include <memory> 3#include <memory>
3#include <sstream> 4#include <sstream>
5#include <span>
4 6
5// Projekt 7// Project
6#include "xml.hpp" 8#include "xml.hpp"
7 9
8// Expat XML Parser 10// Expat XML Parser
9#define XML_STATIC // force static linkage
10#include "expat.h" 11#include "expat.h"
11 12
12using namespace std; 13using namespace std;
13 14
14void 15void
15XML::parse(istream& in) 16XML::parse(istream& ins)
16{ 17{
17 unique_ptr<XML_ParserStruct, decltype(&XML_ParserFree)> parser(XML_ParserCreate(nullptr), XML_ParserFree); 18 unique_ptr<XML_ParserStruct, decltype(&XML_ParserFree)> parser(XML_ParserCreate(nullptr), XML_ParserFree);
18 19
@@ -22,54 +23,57 @@ XML::parse(istream& in)
22 XML_SetCdataSectionHandler(parser.get(), cdata_start, cdata_end); 23 XML_SetCdataSectionHandler(parser.get(), cdata_start, cdata_end);
23 XML_SetCharacterDataHandler(parser.get(), data); 24 XML_SetCharacterDataHandler(parser.get(), data);
24 25
25 char buffer[2048]; 26 static const auto buffer_size = 2048;
26 for ( bool done = false; !done ; ) {
27 in.read(buffer, sizeof buffer);
28 done = (in.gcount() < sizeof buffer);
29 27
30 if ( XML_Parse(parser.get(), buffer, static_cast<int>(in.gcount()), done) != XML_STATUS_OK ) { 28 array<char, buffer_size> buffer{};
29
30 for ( bool done = false; !done; ) {
31 ins.read(buffer.data(), buffer_size);
32 done = ins.gcount() < buffer_size;
33
34 if ( XML_Parse(parser.get(), buffer.data(), static_cast<int>(ins.gcount()), static_cast<int>(done)) != XML_STATUS_OK ) {
31 stringstream msg; 35 stringstream msg;
32 36
33 msg << XML_ErrorString(XML_GetErrorCode(parser.get())); 37 msg << XML_ErrorString(XML_GetErrorCode(parser.get()));
34 msg << " in line " << XML_GetCurrentLineNumber(parser.get()); 38 msg << " in line " << XML_GetCurrentLineNumber(parser.get());
35 39
36 throw runtime_error( msg.str() ); 40 throw runtime_error(msg.str());
37 } 41 }
38 } 42 }
39} 43}
40 44
41void 45void
42XML::tag_start(void* me, const char* name, const char* attr[]) 46XML::tag_start(void* self, const char* name, const char** attr)
43{ 47{
44 vector<pair<string, string>> attr_temp; 48 vector<tuple<string_view, string_view>> attr_temp;
45 49
46 for ( size_t i = 0; attr[i]; i += 2 ) 50 for ( auto i = 0; attr[i] != nullptr; i += 2 ) {
47 attr_temp.push_back( make_pair<string, string>(attr[i], attr[i+1]) ); 51 attr_temp.emplace_back(attr[i], attr[i + 1]);
52 }
48 53
49 reinterpret_cast<XML*>(me)->handle_start(name, attr_temp); 54 static_cast<XML*>(self)->handle_start(name, attr_temp);
50} 55}
51 56
52void 57void
53XML::tag_end(void* me, const char* name) 58XML::tag_end(void* self, const char* name)
54{ 59{
55 reinterpret_cast<XML*>(me)->handle_end(name); 60 static_cast<XML*>(self)->handle_end(name);
56} 61}
57 62
58void 63void
59XML::cdata_start(void* me) 64XML::cdata_start(void* self)
60{ 65{
61 reinterpret_cast<XML*>(me)->handle_cdata_start(); 66 static_cast<XML*>(self)->handle_cdata_start();
62} 67}
63 68
64void 69void
65XML::cdata_end(void* me) 70XML::cdata_end(void* self)
66{ 71{
67 reinterpret_cast<XML*>(me)->handle_cdata_end(); 72 static_cast<XML*>(self)->handle_cdata_end();
68} 73}
69 74
70void 75void
71XML::data(void* me, const char* dat, int len) 76XML::data(void* self, const char* dat, int len)
72{ 77{
73 reinterpret_cast<XML*>(me)->handle_data(vector<char>(dat, dat+len)); 78 static_cast<XML*>(self)->handle_character_data({ dat, dat + len });
74} 79}
75
diff --git a/src/xml_test.cpp b/src/xml_test.cpp
index 0af5b51..0b978a9 100644
--- a/src/xml_test.cpp
+++ b/src/xml_test.cpp
@@ -1,48 +1,78 @@
1#include <iostream> 1#include <iostream>
2#include <string> 2#include <string>
3#include <tuple>
3using namespace std; 4using namespace std;
4 5
5#include "xml.hpp" 6#include "xml.hpp"
6 7
7class MyXML : public XML { 8class MyXML : public XML {
8 public: 9public:
9 explicit MyXML(ostream& out, size_t indent = 4) 10 explicit MyXML(ostream& out, size_t indent = 4)
10 : pout_(&out) 11 : pout_(&out)
11 , depth_(0) 12 , indent_(indent)
12 , indent_(indent) 13 {
13 { 14 }
14 }
15 15
16 protected: 16protected:
17 void handle_start(const string& name, const vector<pair<string, string>>& attr) 17 void handle_start(string_view name, const vector<tuple<string_view, string_view>>& attr) override
18 { 18 {
19 *pout_ << string(depth_++ * indent_, ' ') 19 *pout_ << string(depth_++ * indent_, ' ')
20 << "<" << name; 20 << "<" << name;
21 21
22 auto it = cbegin(attr); 22 auto start = cbegin(attr);
23 auto end = cend(attr); 23 auto end = cend(attr);
24 if ( it != end ) { 24 if ( start != end ) {
25 *pout_ << " " << it->first << "=\"" << it->second << "\""; 25 *pout_ << " " << get<0>(*start) << "=\"" << get<1>(*start) << "\"";
26 26
27 ++it; // skip first Element 27 ++start; // skip first Element
28 for ( ; it != end; ++it ) 28 for ( ; start != end; ++start ) {
29 *pout_ << ", " << it->first << "=\"" << it->second << "\""; 29 *pout_ << ", " << get<0>(*start) << "=\"" << get<1>(*start) << "\"";
30 } 30 }
31
32 *pout_ << ">" << endl;
33 } 31 }
34 32
35 void handle_end(const string& name) 33 *pout_ << ">" << '\n';
36 { 34 }
37 *pout_ << string(--depth_ * indent_, ' ') 35
38 << "</" << name << ">" 36 void handle_end(string_view name) override
39 << endl; 37 {
38 *pout_ << string(--depth_ * indent_, ' ')
39 << "</" << name << ">"
40 << '\n';
41 }
42 void handle_cdata_start() override
43 {
44 *pout_ << string(depth_ * indent_, ' ')
45 << "<![CDATA[" << '\n';
46 }
47
48 void handle_cdata_end() override
49 {
50 *pout_ << string(depth_ * indent_, ' ')
51 << "]]>" << '\n';
52 }
53
54 static bool contains_only_whitespace(span<const char> data)
55 {
56 return ranges::all_of(data, [](unsigned char chr) {
57 return std::isspace(chr);
58 });
59 }
60
61 void handle_character_data(span<const char> data) override
62 {
63 if ( contains_only_whitespace(data) ) {
64 return;
40 } 65 }
41 66
42 private: 67 *pout_ << string(depth_ * indent_, ' ') << "Data: ";
43 ostream* pout_; 68 pout_->write(data.data(), static_cast<streamsize>(data.size()));
44 size_t depth_; 69 *pout_ << '\n';
45 size_t indent_; 70 }
71
72private:
73 ostream* pout_;
74 size_t depth_{};
75 size_t indent_;
46}; 76};
47 77
48int 78int
@@ -53,6 +83,6 @@ main()
53 myxml.parse(cin); 83 myxml.parse(cin);
54 } 84 }
55 catch ( exception& e ) { 85 catch ( exception& e ) {
56 cerr << "Fehler: " << e.what() << endl; 86 cerr << "Fehler: " << e.what() << '\n';
57 } 87 }
58} 88}