]> mj.ucw.cz Git - libucw.git/blob - xml/internals.h
XML: ABI cleanup
[libucw.git] / xml / internals.h
1 /*
2  *      UCW Library -- A simple XML parser
3  *
4  *      (c) 2007--2008 Pavel Charvat <pchar@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #ifndef _UCW_XML_INTERNALS_H
11 #define _UCW_XML_INTERNALS_H
12
13 #include <xml/xml.h>
14 #include <xml/dtd.h>
15
16 #ifdef CONFIG_UCW_CLEAN_ABI
17 #define xml_attrs_table_cleanup ucw_xml_attrs_table_cleanup
18 #define xml_attrs_table_init ucw_xml_attrs_table_init
19 #define xml_fatal_expected ucw_xml_fatal_expected
20 #define xml_fatal_expected_quot ucw_xml_fatal_expected_quot
21 #define xml_fatal_expected_white ucw_xml_fatal_expected_white
22 #define xml_fatal_nested ucw_xml_fatal_nested
23 #define xml_hash_new ucw_xml_hash_new
24 #define xml_parse_attr_list_decl ucw_xml_parse_attr_list_decl
25 #define xml_parse_attr_value ucw_xml_parse_attr_value
26 #define xml_parse_char_ref ucw_xml_parse_char_ref
27 #define xml_parse_element_decl ucw_xml_parse_element_decl
28 #define xml_parse_entity_decl ucw_xml_parse_entity_decl
29 #define xml_parse_eq ucw_xml_parse_eq
30 #define xml_parse_name ucw_xml_parse_name
31 #define xml_parse_nmtoken ucw_xml_parse_nmtoken
32 #define xml_parse_notation_decl ucw_xml_parse_notation_decl
33 #define xml_parse_pe_ref ucw_xml_parse_pe_ref
34 #define xml_parse_pubid_literal ucw_xml_parse_pubid_literal
35 #define xml_parse_system_literal ucw_xml_parse_system_literal
36 #define xml_pop_comment ucw_xml_pop_comment
37 #define xml_pop_pi ucw_xml_pop_pi
38 #define xml_push_comment ucw_xml_push_comment
39 #define xml_push_entity ucw_xml_push_entity
40 #define xml_push_pi ucw_xml_push_pi
41 #define xml_push_source ucw_xml_push_source
42 #define xml_refill ucw_xml_refill
43 #define xml_skip_comment ucw_xml_skip_comment
44 #define xml_skip_internal_subset ucw_xml_skip_internal_subset
45 #define xml_skip_name ucw_xml_skip_name
46 #define xml_skip_pi ucw_xml_skip_pi
47 #define xml_sources_cleanup ucw_xml_sources_cleanup
48 #define xml_spout_chars ucw_xml_spout_chars
49 #define xml_throw ucw_xml_throw
50 #define xml_validate_attr ucw_xml_validate_attr
51 #endif
52
53 /*** Debugging ***/
54
55 #ifdef LOCAL_DEBUG
56 #define TRACE(c, f, p...) do { DBG("XML %u: " f, xml_row(c), ##p); } while(0)
57 #else
58 #define TRACE(c, f, p...) do {} while(0)
59 #endif
60
61 /*** Error handling ***/
62
63 void NONRET xml_throw(struct xml_context *ctx);
64
65 /*** Memory management ***/
66
67 struct xml_stack {
68   struct xml_stack *next;
69   struct mempool_state state;
70   uint flags;
71 };
72
73 static inline void *xml_do_push(struct xml_context *ctx, uint size)
74 {
75   /* Saves ctx->stack and ctx->flags state */
76   struct mempool_state state;
77   mp_save(ctx->stack, &state);
78   struct xml_stack *s = mp_alloc(ctx->stack, size);
79   s->state = state;
80   s->flags = ctx->flags;
81   s->next = ctx->stack_list;
82   ctx->stack_list = s;
83   return s;
84 }
85
86 static inline void xml_do_pop(struct xml_context *ctx, struct xml_stack *s)
87 {
88   /* Restore ctx->stack and ctx->flags state */
89   ctx->stack_list = s->next;
90   ctx->flags = s->flags;
91   mp_restore(ctx->stack, &s->state);
92 }
93
94 static inline void xml_push(struct xml_context *ctx)
95 {
96   TRACE(ctx, "push");
97   xml_do_push(ctx, sizeof(struct xml_stack));
98 }
99
100 static inline void xml_pop(struct xml_context *ctx)
101 {
102   TRACE(ctx, "pop");
103   ASSERT(ctx->stack_list);
104   xml_do_pop(ctx, ctx->stack_list);
105 }
106
107 struct xml_dom_stack {
108   struct xml_stack stack;
109   struct mempool_state state;
110 };
111
112 static inline struct xml_node *xml_push_dom(struct xml_context *ctx, struct mempool_state *state)
113 {
114   /* Create a new DOM node */
115   TRACE(ctx, "push_dom");
116   struct xml_dom_stack *s = xml_do_push(ctx, sizeof(*s));
117   if (state)
118     s->state = *state;
119   else
120     mp_save(ctx->pool, &s->state);
121   struct xml_node *n = mp_alloc(ctx->pool, sizeof(*n));
122   n->user = NULL;
123   if (n->parent = ctx->node)
124     clist_add_tail(&n->parent->sons, &n->n);
125   return ctx->node = n;
126 }
127
128 static inline void xml_pop_dom(struct xml_context *ctx, uint free)
129 {
130   /* Leave DOM subtree */
131   TRACE(ctx, "pop_dom");
132   ASSERT(ctx->node);
133   struct xml_node *p = ctx->node->parent;
134   struct xml_dom_stack *s = (void *)ctx->stack_list;
135   if (free)
136     {
137       /* See xml_pop_element() for cleanup of attribute hash table */
138       if (p)
139         clist_remove(&ctx->node->n);
140       mp_restore(ctx->pool, &s->state);
141     }
142   ctx->node = p;
143   xml_do_pop(ctx, &s->stack);
144 }
145
146 #define XML_HASH_HDR_SIZE ALIGN_TO(sizeof(void *), CPU_STRUCT_ALIGN)
147 #define XML_HASH_GIVE_ALLOC struct HASH_PREFIX(table); \
148   static inline void *HASH_PREFIX(alloc)(struct HASH_PREFIX(table) *t, uint size) \
149   { return mp_alloc(*(void **)((void *)t - XML_HASH_HDR_SIZE), size); } \
150   static inline void HASH_PREFIX(free)(struct HASH_PREFIX(table) *t UNUSED, void *p UNUSED) {}
151
152 void *xml_hash_new(struct mempool *pool, uint size);
153
154 void xml_spout_chars(struct fastbuf *fb);
155
156 /*** Reading of document/external entities ***/
157
158 void NONRET xml_fatal_nested(struct xml_context *ctx);
159
160 static inline void xml_inc(struct xml_context *ctx)
161 {
162   /* Called after the first character of a block */
163   TRACE(ctx, "inc");
164   ctx->depth++;
165 }
166
167 static inline void xml_dec(struct xml_context *ctx)
168 {
169   /* Called after the last character of a block */
170   TRACE(ctx, "dec");
171   if (unlikely(!ctx->depth--))
172     xml_fatal_nested(ctx);
173 }
174
175 #include "obj/xml/unicat.h"
176
177 static inline uint xml_char_cat(uint c)
178 {
179   if (c < 0x10000)
180     return 1U << ucw_xml_char_tab1[(c & 0xff) + ucw_xml_char_tab2[c >> 8]];
181   else if (likely(c < 0x110000))
182     return 1U << ucw_xml_char_tab3[c >> 16];
183   else
184     return 1;
185 }
186
187 static inline uint xml_ascii_cat(uint c)
188 {
189   return ucw_xml_char_tab1[c];
190 }
191
192 struct xml_source *xml_push_source(struct xml_context *ctx);
193 void xml_push_entity(struct xml_context *ctx, struct xml_dtd_entity *ent);
194
195 void xml_refill(struct xml_context *ctx);
196
197 static inline uint xml_peek_char(struct xml_context *ctx)
198 {
199   if (ctx->bptr == ctx->bstop)
200     xml_refill(ctx);
201   return ctx->bptr[0];
202 }
203
204 static inline uint xml_peek_cat(struct xml_context *ctx)
205 {
206   if (ctx->bptr == ctx->bstop)
207     xml_refill(ctx);
208   return ctx->bptr[1];
209 }
210
211 static inline uint xml_get_char(struct xml_context *ctx)
212 {
213   uint c = xml_peek_char(ctx);
214   ctx->bptr += 2;
215   return c;
216 }
217
218 static inline uint xml_get_cat(struct xml_context *ctx)
219 {
220   uint c = xml_peek_cat(ctx);
221   ctx->bptr += 2;
222   return c;
223 }
224
225 static inline uint xml_last_char(struct xml_context *ctx)
226 {
227   return ctx->bptr[-2];
228 }
229
230 static inline uint xml_last_cat(struct xml_context *ctx)
231 {
232   return ctx->bptr[-1];
233 }
234
235 static inline uint xml_skip_char(struct xml_context *ctx)
236 {
237   uint c = ctx->bptr[0];
238   ctx->bptr += 2;
239   return c;
240 }
241
242 static inline uint xml_unget_char(struct xml_context *ctx)
243 {
244   return *(ctx->bptr -= 2);
245 }
246
247 void xml_sources_cleanup(struct xml_context *ctx);
248
249 /*** Parsing ***/
250
251 void NONRET xml_fatal_expected(struct xml_context *ctx, uint c);
252 void NONRET xml_fatal_expected_white(struct xml_context *ctx);
253 void NONRET xml_fatal_expected_quot(struct xml_context *ctx);
254
255 static inline uint xml_parse_white(struct xml_context *ctx, uint mandatory)
256 {
257   /* mandatory=1 -> S ::= (#x20 | #x9 | #xD | #xA)+
258    * mandatory=0 -> S? */
259   uint cnt = 0;
260   while (xml_peek_cat(ctx) & XML_CHAR_WHITE)
261     {
262       xml_skip_char(ctx);
263       cnt++;
264     }
265   if (unlikely(mandatory && !cnt))
266     xml_fatal_expected_white(ctx);
267   return cnt;
268 }
269
270 static inline void xml_parse_char(struct xml_context *ctx, uint c)
271 {
272   /* Consumes a given Unicode character */
273   if (unlikely(c != xml_get_char(ctx)))
274     xml_fatal_expected(ctx, c);
275 }
276
277 static inline void xml_parse_seq(struct xml_context *ctx, const char *seq)
278 {
279   /* Consumes a given sequence of ASCII characters */
280   while (*seq)
281     xml_parse_char(ctx, *seq++);
282 }
283
284 void xml_parse_eq(struct xml_context *ctx);
285
286 static inline uint xml_parse_quote(struct xml_context *ctx)
287 {
288   /* "'" | '"' */
289   uint c = xml_get_char(ctx);
290   if (unlikely(c != '\'' && c != '\"'))
291     xml_fatal_expected_quot(ctx);
292   return c;
293 }
294
295 char *xml_parse_name(struct xml_context *ctx, struct mempool *pool);
296 void xml_skip_name(struct xml_context *ctx);
297 char *xml_parse_nmtoken(struct xml_context *ctx, struct mempool *pool);
298
299 char *xml_parse_system_literal(struct xml_context *ctx, struct mempool *pool);
300 char *xml_parse_pubid_literal(struct xml_context *ctx, struct mempool *pool);
301
302 uint xml_parse_char_ref(struct xml_context *ctx);
303 void xml_parse_pe_ref(struct xml_context *ctx);
304
305 char *xml_parse_attr_value(struct xml_context *ctx, struct xml_dtd_attr *attr);
306
307 void xml_skip_internal_subset(struct xml_context *ctx);
308 void xml_parse_notation_decl(struct xml_context *ctx);
309 void xml_parse_entity_decl(struct xml_context *ctx);
310 void xml_parse_element_decl(struct xml_context *ctx);
311 void xml_parse_attr_list_decl(struct xml_context *ctx);
312
313 void xml_push_comment(struct xml_context *ctx);
314 void xml_pop_comment(struct xml_context *ctx);
315 void xml_skip_comment(struct xml_context *ctx);
316
317 void xml_push_pi(struct xml_context *ctx);
318 void xml_pop_pi(struct xml_context *ctx);
319 void xml_skip_pi(struct xml_context *ctx);
320
321 void xml_attrs_table_init(struct xml_context *ctx);
322 void xml_attrs_table_cleanup(struct xml_context *ctx);
323
324 void xml_validate_attr(struct xml_context *ctx, struct xml_dtd_attr *dtd, char *value);
325
326 #endif