summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bin/.gitkeep0
-rw-r--r--include/xml.hpp28
-rw-r--r--makefile47
-rw-r--r--obj/.gitkeep0
-rw-r--r--src/xml.cpp75
-rw-r--r--src/xml_test.cpp58
-rw-r--r--test.xml7
7 files changed, 215 insertions, 0 deletions
diff --git a/bin/.gitkeep b/bin/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bin/.gitkeep
diff --git a/include/xml.hpp b/include/xml.hpp
new file mode 100644
index 0000000..cc593a3
--- /dev/null
+++ b/include/xml.hpp
@@ -0,0 +1,28 @@
1#ifndef XML_HPP_INCLUDED
2#define XML_HPP_INCLUDED
3
4// Standard C++
5#include <iostream>
6#include <string>
7#include <vector>
8
9class XML {
10 public:
11 void parse(std::istream& in);
12
13 protected:
14 virtual void handle_start(const std::string& name, const std::vector<std::pair<std::string, std::string>>& attr) = 0;
15 virtual void handle_end(const std::string& name) = 0;
16 virtual void handle_cdata_start() {}
17 virtual void handle_cdata_end() {}
18 virtual void handle_data(const std::vector<char>&) {}
19
20 private:
21 static void tag_start(void* me, const char* name, const char* attr[]);
22 static void tag_end(void* me, const char* name);
23 static void cdata_start(void* me);
24 static void cdata_end(void* me);
25 static void data(void* me, const char* dat, int len);
26};
27
28#endif
diff --git a/makefile b/makefile
new file mode 100644
index 0000000..637130c
--- /dev/null
+++ b/makefile
@@ -0,0 +1,47 @@
1EXE = bin/xml.exe
2
3all: $(EXE)
4
5EMPTY =
6
7CONTRIB = ../contrib
8
9EXPAT_DIR = $(CONTRIB)/expat-2.2.0
10EXPAT_INCLUDE_DIR = $(EXPAT_DIR)/lib
11EXPAT_LIB_DIR = $(EXPAT_DIR)/win32/bin/Release
12EXPAT_LIBS = libexpatMT.lib
13
14OBJS = \
15 obj/xml.obj \
16 obj/xml_test.obj \
17 $(EMPTY)
18
19WIN32_LIBS = kernel32.lib comdlg32.lib user32.lib gdi32.lib ole32.lib wsock32.lib Ws2_32.lib comctl32.lib shell32.lib oleaut32.lib advapi32.lib uuid.lib Winspool.lib
20
21# === Compilereinstellungen ===
22
23CPPFLAGS=-nologo -EHsc -Ox -MT -W4 -WX -Iinclude -I$(EXPAT_INCLUDE_DIR) -DWIN32 -D_WINDOWS -D_CRT_NOFORCE_MANIFEST -D_CRT_SECURE_NO_WARNINGS -DNDEBUG
24
25# === Linkereinstellungen ===
26
27LDFLAGS=-nologo -MANIFEST:NO -LIBPATH:$(EXPAT_LIB_DIR)
28LDFLAGS2=$(WIN32_LIBS) $(EXPAT_LIBS)
29
30$(EXE): $(OBJS)
31 @echo link $@
32 @link.exe $(LDFLAGS) -out:$@ $(LDFLAGS2) $(OBJS)
33
34obj/%.obj: src/%.cpp
35 @echo compiling $@
36 cl $(CPPFLAGS) -Tp$< -c -Fo$@
37
38obj/%.obj: src/%.c
39 @echo compiling $@
40 @cl $(CPPFLAGS) -Tc$< -c -Fo$@
41
42clean:
43 @echo cleaning...
44 @del bin\*.exe
45 @del obj\**
46 @del *.pdb
47
diff --git a/obj/.gitkeep b/obj/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/obj/.gitkeep
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 @@
1// Standard C++
2#include <memory>
3#include <sstream>
4
5// Projekt
6#include "xml.hpp"
7
8// Expat XML Parser
9#define XML_STATIC // force static linkage
10#include "expat.h"
11
12using namespace std;
13
14void
15XML::parse(istream& in)
16{
17 unique_ptr<XML_ParserStruct, decltype(&XML_ParserFree)> parser(XML_ParserCreate(nullptr), XML_ParserFree);
18
19 // setup expat
20 XML_SetUserData(parser.get(), this);
21 XML_SetElementHandler(parser.get(), tag_start, tag_end);
22 XML_SetCdataSectionHandler(parser.get(), cdata_start, cdata_end);
23 XML_SetCharacterDataHandler(parser.get(), data);
24
25 char buffer[2048];
26 for ( bool done = false; !done ; ) {
27 in.read(buffer, sizeof buffer);
28 done = (in.gcount() < sizeof buffer);
29
30 if ( XML_Parse(parser.get(), buffer, static_cast<int>(in.gcount()), done) != XML_STATUS_OK ) {
31 stringstream msg;
32
33 msg << XML_ErrorString(XML_GetErrorCode(parser.get()));
34 msg << " in line " << XML_GetCurrentLineNumber(parser.get());
35
36 throw runtime_error( msg.str() );
37 }
38 }
39}
40
41void
42XML::tag_start(void* me, const char* name, const char* attr[])
43{
44 vector<pair<string, string>> attr_temp;
45
46 for ( size_t i = 0; attr[i]; i += 2 )
47 attr_temp.push_back( make_pair<string, string>(attr[i], attr[i+1]) );
48
49 reinterpret_cast<XML*>(me)->handle_start(name, attr_temp);
50}
51
52void
53XML::tag_end(void* me, const char* name)
54{
55 reinterpret_cast<XML*>(me)->handle_end(name);
56}
57
58void
59XML::cdata_start(void* me)
60{
61 reinterpret_cast<XML*>(me)->handle_cdata_start();
62}
63
64void
65XML::cdata_end(void* me)
66{
67 reinterpret_cast<XML*>(me)->handle_cdata_end();
68}
69
70void
71XML::data(void* me, const char* dat, int len)
72{
73 reinterpret_cast<XML*>(me)->handle_data(vector<char>(dat, dat+len));
74}
75
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 @@
1#include <iostream>
2#include <string>
3using namespace std;
4
5#include "xml.hpp"
6
7class MyXML : public XML {
8 public:
9 explicit MyXML(ostream& out, size_t indent = 4)
10 : pout_(&out)
11 , depth_(0)
12 , indent_(indent)
13 {
14 }
15
16 protected:
17 void handle_start(const string& name, const vector<pair<string, string>>& attr)
18 {
19 *pout_ << string(depth_++ * indent_, ' ')
20 << "<" << name;
21
22 auto it = cbegin(attr);
23 auto end = cend(attr);
24 if ( it != end ) {
25 *pout_ << " " << it->first << "=\"" << it->second << "\"";
26
27 ++it; // skip first Element
28 for ( ; it != end; ++it )
29 *pout_ << ", " << it->first << "=\"" << it->second << "\"";
30 }
31
32 *pout_ << ">" << endl;
33 }
34
35 void handle_end(const string& name)
36 {
37 *pout_ << string(--depth_ * indent_, ' ')
38 << "</" << name << ">"
39 << endl;
40 }
41
42 private:
43 ostream* pout_;
44 size_t depth_;
45 size_t indent_;
46};
47
48int
49main()
50{
51 try {
52 MyXML myxml(cout);
53 myxml.parse(cin);
54 }
55 catch ( exception& e ) {
56 cerr << "Fehler: " << e.what() << endl;
57 }
58}
diff --git a/test.xml b/test.xml
new file mode 100644
index 0000000..24d4371
--- /dev/null
+++ b/test.xml
@@ -0,0 +1,7 @@
1<start>
2 <data param="Hallo Welt" />
3 <data param="ich kann Programmieren" />
4 <![CDATA[<gruss>Hallo Welt!</gruss>]]>
5</start>
6
7