<libroxml  version="3.0.1" />
contact: tristan.lelong@libroxml.net
roxml_core.c
Go to the documentation of this file.
1 
12 #include <stdlib.h>
13 #include <string.h>
14 #include "roxml_core.h"
15 #include "roxml_file.h"
16 #include "roxml_buff.h"
17 #include "roxml_parser.h"
18 
19 #ifdef __DEBUG
20 unsigned int _nb_node = 0;
21 unsigned int _nb_attr = 0;
22 unsigned int _nb_text = 0;
23 #endif
24 
26 {
27  node_t *root = n;
28 
29  if (root == ROXML_INVALID_DOC)
30  return;
31 
32  while (root->prnt != NULL)
33  root = root->prnt;
34 
35  roxml_del_tree(root->chld);
36  roxml_del_tree(root->sibl);
37 
38  if ((root->type & ROXML_FILE) == ROXML_FILE)
39  roxml_close_file(root);
40  else
41  roxml_close_buff(root);
42 
43  roxml_free_node(root);
44 }
45 
46 ROXML_INT node_t *roxml_create_node(int pos, void *src, int type)
47 {
48  node_t *n = (node_t *)calloc(1, sizeof(node_t));
49  n->type = type;
50  n->src.src = src;
51  n->pos = pos;
52  n->end = pos;
53 
54  return n;
55 }
56 
65 ROXML_STATIC ROXML_INT void roxml_close_node(node_t *n, node_t *close)
66 {
67  if (n) {
68  n->end = close->pos;
69  free(close);
70 
71 #ifdef __DEBUG
72  if (n->type & ROXML_ELM_NODE)
73  _nb_node++;
74  if (n->type & ROXML_ATTR_NODE)
75  _nb_attr++;
76  if (n->type & ROXML_TXT_NODE)
77  _nb_text++;
78 #endif
79  }
80 }
81 
82 ROXML_INT void roxml_free_node(node_t *n)
83 {
84  if (!n)
85  return;
86 
87  if (n->type & ROXML_PENDING)
88  if (n->pos == 0)
89  free(n->src.buf);
90 
91  if (n->priv) {
92  unsigned char id = *(unsigned char *)n->priv;
93 
94  if (id == ROXML_REQTABLE_ID) {
95  xpath_tok_t *tok;
97 
98  roxml_lock_destroy(n);
99 
100  tok = table->next;
101  free(table);
102  while (tok) {
103  xpath_tok_t *to_delete = tok;
104  tok = tok->next;
105  free(to_delete);
106  }
107  } else if (id == ROXML_NS_ID) {
108  roxml_ns_t *ns = (roxml_ns_t *)n->priv;
109  free(ns);
110  }
111  }
112  free(n);
113 }
114 
115 ROXML_INT void roxml_del_tree(node_t *n)
116 {
117  if (n == NULL)
118  return;
119 
120  if (n != n->chld)
121  roxml_del_tree(n->chld);
122  if (n != n->sibl)
123  roxml_del_tree(n->sibl);
124  roxml_del_tree(n->attr);
125  roxml_free_node(n);
126 }
127 
128 ROXML_INT inline int roxml_is_separator(char sep)
129 {
130  int i = 0;
131  char separators[32] = "\r\t\n ";
132 
133  while (separators[i] != 0)
134  if (sep == separators[i++])
135  return 1;
136  return 0;
137 }
138 
146 ROXML_STATIC ROXML_INT void roxml_process_unaliased_ns(roxml_load_ctx_t *context)
147 {
148  if (context->nsdef) {
149  context->nsdef = 0;
150  context->candidat_arg->type |= ROXML_NS_NODE;
151 
152  if (context->candidat_node->ns && ((context->candidat_node->ns->type & ROXML_INVALID) == ROXML_INVALID))
153  roxml_free_node(context->candidat_node->ns);
154 
155  if (context->candidat_val->pos == context->candidat_val->end) {
156  context->candidat_node->ns = NULL;
157  context->candidat_arg->ns = NULL;
158  } else {
159  roxml_ns_t *ns = calloc(1, sizeof(roxml_ns_t) + 1);
160  ns->id = ROXML_NS_ID;
161  ns->alias = (char *)ns + sizeof(roxml_ns_t);
162 
163  context->candidat_arg->priv = ns;
164  context->candidat_arg->ns = context->candidat_arg;
165  context->candidat_node->ns = context->candidat_arg;
166 
167  context->namespaces = context->candidat_arg;
168  }
169  }
170 }
171 
180 ROXML_STATIC ROXML_INT void roxml_process_begin_node(roxml_load_ctx_t *context, int position)
181 {
182  if (context->candidat_txt) {
183 #ifdef IGNORE_EMPTY_TEXT_NODES
184  if (context->empty_text_node == 0) {
185 #endif /* IGNORE_EMPTY_TEXT_NODES */
186  node_t *to_be_closed =
187  roxml_create_node(position, context->src, ROXML_TXT_NODE | context->type);
188  context->candidat_txt = roxml_append_node(context->current_node, context->candidat_txt);
189  roxml_close_node(context->candidat_txt, to_be_closed);
190  context->current_node = context->candidat_txt->prnt;
191 #ifdef IGNORE_EMPTY_TEXT_NODES
192  } else {
193  roxml_free_node(context->candidat_txt);
194  }
195 #endif /* IGNORE_EMPTY_TEXT_NODES */
196  context->candidat_txt = NULL;
197  }
198  context->candidat_node = roxml_create_node(position, context->src, ROXML_ELM_NODE | context->type);
199 }
200 
201 ROXML_INT node_t *roxml_load(node_t *current_node, FILE *file, char *buffer)
202 {
203  int error = 0;
204  node_t *root = current_node;
205  roxml_load_ctx_t context;
206  roxml_parser_item_t *parser = NULL;
207 
208  memset(&context, 0, sizeof(roxml_load_ctx_t));
209  context.empty_text_node = 1;
210  context.current_node = current_node;
211 
212  parser = roxml_append_parser_item(parser, " ", _func_load_white);
213  parser = roxml_append_parser_item(parser, "<", _func_load_open_node);
214  parser = roxml_append_parser_item(parser, ">", _func_load_close_node);
215  parser = roxml_append_parser_item(parser, "/", _func_load_end_node);
216  parser = roxml_append_parser_item(parser, "'", _func_load_quoted);
217  parser = roxml_append_parser_item(parser, "\"", _func_load_dquoted);
218  parser = roxml_append_parser_item(parser, "\t", _func_load_white);
219  parser = roxml_append_parser_item(parser, "\n", _func_load_white);
220  parser = roxml_append_parser_item(parser, "\r", _func_load_white);
221  parser = roxml_append_parser_item(parser, "!", _func_load_open_spec_node);
222  parser = roxml_append_parser_item(parser, "]", _func_load_close_cdata);
223  parser = roxml_append_parser_item(parser, "-", _func_load_close_comment);
224  parser = roxml_append_parser_item(parser, "?", _func_load_close_pi);
225  parser = roxml_append_parser_item(parser, ":", _func_load_colon);
226  parser = roxml_append_parser_item(parser, "", _func_load_default);
227 
228  parser = roxml_parser_prepare(parser);
229 
230  if (file)
231  error = roxml_parse_file(&context, parser, file);
232  else
233  error = roxml_parse_buff(&context, parser, buffer);
234 
235  roxml_parser_free(parser);
236 
237  if (context.empty_text_node == 1)
238  roxml_free_node(context.candidat_txt);
239  current_node = NULL;
240 
241  if (error == 0) {
242  current_node = roxml_create_root(root);
243  } else {
244  roxml_close(root);
245  current_node = ROXML_INVALID_DOC;
246  }
247 
248  return current_node;
249 }
250 
252 {
253  xpath_tok_table_t *table = (xpath_tok_table_t *)calloc(1, sizeof(xpath_tok_table_t));
254 
255  table->id = ROXML_REQTABLE_ID;
256  table->ids[ROXML_REQTABLE_ID] = 1;
257 
258  n->priv = (void *)table;
259 
260  roxml_lock_init(n);
261 
262  return n;
263 }
264 
273 ROXML_STATIC ROXML_INT node_t *roxml_lookup_nsdef(node_t *nsdef, char *ns)
274 {
275  int len = 0;
276  char namespace[MAX_NAME_LEN];
277 
278  for (len = 0; ns[len] != '\0' && ns[len] != ':' && len < MAX_NAME_LEN; len++)
279  namespace[len] = ns[len];
280 
281  if (len == MAX_NAME_LEN)
282  return NULL; /* truncated */
283 
284  namespace[len] = '\0';
285 
286  while (nsdef) {
287  if (nsdef->priv && strcmp(namespace, ((roxml_ns_t *)nsdef->priv)->alias) == 0)
288  break;
289  nsdef = nsdef->next;
290  }
291  return nsdef;
292 }
293 
302 ROXML_STATIC ROXML_INT inline void roxml_set_type(node_t *n, int type)
303 {
305  n->type |= type;
306 }
307 
308 ROXML_INT node_t *roxml_set_parent(node_t *parent, node_t *n)
309 {
310  if (parent == NULL)
311  return NULL;
312 
313  n->prnt = parent;
314 
315  if (parent->ns && ((parent->ns->type & ROXML_INVALID) != ROXML_INVALID)
316  && parent->ns->priv && ((roxml_ns_t *)parent->ns->priv)->alias[0] == '\0')
317  if (n->ns == NULL)
318  n->ns = parent->ns;
319  return n;
320 }
321 
322 ROXML_STATIC ROXML_INT node_t *roxml_append_attr(node_t *parent, node_t *n)
323 {
324  if (parent->attr) {
325  node_t *attr = parent->attr;
326  while (attr->sibl)
327  attr = attr->sibl;
328  attr->sibl = n;
329  } else {
330  parent->attr = n;
331  }
332 
333  return n;
334 }
335 
336 ROXML_STATIC ROXML_INT node_t *roxml_append_other(node_t *parent, node_t *n)
337 {
338  if (parent->next)
339  parent->next->sibl = n;
340  else
341  parent->chld = n;
342  parent->next = n;
343 
344  return n;
345 }
346 
347 ROXML_INT node_t *roxml_append_node(node_t *parent, node_t *n)
348 {
349  if (!roxml_set_parent(parent, n))
350  return n;
351 
352  if (n->type & ROXML_ATTR_NODE)
353  roxml_append_attr(parent, n);
354  else
355  roxml_append_other(parent, n);
356 
357  return n;
358 }
359 
360 ROXML_INT int _func_load_quoted(roxml_parser_item_t *parser, char *chunk, void *data)
361 {
362 #ifdef DEBUG_PARSING
363  fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
364 #endif /* DEBUG_PARSING */
365  roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
366 
367  if (context->state != STATE_NODE_CONTENT && context->state != STATE_NODE_COMMENT) {
368  if (context->mode == MODE_COMMENT_NONE)
369  context->mode = MODE_COMMENT_QUOTE;
370  else if (context->mode == MODE_COMMENT_QUOTE)
371  context->mode = MODE_COMMENT_NONE;
372  }
373 
374  return 0;
375 }
376 
377 ROXML_INT int _func_load_dquoted(roxml_parser_item_t *parser, char *chunk, void *data)
378 {
379 #ifdef DEBUG_PARSING
380  fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
381 #endif /* DEBUG_PARSING */
382  roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
383 
384  if (context->state != STATE_NODE_CONTENT && context->state != STATE_NODE_COMMENT) {
385  if (context->mode == MODE_COMMENT_NONE)
386  context->mode = MODE_COMMENT_DQUOTE;
387  else if (context->mode == MODE_COMMENT_DQUOTE)
388  context->mode = MODE_COMMENT_NONE;
389  }
390 
391  return 0;
392 }
393 
394 ROXML_INT int _func_load_open_node(roxml_parser_item_t *parser, char *chunk, void *data)
395 {
396 #ifdef DEBUG_PARSING
397  fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
398 #endif /* DEBUG_PARSING */
399  int cur = 1;
400  roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
401 
402  switch (context->state) {
403  case STATE_NODE_CDATA:
404  case STATE_NODE_COMMENT:
405  break;
406  case STATE_NODE_ATTR:
407  case STATE_NODE_BEG:
408  if (context->mode == MODE_COMMENT_NONE)
409  ROXML_PARSE_ERROR("unexpected '<' within node definition");
410  break;
411  default:
412  context->state = STATE_NODE_BEG;
413  context->previous_state = STATE_NODE_BEG;
414  break;
415  }
416 
417  context->pos += cur;
418  return cur;
419 }
420 
421 ROXML_INT int _func_load_close_node(roxml_parser_item_t *parser, char *chunk, void *data)
422 {
423 #ifdef DEBUG_PARSING
424  fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
425 #endif /* DEBUG_PARSING */
426  int cur = 1;
427  roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
428 
429  switch (context->state) {
430  case STATE_NODE_NAME:
431  context->empty_text_node = 1;
432  context->current_node = roxml_append_node(context->current_node, context->candidat_node);
433  break;
434  case STATE_NODE_ATTR:
435  if ((context->mode != MODE_COMMENT_DQUOTE) && (context->mode != MODE_COMMENT_QUOTE)) {
436  if (context->inside_node_state == STATE_INSIDE_VAL) {
437  node_t *to_be_closed = NULL;
438  if (context->content_quoted) {
439  context->content_quoted = 0;
440  to_be_closed =
441  roxml_create_node(context->pos - 1, context->src,
442  ROXML_ATTR_NODE | context->type);
443  } else {
444  to_be_closed =
445  roxml_create_node(context->pos, context->src,
446  ROXML_ATTR_NODE | context->type);
447  }
448  roxml_close_node(context->candidat_val, to_be_closed);
449  }
450  context->current_node = roxml_append_node(context->current_node, context->candidat_node);
453  } else {
454  context->pos++;
455  return 1;
456  }
457  break;
458  case STATE_NODE_SINGLE:
459  if (context->doctype) {
460  context->doctype--;
461  if (context->doctype > 0) {
462  context->pos++;
463  return 1;
464  }
465  context->candidat_node->end = context->pos;
466  }
467  context->empty_text_node = 1;
468  context->current_node = roxml_append_node(context->current_node, context->candidat_node);
469  if (context->current_node->prnt != NULL) {
470  context->current_node = context->current_node->prnt;
471  }
473  break;
474  case STATE_NODE_END:
475  context->empty_text_node = 1;
476  roxml_close_node(context->current_node, context->candidat_node);
477  context->candidat_node = NULL;
478  if (context->current_node->prnt != NULL) {
479  context->current_node = context->current_node->prnt;
480  }
481  break;
482  case STATE_NODE_CDATA:
483  case STATE_NODE_CONTENT:
484  default:
485  context->pos++;
486  return 1;
487  break;
488  }
489 
490  if (context->candidat_node && context->candidat_node->ns
491  && ((context->candidat_node->ns->type & ROXML_INVALID) == ROXML_INVALID)) {
492  roxml_free_node(context->candidat_node->ns);
493  context->candidat_node->ns = NULL;
494  }
495 
496  context->state = STATE_NODE_CONTENT;
498  context->candidat_txt = roxml_create_node(context->pos + 1, context->src, ROXML_TXT_NODE | context->type);
499 #ifdef IGNORE_EMPTY_TEXT_NODES
500  while (chunk[cur] != '\0') {
501  if (chunk[cur] == '<') {
502  break;
503  } else if (!ROXML_WHITE(chunk[cur])) {
504  context->empty_text_node = 0;
505  break;
506  }
507  cur++;
508  }
509 #endif /* IGNORE_EMPTY_TEXT_NODES */
510  while ((chunk[cur] != '<') && (chunk[cur] != '\0'))
511  cur++;
512 
513  context->pos += cur;
514  return cur;
515 }
516 
517 ROXML_INT int _func_load_open_spec_node(roxml_parser_item_t *parser, char *chunk, void *data)
518 {
519 #ifdef DEBUG_PARSING
520  fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
521 #endif /* DEBUG_PARSING */
522  int cur = 1;
523 
524  roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
525 
526  if (context->state == STATE_NODE_BEG) {
527  if (strncmp(chunk, "!--", 3) == 0) {
528  cur = 3;
529  roxml_process_begin_node(context, context->pos - 1);
531  context->state = STATE_NODE_COMMENT;
532  while ((chunk[cur] != '-') && (chunk[cur] != '\0'))
533  cur++;
534  } else if (strncmp(chunk, "![CDATA[", 8) == 0) {
535  roxml_process_begin_node(context, context->pos - 1);
537  context->state = STATE_NODE_CDATA;
538  while ((chunk[cur] != '[') && (chunk[cur] != '\0'))
539  cur++;
540  } else {
541  if (context->doctype == 0) {
542  roxml_process_begin_node(context, context->pos - 1);
544  }
545  context->state = STATE_NODE_SINGLE;
547  context->doctype++;
548  }
549  }
550 
551  context->pos += cur;
552  return cur;
553 }
554 
555 ROXML_INT int _func_load_close_comment(roxml_parser_item_t *parser, char *chunk, void *data)
556 {
557 #ifdef DEBUG_PARSING
558  fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
559 #endif /* DEBUG_PARSING */
560  int cur = 1;
561  roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
562 
563  if (context->state == STATE_NODE_COMMENT) {
564  if (chunk[1] == '-') {
565  cur = 2;
566  context->state = STATE_NODE_SINGLE;
567  context->candidat_node->end = context->pos;
568  }
569  }
570 
571  context->pos += cur;
572  return cur;
573 }
574 
575 ROXML_INT int _func_load_close_cdata(roxml_parser_item_t *parser, char *chunk, void *data)
576 {
577 #ifdef DEBUG_PARSING
578  fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
579 #endif /* DEBUG_PARSING */
580  int cur = 1;
581  roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
582 
583  if (context->state == STATE_NODE_CDATA) {
584  if (chunk[1] == ']') {
585  cur = 2;
586  context->state = STATE_NODE_SINGLE;
587  context->candidat_node->pos += 9;
588  context->candidat_node->end = context->pos;
589  }
590  }
591 
592  context->pos += cur;
593  return cur;
594 }
595 
596 ROXML_INT int _func_load_close_pi(roxml_parser_item_t *parser, char *chunk, void *data)
597 {
598 #ifdef DEBUG_PARSING
599  fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
600 #endif /* DEBUG_PARSING */
601  int cur = 1;
602  roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
603 
604  if (context->state == STATE_NODE_BEG) {
605  cur = 1;
606  context->state = STATE_NODE_PI;
607  context->previous_state = STATE_NODE_PI;
608  roxml_process_begin_node(context, context->pos - 1);
610  // while((chunk[cur] != '?')&&(chunk[cur] != '\0')) { cur++; }
611  } else if (context->state == STATE_NODE_PI) {
612  if (context->mode == MODE_COMMENT_NONE) {
613  cur = 1;
614  context->candidat_node->end = context->pos;
615  context->previous_state = STATE_NODE_PI;
616  context->state = STATE_NODE_SINGLE;
617  }
618  }
619 
620  context->pos += cur;
621  return cur;
622 }
623 
624 ROXML_INT int _func_load_end_node(roxml_parser_item_t *parser, char *chunk, void *data)
625 {
626 #ifdef DEBUG_PARSING
627  fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
628 #endif /* DEBUG_PARSING */
629  int cur = 1;
630  roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
631 
632  switch (context->state) {
633  case STATE_NODE_BEG:
634  context->lvl--;
635  roxml_process_begin_node(context, context->pos - 1);
636  context->state = STATE_NODE_END;
637  if (context->lvl < 0)
638  ROXML_PARSE_ERROR("missing opening node");
639  break;
640  case STATE_NODE_NAME:
641  context->lvl--;
642  context->state = STATE_NODE_SINGLE;
643  break;
644  case STATE_NODE_ATTR:
645  if ((context->mode != MODE_COMMENT_DQUOTE) && (context->mode != MODE_COMMENT_QUOTE)) {
646  if (context->inside_node_state == STATE_INSIDE_VAL) {
647  node_t *to_be_closed = NULL;
648  if (context->content_quoted) {
649  context->content_quoted = 0;
650  to_be_closed =
651  roxml_create_node(context->pos - 1, context->src,
652  ROXML_ATTR_NODE | context->type);
653  } else {
654  to_be_closed =
655  roxml_create_node(context->pos, context->src,
656  ROXML_ATTR_NODE | context->type);
657  }
658  roxml_close_node(context->candidat_val, to_be_closed);
659  }
661  context->state = STATE_NODE_SINGLE;
662  context->lvl--;
663  }
664  break;
665  }
666 
667  context->pos += cur;
668  return cur;
669 }
670 
671 ROXML_INT int _func_load_white(roxml_parser_item_t *parser, char *chunk, void *data)
672 {
673 #ifdef DEBUG_PARSING
674  fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
675 #endif /* DEBUG_PARSING */
676  int cur = 1;
677  roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
678 
679  switch (context->state) {
680  case STATE_NODE_SINGLE:
681  context->state = context->previous_state;
682  break;
683  case STATE_NODE_NAME:
684  context->state = STATE_NODE_ATTR;
686  break;
687  case STATE_NODE_ATTR:
688  if (context->mode == MODE_COMMENT_NONE) {
689  if (context->inside_node_state == STATE_INSIDE_VAL) {
690  node_t *to_be_closed = NULL;
691  if (context->content_quoted) {
692  context->content_quoted = 0;
693  to_be_closed =
694  roxml_create_node(context->pos - 1, context->src,
695  ROXML_ATTR_NODE | context->type);
696  } else {
697  to_be_closed =
698  roxml_create_node(context->pos, context->src,
699  ROXML_ATTR_NODE | context->type);
700  }
701  roxml_close_node(context->candidat_val, to_be_closed);
704  }
705  }
706  break;
707  }
708  context->pos += cur;
709  return cur;
710 }
711 
712 ROXML_INT int _func_load_colon(roxml_parser_item_t *parser, char *chunk, void *data)
713 {
714  int cur = 1;
715  roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
716 #ifdef DEBUG_PARSING
717  fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
718 #endif /* DEBUG_PARSING */
719 
720  if (context->state == STATE_NODE_NAME) {
721  context->state = STATE_NODE_BEG;
722  context->candidat_node->ns = roxml_lookup_nsdef(context->namespaces, context->curr_name);
723  if (!context->candidat_node->ns) {
724  char *nsname = malloc(context->curr_name_len + 1);
725  memcpy(nsname, context->curr_name, context->curr_name_len);
726  nsname[context->curr_name_len] = '\0';
727  context->candidat_node->ns =
729  }
730  context->candidat_node->pos += context->curr_name_len + 2;
731  context->ns = 1;
732  } else if (context->state == STATE_NODE_ATTR) {
733  if (context->inside_node_state == STATE_INSIDE_ARG) {
735  if ((context->curr_name_len == 5) && (strncmp(context->curr_name, "xmlns", 5) == 0)) {
736  context->candidat_arg->type |= ROXML_NS_NODE;
737  context->nsdef = 1;
738  } else {
739  context->candidat_arg->ns = roxml_lookup_nsdef(context->namespaces, context->curr_name);
740  context->candidat_arg->pos += context->curr_name_len + 2;
741  context->ns = 1;
742  }
743 
744  }
745  }
746 
747  context->pos += cur;
748  return cur;
749 }
750 
751 ROXML_INT int _func_load_default(roxml_parser_item_t *parser, char *chunk, void *data)
752 {
753  int cur = 1;
754  roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
755 #ifdef DEBUG_PARSING
756  fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
757 #endif /* DEBUG_PARSING */
758 
759  switch (context->state) {
760  case STATE_NODE_SINGLE:
761  context->state = context->previous_state;
762  break;
763  case STATE_NODE_BEG:
764  if (context->ns == 0) {
765  context->lvl++;
766  roxml_process_begin_node(context, context->pos - 1);
767  }
768  context->ns = 0;
769  context->state = STATE_NODE_NAME;
770  strncpy(context->curr_name, chunk, MAX_NAME_LEN);
771  while (!ROXML_WHITE(chunk[cur]) && (chunk[cur] != '>') && (chunk[cur] != '/') && (chunk[cur] != ':')
772  && (chunk[cur] != '\0')) {
773  cur++;
774  }
775  context->curr_name_len = cur;
776  break;
777  case STATE_NODE_ATTR:
778  if (context->inside_node_state == STATE_INSIDE_ARG_BEG) {
779  if (context->nsdef) {
780  if (context->namespaces == NULL) {
781  context->namespaces = context->candidat_arg;
782  context->last_ns = context->candidat_arg;
783  } else {
784  context->last_ns->next = context->candidat_arg;
785  context->last_ns = context->candidat_arg;
786  }
787  } else if (context->ns == 0) {
788  context->candidat_arg =
789  roxml_create_node(context->pos - 1, context->src, ROXML_ATTR_NODE | context->type);
790  context->candidat_arg =
791  roxml_append_node(context->candidat_node, context->candidat_arg);
792  }
793  context->ns = 0;
795  strncpy(context->curr_name, chunk, MAX_NAME_LEN);
796  while ((chunk[cur] != '=') && (chunk[cur] != '>') && (chunk[cur] != ':')
797  && (chunk[cur] != '\0')) {
798  cur++;
799  }
800  context->curr_name_len = cur;
801  if (context->nsdef) {
802  roxml_ns_t *ns = calloc(1, sizeof(roxml_ns_t) + (1 + context->curr_name_len));
803  ns->id = ROXML_NS_ID;
804  ns->alias = (char *)ns + sizeof(roxml_ns_t);
805  memcpy(ns->alias, context->curr_name, context->curr_name_len);
806  context->candidat_arg->priv = ns;
807  context->nsdef = 0;
808  if (context->candidat_node->ns) {
809  if ((context->candidat_node->ns->type & ROXML_INVALID) == ROXML_INVALID) {
810  if (strcmp(context->candidat_arg->prnt->ns->src.buf, ns->alias) == 0) {
811  roxml_free_node(context->candidat_node->ns);
812  context->candidat_node->ns = context->candidat_arg;
813  }
814  }
815  }
816  }
817  } else if (context->inside_node_state == STATE_INSIDE_VAL_BEG) {
818  if (context->mode != MODE_COMMENT_NONE) {
819  context->content_quoted = 1;
820  context->candidat_val =
821  roxml_create_node(context->pos + 1, context->src, ROXML_TXT_NODE | context->type);
822  } else {
823  context->candidat_val =
824  roxml_create_node(context->pos, context->src, ROXML_TXT_NODE | context->type);
825  }
826  context->candidat_val = roxml_append_node(context->candidat_arg, context->candidat_val);
828  } else if ((context->inside_node_state == STATE_INSIDE_ARG) && (chunk[0] == '=')) {
829  node_t *to_be_closed;
830 
832  to_be_closed = roxml_create_node(context->pos, context->src, ROXML_ATTR_NODE | context->type);
833  roxml_close_node(context->candidat_arg, to_be_closed);
834  if ((context->curr_name_len == 5) && (strncmp(context->curr_name, "xmlns", 5) == 0)) {
835  context->nsdef = 1;
836  if (context->namespaces == NULL) {
837  context->namespaces = context->candidat_arg;
838  context->last_ns = context->candidat_arg;
839  } else {
840  context->last_ns->next = context->candidat_arg;
841  context->last_ns = context->candidat_arg;
842  }
843  }
844  }
845  break;
846  }
847 
848  context->pos += cur;
849  return cur;
850 }
#define ROXML_FILE
#define ROXML_INVALID
#define ROXML_INVALID_DOC
Definition: roxml.h:195
#define STATE_INSIDE_VAL
ROXML_INT int roxml_parse_buff(roxml_load_ctx_t *context, roxml_parser_item_t *parser, char *buffer)
generic load function
Definition: roxml_buff.c:34
#define ROXML_NS_NODE
Definition: roxml.h:102
node_t structure
Definition: roxml_types.h:133
#define STATE_INSIDE_VAL_BEG
struct node * attr
Definition: roxml_types.h:145
ROXML_INT roxml_parser_item_t * roxml_append_parser_item(roxml_parser_item_t *parser, char *key, roxml_parse_func func)
parser item creation function
Definition: roxml_parser.c:41
node_t * last_ns
Definition: roxml_types.h:177
#define ROXML_ATTR_NODE
Definition: roxml.h:51
#define ROXML_PENDING
roxml_pos_t end
Definition: roxml_types.h:141
ROXML_INT int roxml_is_separator(char sep)
separator tester
Definition: roxml_core.c:128
ROXML_INT void roxml_close_buff(node_t *n)
unload function
Definition: roxml_buff.c:29
unsigned char id
Definition: roxml_types.h:120
#define STATE_NODE_CDATA
unsigned char id
Definition: roxml_types.h:94
#define STATE_NODE_END
#define ROXML_PI_NODE
Definition: roxml.h:94
ROXML_STATIC ROXML_INT node_t * roxml_lookup_nsdef(node_t *nsdef, char *ns)
name space lookup in list
Definition: roxml_core.c:273
struct node * chld
Definition: roxml_types.h:143
struct node * next
Definition: roxml_types.h:146
node_t * candidat_val
Definition: roxml_types.h:174
node_t * current_node
Definition: roxml_types.h:175
node_t * candidat_txt
Definition: roxml_types.h:172
ROXML_STATIC ROXML_INT void roxml_set_type(node_t *n, int type)
node type setter function
Definition: roxml_core.c:302
ROXML_INT node_t * roxml_create_root(node_t *n)
internal function
Definition: roxml_core.c:251
char * alias
Definition: roxml_types.h:122
#define STATE_NODE_SINGLE
#define MODE_COMMENT_DQUOTE
struct _xpath_tok * next
Definition: roxml_types.h:109
ROXML_INT void roxml_free_node(node_t *n)
internal function
Definition: roxml_core.c:82
#define ROXML_API
Definition: roxml.h:24
#define MODE_COMMENT_NONE
#define ROXML_DOCTYPE_NODE
Definition: roxml.h:126
node_t * candidat_arg
Definition: roxml_types.h:173
struct node * sibl
Definition: roxml_types.h:142
xpath token structure
Definition: roxml_types.h:107
#define STATE_NODE_PI
File XML document backend.
struct _xpath_tok * next
Definition: roxml_types.h:97
Parsing engine.
#define ROXML_CMT_NODE
Definition: roxml.h:86
#define STATE_INSIDE_ARG_BEG
void * src
Definition: roxml_types.h:138
ROXML_INT int roxml_parse_file(roxml_load_ctx_t *context, roxml_parser_item_t *parser, FILE *file)
generic load function
Definition: roxml_file.c:33
ROXML_API void roxml_close(node_t *n)
unload function
Definition: roxml_core.c:25
#define STATE_NODE_ATTR
#define STATE_NODE_BEG
ROXML_INT node_t * roxml_set_parent(node_t *parent, node_t *n)
node parenting function
Definition: roxml_core.c:308
roxml_pos_t pos
Definition: roxml_types.h:140
#define MODE_COMMENT_QUOTE
#define STATE_INSIDE_ARG
struct node * ns
Definition: roxml_types.h:147
XML parsing core module.
namespace structure
Definition: roxml_types.h:119
ROXML_STATIC ROXML_INT void roxml_close_node(node_t *n, node_t *close)
internal function
Definition: roxml_core.c:65
xml parsing context
Definition: roxml_types.h:158
#define ROXML_NSDEF_NODE
Definition: roxml.h:110
char curr_name[MAX_NAME_LEN]
Definition: roxml_types.h:178
ROXML_STATIC ROXML_INT void roxml_process_begin_node(roxml_load_ctx_t *context, int position)
node creation during parsing
Definition: roxml_core.c:180
node_t * namespaces
Definition: roxml_types.h:176
the parser item struct
#define ROXML_ELM_NODE
Definition: roxml.h:70
#define STATE_NODE_NAME
void * priv
Definition: roxml_types.h:148
ROXML_INT node_t * roxml_create_node(int pos, void *src, int type)
internal function
Definition: roxml_core.c:46
struct node * prnt
Definition: roxml_types.h:144
#define ROXML_WHITE(n)
ROXML_INT void roxml_parser_free(roxml_parser_item_t *parser)
parser table deletion
Definition: roxml_parser.c:100
unsigned char ids[256]
Definition: roxml_types.h:95
#define STATE_NODE_CONTENT
ROXML_STATIC ROXML_INT void roxml_process_unaliased_ns(roxml_load_ctx_t *context)
namespace without alias name creation during parsing
Definition: roxml_core.c:146
#define ROXML_TXT_NODE
Definition: roxml.h:78
unsigned short type
Definition: roxml_types.h:134
ROXML_INT node_t * roxml_load(node_t *current_node, FILE *file, char *buffer)
generic load function
Definition: roxml_core.c:201
ROXML_INT void roxml_close_file(node_t *root)
unload function
Definition: roxml_file.c:28
buffer XML document backend
ROXML_INT node_t * roxml_append_node(node_t *parent, node_t *n)
node append function
Definition: roxml_core.c:347
ROXML_INT roxml_parser_item_t * roxml_parser_prepare(roxml_parser_item_t *parser)
parser preparation function
Definition: roxml_parser.c:105
#define STATE_NODE_COMMENT
node_t * candidat_node
Definition: roxml_types.h:171
#define MAX_NAME_LEN
Definition: roxml_defines.h:66
ROXML_INT void roxml_del_tree(node_t *n)
internal function
Definition: roxml_core.c:115
xpath token structure
Definition: roxml_types.h:93
#define ROXML_CDATA_NODE
Definition: roxml.h:118