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