new files from sakari, missed last time
[ardour.git] / libs / glibmm2 / glib / src / markup.ccg
1 // -*- c++ -*-
2 /* $Id: markup.ccg,v 1.5 2006/10/04 12:04:09 murrayc Exp $ */
3
4 /* Copyright (C) 2002 The gtkmm Development Team
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the Free
18  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include <glibmm/markup.h>
22 #include <glibmm/exceptionhandler.h>
23 #include <glibmm/utility.h>
24 #include <glib.h>
25
26
27 namespace Glib
28 {
29
30 namespace Markup
31 {
32
33 Glib::ustring escape_text(const Glib::ustring& text)
34 {
35   const Glib::ScopedPtr<char> buf (g_markup_escape_text(text.data(), text.bytes()));
36   return Glib::ustring(buf.get());
37 }
38
39
40 /**** Glib::Markup::AttributeKeyLess ***************************************/
41
42 bool AttributeKeyLess::operator()(const Glib::ustring& lhs, const Glib::ustring& rhs) const
43 {
44   return (lhs.raw() < rhs.raw());
45 }
46
47
48 /**** Glib::Markup::ParserCallbacks ****************************************/
49
50 class ParserCallbacks
51 {
52 public:
53   static const GMarkupParser vfunc_table;
54
55   static void start_element(GMarkupParseContext* context,
56                             const char*          element_name,
57                             const char**         attribute_names,
58                             const char**         attribute_values,
59                             void*                user_data,
60                             GError**             error);
61
62   static void end_element(GMarkupParseContext* context,
63                           const char*          element_name,
64                           void*                user_data,
65                           GError**             error);
66
67   static void text(GMarkupParseContext* context,
68                    const char*          text,
69                    gsize                text_len,  
70                    void*                user_data,
71                    GError**             error);
72
73   static void passthrough(GMarkupParseContext* context,
74                           const char*          passthrough_text,
75                           gsize                text_len,  
76                           void*                user_data,
77                           GError**             error);
78
79   static void error(GMarkupParseContext* context,
80                     GError*              error,
81                     void*                user_data);
82 };
83
84
85 const GMarkupParser ParserCallbacks::vfunc_table =
86 {
87   &ParserCallbacks::start_element,
88   &ParserCallbacks::end_element,
89   &ParserCallbacks::text,
90   &ParserCallbacks::passthrough,
91   &ParserCallbacks::error,
92 };
93
94 void ParserCallbacks::start_element(GMarkupParseContext* context,
95                                     const char*          element_name,
96                                     const char**         attribute_names,
97                                     const char**         attribute_values,
98                                     void*                user_data,
99                                     GError**             error)
100 {
101   if(!&error) error = error; //Avoid an unused parameter warning when GLIBMM_EXCEPTIONS_ENABLED is used.
102
103   ParseContext& cpp_context = *static_cast<ParseContext*>(user_data);
104   g_return_if_fail(context == cpp_context.gobj());
105
106   #ifdef GLIBMM_EXCEPTIONS_ENABLED
107   try
108   {
109   #endif //GLIBMM_EXCEPTIONS_ENABLED
110     Parser::AttributeMap attributes;
111
112     if(attribute_names && attribute_values)
113     {
114       const char *const * pname  = attribute_names;
115       const char *const * pvalue = attribute_values;
116
117       for(; *pname && *pvalue; ++pname, ++pvalue)
118         attributes.insert(Parser::AttributeMap::value_type(*pname, *pvalue));
119
120       g_return_if_fail(*pname == 0 && *pvalue == 0);
121     }
122
123     cpp_context.get_parser()->on_start_element(cpp_context, element_name, attributes);
124   #ifdef GLIBMM_EXCEPTIONS_ENABLED
125   }
126   catch(MarkupError& err)
127   {
128     err.propagate(error);
129   }
130   catch(...)
131   {
132     Glib::exception_handlers_invoke();
133   }
134   #endif //GLIBMM_EXCEPTIONS_ENABLED
135 }
136
137 void ParserCallbacks::end_element(GMarkupParseContext* context,
138                                   const char*          element_name,
139                                   void*                user_data,
140                                   GError**             error)
141 {
142   if(!&error) error = error; //Avoid an unused parameter warning when GLIBMM_EXCEPTIONS_ENABLED is used.
143
144   ParseContext& cpp_context = *static_cast<ParseContext*>(user_data);
145   g_return_if_fail(context == cpp_context.gobj());
146
147   #ifdef GLIBMM_EXCEPTIONS_ENABLED
148   try
149   {
150   #endif //GLIBMM_EXCEPTIONS_ENABLED
151     cpp_context.get_parser()->on_end_element(cpp_context, element_name);
152   #ifdef GLIBMM_EXCEPTIONS_ENABLED
153   }
154   catch(MarkupError& err)
155   {
156     err.propagate(error);
157   }
158   catch(...)
159   {
160     Glib::exception_handlers_invoke();
161   }
162   #endif //GLIBMM_EXCEPTIONS_ENABLED
163 }
164
165 void ParserCallbacks::text(GMarkupParseContext* context,
166                            const char*          text,
167                            gsize                text_len,  
168                            void*                user_data,
169                            GError**             error)
170 {
171   if(!&error) error = error; //Avoid an unused parameter warning when GLIBMM_EXCEPTIONS_ENABLED is used.
172
173   ParseContext& cpp_context = *static_cast<ParseContext*>(user_data);
174   g_return_if_fail(context == cpp_context.gobj());
175
176   #ifdef GLIBMM_EXCEPTIONS_ENABLED
177   try
178   {
179   #endif //GLIBMM_EXCEPTIONS_ENABLED
180     cpp_context.get_parser()->on_text(cpp_context, Glib::ustring(text, text + text_len));
181   #ifdef GLIBMM_EXCEPTIONS_ENABLED
182   }
183   catch(MarkupError& err)
184   {
185     err.propagate(error);
186   }
187   catch(...)
188   {
189     Glib::exception_handlers_invoke();
190   }
191   #endif //GLIBMM_EXCEPTIONS_ENABLED
192 }
193
194 void ParserCallbacks::passthrough(GMarkupParseContext* context,
195                                   const char*          passthrough_text,
196                                   gsize                text_len,  
197                                   void*                user_data,
198                                   GError**             error)
199 {
200   if(!&error) error = error; //Avoid an unused parameter warning when GLIBMM_EXCEPTIONS_ENABLED is used.
201
202   ParseContext& cpp_context = *static_cast<ParseContext*>(user_data);
203   g_return_if_fail(context == cpp_context.gobj());
204
205   #ifdef GLIBMM_EXCEPTIONS_ENABLED
206   try
207   {
208   #endif //GLIBMM_EXCEPTIONS_ENABLED
209     cpp_context.get_parser()->on_passthrough(
210         cpp_context, Glib::ustring(passthrough_text, passthrough_text + text_len));
211   #ifdef GLIBMM_EXCEPTIONS_ENABLED
212   }
213   catch(MarkupError& err)
214   {
215     err.propagate(error);
216   }
217   catch(...)
218   {
219     Glib::exception_handlers_invoke();
220   }
221   #endif //GLIBMM_EXCEPTIONS_ENABLED
222 }
223
224 void ParserCallbacks::error(GMarkupParseContext* context,
225                             GError*              error,
226                             void*                user_data)
227 {
228   ParseContext& cpp_context = *static_cast<ParseContext*>(user_data);
229
230   g_return_if_fail(context == cpp_context.gobj());
231   g_return_if_fail(error->domain == G_MARKUP_ERROR);
232
233   #ifdef GLIBMM_EXCEPTIONS_ENABLED
234   try
235   {
236   #endif //GLIBMM_EXCEPTIONS_ENABLED
237     cpp_context.get_parser()->on_error(cpp_context, MarkupError(g_error_copy(error)));
238   #ifdef GLIBMM_EXCEPTIONS_ENABLED
239   }
240   catch(...)
241   {
242     Glib::exception_handlers_invoke();
243   }
244   #endif //GLIBMM_EXCEPTIONS_ENABLED
245 }
246
247
248 /**** Glib::Markup::Parser *************************************************/
249
250 Parser::Parser()
251 {}
252
253 Parser::~Parser()
254 {}
255
256 void Parser::on_start_element(ParseContext&, const Glib::ustring&, const Parser::AttributeMap&)
257 {}
258
259 void Parser::on_end_element(ParseContext&, const Glib::ustring&)
260 {}
261
262 void Parser::on_text(ParseContext&, const Glib::ustring&)
263 {}
264
265 void Parser::on_passthrough(ParseContext&, const Glib::ustring&)
266 {}
267
268 void Parser::on_error(ParseContext&, const MarkupError&)
269 {}
270
271
272 /**** Glib::Markup::ParseContext *******************************************/
273
274 ParseContext::ParseContext(Parser& parser, ParseFlags flags)
275 :
276   parser_  (&parser),
277   gobject_ (g_markup_parse_context_new(&ParserCallbacks::vfunc_table, (GMarkupParseFlags) flags,
278                                        this, &ParseContext::destroy_notify_callback))
279 {}
280
281 ParseContext::~ParseContext()
282 {
283   parser_ = 0;
284   g_markup_parse_context_free(gobject_);
285 }
286
287 void ParseContext::parse(const Glib::ustring& text)
288 {
289   GError* error = 0;
290   g_markup_parse_context_parse(gobject_, text.data(), text.bytes(), &error);
291
292   if(error)
293     Glib::Error::throw_exception(error);
294 }
295
296 void ParseContext::parse(const char* text_begin, const char* text_end)
297 {
298   GError* error = 0;
299   g_markup_parse_context_parse(gobject_, text_begin, text_end - text_begin, &error);
300
301   if(error)
302     Glib::Error::throw_exception(error);
303 }
304
305 void ParseContext::end_parse()
306 {
307   GError* error = 0;
308   g_markup_parse_context_end_parse(gobject_, &error);
309
310   if(error)
311     Glib::Error::throw_exception(error);
312 }
313
314 Glib::ustring ParseContext::get_element() const
315 {
316   const char *const element_name = g_markup_parse_context_get_element(gobject_);
317   return (element_name) ? Glib::ustring(element_name) : Glib::ustring();
318 }
319
320 int ParseContext::get_line_number() const
321 {
322   int line_number = 0;
323   g_markup_parse_context_get_position(gobject_, &line_number, 0);
324   return line_number;
325 }
326
327 int ParseContext::get_char_number() const
328 {
329   int char_number = 0;
330   g_markup_parse_context_get_position(gobject_, 0, &char_number);
331   return char_number;
332 }
333
334 // static
335 void ParseContext::destroy_notify_callback(void* data)
336 {
337   ParseContext *const self = static_cast<ParseContext*>(data);
338
339   // Detect premature destruction.
340   g_return_if_fail(self->parser_ == 0);
341 }
342
343 } // namespace Markup
344
345 } // namespace Glib
346