<libroxml  version="2.3.0" />
contact: tristan.lelong@libroxml.net
roxml-internal.c
Go to the documentation of this file.
1 
26 #include "roxml-internal.h"
27 #include "roxml-parse-engine.h"
28 
29 #ifdef __DEBUG
30 unsigned int _nb_node = 0;
31 unsigned int _nb_attr = 0;
32 unsigned int _nb_text = 0;
33 #endif
34 
36 memory_cell_t head_cell = { PTR_NONE, 0, NULL, 0, NULL, NULL };
37 
38 void ROXML_INT *roxml_malloc(int size, int num, int type)
39 {
40  memory_cell_t *cell = &head_cell;
41  while (cell->next != NULL) {
42  cell = cell->next;
43  }
44  cell->next = (memory_cell_t *) malloc(sizeof(memory_cell_t));
45  if (!cell->next) {
46  return NULL;
47  }
48  cell->next->next = NULL;
49  cell->next->prev = cell;
50  cell = cell->next;
51  cell->type = type;
52  cell->id = pthread_self();
53  cell->occ = size;
54  cell->ptr = calloc(num, size);
55  head_cell.prev = cell;
56  return cell->ptr;
57 }
58 
59 int ROXML_INT roxml_read(int pos, int size, char *buffer, node_t *node)
60 {
61  int ret_len = 0;
62 
63  if (size > 0 && buffer) {
64  if (node->type & ROXML_FILE) {
65  if (fseek(node->src.fil, pos, SEEK_SET) == 0) {
66  ret_len = fread(buffer, 1, size, node->src.fil);
67  }
68  } else {
69  char *r1 = buffer;
70  char const *r2 = node->src.buf + pos;
71 
72  while (size-- && (*r1++ = *r2++)) ;
73  ret_len = r1 - buffer;
74  }
75  }
76  return ret_len;
77 }
78 
79 node_t ROXML_INT *roxml_create_node(int pos, void *src, int type)
80 {
81  node_t *n = (node_t *) calloc(1, sizeof(node_t));
82  n->type = type;
83  n->src.src = src;
84  n->pos = pos;
85  n->end = pos;
86 
87  return n;
88 }
89 
91 {
92  if (n) {
93  n->end = close->pos;
94  free(close);
95 
96 #ifdef __DEBUG
97  if (n->type & ROXML_ELM_NODE)
98  _nb_node++;
99  if (n->type & ROXML_ATTR_NODE)
100  _nb_attr++;
101  if (n->type & ROXML_TXT_NODE)
102  _nb_text++;
103 #endif
104  }
105 }
106 
108 {
109  if (!n) {
110  return;
111  }
112 
113  if (n->type & ROXML_PENDING) {
114  if (n->pos == 0) {
115  free(n->src.buf);
116  }
117  }
118 
119  if (n->priv) {
120  unsigned char id = *(unsigned char *)n->priv;
121 
122  if (id == ROXML_REQTABLE_ID) {
123  xpath_tok_t *tok;
124  xpath_tok_table_t *table = (xpath_tok_table_t *) n->priv;
125  tok = table->next;
126  pthread_mutex_destroy(&table->mut);
127  free(table);
128  while (tok) {
129  xpath_tok_t *to_delete = tok;
130  tok = tok->next;
131  free(to_delete);
132  }
133  } else if (id == ROXML_NS_ID) {
134  roxml_ns_t *ns = (roxml_ns_t *) n->priv;
135  free(ns);
136  }
137  }
138  free(n);
139 }
140 
142 {
143  if (n == NULL) {
144  return;
145  }
146  roxml_del_tree(n->chld);
147  roxml_del_tree(n->sibl);
148  roxml_del_tree(n->attr);
149  roxml_free_node(n);
150 }
151 
152 int roxml_is_number(char *input)
153 {
154  char *end;
155  int is_number = 0;
156 
157  /*
158  * we don't need the value per se and some compiler will
159  * complain about an initialized but unused variable if we
160  * get it.
161  */
162  strtod(input, &end);
163 
164  if ((end == NULL) || (roxml_is_separator(end[0])) || (end[0] == '"') || (end[0] == '\'') || (end[0] == '\0')) {
165  is_number = 1;
166  }
167 
168  return is_number;
169 }
170 
172 {
173  int i = 0;
174  char separators[32] = "\r\t\n ";
175  while (separators[i] != 0) {
176  if (sep == separators[i]) {
177  return 1;
178  }
179  i++;
180  }
181  return 0;
182 }
183 
185 {
186  if (context->nsdef) {
187  context->nsdef = 0;
188  context->candidat_arg->type |= ROXML_NS_NODE;
189 
190  if (context->candidat_val->pos == context->candidat_val->end) {
191  context->candidat_node->ns = NULL;
192  context->candidat_arg->ns = NULL;
193  } else {
194  roxml_ns_t *ns = calloc(1, sizeof(roxml_ns_t) + 1);
195  ns->id = ROXML_NS_ID;
196  ns->alias = (char *)ns + sizeof(roxml_ns_t);
197 
198  context->candidat_arg->priv = ns;
199  context->candidat_arg->ns = context->candidat_arg;
200  context->candidat_node->ns = context->candidat_arg;
201 
202  context->namespaces = context->candidat_arg;
203  }
204  }
205 }
206 
208 {
209  if (context->candidat_txt) {
210 #ifdef IGNORE_EMPTY_TEXT_NODES
211  if (context->empty_text_node == 0) {
212 #endif /* IGNORE_EMPTY_TEXT_NODES */
213  node_t *to_be_closed =
214  roxml_create_node(position, context->src, ROXML_TXT_NODE | context->type);
215  context->candidat_txt = roxml_append_node(context->current_node, context->candidat_txt);
216  roxml_close_node(context->candidat_txt, to_be_closed);
217  context->current_node = context->candidat_txt->prnt;
218 #ifdef IGNORE_EMPTY_TEXT_NODES
219  } else {
220  roxml_free_node(context->candidat_txt);
221  }
222 #endif /* IGNORE_EMPTY_TEXT_NODES */
223  context->candidat_txt = NULL;
224  }
225  context->candidat_node = roxml_create_node(position, context->src, ROXML_ELM_NODE | context->type);
226 }
227 
228 node_t ROXML_INT *roxml_load(node_t *current_node, FILE * file, char *buffer)
229 {
230  int error = 0;
231  roxml_load_ctx_t context;
232  roxml_parser_item_t *parser = NULL;
233  xpath_tok_table_t *table = (xpath_tok_table_t *) calloc(1, sizeof(xpath_tok_table_t));
234 
235  memset(&context, 0, sizeof(roxml_load_ctx_t));
236  context.empty_text_node = 1;
237  context.current_node = current_node;
238 
239  parser = roxml_append_parser_item(parser, " ", _func_load_white);
240  parser = roxml_append_parser_item(parser, "<", _func_load_open_node);
241  parser = roxml_append_parser_item(parser, ">", _func_load_close_node);
242  parser = roxml_append_parser_item(parser, "/", _func_load_end_node);
243  parser = roxml_append_parser_item(parser, "'", _func_load_quoted);
244  parser = roxml_append_parser_item(parser, "\"", _func_load_dquoted);
245  parser = roxml_append_parser_item(parser, "\t", _func_load_white);
246  parser = roxml_append_parser_item(parser, "\n", _func_load_white);
247  parser = roxml_append_parser_item(parser, "\r", _func_load_white);
248  parser = roxml_append_parser_item(parser, "!", _func_load_open_spec_node);
249  parser = roxml_append_parser_item(parser, "]", _func_load_close_cdata);
250  parser = roxml_append_parser_item(parser, "-", _func_load_close_comment);
251  parser = roxml_append_parser_item(parser, "?", _func_load_close_pi);
252  parser = roxml_append_parser_item(parser, ":", _func_load_colon);
253  parser = roxml_append_parser_item(parser, NULL, _func_load_default);
254 
255  parser = roxml_parser_prepare(parser);
256 
257  if (file) {
258  char *int_buffer;
259  int circle = 0;
260  int int_len = 0;
261 
262  context.type = ROXML_FILE;
263  context.src = (void *)file;
264  context.pos = 0;
265 
266  int_buffer = malloc(ROXML_BULK_READ + 1);
267 
268  do {
269  int ret = 0;
270  int chunk_len = 0;
271  int_len = fread(int_buffer + circle, 1, ROXML_BULK_READ - circle, file) + circle;
272  int_buffer[int_len] = '\0';
273 
274  if (int_len == ROXML_BULK_READ) {
275  chunk_len = int_len - ROXML_BASE_LEN;
276  } else {
277  chunk_len = int_len;
278  }
279 
280  ret = roxml_parse_line(parser, int_buffer, chunk_len, &context);
281  circle = int_len - ret;
282  if ((ret < 0) || (circle < 0)) {
283  error = 1;
284  break;
285  }
286  memmove(int_buffer, int_buffer + ret, circle);
287  } while (int_len == ROXML_BULK_READ);
288 
289  free(int_buffer);
290  } else {
291  int ret = 0;
292  context.type = ROXML_BUFF;
293  context.src = (void *)buffer;
294  ret = roxml_parse_line(parser, buffer, 0, &context);
295  if (ret < 0) {
296  error = 1;
297  }
298  }
299 
300  roxml_parser_free(parser);
301 
302  if (context.empty_text_node == 1) {
303  roxml_free_node(context.candidat_txt);
304  }
305 
306  if (!error) {
307  node_t *virtroot = NULL;
308  current_node = roxml_get_root(current_node);
309  virtroot = current_node;
310  while (virtroot->prnt) {
311  virtroot = virtroot->prnt;
312  }
313 
314  table->id = ROXML_REQTABLE_ID;
315  table->ids[ROXML_REQTABLE_ID] = 1;
316  pthread_mutex_init(&table->mut, NULL);
317  virtroot->priv = (void *)table;
318  } else {
319  free(table);
320  roxml_close(current_node);
321  return NULL;
322  }
323 
324  return current_node;
325 }
326 
328 {
329  int len = 0;
330  char namespace[MAX_NS_LEN];
331 
332  for (len = 0; ns[len] != '\0' && ns[len] != ':'; len++) {
333  namespace[len] = ns[len];
334  }
335  namespace[len] = '\0';
336 
337  while (nsdef) {
338  if (nsdef->priv && strcmp(namespace, ((roxml_ns_t *) nsdef->priv)->alias) == 0) {
339  break;
340  }
341  nsdef = nsdef->next;
342  }
343  return nsdef;
344 }
345 
346 void ROXML_INT roxml_set_type(node_t *n, int type)
347 {
349  n->type |= type;
350 }
351 
352 xpath_node_t ROXML_INT *roxml_set_axes(xpath_node_t *node, char *axes, int *offset)
353 {
354  struct _xpath_axes {
355  char id;
356  char *name;
357  };
358 
359  struct _xpath_axes xpath_axes[14] = {
360  {ROXML_ID_PARENT, ROXML_L_PARENT},
361  {ROXML_ID_PARENT, ROXML_S_PARENT},
362  {ROXML_ID_SELF, ROXML_L_SELF},
363  {ROXML_ID_SELF, ROXML_S_SELF},
364  {ROXML_ID_ATTR, ROXML_L_ATTR},
365  {ROXML_ID_ATTR, ROXML_S_ATTR},
366  {ROXML_ID_ANC, ROXML_L_ANC},
367  {ROXML_ID_ANC_O_SELF, ROXML_L_ANC_O_SELF},
368  {ROXML_ID_NEXT_SIBL, ROXML_L_NEXT_SIBL},
369  {ROXML_ID_PREV_SIBL, ROXML_L_PREV_SIBL},
370  {ROXML_ID_NEXT, ROXML_L_NEXT},
371  {ROXML_ID_PREV, ROXML_L_PREV},
372  {ROXML_ID_NS, ROXML_L_NS},
373  {ROXML_ID_CHILD, ROXML_L_CHILD},
374  };
375 
376  xpath_node_t *tmp_node;
377  if (axes[0] == '/') {
378  axes[0] = '\0';
379  *offset += 1;
380  axes++;
381  }
382  if (axes[0] == '/') {
383  // ROXML_S_DESC_O_SELF
384  node->axes = ROXML_ID_DESC_O_SELF;
385  node->name = axes + 1;
386  tmp_node = (xpath_node_t *) calloc(1, sizeof(xpath_node_t));
387  tmp_node->axes = ROXML_ID_CHILD;
388  node->next = tmp_node;
389  if (strlen(node->name) > 0) {
390  tmp_node = (xpath_node_t *) calloc(1, sizeof(xpath_node_t));
391  node->next->next = tmp_node;
392  node = roxml_set_axes(tmp_node, axes + 1, offset);
393  }
394  } else if (strncmp(ROXML_L_DESC_O_SELF, axes, strlen(ROXML_L_DESC_O_SELF)) == 0) {
395  // ROXML_L_DESC_O_SELF
396  node->axes = ROXML_ID_DESC_O_SELF;
397  node->name = axes + strlen(ROXML_L_DESC_O_SELF);
398  *offset += strlen(ROXML_L_DESC_O_SELF);
399  tmp_node = (xpath_node_t *) calloc(1, sizeof(xpath_node_t));
400  tmp_node->axes = ROXML_ID_CHILD;
401  node->next = tmp_node;
402  node = roxml_set_axes(tmp_node, axes + strlen(ROXML_L_DESC_O_SELF), offset);
403  } else if (strncmp(ROXML_L_DESC, axes, strlen(ROXML_L_DESC)) == 0) {
404  // ROXML_L_DESC
405  node->axes = ROXML_ID_DESC;
406  node->name = axes + strlen(ROXML_L_DESC);
407  *offset += strlen(ROXML_L_DESC);
408  tmp_node = (xpath_node_t *) calloc(1, sizeof(xpath_node_t));
409  tmp_node->axes = ROXML_ID_CHILD;
410  node->next = tmp_node;
411  node = roxml_set_axes(tmp_node, axes + strlen(ROXML_L_DESC), offset);
412  } else {
413  int i = 0;
414 
415  // ROXML_S_CHILD is default
416  node->axes = ROXML_ID_CHILD;
417  node->name = axes;
418 
419  for (i = 0; i < 14; i++) {
420  int len = strlen(xpath_axes[i].name);
421  if (strncmp(xpath_axes[i].name, axes, len) == 0) {
422  node->axes = xpath_axes[i].id;
423  node->name = axes + len;
424  break;
425  }
426  }
427  }
428  return node;
429 }
430 
432 {
433  int idx = 1;
434  node_t *prnt;
435  node_t *first;
436  if (n == NULL) {
437  return 0;
438  }
439 
440  prnt = n->prnt;
441  if (!prnt) {
442  return 1;
443  }
444  first = prnt->chld;
445 
446  while ((first) && (first != n)) {
447  idx++;
448  first = first->sibl;
449  }
450 
451  return idx;
452 }
453 
454 #if(CONFIG_XML_XPATH_ENGINE==1)
455 int ROXML_INT roxml_parse_xpath(char *path, xpath_node_t **xpath, int context)
456 {
457  int ret = 0;
458  roxml_xpath_ctx_t ctx;
459  roxml_parser_item_t *parser = NULL;
460  ctx.pos = 0;
461  ctx.nbpath = 1;
462  ctx.bracket = 0;
463  ctx.parenthesys = 0;
464  ctx.quoted = 0;
465  ctx.dquoted = 0;
466  ctx.content_quoted = 0;
467  ctx.is_first_node = 1;
468  ctx.wait_first_node = 1;
469  ctx.shorten_cond = 0;
470  ctx.context = context;
471  ctx.first_node = (xpath_node_t *) calloc(1, sizeof(xpath_node_t));
472  ctx.new_node = ctx.first_node;
473  ctx.new_cond = NULL;
474  ctx.first_node->rel = ROXML_OPERATOR_OR;
475 
476  parser = roxml_append_parser_item(parser, " ", _func_xpath_ignore);
477  parser = roxml_append_parser_item(parser, "\t", _func_xpath_ignore);
478  parser = roxml_append_parser_item(parser, "\n", _func_xpath_ignore);
479  parser = roxml_append_parser_item(parser, "\r", _func_xpath_ignore);
480  parser = roxml_append_parser_item(parser, "\"", _func_xpath_dquote);
481  parser = roxml_append_parser_item(parser, "\'", _func_xpath_quote);
482  parser = roxml_append_parser_item(parser, "/", _func_xpath_new_node);
483  parser = roxml_append_parser_item(parser, "(", _func_xpath_open_parenthesys);
484  parser = roxml_append_parser_item(parser, ")", _func_xpath_close_parenthesys);
485  parser = roxml_append_parser_item(parser, "[", _func_xpath_open_brackets);
486  parser = roxml_append_parser_item(parser, "]", _func_xpath_close_brackets);
487  parser = roxml_append_parser_item(parser, "=", _func_xpath_operator_equal);
488  parser = roxml_append_parser_item(parser, ">", _func_xpath_operator_sup);
489  parser = roxml_append_parser_item(parser, "<", _func_xpath_operator_inf);
490  parser = roxml_append_parser_item(parser, "!", _func_xpath_operator_diff);
491  parser = roxml_append_parser_item(parser, "0", _func_xpath_number);
492  parser = roxml_append_parser_item(parser, "1", _func_xpath_number);
493  parser = roxml_append_parser_item(parser, "2", _func_xpath_number);
494  parser = roxml_append_parser_item(parser, "3", _func_xpath_number);
495  parser = roxml_append_parser_item(parser, "4", _func_xpath_number);
496  parser = roxml_append_parser_item(parser, "5", _func_xpath_number);
497  parser = roxml_append_parser_item(parser, "6", _func_xpath_number);
498  parser = roxml_append_parser_item(parser, "7", _func_xpath_number);
499  parser = roxml_append_parser_item(parser, "8", _func_xpath_number);
500  parser = roxml_append_parser_item(parser, "9", _func_xpath_number);
501  parser = roxml_append_parser_item(parser, "+", _func_xpath_operator_add);
502  parser = roxml_append_parser_item(parser, "-", _func_xpath_operator_subs);
503  parser = roxml_append_parser_item(parser, ROXML_PATH_OR, _func_xpath_path_or);
504  parser = roxml_append_parser_item(parser, ROXML_COND_OR, _func_xpath_condition_or);
505  parser = roxml_append_parser_item(parser, ROXML_COND_AND, _func_xpath_condition_and);
506  parser = roxml_append_parser_item(parser, ROXML_FUNC_POS_STR, _func_xpath_position);
507  parser = roxml_append_parser_item(parser, ROXML_FUNC_FIRST_STR, _func_xpath_first);
508  parser = roxml_append_parser_item(parser, ROXML_FUNC_LAST_STR, _func_xpath_last);
509  parser = roxml_append_parser_item(parser, ROXML_FUNC_NSURI_STR, _func_xpath_nsuri);
510  parser = roxml_append_parser_item(parser, NULL, _func_xpath_default);
511 
512  parser = roxml_parser_prepare(parser);
513  ret = roxml_parse_line(parser, path, 0, &ctx);
514  roxml_parser_free(parser);
515 
516  if (ret >= 0) {
517  if (xpath) {
518  *xpath = ctx.first_node;
519  }
520  return ctx.nbpath;
521  }
522 
524  return -1;
525 }
526 
528 {
529  if (xcond->next) {
530  roxml_free_xcond(xcond->next);
531  }
532  if (xcond->xp) {
533  roxml_free_xpath(xcond->xp, xcond->func2);
534  }
535  free(xcond);
536 }
537 
539 {
540  int i = 0;
541  for (i = 0; i < nb; i++) {
542  if (xpath[i].next) {
543  roxml_free_xpath(xpath[i].next, 1);
544  }
545  if (xpath[i].cond) {
546  roxml_free_xcond(xpath[i].cond);
547  }
548  free(xpath[i].xp_cond);
549  }
550  free(xpath);
551 }
552 
553 double ROXML_INT roxml_double_oper(double a, double b, int op)
554 {
555  if (op == ROXML_OPERATOR_ADD) {
556  return (a + b);
557  } else if (op == ROXML_OPERATOR_SUB) {
558  return (a - b);
559  } else if (op == ROXML_OPERATOR_MUL) {
560  return (a * b);
561  } else if (op == ROXML_OPERATOR_DIV) {
562  return (a / b);
563  }
564  return 0;
565 }
566 
567 int ROXML_INT roxml_double_cmp(double a, double b, int op)
568 {
569  if (op == ROXML_OPERATOR_DIFF) {
570  return (a != b);
571  } else if (op == ROXML_OPERATOR_EINF) {
572  return (a <= b);
573  } else if (op == ROXML_OPERATOR_INF) {
574  return (a < b);
575  } else if (op == ROXML_OPERATOR_ESUP) {
576  return (a >= b);
577  } else if (op == ROXML_OPERATOR_SUP) {
578  return (a > b);
579  } else if (op == ROXML_OPERATOR_EQU) {
580  return (a == b);
581  }
582  return 0;
583 }
584 
585 int ROXML_INT roxml_string_cmp(char *sa, char *sb, int op)
586 {
587  int result;
588 
589  result = strcmp(sa, sb);
590 
591  if (op == ROXML_OPERATOR_DIFF) {
592  return (result != 0);
593  } else if (op == ROXML_OPERATOR_EINF) {
594  return (result <= 0);
595  } else if (op == ROXML_OPERATOR_INF) {
596  return (result < 0);
597  } else if (op == ROXML_OPERATOR_ESUP) {
598  return (result >= 0);
599  } else if (op == ROXML_OPERATOR_SUP) {
600  return (result > 0);
601  } else if (op == ROXML_OPERATOR_EQU) {
602  return (result == 0);
603  }
604  return 0;
605 }
606 
608 {
609  int first = 1;
610  int valid = 0;
611  xpath_cond_t *condition;
612 
613  if (xn == NULL) {
614  return 1;
615  }
616 
617  condition = xn->cond;
618 
619  if (!condition) {
620  return 1;
621  }
622 
623  while (condition) {
624  int status = 0;
625  double iarg1;
626  double iarg2;
627  char *sarg1;
628  char *sarg2;
629 
630  if (condition->func == ROXML_FUNC_POS) {
631  status = 0;
632  iarg2 = atof(condition->arg2);
633  if (xn->name[0] == '*') {
634  iarg1 = roxml_get_node_internal_position(candidat);
635  } else {
636  iarg1 = roxml_get_node_position(candidat);
637  }
638  status = roxml_double_cmp(iarg1, iarg2, condition->op);
639  } else if (condition->func == ROXML_FUNC_LAST) {
640  status = 0;
641  iarg2 = roxml_get_chld_nb(candidat->prnt);
642  if (xn->name[0] == '*') {
643  iarg1 = roxml_get_node_internal_position(candidat);
644  } else {
645  iarg1 = roxml_get_node_position(candidat);
646  }
647  if (condition->op > 0) {
648  double operand = 0;
649  operand = atof(condition->arg2);
650  iarg2 = roxml_double_oper(iarg2, operand, condition->op);
651  }
652  status = roxml_double_cmp(iarg1, iarg2, ROXML_OPERATOR_EQU);
653  } else if (condition->func == ROXML_FUNC_FIRST) {
654  status = 0;
655  iarg2 = 1;
656  if (xn->name[0] == '*') {
657  iarg1 = roxml_get_node_internal_position(candidat);
658  } else {
659  iarg1 = roxml_get_node_position(candidat);
660  }
661  if (condition->op > 0) {
662  double operand = 0;
663  operand = atof(condition->arg2);
664  iarg2 = roxml_double_oper(iarg2, operand, condition->op);
665  }
666  status = roxml_double_cmp(iarg1, iarg2, ROXML_OPERATOR_EQU);
667  } else if (condition->func == ROXML_FUNC_INTCOMP) {
668  node_t *val = roxml_get_attr(candidat, condition->arg1 + 1, 0);
669  status = 0;
670  if (val) {
671  ROXML_GET_BASE_BUFFER(strval);
672  iarg1 = atof(roxml_get_content(val, strval, ROXML_BASE_LEN, &status));
673  if (status >= ROXML_BASE_LEN) {
674  iarg1 = atof(roxml_get_content(val, NULL, 0, &status));
676  }
677  iarg2 = atof(condition->arg2);
678  status = roxml_double_cmp(iarg1, iarg2, condition->op);
679  ROXML_PUT_BASE_BUFFER(strval);
680  }
681  } else if (condition->func == ROXML_FUNC_NSURI) {
682  node_t *val = roxml_get_ns(candidat);
683  status = 0;
684  if (val) {
685  ROXML_GET_BASE_BUFFER(strval);
686  sarg1 = roxml_get_content(val, strval, ROXML_BASE_LEN, &status);
687  if (status >= ROXML_BASE_LEN) {
688  sarg1 = roxml_get_content(val, NULL, 0, &status);
689  }
690  sarg2 = condition->arg2;
691  status = roxml_string_cmp(sarg1, sarg2, condition->op);
692  roxml_release(sarg1);
693  ROXML_PUT_BASE_BUFFER(strval);
694  } else {
695  sarg2 = condition->arg2;
696  status = roxml_string_cmp("", sarg2, condition->op);
697  }
698  } else if (condition->func == ROXML_FUNC_STRCOMP) {
699  node_t *val = roxml_get_attr(candidat, condition->arg1 + 1, 0);
700  status = 0;
701  if (val) {
702  ROXML_GET_BASE_BUFFER(strval);
703  sarg1 = roxml_get_content(val, strval, ROXML_BASE_LEN, &status);
704  if (status >= ROXML_BASE_LEN) {
705  sarg1 = roxml_get_content(val, NULL, 0, &status);
706  }
707  sarg2 = condition->arg2;
708  status = roxml_string_cmp(sarg1, sarg2, condition->op);
709  roxml_release(sarg1);
710  ROXML_PUT_BASE_BUFFER(strval);
711  }
712  } else if (condition->func == ROXML_FUNC_XPATH) {
713  int index = condition->func2;
714  int count = 0;
715  node_t *root = roxml_get_root(candidat);
716  node_t **node_set;
717  status = 0;
718 
719  node_set = roxml_exec_xpath(root, candidat, condition->xp, index, &count);
720 
721  roxml_release(node_set);
722 
723  if (count > 0) {
724  status = 1;
725  }
726 
727  }
728 
729  if (first) {
730  valid = status;
731  first = 0;
732  } else {
733  if (condition->rel == ROXML_OPERATOR_OR) {
734  valid = valid || status;
735  } else if (condition->rel == ROXML_OPERATOR_AND) {
736  valid = valid && status;
737  }
738  }
739  condition = condition->next;
740  }
741 
742  return valid;
743 }
744 
746 {
747  int i = 0;
748  xpath_tok_table_t *table;
749 
750  while (root->prnt) {
751  root = root->prnt;
752  }
753 
754  table = (xpath_tok_table_t *) root->priv;
755 
756  pthread_mutex_lock(&table->mut);
757  for (i = ROXML_XPATH_FIRST_ID; i < 255; i++) {
758  if (table->ids[i] == 0) {
759  table->ids[i]++;
760  pthread_mutex_unlock(&table->mut);
761  return i;
762  }
763  }
764  pthread_mutex_unlock(&table->mut);
765  return -1;
766 }
767 
768 int ROXML_INT roxml_in_pool(node_t *root, node_t * n, int req_id)
769 {
770  xpath_tok_table_t *table;
771 
772  while (root->prnt) {
773  root = root->prnt;
774  }
775 
776  table = (xpath_tok_table_t *) root->priv;
777 
778  pthread_mutex_lock(&table->mut);
779  if (n->priv) {
780  xpath_tok_t *tok = (xpath_tok_t *) n->priv;
781  if (tok->id == req_id) {
782  pthread_mutex_unlock(&table->mut);
783  return 1;
784  } else {
785  while (tok) {
786  if (tok->id == req_id) {
787  pthread_mutex_unlock(&table->mut);
788  return 1;
789  }
790  tok = tok->next;
791  }
792  }
793  }
794  pthread_mutex_unlock(&table->mut);
795  return 0;
796 }
797 
798 void ROXML_INT roxml_release_id(node_t *root, node_t **pool, int pool_len, int req_id)
799 {
800  int i = 0;
801  xpath_tok_table_t *table = NULL;
802 
803  while (root->prnt) {
804  root = root->prnt;
805  }
806 
807  table = (xpath_tok_table_t *) root->priv;
808 
809  for (i = 0; i < pool_len; i++) {
810  roxml_del_from_pool(root, pool[i], req_id);
811  }
812  pthread_mutex_lock(&table->mut);
813  table->ids[req_id] = 0;
814  pthread_mutex_unlock(&table->mut);
815 }
816 
817 void roxml_del_from_pool(node_t *root, node_t * n, int req_id)
818 {
819  xpath_tok_table_t *table = NULL;
820 
821  while (root->prnt) {
822  root = root->prnt;
823  }
824 
825  table = (xpath_tok_table_t *) root->priv;
826 
827  pthread_mutex_lock(&table->mut);
828  if (n->priv) {
829  xpath_tok_t *prev = (xpath_tok_t *) n->priv;
830  xpath_tok_t *tok = (xpath_tok_t *) n->priv;
831  if (tok->id == req_id) {
832  n->priv = (void *)tok->next;
833  free(tok);
834  } else {
835  while (tok) {
836  if (tok->id == req_id) {
837  prev->next = tok->next;
838  free(tok);
839  break;
840  }
841  prev = tok;
842  tok = tok->next;
843  }
844  }
845  }
846  pthread_mutex_unlock(&table->mut);
847 }
848 
849 int ROXML_INT roxml_add_to_pool(node_t *root, node_t * n, int req_id)
850 {
851  xpath_tok_table_t *table;
852  xpath_tok_t *tok;
853  xpath_tok_t *last_tok = NULL;
854 
855  while (root->prnt) {
856  root = root->prnt;
857  }
858 
859  if (req_id == 0) {
860  return 1;
861  }
862  table = (xpath_tok_table_t *) root->priv;
863 
864  pthread_mutex_lock(&table->mut);
865  tok = (xpath_tok_t *) n->priv;
866 
867  while (tok) {
868  if (tok->id == req_id) {
869  pthread_mutex_unlock(&table->mut);
870  return 0;
871  }
872  last_tok = tok;
873  tok = (xpath_tok_t *) tok->next;
874  }
875  if (last_tok == NULL) {
876  n->priv = calloc(1, sizeof(xpath_tok_t));
877  last_tok = (xpath_tok_t *) n->priv;
878  } else {
879  last_tok->next = (xpath_tok_t *) calloc(1, sizeof(xpath_tok_t));
880  last_tok = last_tok->next;
881  }
882  last_tok->id = req_id;
883  pthread_mutex_unlock(&table->mut);
884 
885  return 1;
886 }
887 
888 int ROXML_INT roxml_validate_axes(node_t *root, node_t * candidat, node_t *** ans, int *nb, int *max,
889  xpath_node_t *xn, int req_id)
890 {
891 
892  int valid = 0;
893  int path_end = 0;
894  char *axes = NULL;
895 
896  if (xn == NULL) {
897  valid = 1;
898  path_end = 1;
899  } else {
900  axes = xn->name;
901 
902  if ((axes == NULL) || (strcmp("node()", axes) == 0)) {
903  valid = 1;
904  } else if (strcmp("*", axes) == 0) {
905  if (candidat->type & ROXML_ELM_NODE) {
906  valid = 1;
907  }
908  if (candidat->type & ROXML_ATTR_NODE) {
909  valid = 1;
910  }
911  } else if (strcmp("comment()", axes) == 0) {
912  if (candidat->type & ROXML_CMT_NODE) {
913  valid = 1;
914  }
915  } else if (strcmp("processing-instruction()", axes) == 0) {
916  if (candidat->type & ROXML_PI_NODE) {
917  valid = 1;
918  }
919  } else if (strcmp("text()", axes) == 0) {
920  if (candidat->type & ROXML_TXT_NODE) {
921  valid = 1;
922  }
923  } else if (strcmp("", axes) == 0) {
924  if (xn->abs) {
925  candidat = root;
926  valid = 1;
927  }
928  }
929  if (!valid) {
930  if (candidat->type & ROXML_PI_NODE) {
931  return 0;
932  }
933  if (candidat->type & ROXML_CMT_NODE) {
934  return 0;
935  }
936  }
937  if (xn->next == NULL) {
938  path_end = 1;
939  }
940  if ((xn->axes == ROXML_ID_SELF) || (xn->axes == ROXML_ID_PARENT)) {
941  valid = 1;
942  }
943  }
944 
945  if (!valid) {
946  ROXML_GET_BASE_BUFFER(intern_buff);
947  int ns_len = 0;
948  char *name = intern_buff;
949  if (candidat->ns) {
950  name = roxml_get_name(candidat->ns, intern_buff, ROXML_BASE_LEN);
951  ns_len = strlen(name);
952  if (ns_len) {
953  name[ns_len] = ':';
954  ns_len++;
955  }
956  }
957  roxml_get_name(candidat, intern_buff + ns_len, ROXML_BASE_LEN - ns_len);
958  if (name && strcmp(name, axes) == 0) {
959  valid = 1;
960  }
961  ROXML_PUT_BASE_BUFFER(intern_buff);
962  }
963 
964  if (valid) {
965  valid = roxml_validate_predicat(xn, candidat);
966  }
967 
968  if ((valid) && (xn) && (xn->xp_cond)) {
969  int status;
970  xpath_cond_t *condition = xn->xp_cond;
971  valid = 0;
972  if (condition->func == ROXML_FUNC_STRCOMP) {
973  char *sarg1;
974  char *sarg2;
975  ROXML_GET_BASE_BUFFER(strval);
976  sarg1 = roxml_get_content(candidat, strval, ROXML_BASE_LEN, &status);
977  if (status >= ROXML_BASE_LEN) {
978  sarg1 = roxml_get_content(candidat, NULL, 0, &status);
979  }
980  sarg2 = condition->arg2;
981  valid = roxml_string_cmp(sarg1, sarg2, condition->op);
982  roxml_release(sarg1);
983  ROXML_PUT_BASE_BUFFER(strval);
984  } else if (condition->func == ROXML_FUNC_INTCOMP) {
985  double iarg1;
986  double iarg2;
987  ROXML_GET_BASE_BUFFER(strval);
988  iarg1 = atof(roxml_get_content(candidat, strval, ROXML_BASE_LEN, &status));
989  if (status >= ROXML_BASE_LEN) {
990  iarg1 = atof(roxml_get_content(candidat, NULL, 0, &status));
992  }
993  iarg2 = atof(condition->arg2);
994  valid = roxml_double_cmp(iarg1, iarg2, condition->op);
995  ROXML_PUT_BASE_BUFFER(strval);
996  }
997  }
998 
999  if ((valid) && (path_end)) {
1000  if (roxml_add_to_pool(root, candidat, req_id)) {
1001  if (ans) {
1002  if ((*nb) >= (*max)) {
1003  int new_max = (*max) * 2;
1004  node_t **new_ans = roxml_malloc(sizeof(node_t *), new_max, PTR_NODE_RESULT);
1005  memcpy(new_ans, (*ans), *(max) * sizeof(node_t *));
1006  roxml_release(*ans);
1007  *ans = new_ans;
1008  *max = new_max;
1009  }
1010  (*ans)[*nb] = candidat;
1011  }
1012  (*nb)++;
1013  }
1014  }
1015 
1016  return valid;
1017 }
1018 
1019 void ROXML_INT roxml_check_node(xpath_node_t *xp, node_t * root, node_t * context, node_t *** ans, int *nb, int *max,
1020  int ignore, int req_id)
1021 {
1022  int validate_node = 0;
1023 
1024  if ((req_id == 0) && (*nb > 0)) {
1025  return;
1026  }
1027 
1028  if (!xp) {
1029  return;
1030  }
1031  // if found a "all document" axes
1032  if (ignore == ROXML_DESC_ONLY) {
1033  node_t *current = context->chld;
1034  while (current) {
1035  roxml_check_node(xp, root, current, ans, nb, max, ignore, req_id);
1036  current = current->sibl;
1037  }
1038  }
1039 
1040  switch (xp->axes) {
1041  case ROXML_ID_CHILD:{
1042  node_t *current = context->chld;
1043  while (current) {
1044  validate_node = roxml_validate_axes(root, current, ans, nb, max, xp, req_id);
1045  if (validate_node) {
1046  roxml_check_node(xp->next, root, current, ans, nb, max, ROXML_DIRECT, req_id);
1047  }
1048  current = current->sibl;
1049  }
1050  if ((xp->name == NULL) || (strcmp(xp->name, "text()") == 0)
1051  || (strcmp(xp->name, "node()") == 0)) {
1052  node_t *current = roxml_get_txt(context, 0);
1053  while (current) {
1054  validate_node = roxml_validate_axes(root, current, ans, nb, max, xp, req_id);
1055  current = current->sibl;
1056  }
1057  }
1058  if ((xp->name == NULL) || (strcmp(xp->name, "node()") == 0)) {
1059  node_t *current = context->attr;
1060  while (current) {
1061  validate_node = roxml_validate_axes(root, current, ans, nb, max, xp, req_id);
1062  current = current->sibl;
1063  }
1064  }
1065  }
1066  break;
1067  case ROXML_ID_DESC:{
1068  xp = xp->next;
1069  roxml_check_node(xp, root, context, ans, nb, max, ROXML_DESC_ONLY, req_id);
1070  }
1071  break;
1072  case ROXML_ID_DESC_O_SELF:{
1073  xp = xp->next;
1074  validate_node = roxml_validate_axes(root, context, ans, nb, max, xp, req_id);
1075  if (validate_node) {
1076  roxml_check_node(xp->next, root, context, ans, nb, max, ROXML_DIRECT, req_id);
1077  }
1078  roxml_check_node(xp, root, context, ans, nb, max, ROXML_DESC_ONLY, req_id);
1079  }
1080  break;
1081  case ROXML_ID_SELF:{
1082  validate_node = roxml_validate_axes(root, context, ans, nb, max, xp, req_id);
1083  roxml_check_node(xp->next, root, context, ans, nb, max, ROXML_DIRECT, req_id);
1084  }
1085  break;
1086  case ROXML_ID_PARENT:{
1087  if (context->prnt) {
1088  validate_node = roxml_validate_axes(root, context->prnt, ans, nb, max, xp, req_id);
1089  roxml_check_node(xp->next, root, context->prnt, ans, nb, max, ROXML_DIRECT, req_id);
1090  } else {
1091  validate_node = 0;
1092  }
1093  }
1094  break;
1095  case ROXML_ID_ATTR:{
1096  node_t *attribute = context->attr;
1097  while (attribute) {
1098  validate_node = roxml_validate_axes(root, attribute, ans, nb, max, xp, req_id);
1099  if (validate_node) {
1100  roxml_check_node(xp->next, root, context, ans, nb, max, ROXML_DIRECT, req_id);
1101  }
1102  attribute = attribute->sibl;
1103  }
1104  }
1105  break;
1106  case ROXML_ID_ANC:{
1107  node_t *current = context->prnt;
1108  while (current) {
1109  validate_node = roxml_validate_axes(root, current, ans, nb, max, xp, req_id);
1110  if (validate_node) {
1111  roxml_check_node(xp->next, root, current, ans, nb, max, ROXML_DIRECT, req_id);
1112  }
1113  current = current->prnt;
1114  }
1115  }
1116  break;
1117  case ROXML_ID_NEXT_SIBL:{
1118  node_t *current = context->sibl;
1119  while (current) {
1120  validate_node = roxml_validate_axes(root, current, ans, nb, max, xp, req_id);
1121  if (validate_node) {
1122  roxml_check_node(xp->next, root, current, ans, nb, max, ROXML_DIRECT, req_id);
1123  }
1124  current = current->sibl;
1125  }
1126  }
1127  break;
1128  case ROXML_ID_PREV_SIBL:{
1129  node_t *current = context->prnt->chld;
1130  while (current != context) {
1131  validate_node = roxml_validate_axes(root, current, ans, nb, max, xp, req_id);
1132  if (validate_node) {
1133  roxml_check_node(xp->next, root, current, ans, nb, max, ROXML_DIRECT, req_id);
1134  }
1135  current = current->sibl;
1136  }
1137  }
1138  break;
1139  case ROXML_ID_NEXT:{
1140  node_t *current = context;
1141  while (current) {
1142  node_t *following = current->sibl;
1143  while (following) {
1144  validate_node = roxml_validate_axes(root, following, ans, nb, max, xp, req_id);
1145  if (validate_node) {
1146  roxml_check_node(xp->next, root, following, ans, nb, max, ROXML_DIRECT,
1147  req_id);
1148  } else {
1149  xp->axes = ROXML_ID_CHILD;
1150  roxml_check_node(xp, root, following, ans, nb, max, ROXML_DESC_ONLY,
1151  req_id);
1152  xp->axes = ROXML_ID_NEXT;
1153  }
1154  following = following->sibl;
1155  }
1156  following = current->prnt->chld;
1157  while (following != current) {
1158  following = following->sibl;
1159  }
1160  current = following->sibl;
1161  }
1162  }
1163  break;
1164  case ROXML_ID_PREV:{
1165  node_t *current = context;
1166  while (current && current->prnt) {
1167  node_t *preceding = current->prnt->chld;
1168  while (preceding != current) {
1169  validate_node = roxml_validate_axes(root, preceding, ans, nb, max, xp, req_id);
1170  if (validate_node) {
1171  roxml_check_node(xp->next, root, preceding, ans, nb, max, ROXML_DIRECT,
1172  req_id);
1173  } else {
1174  xp->axes = ROXML_ID_CHILD;
1175  roxml_check_node(xp, root, preceding, ans, nb, max, ROXML_DESC_ONLY,
1176  req_id);
1177  xp->axes = ROXML_ID_PREV;
1178  }
1179  preceding = preceding->sibl;
1180  }
1181  current = current->prnt;
1182  }
1183  }
1184  break;
1185  case ROXML_ID_NS:{
1186  validate_node = roxml_validate_axes(root, context->ns, ans, nb, max, xp, req_id);
1187  if (validate_node) {
1188  roxml_check_node(xp->next, root, context, ans, nb, max, ROXML_DIRECT, req_id);
1189  }
1190  }
1191  break;
1192  case ROXML_ID_ANC_O_SELF:{
1193  node_t *current = context;
1194  while (current) {
1195  validate_node = roxml_validate_axes(root, current, ans, nb, max, xp, req_id);
1196  if (validate_node) {
1197  roxml_check_node(xp->next, root, current, ans, nb, max, ROXML_DIRECT, req_id);
1198  }
1199  current = current->prnt;
1200  }
1201  }
1202  break;
1203  }
1204 
1205  return;
1206 }
1207 
1208 void roxml_compute_and(node_t *root, node_t **node_set, int *count, int cur_req_id, int prev_req_id)
1209 {
1210  int i = 0;
1211  int limit = *count;
1212  int pool1 = 0, pool2 = 0;
1213 
1214  for (i = 0; i < limit; i++) {
1215  if (pool1 == 0)
1216  if (roxml_in_pool(root, node_set[i], cur_req_id))
1217  pool1++;
1218  if (pool2 == 0)
1219  if (roxml_in_pool(root, node_set[i], prev_req_id))
1220  pool2++;
1221  if (pool1 && pool2)
1222  break;
1223  }
1224 
1225  if (!pool1 || !pool2) {
1226  for (i = 0; i < limit; i++) {
1227  roxml_del_from_pool(root, node_set[i], cur_req_id);
1228  roxml_del_from_pool(root, node_set[i], prev_req_id);
1229  }
1230  *count = 0;
1231  }
1232 }
1233 
1234 void roxml_compute_or(node_t *root, node_t **node_set, int *count, int req_id, int glob_id)
1235 {
1236  int i = 0;
1237  for (i = 0; i < *count; i++) {
1238  if (roxml_in_pool(root, node_set[i], req_id)) {
1239  roxml_add_to_pool(root, node_set[i], glob_id);
1240  roxml_del_from_pool(root, node_set[i], req_id);
1241  }
1242  }
1243 }
1244 
1245 node_t **roxml_exec_xpath(node_t *root, node_t * n, xpath_node_t * xpath, int index, int *count)
1246 {
1247  int path_id;
1248  int max_answers = 1;
1249  int glob_id = 0;
1250  int *req_ids = NULL;
1251 
1252  node_t **node_set = roxml_malloc(sizeof(node_t *), max_answers, PTR_NODE_RESULT);
1253 
1254  *count = 0;
1255  glob_id = roxml_request_id(root);
1256  if (glob_id < 0) {
1257  roxml_release(node_set);
1258  return NULL;
1259  }
1260  req_ids = calloc(index, sizeof(int));
1261 
1262  // process all and xpath
1263  for (path_id = 0; path_id < index; path_id++) {
1264  xpath_node_t *cur_xpath = NULL;
1265  xpath_node_t *next_xpath = NULL;
1266  cur_xpath = &xpath[path_id];
1267  if (path_id < index - 1) {
1268  next_xpath = &xpath[path_id + 1];
1269  }
1270 
1271  if ((cur_xpath->rel == ROXML_OPERATOR_AND) || ((next_xpath) && (next_xpath->rel == ROXML_OPERATOR_AND))) {
1272  int req_id = roxml_request_id(root);
1273 
1274  node_t *orig = n;
1275  if (cur_xpath->abs) {
1276  // context node is root
1277  orig = root;
1278  }
1279  // assign a new request ID
1280  roxml_check_node(cur_xpath, root, orig, &node_set, count, &max_answers, ROXML_DIRECT, req_id);
1281 
1282  if (cur_xpath->rel == ROXML_OPERATOR_AND) {
1283  roxml_compute_and(root, node_set, count, req_id, req_ids[path_id - 1]);
1284  }
1285  req_ids[path_id] = req_id;
1286  }
1287  }
1288 
1289  // process all or xpath
1290  for (path_id = 0; path_id < index; path_id++) {
1291  node_t *orig = n;
1292  xpath_node_t *cur_xpath = &xpath[path_id];
1293 
1294  if (cur_xpath->rel == ROXML_OPERATOR_OR) {
1295  if (req_ids[path_id] == 0) {
1296  if (cur_xpath->abs) {
1297  // context node is root
1298  orig = root;
1299  }
1300  // assign a new request ID
1301  roxml_check_node(cur_xpath, root, orig, &node_set, count, &max_answers, ROXML_DIRECT,
1302  glob_id);
1303  } else {
1304  roxml_compute_or(root, node_set, count, req_ids[path_id + 1], glob_id);
1305  roxml_release_id(root, node_set, *count, req_ids[path_id + 1]);
1306  }
1307  }
1308  }
1309  roxml_release_id(root, node_set, *count, glob_id);
1310 
1311  for (path_id = 0; path_id < index; path_id++) {
1312  if (req_ids[path_id] != 0) {
1313  roxml_release_id(root, node_set, *count, req_ids[path_id]);
1314  }
1315  }
1316 
1317  free(req_ids);
1318 
1319  return node_set;
1320 }
1321 #endif /* CONFIG_XML_XPATH_ENGINE */
1322 
1324 {
1325  if (parent == NULL) {
1326  return n;
1327  }
1328 
1329  n->prnt = parent;
1330 
1331  if (parent->ns && ((parent->ns->type & ROXML_INVALID) != ROXML_INVALID)
1332  && parent->ns->priv && ((roxml_ns_t *) parent->ns->priv)->alias[0] == '\0') {
1333  if (n->ns == NULL) {
1334  n->ns = parent->ns;
1335  }
1336  }
1337 
1338  if (n->type & ROXML_ATTR_NODE) {
1339  if (parent->attr) {
1340  node_t *attr = parent->attr;
1341  while (attr->sibl) {
1342  attr = attr->sibl;
1343  }
1344  attr->sibl = n;
1345  } else {
1346  parent->attr = n;
1347  }
1348  } else {
1349  if (parent->next) {
1350  parent->next->sibl = n;
1351  } else {
1352  parent->chld = n;
1353  }
1354  parent->next = n;
1355  }
1356 
1357  return n;
1358 }
1359 
1360 node_t ROXML_INT *roxml_parent_node(node_t *parent, node_t * n, int position)
1361 {
1362  int nb;
1363 
1364  if (n == NULL) {
1365  return NULL;
1366  }
1367  if (parent == NULL) {
1368  return n;
1369  }
1370 
1371  if (position == 0) {
1372  return roxml_append_node(parent, n);
1373  }
1374 
1375  if (n->type & ROXML_ATTR_NODE) {
1376  nb = roxml_get_attr_nb(parent);
1377  } else {
1378  nb = roxml_get_nodes_nb(parent,
1381  }
1382 
1383  if (position > nb) {
1384  return roxml_append_node(parent, n);
1385  }
1386 
1387  n->prnt = parent;
1388 
1389  if (parent->ns && ((parent->ns->type & ROXML_INVALID) != ROXML_INVALID)
1390  && ((roxml_ns_t *) parent->ns->priv)->alias[0] == '\0') {
1391  if (n->ns == NULL) {
1392  n->ns = parent->ns;
1393  }
1394  }
1395 
1396  if (position == 1) {
1397  if (n->type & ROXML_ATTR_NODE) {
1398  n->sibl = parent->attr;
1399  parent->attr = n;
1400  } else {
1401  n->sibl = parent->chld;
1402  parent->chld = n;
1403  }
1404  } else {
1405  int i;
1406  node_t *prev = parent->chld;
1407  node_t *next = parent->chld;
1408 
1409  if (n->type & ROXML_ATTR_NODE) {
1410  next = parent->attr;
1411  }
1412  for (i = 1; i < position; i++) {
1413  prev = next;
1414  next = next->sibl;
1415  }
1416  n->sibl = next;
1417  prev->sibl = n;
1418  }
1419  return n;
1420 }
1421 
1422 #if(CONFIG_XML_COMMIT_XML_TREE==1)
1423 void ROXML_INT roxml_print_space(FILE * f, char **buf, int *offset, int *len, int lvl)
1424 {
1425  if (lvl > 0) {
1426  int i = 0;
1427 
1428  if (buf && *buf) {
1429  int pos = *offset + lvl;
1430  if (pos >= *len) {
1431  *buf = realloc(*buf, *len + ROXML_BASE_LEN);
1432  memset(*buf + *len, 0, ROXML_BASE_LEN);
1433  *len += ROXML_BASE_LEN;
1434  }
1435  for (; i < lvl; i++) {
1436  strcat(*buf, " ");
1437  }
1438  *offset = pos;
1439  }
1440  if (f) {
1441  for (; i < lvl; i++) {
1442  fwrite(" ", 1, 1, f);
1443  }
1444  }
1445  }
1446 }
1447 
1448 void ROXML_INT roxml_write_string(char **buf, FILE * f, char *str, int *offset, int *len)
1449 {
1450  int min_len = strlen(str);
1451  int pos = *offset + min_len;
1452  int appended_space = ROXML_BASE_LEN * ((int)(min_len / ROXML_BASE_LEN) + 1);
1453 
1454  if ((pos >= *len) && (buf) && (*buf)) {
1455  *buf = realloc(*buf, *len + appended_space);
1456  memset(*buf + *len, 0, appended_space);
1457  *len += appended_space;
1458  }
1459  if (f) {
1460  fprintf(f, "%s", str);
1461  }
1462  if (buf && *buf) {
1463  strcat(*buf + (*offset), str);
1464  }
1465  *offset = pos;
1466 }
1467 
1468 void ROXML_INT roxml_write_node(node_t *n, FILE * f, char **buf, int human, int lvl, int *offset, int *len)
1469 {
1470  ROXML_GET_BASE_BUFFER(name);
1471 
1472  roxml_get_name(n, name, ROXML_BASE_LEN);
1473  if (human) {
1474  roxml_print_space(f, buf, offset, len, lvl);
1475  }
1476  if ((n->type & ROXML_NODE_TYPES) == ROXML_ELM_NODE) {
1477  ROXML_GET_BASE_BUFFER(ns);
1478  node_t *attr = n->attr;
1479  if (n->prnt) {
1480  roxml_write_string(buf, f, "<", offset, len);
1481  if (n->ns) {
1482  roxml_get_name(n->ns, ns, ROXML_BASE_LEN);
1483  if (ns[0] != '\0') {
1484  roxml_write_string(buf, f, ns, offset, len);
1485  roxml_write_string(buf, f, ":", offset, len);
1486  }
1487  }
1488  roxml_write_string(buf, f, name, offset, len);
1489  }
1490  while (attr) {
1491  int status = 0;
1492  char *value;
1493  char arg[ROXML_BASE_LEN];
1494  char val[ROXML_BASE_LEN];
1495 
1496  roxml_get_name(attr, arg, ROXML_BASE_LEN);
1497  value = roxml_get_content(attr, val, ROXML_BASE_LEN, &status);
1498  if (status >= ROXML_BASE_LEN) {
1499  value = roxml_get_content(attr, NULL, 0, &status);
1500  }
1501  roxml_write_string(buf, f, " ", offset, len);
1502  if (attr->type & ROXML_NS_NODE) {
1503  roxml_write_string(buf, f, "xmlns", offset, len);
1504  if (arg[0] != '\0') {
1505  roxml_write_string(buf, f, ":", offset, len);
1506  }
1507  }
1508  if (attr->ns) {
1509  ROXML_GET_BASE_BUFFER(arg_ns);
1510  roxml_get_name(attr->ns, arg_ns, ROXML_BASE_LEN);
1511  if (arg_ns[0] != '\0') {
1512  roxml_write_string(buf, f, arg_ns, offset, len);
1513  roxml_write_string(buf, f, ":", offset, len);
1514  }
1515  ROXML_PUT_BASE_BUFFER(arg_ns);
1516  }
1517  roxml_write_string(buf, f, arg, offset, len);
1518  roxml_write_string(buf, f, "=\"", offset, len);
1519  roxml_write_string(buf, f, value, offset, len);
1520  roxml_write_string(buf, f, "\"", offset, len);
1521  attr = attr->sibl;
1522  roxml_release(value);
1523  }
1524  if (n->chld) {
1525  node_t *chld = n->chld;
1526  if (n->prnt) {
1527  roxml_write_string(buf, f, ">", offset, len);
1528  if (human) {
1529  roxml_write_string(buf, f, "\n", offset, len);
1530  }
1531  }
1532  while (chld) {
1533  if (chld->type & ROXML_TXT_NODE) {
1534  ROXML_GET_BASE_BUFFER(val);
1535  char *value;
1536  int status;
1537  if (human) {
1538  roxml_print_space(f, buf, offset, len, lvl + 1);
1539  }
1540  value = roxml_get_content(chld, val, ROXML_BASE_LEN, &status);
1541  if (status >= ROXML_BASE_LEN) {
1542  value = roxml_get_content(chld, NULL, 0, &status);
1543  }
1544  if ((chld->type & ROXML_CDATA_NODE) == ROXML_CDATA_NODE) {
1545  roxml_write_string(buf, f, "<![CDATA[", offset, len);
1546  roxml_write_string(buf, f, value, offset, len);
1547  roxml_write_string(buf, f, "]]>", offset, len);
1548  } else {
1549  char *end = value + status - 2;
1550  char *strip = value;
1551  while (roxml_is_separator(end[0])) {
1552  end[0] = '\0';
1553  end--;
1554  }
1555  while (roxml_is_separator(strip[0])) {
1556  strip++;
1557  }
1558 
1559  roxml_write_string(buf, f, strip, offset, len);
1560  }
1561  if (human) {
1562  roxml_write_string(buf, f, "\n", offset, len);
1563  }
1564  chld = chld->sibl;
1565  roxml_release(value);
1566  ROXML_PUT_BASE_BUFFER(val);
1567  } else {
1568  roxml_write_node(chld, f, buf, human, lvl + 1, offset, len);
1569  chld = chld->sibl;
1570  }
1571  }
1572  if (n->prnt) {
1573  if (human) {
1574  roxml_print_space(f, buf, offset, len, lvl);
1575  }
1576  roxml_write_string(buf, f, "</", offset, len);
1577  if (n->ns) {
1578  if (ns[0] != '\0') {
1579  roxml_write_string(buf, f, ns, offset, len);
1580  roxml_write_string(buf, f, ":", offset, len);
1581  }
1582  }
1583  roxml_write_string(buf, f, name, offset, len);
1584  roxml_write_string(buf, f, ">", offset, len);
1585  if (human) {
1586  roxml_write_string(buf, f, "\n", offset, len);
1587  }
1588  }
1589  } else {
1590  roxml_write_string(buf, f, "/>", offset, len);
1591  if (human) {
1592  roxml_write_string(buf, f, "\n", offset, len);
1593  }
1594  }
1595  ROXML_PUT_BASE_BUFFER(ns);
1596  } else {
1597  char *value;
1598  int status;
1599  char head[8];
1600  char tail[8];
1601 
1602  ROXML_GET_BASE_BUFFER(val);
1603 
1604  if ((n->type & ROXML_NODE_TYPES) == ROXML_CMT_NODE) {
1605  strcpy(head, "<!--");
1606  strcpy(tail, "-->");
1607  } else if ((n->type & ROXML_NODE_TYPES) == ROXML_DOCTYPE_NODE) {
1608  strcpy(head, "<");
1609  strcpy(tail, ">");
1610  } else if ((n->type & ROXML_NODE_TYPES) == ROXML_PI_NODE) {
1611  strcpy(head, "<?");
1612  strcpy(tail, "?>");
1613  } else {
1614  head[0] = '\0';
1615  tail[0] = '\0';
1616  }
1617 
1618  roxml_write_string(buf, f, head, offset, len);
1619 
1620  if (name[0]) {
1621  roxml_write_string(buf, f, name, offset, len);
1622  }
1623 
1624  value = roxml_get_content(n, val, ROXML_BASE_LEN, &status);
1625  if (status >= ROXML_BASE_LEN) {
1626  value = roxml_get_content(n, NULL, 0, &status);
1627  }
1628  if (name[0] && value && value[0]) {
1629  roxml_write_string(buf, f, " ", offset, len);
1630  }
1631  roxml_write_string(buf, f, value, offset, len);
1632  roxml_release(value);
1633 
1634  roxml_write_string(buf, f, tail, offset, len);
1635 
1636  if (human) {
1637  roxml_write_string(buf, f, "\n", offset, len);
1638  }
1639  ROXML_PUT_BASE_BUFFER(val);
1640  }
1641  ROXML_PUT_BASE_BUFFER(name);
1642 }
1643 #endif /* CONFIG_XML_COMMIT_XML_TREE */
1644 
1645 #if(CONFIG_XML_READ_WRITE==1)
1647 {
1648  node_t *attr = NULL;
1649  node_t *chld = NULL;
1650 
1651  if (!n) {
1652  return;
1653  }
1654 
1655  if (n->ns == ns) {
1656  if (n->prnt) {
1657  n->ns = n->prnt->ns;
1658  } else {
1659  n->ns = NULL;
1660  }
1661  }
1662 
1663  chld = n->chld;
1664  while (chld) {
1665  roxml_reset_ns(chld, ns);
1666  chld = chld->sibl;
1667  }
1668 
1669  attr = n->attr;
1670  while (attr) {
1671  if ((attr->type & ROXML_NS_NODE) == 0) {
1672  if (attr->ns == ns) {
1673  attr->ns = attr->prnt->ns;
1674  }
1675  }
1676  attr = attr->sibl;
1677  }
1678 }
1679 
1681 {
1682  node_t *current = n->prnt->attr;
1683 
1684  if (n->type & ROXML_NS_NODE) {
1685  roxml_reset_ns(n->prnt, n);
1686  }
1687 
1688  if (current == n) {
1689  n->prnt->attr = n->sibl;
1690  } else if (current) {
1691  while (current->sibl && current->sibl != n) {
1692  current = current->sibl;
1693  }
1694  current->sibl = n->sibl;
1695  }
1696  roxml_del_tree(n->chld);
1697  return;
1698 }
1699 #endif /* CONFIG_XML_READ_WRITE */
1700 
1701 /* do not call this function if n->prnt == NULL */
1702 static node_t *roxml_get_real_prev_sibling(node_t *n)
1703 {
1704  node_t *current = n->prnt->chld;
1705  node_t *prev = NULL;
1706 
1707  while (current != n) {
1708  prev = current;
1709  current = current->sibl;
1710  }
1711 
1712  return prev;
1713 }
1714 
1716 {
1717  node_t *current = n->prnt->chld;
1718  while (current && (current->type & ROXML_TXT_NODE) == 0) {
1719  current = current->sibl;
1720  }
1721  if (n->prnt && n->prnt->next == n) {
1722  n->prnt->next = roxml_get_real_prev_sibling(n);
1723  }
1724  if (current == n) {
1725  n->prnt->chld = n->sibl;
1726  } else if (current) {
1727  while (current->sibl && current->sibl != n) {
1728  current = current->sibl;
1729  }
1730  current->sibl = n->sibl;
1731  }
1732 
1733 }
1734 
1736 {
1737  node_t *current = n->prnt->chld;
1738  if (n->prnt && n->prnt->next == n) {
1739  n->prnt->next = roxml_get_real_prev_sibling(n);
1740  }
1741  if (current == n) {
1742  n->prnt->chld = n->sibl;
1743  } else if (current) {
1744  while (current->sibl && current->sibl != n) {
1745  current = current->sibl;
1746  }
1747  current->sibl = n->sibl;
1748  }
1749  roxml_del_tree(n->chld);
1750  roxml_del_tree(n->attr);
1751 }
1752 
int ROXML_INT roxml_read(int pos, int size, char *buffer, node_t *node)
read xml doc function
void ROXML_INT roxml_free_xpath(xpath_node_t *xpath, int nb)
xpath free function
xpath_node_t * new_node
Definition: roxml-types.h:220
void ROXML_INT roxml_close_node(node_t *n, node_t *close)
internal function
#define ROXML_NS_NODE
Definition: roxml.h:110
void ROXML_API roxml_close(node_t *n)
unload function
Definition: roxml.c:341
node_t structure
Definition: roxml-types.h:152
int ROXML_API roxml_get_nodes_nb(node_t *n, int type)
number of nodes getter function
Definition: roxml.c:359
node_t ROXML_API * roxml_get_txt(node_t *n, int nth)
text node getter function
Definition: roxml.c:524
struct _xpath_cond * next
Definition: roxml-types.h:85
int ROXML_INT roxml_double_cmp(double a, double b, int op)
double comparison function
struct node * attr
Definition: roxml-types.h:164
node_t ROXML_API * roxml_get_ns(node_t *n)
namespace getter function
Definition: roxml.c:494
#define ROXML_ATTR_NODE
Definition: roxml.h:59
node_t ROXML_API * roxml_get_attr(node_t *n, char *name, int nth)
attribute getter function
Definition: roxml.c:534
node_t ROXML_INT ** roxml_exec_xpath(node_t *root, node_t *n, xpath_node_t *xpath, int index, int *count)
real xpath execution
#define RELEASE_LAST
Definition: roxml.h:196
roxml_pos_t end
Definition: roxml-types.h:160
#define PTR_NODE_RESULT
void ROXML_INT roxml_compute_or(node_t *root, node_t **node_set, int *count, int req_id, int glob_id)
node set or function
int ROXML_API roxml_get_chld_nb(node_t *n)
chlds number getter function
Definition: roxml.c:539
int ROXML_API roxml_get_attr_nb(node_t *n)
number of attribute getter function
Definition: roxml.c:529
unsigned char id
Definition: roxml-types.h:139
#define ROXML_PENDING
node_t ROXML_INT * roxml_lookup_nsdef(node_t *nsdef, char *ns)
name space lookup in list
int roxml_is_number(char *input)
number tester
xpath_node_t * first_node
Definition: roxml-types.h:219
xpath_node_t ROXML_INT * roxml_set_axes(xpath_node_t *node, char *axes, int *offset)
axes setter function
unsigned char id
Definition: roxml-types.h:113
#define ROXML_PI_NODE
Definition: roxml.h:102
void ROXML_INT roxml_del_txt_node(node_t *n)
text node deletion function
struct node * chld
Definition: roxml-types.h:162
struct node * next
Definition: roxml-types.h:165
node_t * candidat_val
Definition: roxml-types.h:192
node_t * current_node
Definition: roxml-types.h:193
memory cell structure
Definition: roxml-types.h:59
int ROXML_INT roxml_parse_xpath(char *path, xpath_node_t **xpath, int context)
xpath parsing function
node_t * candidat_txt
Definition: roxml-types.h:190
char * alias
Definition: roxml-types.h:141
struct _xpath_tok * next
Definition: roxml-types.h:128
node_t ROXML_INT * roxml_load(node_t *current_node, FILE *file, char *buffer)
generic load function
#define ROXML_DOCTYPE_NODE
Definition: roxml.h:134
char * arg2
Definition: roxml-types.h:83
node_t * candidat_arg
Definition: roxml-types.h:191
struct node * sibl
Definition: roxml-types.h:161
xpath token structure
Definition: roxml-types.h:126
char * arg1
Definition: roxml-types.h:82
double ROXML_INT roxml_double_oper(double a, double b, int op)
double operation function
pthread_mutex_t mut
Definition: roxml-types.h:115
int ROXML_INT roxml_in_pool(node_t *root, node_t *n, int req_id)
node pool presence tester function
#define ROXML_BASE_LEN
#define ROXML_BUFF
struct _xpath_tok * next
Definition: roxml-types.h:116
#define ROXML_CMT_NODE
Definition: roxml.h:94
int ROXML_INT roxml_get_node_internal_position(node_t *n)
node absolute position get
void ROXML_INT roxml_compute_and(node_t *root, node_t **node_set, int *count, int cur_req_id, int prev_req_id)
node set and function
void ROXML_INT * roxml_malloc(int size, int num, int type)
alloc memory function
void * src
Definition: roxml-types.h:157
void ROXML_INT roxml_check_node(xpath_node_t *xp, node_t *root, node_t *context, node_t ***ans, int *nb, int *max, int ignore, int req_id)
real xpath validation function
void ROXML_INT roxml_release_id(node_t *root, node_t **pool, int pool_len, int req_id)
release id function
xpath node structure
Definition: roxml-types.h:95
int ROXML_INT roxml_is_separator(char sep)
separator tester
int ROXML_API roxml_get_node_position(node_t *n)
node get position function
Definition: roxml.c:609
void ROXML_INT roxml_process_begin_node(roxml_load_ctx_t *context, int position)
node creation during parsing
#define MAX_NS_LEN
Definition: roxml-defines.h:76
int ROXML_INT roxml_request_id(node_t *root)
id reservation function
node_t ROXML_INT * roxml_create_node(int pos, void *src, int type)
internal function
char ROXML_API * roxml_get_content(node_t *n, char *buffer, int bufsize, int *size)
content getter function
Definition: roxml.c:123
#define ROXML_INT
roxml_pos_t pos
Definition: roxml-types.h:159
void ROXML_INT roxml_reset_ns(node_t *n, node_t *ns)
internal function
void ROXML_API roxml_release(void *data)
memory cleanning function
Definition: roxml.c:28
struct node * ns
Definition: roxml-types.h:166
namespace structure
Definition: roxml-types.h:138
void ROXML_INT roxml_process_unaliased_ns(roxml_load_ctx_t *context)
namespace without alias name creation during parsing
memory_cell_t head_cell
head of memory manager
xml parsing context
Definition: roxml-types.h:177
node_t ROXML_INT * roxml_append_node(node_t *parent, node_t *n)
node append function
#define ROXML_FILE
void ROXML_INT roxml_del_tree(node_t *n)
internal function
#define PTR_NONE
node_t ROXML_API * roxml_get_root(node_t *n)
root getter function
Definition: roxml.c:589
char * name
Definition: roxml-types.h:99
struct _xpath_cond * cond
Definition: roxml-types.h:101
struct memory_cell * prev
Definition: roxml-types.h:65
node_t * namespaces
Definition: roxml-types.h:194
int ROXML_INT roxml_string_cmp(char *sa, char *sb, int op)
string comparison function
void ROXML_INT roxml_del_arg_node(node_t *n)
attribute node deletion function
void ROXML_INT roxml_free_node(node_t *n)
internal function
the parser item struct
Definition: roxml-types.h:230
#define ROXML_ELM_NODE
Definition: roxml.h:78
void ROXML_INT roxml_del_from_pool(node_t *root, node_t *n, int req_id)
pool node delete function
int ROXML_INT roxml_validate_predicat(xpath_node_t *xn, node_t *candidat)
predicat validation function
xpath parsing context
Definition: roxml-types.h:207
void * priv
Definition: roxml-types.h:167
struct node * prnt
Definition: roxml-types.h:163
struct _xpath_cond * xp_cond
Definition: roxml-types.h:100
void ROXML_INT roxml_print_space(FILE *f, char **buf, int *offset, int *len, int lvl)
space printing function
char ROXML_API * roxml_get_name(node_t *n, char *buffer, int size)
name getter function
Definition: roxml.c:228
#define ROXML_NODE_TYPES
Definition: roxml.h:158
unsigned char ids[256]
Definition: roxml-types.h:114
xpath cond structure
Definition: roxml-types.h:75
struct memory_cell * next
Definition: roxml-types.h:64
#define ROXML_TXT_NODE
Definition: roxml.h:86
unsigned short type
Definition: roxml-types.h:153
#define ROXML_BULK_READ
Definition: roxml-defines.h:86
node_t ROXML_INT * roxml_parent_node(node_t *parent, node_t *n, int position)
node relocate function
void ROXML_INT roxml_write_string(char **buf, FILE *f, char *str, int *offset, int *len)
string writter function
void ROXML_INT roxml_set_type(node_t *n, int type)
node type setter function
int ROXML_INT roxml_add_to_pool(node_t *root, node_t *n, int req_id)
add a token top node function
#define ROXML_INVALID
void ROXML_INT roxml_free_xcond(xpath_cond_t *xcond)
xpath condition free function
int ROXML_INT roxml_validate_axes(node_t *root, node_t *candidat, node_t ***ans, int *nb, int *max, xpath_node_t *xn, int req_id)
axe validation function
void ROXML_INT roxml_write_node(node_t *n, FILE *f, char **buf, int human, int lvl, int *offset, int *len)
tree write function
unsigned char id
Definition: roxml-types.h:127
struct _xpath_node * next
Definition: roxml-types.h:102
pthread_t id
Definition: roxml-types.h:63
struct _xpath_node * xp
Definition: roxml-types.h:84
node_t * candidat_node
Definition: roxml-types.h:189
xpath_cond_t * new_cond
Definition: roxml-types.h:221
void ROXML_INT roxml_del_std_node(node_t *n)
node deletion function
xpath token structure
Definition: roxml-types.h:112
#define ROXML_CDATA_NODE
Definition: roxml.h:126
internal header for libroxml.so