Cleanup
[jmdict-cli.git] / xmlparser.h
1 /*
2 jmdict, a frontend to the JMdict file. http://mandrill.fuxx0r.net/jmdict.php
3 Copyright (C) 2004 Florian Bluemel (florian.bluemel@uni-dortmund.de)
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 */
19 #include <expat.h>
20 #include <istream>
21 #include <string>
22 #include <map>
23
24 namespace xml {
25
26 class Tag {
27 public:
28     Tag(const std::string& name, const char** attrs) : m_name(name) {
29         while (*attrs) {
30             m_attributes[*attrs] = *(attrs + 1);
31             attrs += 2;
32         }
33     }
34
35     const std::string& name() const {
36         return m_name;
37     }
38
39     std::string attribute(const std::string& name) const {
40         std::map<std::string, std::string>::const_iterator val = m_attributes.find(name);
41         if (val == m_attributes.end())
42             return "";
43         return val->second;
44     }
45
46     const std::string& text() const {
47         return m_text;
48     }
49
50     void append(const std::string& t) {
51         m_text += t;
52     }
53
54     void append(const char* t, int len) {
55         m_text.append(t, len);
56     }
57
58 private:
59     std::string m_name;
60     std::string m_text;
61     std::map<std::string, std::string> m_attributes;
62 };
63
64 template<class Stack>
65 class Parser {
66 public:
67     Parser(Stack& stack) : m_stack(stack) {
68         m_parser = XML_ParserCreate(0);
69         XML_SetUserData(m_parser, this);
70         XML_SetElementHandler(m_parser, &Parser::start, &Parser::end);
71         XML_SetCharacterDataHandler(m_parser, Parser::chardata);
72     }
73
74     ~Parser() {
75         XML_ParserFree(m_parser);
76     }
77
78     void parse(std::istream& in) {
79         const size_t BLOCK_SIZE = 1 << 15;
80         while (in) {
81             char* buffer = static_cast<char*>(XML_GetBuffer(m_parser, BLOCK_SIZE));
82             in.read(buffer, BLOCK_SIZE);
83             XML_ParseBuffer(m_parser, static_cast<int>(in.gcount()), in.eof());
84         }
85     }
86
87 private:
88     static void start(void* data, const char* e, const char** a) {
89         Parser& parser = *static_cast<Parser*>(data);
90         parser.m_stack.push(Tag(e, a));
91     }
92
93     static void chardata(void* data, const XML_Char* text, int len) {
94         Parser& parser = *static_cast<Parser*>(data);
95         parser.m_stack.top().append(text, len);
96     }
97         
98     static void end(void* data, const char*) {
99         Parser& parser = *static_cast<Parser*>(data);
100         parser.m_stack.pop();
101     }
102         
103     XML_Parser m_parser;
104     Stack& m_stack;
105 };
106
107 } // namespace xml