<libroxml  version="3.0.2" />
contact: tristan.lelong@libroxml.net
roxml_content.c
Go to the documentation of this file.
1
12#include <string.h>
13#include <stdlib.h>
14#include "roxml_mem.h"
15#include "roxml_file.h"
16#include "roxml_buff.h"
17
19 char code;
20 char *escape;
21};
22
23struct roxml_escape_char specials[5] = {
24 { .code = '"', .escape = "&quot;" },
25 { .code = '\'', .escape = "&apos;" },
26 { .code = '<', .escape = "&lt;"},
27 { .code = '>', .escape = "&gt;"},
28 { .code = '&', .escape = "&amp;"}
29};
30
31ROXML_API int roxml_escape(const char *buf, int decode, char *out)
32{
33 size_t i = 0;
34 size_t l = 0;
35 for (; i < strlen(buf); ) {
36 int s = 0;
37 for (; s < 5; s++) {
38 if (decode && (strncmp(specials[s].escape, buf+i, strlen(specials[s].escape)) == 0)) {
39 if (out)
40 out[l] = specials[s].code;
41 l += 1;
42 i += strlen(specials[s].escape);
43 break;
44 } else if (!decode && (buf[i] == specials[s].code)) {
45 if (out)
46 strcpy(out+l, specials[s].escape);
47 l += strlen(specials[s].escape);
48 i += 1;
49 break;
50 }
51 }
52 if (s == 5) {
53 if (out)
54 out[l] = buf[i];
55 l += 1;
56 i += 1;
57 }
58 }
59 if (out)
60 out[l] = '\0';
61 return l;
62}
63
74ROXML_STATIC ROXML_INT inline int roxml_read(int pos, int size, char *buffer, node_t *node)
75{
76 int len = 0;
77
78 if (size > 0 && buffer) {
79 if (node->type & ROXML_FILE)
80 len = roxml_read_file(pos, size, buffer, node);
81 else
82 len = roxml_read_buff(pos, size, buffer, node);
83 }
84
85 return len;
86}
87
88ROXML_STATIC ROXML_INT inline int roxml_content_size(node_t *n, int *offset)
89{
90 int total = 0;
91
92 *offset = 0;
93
94 if (!n)
95 return 0;
96
97 if (n->type & ROXML_ELM_NODE) {
98 node_t *ptr = n->chld;
99 while (ptr) {
100 if ((ptr->type & ROXML_NODE_TYPES) == ROXML_TXT_NODE)
101 total += ptr->end - ptr->pos;
102 ptr = ptr->sibl;
103 }
104 } else if (n->type & ROXML_ATTR_NODE) {
105 if (n->chld) {
106 total = n->chld->end - n->chld->pos;
107 *offset = n->chld->pos;
108 }
109 } else {
110 int name_len = 0;
111
112 ROXML_GET_BASE_BUFFER(name);
113
115 name_len = strlen(name);
116
117 ROXML_PUT_BASE_BUFFER(name);
118
119 if (n->type & ROXML_DOCTYPE_NODE)
120 name_len += 2;
121 else if (n->type & ROXML_TXT_NODE)
122 name_len = 0;
123 else if (n->type & ROXML_CMT_NODE)
124 name_len = 4;
125 else if (n->type & ROXML_PI_NODE)
126 name_len += 3;
127
128 total = n->end - n->pos - name_len;
129 *offset = n->pos + name_len;
130 }
131 return total;
132}
133
134ROXML_STATIC ROXML_INT inline char *roxml_prepare_buffer(node_t *n, char *buffer, int contentsize, int size)
135{
136 if (n == NULL) {
137 if (buffer)
138 memset(buffer, 0, size);
139 return NULL;
140 }
141 if (buffer == NULL)
142 buffer = roxml_malloc(sizeof(char), contentsize + 1, PTR_CHAR);
143 memset(buffer, 0, size);
144
145 return buffer;
146}
147
148ROXML_API char *roxml_get_content(node_t *n, char *buffer, int bufsize, int *size)
149{
150 int total = 0;
151 int content_offset;
152 int content_size;
153 char *content;
154
155 if (n == ROXML_INVALID_DOC)
156 return NULL;
157
158 content_size = roxml_content_size(n, &content_offset);
159 content = roxml_prepare_buffer(n, buffer, content_size, bufsize);
160
161 if (buffer != content)
162 bufsize = content_size + 1;
163 if (content_size > bufsize - 1)
164 content_size = bufsize - 1;
165 if (content == NULL) {
166 if (size)
167 *size = 0;
168 return buffer;
169 }
170
171 if (n->type & ROXML_ELM_NODE) {
172 node_t *ptr = n->chld;
173
174 while (ptr) {
175 if (ptr->type & ROXML_TXT_NODE) {
176 int len = 0;
177 int read_size = ptr->end - ptr->pos;
178
179 if (total + read_size > bufsize - 1)
180 read_size = bufsize - total - 1;
181 len += roxml_read(ptr->pos, read_size, content + total, ptr);
182
183 total += len;
184 }
185 ptr = ptr->sibl;
186 }
187 } else {
188 node_t *target = n;
189 if (n->type & ROXML_ATTR_NODE)
190 target = n->chld;
191 total = roxml_read(content_offset, content_size, content, target);
192 }
193
194 content[total] = '\0';
195 if (size)
196 *size = total + 1;
197 return content;
198}
199
200ROXML_STATIC ROXML_INT inline int roxml_name_size(node_t *n, int size, int *offset)
201{
202 int total = 0;
203
204 *offset = 0;
205
206 if (!n)
207 return 0;
208
209 if ((n->type & ROXML_TXT_NODE) || (n->type & ROXML_CMT_NODE)) {
210 total = 0;
211 } else {
212 *offset = n->pos;
213
214 if (n->type & ROXML_PI_NODE)
215 *offset += 2;
216 else if (n->type & ROXML_DOCTYPE_NODE)
217 *offset += 1;
218
219 total = ROXML_BASE_LEN;
220 }
221
222 return total;
223}
224
225ROXML_API char *roxml_get_name(node_t *n, char *buffer, int size)
226{
227 int content_offset;
228 int content_size;
229 char *content;
230
231 if (n == ROXML_INVALID_DOC)
232 return NULL;
233
234 content_size = roxml_name_size(n, size, &content_offset);
235 content = roxml_prepare_buffer(n, buffer, content_size, size);
236
237 if (buffer != content)
238 size = content_size + 1;
239 if (content_size > size - 1)
240 content_size = size - 1;
241 if (content == NULL)
242 return buffer;
243 if (content_size == 0)
244 return content;
245
246 memset(content, 0, content_size);
247
248 if (n->prnt == NULL) {
249 strcpy(content, "documentRoot");
250 } else if (n->type & ROXML_NS_NODE) {
251 roxml_ns_t *ns = (roxml_ns_t *)n->priv;
252 if (ns)
253 strncpy(content, ns->alias, size);
254 else
255 content[0] = '\0';
256 } else {
257 int total = 0;
258 int count = 0;
259 char *begin = content;
260
261 total = roxml_read(content_offset, content_size, content, n);
262
263 while (ROXML_WHITE(begin[0]) || begin[0] == '<')
264 begin++;
265
266 if (n->type & ROXML_PI_NODE) {
267 for (; count < total; count++) {
268 if (ROXML_WHITE(begin[count]))
269 break;
270 else if ((begin[count] == '?') && (begin[count + 1] == '>'))
271 break;
272 }
273 } else if (n->type & ROXML_ELM_NODE) {
274 for (; count < total; count++) {
275 if (ROXML_WHITE(begin[count]))
276 break;
277 else if ((begin[count] == '/') && (begin[count + 1] == '>'))
278 break;
279 else if (begin[count] == '>')
280 break;
281 }
282 } else if (n->type & ROXML_ATTR_NODE) {
283 for (; count < total; count++) {
284 if (ROXML_WHITE(begin[count]))
285 break;
286 else if (begin[count] == '=')
287 break;
288 else if (begin[count] == '>')
289 break;
290 else if ((begin[count] == '/') && (begin[count + 1] == '>'))
291 break;
292 }
293 } else if (n->type & ROXML_DOCTYPE_NODE) {
294 for (; count < total; count++) {
295 if (ROXML_WHITE(begin[count]))
296 break;
297 else if (begin[count] == '>')
298 break;
299 }
300 }
301 begin[count++] = '\0';
302 memmove(content, begin, count);
303 }
304
305 return content;
306}
307
309{
310 node_t *ptr = n;
311 int nb;
312
313 if (n == ROXML_INVALID_DOC)
314 return -1;
315
316 nb = 0;
317 if (ptr->chld) {
318 ptr = ptr->chld;
319 do {
320 if (ptr->type & type)
321 nb++;
322 ptr = ptr->sibl;
323 } while (ptr);
324 }
325
326 if (type & ROXML_ATTR_NODE) {
327 ptr = n->attr;
328 while (ptr) {
329 nb++;
330 ptr = ptr->sibl;
331 }
332 }
333 return nb;
334}
335
336ROXML_STATIC ROXML_INT inline node_t *roxml_get_nodes_by_name(node_t *n, int type, char *name)
337{
338 node_t *ptr;
339
340 if (n->attr && (type & ROXML_ATTR_NODE))
341 ptr = n->attr;
342 else
343 ptr = n->chld;
344
345 while (ptr) {
346 if ((ptr->type & ROXML_NODE_TYPES) & type) {
347 int ans = strcmp(roxml_get_name(ptr, NULL, 0), name);
349 if (ans == 0)
350 return ptr;
351 }
352 ptr = ptr->sibl;
353 }
354 return NULL;
355}
356
357ROXML_STATIC ROXML_INT inline node_t *roxml_get_nodes_by_nth(node_t *n, int type, int nth)
358{
359 node_t *ptr;
360 int count = 0;
361
362 if (n->ns && (type & ROXML_NS_NODE)) {
363 ptr = n->ns;
364 if (nth == 0)
365 return ptr;
366 } else if (n->attr && (type & ROXML_ATTR_NODE)) {
367 ptr = n->attr;
368 if (nth == 0)
369 return ptr;
370 while ((ptr->sibl) && (nth > count)) {
371 ptr = ptr->sibl;
372 count++;
373 }
374 } else {
375 ptr = n->chld;
376 while (ptr && !((ptr->type & ROXML_NODE_TYPES) & type))
377 ptr = ptr->sibl;
378 }
379 if (nth > count) {
380 ptr = n->chld;
381 while (ptr && !((ptr->type & ROXML_NODE_TYPES) & type))
382 ptr = ptr->sibl;
383 while (ptr && (ptr->sibl) && (nth > count)) {
384 ptr = ptr->sibl;
385 if ((ptr->type & ROXML_NODE_TYPES) & type)
386 count++;
387 }
388 }
389 if (nth > count)
390 return NULL;
391 return ptr;
392}
393
394ROXML_API node_t *roxml_get_nodes(node_t *n, int type, char *name, int nth)
395{
396 if (n == ROXML_INVALID_DOC)
397 return ROXML_INVALID_DOC;
398 else if (name == NULL)
399 return roxml_get_nodes_by_nth(n, type, nth);
400 else
401 return roxml_get_nodes_by_name(n, type, name);
402}
403
405{
406 return roxml_get_nodes(n, ROXML_NS_NODE, NULL, 0);
407}
408
410{
412}
413
415{
416 return roxml_get_nodes(n, ROXML_PI_NODE, NULL, nth);
417}
418
420{
422}
423
425{
426 return roxml_get_nodes(n, ROXML_CMT_NODE, NULL, nth);
427}
428
430{
432}
433
435{
436 return roxml_get_nodes(n, ROXML_TXT_NODE, NULL, nth);
437}
438
440{
442}
443
444ROXML_API inline node_t *roxml_get_attr(node_t *n, char *name, int nth)
445{
446 return roxml_get_nodes(n, ROXML_ATTR_NODE, name, nth);
447}
448
450{
452}
453
454ROXML_API inline node_t *roxml_get_chld(node_t *n, char *name, int nth)
455{
456 return roxml_get_nodes(n, ROXML_ELM_NODE, name, nth);
457}
458
460{
461 if (n == ROXML_INVALID_DOC)
462 return ROXML_INVALID_NODE;
463 return (n->type & ROXML_NODE_TYPES);
464}
465
467{
468 int idx = 1;
469 char name[256];
470 node_t *prnt;
471 node_t *first;
472
473 if (n == ROXML_INVALID_DOC)
474 return 0;
475
476 roxml_get_name(n, name, 256);
477
478 prnt = n->prnt;
479 if (!prnt)
480 return 1;
481 first = prnt->chld;
482
483 while ((first) && (first != n)) {
484 char twin[256];
485
486 roxml_get_name(first, twin, 256);
487 if (strcmp(name, twin) == 0)
488 idx++;
489 first = first->sibl;
490 }
491
492 return idx;
493}
#define ROXML_CMT_NODE
Definition roxml.h:86
#define RELEASE_LAST
Definition roxml.h:228
#define ROXML_PI_NODE
Definition roxml.h:94
#define ROXML_INVALID_DOC
Definition roxml.h:235
ROXML_API void roxml_release(void *data)
memory cleanning function
Definition roxml_mem.c:109
#define ROXML_ATTR_NODE
Definition roxml.h:51
#define ROXML_NS_NODE
Definition roxml.h:102
#define ROXML_TXT_NODE
Definition roxml.h:78
#define ROXML_ELM_NODE
Definition roxml.h:70
#define ROXML_API
Definition roxml.h:24
#define ROXML_INVALID_NODE
Definition roxml.h:43
#define ROXML_NODE_TYPES
Definition roxml.h:158
#define ROXML_DOCTYPE_NODE
Definition roxml.h:134
ROXML_INT int roxml_read_buff(int pos, int size, char *buffer, node_t *node)
read xml doc function
Definition roxml_buff.c:16
buffer XML document backend
ROXML_API int roxml_get_pi_nb(node_t *n)
process-instruction number getter function
ROXML_API node_t * roxml_get_pi(node_t *n, int nth)
process-instruction getter function
ROXML_API int roxml_get_chld_nb(node_t *n)
chlds number getter function
ROXML_API node_t * roxml_get_txt(node_t *n, int nth)
text node getter function
ROXML_API int roxml_get_cmt_nb(node_t *n)
comments number getter function
ROXML_API node_t * roxml_get_chld(node_t *n, char *name, int nth)
chld getter function
ROXML_API int roxml_get_txt_nb(node_t *n)
text node number getter function
ROXML_API node_t * roxml_get_attr(node_t *n, char *name, int nth)
attribute getter function
ROXML_API int roxml_get_nodes_nb(node_t *n, int type)
number of nodes getter function
ROXML_API int roxml_get_type(node_t *n)
node type function
ROXML_API int roxml_get_node_position(node_t *n)
node get position function
ROXML_API int roxml_get_attr_nb(node_t *n)
number of attribute getter function
ROXML_API char * roxml_get_content(node_t *n, char *buffer, int bufsize, int *size)
content getter function
ROXML_API node_t * roxml_get_ns(node_t *n)
namespace getter function
ROXML_API char * roxml_get_name(node_t *n, char *buffer, int size)
name getter function
ROXML_API int roxml_escape(const char *buf, int decode, char *out)
XML encoding/decoding function.
ROXML_STATIC ROXML_INT int roxml_read(int pos, int size, char *buffer, node_t *node)
read xml doc function
ROXML_API node_t * roxml_get_cmt(node_t *n, int nth)
comment getter function
ROXML_API node_t * roxml_get_nodes(node_t *n, int type, char *name, int nth)
nodes getter function
#define PTR_CHAR
#define ROXML_WHITE(n)
#define ROXML_BASE_LEN
#define ROXML_FILE
ROXML_INT int roxml_read_file(int pos, int size, char *buffer, node_t *node)
read xml doc function
Definition roxml_file.c:18
File XML document backend.
ROXML_INT void * roxml_malloc(int size, int num, int type)
alloc memory function
Definition roxml_mem.c:124
XML internal memory management module.
node_t structure
struct node * prnt
roxml_pos_t pos
unsigned short type
struct node * ns
roxml_pos_t end
void * priv
struct node * chld
struct node * attr
struct node * sibl
namespace structure
char * alias