a313924b77
git-svn-id: svn://localhost/ardour2/trunk@2644 d708f5d6-7413-0410-9779-e7cbd77b26cf
347 lines
9.9 KiB
C++
347 lines
9.9 KiB
C++
// -*- c++ -*-
|
|
/* $Id: markup.ccg,v 1.5 2006/10/04 12:04:09 murrayc Exp $ */
|
|
|
|
/* 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)
|
|
{
|
|
if(!&error) error = error; //Avoid an unused parameter warning when GLIBMM_EXCEPTIONS_ENABLED is used.
|
|
|
|
ParseContext& cpp_context = *static_cast<ParseContext*>(user_data);
|
|
g_return_if_fail(context == cpp_context.gobj());
|
|
|
|
#ifdef GLIBMM_EXCEPTIONS_ENABLED
|
|
try
|
|
{
|
|
#endif //GLIBMM_EXCEPTIONS_ENABLED
|
|
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);
|
|
#ifdef GLIBMM_EXCEPTIONS_ENABLED
|
|
}
|
|
catch(MarkupError& err)
|
|
{
|
|
err.propagate(error);
|
|
}
|
|
catch(...)
|
|
{
|
|
Glib::exception_handlers_invoke();
|
|
}
|
|
#endif //GLIBMM_EXCEPTIONS_ENABLED
|
|
}
|
|
|
|
void ParserCallbacks::end_element(GMarkupParseContext* context,
|
|
const char* element_name,
|
|
void* user_data,
|
|
GError** error)
|
|
{
|
|
if(!&error) error = error; //Avoid an unused parameter warning when GLIBMM_EXCEPTIONS_ENABLED is used.
|
|
|
|
ParseContext& cpp_context = *static_cast<ParseContext*>(user_data);
|
|
g_return_if_fail(context == cpp_context.gobj());
|
|
|
|
#ifdef GLIBMM_EXCEPTIONS_ENABLED
|
|
try
|
|
{
|
|
#endif //GLIBMM_EXCEPTIONS_ENABLED
|
|
cpp_context.get_parser()->on_end_element(cpp_context, element_name);
|
|
#ifdef GLIBMM_EXCEPTIONS_ENABLED
|
|
}
|
|
catch(MarkupError& err)
|
|
{
|
|
err.propagate(error);
|
|
}
|
|
catch(...)
|
|
{
|
|
Glib::exception_handlers_invoke();
|
|
}
|
|
#endif //GLIBMM_EXCEPTIONS_ENABLED
|
|
}
|
|
|
|
void ParserCallbacks::text(GMarkupParseContext* context,
|
|
const char* text,
|
|
gsize text_len,
|
|
void* user_data,
|
|
GError** error)
|
|
{
|
|
if(!&error) error = error; //Avoid an unused parameter warning when GLIBMM_EXCEPTIONS_ENABLED is used.
|
|
|
|
ParseContext& cpp_context = *static_cast<ParseContext*>(user_data);
|
|
g_return_if_fail(context == cpp_context.gobj());
|
|
|
|
#ifdef GLIBMM_EXCEPTIONS_ENABLED
|
|
try
|
|
{
|
|
#endif //GLIBMM_EXCEPTIONS_ENABLED
|
|
cpp_context.get_parser()->on_text(cpp_context, Glib::ustring(text, text + text_len));
|
|
#ifdef GLIBMM_EXCEPTIONS_ENABLED
|
|
}
|
|
catch(MarkupError& err)
|
|
{
|
|
err.propagate(error);
|
|
}
|
|
catch(...)
|
|
{
|
|
Glib::exception_handlers_invoke();
|
|
}
|
|
#endif //GLIBMM_EXCEPTIONS_ENABLED
|
|
}
|
|
|
|
void ParserCallbacks::passthrough(GMarkupParseContext* context,
|
|
const char* passthrough_text,
|
|
gsize text_len,
|
|
void* user_data,
|
|
GError** error)
|
|
{
|
|
if(!&error) error = error; //Avoid an unused parameter warning when GLIBMM_EXCEPTIONS_ENABLED is used.
|
|
|
|
ParseContext& cpp_context = *static_cast<ParseContext*>(user_data);
|
|
g_return_if_fail(context == cpp_context.gobj());
|
|
|
|
#ifdef GLIBMM_EXCEPTIONS_ENABLED
|
|
try
|
|
{
|
|
#endif //GLIBMM_EXCEPTIONS_ENABLED
|
|
cpp_context.get_parser()->on_passthrough(
|
|
cpp_context, Glib::ustring(passthrough_text, passthrough_text + text_len));
|
|
#ifdef GLIBMM_EXCEPTIONS_ENABLED
|
|
}
|
|
catch(MarkupError& err)
|
|
{
|
|
err.propagate(error);
|
|
}
|
|
catch(...)
|
|
{
|
|
Glib::exception_handlers_invoke();
|
|
}
|
|
#endif //GLIBMM_EXCEPTIONS_ENABLED
|
|
}
|
|
|
|
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);
|
|
|
|
#ifdef GLIBMM_EXCEPTIONS_ENABLED
|
|
try
|
|
{
|
|
#endif //GLIBMM_EXCEPTIONS_ENABLED
|
|
cpp_context.get_parser()->on_error(cpp_context, MarkupError(g_error_copy(error)));
|
|
#ifdef GLIBMM_EXCEPTIONS_ENABLED
|
|
}
|
|
catch(...)
|
|
{
|
|
Glib::exception_handlers_invoke();
|
|
}
|
|
#endif //GLIBMM_EXCEPTIONS_ENABLED
|
|
}
|
|
|
|
|
|
/**** 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
|
|
|