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.
8 #include "libxml++/exceptions/wrapped_exception.h"
9 #include "libxml++/validators/validator.h"
11 #include <libxml/parser.h>
13 #include <cstdarg> //For va_list.
14 #include <memory> //For unique_ptr.
18 Validator::Validator()
19 : valid_(nullptr), exception_(nullptr)
23 Validator::~Validator()
28 void Validator::initialize_valid()
30 // valid_ is used only by DtdValidator.
31 //TODO: When we can break ABI, move valid_ to DtdValidator.
34 //Tell the validation context about the callbacks:
35 valid_->error = &callback_validity_error;
36 valid_->warning = &callback_validity_warning;
38 //Allow the callback_validity_*() methods to retrieve the C++ instance:
39 valid_->userData = this;
42 //Clear these temporary buffers too:
43 validate_error_.erase();
44 validate_warning_.erase();
47 void Validator::release_underlying()
51 valid_->userData = nullptr; //Not really necessary.
53 xmlFreeValidCtxt(valid_);
58 void Validator::on_validity_error(const Glib::ustring& message)
60 //Throw an exception later when the whole message has been received:
61 validate_error_ += message;
64 void Validator::on_validity_warning(const Glib::ustring& message)
66 //Throw an exception later when the whole message has been received:
67 validate_warning_ += message;
70 void Validator::check_for_validity_messages()
72 Glib::ustring msg(exception_ ? exception_->what() : "");
73 bool validity_msg = false;
75 if (!validate_error_.empty())
78 msg += "\nValidity error:\n" + validate_error_;
79 validate_error_.erase();
82 if (!validate_warning_.empty())
85 msg += "\nValidity warning:\n" + validate_warning_;
86 validate_warning_.erase();
92 exception_ = new validity_error(msg);
96 void Validator::callback_validity_error(void* valid_, const char* msg, ...)
98 auto validator = static_cast<Validator*>(valid_);
102 //Convert the ... to a string:
104 char buff[1024]; //TODO: Larger/Shared
107 vsnprintf(buff, sizeof(buff)/sizeof(buff[0]), msg, arg);
112 validator->on_validity_error(Glib::ustring(buff));
114 catch(const exception& e)
116 validator->handleException(e);
120 validator->handleException(wrapped_exception(std::current_exception()));
125 void Validator::callback_validity_warning(void* valid_, const char* msg, ...)
127 auto validator = static_cast<Validator*>(valid_);
131 //Convert the ... to a string:
133 char buff[1024]; //TODO: Larger/Shared
136 vsnprintf(buff, sizeof(buff)/sizeof(buff[0]), msg, arg);
141 validator->on_validity_warning(Glib::ustring(buff));
143 catch(const exception& e)
145 validator->handleException(e);
149 validator->handleException(wrapped_exception(std::current_exception()));
154 void Validator::handleException(const exception& e)
157 exception_ = e.Clone();
159 // Don't delete the DTD validation context or schema validation context
160 // while validating. It would cause accesses to deallocated memory in libxml2
161 // functions after the return from Validator::callback_validity_...().
162 // Parser::handleException() calls xmlStopParser(), but there is no
163 // xmlStopValidator() or similar function to call here.
164 // We don't throw the exception here, since it would have to pass through
165 // C functions. That's not guaranteed to work. It might work, but it depends
166 // on the C compiler and the options used when building libxml2.
168 //release_underlying();
171 void Validator::check_for_exception()
173 check_for_validity_messages();
177 std::unique_ptr<exception> tmp(exception_);
178 exception_ = nullptr;