diff options
Diffstat (limited to 'glib/src/markup.ccg')
-rw-r--r-- | glib/src/markup.ccg | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/glib/src/markup.ccg b/glib/src/markup.ccg new file mode 100644 index 00000000..2b61a358 --- /dev/null +++ b/glib/src/markup.ccg @@ -0,0 +1,318 @@ +// -*- c++ -*- +/* $Id$ */ + +/* 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 Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <glibmm/markup.h> +#include <glibmm/exceptionhandler.h> +#include <glibmm/utility.h> +#include <glib.h> + + +namespace Glib +{ + +namespace Markup +{ + +Glib::ustring escape_text(const Glib::ustring& text) +{ + const Glib::ScopedPtr<char> 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<ParseContext*>(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<ParseContext*>(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<ParseContext*>(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<ParseContext*>(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<ParseContext*>(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 (element_name) ? Glib::ustring(element_name) : Glib::ustring(); +} + +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<ParseContext*>(data); + + // Detect premature destruction. + g_return_if_fail(self->parser_ == 0); +} + +} // namespace Markup + +} // namespace Glib + |