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