fix missing-override warnings on Scilab types
[scilab.git] / scilab / modules / scicos / src / cpp / view_scilab / BaseAdapter.hxx
index 7e340d2..6db39d7 100644 (file)
@@ -1,12 +1,16 @@
 /*
- *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
- *  Copyright (C) 2014-2014 - Scilab Enterprises - Clement DAVID
+ * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+ * Copyright (C) 2014-2016 - Scilab Enterprises - Clement DAVID
+ * Copyright (C) 2017 - ESI Group - Clement DAVID
  *
- *  This file must be used under the terms of the CeCILL.
- *  This source file is licensed as described in the file COPYING, which
- *  you should have received as part of this distribution.  The terms
- *  are also available at
- *  http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+ * Copyright (C) 2012 - 2016 - Scilab Enterprises
+ *
+ * This file is hereby licensed under the terms of the GNU GPL v2.0,
+ * pursuant to article 5.3.4 of the CeCILL v.2.1.
+ * This file was originally licensed under the terms of the CeCILL v2.1,
+ * and continues to be available under such terms.
+ * For more information, see the COPYING file which you should have received
+ * along with this program.
  *
  */
 
@@ -16,6 +20,7 @@
 #include <cstring>
 
 #include <algorithm>
+#include <functional>
 #include <string>
 #include <vector>
 #include <sstream>
 #include "overload.hxx"
 #include "configvariable.hxx"
 #include "exp.hxx"
+#include "types_comparison_eq.hxx"
 
 #include "view_scilab/Adapters.hxx"
+#include "view_scilab/AdapterView.hxx"
 #include "controller_helpers.hxx"
 #include "utilities.hxx"
 #include "Controller.hxx"
@@ -61,29 +68,40 @@ public:
     typedef std::vector< property<Adaptor> > props_t;
     typedef typename props_t::iterator props_t_it;
 
+    /*
+     * Static properties accessors
+     */
+    static props_t fields;
 
     property(const std::wstring& prop, getter_t g, setter_t s) : original_index(fields.size()), name(prop), get(g), set(s) {};
+    property(const property& p) :
+        original_index(p.original_index),
+        name(p.name),
+        get(p.get),
+        set(p.set)
+    {};
     ~property() {};
+    property(property&& p) :
+        original_index(std::move(p.original_index)),
+        name(std::move(p.name)),
+        get(std::move(p.get)),
+        set(std::move(p.set))
+    {};
+    property<Adaptor>& operator= (property<Adaptor>&& p)
+    {
+        original_index = std::move(p.original_index);
+        name = std::move(p.name);
+        get = std::move(p.get);
+        set = std::move(p.set);
+        return *this;
+    };
 
-    size_t original_index;
+    int original_index;
     std::wstring name;
     getter_t get;
     setter_t set;
 
-    bool operator< (const std::wstring& v) const
-    {
-        return name < v;
-    }
-
-    static bool original_index_cmp(property<Adaptor> p1, property<Adaptor> p2)
-    {
-        return p1.original_index < p2.original_index;
-    }
-
-    /*
-     * Static properties accessors
-     */
-    static props_t fields;
+public:
 
     /**
      * @return true if the properties have already been setup, false otherwise.
@@ -93,16 +111,68 @@ public:
         return fields.empty();
     }
 
-    /**
-     * Add a property to an Adaptor
-     */
+    /** reserve an amount of property */
+    static void reserve_properties(size_t count)
+    {
+        fields.reserve(count);
+    }
+
+    /** compact the properties and setup for a fast lookup */
+    static void shrink_to_fit()
+    {
+        fields.shrink_to_fit();
+        std::sort(fields.begin(), fields.end());
+    }
+
+    /** add a property to an Adaptor */
     static void add_property(const std::wstring& name, getter_t g, setter_t s)
     {
-        property<Adaptor>::props_t_it pos = std::lower_bound(fields.begin(), fields.end(), name);
-        fields.insert(pos, property(name, g, s));
+        fields.emplace_back(property(name, g, s));
+    }
+
+    /** lookup for a name */
+    static props_t_it find(const std::wstring& name)
+    {
+        props_t_it found = std::lower_bound(fields.begin(), fields.end(), name);
+        if (found != fields.end() && *found == name)
+        {
+            return found;
+        }
+        else
+        {
+            return fields.end();
+        }
     }
 };
 
+template<typename Adaptor>
+inline bool
+operator<(const property<Adaptor>& x, const property<Adaptor>& y)
+{
+    return x.name < y.name;
+}
+
+template<typename Adaptor>
+inline bool
+operator<(const property<Adaptor>& x, const std::wstring& y)
+{
+    return x.name < y;
+}
+
+template<typename Adaptor>
+inline bool
+operator==(const property<Adaptor>& x, const property<Adaptor>& y)
+{
+    return x.name == y.name;
+}
+
+template<typename Adaptor>
+inline bool
+operator==(const property<Adaptor>& x, const std::wstring& y)
+{
+    return x.name == y;
+}
+
 /**
  * Base definition of the adapter pattern, implement the get / set dispatch.
  *
@@ -111,21 +181,32 @@ public:
 template<typename Adaptor, typename Adaptee>
 class BaseAdapter : public types::UserType
 {
+private:
+    using BaseObject = org_scilab_modules_scicos::model::BaseObject;
 
 public:
-    BaseAdapter() : m_adaptee(nullptr) {};
+    explicit BaseAdapter() : m_adaptee(nullptr) {}
     BaseAdapter(const Controller& /*c*/, Adaptee* adaptee) : m_adaptee(adaptee) {}
     BaseAdapter(const BaseAdapter& adapter) : BaseAdapter(adapter, true) {}
     BaseAdapter(const BaseAdapter& adapter, bool cloneChildren) : m_adaptee(nullptr)
     {
-        Controller controller;
-        ScicosID id = controller.cloneObject(adapter.getAdaptee()->id(), cloneChildren, true);
-        m_adaptee = controller.getObject< Adaptee >(id);
+        if (adapter.getAdaptee() != nullptr)
+        {
+            AdapterView update_partial_information;
+            Controller controller;
+
+            Controller::cloned_t mapped;
+            BaseObject* clone = controller.cloneBaseObject(mapped, adapter.getAdaptee(), cloneChildren, true);
+            m_adaptee = static_cast<Adaptee*>(clone);
+        }
     };
+    BaseAdapter(const BaseAdapter&& adapter) : BaseAdapter(Controller(), adapter.m_adaptee) {}
     ~BaseAdapter()
     {
         if (m_adaptee != nullptr)
         {
+            AdapterView update_partial_information;
+
             Controller controller;
             controller.deleteObject(m_adaptee->id());
         }
@@ -137,59 +218,66 @@ public:
 
     bool hasProperty(const std::wstring& _sKey) const
     {
-        typename property<Adaptor>::props_t_it found = std::lower_bound(property<Adaptor>::fields.begin(), property<Adaptor>::fields.end(), _sKey);
-        return found != property<Adaptor>::fields.end() && !(_sKey < found->name);
+        typename property<Adaptor>::props_t_it found = property<Adaptor>::find(_sKey);
+        return found != property<Adaptor>::fields.end();
     }
 
     types::InternalType* getProperty(const std::wstring& _sKey, Controller controller = Controller()) const
     {
-        typename property<Adaptor>::props_t_it found = std::lower_bound(property<Adaptor>::fields.begin(), property<Adaptor>::fields.end(), _sKey);
-        if (found != property<Adaptor>::fields.end() && !(_sKey < found->name))
+        typename property<Adaptor>::props_t_it found = property<Adaptor>::find(_sKey);
+        if (found != property<Adaptor>::fields.end())
         {
-            return found->get(static_cast<Adaptor*>(this), controller);
+            Adaptor& adapter = *static_cast<Adaptor*>(this);
+            return found->get(adapter, controller);
         }
-        return 0;
+        return nullptr;
     }
 
     bool setProperty(const std::wstring& _sKey, types::InternalType* v, Controller controller = Controller())
     {
-        typename property<Adaptor>::props_t_it found = std::lower_bound(property<Adaptor>::fields.begin(), property<Adaptor>::fields.end(), _sKey);
-        if (found != property<Adaptor>::fields.end() && !(_sKey < found->name))
+        typename property<Adaptor>::props_t_it found = property<Adaptor>::find(_sKey);
+        if (found != property<Adaptor>::fields.end())
         {
-            return found->set(*static_cast<Adaptor*>(this), v, controller);
+            Adaptor& adapter = *static_cast<Adaptor*>(this);
+            return found->set(adapter, v, controller);
         }
         return false;
     }
 
+    void copyProperties(const Adaptor& adaptor, Controller controller = Controller())
+    {
+        for (const auto& p : property<Adaptor>::fields)
+        {
+            types::InternalType* pIT = p.get(adaptor, controller);
+            p.set(*static_cast<Adaptor*>(this), pIT, controller);
+            pIT->killMe();
+        }
+    }
+
     /**
      * property as TList accessors
      */
 
     types::InternalType* getAsTList(types::TList* tlist, const Controller& controller)
     {
-        typename property<Adaptor>::props_t properties = property<Adaptor>::fields;
-        std::sort(properties.begin(), properties.end(), property<Adaptor>::original_index_cmp);
+        const typename property<Adaptor>::props_t& properties = property<Adaptor>::fields;
 
         // create the header
         types::String* header = new types::String(1, 1 + (int)properties.size());
         header->set(0, Adaptor::getSharedTypeStr().c_str());
-        int index = 1;
-        for (typename property<Adaptor>::props_t_it it = properties.begin(); it != properties.end(); ++it, ++index)
+        for (const auto& p : properties)
         {
-            header->set(index, it->name.c_str());
-        }
-        tlist->append(header);
+            header->set(1 + p.original_index, p.name.c_str());
 
-        // set the tlist field value
-        for (typename property<Adaptor>::props_t_it it = properties.begin(); it != properties.end(); ++it)
-        {
-            types::InternalType* field = it->get(*static_cast<Adaptor*>(this), controller);
-            tlist->append(field);
+            types::InternalType* field = p.get(*static_cast<Adaptor*>(this), controller);
+            tlist->set(1 + p.original_index, field);
             if (field->isList())
             {
                 field->killMe();
             }
+
         }
+        tlist->set(0, header);
 
         return tlist;
     }
@@ -198,14 +286,14 @@ public:
     {
         if (v->getType() != types::InternalType::ScilabTList && v->getType() != types::InternalType::ScilabMList)
         {
-            get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %s: Tlist or Mlist expected.\n"), Adaptor::getSharedTypeStr().c_str());
+            get_or_allocate_logger()->log(LOG_ERROR, _("Wrong type for field %ls: Tlist or Mlist expected.\n"), Adaptor::getSharedTypeStr().c_str());
             return false;
         }
         types::TList* current = v->getAs<types::TList>();
         // The input TList cannot be empty
         if (current->getSize() < 1)
         {
-            get_or_allocate_logger()->log(LOG_ERROR, _("Wrong length for field %s: at least %d element expected.\n"), Adaptor::getSharedTypeStr().c_str(), 1);
+            get_or_allocate_logger()->log(LOG_ERROR, _("Wrong length for field %ls: at least %d element expected.\n"), Adaptor::getSharedTypeStr().c_str(), 1);
             return false;
         }
 
@@ -213,24 +301,25 @@ public:
         types::String* header = current->getFieldNames();
         if (header->getSize() < 1)
         {
-            get_or_allocate_logger()->log(LOG_ERROR, _("Wrong length for header of field %s: at least %d element expected.\n"), Adaptor::getSharedTypeStr().c_str(), 1);
+            get_or_allocate_logger()->log(LOG_ERROR, _("Wrong length for header of field \"%ls\": at least %d element expected.\n"), Adaptor::getSharedTypeStr().c_str(), 1);
             return false;
         }
         // Make sure it is the same type as the Adapter
         if (header->get(0) != Adaptor::getSharedTypeStr())
         {
-            get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for header of field %s: %s expected.\n"), Adaptor::getSharedTypeStr().c_str(), Adaptor::getSharedTypeStr().c_str());
+            get_or_allocate_logger()->log(LOG_ERROR, _("Wrong value for header of field \"%ls\": \"%ls\" expected.\n"), Adaptor::getSharedTypeStr().c_str(), Adaptor::getSharedTypeStr().c_str());
             return false;
         }
 
         // Retrieve the Adapter's properties
-        typename property<Adaptor>::props_t properties = property<Adaptor>::fields;
+        const typename property<Adaptor>::props_t& properties = property<Adaptor>::fields;
 
         // For each input property, if it corresponds to an Adapter's property, set it.
         for (int index = 1; index < header->getSize(); ++index)
         {
-            typename property<Adaptor>::props_t_it found = std::lower_bound(properties.begin(), properties.end(), header->get(index));
-            if (found != properties.end() && !(header->get(index) < found->name))
+            std::wstring name(header->get(index));
+            typename property<Adaptor>::props_t_it found = property<Adaptor>::find(name);
+            if (found != properties.end())
             {
                 bool status = found->set(*static_cast<Adaptor*>(this), current->get(index), controller);
                 if (!status)
@@ -247,7 +336,46 @@ public:
      * property comparison
      */
 
-    types::Bool* equal(types::UserType*& ut)
+    bool operator==(const types::InternalType& o) override final
+    {
+
+        const Adapters::adapters_index_t adapter_index = Adapters::instance().lookup_by_typename(o.getShortTypeStr());
+        // Check that 'ut' is an Adapter of the same type as *this
+        if (adapter_index == Adapters::INVALID_ADAPTER)
+        {
+            return false;
+        }
+        if (this->getTypeStr() != o.getTypeStr())
+        {
+            return false;
+        }
+
+        const typename property<Adaptor>::props_t& properties = property<Adaptor>::fields;
+
+        bool internal_equal;
+        Controller controller;
+        for (const auto& p : properties)
+        {
+            types::InternalType* ith_prop1 = p.get(*static_cast<const Adaptor*>(this), controller);
+            types::InternalType* ith_prop2 = p.get(*static_cast<const Adaptor*>(&o), controller);
+
+            // loop while the inner types are equals
+            internal_equal = *ith_prop1 == *ith_prop2;
+
+            // Getting a property allocates data, so free it
+            ith_prop1->killMe();
+            ith_prop2->killMe();
+
+            if (!internal_equal)
+            {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    types::Bool* equal(types::UserType*& ut) override final
     {
         const Adapters::adapters_index_t adapter_index = Adapters::instance().lookup_by_typename(ut->getShortTypeStr());
         // Check that 'ut' is an Adapter of the same type as *this
@@ -260,21 +388,19 @@ public:
             return new types::Bool(false);
         }
 
-        typename property<Adaptor>::props_t properties = property<Adaptor>::fields;
-        std::sort(properties.begin(), properties.end(), property<Adaptor>::original_index_cmp);
+        const typename property<Adaptor>::props_t& properties = property<Adaptor>::fields;
 
-        types::Bool* ret = new types::Bool(1, 1 + properties.size());
+        types::Bool* ret = new types::Bool(1, 1 + (int)properties.size());
         ret->set(0, true); // First field is just the Adapter's name, which has been checked by the above conditions
 
         Controller controller;
-        int index = 1;
-        for (typename property<Adaptor>::props_t_it it = properties.begin(); it != properties.end(); ++it, ++index)
+        for (const auto& p : properties)
         {
-            types::InternalType* ith_prop1 = it->get(*static_cast<Adaptor*>(this), controller);
-            types::InternalType* ith_prop2 = it->get(*static_cast<Adaptor*>(ut), controller);
-            ret->set(index, *ith_prop1 == *ith_prop2);
+            types::InternalType* ith_prop1 = p.get(*static_cast<Adaptor*>(this), controller);
+            types::InternalType* ith_prop2 = p.get(*static_cast<Adaptor*>(ut), controller);
+            ret->set(p.original_index + 1, *ith_prop1 == *ith_prop2);
 
-            // Getting a property allocates data, so free it
+            // Getting a property allocates data, so free them
             ith_prop1->killMe();
             ith_prop2->killMe();
         }
@@ -283,6 +409,28 @@ public:
     }
 
     /**
+     * Return a default constructed Scilab value
+     */
+    template<typename T>
+    static types::InternalType* default_value()
+    {
+        T* o = new T();
+        o->IncreaseRef();
+        return o;
+    }
+
+    /**
+     * Increase reference count to store a Scilab value
+     */
+    template<typename T>
+    static T* reference_value(T* o)
+    {
+        o->IncreaseRef();
+        return o;
+    }
+
+
+    /**
      * @return the Adaptee
      */
     Adaptee* getAdaptee() const
@@ -294,11 +442,11 @@ public:
      * All following methods should be implemented by each template instance
      */
 
-    virtual std::wstring getTypeStr() = 0;
-    virtual std::wstring getShortTypeStr() = 0;
+    virtual std::wstring getTypeStr() const override = 0;
+    virtual std::wstring getShortTypeStr() const override = 0;
 
 private:
-    virtual UserType* clone() final
+    virtual UserType* clone() override final
     {
         return new Adaptor(*static_cast<Adaptor*>(this));
     }
@@ -307,15 +455,21 @@ private:
      * Implement a specific types::User
      */
 
-    bool isAssignable()
+    bool isAssignable() override final
     {
         return true;
     }
 
-    bool extract(const std::wstring & name, types::InternalType *& out)
+    // sb.model.rpar.contrib will return a reference to contrib
+    bool isContainer() override final
     {
-        typename property<Adaptor>::props_t_it found = std::lower_bound(property<Adaptor>::fields.begin(), property<Adaptor>::fields.end(), name);
-        if (found != property<Adaptor>::fields.end() && !(name < found->name))
+        return true;
+    }
+
+    bool extract(const std::wstring & name, types::InternalType *& out) override final
+    {
+        typename property<Adaptor>::props_t_it found = property<Adaptor>::find(name);
+        if (found != property<Adaptor>::fields.end())
         {
             Controller controller;
             types::InternalType* value = found->get(*static_cast<Adaptor*>(this), controller);
@@ -338,7 +492,7 @@ private:
         return false;
     }
 
-    types::InternalType* extract(types::typed_list* _pArgs)
+    types::InternalType* extract(types::typed_list* _pArgs) override final
     {
         if (_pArgs->size() == 0)
         {
@@ -363,17 +517,14 @@ private:
                 {
                     // When _pArgs is '1', return the list of the property names of the Adaptor
 
-                    // Sort the properties before extracting them
-                    typename property<Adaptor>::props_t properties = property<Adaptor>::fields;
-                    std::sort(properties.begin(), properties.end(), property<Adaptor>::original_index_cmp);
+                    const typename property<Adaptor>::props_t& properties = property<Adaptor>::fields;
 
                     // Allocate the return
                     types::String* pOut = new types::String(1, static_cast<int>(properties.size()));
 
-                    int i = 0;
-                    for (typename property<Adaptor>::props_t_it it = properties.begin(); it != properties.end(); ++it, ++i)
+                    for (const auto& p : properties)
                     {
-                        pOut->set(i, it->name.data());
+                        pOut->set(p.original_index, p.name.data());
                     }
                     return pOut;
                 }
@@ -387,23 +538,34 @@ private:
         return NULL;
     }
 
-    types::UserType* insert(types::typed_list* _pArgs, types::InternalType* _pSource)
+    types::UserType* insert(types::typed_list* _pArgs, types::InternalType* _pSource) override final
     {
         for (size_t i = 0; i < _pArgs->size(); i++)
         {
             if ((*_pArgs)[i]->isString())
             {
+                Controller controller;
+
                 types::String* pStr = (*_pArgs)[i]->getAs<types::String>();
-                std::wstring name = pStr->get(0);
 
-                Controller controller;
-                typename property<Adaptor>::props_t_it found = std::lower_bound(property<Adaptor>::fields.begin(), property<Adaptor>::fields.end(), name);
-                if (found != property<Adaptor>::fields.end() && !(name < found->name))
+                Adaptor* work;
+                if (getAdaptee()->refCount() > 0)
+                {
+                    // clone()
+                    work = new Adaptor(*static_cast<Adaptor*>(this));
+                }
+                else
+                {
+                    work = static_cast<Adaptor*>(this);
+                }
+
+                typename property<Adaptor>::props_t_it found = property<Adaptor>::find(std::wstring(pStr->get(0)));
+                if (found != property<Adaptor>::fields.end())
                 {
-                    found->set(*static_cast<Adaptor*>(this), _pSource, controller);
+                    found->set(*work, _pSource, controller);
                 }
 
-                return this;
+                return work;
             }
             else
             {
@@ -415,37 +577,36 @@ private:
         return NULL;
     }
 
-    void whoAmI(void)
+    void whoAmI(void) override
     {
         std::cout << "scicos object";
     }
 
-    bool hasToString()
+    bool hasToString() override final
     {
         // Do not allow scilab to call toString of this class
         return false;
     }
 
-    bool toString(std::wostringstream& ostr)
+    bool toString(std::wostringstream& ostr) override final
     {
         // Deprecated, use the overload instead
-        typename property<Adaptor>::props_t properties = property<Adaptor>::fields;
-        std::sort(properties.begin(), properties.end(), property<Adaptor>::original_index_cmp);
+        const typename property<Adaptor>::props_t& properties = property<Adaptor>::fields;
 
-        ostr << L"scicos_" <<  getTypeStr() << L" type :" << std::endl;
-        for (typename property<Adaptor>::props_t_it it = properties.begin(); it != properties.end(); ++it)
+        ostr << L"scicos_" <<  getTypeStr() << L" type :" << '\n';
+        for (const auto& p : properties)
         {
-            ostr << L"  " << it->name << std::endl;
+            ostr << L"  " << p.name << '\n';
         }
         return true;
     }
 
-    bool isInvokable() const
+    bool isInvokable() const override final
     {
         return true;
     }
 
-    bool invoke(types::typed_list & in, types::optional_list & /*opt*/, int /*_iRetCount*/, types::typed_list & out, const ast::Exp & e) override
+    bool invoke(types::typed_list & in, types::optional_list & /*opt*/, int /*_iRetCount*/, types::typed_list & out, const ast::Exp & e) override final
     {
         if (in.size() == 0)
         {