c2733aa835a9762541ef5f6781b1c9943f883ed1
[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 types::InternalType* getPropList(const ModelAdapter& adaptor, const Controller& controller, const object_properties_t prop)
372 {
373     ScicosID adaptee = adaptor.getAdaptee()->id();
374
375     std::vector<int> prop_content;
376     controller.getObjectProperty(adaptee, BLOCK, prop, prop_content);
377
378     if (prop_content.empty())
379     {
380         return types::Double::Empty();
381     }
382
383     types::List* list = new types::List();
384
385     int index = 1; // Index to each element of the returned list
386
387     for (int i = 0; i < prop_content[0]; ++i) // 'list' must have exactly 'prop_content[0]' elements
388     {
389         int  iDims;
390         int* pDims;
391         int  iElements = 1;
392         int  numberOfIntNeeded = 0;
393         switch (prop_content[index])
394         {
395             case types::InternalType::ScilabDouble:
396             {
397                 iDims = prop_content[index + 1];
398                 pDims = new int[iDims];
399                 for (int j = 0; j < iDims; ++j)
400                 {
401                     pDims[j] = prop_content[index + 2 + j];
402                     iElements *= pDims[j];
403                 }
404                 if (pDims[0] == 0)
405                 {
406                     numberOfIntNeeded = 1; // Only mind the complex flag
407                     list->set(i, types::Double::Empty());
408                     break;
409                 }
410                 int isComplex = prop_content[index + 2 + iDims];
411
412                 types::Double* pDouble;
413
414                 if (isComplex == 0)
415                 {
416                     pDouble = new types::Double(iDims, pDims, false);
417                     numberOfIntNeeded = 2 * iElements + 1;
418                     memcpy(pDouble->get(), &prop_content[index + 2 + iDims + 1], iElements * sizeof(double));
419                 }
420                 else
421                 {
422                     pDouble = new types::Double(iDims, pDims, true);
423                     numberOfIntNeeded = 4 * iElements + 1;
424                     memcpy(pDouble->get(), &prop_content[index + 2 + iDims + 1], iElements * sizeof(double));
425                     memcpy(pDouble->getImg(), &prop_content[index + 2 + iDims + 1 + 2 * iElements], iElements * sizeof(double));
426                 }
427                 delete[] pDims;
428
429                 list->set(i, pDouble);
430                 break;
431             }
432             case types::InternalType::ScilabInt8:
433             {
434                 iDims = prop_content[index + 1];
435                 pDims = new int[iDims];
436                 for (int j = 0; j < iDims; ++j)
437                 {
438                     pDims[j] = prop_content[index + 2 + j];
439                     iElements *= pDims[j];
440                 }
441                 numberOfIntNeeded = ((iElements - 1) / 4) + 1;
442
443                 types::Int8* pInt8 = new types::Int8(iDims, pDims);
444                 delete[] pDims;
445
446                 // Use a buffer to prevent copying only parts of integers
447                 char* buffer = new char[numberOfIntNeeded * 4];
448                 memcpy(buffer, &prop_content[index + 2 + iDims], numberOfIntNeeded * sizeof(int));
449                 memcpy(pInt8->get(), buffer, iElements * sizeof(char));
450                 delete[] buffer;
451
452                 list->set(i, pInt8);
453                 break;
454             }
455             case types::InternalType::ScilabUInt8:
456             {
457                 iDims = prop_content[index + 1];
458                 pDims = new int[iDims];
459                 for (int j = 0; j < iDims; ++j)
460                 {
461                     pDims[j] = prop_content[index + 2 + j];
462                     iElements *= pDims[j];
463                 }
464                 numberOfIntNeeded = ((iElements - 1) / 4) + 1;
465
466                 types::UInt8* pUInt8 = new types::UInt8(iDims, pDims);
467                 delete[] pDims;
468
469                 // Use a buffer to prevent copying only parts of integers
470                 unsigned char* buffer = new unsigned char[numberOfIntNeeded * 4];
471                 memcpy(buffer, &prop_content[index + 2 + iDims], numberOfIntNeeded * sizeof(int));
472                 memcpy(pUInt8->get(), buffer, iElements * sizeof(char));
473                 delete[] buffer;
474
475                 list->set(i, pUInt8);
476                 break;
477             }
478             case types::InternalType::ScilabInt16:
479             {
480                 iDims = prop_content[index + 1];
481                 pDims = new int[iDims];
482                 for (int j = 0; j < iDims; ++j)
483                 {
484                     pDims[j] = prop_content[index + 2 + j];
485                     iElements *= pDims[j];
486                 }
487                 numberOfIntNeeded = ((iElements - 1) / 2) + 1;
488
489                 types::Int16* pInt16 = new types::Int16(iDims, pDims);
490                 delete[] pDims;
491
492                 // Use a buffer to prevent copying only parts of integers
493                 short int* buffer = new short int[numberOfIntNeeded * 2];
494                 memcpy(buffer, &prop_content[index + 2 + iDims], numberOfIntNeeded * sizeof(int));
495                 memcpy(pInt16->get(), buffer, iElements * sizeof(short int));
496                 delete[] buffer;
497
498                 list->set(i, pInt16);
499                 break;
500             }
501             case types::InternalType::ScilabUInt16:
502             {
503                 iDims = prop_content[index + 1];
504                 pDims = new int[iDims];
505                 for (int j = 0; j < iDims; ++j)
506                 {
507                     pDims[j] = prop_content[index + 2 + j];
508                     iElements *= pDims[j];
509                 }
510                 numberOfIntNeeded = ((iElements - 1) / 2) + 1;
511
512                 types::UInt16* pUInt16 = new types::UInt16(iDims, pDims);
513                 delete[] pDims;
514
515                 // Use a buffer to prevent copying only parts of integers
516                 unsigned short int* buffer = new unsigned short int[numberOfIntNeeded * 2];
517                 memcpy(buffer, &prop_content[index + 2 + iDims], numberOfIntNeeded * sizeof(int));
518                 memcpy(pUInt16->get(), buffer, iElements * sizeof(unsigned short int));
519                 delete[] buffer;
520
521                 list->set(i, pUInt16);
522                 break;
523             }
524             case types::InternalType::ScilabInt32:
525             {
526                 iDims = prop_content[index + 1];
527                 pDims = new int[iDims];
528                 for (int j = 0; j < iDims; ++j)
529                 {
530                     pDims[j] = prop_content[index + 2 + j];
531                     iElements *= pDims[j];
532                 }
533                 numberOfIntNeeded = iElements;
534
535                 types::Int32* pInt32 = new types::Int32(iDims, pDims);
536                 delete[] pDims;
537
538                 memcpy(pInt32->get(), &prop_content[index + 2 + iDims], iElements * sizeof(int));
539
540                 list->set(i, pInt32);
541                 break;
542             }
543             case types::InternalType::ScilabUInt32:
544             {
545                 iDims = prop_content[index + 1];
546                 pDims = new int[iDims];
547                 for (int j = 0; j < iDims; ++j)
548                 {
549                     pDims[j] = prop_content[index + 2 + j];
550                     iElements *= pDims[j];
551                 }
552                 numberOfIntNeeded = iElements;
553
554                 types::UInt32* pUInt32 = new types::UInt32(iDims, pDims);
555                 delete[] pDims;
556
557                 memcpy(pUInt32->get(), &prop_content[index + 2 + iDims], iElements * sizeof(unsigned int));
558
559                 list->set(i, pUInt32);
560                 break;
561             }
562             case types::InternalType::ScilabString:
563             {
564                 iDims = prop_content[index + 1];
565                 pDims = new int[iDims];
566                 for (int j = 0; j < iDims; ++j)
567                 {
568                     pDims[j] = prop_content[index + 2 + j];
569                     iElements *= pDims[j];
570                 }
571
572                 types::String* pString = new types::String(iDims, pDims);
573                 delete[] pDims;
574
575                 for (int j = 0; j < iElements; ++j)
576                 {
577                     int strLen = prop_content[index + 2 + iDims + numberOfIntNeeded];
578
579                     wchar_t* str = new wchar_t[strLen + 1];
580                     memcpy(str, &prop_content[index + 2 + iDims + numberOfIntNeeded + 1], strLen * sizeof(wchar_t));
581                     str[strLen] = '\0';
582                     pString->set(j, str);
583                     delete[] str;
584
585                     numberOfIntNeeded += 1 + strLen;
586                 }
587                 list->set(i, pString);
588                 break;
589             }
590             case types::InternalType::ScilabBool:
591             {
592                 iDims = prop_content[index + 1];
593                 pDims = new int[iDims];
594                 for (int j = 0; j < iDims; ++j)
595                 {
596                     pDims[j] = prop_content[index + 2 + j];
597                     iElements *= pDims[j];
598                 }
599                 numberOfIntNeeded = iElements;
600
601                 types::Bool* pBool = new types::Bool(iDims, pDims);
602                 delete[] pDims;
603
604                 memcpy(pBool->get(), &prop_content[index + 2 + iDims], iElements * sizeof(int));
605                 list->set(i, pBool);
606                 break;
607             }
608             default:
609                 return 0;
610         }
611
612         index += 2 + iDims + numberOfIntNeeded;
613     }
614
615     return list;
616 }
617
618 bool setPropList(ModelAdapter& adaptor, Controller& controller, const object_properties_t prop, types::InternalType* v)
619 {
620     ScicosID adaptee = adaptor.getAdaptee()->id();
621
622     if (v->getType() == types::InternalType::ScilabDouble)
623     {
624         types::Double* current = v->getAs<types::Double>();
625         if (current->getSize() != 0)
626         {
627             return false;
628         }
629
630         std::vector<int> prop_content;
631         controller.setObjectProperty(adaptee, BLOCK, prop, prop_content);
632         return true;
633     }
634
635     if (v->getType() != types::InternalType::ScilabList)
636     {
637         return false;
638     }
639
640     types::List* list = v->getAs<types::List>();
641
642     // 'prop_content' will be a buffer containing the elements of the list, copied into 'int' type by bits
643     std::vector<int> prop_content (1, list->getSize()); // Save the number of list elements in the first element
644     int index = 1; // Index to point at every new list element
645
646     for (int i = 0; i < list->getSize(); ++i)
647     {
648         // Save the variable type
649         prop_content.resize(prop_content.size() + 1);
650         prop_content[index] = list->get(i)->getType();
651         // The two previous lines could be simplified to 'prop_content.push_back(list->get(i)->getType());' but they explicit 'index' role
652
653         int  iDims;
654         int* pDims;
655         int  iElements = 1;
656         int  numberOfIntNeeded = 0;
657         switch (list->get(i)->getType())
658         {
659             case types::InternalType::ScilabDouble:
660             {
661                 types::Double* pDouble = list->get(i)->getAs<types::Double>();
662                 iDims = pDouble->getDims();
663                 pDims = pDouble->getDimsArray();
664                 for (int j = 0; j < iDims; ++j)
665                 {
666                     iElements *= pDims[j];
667                 }
668
669                 if (!pDouble->isComplex())
670                 {
671                     // It takes 2 int (4 bytes) to save 1 real (1 double: 8 bytes)
672                     // So reserve '2*iElements', '1 + iDims' integers for the matrix dimensions and 1 for the complexity
673                     numberOfIntNeeded = 1 + 2 * iElements;
674                     prop_content.resize(prop_content.size() + 1 + iDims + numberOfIntNeeded);
675                     prop_content[index + 2 + iDims] = 0; // Flag for real
676
677                     // Using contiguity of the memory, we save the input into 'prop_content'
678                     memcpy(&prop_content[index + 2 + iDims + 1], pDouble->getReal(), iElements * sizeof(double));
679                 }
680                 else
681                 {
682                     // It takes 4 int (4 bytes) to save 1 complex (2 double: 16 bytes)
683                     // So reserve '4*iElements', '1 + iDims' integers for the matrix dimensions and 1 for the complexity
684                     numberOfIntNeeded = 1 + 4 * iElements;
685                     prop_content.resize(prop_content.size() + 1 + iDims + numberOfIntNeeded);
686                     prop_content[index + 2 + iDims] = 1; // Flag for complex
687
688                     // Contiguously save the real and complex parts
689                     memcpy(&prop_content[index + 2 + iDims + 1], pDouble->getReal(), iElements * sizeof(double));
690                     memcpy(&prop_content[index + 2 + iDims + 1 + 2 * iElements], pDouble->getImg(), iElements * sizeof(double));
691                 }
692                 break;
693             }
694             case types::InternalType::ScilabInt8:
695             {
696                 types::Int8* pInt8 = list->get(i)->getAs<types::Int8>();
697                 iDims = pInt8->getDims();
698                 pDims = pInt8->getDimsArray();
699                 for (int j = 0; j < iDims; ++j)
700                 {
701                     iElements *= pDims[j];
702                 }
703
704                 // It takes 1 int (4 bytes) to save 4 char (1 byte)
705                 // So reserve 'iElements/4' and '1+iDims' integers for the matrix dimensions
706                 numberOfIntNeeded = ((iElements - 1) / 4) + 1;
707                 prop_content.resize(prop_content.size() + 1 + iDims + numberOfIntNeeded);
708
709                 // Using contiguity of the memory, we save the input into 'prop_content'
710                 // Use a buffer to fill the entirety of 'prop_content'
711                 char* buffer = new char[numberOfIntNeeded * 4];
712                 memcpy(buffer, pInt8->get(), iElements * sizeof(char));
713                 memcpy(&prop_content[index + 2 + iDims], buffer, numberOfIntNeeded * sizeof(int));
714                 delete[] buffer;
715                 break;
716             }
717             case types::InternalType::ScilabUInt8:
718             {
719                 types::UInt8* pUInt8 = list->get(i)->getAs<types::UInt8>();
720                 iDims = pUInt8->getDims();
721                 pDims = pUInt8->getDimsArray();
722                 for (int j = 0; j < iDims; ++j)
723                 {
724                     iElements *= pDims[j];
725                 }
726
727                 // It takes 1 int (4 bytes) to save 4 unsigned char (1 byte)
728                 // So reserve 'iElements/4' and '1+iDims' integers for the matrix dimensions
729                 numberOfIntNeeded = ((iElements - 1) / 4) + 1;
730                 prop_content.resize(prop_content.size() + 1 + iDims + numberOfIntNeeded);
731
732                 // Using contiguity of the memory, we save the input into 'prop_content'
733                 // Use a buffer to fill the entirety of 'prop_content'
734                 unsigned char* buffer = new unsigned char[numberOfIntNeeded * 4];
735                 memcpy(buffer, pUInt8->get(), iElements * sizeof(unsigned char));
736                 memcpy(&prop_content[index + 2 + iDims], buffer, numberOfIntNeeded * sizeof(int));
737                 delete[] buffer;
738                 break;
739             }
740             case types::InternalType::ScilabInt16:
741             {
742                 types::Int16* pInt16 = list->get(i)->getAs<types::Int16>();
743                 iDims = pInt16->getDims();
744                 pDims = pInt16->getDimsArray();
745                 for (int j = 0; j < iDims; ++j)
746                 {
747                     iElements *= pDims[j];
748                 }
749
750                 // It takes 1 int (4 bytes) to save 2 short int (2 bytes)
751                 // So reserve 'iElements/2' and '1+iDims' integers for the matrix dimensions
752                 numberOfIntNeeded = ((iElements - 1) / 2) + 1;
753                 prop_content.resize(prop_content.size() + 1 + iDims + numberOfIntNeeded);
754
755                 // Using contiguity of the memory, we save the input into 'prop_content'
756                 // Use a buffer to fill the entirety of 'prop_content'
757                 short int* buffer = new short int[numberOfIntNeeded * 2];
758                 memcpy(buffer, pInt16->get(), iElements * sizeof(short int));
759                 memcpy(&prop_content[index + 2 + iDims], buffer, numberOfIntNeeded * sizeof(int));
760                 delete[] buffer;
761                 break;
762             }
763             case types::InternalType::ScilabUInt16:
764             {
765                 types::UInt16* pUInt16 = list->get(i)->getAs<types::UInt16>();
766                 iDims = pUInt16->getDims();
767                 pDims = pUInt16->getDimsArray();
768                 for (int j = 0; j < iDims; ++j)
769                 {
770                     iElements *= pDims[j];
771                 }
772
773                 // It takes 1 int (4 bytes) to save 2 unsigned short int (2 bytes)
774                 // So reserve 'iElements/2' and '1+iDims' integers for the matrix dimensions
775                 numberOfIntNeeded = ((iElements - 1) / 2) + 1;
776                 prop_content.resize(prop_content.size() + 1 + iDims + numberOfIntNeeded);
777
778                 // Using contiguity of the memory, we save the input into prop_content
779                 // Use a buffer to fill the entirety of 'prop_content'
780                 unsigned short int* buffer = new unsigned short int[numberOfIntNeeded * 2];
781                 memcpy(buffer, pUInt16->get(), iElements * sizeof(unsigned short int));
782                 memcpy(&prop_content[index + 2 + iDims], buffer, numberOfIntNeeded * sizeof(int));
783                 delete[] buffer;
784                 break;
785             }
786             case types::InternalType::ScilabInt32:
787             {
788                 types::Int32* pInt32 = list->get(i)->getAs<types::Int32>();
789                 iDims = pInt32->getDims();
790                 pDims = pInt32->getDimsArray();
791                 for (int j = 0; j < iDims; ++j)
792                 {
793                     iElements *= pDims[j];
794                 }
795
796                 // It takes 1 int (4 bytes) to save 1 int (4 bytes)
797                 // So reserve 'iElements' and '1+iDims' integers for the matrix dimensions
798                 numberOfIntNeeded = iElements;
799                 prop_content.resize(prop_content.size() + 1 + iDims + numberOfIntNeeded);
800
801                 // Using contiguity of the memory, we save the input into 'prop_content'
802                 memcpy(&prop_content[index + 2 + iDims], pInt32->get(), iElements * sizeof(int));
803                 break;
804             }
805             case types::InternalType::ScilabUInt32:
806             {
807                 types::UInt32* pUInt32 = list->get(i)->getAs<types::UInt32>();
808                 iDims = pUInt32->getDims();
809                 pDims = pUInt32->getDimsArray();
810                 for (int j = 0; j < iDims; ++j)
811                 {
812                     iElements *= pDims[j];
813                 }
814
815                 // It takes 1 int (4 bytes) to save 1 unsigned int (4 bytes)
816                 // So reserve 'iElements' and '1+iDims' integers for the matrix dimensions
817                 numberOfIntNeeded = iElements;
818                 prop_content.resize(prop_content.size() + 1 + iDims + numberOfIntNeeded);
819
820                 // Using contiguity of the memory, we save the input into 'prop_content'
821                 memcpy(&prop_content[index + 2 + iDims], pUInt32->get(), iElements * sizeof(unsigned int));
822                 break;
823             }
824             case types::InternalType::ScilabInt64:
825             case types::InternalType::ScilabUInt64:
826                 // int64 and uint64 are not treated yet
827                 return false;
828             case types::InternalType::ScilabString:
829             {
830                 types::String* pString = list->get(i)->getAs<types::String>();
831                 iDims = pString->getDims();
832                 pDims = pString->getDimsArray();
833                 for (int j = 0; j < iDims; ++j)
834                 {
835                     iElements *= pDims[j];
836                 }
837
838                 // For the moment, we don't know how many characters each string is long, so only reserve the matrix size
839                 prop_content.resize(prop_content.size() + 1 + iDims);
840
841                 for (int j = 0; j < iElements; ++j)
842                 {
843                     // Extract the input string length and reserve as many characters in 'prop_content'
844                     int strLen = static_cast<int>(wcslen(pString->get(j)));
845                     prop_content.resize(prop_content.size() + 1 + strLen);
846                     prop_content[index + 2 + iDims + numberOfIntNeeded] = strLen;
847
848                     memcpy(&prop_content[index + 2 + iDims + numberOfIntNeeded + 1], pString->get(j), strLen * sizeof(wchar_t));
849                     numberOfIntNeeded += 1 + strLen;
850                 }
851                 break;
852             }
853             case types::InternalType::ScilabBool:
854             {
855                 types::Bool* pBool = list->get(i)->getAs<types::Bool>();
856                 iDims = pBool->getDims();
857                 pDims = pBool->getDimsArray();
858                 for (int j = 0; j < iDims; ++j)
859                 {
860                     iElements *= pDims[j];
861                 }
862
863                 // It takes 1 int (4 bytes) to save 1 bool (1 int: 4 bytes)
864                 // So reserve 'iElements' and '1+iDims' integers for the matrix dimensions
865                 numberOfIntNeeded = iElements;
866                 prop_content.resize(prop_content.size() + 1 + iDims + numberOfIntNeeded);
867
868                 // Using contiguity of the memory, we save the input into 'prop_content'
869                 memcpy(&prop_content[index + 2 + iDims], pBool->get(), iElements * sizeof(int));
870                 break;
871             }
872             default:
873                 return false;
874         }
875         // Save the matrix (/hypermatrix) dimensions in 'prop_content' and increment index to match the next list element
876         prop_content[index + 1] = iDims;
877         for (int j = 0; j < iDims; ++j)
878         {
879             prop_content[index + 2 + j] = pDims[j];
880         }
881         index += 2 + iDims + numberOfIntNeeded;
882     }
883
884     controller.setObjectProperty(adaptee, BLOCK, prop, prop_content);
885     return true;
886 }
887
888 struct odstate
889 {
890
891     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
892     {
893         return getPropList(adaptor, controller, ODSTATE);
894     }
895
896     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
897     {
898         return setPropList(adaptor, controller, ODSTATE, v);
899     }
900 };
901
902 /*
903  * When setting a diagram in 'rpar', the Superblock's ports must be consistent with the "port blocks" inside it.
904  * By "port blocks", we mean IN_f, OUT_f, CLKIN_f, CLKOUT_f, CLKINV_f, CLKOUTV_f, INIMPL_f and OUTIMPL_f.
905  */
906 bool setInnerBlocksRefs(ModelAdapter& adaptor, const std::vector<ScicosID>& children, Controller& controller)
907 {
908     ScicosID adaptee = adaptor.getAdaptee()->id();
909
910     for (std::vector<ScicosID>::const_iterator it = children.begin(); it != children.end(); ++it)
911     {
912         if (controller.getObject(*it)->kind() == BLOCK) // Rule out Annotations and Links
913         {
914             std::string name;
915             controller.getObjectProperty(*it, BLOCK, SIM_FUNCTION_NAME, name);
916
917             // Find the "port blocks"
918             if (name == input || name == inimpl || name == output || name == outimpl)
919             {
920                 std::vector<int> ipar;
921                 controller.getObjectProperty(*it, BLOCK, IPAR, ipar);
922                 if (ipar.size() != 1)
923                 {
924                     return false;
925                 }
926                 int portIndex = ipar[0];
927
928                 // "name" is not enough to tell the event and data ports apart, so check the block's port.
929                 object_properties_t kind;
930                 std::vector<ScicosID> innerPort;
931                 if (name == input || name == inimpl)
932                 {
933                     controller.getObjectProperty(*it, BLOCK, OUTPUTS, innerPort);
934                     if (!innerPort.empty())
935                     {
936                         kind = INPUTS;
937                     }
938                     else
939                     {
940                         kind = EVENT_INPUTS;
941                     }
942                 }
943                 else
944                 {
945                     controller.getObjectProperty(*it, BLOCK, INPUTS, innerPort);
946                     if (!innerPort.empty())
947                     {
948                         kind = OUTPUTS;
949                     }
950                     else
951                     {
952                         kind = EVENT_OUTPUTS;
953                     }
954                 }
955
956                 std::vector<ScicosID> superPorts;
957                 controller.getObjectProperty(adaptee, BLOCK, kind, superPorts);
958                 if (static_cast<int>(superPorts.size()) < portIndex)
959                 {
960                     return false;
961                 }
962
963                 ScicosID port = superPorts[portIndex - 1];
964
965                 // Check consistency of the implicitness between the inner and outer ports
966                 bool isImplicit;
967                 controller.getObjectProperty(port, PORT, IMPLICIT, isImplicit);
968                 if (name == input || name == output)
969                 {
970                     if (isImplicit)
971                     {
972                         return false;
973                     }
974                 }
975                 else
976                 {
977                     if (!isImplicit)
978                     {
979                         return false;
980                     }
981                 }
982
983                 controller.setObjectProperty(*it, BLOCK, PORT_REFERENCE, port);
984             }
985
986             // Regardless of the ports, use the loop to set each Block's 'parent_block' property
987             controller.setObjectProperty(*it, BLOCK, PARENT_BLOCK, adaptee);
988         }
989     }
990     return true;
991 }
992
993 struct rpar
994 {
995
996     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
997     {
998         ScicosID adaptee = adaptor.getAdaptee()->id();
999
1000         std::vector<ScicosID> diagramChild;
1001         controller.getObjectProperty(adaptee, BLOCK, CHILDREN, diagramChild);
1002
1003         if (diagramChild.empty())
1004         {
1005             std::vector<double> rpar;
1006             controller.getObjectProperty(adaptee, BLOCK, RPAR, rpar);
1007
1008             double *data;
1009             types::Double* o = new types::Double((int)rpar.size(), 1, &data);
1010 #ifdef _MSC_VER
1011             std::copy(rpar.begin(), rpar.end(), stdext::checked_array_iterator<double*>(data, rpar.size()));
1012 #else
1013             std::copy(rpar.begin(), rpar.end(), data);
1014 #endif
1015             return o;
1016         }
1017         else // SuperBlock, return the contained diagram
1018         {
1019             std::shared_ptr<model::Diagram> super = std::static_pointer_cast<model::Diagram>(controller.getObject(diagramChild[0]));
1020             DiagramAdapter* localAdaptor = new DiagramAdapter(super);
1021
1022             DiagramAdapter* diagram = adaptor.getDiagram();
1023             localAdaptor->setListObjects(diagram->getListObjects());
1024             localAdaptor->setFrom(diagram->getFrom());
1025             localAdaptor->setTo(diagram->getTo());
1026             return localAdaptor;
1027         }
1028     }
1029
1030     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1031     {
1032         ScicosID adaptee = adaptor.getAdaptee()->id();
1033
1034         if (v->getType() == types::InternalType::ScilabDouble)
1035         {
1036             types::Double* current = v->getAs<types::Double>();
1037
1038             std::vector<double> rpar (current->getSize());
1039             for (int i = 0; i < current->getSize(); ++i)
1040             {
1041                 rpar[i] = current->get(i);
1042             }
1043
1044             controller.setObjectProperty(adaptee, BLOCK, RPAR, rpar);
1045             return true;
1046         }
1047         else if (v->getType() == types::InternalType::ScilabString)
1048         {
1049             // Allow Text blocks to define strings in rpar
1050             return true;
1051         }
1052         else if (v->getType() == types::InternalType::ScilabUserType)
1053         {
1054             // Make sure the input describes a Diagram
1055             const Adapters::adapters_index_t adapter_index = Adapters::instance().lookup_by_typename(v->getShortTypeStr());
1056             if (adapter_index != Adapters::DIAGRAM_ADAPTER)
1057             {
1058                 return false;
1059             }
1060
1061             // Translate 'v' to an DiagramAdapter, save it and update the Block's children list
1062             DiagramAdapter* diagram = v->getAs<DiagramAdapter>();
1063
1064             adaptor.setDiagram(diagram);
1065
1066             // Save the child diagram's ID so it is deleted on 'clear'
1067             std::vector<ScicosID> diagramChild (1, diagram->getAdaptee()->id());
1068             controller.setObjectProperty(adaptee, BLOCK, CHILDREN, diagramChild);
1069
1070             // Link the Superblock ports to their inner "port blocks"
1071             std::vector<ScicosID> diagramChildren;
1072             controller.getObjectProperty(diagram->getAdaptee()->id(), DIAGRAM, CHILDREN, diagramChildren);
1073             return setInnerBlocksRefs(adaptor, diagramChildren, controller);
1074         }
1075         else
1076         {
1077             return false;
1078         }
1079     }
1080 };
1081
1082 double toDouble(const int a)
1083 {
1084     return static_cast<double>(a);
1085 }
1086
1087 struct ipar
1088 {
1089
1090     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1091     {
1092         ScicosID adaptee = adaptor.getAdaptee()->id();
1093
1094         std::vector<int> ipar;
1095         controller.getObjectProperty(adaptee, BLOCK, IPAR, ipar);
1096
1097         double *data;
1098         types::Double* o = new types::Double((int)ipar.size(), 1, &data);
1099
1100 #ifdef _MSC_VER
1101         std::transform(ipar.begin(), ipar.end(), stdext::checked_array_iterator<double*>(data, ipar.size()), toDouble);
1102 #else
1103         std::transform(ipar.begin(), ipar.end(), data, toDouble);
1104 #endif
1105         return o;
1106     }
1107
1108     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1109     {
1110         ScicosID adaptee = adaptor.getAdaptee()->id();
1111
1112         if (v->getType() == types::InternalType::ScilabList)
1113         {
1114             std::vector<int> ipar;
1115             controller.setObjectProperty(adaptee, BLOCK, IPAR, ipar);
1116             return true;
1117         }
1118
1119         if (v->getType() != types::InternalType::ScilabDouble)
1120         {
1121             return false;
1122         }
1123
1124         types::Double* current = v->getAs<types::Double>();
1125         if (current->getCols() != 0 && current->getCols() != 1)
1126         {
1127             return false;
1128         }
1129
1130         std::vector<int> ipar (current->getSize());
1131         for (int i = 0; i < current->getSize(); ++i)
1132         {
1133             if (floor(current->get(i)) != current->get(i))
1134             {
1135                 return false;
1136             }
1137             ipar[i] = static_cast<int>(current->get(i));
1138         }
1139
1140         controller.setObjectProperty(adaptee, BLOCK, IPAR, ipar);
1141         return true;
1142     }
1143 };
1144
1145 struct opar
1146 {
1147
1148     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1149     {
1150         return getPropList(adaptor, controller, OPAR);
1151     }
1152
1153     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1154     {
1155         return setPropList(adaptor, controller, OPAR, v);
1156     }
1157 };
1158
1159 struct blocktype
1160 {
1161
1162     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1163     {
1164         ScicosID adaptee = adaptor.getAdaptee()->id();
1165
1166         std::string type;
1167         controller.getObjectProperty(adaptee, BLOCK, SIM_BLOCKTYPE, type);
1168
1169         types::String* o = new types::String(type.c_str());
1170         return o;
1171     }
1172
1173     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1174     {
1175         ScicosID adaptee = adaptor.getAdaptee()->id();
1176
1177         if (v->getType() != types::InternalType::ScilabString)
1178         {
1179             return false;
1180         }
1181
1182         types::String* current = v->getAs<types::String>();
1183         if (current->getSize() != 1)
1184         {
1185             return false;
1186         }
1187
1188         char* c_str = wide_string_to_UTF8(current->get(0));
1189         std::string type (c_str);
1190         FREE(c_str);
1191
1192         // the value validation is performed on the model
1193         return controller.setObjectProperty(adaptee, BLOCK, SIM_BLOCKTYPE, type) != FAIL;
1194     }
1195 };
1196
1197 struct firing
1198 {
1199
1200     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1201     {
1202         return get_ports_property<ModelAdapter, FIRING>(adaptor, EVENT_OUTPUTS, controller);
1203     }
1204
1205     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1206     {
1207         return set_ports_property<ModelAdapter, FIRING>(adaptor, EVENT_OUTPUTS, controller, v);
1208     }
1209 };
1210
1211 struct dep_ut
1212 {
1213
1214     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1215     {
1216         ScicosID adaptee = adaptor.getAdaptee()->id();
1217
1218         std::vector<int> dep_ut;
1219         controller.getObjectProperty(adaptee, BLOCK, SIM_DEP_UT, dep_ut);
1220
1221         int* dep;
1222         types::Bool* o = new types::Bool(1, 2, &dep);
1223
1224         dep[0] = dep_ut[0];
1225         dep[1] = dep_ut[1];
1226
1227         return o;
1228     }
1229
1230     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1231     {
1232         ScicosID adaptee = adaptor.getAdaptee()->id();
1233
1234         if (v->getType() != types::InternalType::ScilabBool)
1235         {
1236             return false;
1237         }
1238
1239         types::Bool* current = v->getAs<types::Bool>();
1240         if (current->getRows() != 1 || current->getCols() != 2)
1241         {
1242             return false;
1243         }
1244
1245         std::vector<int> dep_ut (2);
1246         dep_ut[0] = current->get(0);
1247         dep_ut[1] = current->get(1);
1248
1249         controller.setObjectProperty(adaptee, BLOCK, SIM_DEP_UT, dep_ut);
1250         return true;
1251     }
1252 };
1253
1254 struct label
1255 {
1256
1257     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1258     {
1259         ScicosID adaptee = adaptor.getAdaptee()->id();
1260
1261         std::string label;
1262         controller.getObjectProperty(adaptee, BLOCK, LABEL, label);
1263
1264         types::String* o = new types::String(1, 1);
1265         o->set(0, label.data());
1266
1267         return o;
1268     }
1269
1270     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1271     {
1272         if (v->getType() != types::InternalType::ScilabString)
1273         {
1274             return false;
1275         }
1276
1277         types::String* current = v->getAs<types::String>();
1278         if (current->getSize() != 1)
1279         {
1280             return false;
1281         }
1282
1283         ScicosID adaptee = adaptor.getAdaptee()->id();
1284
1285         char* c_str = wide_string_to_UTF8(current->get(0));
1286         std::string label(c_str);
1287         FREE(c_str);
1288
1289         controller.setObjectProperty(adaptee, BLOCK, LABEL, label);
1290         return true;
1291     }
1292 };
1293
1294 struct nzcross
1295 {
1296
1297     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1298     {
1299         ScicosID adaptee = adaptor.getAdaptee()->id();
1300
1301         std::vector<int> nzcross;
1302         controller.getObjectProperty(adaptee, BLOCK, NZCROSS, nzcross);
1303
1304         double *data;
1305         types::Double* o = new types::Double((int)nzcross.size(), 1, &data);
1306
1307 #ifdef _MSC_VER
1308         std::transform(nzcross.begin(), nzcross.end(), stdext::checked_array_iterator<double*>(data, nzcross.size()), toDouble);
1309 #else
1310         std::transform(nzcross.begin(), nzcross.end(), data, toDouble);
1311 #endif
1312         return o;
1313     }
1314
1315     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1316     {
1317         ScicosID adaptee = adaptor.getAdaptee()->id();
1318
1319         if (v->getType() != types::InternalType::ScilabDouble)
1320         {
1321             return false;
1322         }
1323
1324         types::Double* current = v->getAs<types::Double>();
1325         if (current->getCols() != 0 && current->getCols() != 1)
1326         {
1327             return false;
1328         }
1329
1330         std::vector<int> nzcross (current->getSize());
1331         for (int i = 0; i < current->getSize(); ++i)
1332         {
1333             if (floor(current->get(i)) != current->get(i))
1334             {
1335                 return false;
1336             }
1337             nzcross[i] = static_cast<int>(current->get(i));
1338         }
1339
1340         controller.setObjectProperty(adaptee, BLOCK, NZCROSS, nzcross);
1341         return true;
1342     }
1343 };
1344
1345 struct nmode
1346 {
1347
1348     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1349     {
1350         ScicosID adaptee = adaptor.getAdaptee()->id();
1351
1352         std::vector<int> nmode;
1353         controller.getObjectProperty(adaptee, BLOCK, NMODE, nmode);
1354
1355         double *data;
1356         types::Double* o = new types::Double((int)nmode.size(), 1, &data);
1357
1358 #ifdef _MSC_VER
1359         std::transform(nmode.begin(), nmode.end(), stdext::checked_array_iterator<double*>(data, nmode.size()), toDouble);
1360 #else
1361         std::transform(nmode.begin(), nmode.end(), data, toDouble);
1362 #endif
1363         return o;
1364     }
1365
1366     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1367     {
1368         ScicosID adaptee = adaptor.getAdaptee()->id();
1369
1370         if (v->getType() != types::InternalType::ScilabDouble)
1371         {
1372             return false;
1373         }
1374
1375         types::Double* current = v->getAs<types::Double>();
1376         if (current->getCols() != 0 && current->getCols() != 1)
1377         {
1378             return false;
1379         }
1380
1381         std::vector<int> nmode (current->getSize());
1382         for (int i = 0; i < current->getSize(); ++i)
1383         {
1384             if (floor(current->get(i)) != current->get(i))
1385             {
1386                 return false;
1387             }
1388             nmode[i] = static_cast<int>(current->get(i));
1389         }
1390
1391         controller.setObjectProperty(adaptee, BLOCK, NMODE, nmode);
1392         return true;
1393     }
1394 };
1395
1396 struct equations
1397 {
1398
1399     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1400     {
1401         ScicosID adaptee = adaptor.getAdaptee()->id();
1402
1403         std::vector<std::string> equations;
1404         controller.getObjectProperty(adaptee, BLOCK, EQUATIONS, equations);
1405
1406         if (equations.size() == 0)
1407         {
1408             return new types::List();
1409         }
1410
1411         types::TList* o = new types::TList();
1412
1413         // Header, starting with "modelica"
1414         types::String* header = new types::String(1, 5);
1415         header->set(0, modelica.c_str());
1416         header->set(1, model.c_str());
1417         header->set(2, inputs.c_str());
1418         header->set(3, outputs.c_str());
1419         header->set(4, parameters.c_str());
1420         o->set(0, header);
1421
1422         // 'model'
1423         if (equations[0].c_str() == std::string())
1424         {
1425             o->set(1, types::Double::Empty());
1426         }
1427         else
1428         {
1429             types::String* modelField = new types::String(1, 1);
1430             modelField->set(0, equations[0].c_str());
1431             o->set(1, modelField);
1432         }
1433
1434         // 'inputs'
1435         std::istringstream inputsSizeStr (equations[1]);
1436         int inputsSize;
1437         inputsSizeStr >> inputsSize;
1438         if (inputsSize == 0)
1439         {
1440             types::Double* inputsField = types::Double::Empty();
1441             o->set(2, inputsField);
1442         }
1443         else
1444         {
1445             types::String* inputsField = new types::String(inputsSize, 1);
1446             for (int i = 0; i < inputsSize; ++i)
1447             {
1448                 inputsField->set(i, equations[i + 2].c_str());
1449             }
1450             o->set(2, inputsField);
1451         }
1452
1453         // 'outputs'
1454         std::istringstream outputsSizeStr (equations[2 + inputsSize]);
1455         int outputsSize;
1456         outputsSizeStr >> outputsSize;
1457         if (outputsSize == 0)
1458         {
1459             types::Double* outputsField = types::Double::Empty();
1460             o->set(3, outputsField);
1461         }
1462         else
1463         {
1464             types::String* outputsField = new types::String(outputsSize, 1);
1465             for (int i = 0; i < outputsSize; ++i)
1466             {
1467                 outputsField->set(i, equations[i + 3 + inputsSize].c_str());
1468             }
1469             o->set(3, outputsField);
1470         }
1471
1472         // 'parameters'
1473         types::List* parametersField = new types::List();
1474
1475         // 'parameters' names
1476         std::istringstream parametersSizeStr (equations[3 + inputsSize + outputsSize]);
1477         int parametersSize;
1478         parametersSizeStr >> parametersSize;
1479         if (parametersSize == 0)
1480         {
1481             types::Double* parametersNames = types::Double::Empty();
1482             parametersField->set(0, parametersNames);
1483         }
1484         else
1485         {
1486             types::String* parametersNames = new types::String(parametersSize, 1);
1487             for (int i = 0; i < parametersSize; ++i)
1488             {
1489                 parametersNames->set(i, equations[i + 4 + inputsSize + outputsSize].c_str());
1490             }
1491             parametersField->set(0, parametersNames);
1492         }
1493
1494         // 'parameters' values
1495         types::List* parametersValues = new types::List();
1496         for (int i = 0; i < parametersSize; ++i)
1497         {
1498             std::istringstream parametersValueStr (equations[i + 4 + inputsSize + outputsSize + parametersSize]);
1499             double parametersVal;
1500             parametersValueStr >> parametersVal;
1501             types::Double* parametersValue = new types::Double(parametersVal);
1502             parametersValues->set(i, parametersValue);
1503         }
1504         parametersField->set(1, parametersValues);
1505
1506         o->set(4, parametersField);
1507
1508         return o;
1509     }
1510
1511     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1512     {
1513         ScicosID adaptee = adaptor.getAdaptee()->id();
1514
1515         if (v->getType() == types::InternalType::ScilabList)
1516         {
1517             types::List* current = v->getAs<types::List>();
1518             if (current->getSize() != 0)
1519             {
1520                 return false;
1521             }
1522             return true;
1523         }
1524
1525         if (v->getType() != types::InternalType::ScilabTList)
1526         {
1527             return false;
1528         }
1529
1530         types::TList* current = v->getAs<types::TList>();
1531
1532         // Check the header
1533         types::String* header = current->getFieldNames();
1534         if (header->getSize() != 5)
1535         {
1536             return false;
1537         }
1538         if (header->get(0) != modelica)
1539         {
1540             return false;
1541         }
1542         if (header->get(1) != model)
1543         {
1544             return false;
1545         }
1546         if (header->get(2) != inputs)
1547         {
1548             return false;
1549         }
1550         if (header->get(3) != outputs)
1551         {
1552             return false;
1553         }
1554         if (header->get(4) != parameters)
1555         {
1556             return false;
1557         }
1558
1559         char* c_str; // Temporary buffer used for conversions
1560
1561         // 'model'
1562         std::vector<std::string> equations;
1563         if (current->get(1)->getType() == types::InternalType::ScilabString)
1564         {
1565             types::String* modelField = current->get(1)->getAs<types::String>();
1566             if (modelField->getSize() != 1)
1567             {
1568                 return false;
1569             }
1570
1571             c_str = wide_string_to_UTF8(modelField->get(0));
1572             std::string modelFieldStored(c_str);
1573             FREE(c_str);
1574             equations.push_back(modelFieldStored);
1575         }
1576         else if (current->get(1)->getType() == types::InternalType::ScilabDouble)
1577         {
1578             types::Double* modelFieldDouble = current->get(1)->getAs<types::Double>();
1579             if (modelFieldDouble->getSize() != 0)
1580             {
1581                 return false;
1582             }
1583
1584             // An empty matrix stores an empty string, which will later be translated back to an empty matrix
1585             equations.push_back(std::string());
1586         }
1587         else
1588         {
1589             return false;
1590         }
1591
1592         // 'inputs'
1593         size_t inputsSize;
1594         if (current->get(2)->getType() == types::InternalType::ScilabDouble)
1595         {
1596             types::Double* inputsField = current->get(2)->getAs<types::Double>();
1597             if (inputsField->getSize() != 0)
1598             {
1599                 return false;
1600             }
1601
1602             inputsSize = 0;
1603             std::ostringstream strInputs;
1604             strInputs << inputsSize;
1605             std::string inputsSizeStr = strInputs.str();
1606             equations.push_back(inputsSizeStr); // When 'inputs'=[], just insert "0" in 'equations'
1607         }
1608         else
1609         {
1610             if (current->get(2)->getType() != types::InternalType::ScilabString)
1611             {
1612                 return false;
1613             }
1614
1615             types::String* inputsField = current->get(2)->getAs<types::String>();
1616             inputsSize = inputsField->getSize();
1617             equations.resize(equations.size() + 1 + inputsSize);
1618             std::ostringstream strInputs;
1619             strInputs << inputsSize;
1620             std::string inputsSizeStr = strInputs.str();
1621             equations[1] = inputsSizeStr; // Saving the size of the 'inputs' field'
1622             for (size_t i = 0; i < inputsSize; ++i)
1623             {
1624                 c_str = wide_string_to_UTF8(inputsField->get(static_cast<int>(i)));
1625                 std::string inputsFieldStored(c_str);
1626                 FREE(c_str);
1627                 equations[i + 2] = inputsFieldStored;
1628             }
1629         }
1630
1631         // 'outputs'
1632         size_t outputsSize;
1633         if (current->get(3)->getType() == types::InternalType::ScilabDouble)
1634         {
1635             types::Double* outputsField = current->get(3)->getAs<types::Double>();
1636             if (outputsField->getSize() != 0)
1637             {
1638                 return false;
1639             }
1640
1641             outputsSize = 0;
1642             std::ostringstream strOutputs;
1643             strOutputs << outputsSize;
1644             std::string outputsSizeStr = strOutputs.str();
1645             equations.push_back(outputsSizeStr); // When 'outputs'=[], just insert "0" in 'equations'
1646         }
1647         else
1648         {
1649             if (current->get(3)->getType() != types::InternalType::ScilabString)
1650             {
1651                 return false;
1652             }
1653
1654             types::String* outputsField = current->get(3)->getAs<types::String>();
1655             outputsSize = outputsField->getSize();
1656             equations.resize(equations.size() + 1 + outputsSize);
1657             std::ostringstream strOutputs;
1658             strOutputs << outputsSize;
1659             std::string outputsSizeStr = strOutputs.str();
1660             equations[2 + inputsSize] = outputsSizeStr; // Saving the size of the 'outputs' field'
1661             for (size_t i = 0; i < outputsSize; ++i)
1662             {
1663                 c_str = wide_string_to_UTF8(outputsField->get(static_cast<int>(i)));
1664                 std::string outputsFieldStored(c_str);
1665                 FREE(c_str);
1666                 equations[i + 3 + inputsSize] = outputsFieldStored;
1667             }
1668         }
1669
1670         // 'parameters'
1671         int parametersIndex = 4;
1672         if (current->get(parametersIndex)->getType() == types::InternalType::ScilabDouble)
1673         {
1674             // For backward compatibility sake, allow the presence of an empty matrix here
1675             types::Double* emptyMatrix = current->get(parametersIndex)->getAs<types::Double>();
1676             if (emptyMatrix->getSize() != 0)
1677             {
1678                 return false;
1679             }
1680
1681             parametersIndex++;
1682         }
1683
1684         if (current->get(parametersIndex)->getType() != types::InternalType::ScilabList)
1685         {
1686             return false;
1687         }
1688
1689         types::List* list = current->get(parametersIndex)->getAs<types::List>();
1690         if (list->getSize() < 1)
1691         {
1692             return false;
1693         }
1694
1695         // 'parameters' names
1696         size_t parametersSize;
1697         if (list->get(0)->getType() == types::InternalType::ScilabDouble)
1698         {
1699             types::Double* parametersNames = list->get(0)->getAs<types::Double>();
1700             if (parametersNames->getSize() != 0)
1701             {
1702                 return false;
1703             }
1704
1705             // When 'parameters(1)'=[], just insert "0" in 'equations', set in the model and return
1706             parametersSize = 0;
1707             std::ostringstream strParameters;
1708             strParameters << parametersSize;
1709             std::string parametersSizeStr = strParameters.str();
1710             equations.push_back(parametersSizeStr);
1711
1712             controller.setObjectProperty(adaptee, BLOCK, EQUATIONS, equations);
1713             return true;
1714         }
1715         else
1716         {
1717             if (list->get(0)->getType() != types::InternalType::ScilabString)
1718             {
1719                 return false;
1720             }
1721
1722             types::String* parametersNames = list->get(0)->getAs<types::String>();
1723             parametersSize = parametersNames->getSize();
1724             equations.resize(equations.size() + 1 + parametersSize);
1725             std::ostringstream strParameters;
1726             strParameters << parametersSize;
1727             std::string parametersSizeStr = strParameters.str();
1728             equations[3 + inputsSize + outputsSize] = parametersSizeStr; // Saving the size of the 'parameters' field'
1729             for (size_t i = 0; i < parametersSize; ++i)
1730             {
1731                 c_str = wide_string_to_UTF8(parametersNames->get(static_cast<int>(i)));
1732                 std::string parametersName(c_str);
1733                 FREE(c_str);
1734                 equations[i + 4 + inputsSize + outputsSize] = parametersName;
1735             }
1736         }
1737
1738         // 'parameters' values
1739         if (list->get(1)->getType() == types::InternalType::ScilabDouble)
1740         {
1741             types::Double* parameterVal = list->get(1)->getAs<types::Double>();
1742             if (parameterVal->getSize() != static_cast<int>(parametersSize))
1743             {
1744                 return false;
1745             }
1746
1747             for (size_t i = 0; i < parametersSize; ++i)
1748             {
1749                 std::ostringstream strParameterVal;
1750                 strParameterVal << parameterVal->get(static_cast<int>(i));
1751                 std::string parameterValStr = strParameterVal.str();
1752                 equations.push_back(parameterValStr);
1753             }
1754         }
1755         else
1756         {
1757             if (list->get(1)->getType() != types::InternalType::ScilabList)
1758             {
1759                 return false;
1760             }
1761
1762             types::List* list2 = list->get(1)->getAs<types::List>();
1763             if (list2->getSize() != static_cast<int>(parametersSize))
1764             {
1765                 return false;
1766             }
1767
1768             equations.resize(equations.size() + parametersSize);
1769             for (size_t i = 0; i < parametersSize; ++i)
1770             {
1771                 if (list2->get(static_cast<int>(i))->getType() != types::InternalType::ScilabDouble)
1772                 {
1773                     return false;
1774                 }
1775
1776                 types::Double* parametersVal = list2->get(static_cast<int>(i))->getAs<types::Double>();
1777                 if (parametersVal->getSize() != 1)
1778                 {
1779                     return false;
1780                 }
1781
1782                 std::ostringstream strParametersVal;
1783                 strParametersVal << parametersVal->get(0);
1784                 std::string parametersValStr = strParametersVal.str();
1785                 equations[i + 4 + inputsSize + outputsSize + parametersSize] = parametersValStr;
1786             }
1787         }
1788
1789         controller.setObjectProperty(adaptee, BLOCK, EQUATIONS, equations);
1790         return true;
1791     }
1792 };
1793
1794 struct uid
1795 {
1796
1797     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1798     {
1799         ScicosID adaptee = adaptor.getAdaptee()->id();
1800
1801         std::string uid;
1802         controller.getObjectProperty(adaptee, BLOCK, UID, uid);
1803
1804         types::String* o = new types::String(1, 1);
1805         o->set(0, uid.data());
1806
1807         return o;
1808     }
1809
1810     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1811     {
1812         if (v->getType() != types::InternalType::ScilabString)
1813         {
1814             return false;
1815         }
1816
1817         types::String* current = v->getAs<types::String>();
1818         if (current->getSize() != 1)
1819         {
1820             return false;
1821         }
1822
1823         ScicosID adaptee = adaptor.getAdaptee()->id();
1824
1825         char* c_str = wide_string_to_UTF8(current->get(0));
1826         std::string uid(c_str);
1827         FREE(c_str);
1828
1829         controller.setObjectProperty(adaptee, BLOCK, UID, uid);
1830         return true;
1831     }
1832 };
1833
1834 } /* namespace */
1835
1836 template<> property<ModelAdapter>::props_t property<ModelAdapter>::fields = property<ModelAdapter>::props_t();
1837
1838 ModelAdapter::ModelAdapter(std::shared_ptr<model::Block> adaptee) :
1839     BaseAdapter<ModelAdapter, org_scilab_modules_scicos::model::Block>(adaptee),
1840     diagramAdapter(nullptr)
1841 {
1842     if (property<ModelAdapter>::properties_have_not_been_set())
1843     {
1844         property<ModelAdapter>::fields.reserve(23);
1845         property<ModelAdapter>::add_property(L"sim", &sim::get, &sim::set);
1846         property<ModelAdapter>::add_property(L"in", &in::get, &in::set);
1847         property<ModelAdapter>::add_property(L"in2", &in2::get, &in2::set);
1848         property<ModelAdapter>::add_property(L"intyp", &intyp::get, &intyp::set);
1849         property<ModelAdapter>::add_property(L"out", &out::get, &out::set);
1850         property<ModelAdapter>::add_property(L"out2", &out2::get, &out2::set);
1851         property<ModelAdapter>::add_property(L"outtyp", &outtyp::get, &outtyp::set);
1852         property<ModelAdapter>::add_property(L"evtin", &evtin::get, &evtin::set);
1853         property<ModelAdapter>::add_property(L"evtout", &evtout::get, &evtout::set);
1854         property<ModelAdapter>::add_property(L"state", &state::get, &state::set);
1855         property<ModelAdapter>::add_property(L"dstate", &dstate::get, &dstate::set);
1856         property<ModelAdapter>::add_property(L"odstate", &odstate::get, &odstate::set);
1857         property<ModelAdapter>::add_property(L"rpar", &rpar::get, &rpar::set);
1858         property<ModelAdapter>::add_property(L"ipar", &ipar::get, &ipar::set);
1859         property<ModelAdapter>::add_property(L"opar", &opar::get, &opar::set);
1860         property<ModelAdapter>::add_property(L"blocktype", &blocktype::get, &blocktype::set);
1861         property<ModelAdapter>::add_property(L"firing", &firing::get, &firing::set);
1862         property<ModelAdapter>::add_property(L"dep_ut", &dep_ut::get, &dep_ut::set);
1863         property<ModelAdapter>::add_property(L"label", &label::get, &label::set);
1864         property<ModelAdapter>::add_property(L"nzcross", &nzcross::get, &nzcross::set);
1865         property<ModelAdapter>::add_property(L"nmode", &nmode::get, &nmode::set);
1866         property<ModelAdapter>::add_property(L"equations", &equations::get, &equations::set);
1867         property<ModelAdapter>::add_property(L"uid", &uid::get, &uid::set);
1868     }
1869 }
1870
1871 ModelAdapter::ModelAdapter(const ModelAdapter& adapter) :
1872     BaseAdapter<ModelAdapter, org_scilab_modules_scicos::model::Block>(adapter),
1873     diagramAdapter(adapter.getDiagram())
1874 {
1875 }
1876
1877 ModelAdapter::~ModelAdapter()
1878 {
1879     if (diagramAdapter != nullptr)
1880     {
1881         diagramAdapter->DecreaseRef();
1882         diagramAdapter->killMe();
1883     }
1884 }
1885
1886 std::wstring ModelAdapter::getTypeStr()
1887 {
1888     return getSharedTypeStr();
1889 }
1890
1891 std::wstring ModelAdapter::getShortTypeStr()
1892 {
1893     return getSharedTypeStr();
1894 }
1895
1896 DiagramAdapter* ModelAdapter::getDiagram() const
1897 {
1898     if (diagramAdapter != nullptr)
1899     {
1900         diagramAdapter->IncreaseRef();
1901     }
1902     return diagramAdapter;
1903 }
1904
1905 void ModelAdapter::setDiagram(DiagramAdapter* newDiagram)
1906 {
1907     if (newDiagram != nullptr)
1908     {
1909         // The old 'diagramAdapter' needs to be freed after setting it to 'v'
1910         DiagramAdapter* temp = diagramAdapter;
1911
1912         newDiagram->IncreaseRef();
1913         diagramAdapter = newDiagram;
1914
1915         if (temp != nullptr)
1916         {
1917             temp->DecreaseRef();
1918             temp->killMe();
1919         }
1920     }
1921 }
1922
1923 } /* namespace view_scilab */
1924 } /* namespace org_scilab_modules_scicos */