26 namespace xmltable { |
27 namespace xmltable { |
27 |
28 |
28 class HierarchicalINIContentHandler : public INIContentHandler { |
29 class HierarchicalINIContentHandler : public INIContentHandler { |
29 private: |
30 private: |
30 xmlpp::DomParser* domParser; |
31 xmlpp::DomParser* domParser; |
31 wstring_convert < codecvt_utf8<wchar_t>> convertor; // INI parser works with UTF-8 |
32 XMLNameCodec nameCodec; |
|
33 xmlpp::Element* currentSection = nullptr; |
32 public: |
34 public: |
33 |
35 |
34 HierarchicalINIContentHandler(xmlpp::DomParser* domParser) : domParser(domParser) { |
36 HierarchicalINIContentHandler(xmlpp::DomParser* domParser) : domParser(domParser) { |
35 } |
37 } |
36 |
38 |
37 virtual ~HierarchicalINIContentHandler() { |
39 virtual ~HierarchicalINIContentHandler() { |
38 } |
40 } |
39 |
41 |
40 void startDocument() override { |
42 void startDocument() override { |
41 domParser->get_document()->create_root_node("ini"); |
43 if (currentSection) throw std::out_of_range("Lunatic INI parser send us multiple documents."); |
42 domParser->get_document()->get_root_node()->add_child("startDocument"); |
44 currentSection = domParser->get_document()->create_root_node("ini"); |
43 // there should be only one document |
|
44 }; |
45 }; |
45 |
46 |
46 void endDocument() override { |
47 void endDocument() override { |
47 domParser->get_document()->get_root_node()->add_child("endDocument"); |
|
48 }; |
48 }; |
49 |
49 |
50 void startSection(const SectionStartEvent& event) override { |
50 void startSection(const SectionStartEvent& event) override { |
51 xmlpp::Element* node = domParser->get_document()->get_root_node()->add_child("startSection"); |
51 currentSection = currentSection->add_child(nameCodec.encode(event.name)); |
52 node->add_child("name")->add_child_text(event.name); |
52 currentSection->set_attribute("type", "section"); |
53 node->add_child("comment")->add_child_text(event.comment); |
53 currentSection->set_attribute("name", event.name); |
54 node->add_child("line-number")->add_child_text(std::to_string(event.lineNumber)); |
54 if (event.comment.size()) currentSection->set_attribute("comment", event.comment); |
55 node->add_child("event-number")->add_child_text(std::to_string(event.eventNumber)); |
55 if (event.lineNumber >= 0) currentSection->set_attribute("line-number", std::to_string(event.lineNumber)); |
|
56 if (event.eventNumber >= 0) currentSection->set_attribute("event-number", std::to_string(event.eventNumber)); |
56 }; |
57 }; |
57 |
58 |
58 void endSection() override { |
59 void endSection() override { |
59 domParser->get_document()->get_root_node()->add_child("endSection"); |
60 currentSection = currentSection->get_parent(); |
|
61 if (currentSection == nullptr) throw std::out_of_range("Lunatic INI parser tried to end a section without starting it before."); |
60 }; |
62 }; |
61 |
63 |
62 void entry(const EntryEvent& event) override { |
64 void entry(const EntryEvent& event) override { |
63 xmlpp::Element* node = domParser->get_document()->get_root_node()->add_child("entry"); |
65 xmlpp::Element* entry = currentSection->add_child(nameCodec.encode(event.fullKey)); |
64 node->add_child("key")->add_child_text(event.key); |
66 entry->set_attribute("type", "entry"); |
65 node->add_child("sub-key")->add_child_text(event.subKey); |
67 entry->set_attribute("key", event.key); |
66 node->add_child("full-key")->add_child_text(event.fullKey); |
68 entry->set_attribute("full-key", event.fullKey); |
67 node->add_child("value")->add_child_text(event.value); |
69 if (event.subKey.size()) entry->set_attribute("sub-key", event.subKey); |
68 node->add_child("comment")->add_child_text(event.comment); |
70 if (event.comment.size()) currentSection->set_attribute("comment", event.comment); |
69 node->add_child("line-number")->add_child_text(std::to_string(event.lineNumber)); |
71 if (event.lineNumber >= 0) currentSection->set_attribute("line-number", std::to_string(event.lineNumber)); |
70 node->add_child("event-number")->add_child_text(std::to_string(event.eventNumber)); |
72 if (event.eventNumber >= 0) currentSection->set_attribute("event-number", std::to_string(event.eventNumber)); |
|
73 entry->add_child_text(event.value); |
71 }; |
74 }; |
72 |
75 |
73 }; |
76 }; |
|
77 |
|
78 // TODO: support also other styles/mappings e.g. <section/> and <entry/> with INI names only in the XML attributes (and thus without @type="section|entry") |
74 |
79 |
75 class XMLDocumentConstructor { |
80 class XMLDocumentConstructor { |
76 private: |
81 private: |
77 std::istream* input = nullptr; |
82 std::istream* input = nullptr; |
78 xmlpp::DomParser* parser = nullptr; |
83 xmlpp::DomParser* parser = nullptr; |