/* Copyright (C) 2002 The gtkmm Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include namespace Glib { namespace Markup { Glib::ustring escape_text(const Glib::ustring& text) { const Glib::ScopedPtr buf (g_markup_escape_text(text.data(), text.bytes())); return Glib::ustring(buf.get()); } /**** Glib::Markup::AttributeKeyLess ***************************************/ bool AttributeKeyLess::operator()(const Glib::ustring& lhs, const Glib::ustring& rhs) const { return (lhs.raw() < rhs.raw()); } /**** Glib::Markup::ParserCallbacks ****************************************/ class ParserCallbacks { public: static const GMarkupParser vfunc_table; static void start_element(GMarkupParseContext* context, const char* element_name, const char** attribute_names, const char** attribute_values, void* user_data, GError** error); static void end_element(GMarkupParseContext* context, const char* element_name, void* user_data, GError** error); static void text(GMarkupParseContext* context, const char* text, gsize text_len, void* user_data, GError** error); static void passthrough(GMarkupParseContext* context, const char* passthrough_text, gsize text_len, void* user_data, GError** error); static void error(GMarkupParseContext* context, GError* error, void* user_data); }; const GMarkupParser ParserCallbacks::vfunc_table = { &ParserCallbacks::start_element, &ParserCallbacks::end_element, &ParserCallbacks::text, &ParserCallbacks::passthrough, &ParserCallbacks::error, }; void ParserCallbacks::start_element(GMarkupParseContext* context, const char* element_name, const char** attribute_names, const char** attribute_values, void* user_data, GError** error) { ParseContext& cpp_context = *static_cast(user_data); g_return_if_fail(context == cpp_context.gobj()); try { Parser::AttributeMap attributes; if(attribute_names && attribute_values) { const char *const * pname = attribute_names; const char *const * pvalue = attribute_values; for(; *pname && *pvalue; ++pname, ++pvalue) attributes.insert(Parser::AttributeMap::value_type(*pname, *pvalue)); g_return_if_fail(*pname == 0 && *pvalue == 0); } cpp_context.get_parser()->on_start_element(cpp_context, element_name, attributes); } catch(MarkupError& err) { err.propagate(error); } catch(...) { Glib::exception_handlers_invoke(); } } void ParserCallbacks::end_element(GMarkupParseContext* context, const char* element_name, void* user_data, GError** error) { ParseContext& cpp_context = *static_cast(user_data); g_return_if_fail(context == cpp_context.gobj()); try { cpp_context.get_parser()->on_end_element(cpp_context, element_name); } catch(MarkupError& err) { err.propagate(error); } catch(...) { Glib::exception_handlers_invoke(); } } void ParserCallbacks::text(GMarkupParseContext* context, const char* text, gsize text_len, void* user_data, GError** error) { ParseContext& cpp_context = *static_cast(user_data); g_return_if_fail(context == cpp_context.gobj()); try { cpp_context.get_parser()->on_text(cpp_context, Glib::ustring(text, text + text_len)); } catch(MarkupError& err) { err.propagate(error); } catch(...) { Glib::exception_handlers_invoke(); } } void ParserCallbacks::passthrough(GMarkupParseContext* context, const char* passthrough_text, gsize text_len, void* user_data, GError** error) { ParseContext& cpp_context = *static_cast(user_data); g_return_if_fail(context == cpp_context.gobj()); try { cpp_context.get_parser()->on_passthrough( cpp_context, Glib::ustring(passthrough_text, passthrough_text + text_len)); } catch(MarkupError& err) { err.propagate(error); } catch(...) { Glib::exception_handlers_invoke(); } } void ParserCallbacks::error(GMarkupParseContext* context, GError* error, void* user_data) { ParseContext& cpp_context = *static_cast(user_data); g_return_if_fail(context == cpp_context.gobj()); g_return_if_fail(error->domain == G_MARKUP_ERROR); try { cpp_context.get_parser()->on_error(cpp_context, MarkupError(g_error_copy(error))); } catch(...) { Glib::exception_handlers_invoke(); } } /**** Glib::Markup::Parser *************************************************/ Parser::Parser() {} Parser::~Parser() {} void Parser::on_start_element(ParseContext&, const Glib::ustring&, const Parser::AttributeMap&) {} void Parser::on_end_element(ParseContext&, const Glib::ustring&) {} void Parser::on_text(ParseContext&, const Glib::ustring&) {} void Parser::on_passthrough(ParseContext&, const Glib::ustring&) {} void Parser::on_error(ParseContext&, const MarkupError&) {} /**** Glib::Markup::ParseContext *******************************************/ ParseContext::ParseContext(Parser& parser, ParseFlags flags) : parser_ (&parser), gobject_ (g_markup_parse_context_new(&ParserCallbacks::vfunc_table, (GMarkupParseFlags) flags, this, &ParseContext::destroy_notify_callback)) {} ParseContext::~ParseContext() { parser_ = 0; g_markup_parse_context_free(gobject_); } void ParseContext::parse(const Glib::ustring& text) { GError* error = 0; g_markup_parse_context_parse(gobject_, text.data(), text.bytes(), &error); if(error) Glib::Error::throw_exception(error); } void ParseContext::parse(const char* text_begin, const char* text_end) { GError* error = 0; g_markup_parse_context_parse(gobject_, text_begin, text_end - text_begin, &error); if(error) Glib::Error::throw_exception(error); } void ParseContext::end_parse() { GError* error = 0; g_markup_parse_context_end_parse(gobject_, &error); if(error) Glib::Error::throw_exception(error); } Glib::ustring ParseContext::get_element() const { const char *const element_name = g_markup_parse_context_get_element(gobject_); return convert_const_gchar_ptr_to_ustring(element_name); } int ParseContext::get_line_number() const { int line_number = 0; g_markup_parse_context_get_position(gobject_, &line_number, 0); return line_number; } int ParseContext::get_char_number() const { int char_number = 0; g_markup_parse_context_get_position(gobject_, 0, &char_number); return char_number; } // static void ParseContext::destroy_notify_callback(void* data) { ParseContext *const self = static_cast(data); // Detect premature destruction. g_return_if_fail(self->parser_ == 0); } } // namespace Markup } // namespace Glib