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