Removing warnings reported by cppcheck tool.
[framework/web/wrt-installer.git] / src / configuration_parser / parser_runner.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /**
17  * @file        parser_runner.cpp
18  * @author      Lukasz Wrzosek (l.wrzosek@samsung.com)
19  * @version     0.1
20  * @brief
21  */
22 #include "parser_runner.h"
23 #include "root_parser.h"
24
25 #include <stack>
26 #include <libxml/xmlreader.h>
27 #include <dpl/binary_queue.h>
28 #include <dpl/assert.h>
29 #include <dpl/file_input.h>
30 #include <dpl/log/log.h>
31
32 class ParserRunner::Impl
33 {
34   public:
35     void Parse(const std::string& filename,
36                const ElementParserPtr& root)
37     {
38         DPL::FileInput input(filename);
39         Parse(&input, root);
40     }
41
42     void Parse (DPL::AbstractInput *input,
43                 const ElementParserPtr& root)
44     {
45         Try
46         {
47             m_reader = xmlReaderForIO(&IoRead,
48                                       &IoClose,
49                                       input,
50                                       NULL,
51                                       NULL,
52                                       XML_PARSE_NOENT);
53
54             xmlTextReaderSetErrorHandler(m_reader,
55                                          &xmlTextReaderErrorHandler,
56                                          this);
57             xmlTextReaderSetStructuredErrorHandler(
58                 m_reader,
59                 &xmlTextReaderStructuredErrorHandler,
60                 this);
61             SetCurrentElementParser(root);
62
63             while (xmlTextReaderRead(m_reader) == 1) {
64                 switch (xmlTextReaderNodeType(m_reader)) {
65                 case XML_READER_TYPE_END_ELEMENT:
66                     VerifyAndRemoveCurrentElementParser();
67                     break;
68
69                 case XML_READER_TYPE_ELEMENT:
70                 {
71                     // Elements without closing tag don't receive
72                     // XML_READER_TYPE_END_ELEMENT event.
73                     if (IsNoClosingTagElementLeft()) {
74                         VerifyAndRemoveCurrentElementParser();
75                     }
76
77                     DPL::String elementName = GetNameWithoutNamespace();
78                     DPL::String nameSpace = GetNamespace();
79                     ElementParserPtr parser = GetCurrentElementParser();
80                     parser = parser->GetElementParser(nameSpace,
81                                                       elementName) ();
82                     Assert(!!parser);
83                     SetCurrentElementParser(parser);
84                     ParseNodeElement(parser);
85                     break;
86                 }
87                 case XML_READER_TYPE_TEXT:
88                 case XML_READER_TYPE_CDATA:
89                 {
90                     ParseNodeText(GetCurrentElementParser());
91                     break;
92                 }
93                 default:
94                     LogWarning("Ignoring Node of Type: " <<
95                                xmlTextReaderNodeType(m_reader));
96                     break;
97                 }
98
99                 if (m_parsingError) {
100                     LogError("Parsing error occured: " << m_errorMsg);
101                     ThrowMsg(ElementParser::Exception::ParseError, m_errorMsg);
102                 }
103             }
104
105             if (m_parsingError) {
106                 LogError("Parsing error occured: " << m_errorMsg);
107                 ThrowMsg(ElementParser::Exception::ParseError, m_errorMsg);
108             }
109
110             while (!m_stack.empty()) {
111                 VerifyAndRemoveCurrentElementParser();
112             }
113         }
114         Catch(ElementParser::Exception::Base)
115         {
116             CleanupParserRunner();
117             LogError(_rethrown_exception.DumpToString());
118             ReThrow(ElementParser::Exception::ParseError);
119         }
120         CleanupParserRunner();
121     }
122
123     Impl() :
124         m_reader(NULL),
125         m_parsingError(false)
126     {}
127
128     ~Impl()
129     {
130         CleanupParserRunner();
131     }
132
133   private:
134     typedef std::stack<ElementParserPtr> ElementStack;
135
136   private:
137     static void xmlTextReaderErrorHandler(void* arg,
138                                           const char* msg,
139                                           xmlParserSeverities /* severity */,
140                                           xmlTextReaderLocatorPtr /* locator */)
141     {
142         ParserRunner::Impl* impl = static_cast<ParserRunner::Impl*>(arg);
143         impl->ErrorHandler(DPL::FromASCIIString(msg));
144     }
145
146     static void xmlTextReaderStructuredErrorHandler(void* arg,
147                                                     xmlErrorPtr error)
148     {
149         ParserRunner::Impl* impl = static_cast<ParserRunner::Impl*>(arg);
150         impl->StructuredErrorHandler(error);
151     }
152
153     static int XMLCALL IoRead(void *context,
154                               char *buffer,
155                               int len)
156     {
157         DPL::AbstractInput *input = static_cast<DPL::AbstractInput *>(context);
158         DPL::BinaryQueueAutoPtr data = input->Read(static_cast<size_t>(len));
159         if (!data.get()) {
160             return -1;
161         }
162         data->Flatten(buffer, data->Size());
163         return static_cast<int>(data->Size());
164     }
165
166     static int XMLCALL IoClose(void */* context */)
167     {
168         // NOOP
169         return 0;
170     }
171
172   private:
173     void SetCurrentElementParser(const ElementParserPtr& elementParser)
174     {
175         Assert(elementParser);
176
177         m_stack.push(elementParser);
178     }
179
180     const ElementParserPtr& GetCurrentElementParser() const
181     {
182         Assert(!m_stack.empty());
183
184         return m_stack.top();
185     }
186
187     void VerifyAndRemoveCurrentElementParser()
188     {
189         Assert(!m_stack.empty());
190
191         m_stack.top()->Verify();
192         m_stack.pop();
193     }
194
195     bool IsNoClosingTagElementLeft() const
196     {
197         Assert(m_reader);
198
199         int depth = xmlTextReaderDepth(m_reader);
200         return (static_cast<int>(m_stack.size()) - 2 == depth);
201     }
202
203     void ParseNodeElement(const ElementParserPtr& parser)
204     {
205         Assert(m_reader);
206
207         Element element;
208         element.value = GetValue();
209         element.lang = GetLanguageTag();
210         element.ns = GetNamespace();
211
212         LogDebug("value: " << element.value <<
213                  ", lang: " << element.lang <<
214                  ", ns: " << element.ns << ")");
215
216         parser->Accept(element);
217         ParseNodeElementAttributes(parser);
218     }
219
220     void ParseNodeElementAttributes(const ElementParserPtr& parser)
221     {
222         Assert(m_reader);
223
224         int count = xmlTextReaderAttributeCount(m_reader);
225         for (int i = 0; i < count; ++i) {
226             xmlTextReaderMoveToAttributeNo(m_reader, i);
227
228             XmlAttribute attribute;
229             attribute.ns = GetAttributeNamespace();
230             attribute.prefix = GetNamePrefix();
231             attribute.name = GetNameWithoutNamespace();
232             attribute.value = GetValue();
233             attribute.lang = GetLanguageTag();
234             LogDebug("Attribute name: " << attribute.name <<
235                      ", value: " << attribute.value <<
236                      ", prefix: " << attribute.prefix <<
237                      ", namespace: " << attribute.ns <<
238                      ", lang: " << attribute.lang);
239             parser->Accept(attribute);
240         }
241     }
242
243     void ParseNodeText(const ElementParserPtr& parser)
244     {
245         Text text;
246         text.value = GetValue();
247         text.lang = GetLanguageTag();
248         parser->Accept(text);
249     }
250
251     DPL::String GetValue() const
252     {
253         DPL::String ret_value;
254         const xmlChar* value = xmlTextReaderConstValue(m_reader);
255         if (value) {
256             ret_value =
257                 DPL::FromUTF8String(reinterpret_cast<const char*>(value));
258         }
259
260         return ret_value;
261     }
262
263     DPL::String GetAttributeValue(int pos) const
264     {
265         DPL::String ret_value;
266         const xmlChar* value = xmlTextReaderGetAttributeNo(m_reader, pos);
267         if (value) {
268             ret_value =
269                 DPL::FromUTF8String(reinterpret_cast<const char*>(value));
270         }
271         xmlFree(const_cast<xmlChar*>(value));
272
273         return ret_value;
274     }
275
276     DPL::String GetAttributeNamespace() const
277     {
278         DPL::String ret_value;
279         const xmlChar* value = xmlTextReaderLookupNamespace(m_reader, NULL);
280         if (value) {
281             ret_value =
282                 DPL::FromUTF8String(reinterpret_cast<const char*>(value));
283         }
284         xmlFree(const_cast<xmlChar*>(value));
285
286         return ret_value;
287     }
288
289     DPL::String GetName() const
290     {
291         DPL::String ret_value;
292         const xmlChar* value = xmlTextReaderConstName(m_reader);
293         if (value) {
294             ret_value =
295                 DPL::FromUTF8String(reinterpret_cast<const char*>(value));
296         }
297
298         return ret_value;
299     }
300
301     DPL::String GetNamePrefix() const
302     {
303         DPL::String ret_value;
304         const xmlChar* value = xmlTextReaderPrefix(m_reader);
305         if (value) {
306             ret_value =
307                 DPL::FromUTF8String(reinterpret_cast<const char*>(value));
308         }
309
310         return ret_value;
311     }
312
313     DPL::String GetNameWithoutNamespace() const
314     {
315         DPL::String ret_value;
316         const xmlChar* value = xmlTextReaderLocalName(m_reader);
317         if (value) {
318             ret_value =
319                 DPL::FromUTF8String(reinterpret_cast<const char*>(value));
320         }
321
322         return ret_value;
323     }
324
325     DPL::String GetNamespace() const
326     {
327         DPL::String ret_value;
328
329         const xmlChar* value = xmlTextReaderConstNamespaceUri(m_reader);
330         if (value) {
331             ret_value =
332                 DPL::FromUTF8String(reinterpret_cast<const char*>(value));
333         }
334
335         return ret_value;
336     }
337
338     DPL::String GetLanguageTag() const
339     {
340         DPL::String ret_value;
341         const xmlChar* value = xmlTextReaderConstXmlLang(m_reader);
342         if (value) {
343             ret_value =
344                 DPL::FromUTF8String(reinterpret_cast<const char*>(value));
345         }
346
347         return ret_value;
348     }
349
350     void ErrorHandler(const DPL::String& msg)
351     {
352         LogError("LibXML:  " << msg);
353         m_parsingError = true;
354         m_errorMsg = m_errorMsg + DPL::FromASCIIString("\n");
355         m_errorMsg = m_errorMsg + msg;
356     }
357
358     void StructuredErrorHandler(xmlErrorPtr error)
359     {
360         LogError("LibXML:  " << error->message);
361         m_parsingError = true;
362         m_errorMsg = m_errorMsg + DPL::FromASCIIString("\n");
363         m_errorMsg = m_errorMsg + DPL::FromUTF8String(error->message);
364     }
365
366     void CleanupParserRunner()
367     {
368         while (!m_stack.empty()) {
369             m_stack.pop();
370         }
371         if (m_reader) {
372             xmlFreeTextReader(m_reader);
373         }
374         m_reader = NULL;
375     }
376
377   private:
378     xmlTextReaderPtr m_reader;
379     ElementStack m_stack;
380     bool m_parsingError;
381     DPL::String m_errorMsg;
382 };
383
384 ParserRunner::ParserRunner() :
385     m_impl(new ParserRunner::Impl())
386 {}
387
388 void ParserRunner::Parse(const std::string& filename,
389                          ElementParserPtr root)
390 {
391     m_impl->Parse(filename, root);
392 }
393
394 void ParserRunner::Parse(DPL::AbstractInput *input,
395                          ElementParserPtr root)
396 {
397     m_impl->Parse(input, root);
398 }
399
400 ParserRunner::~ParserRunner()
401 {
402     delete m_impl;
403 }