/src/libvisio/src/lib/libvisio_xml.cpp
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* |
3 | | * This file is part of the libvisio project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | */ |
9 | | |
10 | | #include "libvisio_xml.h" |
11 | | |
12 | | #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE |
13 | | #define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE 1 |
14 | | #endif |
15 | | #include <boost/lexical_cast.hpp> |
16 | | |
17 | | #include "VSDTypes.h" |
18 | | #include "libvisio_utils.h" |
19 | | |
20 | | namespace libvisio |
21 | | { |
22 | | |
23 | | namespace |
24 | | { |
25 | | |
26 | | extern "C" |
27 | | { |
28 | | |
29 | | static int vsdxInputCloseFunc(void *) |
30 | 31.6k | { |
31 | 31.6k | return 0; |
32 | 31.6k | } |
33 | | |
34 | | static int vsdxInputReadFunc(void *context, char *buffer, int len) |
35 | 117k | { |
36 | 117k | auto *input = (librevenge::RVNGInputStream *)context; |
37 | | |
38 | 117k | if ((!input) || (!buffer) || (len < 0)) |
39 | 0 | return -1; |
40 | | |
41 | 117k | if (input->isEnd()) |
42 | 24.0k | return 0; |
43 | | |
44 | 93.6k | unsigned long tmpNumBytesRead = 0; |
45 | 93.6k | const unsigned char *tmpBuffer = input->read(len, tmpNumBytesRead); |
46 | | |
47 | 93.6k | if (tmpBuffer && tmpNumBytesRead) |
48 | 93.6k | memcpy(buffer, tmpBuffer, tmpNumBytesRead); |
49 | 93.6k | return tmpNumBytesRead; |
50 | 117k | } |
51 | | |
52 | | #ifdef DEBUG |
53 | | static void vsdxReaderErrorFunc(void *arg, const char *message, xmlParserSeverities severity, xmlTextReaderLocatorPtr) |
54 | | #else |
55 | | static void vsdxReaderErrorFunc(void *arg, const char *, xmlParserSeverities severity, xmlTextReaderLocatorPtr) |
56 | | #endif |
57 | 491k | { |
58 | 491k | auto *const watcher = reinterpret_cast<XMLErrorWatcher *>(arg); |
59 | 491k | switch (severity) |
60 | 491k | { |
61 | 2.93k | case XML_PARSER_SEVERITY_VALIDITY_WARNING: |
62 | 2.93k | VSD_DEBUG_MSG(("Found xml parser severity validity warning %s\n", message)); |
63 | 2.93k | break; |
64 | 12.1k | case XML_PARSER_SEVERITY_VALIDITY_ERROR: |
65 | 12.1k | VSD_DEBUG_MSG(("Found xml parser severity validity error %s\n", message)); |
66 | 12.1k | break; |
67 | 15.9k | case XML_PARSER_SEVERITY_WARNING: |
68 | 15.9k | VSD_DEBUG_MSG(("Found xml parser severity warning %s\n", message)); |
69 | 15.9k | break; |
70 | 460k | case XML_PARSER_SEVERITY_ERROR: |
71 | 460k | VSD_DEBUG_MSG(("Found xml parser severity error %s\n", message)); |
72 | 460k | if (watcher) |
73 | 6.85k | watcher->setError(); |
74 | 460k | break; |
75 | 0 | default: |
76 | 0 | break; |
77 | 491k | } |
78 | 491k | } |
79 | | |
80 | | } // extern "C" |
81 | | |
82 | | } // anonymous namespace |
83 | | |
84 | | XMLErrorWatcher::XMLErrorWatcher() |
85 | 5.31k | : m_error(false) |
86 | 5.31k | { |
87 | 5.31k | } |
88 | | |
89 | | bool XMLErrorWatcher::isError() const |
90 | 570k | { |
91 | 570k | return m_error; |
92 | 570k | } |
93 | | |
94 | | void XMLErrorWatcher::setError() |
95 | 6.85k | { |
96 | 6.85k | m_error = true; |
97 | 6.85k | } |
98 | | |
99 | | std::unique_ptr<xmlTextReader, void (*)(xmlTextReaderPtr)> |
100 | | xmlReaderForStream(librevenge::RVNGInputStream *input, XMLErrorWatcher *const watcher, bool recover) |
101 | 31.6k | { |
102 | 31.6k | int options = XML_PARSE_NOBLANKS | XML_PARSE_NONET; |
103 | 31.6k | if (recover) |
104 | 26.3k | options |= XML_PARSE_RECOVER; |
105 | 31.6k | std::unique_ptr<xmlTextReader, void (*)(xmlTextReaderPtr)> reader |
106 | 31.6k | { |
107 | 31.6k | xmlReaderForIO(vsdxInputReadFunc, vsdxInputCloseFunc, (void *)input, nullptr, nullptr, options), |
108 | 31.6k | xmlFreeTextReader |
109 | 31.6k | }; |
110 | 31.6k | if (reader) |
111 | 31.6k | xmlTextReaderSetErrorHandler(reader.get(), vsdxReaderErrorFunc, watcher); |
112 | 31.6k | return reader; |
113 | 31.6k | } |
114 | | |
115 | | Colour xmlStringToColour(const xmlChar *s) |
116 | 60.4k | { |
117 | 60.4k | if (xmlStrEqual(s, BAD_CAST("Themed"))) |
118 | 0 | return Colour(); |
119 | 60.4k | std::string str((const char *)s); |
120 | 60.4k | if (str[0] == '#') |
121 | 41.0k | { |
122 | 41.0k | if (str.length() != 7) |
123 | 7 | { |
124 | 7 | VSD_DEBUG_MSG(("Throwing XmlParserException\n")); |
125 | 7 | throw XmlParserException(); |
126 | 7 | } |
127 | 41.0k | else |
128 | 41.0k | str.erase(str.begin()); |
129 | 41.0k | } |
130 | 19.3k | else |
131 | 19.3k | { |
132 | 19.3k | if (str.length() != 6) |
133 | 19.3k | { |
134 | 19.3k | VSD_DEBUG_MSG(("Throwing XmlParserException\n")); |
135 | 19.3k | throw XmlParserException(); |
136 | 19.3k | } |
137 | 19.3k | } |
138 | | |
139 | 41.1k | std::istringstream istr(str); |
140 | 41.1k | unsigned val = 0; |
141 | 41.1k | istr >> std::hex >> val; |
142 | | |
143 | 41.1k | return Colour((val & 0xff0000) >> 16, (val & 0xff00) >> 8, val & 0xff, 0); |
144 | 60.4k | } |
145 | | |
146 | | Colour xmlStringToColour(const std::shared_ptr<xmlChar> &s) |
147 | 60.4k | { |
148 | 60.4k | return xmlStringToColour(s.get()); |
149 | 60.4k | } |
150 | | |
151 | | long xmlStringToLong(const xmlChar *s) |
152 | 315k | { |
153 | 315k | using boost::lexical_cast; |
154 | 315k | using boost::bad_lexical_cast; |
155 | 315k | if (xmlStrEqual(s, BAD_CAST("Themed"))) |
156 | 3 | return 0; |
157 | | |
158 | 315k | try |
159 | 315k | { |
160 | 315k | return boost::lexical_cast<long, const char *>((const char *)s); |
161 | 315k | } |
162 | 315k | catch (const boost::bad_lexical_cast &) |
163 | 315k | { |
164 | 894 | VSD_DEBUG_MSG(("Throwing XmlParserException\n")); |
165 | 894 | throw XmlParserException(); |
166 | 894 | } |
167 | 0 | return 0; |
168 | 315k | } |
169 | | |
170 | | long xmlStringToLong(const std::shared_ptr<xmlChar> &s) |
171 | 147k | { |
172 | 147k | return xmlStringToLong(s.get()); |
173 | 147k | } |
174 | | |
175 | 388k | double xmlStringToDouble(const xmlChar *s) try |
176 | 388k | { |
177 | 388k | if (xmlStrEqual(s, BAD_CAST("Themed"))) |
178 | 0 | return 0.0; |
179 | | |
180 | 388k | return boost::lexical_cast<double, const char *>((const char *)s); |
181 | 388k | } |
182 | 388k | catch (const boost::bad_lexical_cast &) |
183 | 388k | { |
184 | 403 | VSD_DEBUG_MSG(("Throwing XmlParserException\n")); |
185 | 403 | throw XmlParserException(); |
186 | 403 | } |
187 | | |
188 | | double xmlStringToDouble(const std::shared_ptr<xmlChar> &s) |
189 | 388k | { |
190 | 388k | return xmlStringToDouble(s.get()); |
191 | 388k | } |
192 | | |
193 | | bool xmlStringToBool(const xmlChar *s) |
194 | 36.7k | { |
195 | 36.7k | if (xmlStrEqual(s, BAD_CAST("Themed"))) |
196 | 0 | return 0; |
197 | | |
198 | 36.7k | bool value = false; |
199 | 36.7k | if (xmlStrEqual(s, BAD_CAST("true")) || xmlStrEqual(s, BAD_CAST("1"))) |
200 | 6.70k | value = true; |
201 | 30.0k | else if (xmlStrEqual(s, BAD_CAST("false")) || xmlStrEqual(s, BAD_CAST("0"))) |
202 | 30.0k | value = false; |
203 | 46 | else |
204 | 46 | { |
205 | 46 | VSD_DEBUG_MSG(("Throwing XmlParserException\n")); |
206 | 46 | throw XmlParserException(); |
207 | 46 | } |
208 | 36.7k | return value; |
209 | | |
210 | 36.7k | } |
211 | | |
212 | | bool xmlStringToBool(const std::shared_ptr<xmlChar> &s) |
213 | 36.7k | { |
214 | 36.7k | return xmlStringToBool(s.get()); |
215 | 36.7k | } |
216 | | |
217 | | } // namespace libvisio |
218 | | |
219 | | /* vim:set shiftwidth=2 softtabstop=2 expandtab: */ |