Xcos MVC: fix valgrind detected invalid access
[scilab.git] / scilab / modules / scicos / src / cpp / view_scilab / ModelAdapter.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 <cwchar>
14 #include <cstring>
15
16 #include <string>
17 #include <vector>
18 #include <algorithm>
19 #include <sstream>
20 #include <memory>
21
22 #include "int.hxx"
23 #include "bool.hxx"
24 #include "double.hxx"
25 #include "string.hxx"
26 #include "list.hxx"
27 #include "tlist.hxx"
28 #include "user.hxx"
29
30 #include "Controller.hxx"
31 #include "Adapters.hxx"
32 #include "ModelAdapter.hxx"
33 #include "DiagramAdapter.hxx"
34 #include "ports_management.hxx"
35 #include "utilities.hxx"
36
37 extern "C" {
38 #include "sci_malloc.h"
39 #include "charEncoding.h"
40 }
41
42 namespace org_scilab_modules_scicos
43 {
44 namespace view_scilab
45 {
46 namespace
47 {
48
49 const std::string input ("input");
50 const std::string output ("output");
51 const std::string inimpl ("inimpl");
52 const std::string outimpl ("outimpl");
53
54 const std::wstring modelica (L"modelica");
55 const std::wstring model (L"model");
56 const std::wstring inputs (L"inputs");
57 const std::wstring outputs (L"outputs");
58 const std::wstring parameters (L"parameters");
59
60 struct sim
61 {
62
63     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
64     {
65         ScicosID adaptee = adaptor.getAdaptee()->id();
66
67         // First, extract the function Name
68         std::string name;
69         controller.getObjectProperty(adaptee, BLOCK, SIM_FUNCTION_NAME, name);
70         types::String* Name = new types::String(1, 1);
71         Name->set(0, name.data());
72
73         // Then the Api. If it is zero, then just return the Name. Otherwise, return a list containing both.
74         int api;
75         controller.getObjectProperty(adaptee, BLOCK, SIM_FUNCTION_API, api);
76
77         if (api == 0)
78         {
79             return Name;
80         }
81         else
82         {
83             types::Double* Api = new types::Double(static_cast<double>(api));
84             types::List* o = new types::List();
85             o->set(0, Name);
86             o->set(1, Api);
87             return o;
88         }
89     }
90
91     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
92     {
93         ScicosID adaptee = adaptor.getAdaptee()->id();
94
95         if (v->getType() == types::InternalType::ScilabString)
96         {
97             types::String* current = v->getAs<types::String>();
98             if (current->getSize() != 1)
99             {
100                 return false;
101             }
102
103             char* c_str = wide_string_to_UTF8(current->get(0));
104             std::string name(c_str);
105             FREE(c_str);
106
107             // If the input is a scalar string, then the functionApi is 0.
108             int api = 0;
109
110             controller.setObjectProperty(adaptee, BLOCK, SIM_FUNCTION_NAME, name);
111             controller.setObjectProperty(adaptee, BLOCK, SIM_FUNCTION_API, api);
112         }
113         else if (v->getType() == types::InternalType::ScilabList)
114         {
115             // If the input is a 2-sized list, then it must be string and positive integer.
116             types::List* current = v->getAs<types::List>();
117             if (current->getSize() != 2)
118             {
119                 return false;
120             }
121             if (current->get(0)->getType() != types::InternalType::ScilabString || current->get(1)->getType() != types::InternalType::ScilabDouble)
122             {
123                 return false;
124             }
125
126             types::String* Name = current->get(0)->getAs<types::String>();
127             if (Name->getSize() != 1)
128             {
129                 return false;
130             }
131             char* c_str = wide_string_to_UTF8(Name->get(0));
132             std::string name(c_str);
133             FREE(c_str);
134
135             types::Double* Api = current->get(1)->getAs<types::Double>();
136             if (Api->getSize() != 1)
137             {
138                 return false;
139             }
140             double api = Api->get(0);
141             if (floor(api) != api)
142             {
143                 return false;
144             }
145             int api_int = static_cast<int>(api);
146
147             controller.setObjectProperty(adaptee, BLOCK, SIM_FUNCTION_NAME, name);
148             controller.setObjectProperty(adaptee, BLOCK, SIM_FUNCTION_API, api_int);
149         }
150         else
151         {
152             return false;
153         }
154         return true;
155     }
156 };
157
158 struct in
159 {
160
161     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
162     {
163         return get_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, INPUTS, controller);
164     }
165
166     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
167     {
168         return update_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, INPUTS, controller, v);
169     }
170 };
171
172 struct in2
173 {
174
175     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
176     {
177         return get_ports_property<ModelAdapter, DATATYPE_COLS>(adaptor, INPUTS, controller);
178     }
179
180     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
181     {
182         return set_ports_property<ModelAdapter, DATATYPE_COLS>(adaptor, INPUTS, controller, v);
183     }
184 };
185
186 struct intyp
187 {
188
189     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
190     {
191         return get_ports_property<ModelAdapter, DATATYPE_TYPE>(adaptor, INPUTS, controller);
192     }
193
194     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
195     {
196         return set_ports_property<ModelAdapter, DATATYPE_TYPE>(adaptor, INPUTS, controller, v);
197     }
198 };
199
200 struct out
201 {
202
203     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
204     {
205         return get_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, OUTPUTS, controller);
206     }
207
208     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
209     {
210         return update_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, OUTPUTS, controller, v);
211     }
212 };
213
214 struct out2
215 {
216
217     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
218     {
219         return get_ports_property<ModelAdapter, DATATYPE_COLS>(adaptor, OUTPUTS, controller);
220     }
221
222     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
223     {
224         return set_ports_property<ModelAdapter, DATATYPE_COLS>(adaptor, OUTPUTS, controller, v);
225     }
226 };
227
228 struct outtyp
229 {
230
231     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
232     {
233         return get_ports_property<ModelAdapter, DATATYPE_TYPE>(adaptor, OUTPUTS, controller);
234     }
235
236     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
237     {
238         return set_ports_property<ModelAdapter, DATATYPE_TYPE>(adaptor, OUTPUTS, controller, v);
239     }
240 };
241
242 struct evtin
243 {
244
245     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
246     {
247         return get_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, EVENT_INPUTS, controller);
248     }
249
250     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
251     {
252         return update_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, EVENT_INPUTS, controller, v);
253     }
254 };
255
256 struct evtout
257 {
258
259     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
260     {
261         return get_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, EVENT_OUTPUTS, controller);
262     }
263
264     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
265     {
266         return update_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, EVENT_OUTPUTS, controller, v);
267     }
268 };
269
270 struct state
271 {
272
273     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
274     {
275         ScicosID adaptee = adaptor.getAdaptee()->id();
276
277         std::vector<double> state;
278         controller.getObjectProperty(adaptee, BLOCK, STATE, state);
279
280         double* data;
281         types::Double* o = new types::Double((int)state.size(), 1, &data);
282
283 #ifdef _MSC_VER
284         std::copy(state.begin(), state.end(), stdext::checked_array_iterator<double*>(data, state.size()));
285 #else
286         std::copy(state.begin(), state.end(), data);
287 #endif
288         return o;
289     }
290
291     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
292     {
293
294         if (v->getType() != types::InternalType::ScilabDouble)
295         {
296             return false;
297         }
298
299         types::Double* current = v->getAs<types::Double>();
300         if (current->getCols() != 0 && current->getCols() != 1)
301         {
302             return false;
303         }
304
305         ScicosID adaptee = adaptor.getAdaptee()->id();
306
307         std::vector<double> state (current->getSize());
308         std::copy(current->getReal(), current->getReal() + current->getSize(), state.begin());
309
310         controller.setObjectProperty(adaptee, BLOCK, STATE, state);
311         return true;
312     }
313 };
314
315 struct dstate
316 {
317
318     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
319     {
320         ScicosID adaptee = adaptor.getAdaptee()->id();
321
322         std::vector<double> dstate;
323         controller.getObjectProperty(adaptee, BLOCK, DSTATE, dstate);
324
325         double* data;
326         types::Double* o = new types::Double((int)dstate.size(), 1, &data);
327
328 #ifdef _MSC_VER
329         std::copy(dstate.begin(), dstate.end(), stdext::checked_array_iterator<double*>(data, dstate.size()));
330 #else
331         std::copy(dstate.begin(), dstate.end(), data);
332 #endif
333         return o;
334     }
335
336     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
337     {
338         ScicosID adaptee = adaptor.getAdaptee()->id();
339
340         if (v->getType() == types::InternalType::ScilabString)
341         {
342             types::String* current = v->getAs<types::String>();
343             if (current->getSize() != 1)
344             {
345                 return false;
346             }
347
348             std::vector<double> dstate;
349             controller.setObjectProperty(adaptee, BLOCK, DSTATE, dstate);
350             return true;
351         }
352
353         if (v->getType() != types::InternalType::ScilabDouble)
354         {
355             return false;
356         }
357         types::Double* current = v->getAs<types::Double>();
358         if (current->getCols() != 0 && current->getCols() != 1)
359         {
360             return false;
361         }
362
363         std::vector<double> dstate (current->getSize());
364         std::copy(current->getReal(), current->getReal() + current->getSize(), dstate.begin());
365
366         controller.setObjectProperty(adaptee, BLOCK, DSTATE, dstate);
367         return true;
368     }
369 };
370
371 void decodeDims(std::vector<int>::iterator& prop_it, std::vector<int>& dims)
372 {
373     const int iDims = *prop_it++;
374     dims.resize(iDims);
375
376     memcpy(&dims[0], &(*prop_it), iDims * sizeof(int));
377     prop_it += iDims;
378 }
379
380 void encodeDims(std::vector<int>& prop_content, types::GenericType* v)
381 {
382     const int iDims = v->getDims();
383     prop_content.push_back(iDims);
384
385     const int index = prop_content.size();
386     prop_content.resize(index + iDims);
387
388     memcpy(&prop_content[index], v->getDimsArray(), iDims * sizeof(int));
389 }
390
391 /**
392  * Calculate the length increment depending on the ::value_type of the buffer and the type of the Scilab type
393  *
394  * @param V buffer type which must have a ::value_type field
395  * @param T Scilab type
396  * @param v the instance on the Scilab type
397  * @return the number of V elements used to store the data
398  */
399 template<typename V, typename T>
400 size_t required_length(const V& /*it*/, T* v)
401 {
402     const size_t sizeof_prop_value = sizeof(typename V::value_type);
403     if (sizeof(typename T::type) >= sizeof_prop_value)
404     {
405         return v->getSize() * sizeof(typename T::type) / sizeof_prop_value;
406     }
407     else
408     {
409         // increase the size to contain enough space, manage the size_t rounding issue
410         return v->getSize() * sizeof(typename T::type) + (sizeof_prop_value - 1) / sizeof_prop_value;
411     }
412 }
413
414 template <typename T>
415 T* decode(std::vector<int>::iterator& prop_it)
416 {
417     std::vector<int> dims;
418     decodeDims(prop_it, dims);
419
420     T* v = new T(static_cast<int>(dims.size()), &dims[0]);
421     memcpy(v->get(), &(*prop_it), v->getSize() * sizeof(typename T::type));
422
423     prop_it += required_length(prop_it, v);
424     return v;
425 }
426
427 template <typename T>
428 bool encode(std::vector<int>& prop_content, T* v)
429 {
430     encodeDims(prop_content, v);
431
432     const int index = prop_content.size();
433     const int len = required_length(prop_content, v);
434     prop_content.resize(index + len);
435
436     // Using contiguity of the memory, we save the input into 'prop_content'
437     memcpy(&prop_content[index], v->get(), v->getSize() * sizeof(typename T::type));
438     return true;
439 }
440
441 template<>
442 types::Double* decode(std::vector<int>::iterator& prop_it)
443 {
444     std::vector<int> dims;
445     decodeDims(prop_it, dims);
446
447     bool isComplex = *prop_it++;
448
449     types::Double* v = new types::Double(static_cast<int>(dims.size()), &dims[0], isComplex);
450     memcpy(v->getReal(), &(*prop_it), v->getSize() * sizeof(double));
451
452     if (isComplex)
453     {
454         prop_it += required_length(prop_it, v);
455         memcpy(v->getImg(), &(*prop_it), v->getSize() * sizeof(double));
456     }
457
458     prop_it += required_length(prop_it, v);
459     return v;
460 }
461
462 bool encode(std::vector<int>& prop_content, types::Double* v)
463 {
464     encodeDims(prop_content, v);
465
466     // Flag for complex
467     prop_content.push_back(v->isComplex());
468
469     const int index = prop_content.size();
470     const int len = required_length(prop_content, v);
471     prop_content.resize(index + len);
472
473     // Using contiguity of the memory, we save the input into 'prop_content'
474     memcpy(&prop_content[index], v->get(), v->getSize() * sizeof(double));
475
476     if (v->isComplex())
477     {
478         prop_content.resize(index + 2 * len);
479         // Using contiguity of the memory, we save the input into 'prop_content'
480         memcpy(&prop_content[index + len], v->getImg(), v->getSize() * sizeof(double));
481     }
482
483     return true;
484 }
485
486 template<>
487 types::String* decode(std::vector<int>::iterator& prop_it)
488 {
489     std::vector<int> dims;
490     decodeDims(prop_it, dims);
491
492     types::String* v = new types::String(static_cast<int>(dims.size()), &dims[0]);
493     // retrieving the first value iterator
494     std::vector<int>::iterator strData = prop_it + v->getSize();
495
496     v->set(0, (char*) & (*strData));
497     strData += static_cast<size_t>(*prop_it++);
498     for (int i = 1; i < v->getSize(); i++)
499     {
500         v->set(i, (char*) & (*strData));
501
502         // increment the value iterator by the number of element
503         const size_t numberOfElem = static_cast<size_t>(*prop_it) - static_cast<size_t>(*(prop_it - 1)) ;
504         prop_it++;
505         strData += numberOfElem;
506     }
507
508     prop_it = strData;
509     return v;
510 }
511
512 bool encode(std::vector<int>& prop_content, types::String* v)
513 {
514     encodeDims(prop_content, v);
515
516     const int index = prop_content.size();
517
518     std::vector<char*> utf8;
519     utf8.reserve(v->getSize());
520
521     std::vector<size_t> str_len;
522     str_len.reserve(v->getSize());
523
524     int offset = 0;
525     for (int i = 0; i < v->getSize(); i++)
526     {
527         char* str = wide_string_to_UTF8(v->get(i));
528         utf8.push_back(str);
529
530         // adding the '\0' byte to the len
531         const size_t len = strlen(str) + 1;
532         str_len.push_back(len);
533
534         offset += (len * sizeof(char) + sizeof(int) - 1) / sizeof(int);
535         prop_content.push_back(offset);
536     }
537
538     // reserve space for the string offsets and contents
539     prop_content.resize(index + v->getSize() + offset);
540
541     size_t len = str_len[0];
542     memcpy(&prop_content[index + v->getSize()], &(*utf8[0]), len * sizeof(char));
543     for (int i = 1; i < v->getSize(); i++)
544     {
545         len = str_len[i];
546         memcpy(&prop_content[index + v->getSize() + prop_content[index + i - 1]], &(*utf8[i]), len * sizeof(char));
547     }
548
549     // free all the string, after being copied
550     for (std::vector<char*>::iterator it = utf8.begin(); it != utf8.end(); it++)
551     {
552         FREE(*it);
553     }
554
555     return true;
556 }
557
558
559 template<>
560 types::List* decode(std::vector<int>::iterator& prop_it)
561 {
562     int length = *prop_it++;
563
564     types::List* list = new types::List();
565     for (int i = 0; i < length; i++)
566     {
567         switch (*prop_it++)
568         {
569             case types::InternalType::ScilabDouble:
570                 list->set(i, decode<types::Double>(prop_it));
571                 break;
572             case types::InternalType::ScilabInt8:
573                 list->set(i, decode<types::Int8>(prop_it));
574                 break;
575             case types::InternalType::ScilabUInt8:
576                 list->set(i, decode<types::UInt8>(prop_it));
577                 break;
578             case types::InternalType::ScilabInt16:
579                 list->set(i, decode<types::Int16>(prop_it));
580                 break;
581             case types::InternalType::ScilabUInt16:
582                 list->set(i, decode<types::UInt16>(prop_it));
583                 break;
584             case types::InternalType::ScilabInt32:
585                 list->set(i, decode<types::Int32>(prop_it));
586                 break;
587             case types::InternalType::ScilabUInt32:
588                 list->set(i, decode<types::UInt32>(prop_it));
589                 break;
590             case types::InternalType::ScilabInt64:
591                 list->set(i, decode<types::Int64>(prop_it));
592                 break;
593             case types::InternalType::ScilabUInt64:
594                 list->set(i, decode<types::UInt64>(prop_it));
595                 break;
596             case types::InternalType::ScilabString:
597                 list->set(i, decode<types::String>(prop_it));
598                 break;
599             case types::InternalType::ScilabBool:
600                 list->set(i, decode<types::Bool>(prop_it));
601                 break;
602             case types::InternalType::ScilabList:
603                 list->set(i, decode<types::List>(prop_it));
604                 break;
605         }
606     }
607     return list;
608 }
609
610 bool encode(std::vector<int>& prop_content, types::List* list)
611 {
612     // Save the number of list elements in the first element
613     prop_content.push_back(list->getSize());
614
615     for (int i = 0; i < list->getSize(); ++i)
616     {
617         // Insert a new element and save its variable type
618         prop_content.push_back(list->get(i)->getType());
619
620         switch (list->get(i)->getType())
621         {
622             case types::InternalType::ScilabDouble:
623                 encode(prop_content, list->get(i)->getAs<types::Double>());
624                 break;
625             case types::InternalType::ScilabInt8:
626                 encode(prop_content, list->get(i)->getAs<types::Int8>());
627                 break;
628             case types::InternalType::ScilabUInt8:
629                 encode(prop_content, list->get(i)->getAs<types::UInt8>());
630                 break;
631             case types::InternalType::ScilabInt16:
632                 encode(prop_content, list->get(i)->getAs<types::Int16>());
633                 break;
634             case types::InternalType::ScilabUInt16:
635                 encode(prop_content, list->get(i)->getAs<types::UInt16>());
636                 break;
637             case types::InternalType::ScilabInt32:
638                 encode(prop_content, list->get(i)->getAs<types::Int32>());
639                 break;
640             case types::InternalType::ScilabUInt32:
641                 encode(prop_content, list->get(i)->getAs<types::UInt32>());
642                 break;
643             case types::InternalType::ScilabInt64:
644                 encode(prop_content, list->get(i)->getAs<types::Int64>());
645                 break;
646             case types::InternalType::ScilabUInt64:
647                 encode(prop_content, list->get(i)->getAs<types::UInt64>());
648                 break;
649             case types::InternalType::ScilabString:
650                 encode(prop_content, list->get(i)->getAs<types::String>());
651                 break;
652             case types::InternalType::ScilabBool:
653                 encode(prop_content, list->get(i)->getAs<types::Bool>());
654                 break;
655             default:
656                 return false;
657         }
658     }
659
660     return true;
661 }
662
663 struct odstate
664 {
665
666     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
667     {
668         ScicosID adaptee = adaptor.getAdaptee()->id();
669
670         std::vector<int> prop_content;
671         controller.getObjectProperty(adaptee, BLOCK, ODSTATE, prop_content);
672
673         // corner-case, the empty content is an empty double
674         if (prop_content.empty())
675         {
676             return types::Double::Empty();
677         }
678
679         // the returned value is a list
680         std::vector<int>::iterator prop_it = prop_content.begin();
681         return decode<types::List>(prop_it);
682     }
683
684     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
685     {
686         ScicosID adaptee = adaptor.getAdaptee()->id();
687         std::vector<int> prop_content;
688
689         // corner-case the empty content is an empty-double
690         if (v->getType() == types::InternalType::ScilabDouble)
691         {
692             types::Double* current = v->getAs<types::Double>();
693             if (current->getSize() != 0)
694             {
695                 return false;
696             }
697
698             // propr_content is empty
699             controller.setObjectProperty(adaptee, BLOCK, ODSTATE, prop_content);
700             return true;
701         }
702
703         if (v->getType() != types::InternalType::ScilabList)
704         {
705             return false;
706         }
707
708         types::List* list = v->getAs<types::List>();
709         if (!encode(prop_content, list))
710         {
711             return false;
712         }
713
714         controller.setObjectProperty(adaptee, BLOCK, ODSTATE, prop_content);
715         return true;
716     }
717 };
718
719 /*
720  * When setting a diagram in 'rpar', the Superblock's ports must be consistent with the "port blocks" inside it.
721  * By "port blocks", we mean IN_f, OUT_f, CLKIN_f, CLKOUT_f, CLKINV_f, CLKOUTV_f, INIMPL_f and OUTIMPL_f.
722  */
723 bool setInnerBlocksRefs(ModelAdapter& adaptor, const std::vector<ScicosID>& children, Controller& controller)
724 {
725     ScicosID adaptee = adaptor.getAdaptee()->id();
726
727     for (std::vector<ScicosID>::const_iterator it = children.begin(); it != children.end(); ++it)
728     {
729         if (controller.getObject(*it)->kind() == BLOCK) // Rule out Annotations and Links
730         {
731             std::string name;
732             controller.getObjectProperty(*it, BLOCK, SIM_FUNCTION_NAME, name);
733
734             // Find the "port blocks"
735             if (name == input || name == inimpl || name == output || name == outimpl)
736             {
737                 std::vector<int> ipar;
738                 controller.getObjectProperty(*it, BLOCK, IPAR, ipar);
739                 if (ipar.size() != 1)
740                 {
741                     return false;
742                 }
743                 int portIndex = ipar[0];
744
745                 // "name" is not enough to tell the event and data ports apart, so check the block's port.
746                 object_properties_t kind;
747                 std::vector<ScicosID> innerPort;
748                 if (name == input || name == inimpl)
749                 {
750                     controller.getObjectProperty(*it, BLOCK, OUTPUTS, innerPort);
751                     if (!innerPort.empty())
752                     {
753                         kind = INPUTS;
754                     }
755                     else
756                     {
757                         kind = EVENT_INPUTS;
758                     }
759                 }
760                 else
761                 {
762                     controller.getObjectProperty(*it, BLOCK, INPUTS, innerPort);
763                     if (!innerPort.empty())
764                     {
765                         kind = OUTPUTS;
766                     }
767                     else
768                     {
769                         kind = EVENT_OUTPUTS;
770                     }
771                 }
772
773                 std::vector<ScicosID> superPorts;
774                 controller.getObjectProperty(adaptee, BLOCK, kind, superPorts);
775                 if (static_cast<int>(superPorts.size()) < portIndex)
776                 {
777                     return false;
778                 }
779
780                 ScicosID port = superPorts[portIndex - 1];
781
782                 // Check consistency of the implicitness between the inner and outer ports
783                 bool isImplicit;
784                 controller.getObjectProperty(port, PORT, IMPLICIT, isImplicit);
785                 if (name == input || name == output)
786                 {
787                     if (isImplicit)
788                     {
789                         return false;
790                     }
791                 }
792                 else
793                 {
794                     if (!isImplicit)
795                     {
796                         return false;
797                     }
798                 }
799
800                 controller.setObjectProperty(*it, BLOCK, PORT_REFERENCE, port);
801             }
802
803             // Regardless of the ports, use the loop to set each Block's 'parent_block' property
804             controller.setObjectProperty(*it, BLOCK, PARENT_BLOCK, adaptee);
805         }
806     }
807     return true;
808 }
809
810 struct rpar
811 {
812
813     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
814     {
815         ScicosID adaptee = adaptor.getAdaptee()->id();
816
817         std::vector<ScicosID> diagramChild;
818         controller.getObjectProperty(adaptee, BLOCK, CHILDREN, diagramChild);
819
820         if (diagramChild.empty())
821         {
822             std::vector<double> rpar;
823             controller.getObjectProperty(adaptee, BLOCK, RPAR, rpar);
824
825             double *data;
826             types::Double* o = new types::Double((int)rpar.size(), 1, &data);
827 #ifdef _MSC_VER
828             std::copy(rpar.begin(), rpar.end(), stdext::checked_array_iterator<double*>(data, rpar.size()));
829 #else
830             std::copy(rpar.begin(), rpar.end(), data);
831 #endif
832             return o;
833         }
834         else // SuperBlock, return the contained diagram
835         {
836             std::shared_ptr<model::Diagram> super = std::static_pointer_cast<model::Diagram>(controller.getObject(diagramChild[0]));
837             DiagramAdapter* localAdaptor = new DiagramAdapter(super);
838
839             DiagramAdapter* diagram = adaptor.getDiagram();
840             localAdaptor->setListObjects(diagram->getListObjects());
841             localAdaptor->setFrom(diagram->getFrom());
842             localAdaptor->setTo(diagram->getTo());
843             return localAdaptor;
844         }
845     }
846
847     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
848     {
849         ScicosID adaptee = adaptor.getAdaptee()->id();
850
851         if (v->getType() == types::InternalType::ScilabDouble)
852         {
853             types::Double* current = v->getAs<types::Double>();
854
855             std::vector<double> rpar (current->getSize());
856             for (int i = 0; i < current->getSize(); ++i)
857             {
858                 rpar[i] = current->get(i);
859             }
860
861             controller.setObjectProperty(adaptee, BLOCK, RPAR, rpar);
862             return true;
863         }
864         else if (v->getType() == types::InternalType::ScilabString)
865         {
866             // Allow Text blocks to define strings in rpar
867             return true;
868         }
869         else if (v->getType() == types::InternalType::ScilabUserType)
870         {
871             // Make sure the input describes a Diagram
872             const Adapters::adapters_index_t adapter_index = Adapters::instance().lookup_by_typename(v->getShortTypeStr());
873             if (adapter_index != Adapters::DIAGRAM_ADAPTER)
874             {
875                 return false;
876             }
877
878             // Translate 'v' to an DiagramAdapter, save it and update the Block's children list
879             DiagramAdapter* diagram = v->getAs<DiagramAdapter>();
880
881             adaptor.setDiagram(diagram);
882
883             // Save the child diagram's ID so it is deleted on 'clear'
884             std::vector<ScicosID> diagramChild (1, diagram->getAdaptee()->id());
885             controller.setObjectProperty(adaptee, BLOCK, CHILDREN, diagramChild);
886
887             // Link the Superblock ports to their inner "port blocks"
888             std::vector<ScicosID> diagramChildren;
889             controller.getObjectProperty(diagram->getAdaptee()->id(), DIAGRAM, CHILDREN, diagramChildren);
890             return setInnerBlocksRefs(adaptor, diagramChildren, controller);
891         }
892         else
893         {
894             return false;
895         }
896     }
897 };
898
899 double toDouble(const int a)
900 {
901     return static_cast<double>(a);
902 }
903
904 struct ipar
905 {
906
907     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
908     {
909         ScicosID adaptee = adaptor.getAdaptee()->id();
910
911         std::vector<int> ipar;
912         controller.getObjectProperty(adaptee, BLOCK, IPAR, ipar);
913
914         double *data;
915         types::Double* o = new types::Double((int)ipar.size(), 1, &data);
916
917 #ifdef _MSC_VER
918         std::transform(ipar.begin(), ipar.end(), stdext::checked_array_iterator<double*>(data, ipar.size()), toDouble);
919 #else
920         std::transform(ipar.begin(), ipar.end(), data, toDouble);
921 #endif
922         return o;
923     }
924
925     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
926     {
927         ScicosID adaptee = adaptor.getAdaptee()->id();
928
929         if (v->getType() == types::InternalType::ScilabList)
930         {
931             std::vector<int> ipar;
932             controller.setObjectProperty(adaptee, BLOCK, IPAR, ipar);
933             return true;
934         }
935
936         if (v->getType() != types::InternalType::ScilabDouble)
937         {
938             return false;
939         }
940
941         types::Double* current = v->getAs<types::Double>();
942         if (current->getCols() != 0 && current->getCols() != 1)
943         {
944             return false;
945         }
946
947         std::vector<int> ipar (current->getSize());
948         for (int i = 0; i < current->getSize(); ++i)
949         {
950             if (floor(current->get(i)) != current->get(i))
951             {
952                 return false;
953             }
954             ipar[i] = static_cast<int>(current->get(i));
955         }
956
957         controller.setObjectProperty(adaptee, BLOCK, IPAR, ipar);
958         return true;
959     }
960 };
961
962 struct opar
963 {
964
965     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
966     {
967         ScicosID adaptee = adaptor.getAdaptee()->id();
968
969         std::vector<int> prop_content;
970         controller.getObjectProperty(adaptee, BLOCK, OPAR, prop_content);
971
972         // corner-case, the empty content is an empty double
973         if (prop_content.empty())
974         {
975             return types::Double::Empty();
976         }
977
978         // the returned value is a list
979         std::vector<int>::iterator prop_it = prop_content.begin();
980         return decode<types::List>(prop_it);
981     }
982
983     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
984     {
985         ScicosID adaptee = adaptor.getAdaptee()->id();
986         std::vector<int> prop_content;
987
988         // corner-case the empty content is an empty-double
989         if (v->getType() == types::InternalType::ScilabDouble)
990         {
991             types::Double* current = v->getAs<types::Double>();
992             if (current->getSize() != 0)
993             {
994                 return false;
995             }
996
997             // prop_content should be empty
998             controller.setObjectProperty(adaptee, BLOCK, OPAR, prop_content);
999             return true;
1000         }
1001
1002         if (v->getType() != types::InternalType::ScilabList)
1003         {
1004             return false;
1005         }
1006
1007         types::List* list = v->getAs<types::List>();
1008         if (!encode(prop_content, list))
1009         {
1010             return false;
1011         }
1012
1013         controller.setObjectProperty(adaptee, BLOCK, OPAR, prop_content);
1014         return true;
1015     }
1016 };
1017
1018 struct blocktype
1019 {
1020
1021     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1022     {
1023         ScicosID adaptee = adaptor.getAdaptee()->id();
1024
1025         std::string type;
1026         controller.getObjectProperty(adaptee, BLOCK, SIM_BLOCKTYPE, type);
1027
1028         types::String* o = new types::String(type.c_str());
1029         return o;
1030     }
1031
1032     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1033     {
1034         ScicosID adaptee = adaptor.getAdaptee()->id();
1035
1036         if (v->getType() != types::InternalType::ScilabString)
1037         {
1038             return false;
1039         }
1040
1041         types::String* current = v->getAs<types::String>();
1042         if (current->getSize() != 1)
1043         {
1044             return false;
1045         }
1046
1047         char* c_str = wide_string_to_UTF8(current->get(0));
1048         std::string type (c_str);
1049         FREE(c_str);
1050
1051         // the value validation is performed on the model
1052         return controller.setObjectProperty(adaptee, BLOCK, SIM_BLOCKTYPE, type) != FAIL;
1053     }
1054 };
1055
1056 struct firing
1057 {
1058
1059     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1060     {
1061         return get_ports_property<ModelAdapter, FIRING>(adaptor, EVENT_OUTPUTS, controller);
1062     }
1063
1064     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1065     {
1066         return set_ports_property<ModelAdapter, FIRING>(adaptor, EVENT_OUTPUTS, controller, v);
1067     }
1068 };
1069
1070 struct dep_ut
1071 {
1072
1073     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1074     {
1075         ScicosID adaptee = adaptor.getAdaptee()->id();
1076
1077         std::vector<int> dep_ut;
1078         controller.getObjectProperty(adaptee, BLOCK, SIM_DEP_UT, dep_ut);
1079
1080         int* dep;
1081         types::Bool* o = new types::Bool(1, 2, &dep);
1082
1083         dep[0] = dep_ut[0];
1084         dep[1] = dep_ut[1];
1085
1086         return o;
1087     }
1088
1089     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1090     {
1091         ScicosID adaptee = adaptor.getAdaptee()->id();
1092
1093         if (v->getType() != types::InternalType::ScilabBool)
1094         {
1095             return false;
1096         }
1097
1098         types::Bool* current = v->getAs<types::Bool>();
1099         if (current->getRows() != 1 || current->getCols() != 2)
1100         {
1101             return false;
1102         }
1103
1104         std::vector<int> dep_ut (2);
1105         dep_ut[0] = current->get(0);
1106         dep_ut[1] = current->get(1);
1107
1108         controller.setObjectProperty(adaptee, BLOCK, SIM_DEP_UT, dep_ut);
1109         return true;
1110     }
1111 };
1112
1113 struct label
1114 {
1115
1116     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1117     {
1118         ScicosID adaptee = adaptor.getAdaptee()->id();
1119
1120         std::string label;
1121         controller.getObjectProperty(adaptee, BLOCK, LABEL, label);
1122
1123         types::String* o = new types::String(1, 1);
1124         o->set(0, label.data());
1125
1126         return o;
1127     }
1128
1129     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1130     {
1131         if (v->getType() != types::InternalType::ScilabString)
1132         {
1133             return false;
1134         }
1135
1136         types::String* current = v->getAs<types::String>();
1137         if (current->getSize() != 1)
1138         {
1139             return false;
1140         }
1141
1142         ScicosID adaptee = adaptor.getAdaptee()->id();
1143
1144         char* c_str = wide_string_to_UTF8(current->get(0));
1145         std::string label(c_str);
1146         FREE(c_str);
1147
1148         controller.setObjectProperty(adaptee, BLOCK, LABEL, label);
1149         return true;
1150     }
1151 };
1152
1153 struct nzcross
1154 {
1155
1156     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1157     {
1158         ScicosID adaptee = adaptor.getAdaptee()->id();
1159
1160         std::vector<int> nzcross;
1161         controller.getObjectProperty(adaptee, BLOCK, NZCROSS, nzcross);
1162
1163         double *data;
1164         types::Double* o = new types::Double((int)nzcross.size(), 1, &data);
1165
1166 #ifdef _MSC_VER
1167         std::transform(nzcross.begin(), nzcross.end(), stdext::checked_array_iterator<double*>(data, nzcross.size()), toDouble);
1168 #else
1169         std::transform(nzcross.begin(), nzcross.end(), data, toDouble);
1170 #endif
1171         return o;
1172     }
1173
1174     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1175     {
1176         ScicosID adaptee = adaptor.getAdaptee()->id();
1177
1178         if (v->getType() != types::InternalType::ScilabDouble)
1179         {
1180             return false;
1181         }
1182
1183         types::Double* current = v->getAs<types::Double>();
1184         if (current->getCols() != 0 && current->getCols() != 1)
1185         {
1186             return false;
1187         }
1188
1189         std::vector<int> nzcross (current->getSize());
1190         for (int i = 0; i < current->getSize(); ++i)
1191         {
1192             if (floor(current->get(i)) != current->get(i))
1193             {
1194                 return false;
1195             }
1196             nzcross[i] = static_cast<int>(current->get(i));
1197         }
1198
1199         controller.setObjectProperty(adaptee, BLOCK, NZCROSS, nzcross);
1200         return true;
1201     }
1202 };
1203
1204 struct nmode
1205 {
1206
1207     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1208     {
1209         ScicosID adaptee = adaptor.getAdaptee()->id();
1210
1211         std::vector<int> nmode;
1212         controller.getObjectProperty(adaptee, BLOCK, NMODE, nmode);
1213
1214         double *data;
1215         types::Double* o = new types::Double((int)nmode.size(), 1, &data);
1216
1217 #ifdef _MSC_VER
1218         std::transform(nmode.begin(), nmode.end(), stdext::checked_array_iterator<double*>(data, nmode.size()), toDouble);
1219 #else
1220         std::transform(nmode.begin(), nmode.end(), data, toDouble);
1221 #endif
1222         return o;
1223     }
1224
1225     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1226     {
1227         ScicosID adaptee = adaptor.getAdaptee()->id();
1228
1229         if (v->getType() != types::InternalType::ScilabDouble)
1230         {
1231             return false;
1232         }
1233
1234         types::Double* current = v->getAs<types::Double>();
1235         if (current->getCols() != 0 && current->getCols() != 1)
1236         {
1237             return false;
1238         }
1239
1240         std::vector<int> nmode (current->getSize());
1241         for (int i = 0; i < current->getSize(); ++i)
1242         {
1243             if (floor(current->get(i)) != current->get(i))
1244             {
1245                 return false;
1246             }
1247             nmode[i] = static_cast<int>(current->get(i));
1248         }
1249
1250         controller.setObjectProperty(adaptee, BLOCK, NMODE, nmode);
1251         return true;
1252     }
1253 };
1254
1255 struct equations
1256 {
1257
1258     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1259     {
1260         ScicosID adaptee = adaptor.getAdaptee()->id();
1261
1262         std::vector<std::string> equations;
1263         controller.getObjectProperty(adaptee, BLOCK, EQUATIONS, equations);
1264
1265         if (equations.size() == 0)
1266         {
1267             return new types::List();
1268         }
1269
1270         types::TList* o = new types::TList();
1271
1272         // Header, starting with "modelica"
1273         types::String* header = new types::String(1, 5);
1274         header->set(0, modelica.c_str());
1275         header->set(1, model.c_str());
1276         header->set(2, inputs.c_str());
1277         header->set(3, outputs.c_str());
1278         header->set(4, parameters.c_str());
1279         o->set(0, header);
1280
1281         // 'model'
1282         if (equations[0].c_str() == std::string())
1283         {
1284             o->set(1, types::Double::Empty());
1285         }
1286         else
1287         {
1288             types::String* modelField = new types::String(1, 1);
1289             modelField->set(0, equations[0].c_str());
1290             o->set(1, modelField);
1291         }
1292
1293         // 'inputs'
1294         std::istringstream inputsSizeStr (equations[1]);
1295         int inputsSize;
1296         inputsSizeStr >> inputsSize;
1297         if (inputsSize == 0)
1298         {
1299             types::Double* inputsField = types::Double::Empty();
1300             o->set(2, inputsField);
1301         }
1302         else
1303         {
1304             types::String* inputsField = new types::String(inputsSize, 1);
1305             for (int i = 0; i < inputsSize; ++i)
1306             {
1307                 inputsField->set(i, equations[i + 2].c_str());
1308             }
1309             o->set(2, inputsField);
1310         }
1311
1312         // 'outputs'
1313         std::istringstream outputsSizeStr (equations[2 + inputsSize]);
1314         int outputsSize;
1315         outputsSizeStr >> outputsSize;
1316         if (outputsSize == 0)
1317         {
1318             types::Double* outputsField = types::Double::Empty();
1319             o->set(3, outputsField);
1320         }
1321         else
1322         {
1323             types::String* outputsField = new types::String(outputsSize, 1);
1324             for (int i = 0; i < outputsSize; ++i)
1325             {
1326                 outputsField->set(i, equations[i + 3 + inputsSize].c_str());
1327             }
1328             o->set(3, outputsField);
1329         }
1330
1331         // 'parameters'
1332         types::List* parametersField = new types::List();
1333
1334         // 'parameters' names
1335         std::istringstream parametersSizeStr (equations[3 + inputsSize + outputsSize]);
1336         int parametersSize;
1337         parametersSizeStr >> parametersSize;
1338         if (parametersSize == 0)
1339         {
1340             types::Double* parametersNames = types::Double::Empty();
1341             parametersField->set(0, parametersNames);
1342         }
1343         else
1344         {
1345             types::String* parametersNames = new types::String(parametersSize, 1);
1346             for (int i = 0; i < parametersSize; ++i)
1347             {
1348                 parametersNames->set(i, equations[i + 4 + inputsSize + outputsSize].c_str());
1349             }
1350             parametersField->set(0, parametersNames);
1351         }
1352
1353         // 'parameters' values
1354         types::List* parametersValues = new types::List();
1355         for (int i = 0; i < parametersSize; ++i)
1356         {
1357             std::istringstream parametersValueStr (equations[i + 4 + inputsSize + outputsSize + parametersSize]);
1358             double parametersVal;
1359             parametersValueStr >> parametersVal;
1360             types::Double* parametersValue = new types::Double(parametersVal);
1361             parametersValues->set(i, parametersValue);
1362         }
1363         parametersField->set(1, parametersValues);
1364
1365         o->set(4, parametersField);
1366
1367         return o;
1368     }
1369
1370     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1371     {
1372         ScicosID adaptee = adaptor.getAdaptee()->id();
1373
1374         if (v->getType() == types::InternalType::ScilabList)
1375         {
1376             types::List* current = v->getAs<types::List>();
1377             if (current->getSize() != 0)
1378             {
1379                 return false;
1380             }
1381             return true;
1382         }
1383
1384         if (v->getType() != types::InternalType::ScilabTList)
1385         {
1386             return false;
1387         }
1388
1389         types::TList* current = v->getAs<types::TList>();
1390
1391         // Check the header
1392         types::String* header = current->getFieldNames();
1393         if (header->getSize() != 5)
1394         {
1395             return false;
1396         }
1397         if (header->get(0) != modelica)
1398         {
1399             return false;
1400         }
1401         if (header->get(1) != model)
1402         {
1403             return false;
1404         }
1405         if (header->get(2) != inputs)
1406         {
1407             return false;
1408         }
1409         if (header->get(3) != outputs)
1410         {
1411             return false;
1412         }
1413         if (header->get(4) != parameters)
1414         {
1415             return false;
1416         }
1417
1418         char* c_str; // Temporary buffer used for conversions
1419
1420         // 'model'
1421         std::vector<std::string> equations;
1422         if (current->get(1)->getType() == types::InternalType::ScilabString)
1423         {
1424             types::String* modelField = current->get(1)->getAs<types::String>();
1425             if (modelField->getSize() != 1)
1426             {
1427                 return false;
1428             }
1429
1430             c_str = wide_string_to_UTF8(modelField->get(0));
1431             std::string modelFieldStored(c_str);
1432             FREE(c_str);
1433             equations.push_back(modelFieldStored);
1434         }
1435         else if (current->get(1)->getType() == types::InternalType::ScilabDouble)
1436         {
1437             types::Double* modelFieldDouble = current->get(1)->getAs<types::Double>();
1438             if (modelFieldDouble->getSize() != 0)
1439             {
1440                 return false;
1441             }
1442
1443             // An empty matrix stores an empty string, which will later be translated back to an empty matrix
1444             equations.push_back(std::string());
1445         }
1446         else
1447         {
1448             return false;
1449         }
1450
1451         // 'inputs'
1452         size_t inputsSize;
1453         if (current->get(2)->getType() == types::InternalType::ScilabDouble)
1454         {
1455             types::Double* inputsField = current->get(2)->getAs<types::Double>();
1456             if (inputsField->getSize() != 0)
1457             {
1458                 return false;
1459             }
1460
1461             inputsSize = 0;
1462             std::ostringstream strInputs;
1463             strInputs << inputsSize;
1464             std::string inputsSizeStr = strInputs.str();
1465             equations.push_back(inputsSizeStr); // When 'inputs'=[], just insert "0" in 'equations'
1466         }
1467         else
1468         {
1469             if (current->get(2)->getType() != types::InternalType::ScilabString)
1470             {
1471                 return false;
1472             }
1473
1474             types::String* inputsField = current->get(2)->getAs<types::String>();
1475             inputsSize = inputsField->getSize();
1476             equations.resize(equations.size() + 1 + inputsSize);
1477             std::ostringstream strInputs;
1478             strInputs << inputsSize;
1479             std::string inputsSizeStr = strInputs.str();
1480             equations[1] = inputsSizeStr; // Saving the size of the 'inputs' field'
1481             for (size_t i = 0; i < inputsSize; ++i)
1482             {
1483                 c_str = wide_string_to_UTF8(inputsField->get(static_cast<int>(i)));
1484                 std::string inputsFieldStored(c_str);
1485                 FREE(c_str);
1486                 equations[i + 2] = inputsFieldStored;
1487             }
1488         }
1489
1490         // 'outputs'
1491         size_t outputsSize;
1492         if (current->get(3)->getType() == types::InternalType::ScilabDouble)
1493         {
1494             types::Double* outputsField = current->get(3)->getAs<types::Double>();
1495             if (outputsField->getSize() != 0)
1496             {
1497                 return false;
1498             }
1499
1500             outputsSize = 0;
1501             std::ostringstream strOutputs;
1502             strOutputs << outputsSize;
1503             std::string outputsSizeStr = strOutputs.str();
1504             equations.push_back(outputsSizeStr); // When 'outputs'=[], just insert "0" in 'equations'
1505         }
1506         else
1507         {
1508             if (current->get(3)->getType() != types::InternalType::ScilabString)
1509             {
1510                 return false;
1511             }
1512
1513             types::String* outputsField = current->get(3)->getAs<types::String>();
1514             outputsSize = outputsField->getSize();
1515             equations.resize(equations.size() + 1 + outputsSize);
1516             std::ostringstream strOutputs;
1517             strOutputs << outputsSize;
1518             std::string outputsSizeStr = strOutputs.str();
1519             equations[2 + inputsSize] = outputsSizeStr; // Saving the size of the 'outputs' field'
1520             for (size_t i = 0; i < outputsSize; ++i)
1521             {
1522                 c_str = wide_string_to_UTF8(outputsField->get(static_cast<int>(i)));
1523                 std::string outputsFieldStored(c_str);
1524                 FREE(c_str);
1525                 equations[i + 3 + inputsSize] = outputsFieldStored;
1526             }
1527         }
1528
1529         // 'parameters'
1530         int parametersIndex = 4;
1531         if (current->get(parametersIndex)->getType() == types::InternalType::ScilabDouble)
1532         {
1533             // For backward compatibility sake, allow the presence of an empty matrix here
1534             types::Double* emptyMatrix = current->get(parametersIndex)->getAs<types::Double>();
1535             if (emptyMatrix->getSize() != 0)
1536             {
1537                 return false;
1538             }
1539
1540             parametersIndex++;
1541         }
1542
1543         if (current->get(parametersIndex)->getType() != types::InternalType::ScilabList)
1544         {
1545             return false;
1546         }
1547
1548         types::List* list = current->get(parametersIndex)->getAs<types::List>();
1549         if (list->getSize() < 1)
1550         {
1551             return false;
1552         }
1553
1554         // 'parameters' names
1555         size_t parametersSize;
1556         if (list->get(0)->getType() == types::InternalType::ScilabDouble)
1557         {
1558             types::Double* parametersNames = list->get(0)->getAs<types::Double>();
1559             if (parametersNames->getSize() != 0)
1560             {
1561                 return false;
1562             }
1563
1564             // When 'parameters(1)'=[], just insert "0" in 'equations', set in the model and return
1565             parametersSize = 0;
1566             std::ostringstream strParameters;
1567             strParameters << parametersSize;
1568             std::string parametersSizeStr = strParameters.str();
1569             equations.push_back(parametersSizeStr);
1570
1571             controller.setObjectProperty(adaptee, BLOCK, EQUATIONS, equations);
1572             return true;
1573         }
1574         else
1575         {
1576             if (list->get(0)->getType() != types::InternalType::ScilabString)
1577             {
1578                 return false;
1579             }
1580
1581             types::String* parametersNames = list->get(0)->getAs<types::String>();
1582             parametersSize = parametersNames->getSize();
1583             equations.resize(equations.size() + 1 + parametersSize);
1584             std::ostringstream strParameters;
1585             strParameters << parametersSize;
1586             std::string parametersSizeStr = strParameters.str();
1587             equations[3 + inputsSize + outputsSize] = parametersSizeStr; // Saving the size of the 'parameters' field'
1588             for (size_t i = 0; i < parametersSize; ++i)
1589             {
1590                 c_str = wide_string_to_UTF8(parametersNames->get(static_cast<int>(i)));
1591                 std::string parametersName(c_str);
1592                 FREE(c_str);
1593                 equations[i + 4 + inputsSize + outputsSize] = parametersName;
1594             }
1595         }
1596
1597         // 'parameters' values
1598         if (list->get(1)->getType() == types::InternalType::ScilabDouble)
1599         {
1600             types::Double* parameterVal = list->get(1)->getAs<types::Double>();
1601             if (parameterVal->getSize() != static_cast<int>(parametersSize))
1602             {
1603                 return false;
1604             }
1605
1606             for (size_t i = 0; i < parametersSize; ++i)
1607             {
1608                 std::ostringstream strParameterVal;
1609                 strParameterVal << parameterVal->get(static_cast<int>(i));
1610                 std::string parameterValStr = strParameterVal.str();
1611                 equations.push_back(parameterValStr);
1612             }
1613         }
1614         else
1615         {
1616             if (list->get(1)->getType() != types::InternalType::ScilabList)
1617             {
1618                 return false;
1619             }
1620
1621             types::List* list2 = list->get(1)->getAs<types::List>();
1622             if (list2->getSize() != static_cast<int>(parametersSize))
1623             {
1624                 return false;
1625             }
1626
1627             equations.resize(equations.size() + parametersSize);
1628             for (size_t i = 0; i < parametersSize; ++i)
1629             {
1630                 if (list2->get(static_cast<int>(i))->getType() != types::InternalType::ScilabDouble)
1631                 {
1632                     return false;
1633                 }
1634
1635                 types::Double* parametersVal = list2->get(static_cast<int>(i))->getAs<types::Double>();
1636                 if (parametersVal->getSize() != 1)
1637                 {
1638                     return false;
1639                 }
1640
1641                 std::ostringstream strParametersVal;
1642                 strParametersVal << parametersVal->get(0);
1643                 std::string parametersValStr = strParametersVal.str();
1644                 equations[i + 4 + inputsSize + outputsSize + parametersSize] = parametersValStr;
1645             }
1646         }
1647
1648         controller.setObjectProperty(adaptee, BLOCK, EQUATIONS, equations);
1649         return true;
1650     }
1651 };
1652
1653 struct uid
1654 {
1655
1656     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1657     {
1658         ScicosID adaptee = adaptor.getAdaptee()->id();
1659
1660         std::string uid;
1661         controller.getObjectProperty(adaptee, BLOCK, UID, uid);
1662
1663         types::String* o = new types::String(1, 1);
1664         o->set(0, uid.data());
1665
1666         return o;
1667     }
1668
1669     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1670     {
1671         if (v->getType() != types::InternalType::ScilabString)
1672         {
1673             return false;
1674         }
1675
1676         types::String* current = v->getAs<types::String>();
1677         if (current->getSize() != 1)
1678         {
1679             return false;
1680         }
1681
1682         ScicosID adaptee = adaptor.getAdaptee()->id();
1683
1684         char* c_str = wide_string_to_UTF8(current->get(0));
1685         std::string uid(c_str);
1686         FREE(c_str);
1687
1688         controller.setObjectProperty(adaptee, BLOCK, UID, uid);
1689         return true;
1690     }
1691 };
1692
1693 } /* namespace */
1694
1695 template<> property<ModelAdapter>::props_t property<ModelAdapter>::fields = property<ModelAdapter>::props_t();
1696
1697 ModelAdapter::ModelAdapter(std::shared_ptr<model::Block> adaptee) :
1698     BaseAdapter<ModelAdapter, org_scilab_modules_scicos::model::Block>(adaptee),
1699     diagramAdapter(nullptr)
1700 {
1701     if (property<ModelAdapter>::properties_have_not_been_set())
1702     {
1703         property<ModelAdapter>::fields.reserve(23);
1704         property<ModelAdapter>::add_property(L"sim", &sim::get, &sim::set);
1705         property<ModelAdapter>::add_property(L"in", &in::get, &in::set);
1706         property<ModelAdapter>::add_property(L"in2", &in2::get, &in2::set);
1707         property<ModelAdapter>::add_property(L"intyp", &intyp::get, &intyp::set);
1708         property<ModelAdapter>::add_property(L"out", &out::get, &out::set);
1709         property<ModelAdapter>::add_property(L"out2", &out2::get, &out2::set);
1710         property<ModelAdapter>::add_property(L"outtyp", &outtyp::get, &outtyp::set);
1711         property<ModelAdapter>::add_property(L"evtin", &evtin::get, &evtin::set);
1712         property<ModelAdapter>::add_property(L"evtout", &evtout::get, &evtout::set);
1713         property<ModelAdapter>::add_property(L"state", &state::get, &state::set);
1714         property<ModelAdapter>::add_property(L"dstate", &dstate::get, &dstate::set);
1715         property<ModelAdapter>::add_property(L"odstate", &odstate::get, &odstate::set);
1716         property<ModelAdapter>::add_property(L"rpar", &rpar::get, &rpar::set);
1717         property<ModelAdapter>::add_property(L"ipar", &ipar::get, &ipar::set);
1718         property<ModelAdapter>::add_property(L"opar", &opar::get, &opar::set);
1719         property<ModelAdapter>::add_property(L"blocktype", &blocktype::get, &blocktype::set);
1720         property<ModelAdapter>::add_property(L"firing", &firing::get, &firing::set);
1721         property<ModelAdapter>::add_property(L"dep_ut", &dep_ut::get, &dep_ut::set);
1722         property<ModelAdapter>::add_property(L"label", &label::get, &label::set);
1723         property<ModelAdapter>::add_property(L"nzcross", &nzcross::get, &nzcross::set);
1724         property<ModelAdapter>::add_property(L"nmode", &nmode::get, &nmode::set);
1725         property<ModelAdapter>::add_property(L"equations", &equations::get, &equations::set);
1726         property<ModelAdapter>::add_property(L"uid", &uid::get, &uid::set);
1727     }
1728 }
1729
1730 ModelAdapter::ModelAdapter(const ModelAdapter& adapter) :
1731     BaseAdapter<ModelAdapter, org_scilab_modules_scicos::model::Block>(adapter),
1732     diagramAdapter(adapter.getDiagram())
1733 {
1734 }
1735
1736 ModelAdapter::~ModelAdapter()
1737 {
1738     if (diagramAdapter != nullptr)
1739     {
1740         diagramAdapter->DecreaseRef();
1741         diagramAdapter->killMe();
1742     }
1743 }
1744
1745 std::wstring ModelAdapter::getTypeStr()
1746 {
1747     return getSharedTypeStr();
1748 }
1749
1750 std::wstring ModelAdapter::getShortTypeStr()
1751 {
1752     return getSharedTypeStr();
1753 }
1754
1755 DiagramAdapter* ModelAdapter::getDiagram() const
1756 {
1757     if (diagramAdapter != nullptr)
1758     {
1759         diagramAdapter->IncreaseRef();
1760     }
1761     return diagramAdapter;
1762 }
1763
1764 void ModelAdapter::setDiagram(DiagramAdapter* newDiagram)
1765 {
1766     if (newDiagram != nullptr)
1767     {
1768         // The old 'diagramAdapter' needs to be freed after setting it to 'v'
1769         DiagramAdapter* temp = diagramAdapter;
1770
1771         newDiagram->IncreaseRef();
1772         diagramAdapter = newDiagram;
1773
1774         if (temp != nullptr)
1775         {
1776             temp->DecreaseRef();
1777             temp->killMe();
1778         }
1779     }
1780 }
1781
1782 } /* namespace view_scilab */
1783 } /* namespace org_scilab_modules_scicos */