Commit non-working, work-in-progress
[mono.git] / eglib / src / gmarkup.c
1 /*
2  * gmakrup.c: Minimal XML markup reader.
3  *
4  * Unlike the GLib one, this can not be restarted with more text
5  * as the Mono use does not require it
6  *
7  * Author:
8  *   Miguel de Icaza (miguel@novell.com)
9  *
10  * (C) 2006 Novell, Inc.
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining
13  * a copy of this software and associated documentation files (the
14  * "Software"), to deal in the Software without restriction, including
15  * without limitation the rights to use, copy, modify, merge, publish,
16  * distribute, sublicense, and/or sell copies of the Software, and to
17  * permit persons to whom the Software is furnished to do so, subject to
18  * the following conditions:
19  *
20  * The above copyright notice and this permission notice shall be
21  * included in all copies or substantial portions of the Software.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30  */
31 #include <stdio.h>
32 #include <glib.h>
33
34 #define set_error(msg...) do { if (error != NULL) *error = g_error_new (1, 1, msg); } while (0);
35
36 typedef enum {
37         START,
38 } ParseState;
39
40 struct _GMarkupParseContext {
41         GMarkupParser  parser;
42         gpointer       user_data;
43         GDestroyNotify user_data_dnotify;
44         ParseState     state;
45 };
46
47 GMarkupParseContext *
48 g_markup_parse_context_new (const GMarkupParser *parser,
49                             GMarkupParseFlags flags,
50                             gpointer user_data,
51                             GDestroyNotify user_data_dnotify)
52 {
53         GMarkupParseContext *context = g_new0 (GMarkupParseContext, 1);
54
55         context->parser = *parser;
56         context->user_data = user_data;
57         context->user_data_dnotify = user_data_dnotify;
58
59         return context;
60 }
61
62 void
63 g_markup_parse_context_free (GMarkupParseContext *context)
64 {
65         g_free (context);
66 }
67
68 gboolean
69 g_markup_parse_context_parse (GMarkupParseContext *context,
70                               const gchar *text, gssize text_len, GError **error)
71 {
72         char *p, *end;
73         
74         g_return_val_if_fail (context != NULL, FALSE);
75         g_return_val_if_fail (text != NULL, FALSE);
76         g_return_val_if_fail (text_len >= 0, FALSE);
77
78         end = text + text_len;
79         
80         for (p = text; p < end; p++){
81                 char c = *p;
82                 
83                 switch (context->state){
84                 case START:
85                         if (c == ' ' || c == '\t' || c == '\f' || c == '\n')
86                                 continue;
87                         if (c == '<'){
88                                 context->state = START_ELEMENT;
89                                 continue;
90                         }
91                         set_error ("Expected < to start the document");
92                         
93                         return FALSE;
94
95
96                 case START_ELEMENT: {
97                         char *element_start = p;
98                         char **names, *values;
99
100                         if (!(isascii (*p) && isalpha (*p)))
101                                 set_error ("Must start with a letter");
102                         
103                         for (++p; p < end && isalnum (*p); p++)
104                                 ;
105                         if (p == end){
106                                 set_error ("Expected an element");
107                                 return FALSE;
108                         }
109                         for (; p < end && isspace (*p); p++)
110                                 ;
111                         if (p == end){
112                                 set_error ("Unfinished element");
113                                 return FALSE;
114                         }
115                         p = parse_attributes (p, end, &names, &values);
116                         if (p == end){
117                                 set_error ("unfinished element");
118                                 return FALSE;
119                         }
120                         
121                 }
122                 }
123         }
124 }
125