1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2012-2014 - Scilab Enterprises - Calixte DENIZET
4 *
5 * Copyright (C) 2012 - 2016 - Scilab Enterprises
6 *
7 * This file is hereby licensed under the terms of the GNU GPL v2.0,
8 * pursuant to article 5.3.4 of the CeCILL v.2.1.
9 * This file was originally licensed under the terms of the CeCILL v2.1,
10 * and continues to be available under such terms.
11 * For more information, see the COPYING file which you should have received
12 * along with this program.
13 *
14 */
15
16 #include <string>
17
18 #include "XMLObject.hxx"
19 #include "XMLDocument.hxx"
20 #include "XMLAttr.hxx"
21 #include "XMLElement.hxx"
22 #include "XMLNodeList.hxx"
23 #include "VariableScope.hxx"
24
25 namespace org_modules_xml
26 {
27
XMLNodeList(const XMLDocument & _doc,xmlNode * _parent)28 XMLNodeList::XMLNodeList(const XMLDocument & _doc, xmlNode * _parent): XMLList(), doc(_doc)
29 {
30 parent = _parent;
31 size = getNodeListSize(parent->children);
32 prev = 1;
33 prevNode = parent->children;
34 scope->registerPointers(parent->children, this);
35 id = scope->getVariableId(*this);
36 }
37
~XMLNodeList()38 XMLNodeList::~XMLNodeList()
39 {
40 scope->unregisterNodeListPointer(parent->children);
41 scope->removeId(id);
42 }
43
getRealXMLPointer() const44 void *XMLNodeList::getRealXMLPointer() const
45 {
46 return static_cast < void *>(parent->children);
47 }
48
getContentFromList() const49 const char **XMLNodeList::getContentFromList() const
50 {
51 const char **list = new const char *[size];
52 int i = 0;
53 for (xmlNode * cur = parent->children; cur; cur = cur->next, i++)
54 {
55 list[i] = (const char *)xmlNodeGetContent(cur);
56 }
57
58 return list;
59 }
60
getNameFromList() const61 const char **XMLNodeList::getNameFromList() const
62 {
63 const char **list = new const char *[size];
64 int i = 0;
65 for (xmlNode * cur = parent->children; cur; cur = cur->next, i++)
66 {
67 list[i] = cur->name ? (const char *)cur->name : "";
68 }
69
70 return list;
71 }
72
setAttributeValue(const char ** prefix,const char ** name,const char ** value,int lsize) const73 void XMLNodeList::setAttributeValue(const char **prefix, const char **name, const char **value, int lsize) const
74 {
75 for (xmlNode * cur = parent->children; cur; cur = cur->next)
76 {
77 XMLAttr::setAttributeValue(cur, prefix, name, value, lsize);
78 }
79 }
80
setAttributeValue(const char ** name,const char ** value,int lsize) const81 void XMLNodeList::setAttributeValue(const char **name, const char **value, int lsize) const
82 {
83 for (xmlNode * cur = parent->children; cur; cur = cur->next)
84 {
85 XMLAttr::setAttributeValue(cur, name, value, lsize);
86 }
87 }
88
remove() const89 void XMLNodeList::remove() const
90 {
91 xmlNode *cur = parent->children;
92
93 while (cur != NULL)
94 {
95 xmlNode *nxt = cur->next;
96 xmlUnlinkNode(cur);
97 xmlFreeNode(cur);
98 cur = nxt;
99 }
100 }
101
getXMLObjectParent() const102 const XMLObject *XMLNodeList::getXMLObjectParent() const
103 {
104 return &doc;
105 }
106
dump() const107 const std::string XMLNodeList::dump() const
108 {
109 xmlBufferPtr buffer = xmlBufferCreate();
110 for (xmlNode * cur = parent->children; cur; cur = cur->next)
111 {
112 xmlNodeDump(buffer, doc.getRealDocument(), cur, 0, 1);
113 xmlBufferAdd(buffer, (xmlChar *) "\n", (int)strlen("\n"));
114 }
115 std::string str = std::string((const char *)buffer->content);
116
117 xmlBufferFree(buffer);
118
119 return str;
120 }
121
getListElement(int index)122 const XMLObject *XMLNodeList::getListElement(int index)
123 {
124 xmlNode *n = getListNode(index);
125
126 if (n)
127 {
128 XMLObject *obj = scope->getXMLObjectFromLibXMLPtr(n);
129
130 if (obj)
131 {
132 return static_cast < XMLElement * >(obj);
133 }
134
135 return new XMLElement(doc, n);
136 }
137
138 return 0;
139 }
140
removeElementAtPosition(int index)141 void XMLNodeList::removeElementAtPosition(int index)
142 {
143 if (size && index >= 1 && index <= size)
144 {
145 if (index == 1)
146 {
147 xmlNode *n = parent->children;
148
149 scope->unregisterNodeListPointer(n);
150 xmlUnlinkNode(n);
151 xmlFreeNode(n);
152 size--;
153 if (size == 0)
154 {
155 parent->children = 0;
156 }
157 prevNode = parent->children;
158 scope->registerPointers(parent->children, this);
159 prev = 1;
160 }
161 else
162 {
163 xmlNode *n = getListNode(index);
164
165 if (n)
166 {
167 xmlNode *next = n->next;
168
169 prevNode = prevNode->prev;
170 prev--;
171 xmlUnlinkNode(n);
172 xmlFreeNode(n);
173 prevNode->next = next;
174 size--;
175 }
176 }
177 }
178 }
179
setElementAtPosition(double index,const XMLElement & elem)180 void XMLNodeList::setElementAtPosition(double index, const XMLElement & elem)
181 {
182 if (size == 0)
183 {
184 insertAtEnd(elem);
185 prevNode = parent->children;
186 prev = 1;
187 }
188 else if (index < 1)
189 {
190 insertAtBeginning(elem);
191 }
192 else if (index > size)
193 {
194 insertAtEnd(elem);
195 }
196 else if ((int)index == index)
197 {
198 replaceAtIndex((int)index, elem);
199 }
200 else
201 {
202 insertAtIndex((int)index, elem);
203 }
204 }
205
setElementAtPosition(double index,const XMLDocument & document)206 void XMLNodeList::setElementAtPosition(double index, const XMLDocument & document)
207 {
208 const XMLElement *e = document.getRoot();
209
210 setElementAtPosition(index, *e);
211 delete e;
212 }
213
setElementAtPosition(double index,const std::string & xmlCode)214 void XMLNodeList::setElementAtPosition(double index, const std::string & xmlCode)
215 {
216 std::string error;
217 XMLDocument document = XMLDocument(xmlCode, false, &error);
218
219 if (error.empty())
220 {
221 setElementAtPosition(index, document);
222 }
223 else
224 {
225 xmlNode *n = xmlNewText((xmlChar *) xmlCode.c_str());
226
227 setElementAtPosition(index, XMLElement(doc, n));
228 }
229 }
230
setElementAtPosition(double index,const XMLNodeList & list)231 void XMLNodeList::setElementAtPosition(double index, const XMLNodeList & list)
232 {
233 if (list.getSize() && list.getRealNode() != parent)
234 {
235 xmlNode * node = 0;
236 xmlNode * snode = 0;
237 int pos = (int)index;
238
239 if (index < 1)
240 {
241 pos = 1;
242 }
243 else if (index > size)
244 {
245 pos = size + 1;
246 }
247 else if ((int)index != index)
248 {
249 pos++;
250 }
251
252 if (&list == this)
253 {
254 snode = node = xmlCopyNode(list.getRealNode(), 1);
255 for (xmlNode * cur = list.getRealNode()->next; cur; cur = cur->next)
256 {
257 node->next = xmlCopyNode(cur, 1);
258 node = node->next;
259 }
260 node = snode;
261 }
262 else
263 {
264 node = list.getRealNode();
265 }
266
267 setElementAtPosition(index, XMLElement(doc, node));
268 for (xmlNode * cur = node->next; cur; cur = cur->next)
269 {
270 setElementAtPosition((double)(pos++) + 0.5, XMLElement(doc, cur));
271 }
272 }
273 }
274
replaceAtIndex(int index,const XMLElement & elem)275 void XMLNodeList::replaceAtIndex(int index, const XMLElement & elem)
276 {
277 xmlNode *n = getListNode(index);
278
279 if (n && n != elem.getRealNode())
280 {
281 if (index == 1)
282 {
283 scope->unregisterNodeListPointer(parent->children);
284 }
285 xmlNode *previous = n->prev;
286 xmlNode *next = n->next;
287 xmlNode *cpy = xmlCopyNode(elem.getRealNode(), 1);
288 xmlUnlinkNode(cpy);
289 xmlReplaceNode(n, cpy);
290 xmlFreeNode(n);
291 prevNode = cpy;
292 cpy->prev = previous;
293 cpy->next = next;
294 if (index == 1)
295 {
296 scope->registerPointers(parent->children, this);
297 }
298 }
299 }
300
insertAtEnd(const XMLElement & elem)301 void XMLNodeList::insertAtEnd(const XMLElement & elem)
302 {
303 xmlNode *cpy = xmlCopyNode(elem.getRealNode(), 1);
304
305 xmlUnlinkNode(cpy);
306 xmlAddChild(parent, cpy);
307 size++;
308 }
309
insertAtBeginning(const XMLElement & elem)310 void XMLNodeList::insertAtBeginning(const XMLElement & elem)
311 {
312 xmlNode *cpy = xmlCopyNode(elem.getRealNode(), 1);
313
314 xmlUnlinkNode(cpy);
315 scope->unregisterNodeListPointer(parent->children);
316 xmlAddPrevSibling(parent->children, cpy);
317 scope->registerPointers(parent->children, this);
318 size++;
319 }
320
insertAtIndex(int index,const XMLElement & elem)321 void XMLNodeList::insertAtIndex(int index, const XMLElement & elem)
322 {
323 xmlNode *n = getListNode(index);
324
325 if (n)
326 {
327 xmlNode *cpy = xmlCopyNode(elem.getRealNode(), 1);
328
329 xmlUnlinkNode(cpy);
330 xmlAddNextSibling(n, cpy);
331 size++;
332 }
333 }
334
getListNode(int index)335 xmlNode *XMLNodeList::getListNode(int index)
336 {
337 return XMLList::getListElement < xmlNode > (index, size, &prev, &prevNode);
338 }
339
revalidateSize()340 void XMLNodeList::revalidateSize()
341 {
342 size = getNodeListSize(parent->children);
343 prevNode = parent->children;
344 prev = 1;
345 }
346
getNodeListSize(xmlNode * node)347 int XMLNodeList::getNodeListSize(xmlNode * node)
348 {
349 int i = 0;
350
351 for (xmlNode * n = node; n; n = n->next, i++)
352 {
353 ;
354 }
355
356 return i;
357 }
358 }
359