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