1 /********************************************************************
2  * sixtp-to-dom-parser.c                                            *
3  * Copyright 2001 Gnumatic, Inc.                                    *
4  *                                                                  *
5  * This program is free software; you can redistribute it and/or    *
6  * modify it under the terms of the GNU General Public License as   *
7  * published by the Free Software Foundation; either version 2 of   *
8  * the License, or (at your option) any later version.              *
9  *                                                                  *
10  * This program is distributed in the hope that it will be useful,  *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
13  * GNU General Public License for more details.                     *
14  *                                                                  *
15  * You should have received a copy of the GNU General Public License*
16  * along with this program; if not, contact:                        *
17  *                                                                  *
18  * Free Software Foundation           Voice:  +1-617-542-5942       *
19  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
20  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
21  *                                                                  *
22  ********************************************************************/
23 extern "C"
24 {
25 #include <config.h>
26 #include <ctype.h>
27 }
28 
29 #include <glib.h>
30 
31 #include "sixtp-parsers.h"
32 #include "sixtp-utils.h"
33 #include "sixtp.h"
34 
35 static xmlNsPtr global_namespace = NULL;
36 
37 /* Don't pass anything in the data_for_children value to this
38    function.  It'll cause a segfault */
dom_start_handler(GSList * sibling_data,gpointer parent_data,gpointer global_data,gpointer * data_for_children,gpointer * result,const gchar * tag,gchar ** attrs)39 static gboolean dom_start_handler (
40     GSList* sibling_data, gpointer parent_data, gpointer global_data,
41     gpointer* data_for_children, gpointer* result, const gchar* tag,
42     gchar** attrs)
43 {
44     xmlNodePtr thing;
45     gchar** atptr = attrs;
46 
47     if (parent_data == NULL)
48     {
49         thing = xmlNewNode (global_namespace, BAD_CAST tag);
50         /* only publish the result if we're the parent */
51         *result = thing;
52     }
53     else
54     {
55         thing = xmlNewChild ((xmlNodePtr) parent_data,
56                              global_namespace,
57                              BAD_CAST tag,
58                              NULL);
59         *result = NULL;
60     }
61     *data_for_children = thing;
62 
63     if (attrs != NULL)
64     {
65         while (*atptr != 0)
66         {
67             gchar* attr0 = g_strdup (atptr[0]);
68             gchar* attr1 = g_strdup (atptr[1]);
69             xmlSetProp (thing, checked_char_cast (attr0),
70                         checked_char_cast (attr1));
71             g_free (attr0);
72             g_free (attr1);
73             atptr += 2;
74         }
75     }
76     return TRUE;
77 }
78 
79 static void
dom_fail_handler(gpointer data_for_children,GSList * data_from_children,GSList * sibling_data,gpointer parent_data,gpointer global_data,gpointer * result,const gchar * tag)80 dom_fail_handler (gpointer data_for_children,
81                   GSList* data_from_children,
82                   GSList* sibling_data,
83                   gpointer parent_data,
84                   gpointer global_data,
85                   gpointer* result,
86                   const gchar* tag)
87 {
88     if (*result) xmlFreeNode (static_cast<xmlNodePtr> (*result));
89 }
90 
dom_chars_handler(GSList * sibling_data,gpointer parent_data,gpointer global_data,gpointer * result,const char * text,int length)91 static gboolean dom_chars_handler (
92     GSList* sibling_data, gpointer parent_data, gpointer global_data,
93     gpointer* result, const char* text, int length)
94 {
95     if (length > 0)
96     {
97         gchar* newtext = g_strndup (text,length);
98         xmlNodeAddContentLen ((xmlNodePtr)parent_data,
99                               checked_char_cast (newtext), length);
100         g_free (newtext);
101     }
102     return TRUE;
103 }
104 
105 sixtp*
sixtp_dom_parser_new(sixtp_end_handler ender,sixtp_result_handler cleanup_result_by_default_func,sixtp_result_handler cleanup_result_on_fail_func)106 sixtp_dom_parser_new (sixtp_end_handler ender,
107                       sixtp_result_handler cleanup_result_by_default_func,
108                       sixtp_result_handler cleanup_result_on_fail_func)
109 {
110     sixtp* top_level;
111 
112     g_return_val_if_fail (ender, NULL);
113 
114     if (! (top_level =
115                sixtp_set_any (sixtp_new (), FALSE,
116                               SIXTP_START_HANDLER_ID, dom_start_handler,
117                               SIXTP_CHARACTERS_HANDLER_ID, dom_chars_handler,
118                               SIXTP_END_HANDLER_ID, ender,
119                               SIXTP_FAIL_HANDLER_ID, dom_fail_handler,
120                               SIXTP_NO_MORE_HANDLERS)))
121     {
122         return NULL;
123     }
124 
125     if (cleanup_result_by_default_func)
126     {
127         sixtp_set_cleanup_result (top_level, cleanup_result_by_default_func);
128     }
129 
130     if (cleanup_result_by_default_func)
131     {
132         sixtp_set_result_fail (top_level, cleanup_result_on_fail_func);
133     }
134 
135     if (!sixtp_add_sub_parser (top_level, SIXTP_MAGIC_CATCHER, top_level))
136     {
137         sixtp_destroy (top_level);
138         return NULL;
139     }
140 
141     return top_level;
142 }
143