Coverage Report

Created: 2026-09-06 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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: */