Imported Upstream version 2.91.2
[platform/upstream/libxml++.git] / libxml++ / validators / validator.cc
1 /* validator.cc
2  * libxml++ and this file are copyright (C) 2000 by Ari Johnson
3  * (C) 2002-2004 by the libxml dev team and
4  * are covered by the GNU Lesser General Public License, which should be
5  * included with libxml++ as the file COPYING.
6  */
7
8 #include "libxml++/exceptions/wrapped_exception.h"
9 #include "libxml++/validators/validator.h"
10
11 #include <libxml/parser.h>
12
13 #include <cstdarg> //For va_list.
14 #include <memory> //For unique_ptr.
15
16 namespace xmlpp {
17
18 Validator::Validator()
19 : exception_(nullptr)
20 {
21 }
22
23 Validator::~Validator()
24 {
25   release_underlying();
26 }
27
28 void Validator::initialize_context()
29 {
30   //Clear these temporary buffers:
31   validate_error_.erase();
32   validate_warning_.erase();
33 }
34
35 void Validator::release_underlying()
36 {
37 }
38
39 void Validator::on_validity_error(const Glib::ustring& message)
40 {
41   //Throw an exception later when the whole message has been received:
42   validate_error_ += message;
43 }
44
45 void Validator::on_validity_warning(const Glib::ustring& message)
46 {
47   //Throw an exception later when the whole message has been received:
48   validate_warning_ += message;
49 }
50
51 void Validator::check_for_validity_messages()
52 {
53   Glib::ustring msg(exception_ ? exception_->what() : "");
54   bool validity_msg = false;
55
56   if (!validate_error_.empty())
57   {
58     validity_msg = true;
59     msg += "\nValidity error:\n" + validate_error_;
60     validate_error_.erase();
61   }
62
63   if (!validate_warning_.empty())
64   {
65     validity_msg = true;
66     msg += "\nValidity warning:\n" + validate_warning_;
67     validate_warning_.erase();
68   }
69
70   if (validity_msg)
71     exception_.reset(new validity_error(msg));
72 }
73
74 void Validator::callback_validity_error(void* valid_, const char* msg, ...)
75 {
76   auto validator = static_cast<Validator*>(valid_);
77
78   if(validator)
79   {
80     //Convert the ... to a string:
81     va_list arg;
82     va_start(arg, msg);
83     const Glib::ustring buff = format_printf_message(msg, arg);
84     va_end(arg);
85
86     try
87     {
88       validator->on_validity_error(buff);
89     }
90     catch (...)
91     {
92       validator->handle_exception();
93     }
94   }
95 }
96
97 void Validator::callback_validity_warning(void* valid_, const char* msg, ...)
98 {
99   auto validator = static_cast<Validator*>(valid_);
100
101   if(validator)
102   {
103     //Convert the ... to a string:
104     va_list arg;
105     va_start(arg, msg);
106     const Glib::ustring buff = format_printf_message(msg, arg);
107     va_end(arg);
108
109     try
110     {
111       validator->on_validity_warning(buff);
112     }
113     catch (...)
114     {
115       validator->handle_exception();
116     }
117   }
118 }
119
120 void Validator::handle_exception()
121 {
122   try
123   {
124     throw; // Re-throw current exception
125   }
126   catch (const exception& e)
127   {
128     exception_.reset(e.clone());
129   }
130 #ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
131   catch (...)
132   {
133     exception_.reset(new wrapped_exception(std::current_exception()));
134   }
135 #else
136   catch (const std::exception& e)
137   {
138     exception_.reset(new exception(e.what()));
139   }
140   catch (...)
141   {
142     exception_.reset(new exception("An exception was thrown that is not derived from std::exception or xmlpp::exception.\n"
143       "It could not be caught and rethrown because this platform does not support std::exception_ptr."));
144   }
145 #endif
146
147   // Don't delete the DTD validation context or schema validation context
148   // while validating. It would cause accesses to deallocated memory in libxml2
149   // functions after the return from Validator::callback_validity_...().
150   // Parser::handle_exception() calls xmlStopParser(), but there is no
151   // xmlStopValidator() or similar function to call here.
152   // We don't throw the exception here, since it would have to pass through
153   // C functions. That's not guaranteed to work. It might work, but it depends
154   // on the C compiler and the options used when building libxml2.
155
156   //release_underlying();
157 }
158
159 void Validator::check_for_exception()
160 {
161   check_for_validity_messages();
162   
163   if (exception_)
164   {
165     std::unique_ptr<exception> tmp(std::move(exception_));
166     tmp->raise();
167   }
168 }
169
170 } // namespace xmlpp