Imported Upstream version 2.91.2
[platform/upstream/libxml++.git] / libxml++ / exceptions / exception.cc
1 #include "exception.h"
2 #include <libxml/xmlerror.h>
3 #include <libxml/parser.h>
4 #include <cstdio>
5 #include <vector>
6
7 namespace xmlpp {
8   
9 exception::exception(const Glib::ustring& message)
10 : message_(message)
11 {
12 }
13
14 exception::~exception() noexcept
15 {}
16
17 const char* exception::what() const noexcept
18 {
19   return message_.c_str();
20 }
21
22 void exception::raise() const
23 {
24   throw *this;
25 }
26
27 exception* exception::clone() const
28 {
29   return new exception(*this);
30 }
31
32 Glib::ustring format_xml_error(const _xmlError* error)
33 {
34   if (!error)
35     error = xmlGetLastError();
36
37   if (!error || error->code == XML_ERR_OK)
38     return ""; // No error
39
40   Glib::ustring str;
41
42   if (error->file && *error->file != '\0')
43   {
44     str += "File ";
45     str += error->file;
46   }
47
48   if (error->line > 0)
49   {
50     str += (str.empty() ? "Line " : ", line ") + Glib::ustring::format(error->line);
51     if (error->int2 > 0)
52       str += ", column " + Glib::ustring::format(error->int2);
53   }
54
55   const bool two_lines = !str.empty();
56   if (two_lines)
57     str += ' ';
58
59   switch (error->level)
60   {
61     case XML_ERR_WARNING:
62       str += "(warning):";
63       break;
64     case XML_ERR_ERROR:
65       str += "(error):";
66       break;
67     case XML_ERR_FATAL:
68       str += "(fatal):";
69       break;
70     default:
71       str += "():";
72       break;
73   }
74
75   str += two_lines ? '\n' : ' ';
76
77   if (error->message && *error->message != '\0')
78     str += error->message;
79   else
80     str += "Error code " + Glib::ustring::format(error->code);
81
82   // If the string does not end with end-of-line, append an end-of-line.
83   if (*str.rbegin() != '\n')
84     str += '\n';
85
86   return str;
87 }
88
89 Glib::ustring format_xml_parser_error(const _xmlParserCtxt* parser_context)
90 {
91   if (!parser_context)
92     return "Error. xmlpp::format_xml_parser_error() called with parser_context == nullptr\n";
93
94   const auto error = xmlCtxtGetLastError(const_cast<_xmlParserCtxt*>(parser_context));
95
96   if (!error)
97     return ""; // No error
98
99   Glib::ustring str;
100
101   if (!parser_context->wellFormed)
102     str += "Document not well-formed.\n";
103
104   return str + format_xml_error(error);
105 }
106
107 Glib::ustring format_printf_message(const char* fmt, va_list args)
108 {
109   // This code was inspired by the example at
110   // http://en.cppreference.com/w/cpp/io/c/vfprintf
111   va_list args2;
112   va_copy(args2, args);
113   // Number of characters (bytes) in the resulting string;
114   // error, if < 0.
115   const int nchar = std::vsnprintf(nullptr, 0, fmt, args2);
116   va_end(args2);
117   if (nchar < 0)
118    return Glib::ustring::format("Error code from std::vsnprintf = ", nchar);
119
120   std::vector<char> buf(nchar+1);
121   std::vsnprintf(buf.data(), buf.size(), fmt, args);
122   return Glib::ustring(buf.data());
123 }
124
125 } //namespace xmlpp