Xcos MVC: fix includes
[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 <vector>
15 #include <utility>
16 #include <algorithm>
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), has_looped(false), 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     model::BaseObject* o;
54     switch (k)
55     {
56         case ANNOTATION:
57             o = new model::Annotation();
58             break;
59         case DIAGRAM:
60             o = new model::Diagram();
61             break;
62         case BLOCK:
63             o = new model::Block();
64             break;
65         case LINK:
66             o = new model::Link();
67             break;
68         case PORT:
69             o = new model::Port();
70             break;
71     }
72
73     /*
74      * Found the next unused id
75      */
76     lastId++;
77     if (lastId == 0)
78     {
79         lastId++;
80         has_looped = true;
81     }
82
83     if (has_looped)
84     {
85         bool has_looped_twice = false;
86
87         // while key is found
88         for (objects_map_t::iterator iter = allObjects.find(lastId);
89                 iter != allObjects.end();
90                 iter = allObjects.find(lastId))
91         {
92             // try a valid ID
93             lastId++;
94             if (lastId == 0)
95             {
96                 lastId++;
97
98                 // return the invalid value if the loop counter encounter 2 zeros.
99                 if (has_looped_twice)
100                 {
101                     return ScicosID();
102                 }
103                 else
104                 {
105                     has_looped_twice = true;
106                 }
107             }
108         }
109     }
110
111     /*
112      * Insert then return
113      */
114     allObjects.emplace(lastId, o);
115     o->id(lastId);
116     return lastId;
117 }
118
119 unsigned Model::referenceObject(const ScicosID uid)
120 {
121     objects_map_t::iterator iter = allObjects.find(uid);
122     if (iter == allObjects.end())
123     {
124         return 0;
125     }
126
127     ModelObject& modelObject = iter->second;
128     return ++(modelObject.m_refCounter);
129 }
130
131 unsigned& Model::referenceCount(ScicosID uid)
132 {
133     objects_map_t::iterator iter = allObjects.find(uid);
134     if (iter == allObjects.end())
135     {
136         throw std::string("key has not been found");
137     }
138
139     ModelObject& modelObject = iter->second;
140     return modelObject.m_refCounter;
141
142 }
143
144 void Model::deleteObject(ScicosID uid)
145 {
146     objects_map_t::iterator iter = allObjects.find(uid);
147     if (iter == allObjects.end())
148     {
149         throw std::string("key has not been found");
150     }
151
152     ModelObject& modelObject = iter->second;
153     if (modelObject.m_refCounter == 0)
154     {
155         model::BaseObject* o = modelObject.m_o;
156         allObjects.erase(iter);
157         delete o;
158     }
159     else
160     {
161         --(modelObject.m_refCounter);
162     }
163 }
164
165 model::BaseObject* Model::getObject(ScicosID uid) const
166 {
167     objects_map_t::const_iterator iter = allObjects.find(uid);
168     if (iter == allObjects.end())
169     {
170         throw std::string("key has not been found");
171     }
172
173     return iter->second.m_o;
174 }
175
176 // datatypes being a vector of Datatype pointers, we need a dereferencing comparison operator to use std::lower_bound()
177 static bool isInferior(const model::Datatype* d1, const model::Datatype* d2)
178 {
179     return *d1 < *d2;
180 }
181
182 model::Datatype* Model::flyweight(const model::Datatype& d)
183 {
184     datatypes_set_t::iterator iter = std::lower_bound(datatypes.begin(), datatypes.end(), &d, isInferior);
185     if (iter != datatypes.end() && !(d < **iter)) // if d is found
186     {
187         (*iter)->m_refCount++;
188         return *iter;
189     }
190     else
191     {
192         return *datatypes.insert(iter, new model::Datatype(d));
193     }
194 }
195
196 void Model::erase(model::Datatype* d)
197 {
198     datatypes_set_t::iterator iter = std::lower_bound(datatypes.begin(), datatypes.end(), d, isInferior);
199     if (iter != datatypes.end() && !(*d < **iter)) // if d is found
200     {
201         (*iter)->m_refCount--;
202         if ((*iter)->m_refCount < 0)
203         {
204             delete *iter;
205             datatypes.erase(iter);
206         }
207     }
208 }
209
210 } /* namespace org_scilab_modules_scicos */