1 /***************************************************************************
2 expatwrap.h - c++ wrapper for expat
3 -------------------
4 begin : Sun May 20 2007
5 copyright : (C) 2002-2007 by Ewald Arnold
6 email : ulxmlrpcpp@ewald-arnold.de
7
8 $Id: expatwrap.cpp 966 2007-07-08 17:23:21Z ewald-arnold $
9
10 ***************************************************************************/
11
12 /**************************************************************************
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License as
16 * published by the Free Software Foundation; either version 2 of the License,
17 * or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU Lesser General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 *
28 ***************************************************************************/
29
30
31 #include "expatwrap.h"
32 #include "xmlexcept.h"
33
34
ExpatWrapper(bool createParser)35 ExpatWrapper::ExpatWrapper(bool createParser)
36 : XmlParserBase()
37 {
38 if (createParser)
39 {
40 expatParser = ::XML_ParserCreate(0);
41 setHandler();
42 }
43 }
44
45
~ExpatWrapper()46 ExpatWrapper::~ExpatWrapper()
47 {
48 if (expatParser) // allows subclasses to avoid finishing parsing
49 ::XML_ParserFree(expatParser);
50 }
51
52
setHandler()53 void ExpatWrapper::setHandler()
54 {
55 ::XML_SetUserData(expatParser, this);
56 ::XML_SetElementHandler(expatParser, startElementCallback, endElementCallback);
57 ::XML_SetCharacterDataHandler(expatParser, charDataCallback);
58 }
59
60
reset()61 void ExpatWrapper::reset()
62 {
63 ::XML_ParserReset(expatParser, 0);
64 setHandler();
65 }
66
67
startElement(const XML_Char *,const XML_Char **)68 void ExpatWrapper::startElement(const XML_Char*, const XML_Char**)
69 {
70 }
71
72
endElement(const XML_Char *)73 void ExpatWrapper::endElement(const XML_Char*)
74 {
75 }
76
77
charData(const XML_Char *,int)78 void ExpatWrapper::charData(const XML_Char*, int )
79 {
80 }
81
82
mapToFaultCode(int xpatcode) const83 int ExpatWrapper::mapToFaultCode(int xpatcode) const
84 {
85 int fc = NotWellformedError;
86 // try to map error codes
87 switch (xpatcode)
88 {
89 case XML_ERROR_UNKNOWN_ENCODING:
90 fc = UnsupportedEncodingError;
91 break;
92
93 case XML_ERROR_BAD_CHAR_REF:
94 case XML_ERROR_PARTIAL_CHAR:
95 case XML_ERROR_INCORRECT_ENCODING: // fallthrough
96 fc = InvalidCharacterError;
97 break;
98
99 default:
100 fc = NotWellformedError;
101 }
102 return fc;
103 }
104
105
106
startElementCallback(void * userData,const XML_Char * name,const XML_Char ** atts)107 void ExpatWrapper::startElementCallback(void *userData,
108 const XML_Char* name,
109 const XML_Char** atts)
110 {
111 ((ExpatWrapper*)userData)->startElement(name, atts);
112 }
113
114
115
endElementCallback(void * userData,const XML_Char * name)116 void ExpatWrapper::endElementCallback(void *userData, const XML_Char* name)
117 {
118 ((ExpatWrapper*)userData)->endElement(name);
119 }
120
121
122
charDataCallback(void * userData,const XML_Char * s,int len)123 void ExpatWrapper::charDataCallback(void *userData, const XML_Char* s, int len)
124 {
125 ((ExpatWrapper*)userData)->charData(s, len);
126 }
127
128
parse(const char * buffer,int len,int isFinal)129 int ExpatWrapper::parse(const char* buffer, int len, int isFinal)
130 {
131 return ::XML_Parse(expatParser, buffer, len, isFinal);
132 }
133
134
getErrorCode() const135 unsigned ExpatWrapper::getErrorCode() const
136 {
137 return ::XML_GetErrorCode(expatParser);
138 }
139
140
getErrorString(unsigned code) const141 std::string ExpatWrapper::getErrorString(unsigned code) const
142 {
143 return XML_ErrorString((XML_Error) code);
144 }
145
146
getCurrentLineNumber() const147 int ExpatWrapper::getCurrentLineNumber() const
148 {
149 return ::XML_GetCurrentLineNumber(expatParser);
150 }
151
152
153 ///////////////////////////////////////////////
154
155
AttributeList(ExpatWrapper * in_parser,const XML_Char ** atts)156 ExpatWrapper::AttributeList::AttributeList(ExpatWrapper *in_parser, const XML_Char** atts)
157 : parser(in_parser)
158 {
159 for (unsigned i = 0; atts[i]; i += 2)
160 {
161 const std::string name = atts[i];
162 const std::string content = atts[i+1];
163
164 if (hasAttribute(name))
165 throw XmlException(NotWellformedError,
166 "Problem while parsing xml structure",
167 parser->getCurrentLineNumber(),
168 std::string("duplicate attribute: ") + name);
169
170 attributes.insert(std::make_pair(name, content));
171 }
172 }
173
174
hasAttribute(const std::string & name) const175 bool ExpatWrapper::AttributeList::hasAttribute(const std::string &name) const
176 {
177 return attributes.find(name) != attributes.end();
178 }
179
180
getAttribute(const std::string & name) const181 std::string ExpatWrapper::AttributeList::getAttribute(const std::string &name) const
182 {
183 std::map<std::string, std::string>::const_iterator it = attributes.find(name);
184
185 if (it == attributes.end())
186 throw XmlException(NotWellformedError,
187 "Problem while parsing xml structure",
188 parser->getCurrentLineNumber(),
189 std::string("attribute not available: ") + name);
190
191 return (*it).second;
192 }
193