Bug 13731 fixed: xmlDelete could be very slow 10/15910/4
Calixte DENIZET [Thu, 5 Feb 2015 11:03:22 +0000 (12:03 +0100)]
Change-Id: Id14d04aa728725d906d4a216e94e25549c8ff60a

scilab/CHANGES_5.5.X
scilab/modules/xml/src/cpp/VariableScope.cpp
scilab/modules/xml/src/cpp/VariableScope.hxx
scilab/modules/xml/src/cpp/XMLDocument.cpp
scilab/modules/xml/src/cpp/XMLElement.cpp
scilab/modules/xml/src/cpp/XMLElement.hxx
scilab/modules/xml/src/cpp/XMLObject.cpp
scilab/modules/xml/src/cpp/XMLObject.hxx
scilab/modules/xml/tests/unit_tests/xmlRemove.dia.ref
scilab/modules/xml/tests/unit_tests/xmlRemove.tst

index 9382546..4906162 100644 (file)
@@ -64,6 +64,8 @@ Scilab Bug Fixes
 
 * Bug #13725 fixed - Polyline was not correctly filled with big values.
 
+* Bug #13731 fixed - xmlDelete could be very slow.
+
 * Bug #13741 fixed - Impossible to print an invisible figure under Windows.
 
 * Bug #13742 fixed - Figure was not well printed when there is a xstring with latex.
index 18afcf2..18e9e35 100644 (file)
 #include "VariableScope.hxx"
 #include "XMLObject.hxx"
 #include "XMLNodeList.hxx"
+#include <iostream>
 
 namespace org_modules_xml
 {
-    xmlFreeFunc VariableScope::XMLFreeFunc = 0;
-      std::map < void *, XMLObject * >*VariableScope::mapLibXMLToXMLObject = new std::map < void *, XMLObject * >();
-      std::map < void *, XMLNodeList * >*VariableScope::mapLibXMLToXMLNodeList = new std::map < void *, XMLNodeList * >();
-      std::map < const XMLObject *, std::vector < const XMLObject *>*>*VariableScope::parentToChildren =
-        new std::map < const XMLObject *, std::vector < const XMLObject *>*>();
+xmlFreeFunc VariableScope::XMLFreeFunc = 0;
+std::map < void *, XMLObject * >*VariableScope::mapLibXMLToXMLObject = new std::map < void *, XMLObject * >();
+std::map < void *, XMLNodeList * >*VariableScope::mapLibXMLToXMLNodeList = new std::map < void *, XMLNodeList * >();
+std::map < const XMLObject *, std::map < const XMLObject *, bool>*>*VariableScope::parentToChildren;
 
-      VariableScope::VariableScope(int _initialSize)
-    {
-        position = -1;
-        initialSize = _initialSize;
-        scope = new std::vector < XMLObject * >();
-        freePlaces = new std::stack < int >();
-          parentToChildren = new std::map < const XMLObject *, std::vector < const XMLObject *>*>();
-          initXMLMemory();
-    }
+VariableScope::VariableScope(int _initialSize)
+{
+    position = -1;
+    initialSize = _initialSize;
+    scope = new std::vector < XMLObject * >();
+    freePlaces = new std::stack < int >();
+    parentToChildren = new std::map < const XMLObject *, std::map < const XMLObject *, bool>*>();
+    initXMLMemory();
+}
 
-    VariableScope::~VariableScope()
+VariableScope::~VariableScope()
+{
+    for (unsigned int i = 0; i < scope->size(); i++)
     {
-        for (unsigned int i = 0; i < scope->size(); i++)
+        if ((*scope)[i])
         {
-            if ((*scope)[i])
-            {
-                delete(*scope)[i];
-            }
+            delete(*scope)[i];
         }
-        delete scope;
-        delete freePlaces;
-        delete parentToChildren;
     }
+    delete scope;
+    delete freePlaces;
+    delete parentToChildren;
+}
+
+/**
+ * To avoid unused place in the vector, we use a stack which contains the empty places.
+ */
+int VariableScope::getVariableId(const XMLObject & obj)
+{
+    int returnValue;
+    const XMLObject *parent = obj.getXMLObjectParent();
 
-    /**
-     * To avoid unused place in the vector, we use a stack which contains the empty places.
-     */
-    int VariableScope::getVariableId(const XMLObject & obj)
+    if (freePlaces->size() != 0)
+    {
+        returnValue = freePlaces->top();
+        freePlaces->pop();
+        (*scope)[returnValue] = const_cast < XMLObject * >(&obj);
+    }
+    else
     {
-        int returnValue;
-        const XMLObject *parent = obj.getXMLObjectParent();
+        returnValue = (int)scope->size();
+        scope->push_back(const_cast < XMLObject * >(&obj));
+    }
 
-        if (freePlaces->size() != 0)
-        {
-            returnValue = freePlaces->top();
-            freePlaces->pop();
-            (*scope)[returnValue] = const_cast < XMLObject * >(&obj);
-        }
-        else
-        {
-            returnValue = (int)scope->size();
-            scope->push_back(const_cast < XMLObject * >(&obj));
-        }
+    if (parent)
+    {
+        std::map < const XMLObject *, std::map < const XMLObject *, bool>*>::const_iterator it = parentToChildren->find(parent);
 
-        if (parent)
+        if (it != parentToChildren->end())
         {
-            std::map < const XMLObject *, std::vector < const XMLObject *>*>::const_iterator it = parentToChildren->find(parent);
-
-            if (it != parentToChildren->end())
+            std::map < const XMLObject *, bool>::iterator jt = it->second->find(&obj);
+            if (jt != it->second->end())
             {
-                it->second->push_back(&obj);
+                jt->second = true;
             }
             else
             {
-                (*parentToChildren)[parent] = new std::vector < const XMLObject *>();
-
-                (*parentToChildren)[parent]->push_back(&obj);
+                it->second->insert(std::pair<const XMLObject *, bool>(&obj, true));
             }
         }
-
-        return returnValue;
-    }
-
-    XMLObject *VariableScope::getVariableFromId(int id)
-    {
-        if (id >= 0 && id < (int)scope->size())
+        else
         {
-            return (*scope)[id];
+            std::map < const XMLObject *, bool> * map = new std::map < const XMLObject *, bool>();
+            map->insert(std::pair<const XMLObject *, bool>(&obj, true));
+            parentToChildren->insert(std::pair<const XMLObject *, std::map < const XMLObject *, bool>*>(parent, map));
         }
-
-        return 0;
     }
 
-    /**
-     * There are two motivations to register libxml pointers:
-     *   i) if a XMLObject is associated to a libxml node, then when this node will be removed
-     *      the XMLObject must be destroyed. This job is done in _xmlFreeFunc which is called
-     *      by libxml when a libxml node is freed.
-     *   ii) To avoid multiple instances of a XMLObject which wraps the same node, the function
-     *       getXMLObjectFromLibXMLPtr is used to know if a XMLObject already exists for the
-     *       libxml node.
-     */
-    void VariableScope::registerPointers(void *libxml, XMLObject * obj)
+    return returnValue;
+}
+
+XMLObject *VariableScope::getVariableFromId(int id)
+{
+    if (id >= 0 && id < (int)scope->size())
     {
-        if (libxml)
-        {
-            (*mapLibXMLToXMLObject)[libxml] = obj;
-        }
+        return (*scope)[id];
     }
 
-    void VariableScope::registerPointers(void *libxml, XMLNodeList * nodeList)
+    return 0;
+}
+
+/**
+ * There are two motivations to register libxml pointers:
+ *   i) if a XMLObject is associated to a libxml node, then when this node will be removed
+ *      the XMLObject must be destroyed. This job is done in _xmlFreeFunc which is called
+ *      by libxml when a libxml node is freed.
+ *   ii) To avoid multiple instances of a XMLObject which wraps the same node, the function
+ *       getXMLObjectFromLibXMLPtr is used to know if a XMLObject already exists for the
+ *       libxml node.
+ */
+void VariableScope::registerPointers(void *libxml, XMLObject * obj)
+{
+    if (libxml)
     {
-        if (libxml)
-        {
-            (*mapLibXMLToXMLNodeList)[libxml] = nodeList;
-        }
+        (*mapLibXMLToXMLObject)[libxml] = obj;
     }
+}
 
-    void VariableScope::unregisterPointer(void *libxml)
+void VariableScope::registerPointers(void *libxml, XMLNodeList * nodeList)
+{
+    if (libxml)
     {
-        if (libxml)
-        {
-            mapLibXMLToXMLObject->erase(libxml);
-        }
+        (*mapLibXMLToXMLNodeList)[libxml] = nodeList;
     }
+}
 
-    void VariableScope::unregisterNodeListPointer(void *libxml)
+void VariableScope::unregisterPointer(void *libxml)
+{
+    if (libxml)
     {
-        if (libxml)
-        {
-            mapLibXMLToXMLNodeList->erase(libxml);
-        }
+        mapLibXMLToXMLObject->erase(libxml);
     }
+}
 
-    XMLObject *VariableScope::getXMLObjectFromLibXMLPtr(void *libxml) const
+void VariableScope::unregisterNodeListPointer(void *libxml)
+{
+    if (libxml)
     {
-        if (libxml)
-        {
-            std::map < void *, XMLObject * >::const_iterator it = mapLibXMLToXMLObject->find(libxml);
-            if (it != mapLibXMLToXMLObject->end())
-            {
-                return it->second;
-            }
-        }
-
-        return 0;
+        mapLibXMLToXMLNodeList->erase(libxml);
     }
+}
 
-    XMLNodeList *VariableScope::getXMLNodeListFromLibXMLPtr(void *libxml)const
+XMLObject *VariableScope::getXMLObjectFromLibXMLPtr(void *libxml) const
+{
+    if (libxml)
     {
-        if (libxml)
+        std::map < void *, XMLObject * >::const_iterator it = mapLibXMLToXMLObject->find(libxml);
+        if (it != mapLibXMLToXMLObject->end())
         {
-            std::map < void *, XMLNodeList * >::const_iterator it = mapLibXMLToXMLNodeList->find(libxml);
-            if (it != mapLibXMLToXMLNodeList->end())
-            {
-                return it->second;
-            }
+            return it->second;
         }
-
-        return 0;
     }
 
-    void VariableScope::removeId(int id)
+    return 0;
+}
+
+XMLNodeList *VariableScope::getXMLNodeListFromLibXMLPtr(void *libxml)const
+{
+    if (libxml)
     {
-        if (id >= 0 && id < (int)scope->size() && (*scope)[id])
+        std::map < void *, XMLNodeList * >::const_iterator it = mapLibXMLToXMLNodeList->find(libxml);
+        if (it != mapLibXMLToXMLNodeList->end())
         {
-            removeChildFromParent((*scope)[id]);
-            removeDependencies((*scope)[id]);
-            (*scope)[id] = 0;
-            freePlaces->push(id);
+            return it->second;
         }
     }
 
-    void VariableScope::removeDependencies(XMLObject * obj)
+    return 0;
+}
+
+void VariableScope::removeId(int id)
+{
+    if (id >= 0 && id < (int)scope->size() && (*scope)[id])
     {
-        std::map < const XMLObject *, std::vector < const XMLObject *>*>::const_iterator it = parentToChildren->find(obj);
+        XMLObject * const child = (*scope)[id];
+        removeChildFromParent(child);
+        removeDependencies(child);
+        (*scope)[id] = 0;
+        freePlaces->push(id);
+    }
+}
 
-        if (it != parentToChildren->end())
+void VariableScope::removeDependencies(XMLObject * obj)
+{
+    std::map < const XMLObject *, std::map < const XMLObject *, bool>*>::const_iterator it = parentToChildren->find(obj);
+
+    if (it != parentToChildren->end())
+    {
+        for (std::map < const XMLObject *, bool>::const_iterator i = it->second->begin(), e = it->second->end(); i != e; ++i)
         {
-            for (unsigned int i = 0; i < it->second->size(); i++)
+            const XMLObject *child = i->first;
+            if (child && i->second && getVariableFromId(child->getId()) == child)
             {
-                const XMLObject *child = (*(it->second))[i];
-
-                if (child && getVariableFromId(child->getId()) == child)
-                {
-                    delete child;
-                }
+                delete child;
             }
-            delete it->second;
-
-            parentToChildren->erase(obj);
         }
+        delete it->second;
+
+        parentToChildren->erase(obj);
     }
+}
 
-    void VariableScope::initXMLMemory()
+void VariableScope::initXMLMemory()
+{
+    xmlFreeFunc freeFunc;
+    xmlMallocFunc mallocFunc;
+    xmlReallocFunc reallocFunc;
+    xmlStrdupFunc strdupFunc;
+
+    xmlMemGet(&freeFunc, &mallocFunc, &reallocFunc, &strdupFunc);
+    freeFunc = getFreeFunc(freeFunc);
+    xmlMemSetup(freeFunc, mallocFunc, reallocFunc, strdupFunc);
+}
+
+xmlFreeFunc VariableScope::getFreeFunc(xmlFreeFunc freeFunc)
+{
+    if (!XMLFreeFunc)
     {
-        xmlFreeFunc freeFunc;
-        xmlMallocFunc mallocFunc;
-        xmlReallocFunc reallocFunc;
-        xmlStrdupFunc strdupFunc;
-
-        xmlMemGet(&freeFunc, &mallocFunc, &reallocFunc, &strdupFunc);
-        freeFunc = getFreeFunc(freeFunc);
-        xmlMemSetup(freeFunc, mallocFunc, reallocFunc, strdupFunc);
+        XMLFreeFunc = freeFunc;
     }
 
-    xmlFreeFunc VariableScope::getFreeFunc(xmlFreeFunc freeFunc)
-    {
-        if (!XMLFreeFunc)
-        {
-            XMLFreeFunc = freeFunc;
-        }
+    return &_xmlFreeFunc;
+}
 
-        return &_xmlFreeFunc;
-    }
+void VariableScope::_xmlFreeFunc(void *mem)
+{
+    std::map < void *, XMLObject * >::const_iterator it = mapLibXMLToXMLObject->find(mem);
 
-    void VariableScope::_xmlFreeFunc(void *mem)
+    if (it != mapLibXMLToXMLObject->end())
     {
-        std::map < void *, XMLObject * >::const_iterator it = mapLibXMLToXMLObject->find(mem);
+        delete it->second;
 
-        if (it != mapLibXMLToXMLObject->end())
-        {
-            delete it->second;
+        mapLibXMLToXMLObject->erase(mem);
+    }
 
-            mapLibXMLToXMLObject->erase(mem);
-        }
+    std::map < void *, XMLNodeList * >::const_iterator itnl = mapLibXMLToXMLNodeList->find(mem);
 
-        std::map < void *, XMLNodeList * >::const_iterator itnl = mapLibXMLToXMLNodeList->find(mem);
+    if (itnl != mapLibXMLToXMLNodeList->end())
+    {
+        delete itnl->second;
 
-        if (itnl != mapLibXMLToXMLNodeList->end())
-        {
-            delete itnl->second;
+        mapLibXMLToXMLNodeList->erase(mem);
+    }
 
-            mapLibXMLToXMLNodeList->erase(mem);
-        }
+    XMLFreeFunc(mem);
+}
 
-        XMLFreeFunc(mem);
-    }
+inline void VariableScope::removeChildFromParent(const XMLObject * child)
+{
+    const XMLObject *parent = child->getXMLObjectParent();
+    std::map < const XMLObject *, std::map < const XMLObject *, bool>*>::iterator i = parentToChildren->find(parent);
 
-    inline void VariableScope::removeChildFromParent(const XMLObject * child)
+    if (i != parentToChildren->end())
     {
-        const XMLObject *parent = child->getXMLObjectParent();
-        std::map < const XMLObject *, std::vector < const XMLObject *>*>::const_iterator it = parentToChildren->find(parent);
-
-        if (it != parentToChildren->end())
+        std::map < const XMLObject *, bool>::iterator j = i->second->find(child);
+        if (j != i->second->end())
         {
-            for (unsigned int i = 0; i < it->second->size(); i++)
-            {
-                if (child == (*(it->second))[i])
-                {
-                    (*(it->second))[i] = 0;
-                }
-            }
+            j->second = false;
         }
     }
 }
+}
index 627e163..9d7c633 100644 (file)
@@ -37,7 +37,7 @@ class VariableScope
     int initialSize;
     std::stack < int >*freePlaces;
 
-    static std::map < const XMLObject *, std::vector < const XMLObject *>*>*parentToChildren;
+    static std::map < const XMLObject *, std::map < const XMLObject *, bool>*>*parentToChildren;
     static std::map < void *, XMLObject * >*mapLibXMLToXMLObject;
     static std::map < void *, XMLNodeList * >*mapLibXMLToXMLNodeList;
     static xmlFreeFunc XMLFreeFunc;
index d7b6f93..a2308ff 100644 (file)
@@ -32,504 +32,515 @@ extern "C"
 namespace org_modules_xml
 {
 
-    std::string * XMLDocument::errorBuffer = 0;
-    std::string * XMLDocument::errorXPathBuffer = 0;
-    std::list < XMLDocument * >&XMLDocument::openDocs = *new std::list < XMLDocument * >();
+std::string * XMLDocument::errorBuffer = 0;
+std::string * XMLDocument::errorXPathBuffer = 0;
+std::list < XMLDocument * >&XMLDocument::openDocs = *new std::list < XMLDocument * >();
 
-    XMLDocument::XMLDocument(const char *path, bool validate, std::string * error, const char * encoding, const bool html): XMLObject()
-    {
-        char *expandedPath = expandPathVariable(const_cast<char *>(path));
-        if (expandedPath)
-        {
-            if (html)
-            {
-                document = readHTMLDocument(const_cast<const char *>(expandedPath), encoding, error);
-            }
-            else
-            {
-                document = readDocument(const_cast<const char *>(expandedPath), encoding, validate, error);
-            }
-
-            FREE(expandedPath);
-            if (document)
-            {
-                openDocs.push_back(this);
-                scope->registerPointers(document, this);
-            }
-        }
-        else
-        {
-            document = 0;
-            *error = std::string(gettext("Invalid file name: ")) + std::string(path);
-        }
-
-        id = scope->getVariableId(*this);
-        scilabType = XMLDOCUMENT;
-    }
-
-    XMLDocument::XMLDocument(const std::string & xmlCode, bool validate, std::string * error, const char * encoding, const bool html): XMLObject()
+XMLDocument::XMLDocument(const char *path, bool validate, std::string * error, const char * encoding, const bool html): XMLObject()
+{
+    char *expandedPath = expandPathVariable(const_cast<char *>(path));
+    if (expandedPath)
     {
         if (html)
         {
-            document = readHTMLDocument(xmlCode, encoding, error);
+            document = readHTMLDocument(const_cast<const char *>(expandedPath), encoding, error);
         }
         else
         {
-            document = readDocument(xmlCode, encoding, validate, error);
+            document = readDocument(const_cast<const char *>(expandedPath), encoding, validate, error);
         }
 
+        FREE(expandedPath);
         if (document)
         {
             openDocs.push_back(this);
+            scope->registerPointers(document, this);
         }
-        scope->registerPointers(document, this);
-        id = scope->getVariableId(*this);
-        scilabType = XMLDOCUMENT;
+    }
+    else
+    {
+        document = 0;
+        *error = std::string(gettext("Invalid file name: ")) + std::string(path);
     }
 
-    XMLDocument::XMLDocument(char *uri, char *version): XMLObject()
+    id = scope->getVariableId(*this);
+    scilabType = XMLDOCUMENT;
+}
+
+XMLDocument::XMLDocument(const std::string & xmlCode, bool validate, std::string * error, const char * encoding, const bool html): XMLObject()
+{
+    if (html)
     {
-        char *newUri = 0;
-        char *expandedPath = 0;
+        document = readHTMLDocument(xmlCode, encoding, error);
+    }
+    else
+    {
+        document = readDocument(xmlCode, encoding, validate, error);
+    }
 
-        if (!version)
-        {
-            version = const_cast < char *>("1.0");
-        }
-        document = xmlNewDoc((xmlChar *) version);
+    if (document)
+    {
         openDocs.push_back(this);
-        scope->registerPointers(document, this);
-        id = scope->getVariableId(*this);
-        scilabType = XMLDOCUMENT;
+    }
+    scope->registerPointers(document, this);
+    id = scope->getVariableId(*this);
+    scilabType = XMLDOCUMENT;
+}
 
-        expandedPath = expandPathVariable(const_cast < char *>(uri));
+XMLDocument::XMLDocument(char *uri, char *version): XMLObject()
+{
+    char *newUri = 0;
+    char *expandedPath = 0;
 
-        if (expandedPath)
-        {
-            newUri = (char *)xmlMalloc(sizeof(char *) * (strlen(expandedPath) + 1));
-            memcpy(newUri, expandedPath, sizeof(char) * (strlen(expandedPath) + 1));
-            document->URL = (xmlChar *) newUri;
-            FREE(expandedPath);
-        }
+    if (!version)
+    {
+        version = const_cast < char *>("1.0");
     }
+    document = xmlNewDoc((xmlChar *) version);
+    openDocs.push_back(this);
+    scope->registerPointers(document, this);
+    id = scope->getVariableId(*this);
+    scilabType = XMLDOCUMENT;
+
+    expandedPath = expandPathVariable(const_cast < char *>(uri));
 
-    XMLDocument::~XMLDocument()
+    if (expandedPath)
     {
-        scope->unregisterPointer(document);
-        scope->removeId(id);
-        if (document)
-        {
-            openDocs.remove(this);
-            if (openDocs.size() == 0 && XMLValidation::getOpenValidationFiles().size() == 0)
-            {
-                resetScope();
-            }
-            xmlFreeDoc(document);
-        }
-        if (errorBuffer)
-        {
-            delete errorBuffer;
-            errorBuffer = 0;
-        }
-        if (errorXPathBuffer)
+        newUri = (char *)xmlMalloc(sizeof(char *) * (strlen(expandedPath) + 1));
+        memcpy(newUri, expandedPath, sizeof(char) * (strlen(expandedPath) + 1));
+        document->URL = (xmlChar *) newUri;
+        FREE(expandedPath);
+    }
+}
+
+XMLDocument::~XMLDocument()
+{
+    scope->unregisterPointer(document);
+    scope->removeId(id);
+    if (document)
+    {
+        openDocs.remove(this);
+        if (openDocs.size() == 0 && XMLValidation::getOpenValidationFiles().size() == 0)
         {
-            delete errorXPathBuffer;
-            errorXPathBuffer = 0;
+            resetScope();
         }
+        xmlFreeDoc(document);
     }
-
-    void *XMLDocument::getRealXMLPointer() const
+    if (errorBuffer)
     {
-        return static_cast < void *>(document);
+        delete errorBuffer;
+        errorBuffer = 0;
+    }
+    if (errorXPathBuffer)
+    {
+        delete errorXPathBuffer;
+        errorXPathBuffer = 0;
     }
 
-    const XMLXPath *XMLDocument::makeXPathQuery(const char *query, char **namespaces, int length, const XMLElement * e, std::string * error)
+#ifdef SCILAB_DEBUG_XML
+    for (std::set<XMLObject *>::const_iterator i = XMLObject::pointers.begin(), e = XMLObject::pointers.end(); i != e; ++i)
     {
-        if (errorXPathBuffer)
+        XMLObject * p = *i;
+        if (p != this)
         {
-            delete errorXPathBuffer;
+            std::cout << "Stay = " << (void*)p << ":" << typeid(*p).name() << std::endl;
         }
-        errorXPathBuffer = new std::string();
+    }
+#endif
+}
 
-        xmlXPathContext *ctxt = xmlXPathNewContext(document);
+void *XMLDocument::getRealXMLPointer() const
+{
+    return static_cast < void *>(document);
+}
 
-        if (!ctxt)
-        {
-            errorXPathBuffer->append(gettext("Cannot create a parser context"));
-            *error = *errorXPathBuffer;
-            return 0;
-        }
+const XMLXPath *XMLDocument::makeXPathQuery(const char *query, char **namespaces, int length, const XMLElement * e, std::string * error)
+{
+    if (errorXPathBuffer)
+    {
+        delete errorXPathBuffer;
+    }
+    errorXPathBuffer = new std::string();
 
-        if (e)
-        {
-            ctxt->node = (xmlNode *) e->getRealXMLPointer();
-        }
+    xmlXPathContext *ctxt = xmlXPathNewContext(document);
 
-        if (namespaces)
-        {
-            for (int i = 0; i < length; i++)
-            {
-                xmlXPathRegisterNs(ctxt, (const xmlChar *)namespaces[i], (const xmlChar *)namespaces[i + length]);
-            }
-        }
+    if (!ctxt)
+    {
+        errorXPathBuffer->append(gettext("Cannot create a parser context"));
+        *error = *errorXPathBuffer;
+        return 0;
+    }
 
-        xmlSetStructuredErrorFunc(ctxt, XMLDocument::errorXPathFunction);
-        xmlXPathCompExpr *expr = xmlXPathCtxtCompile(ctxt, (const xmlChar *)query);
+    if (e)
+    {
+        ctxt->node = (xmlNode *) e->getRealXMLPointer();
+    }
 
-        if (!expr)
+    if (namespaces)
+    {
+        for (int i = 0; i < length; i++)
         {
-            xmlSetStructuredErrorFunc(ctxt, 0);
-            xmlXPathFreeContext(ctxt);
-            *error = *errorXPathBuffer;
-            return 0;
+            xmlXPathRegisterNs(ctxt, (const xmlChar *)namespaces[i], (const xmlChar *)namespaces[i + length]);
         }
+    }
 
-        xmlXPathObject *xpath = xmlXPathCompiledEval(expr, ctxt);
+    xmlSetStructuredErrorFunc(ctxt, XMLDocument::errorXPathFunction);
+    xmlXPathCompExpr *expr = xmlXPathCtxtCompile(ctxt, (const xmlChar *)query);
 
+    if (!expr)
+    {
         xmlSetStructuredErrorFunc(ctxt, 0);
         xmlXPathFreeContext(ctxt);
-        xmlXPathFreeCompExpr(expr);
-        if (!xpath)
-        {
-            *error = *errorXPathBuffer;
-            return 0;
-        }
-
-        return new XMLXPath(*this, xpath);
+        *error = *errorXPathBuffer;
+        return 0;
     }
 
-    const XMLObject *XMLDocument::getXMLObjectParent() const
+    xmlXPathObject *xpath = xmlXPathCompiledEval(expr, ctxt);
+
+    xmlSetStructuredErrorFunc(ctxt, 0);
+    xmlXPathFreeContext(ctxt);
+    xmlXPathFreeCompExpr(expr);
+    if (!xpath)
     {
+        *error = *errorXPathBuffer;
         return 0;
     }
 
-    const std::string XMLDocument::toString() const
-    {
-        std::ostringstream oss;
-
-        oss << "XML Document" << std::endl
-            << "url: " << getDocumentURL() << std::endl
-            << "root: " << "XML Element";
+    return new XMLXPath(*this, xpath);
+}
 
-        return oss.str();
-    }
+const XMLObject *XMLDocument::getXMLObjectParent() const
+{
+    return 0;
+}
 
-    const std::string XMLDocument::dump(bool indent) const
-    {
-        xmlChar *buffer = 0;
-        int size = 0;
-        xmlDocDumpFormatMemory(document, &buffer, &size, indent ? 1 : 0);
-        std::string str((const char *)buffer);
-        xmlFree(buffer);
+const std::string XMLDocument::toString() const
+{
+    std::ostringstream oss;
 
-        return str;
-    }
+    oss << "XML Document" << std::endl
+        << "url: " << getDocumentURL() << std::endl
+        << "root: " << "XML Element";
 
-    const std::string XMLDocument::dumpHTML(bool indent) const
-    {
-        xmlBuffer * buffer = xmlBufferCreate();
-        int ret;
-        int options = XML_SAVE_AS_HTML;
-        if (indent)
-        {
-            options |= XML_SAVE_FORMAT;
-        }
+    return oss.str();
+}
 
-        xmlThrDefIndentTreeOutput(1);
-        xmlSaveCtxtPtr ctxt = xmlSaveToBuffer(buffer, 0, options);
-        ret = xmlSaveDoc(ctxt, document);
-        xmlSaveFlush(ctxt);
-        xmlSaveClose(ctxt);
+const std::string XMLDocument::dump(bool indent) const
+{
+    xmlChar *buffer = 0;
+    int size = 0;
+    xmlDocDumpFormatMemory(document, &buffer, &size, indent ? 1 : 0);
+    std::string str((const char *)buffer);
+    xmlFree(buffer);
 
-        std::string str((const char *)xmlBufferDetach(buffer));
-        xmlBufferFree(buffer);
+    return str;
+}
 
-        return str;
+const std::string XMLDocument::dumpHTML(bool indent) const
+{
+    xmlBuffer * buffer = xmlBufferCreate();
+    int ret;
+    int options = XML_SAVE_AS_HTML;
+    if (indent)
+    {
+        options |= XML_SAVE_FORMAT;
     }
 
-    const XMLElement *XMLDocument::getRoot() const
-    {
-        xmlNode *root = xmlDocGetRootElement(document);
-        if (!root)
-        {
-            return 0;
-        }
+    xmlThrDefIndentTreeOutput(1);
+    xmlSaveCtxtPtr ctxt = xmlSaveToBuffer(buffer, 0, options);
+    ret = xmlSaveDoc(ctxt, document);
+    xmlSaveFlush(ctxt);
+    xmlSaveClose(ctxt);
 
-        XMLObject *obj = scope->getXMLObjectFromLibXMLPtr(root);
+    std::string str((const char *)xmlBufferDetach(buffer));
+    xmlBufferFree(buffer);
 
-        if (obj)
-        {
-            return static_cast < XMLElement * >(obj);
-        }
+    return str;
+}
 
-        return new XMLElement(*this, root);
+const XMLElement *XMLDocument::getRoot() const
+{
+    xmlNode *root = xmlDocGetRootElement(document);
+    if (!root)
+    {
+        return 0;
     }
 
-    void XMLDocument::setRoot(const XMLElement & elem) const
+    XMLObject *obj = scope->getXMLObjectFromLibXMLPtr(root);
+
+    if (obj)
     {
-        xmlNode *root = xmlDocGetRootElement(document);
-        if (root != elem.getRealNode())
-        {
-            xmlNode *cpy = xmlCopyNodeList(elem.getRealNode());
-            xmlUnlinkNode(cpy);
-            xmlDocSetRootElement(document, cpy);
-        }
+        return static_cast < XMLElement * >(obj);
     }
 
-    void XMLDocument::setRoot(const std::string & xmlCode, std::string * error) const
-    {
-        XMLDocument doc = XMLDocument(xmlCode, false, error);
+    return new XMLElement(*this, root);
+}
 
-        if (error->empty())
-        {
-            setRoot(*doc.getRoot());
-        }
+void XMLDocument::setRoot(const XMLElement & elem) const
+{
+    xmlNode *root = xmlDocGetRootElement(document);
+    if (root != elem.getRealNode())
+    {
+        xmlNode *cpy = xmlCopyNodeList(elem.getRealNode());
+        xmlUnlinkNode(cpy);
+        xmlDocSetRootElement(document, cpy);
     }
+}
 
-    const char *XMLDocument::getDocumentURL() const
+void XMLDocument::setRoot(const std::string & xmlCode, std::string * error) const
+{
+    XMLDocument doc = XMLDocument(xmlCode, false, error);
+
+    if (error->empty())
     {
-        if (document->URL)
-        {
-            return (const char *)document->URL;
-        }
-        else
-        {
-            return "Undefined";
-        }
+        setRoot(*doc.getRoot());
     }
+}
 
-    void XMLDocument::setDocumentURL(const std::string & url) const
+const char *XMLDocument::getDocumentURL() const
+{
+    if (document->URL)
     {
-        char *expandedPath = 0;
-        char *newURL = 0;
-        expandedPath = expandPathVariable(const_cast < char *>(url.c_str()));
-
-        if (expandedPath)
-        {
-            xmlFree((void *)document->URL);
-            newURL = (char *)xmlMalloc(sizeof(char *) * (strlen(expandedPath) + 1));
-            memcpy(newURL, expandedPath, sizeof(char) * (strlen(expandedPath) + 1));
-            document->URL = (xmlChar *) newURL;
-            FREE(expandedPath);
-        }
+        return (const char *)document->URL;
     }
-
-    const std::list < XMLDocument * >&XMLDocument::getOpenDocuments()
+    else
     {
-        return openDocs;
+        return "Undefined";
     }
+}
 
-    void XMLDocument::closeAllDocuments()
-    {
-        int size = (int)openDocs.size();
-        XMLDocument **arr = new XMLDocument *[size];
-        int j = 0;
+void XMLDocument::setDocumentURL(const std::string & url) const
+{
+    char *expandedPath = 0;
+    char *newURL = 0;
+    expandedPath = expandPathVariable(const_cast < char *>(url.c_str()));
 
-        for (std::list < XMLDocument * >::iterator i = openDocs.begin(); i != openDocs.end(); i++, j++)
-        {
-            arr[j] = *i;
-        }
-        for (j = 0; j < size; j++)
-        {
-            delete arr[j];
-        }
-        delete[]arr;
+    if (expandedPath)
+    {
+        xmlFree((void *)document->URL);
+        newURL = (char *)xmlMalloc(sizeof(char *) * (strlen(expandedPath) + 1));
+        memcpy(newURL, expandedPath, sizeof(char) * (strlen(expandedPath) + 1));
+        document->URL = (xmlChar *) newURL;
+        FREE(expandedPath);
     }
+}
 
-    xmlDoc *XMLDocument::readDocument(const char *filename, const char * encoding, bool validate, std::string * error)
-    {
-        xmlParserCtxt *ctxt = initContext(error, validate);
-        xmlDoc *doc = 0;
-        int options = XML_PARSE_NSCLEAN | XML_PARSE_NOBLANKS;
+const std::list < XMLDocument * >&XMLDocument::getOpenDocuments()
+{
+    return openDocs;
+}
 
-        if (validate)
-        {
-            options |= XML_PARSE_DTDVALID;
-        }
+void XMLDocument::closeAllDocuments()
+{
+    int size = (int)openDocs.size();
+    XMLDocument **arr = new XMLDocument *[size];
+    int j = 0;
 
-        if (!ctxt)
-        {
-            xmlSetGenericErrorFunc(0, errorFunctionWithoutOutput);
-            return 0;
-        }
+    for (std::list < XMLDocument * >::iterator i = openDocs.begin(); i != openDocs.end(); i++, j++)
+    {
+        arr[j] = *i;
+    }
+    for (j = 0; j < size; j++)
+    {
+        delete arr[j];
+    }
+    delete[]arr;
+}
 
-        doc = xmlCtxtReadFile(ctxt, filename, encoding, options);
-        if (!doc || !ctxt->valid)
-        {
-            *error = *errorBuffer;
-        }
+xmlDoc *XMLDocument::readDocument(const char *filename, const char * encoding, bool validate, std::string * error)
+{
+    xmlParserCtxt *ctxt = initContext(error, validate);
+    xmlDoc *doc = 0;
+    int options = XML_PARSE_NSCLEAN | XML_PARSE_NOBLANKS;
 
-        xmlSetGenericErrorFunc(0, errorFunctionWithoutOutput);
-        xmlFreeParserCtxt(ctxt);
+    if (validate)
+    {
+        options |= XML_PARSE_DTDVALID;
+    }
 
-        return doc;
+    if (!ctxt)
+    {
+        xmlSetGenericErrorFunc(0, errorFunctionWithoutOutput);
+        return 0;
     }
 
-    xmlDoc *XMLDocument::readHTMLDocument(const char *filename, const char * encoding, std::string * error)
+    doc = xmlCtxtReadFile(ctxt, filename, encoding, options);
+    if (!doc || !ctxt->valid)
     {
-        htmlParserCtxt *ctxt = initHTMLContext(error);
-        htmlDocPtr doc = 0;
-        int options = HTML_PARSE_NOWARNING | HTML_PARSE_NOBLANKS | HTML_PARSE_COMPACT;
+        *error = *errorBuffer;
+    }
 
-        if (!ctxt)
-        {
-            xmlSetGenericErrorFunc(0, errorFunctionWithoutOutput);
-            return 0;
-        }
+    xmlSetGenericErrorFunc(0, errorFunctionWithoutOutput);
+    xmlFreeParserCtxt(ctxt);
 
-        doc = htmlCtxtReadFile(ctxt, filename, encoding, options);
-        if (!doc || !ctxt->valid)
-        {
-            *error = *errorBuffer;
-        }
+    return doc;
+}
 
-        xmlSetGenericErrorFunc(0, errorFunctionWithoutOutput);
-        htmlFreeParserCtxt(ctxt);
+xmlDoc *XMLDocument::readHTMLDocument(const char *filename, const char * encoding, std::string * error)
+{
+    htmlParserCtxt *ctxt = initHTMLContext(error);
+    htmlDocPtr doc = 0;
+    int options = HTML_PARSE_NOWARNING | HTML_PARSE_NOBLANKS | HTML_PARSE_COMPACT;
 
-        return (xmlDoc *)doc;
+    if (!ctxt)
+    {
+        xmlSetGenericErrorFunc(0, errorFunctionWithoutOutput);
+        return 0;
     }
 
-    xmlDoc *XMLDocument::readDocument(const std::string & xmlCode, const char * encoding, bool validate, std::string * error)
+    doc = htmlCtxtReadFile(ctxt, filename, encoding, options);
+    if (!doc || !ctxt->valid)
     {
-        xmlParserCtxt *ctxt = initContext(error, validate);
-        xmlDoc *doc = 0;
-        int options = XML_PARSE_NSCLEAN | XML_PARSE_NOBLANKS;
+        *error = *errorBuffer;
+    }
 
-        if (validate)
-        {
-            options |= XML_PARSE_DTDVALID;
-        }
+    xmlSetGenericErrorFunc(0, errorFunctionWithoutOutput);
+    htmlFreeParserCtxt(ctxt);
 
-        if (!ctxt)
-        {
-            xmlSetGenericErrorFunc(0, errorFunctionWithoutOutput);
-            return 0;
-        }
+    return (xmlDoc *)doc;
+}
 
-        doc = xmlCtxtReadDoc(ctxt, (const xmlChar *)xmlCode.c_str(), 0, encoding, options);
-        if (!doc || !ctxt->valid)
-        {
-            *error = *errorBuffer;
-        }
+xmlDoc *XMLDocument::readDocument(const std::string & xmlCode, const char * encoding, bool validate, std::string * error)
+{
+    xmlParserCtxt *ctxt = initContext(error, validate);
+    xmlDoc *doc = 0;
+    int options = XML_PARSE_NSCLEAN | XML_PARSE_NOBLANKS;
 
-        xmlSetGenericErrorFunc(0, errorFunctionWithoutOutput);
-        xmlFreeParserCtxt(ctxt);
+    if (validate)
+    {
+        options |= XML_PARSE_DTDVALID;
+    }
 
-        return doc;
+    if (!ctxt)
+    {
+        xmlSetGenericErrorFunc(0, errorFunctionWithoutOutput);
+        return 0;
     }
 
-    xmlDoc *XMLDocument::readHTMLDocument(const std::string & htmlCode, const char * encoding, std::string * error)
+    doc = xmlCtxtReadDoc(ctxt, (const xmlChar *)xmlCode.c_str(), 0, encoding, options);
+    if (!doc || !ctxt->valid)
     {
-        htmlParserCtxt *ctxt = initHTMLContext(error);
-        htmlDocPtr doc = 0;
-        int options = HTML_PARSE_NOWARNING | HTML_PARSE_NOBLANKS | HTML_PARSE_COMPACT;
+        *error = *errorBuffer;
+    }
 
-        if (!ctxt)
-        {
-            xmlSetGenericErrorFunc(0, errorFunctionWithoutOutput);
-            return 0;
-        }
+    xmlSetGenericErrorFunc(0, errorFunctionWithoutOutput);
+    xmlFreeParserCtxt(ctxt);
 
-        doc = htmlCtxtReadDoc(ctxt, (const xmlChar *)htmlCode.c_str(), 0, encoding, options);
-        if (!doc || !ctxt->valid)
-        {
-            *error = *errorBuffer;
-        }
+    return doc;
+}
 
-        xmlSetGenericErrorFunc(0, errorFunctionWithoutOutput);
-        htmlFreeParserCtxt(ctxt);
+xmlDoc *XMLDocument::readHTMLDocument(const std::string & htmlCode, const char * encoding, std::string * error)
+{
+    htmlParserCtxt *ctxt = initHTMLContext(error);
+    htmlDocPtr doc = 0;
+    int options = HTML_PARSE_NOWARNING | HTML_PARSE_NOBLANKS | HTML_PARSE_COMPACT;
 
-        return (xmlDoc *)doc;
+    if (!ctxt)
+    {
+        xmlSetGenericErrorFunc(0, errorFunctionWithoutOutput);
+        return 0;
     }
 
-    bool XMLDocument::saveToFile(const std::string & filename, const bool indent) const
+    doc = htmlCtxtReadDoc(ctxt, (const xmlChar *)htmlCode.c_str(), 0, encoding, options);
+    if (!doc || !ctxt->valid)
     {
-        xmlThrDefIndentTreeOutput(1);
-        return xmlSaveFormatFile(filename.c_str(), document, indent) != -1;
+        *error = *errorBuffer;
     }
 
-    bool XMLDocument::saveToHTMLFile(const std::string & filename, const bool indent) const
-    {
-        int ret;
-        int options = XML_SAVE_AS_HTML;
-        if (indent)
-        {
-            options |= XML_SAVE_FORMAT;
-        }
+    xmlSetGenericErrorFunc(0, errorFunctionWithoutOutput);
+    htmlFreeParserCtxt(ctxt);
 
-        xmlThrDefIndentTreeOutput(1);
-        xmlSaveCtxtPtr ctxt = xmlSaveToFilename(filename.c_str(), 0, options);
-        ret = xmlSaveDoc(ctxt, document);
-        xmlSaveFlush(ctxt);
-        xmlSaveClose(ctxt);
+    return (xmlDoc *)doc;
+}
 
-        return ret != -1;
-    }
+bool XMLDocument::saveToFile(const std::string & filename, const bool indent) const
+{
+    xmlThrDefIndentTreeOutput(1);
+    return xmlSaveFormatFile(filename.c_str(), document, indent) != -1;
+}
 
-    xmlParserCtxt *XMLDocument::initContext(std::string * error, bool validate)
+bool XMLDocument::saveToHTMLFile(const std::string & filename, const bool indent) const
+{
+    int ret;
+    int options = XML_SAVE_AS_HTML;
+    if (indent)
     {
-        xmlParserCtxt *ctxt;
-
-        if (errorBuffer)
-        {
-            delete errorBuffer;
-        }
-        errorBuffer = new std::string();
+        options |= XML_SAVE_FORMAT;
+    }
 
-        ctxt = xmlNewParserCtxt();
-        if (!ctxt)
-        {
-            errorBuffer->append(gettext("Cannot create a parser context"));
-            *error = *errorBuffer;
-            return 0;
-        }
+    xmlThrDefIndentTreeOutput(1);
+    xmlSaveCtxtPtr ctxt = xmlSaveToFilename(filename.c_str(), 0, options);
+    ret = xmlSaveDoc(ctxt, document);
+    xmlSaveFlush(ctxt);
+    xmlSaveClose(ctxt);
 
-        if (validate)
-        {
-            ctxt->vctxt.error = (xmlValidityErrorFunc) errorFunction;
-        }
+    return ret != -1;
+}
 
-        xmlSetGenericErrorFunc(ctxt, errorFunction);
+xmlParserCtxt *XMLDocument::initContext(std::string * error, bool validate)
+{
+    xmlParserCtxt *ctxt;
 
-        return ctxt;
+    if (errorBuffer)
+    {
+        delete errorBuffer;
     }
+    errorBuffer = new std::string();
 
-    htmlParserCtxt *XMLDocument::initHTMLContext(std::string * error)
+    ctxt = xmlNewParserCtxt();
+    if (!ctxt)
     {
-        htmlParserCtxt *ctxt;
+        errorBuffer->append(gettext("Cannot create a parser context"));
+        *error = *errorBuffer;
+        return 0;
+    }
 
-        if (errorBuffer)
-        {
-            delete errorBuffer;
-        }
-        errorBuffer = new std::string();
+    if (validate)
+    {
+        ctxt->vctxt.error = (xmlValidityErrorFunc) errorFunction;
+    }
 
-        ctxt = htmlNewParserCtxt();
-        if (!ctxt)
-        {
-            errorBuffer->append(gettext("Cannot create a parser context"));
-            *error = *errorBuffer;
-            return 0;
-        }
+    xmlSetGenericErrorFunc(ctxt, errorFunction);
 
-        xmlSetGenericErrorFunc((xmlParserCtxt *)ctxt, errorFunction);
+    return ctxt;
+}
 
-        return ctxt;
-    }
+htmlParserCtxt *XMLDocument::initHTMLContext(std::string * error)
+{
+    htmlParserCtxt *ctxt;
 
-    void XMLDocument::errorFunction(void *ctx, const char *msg, ...)
+    if (errorBuffer)
     {
-        char str[BUFFER_SIZE];
-        va_list args;
-
-        va_start(args, msg);
-        vsnprintf(str, BUFFER_SIZE, msg, args);
-        va_end(args);
-        errorBuffer->append(str);
+        delete errorBuffer;
     }
+    errorBuffer = new std::string();
 
-    void XMLDocument::errorXPathFunction(void *ctx, xmlError * error)
+    ctxt = htmlNewParserCtxt();
+    if (!ctxt)
     {
-        errorXPathBuffer->append(error->message);
+        errorBuffer->append(gettext("Cannot create a parser context"));
+        *error = *errorBuffer;
+        return 0;
     }
+
+    xmlSetGenericErrorFunc((xmlParserCtxt *)ctxt, errorFunction);
+
+    return ctxt;
+}
+
+void XMLDocument::errorFunction(void *ctx, const char *msg, ...)
+{
+    char str[BUFFER_SIZE];
+    va_list args;
+
+    va_start(args, msg);
+    vsnprintf(str, BUFFER_SIZE, msg, args);
+    va_end(args);
+    errorBuffer->append(str);
+}
+
+void XMLDocument::errorXPathFunction(void *ctx, xmlError * error)
+{
+    errorXPathBuffer->append(error->message);
+}
 }
index e06f972..eba6351 100644 (file)
@@ -26,7 +26,7 @@ extern "C"
 namespace org_modules_xml
 {
 
-XMLElement::XMLElement(const XMLDocument & _doc, xmlNode * _node): XMLObject(), doc(_doc)
+XMLElement::XMLElement(const XMLDocument & _doc, xmlNode * _node): XMLObject(), allocated(false), doc(_doc)
 {
     node = _node;
     scope->registerPointers(node, this);
@@ -34,7 +34,7 @@ XMLElement::XMLElement(const XMLDocument & _doc, xmlNode * _node): XMLObject(),
     id = scope->getVariableId(*this);
 }
 
-XMLElement::XMLElement(const XMLDocument & _doc, const char *name): XMLObject(), doc(_doc)
+XMLElement::XMLElement(const XMLDocument & _doc, const char *name): XMLObject(), allocated(true), doc(_doc)
 {
     node = xmlNewNode(0, (const xmlChar *)name);
     scope->registerPointers(node, this);
@@ -46,6 +46,11 @@ XMLElement::~XMLElement()
 {
     scope->unregisterPointer(node);
     scope->removeId(id);
+
+    if (allocated)
+    {
+        xmlFreeNode(node);
+    }
 }
 
 void *XMLElement::getRealXMLPointer() const
index 23d4eea..f5ea8a6 100644 (file)
@@ -36,6 +36,7 @@ class XMLAttr;
  */
 class XML_SCILAB_IMPEXP XMLElement: public XMLObject, public XMLRemovable
 {
+    bool allocated;
     xmlNode *node;
     const XMLDocument & doc;
 
index 36cf5f9..2afc025 100644 (file)
@@ -19,12 +19,22 @@ namespace org_modules_xml
 {
 VariableScope *XMLObject::scope = 0;
 
-XMLObject::XMLObject(): id(0)
+#ifdef SCILAB_DEBUG_XML
+std::set<XMLObject *> XMLObject::pointers;
+#endif
+
+XMLObject::XMLObject(): id(0), valid(true)
 {
     if (!scope)
     {
         scope = new VariableScope(SCOPE_SIZE);
     }
+
+#ifdef SCILAB_DEBUG_XML
+    XMLObject::pointers.insert(this);
+    //std::cout << "Create = " << (void*)this << std::endl;
+#endif
+
     scilabType = -1;
 }
 
index 496191a..3b699fc 100644 (file)
 #ifndef __XMLOBJECTS_HXX__
 #define __XMLOBJECTS_HXX__
 
+#include <iostream>
 #include <string>
 #include <sstream>
 #include <typeinfo>
+#include <set>
 
 extern "C"
 {
@@ -23,6 +25,8 @@ extern "C"
 #include "dynlib_xml_scilab.h"
 }
 
+//#define SCILAB_DEBUG_XML
+
 namespace org_modules_xml
 {
 class VariableScope;
@@ -37,6 +41,11 @@ class XML_SCILAB_IMPEXP XMLObject
 {
 
 public:
+
+#ifdef SCILAB_DEBUG_XML
+    static std::set<XMLObject *> pointers;
+#endif
+
     /**
      * Default constructor
      */
@@ -47,6 +56,10 @@ public:
      */
     virtual ~ XMLObject()
     {
+#ifdef SCILAB_DEBUG_XML
+        //std::cout << "Delete = " << (void*)this << std::endl;
+        pointers.erase(this);
+#endif
     }
 
     /**
@@ -110,11 +123,21 @@ public:
     /**
      * @return the object id
      */
-    int getId() const
+    inline int getId() const
     {
         return id;
     }
 
+    inline bool isValid() const
+    {
+        return valid;
+    }
+
+    inline void invalid()
+    {
+        valid = false;
+    }
+
     /**
      * Creates the Scilab's variable corresponding to this object
      * @param pos the stack position
@@ -134,6 +157,7 @@ public:
 protected:
     int id;
     int scilabType;
+    bool valid;
 
     static VariableScope *scope;
 
index 7443fce..b161717 100644 (file)
@@ -33,27 +33,33 @@ assert_checktrue(and(xmlDump(doc)==xmlDump(doc3)));
 xmlRemove(doc.root.children(1));
 doc4 = xmlReadStr("<root></root>");
 assert_checktrue(and(xmlDump(doc)==xmlDump(doc4)));
-doc = xmlReadStr("<root><a>Hello</a><b>Scilab</b><a>World</a></root>");
 //Remove all the root children
-doc = xmlReadStr("<root><a>Hello</a><b>Scilab</b><a>World</a></root>");
-xmlRemove(doc.root.children);
-doc4 = xmlReadStr("<root></root>");
-assert_checktrue(and(xmlDump(doc)==xmlDump(doc4)));
+doc5 = xmlReadStr("<root><a>Hello</a><b>Scilab</b><a>World</a></root>");
+xmlRemove(doc5.root.children);
+doc6 = xmlReadStr("<root></root>");
+assert_checktrue(and(xmlDump(doc5)==xmlDump(doc6)));
 xmlDelete(doc);
 xmlDelete(doc2);
 xmlDelete(doc3);
 xmlDelete(doc4);
+xmlDelete(doc5);
+xmlDelete(doc6);
 doc = xmlReadStr("<root><a>Hello</a><mynode><b>Scilab</b></mynode><a>World</a></root>");
 xmlRemove(doc.root.children(1));
 doc2 = xmlReadStr("<root><mynode><b>Scilab</b></mynode><a>World</a></root>");
 assert_checktrue(and(xmlDump(doc)==xmlDump(doc2)));
 xmlRemove(doc.root.children(1).children(1));
-doc2 = xmlReadStr("<root><mynode></mynode><a>World</a></root>");
-assert_checktrue(and(xmlDump(doc)==xmlDump(doc2)));
+doc3 = xmlReadStr("<root><mynode></mynode><a>World</a></root>");
+assert_checktrue(and(xmlDump(doc)==xmlDump(doc3)));
+xmlDelete(doc);
+xmlDelete(doc2);
+xmlDelete(doc3);
 doc = xmlReadStr("<root><a>Hello</a><mynode><b>Scilab</b></mynode><a>World</a></root>");
 xmlRemove(doc.root.children(1).children(1));
 doc2 = xmlReadStr("<root><a></a><mynode><b>Scilab</b></mynode><a>World</a></root>");
 assert_checktrue(and(xmlDump(doc)==xmlDump(doc2)));
+xmlDelete(doc);
+xmlDelete(doc2);
 doc = xmlReadStr("<root><a>Hello</a><mynode><b>Scilab</b></mynode><a>World</a></root>");
 xmlRemove(doc.root.children(2).children(1));
 doc2 = xmlReadStr("<root><a>Hello</a><mynode></mynode><a>World</a></root>");
index 5aa8e55..945c345 100644 (file)
@@ -43,32 +43,39 @@ assert_checktrue(and(xmlDump(doc)==xmlDump(doc3)));
 xmlRemove(doc.root.children(1));
 doc4 = xmlReadStr("<root></root>");
 assert_checktrue(and(xmlDump(doc)==xmlDump(doc4)));
-doc = xmlReadStr("<root><a>Hello</a><b>Scilab</b><a>World</a></root>");
 
 //Remove all the root children
-doc = xmlReadStr("<root><a>Hello</a><b>Scilab</b><a>World</a></root>");
-xmlRemove(doc.root.children);
-doc4 = xmlReadStr("<root></root>");
-assert_checktrue(and(xmlDump(doc)==xmlDump(doc4)));
+doc5 = xmlReadStr("<root><a>Hello</a><b>Scilab</b><a>World</a></root>");
+xmlRemove(doc5.root.children);
+doc6 = xmlReadStr("<root></root>");
+assert_checktrue(and(xmlDump(doc5)==xmlDump(doc6)));
 
 xmlDelete(doc);
 xmlDelete(doc2);
 xmlDelete(doc3);
 xmlDelete(doc4);
+xmlDelete(doc5);
+xmlDelete(doc6);
 
 doc = xmlReadStr("<root><a>Hello</a><mynode><b>Scilab</b></mynode><a>World</a></root>");
 xmlRemove(doc.root.children(1));
 doc2 = xmlReadStr("<root><mynode><b>Scilab</b></mynode><a>World</a></root>");
 assert_checktrue(and(xmlDump(doc)==xmlDump(doc2)));
 xmlRemove(doc.root.children(1).children(1));
-doc2 = xmlReadStr("<root><mynode></mynode><a>World</a></root>");
-assert_checktrue(and(xmlDump(doc)==xmlDump(doc2)));
+doc3 = xmlReadStr("<root><mynode></mynode><a>World</a></root>");
+assert_checktrue(and(xmlDump(doc)==xmlDump(doc3)));
+
+xmlDelete(doc);
+xmlDelete(doc2);
+xmlDelete(doc3);
 
 doc = xmlReadStr("<root><a>Hello</a><mynode><b>Scilab</b></mynode><a>World</a></root>");
 xmlRemove(doc.root.children(1).children(1));
 doc2 = xmlReadStr("<root><a></a><mynode><b>Scilab</b></mynode><a>World</a></root>");
 assert_checktrue(and(xmlDump(doc)==xmlDump(doc2)));
 
+xmlDelete(doc);
+xmlDelete(doc2);
 
 doc = xmlReadStr("<root><a>Hello</a><mynode><b>Scilab</b></mynode><a>World</a></root>");
 xmlRemove(doc.root.children(2).children(1));