1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2012 - 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 "VariableScope.hxx"
17 #include "XMLObject.hxx"
18 #include "XMLNodeList.hxx"
19 #include <iostream>
20
21 namespace org_modules_xml
22 {
23 xmlFreeFunc VariableScope::XMLFreeFunc = 0;
24 std::map < void *, XMLObject * > VariableScope::mapLibXMLToXMLObject = std::map < void *, XMLObject * >();
25 std::map < void *, XMLNodeList * > VariableScope::mapLibXMLToXMLNodeList = std::map < void *, XMLNodeList * >();
26 std::map < const XMLObject *, std::map < const XMLObject *, bool>*> VariableScope::parentToChildren = std::map < const XMLObject *, std::map < const XMLObject *, bool>*>();
27
VariableScope(int _initialSize)28 VariableScope::VariableScope(int _initialSize)
29 {
30 position = -1;
31 initialSize = _initialSize;
32 scope = new std::vector < XMLObject * >();
33 freePlaces = new std::stack < int >();
34 initXMLMemory();
35 }
36
~VariableScope()37 VariableScope::~VariableScope()
38 {
39 for (unsigned int i = 0; i < scope->size(); i++)
40 {
41 if ((*scope)[i])
42 {
43 delete(*scope)[i];
44 }
45 }
46 delete scope;
47 delete freePlaces;
48 }
49
50 /**
51 * To avoid unused place in the vector, we use a stack which contains the empty places.
52 */
getVariableId(const XMLObject & obj)53 int VariableScope::getVariableId(const XMLObject & obj)
54 {
55 int returnValue;
56 const XMLObject *parent = obj.getXMLObjectParent();
57
58 if (freePlaces->size() != 0)
59 {
60 returnValue = freePlaces->top();
61 freePlaces->pop();
62 (*scope)[returnValue] = const_cast < XMLObject * >(&obj);
63 }
64 else
65 {
66 returnValue = (int)scope->size();
67 scope->push_back(const_cast < XMLObject * >(&obj));
68 }
69
70 if (parent)
71 {
72 std::map < const XMLObject *, std::map < const XMLObject *, bool>*>::const_iterator it = parentToChildren.find(parent);
73
74 if (it != parentToChildren.end())
75 {
76 std::map < const XMLObject *, bool>::iterator jt = it->second->find(&obj);
77 if (jt != it->second->end())
78 {
79 jt->second = true;
80 }
81 else
82 {
83 it->second->insert(std::pair<const XMLObject *, bool>(&obj, true));
84 }
85 }
86 else
87 {
88 std::map < const XMLObject *, bool> * map = new std::map < const XMLObject *, bool>();
89 map->insert(std::pair<const XMLObject *, bool>(&obj, true));
90 parentToChildren.insert(std::pair<const XMLObject *, std::map < const XMLObject *, bool>*>(parent, map));
91 }
92 }
93
94 return returnValue;
95 }
96
getVariableFromId(int id)97 XMLObject *VariableScope::getVariableFromId(int id)
98 {
99 if (id >= 0 && id < (int)scope->size())
100 {
101 return (*scope)[id];
102 }
103
104 return 0;
105 }
106
107 /**
108 * There are two motivations to register libxml pointers:
109 * i) if a XMLObject is associated to a libxml node, then when this node will be removed
110 * the XMLObject must be destroyed. This job is done in _xmlFreeFunc which is called
111 * by libxml when a libxml node is freed.
112 * ii) To avoid multiple instances of a XMLObject which wraps the same node, the function
113 * getXMLObjectFromLibXMLPtr is used to know if a XMLObject already exists for the
114 * libxml node.
115 */
registerPointers(void * libxml,XMLObject * obj)116 void VariableScope::registerPointers(void *libxml, XMLObject * obj)
117 {
118 if (libxml)
119 {
120 mapLibXMLToXMLObject[libxml] = obj;
121 }
122 }
123
registerPointers(void * libxml,XMLNodeList * nodeList)124 void VariableScope::registerPointers(void *libxml, XMLNodeList * nodeList)
125 {
126 if (libxml)
127 {
128 mapLibXMLToXMLNodeList[libxml] = nodeList;
129 }
130 }
131
unregisterPointer(void * libxml)132 void VariableScope::unregisterPointer(void *libxml)
133 {
134 if (libxml)
135 {
136 mapLibXMLToXMLObject.erase(libxml);
137 }
138 }
139
unregisterNodeListPointer(void * libxml)140 void VariableScope::unregisterNodeListPointer(void *libxml)
141 {
142 if (libxml)
143 {
144 mapLibXMLToXMLNodeList.erase(libxml);
145 }
146 }
147
getXMLObjectFromLibXMLPtr(void * libxml) const148 XMLObject *VariableScope::getXMLObjectFromLibXMLPtr(void *libxml) const
149 {
150 if (libxml)
151 {
152 std::map < void *, XMLObject * >::const_iterator it = mapLibXMLToXMLObject.find(libxml);
153 if (it != mapLibXMLToXMLObject.end())
154 {
155 return it->second;
156 }
157 }
158
159 return 0;
160 }
161
getXMLNodeListFromLibXMLPtr(void * libxml) const162 XMLNodeList *VariableScope::getXMLNodeListFromLibXMLPtr(void *libxml)const
163 {
164 if (libxml)
165 {
166 std::map < void *, XMLNodeList * >::const_iterator it = mapLibXMLToXMLNodeList.find(libxml);
167 if (it != mapLibXMLToXMLNodeList.end())
168 {
169 return it->second;
170 }
171 }
172
173 return 0;
174 }
175
removeId(int id)176 void VariableScope::removeId(int id)
177 {
178 if (id >= 0 && id < (int)scope->size() && (*scope)[id])
179 {
180 XMLObject * const child = (*scope)[id];
181 removeChildFromParent(child);
182 removeDependencies(child);
183 (*scope)[id] = 0;
184 freePlaces->push(id);
185 }
186 }
187
removeDependencies(XMLObject * obj)188 void VariableScope::removeDependencies(XMLObject * obj)
189 {
190 std::map < const XMLObject *, std::map < const XMLObject *, bool>*>::const_iterator it = parentToChildren.find(obj);
191
192 if (it != parentToChildren.end())
193 {
194 for (std::map < const XMLObject *, bool>::const_iterator i = it->second->begin(), e = it->second->end(); i != e; ++i)
195 {
196 const XMLObject *child = i->first;
197 if (child && i->second && getVariableFromId(child->getId()) == child)
198 {
199 delete child;
200 }
201 }
202 delete it->second;
203
204 parentToChildren.erase(obj);
205 }
206 }
207
initXMLMemory()208 void VariableScope::initXMLMemory()
209 {
210 xmlFreeFunc freeFunc;
211 xmlMallocFunc mallocFunc;
212 xmlReallocFunc reallocFunc;
213 xmlStrdupFunc strdupFunc;
214
215 xmlMemGet(&freeFunc, &mallocFunc, &reallocFunc, &strdupFunc);
216 freeFunc = getFreeFunc(freeFunc);
217 xmlMemSetup(freeFunc, mallocFunc, reallocFunc, strdupFunc);
218 }
219
getFreeFunc(xmlFreeFunc freeFunc)220 xmlFreeFunc VariableScope::getFreeFunc(xmlFreeFunc freeFunc)
221 {
222 if (!XMLFreeFunc)
223 {
224 XMLFreeFunc = freeFunc;
225 }
226
227 return &_xmlFreeFunc;
228 }
229
_xmlFreeFunc(void * mem)230 void VariableScope::_xmlFreeFunc(void *mem)
231 {
232 std::map < void *, XMLObject * >::const_iterator it = mapLibXMLToXMLObject.find(mem);
233
234 if (it != mapLibXMLToXMLObject.end())
235 {
236 delete it->second;
237
238 mapLibXMLToXMLObject.erase(mem);
239 }
240
241 std::map < void *, XMLNodeList * >::const_iterator itnl = mapLibXMLToXMLNodeList.find(mem);
242
243 if (itnl != mapLibXMLToXMLNodeList.end())
244 {
245 delete itnl->second;
246
247 mapLibXMLToXMLNodeList.erase(mem);
248 }
249
250 XMLFreeFunc(mem);
251 }
252
removeChildFromParent(const XMLObject * child)253 inline void VariableScope::removeChildFromParent(const XMLObject * child)
254 {
255 const XMLObject *parent = child->getXMLObjectParent();
256 std::map < const XMLObject *, std::map < const XMLObject *, bool>*>::iterator i = parentToChildren.find(parent);
257
258 if (i != parentToChildren.end())
259 {
260 std::map < const XMLObject *, bool>::iterator j = i->second->find(child);
261 if (j != i->second->end())
262 {
263 j->second = false;
264 }
265 }
266 }
267 }
268