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