Xcos MVC: standardize C++ code
[scilab.git] / scilab / modules / scicos / src / cpp / Model.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2014-2014 - Scilab Enterprises - Clement DAVID
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 <string>
14 #include <utility>
15 #include <algorithm>
16 #include <memory>
17
18 #include "Model.hxx"
19 #include "utilities.hxx"
20
21 #include "model/BaseObject.hxx"
22 #include "model/Annotation.hxx"
23 #include "model/Diagram.hxx"
24 #include "model/Block.hxx"
25 #include "model/Link.hxx"
26 #include "model/Port.hxx"
27
28 namespace org_scilab_modules_scicos
29 {
30
31 Model::Model() :
32     lastId(0), allObjects()
33 {
34     std::vector<int> datatypeDefault (3, 1);
35     datatypeDefault[0] = -1;
36     datatypes.push_back(new model::Datatype(datatypeDefault));
37 }
38
39 Model::~Model()
40 {
41     while (!datatypes.empty())
42     {
43         Model::erase(datatypes[0]);
44     }
45     datatypes.clear();
46 }
47
48 ScicosID Model::createObject(kind_t k)
49 {
50     /*
51      * Allocate the object per kind
52      */
53     std::shared_ptr<model::BaseObject> o;
54     switch (k)
55     {
56         case ANNOTATION:
57             o = std::make_shared<model::Annotation>(model::Annotation());
58             break;
59         case DIAGRAM:
60             o = std::make_shared<model::Diagram>(model::Diagram());
61             break;
62         case BLOCK:
63             o = std::make_shared<model::Block>(model::Block());
64             break;
65         case LINK:
66             o = std::make_shared<model::Link>(model::Link());
67             break;
68         case PORT:
69             o = std::make_shared<model::Port>(model::Port());
70             break;
71     }
72
73     /*
74      * Found the next unused id
75      */
76     lastId++;
77     if (lastId == 0)
78     {
79         lastId++;
80     }
81
82     // full map, detection
83     bool has_looped = false;
84
85     objects_map_t::iterator iter = allObjects.lower_bound(lastId);
86     while (iter != allObjects.end() && !(lastId < iter->first)) // while key is found
87     {
88         // try a valid ID
89         lastId++;
90         if (lastId == 0)
91         {
92             lastId++;
93
94             // if the map is full, return 0;
95             if (has_looped)
96             {
97                 return 0;
98             }
99             has_looped = true;
100         }
101
102         // look for it
103         iter = allObjects.lower_bound(lastId);
104     }
105
106     /*
107      * Insert then return
108      */
109     allObjects.insert(iter, std::make_pair(lastId, o));
110     o->id(lastId);
111     return lastId;
112 }
113
114 void Model::deleteObject(ScicosID uid)
115 {
116     objects_map_t::iterator iter = allObjects.lower_bound(uid);
117     if (iter == allObjects.end() || uid < iter->first)
118     {
119         throw std::string("key has not been found");
120     }
121
122     allObjects.erase(iter);
123 }
124
125 std::shared_ptr<model::BaseObject> Model::getObject(ScicosID uid) const
126 {
127     objects_map_t::const_iterator iter = allObjects.lower_bound(uid);
128     if (iter == allObjects.end() || uid < iter->first)
129     {
130         throw std::string("key has not been found");
131     }
132
133     return iter->second;
134 }
135
136 // datatypes being a vector of Datatype pointers, we need a dereferencing comparison operator to use std::lower_bound()
137 static bool isInferior(const model::Datatype* d1, const model::Datatype* d2)
138 {
139     return *d1 < *d2;
140 }
141
142 model::Datatype* Model::flyweight(const model::Datatype& d)
143 {
144     datatypes_set_t::iterator iter = std::lower_bound(datatypes.begin(), datatypes.end(), &d, isInferior);
145     if (iter != datatypes.end() && !(d < **iter)) // if d is found
146     {
147         (*iter)->m_refCount++;
148         return *iter;
149     }
150     else
151     {
152         return *datatypes.insert(iter, new model::Datatype(d));
153     }
154 }
155
156 void Model::erase(model::Datatype* d)
157 {
158     datatypes_set_t::iterator iter = std::lower_bound(datatypes.begin(), datatypes.end(), d, isInferior);
159     if (iter != datatypes.end() && !(*d < **iter)) // if d is found
160     {
161         (*iter)->m_refCount--;
162         if ((*iter)->m_refCount < 0)
163         {
164             delete *iter;
165             datatypes.erase(iter);
166         }
167     }
168 }
169
170 } /* namespace org_scilab_modules_scicos */