src/server/webdav/xml.c

branch
webdav
changeset 223
bbaec8415c10
parent 211
2160585200ac
child 224
0de1ec82628e
equal deleted inserted replaced
222:5f05e56cb8e2 223:bbaec8415c10
28 28
29 #include <stdio.h> 29 #include <stdio.h>
30 #include <stdlib.h> 30 #include <stdlib.h>
31 #include <string.h> 31 #include <string.h>
32 32
33
33 #include "xml.h" 34 #include "xml.h"
34 35
36 typedef struct StackElm {
37 WSXmlNode *node; // list of nodes
38 WSXmlNode *parent; // if not NULL, call endcb after node->next is NULL
39 struct StackElm *next;
40 } StackElm;
35 41
42 #define STACK_PUSH(stack, elm) if(stack) { elm->next = stack; } stack = elm;
36 43
44 int wsxml_iterator(
45 pool_handle_t *pool,
46 WSXmlNode *node,
47 wsxml_func begincb,
48 wsxml_func endcb,
49 void *udata)
50 {
51 if(!node) {
52 return 0;
53 }
54
55 StackElm *stack = pool_malloc(pool, sizeof(StackElm));
56 if(!stack) {
57 return 1; // OOM
58 }
59 stack->next = NULL;
60 stack->node = node;
61 stack->parent = NULL;
62
63 int ret = 0;
64 int br = 0;
65 while(stack) {
66 StackElm *cur = stack;
67 WSXmlNode *xmlnode = cur->node; // get top stack element
68 stack = cur->next; // and remove it
69 cur->next = NULL;
70
71 while(xmlnode) {
72 // element begin callback
73 if(begincb(xmlnode, udata)) {
74 br = 1;
75 break; // I don't like break with labels - is this wrong?
76 }
77
78 if(xmlnode->children) {
79 // put the children on the stack
80 // the next stack iteration will process the children
81 StackElm *newelm = pool_malloc(pool, sizeof(StackElm));
82 if(!newelm) {
83 ret = 1;
84 br = 1;
85 break;
86 }
87 newelm->next = NULL;
88 newelm->node = xmlnode->children;
89 // setting the parent will make sure endcb will be called
90 // for the current xmlnode after all children are processed
91 newelm->parent = xmlnode;
92
93 // if xmlnode->next is not NULL, there are still nodes at
94 // this level, therefore we have to put these also on the
95 // stack
96 // this way, the remaining nodes are processed after all
97 // children of the current node are processed
98 if(xmlnode->next) {
99 // reuse current StackElm
100 cur->node = xmlnode->next;
101 STACK_PUSH(stack, cur);
102 cur = NULL;
103 }
104
105 // now we can put the children on the stack
106 STACK_PUSH(stack, newelm);
107 // break, because we don't want to process xmlnode->next now
108 break;
109 } else {
110 // no children means, the end callback can be called directly
111 // after the begin callback (no intermediate nodes)
112 if(endcb(xmlnode, udata)) {
113 br = 1;
114 break;
115 }
116 }
117
118 // continue with next node at this level
119 xmlnode = xmlnode->next;
120 }
121 if(br) {
122 break; // break because of an error
123 }
124
125 if(cur) {
126 if(cur->parent) {
127 if(endcb(cur->parent, udata)) {
128 break;
129 }
130 }
131 pool_free(pool, cur);
132 }
133 }
134
135 // free all remaining elements
136 StackElm *elm = stack;
137 while(elm) {
138 StackElm *next = elm->next;
139 pool_free(pool, elm);
140 elm = next;
141 }
142
143 return ret;
144 }
145

mercurial