Xcos MVC: use shared_ptr on the Model
[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
18 #include "int.hxx"
19 #include "bool.hxx"
20 #include "double.hxx"
21 #include "string.hxx"
22 #include "list.hxx"
23 #include "user.hxx"
24
25 #include "Controller.hxx"
26 #include "Adapters.hxx"
27 #include "ModelAdapter.hxx"
28 #include "DiagramAdapter.hxx"
29 #include "ports_management.hxx"
30 #include "utilities.hxx"
31
32 extern "C" {
33 #include "wchar.h"
34 #include "string.h"
35 #include "sci_malloc.h"
36 #include "charEncoding.h"
37 }
38
39 namespace org_scilab_modules_scicos
40 {
41 namespace view_scilab
42 {
43 namespace
44 {
45
46 const std::string input ("input");
47 const std::string output ("output");
48 const std::string inimpl ("inimpl");
49 const std::string outimpl ("outimpl");
50
51 struct sim
52 {
53
54     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
55     {
56         ScicosID adaptee = adaptor.getAdaptee()->id();
57
58         // First, extract the function Name
59         std::string name;
60         controller.getObjectProperty(adaptee, BLOCK, SIM_FUNCTION_NAME, name);
61         types::String* Name = new types::String(1, 1);
62         Name->set(0, name.data());
63
64         // Then the Api. If it is zero, then just return the Name. Otherwise, return a list containing both.
65         int api;
66         controller.getObjectProperty(adaptee, BLOCK, SIM_FUNCTION_API, api);
67
68         if (api == 0)
69         {
70             return Name;
71         }
72         else
73         {
74             types::Double* Api = new types::Double(static_cast<double>(api));
75             types::List* o = new types::List();
76             o->set(0, Name);
77             o->set(1, Api);
78             return o;
79         }
80     }
81
82     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
83     {
84         ScicosID adaptee = adaptor.getAdaptee()->id();
85
86         if (v->getType() == types::InternalType::ScilabString)
87         {
88             types::String* current = v->getAs<types::String>();
89             if (current->getSize() != 1)
90             {
91                 return false;
92             }
93
94             char* c_str = wide_string_to_UTF8(current->get(0));
95             std::string name = std::string(c_str);
96             FREE(c_str);
97
98             // If the input is a scalar string, then the functionApi is 0.
99             int api = 0;
100
101             controller.setObjectProperty(adaptee, BLOCK, SIM_FUNCTION_NAME, name);
102             controller.setObjectProperty(adaptee, BLOCK, SIM_FUNCTION_API, api);
103         }
104         else if (v->getType() == types::InternalType::ScilabList)
105         {
106             // If the input is a 2-sized list, then it must be string and positive integer.
107             types::List* current = v->getAs<types::List>();
108             if (current->getSize() != 2)
109             {
110                 return false;
111             }
112             if (current->get(0)->getType() != types::InternalType::ScilabString || current->get(1)->getType() != types::InternalType::ScilabDouble)
113             {
114                 return false;
115             }
116
117             types::String* Name = current->get(0)->getAs<types::String>();
118             if (Name->getSize() != 1)
119             {
120                 return false;
121             }
122             char* c_str = wide_string_to_UTF8(Name->get(0));
123             std::string name = std::string(c_str);
124             FREE(c_str);
125
126             types::Double* Api = current->get(1)->getAs<types::Double>();
127             if (Api->getSize() != 1)
128             {
129                 return false;
130             }
131             double api = Api->get(0);
132             if (floor(api) != api)
133             {
134                 return false;
135             }
136             int api_int = static_cast<int>(api);
137
138             controller.setObjectProperty(adaptee, BLOCK, SIM_FUNCTION_NAME, name);
139             controller.setObjectProperty(adaptee, BLOCK, SIM_FUNCTION_API, api_int);
140         }
141         else
142         {
143             return false;
144         }
145         return true;
146     }
147 };
148
149 struct in
150 {
151
152     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
153     {
154         return get_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, INPUTS, controller);
155     }
156
157     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
158     {
159         return update_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, INPUTS, controller, v);
160     }
161 };
162
163 struct in2
164 {
165
166     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
167     {
168         return get_ports_property<ModelAdapter, DATATYPE_COLS>(adaptor, INPUTS, controller);
169     }
170
171     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
172     {
173         return set_ports_property<ModelAdapter, DATATYPE_COLS>(adaptor, INPUTS, controller, v);
174     }
175 };
176
177 struct intyp
178 {
179
180     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
181     {
182         return get_ports_property<ModelAdapter, DATATYPE_TYPE>(adaptor, INPUTS, controller);
183     }
184
185     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
186     {
187         return set_ports_property<ModelAdapter, DATATYPE_TYPE>(adaptor, INPUTS, controller, v);
188     }
189 };
190
191 struct out
192 {
193
194     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
195     {
196         return get_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, OUTPUTS, controller);
197     }
198
199     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
200     {
201         return update_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, OUTPUTS, controller, v);
202     }
203 };
204
205 struct out2
206 {
207
208     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
209     {
210         return get_ports_property<ModelAdapter, DATATYPE_COLS>(adaptor, OUTPUTS, controller);
211     }
212
213     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
214     {
215         return set_ports_property<ModelAdapter, DATATYPE_COLS>(adaptor, OUTPUTS, controller, v);
216     }
217 };
218
219 struct outtyp
220 {
221
222     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
223     {
224         return get_ports_property<ModelAdapter, DATATYPE_TYPE>(adaptor, OUTPUTS, controller);
225     }
226
227     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
228     {
229         return set_ports_property<ModelAdapter, DATATYPE_TYPE>(adaptor, OUTPUTS, controller, v);
230     }
231 };
232
233 struct evtin
234 {
235
236     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
237     {
238         return get_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, EVENT_INPUTS, controller);
239     }
240
241     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
242     {
243         return update_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, EVENT_INPUTS, controller, v);
244     }
245 };
246
247 struct evtout
248 {
249
250     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
251     {
252         return get_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, EVENT_OUTPUTS, controller);
253     }
254
255     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
256     {
257         return update_ports_property<ModelAdapter, DATATYPE_ROWS>(adaptor, EVENT_OUTPUTS, controller, v);
258     }
259 };
260
261 struct state
262 {
263
264     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
265     {
266         ScicosID adaptee = adaptor.getAdaptee()->id();
267
268         std::vector<double> state;
269         controller.getObjectProperty(adaptee, BLOCK, STATE, state);
270
271         double* data;
272         types::Double* o = new types::Double((int)state.size(), 1, &data);
273
274 #ifdef _MSC_VER
275         std::copy(state.begin(), state.end(), stdext::checked_array_iterator<double*>(data, state.size()));
276 #else
277         std::copy(state.begin(), state.end(), data);
278 #endif
279         return o;
280     }
281
282     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
283     {
284
285         if (v->getType() != types::InternalType::ScilabDouble)
286         {
287             return false;
288         }
289
290         types::Double* current = v->getAs<types::Double>();
291         if (current->getCols() != 0 && current->getCols() != 1)
292         {
293             return false;
294         }
295
296         ScicosID adaptee = adaptor.getAdaptee()->id();
297
298         std::vector<double> state (current->getSize());
299         std::copy(current->getReal(), current->getReal() + current->getSize(), state.begin());
300
301         controller.setObjectProperty(adaptee, BLOCK, STATE, state);
302         return true;
303     }
304 };
305
306 struct dstate
307 {
308
309     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
310     {
311         ScicosID adaptee = adaptor.getAdaptee()->id();
312
313         std::vector<double> dstate;
314         controller.getObjectProperty(adaptee, BLOCK, DSTATE, dstate);
315
316         double* data;
317         types::Double* o = new types::Double((int)dstate.size(), 1, &data);
318
319 #ifdef _MSC_VER
320         std::copy(dstate.begin(), dstate.end(), stdext::checked_array_iterator<double*>(data, dstate.size()));
321 #else
322         std::copy(dstate.begin(), dstate.end(), data);
323 #endif
324         return o;
325     }
326
327     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
328     {
329         ScicosID adaptee = adaptor.getAdaptee()->id();
330
331         if (v->getType() == types::InternalType::ScilabString)
332         {
333             types::String* current = v->getAs<types::String>();
334             if (current->getSize() != 1)
335             {
336                 return false;
337             }
338
339             std::vector<double> dstate;
340             controller.setObjectProperty(adaptee, BLOCK, DSTATE, dstate);
341             return true;
342         }
343
344         if (v->getType() != types::InternalType::ScilabDouble)
345         {
346             return false;
347         }
348         types::Double* current = v->getAs<types::Double>();
349         if (current->getCols() != 0 && current->getCols() != 1)
350         {
351             return false;
352         }
353
354         std::vector<double> dstate (current->getSize());
355         std::copy(current->getReal(), current->getReal() + current->getSize(), dstate.begin());
356
357         controller.setObjectProperty(adaptee, BLOCK, DSTATE, dstate);
358         return true;
359     }
360 };
361
362 types::InternalType* getPropList(const ModelAdapter& adaptor, const Controller& controller, const object_properties_t prop)
363 {
364     ScicosID adaptee = adaptor.getAdaptee()->id();
365
366     std::vector<int> prop_content;
367     controller.getObjectProperty(adaptee, BLOCK, prop, prop_content);
368
369     if (prop_content.empty())
370     {
371         return types::Double::Empty();
372     }
373
374     types::List* list = new types::List();
375
376     int index = 1; // Index to each element of the returned list
377
378     for (int i = 0; i < prop_content[0]; ++i) // 'o' must have exactly 'prop_content[0]' elements
379     {
380         int m, n, numberOfIntNeeded = 0;
381         switch (prop_content[index])
382         {
383             case types::InternalType::ScilabDouble:
384             {
385                 m = prop_content[index + 1];
386                 n = prop_content[index + 2];
387                 int isComplex = prop_content[index + 3];
388
389                 double* real;
390                 types::Double* pDouble;
391
392                 if (isComplex == 0)
393                 {
394                     pDouble = new types::Double(m, n, &real);
395                     numberOfIntNeeded = 2 * m * n + 1;
396                     memcpy(real, &prop_content[index + 3 + 1], m * n * sizeof(double));
397                 }
398                 else
399                 {
400                     double* imag;
401                     pDouble = new types::Double(m, n, &real, &imag);
402                     numberOfIntNeeded = 4 * m * n + 1;
403                     memcpy(real, &prop_content[index + 3 + 1], m * n * sizeof(double));
404                     memcpy(imag, &prop_content[index + 3 + 1 + 2 * m * n], m * n * sizeof(double));
405                 }
406                 list->set(i, pDouble);
407                 break;
408             }
409             case types::InternalType::ScilabInt8:
410             {
411                 m = prop_content[index + 1];
412                 n = prop_content[index + 2];
413                 numberOfIntNeeded = m * n / 4;
414
415                 char* data;
416                 types::Int8* pInt8 = new types::Int8(m, n, &data);
417
418                 memcpy(data, &prop_content[index + 3], m * n * sizeof(char));
419                 list->set(i, pInt8);
420                 break;
421             }
422             case types::InternalType::ScilabUInt8:
423             {
424                 m = prop_content[index + 1];
425                 n = prop_content[index + 2];
426                 numberOfIntNeeded = m * n / 4;
427
428                 unsigned char* data;
429                 types::UInt8* pUInt8 = new types::UInt8(m, n, &data);
430
431                 memcpy(data, &prop_content[index + 3], m * n * sizeof(unsigned char));
432                 list->set(i, pUInt8);
433                 break;
434             }
435             case types::InternalType::ScilabInt16:
436             {
437                 m = prop_content[index + 1];
438                 n = prop_content[index + 2];
439                 numberOfIntNeeded = m * n / 2;
440
441                 short int* data;
442                 types::Int16* pInt16 = new types::Int16(m, n, &data);
443
444                 memcpy(data, &prop_content[index + 3], m * n * sizeof(short int));
445                 list->set(i, pInt16);
446                 break;
447             }
448             case types::InternalType::ScilabUInt16:
449             {
450                 m = prop_content[index + 1];
451                 n = prop_content[index + 2];
452                 numberOfIntNeeded = m * n / 2;
453
454                 unsigned short int* data;
455                 types::UInt16* pUInt16 = new types::UInt16(m, n, &data);
456
457                 memcpy(data, &prop_content[index + 3], m * n * sizeof(unsigned short int));
458                 list->set(i, pUInt16);
459                 break;
460             }
461             case types::InternalType::ScilabInt32:
462             {
463                 m = prop_content[index + 1];
464                 n = prop_content[index + 2];
465                 numberOfIntNeeded = m * n;
466
467                 int* data;
468                 types::Int32* pInt32 = new types::Int32(m, n, &data);
469
470                 memcpy(data, &prop_content[index + 3], m * n * sizeof(int));
471                 list->set(i, pInt32);
472                 break;
473             }
474             case types::InternalType::ScilabUInt32:
475             {
476                 m = prop_content[index + 1];
477                 n = prop_content[index + 2];
478                 numberOfIntNeeded = m * n;
479
480                 unsigned int* data;
481                 types::UInt32* pUInt32 = new types::UInt32(m, n, &data);
482
483                 memcpy(data, &prop_content[index + 3], m * n * sizeof(unsigned int));
484                 list->set(i, pUInt32);
485                 break;
486             }
487             case types::InternalType::ScilabString:
488             {
489                 m = prop_content[index + 1];
490                 n = prop_content[index + 2];
491
492                 types::String* pString = new types::String(m, n);
493
494                 for (int j = 0; j < m * n; ++j)
495                 {
496                     int strLen = prop_content[index + 3 + numberOfIntNeeded];
497                     wchar_t* str = new wchar_t[strLen + 1];
498                     memcpy(str, &prop_content[index + 3 + numberOfIntNeeded + 1], strLen * sizeof(wchar_t));
499                     str[strLen] = '\0';
500                     pString->set(j, str);
501                     delete str;
502
503                     numberOfIntNeeded += 1 + strLen;
504                 }
505                 list->set(i, pString);
506                 break;
507             }
508             case types::InternalType::ScilabBool:
509             {
510                 m = prop_content[index + 1];
511                 n = prop_content[index + 2];
512                 numberOfIntNeeded = m * n;
513
514                 int* data;
515                 types::Bool* pBool = new types::Bool(m, n, &data);
516
517                 memcpy(data, &prop_content[index + 3], m * n * sizeof(int));
518                 list->set(i, pBool);
519                 break;
520             }
521             default:
522                 return 0;
523         }
524
525         index += 3 + numberOfIntNeeded;
526     }
527
528     return list;
529 }
530
531 bool setPropList(ModelAdapter& adaptor, Controller& controller, const object_properties_t prop, types::InternalType* v)
532 {
533     ScicosID adaptee = adaptor.getAdaptee()->id();
534
535     if (v->getType() == types::InternalType::ScilabDouble)
536     {
537         types::Double* current = v->getAs<types::Double>();
538         if (current->getSize() != 0)
539         {
540             return false;
541         }
542
543         std::vector<int> prop_content;
544         controller.setObjectProperty(adaptee, BLOCK, prop, prop_content);
545         return true;
546     }
547
548     if (v->getType() != types::InternalType::ScilabList)
549     {
550         return false;
551     }
552
553     types::List* list = v->getAs<types::List>();
554
555     // 'prop_content' will be a buffer containing the elements of the list, copied into 'int' type by bits
556     std::vector<int> prop_content (1, list->getSize()); // Save the number of list elements in the first element
557     int index = 1; // Index to point at every new list element
558
559     for (int i = 0; i < list->getSize(); ++i)
560     {
561         // Save the variable type
562         prop_content.resize(prop_content.size() + 1);
563         prop_content[index] = list->get(i)->getType();
564
565         int m, n, numberOfIntNeeded = 0;
566         switch (list->get(i)->getType())
567         {
568             case types::InternalType::ScilabDouble:
569             {
570                 types::Double* pDouble = list->get(i)->getAs<types::Double>();
571                 m = pDouble->getRows();
572                 n = pDouble->getCols();
573
574                 if (!pDouble->isComplex())
575                 {
576                     // It takes 2 int (4 bytes) to save 1 real (1 double: 8 bytes)
577                     // So reserve 2*m*n, 2 integers for the matrix dimensions and 1 for the complexity
578                     numberOfIntNeeded = 2 * m * n + 1;
579                     prop_content.resize(prop_content.size() + 2 + numberOfIntNeeded);
580                     prop_content[index + 3] = 0; // Flag for real
581
582                     // Using contiguity of the memory, we save the input into 'prop_content'
583                     memcpy(&prop_content[index + 3 + 1], pDouble->getReal(), m * n * sizeof(double));
584                 }
585                 else
586                 {
587                     // It takes 4 int (4 bytes) to save 1 complex (2 double: 16 bytes)
588                     // So reserve 2*m*n, 2 integers for the matrix dimensions and 1 for the complexity
589                     numberOfIntNeeded = 4 * m * n + 1;
590                     prop_content.resize(prop_content.size() + 2 + numberOfIntNeeded);
591                     prop_content[index + 3] = 1; // Flag for complex
592
593                     // Contiguously save the real and complex parts
594                     memcpy(&prop_content[index + 3 + 1], pDouble->getReal(), m * n * sizeof(double));
595                     memcpy(&prop_content[index + 3 + 1 + 2 * m * n], pDouble->getImg(), m * n * sizeof(double));
596                 }
597                 break;
598             }
599             case types::InternalType::ScilabInt8:
600             {
601                 types::Int8* pInt8 = list->get(i)->getAs<types::Int8>();
602                 m = pInt8->getRows();
603                 n = pInt8->getCols();
604
605                 // It takes 1 int (4 bytes) to save 4 char (1 byte)
606                 // So reserve m*n/4 and 2 integers for the matrix dimensions
607                 numberOfIntNeeded = m * n / 4;
608                 prop_content.resize(prop_content.size() + 2 + numberOfIntNeeded);
609
610                 // Using contiguity of the memory, we save the input into 'prop_content'
611                 memcpy(&prop_content[index + 3], pInt8->get(), m * n * sizeof(char));
612                 break;
613             }
614             case types::InternalType::ScilabUInt8:
615             {
616                 types::Int16* pInt16 = list->get(i)->getAs<types::Int16>();
617                 m = pInt16->getRows();
618                 n = pInt16->getCols();
619
620                 // It takes 1 int (4 bytes) to save 4 unsigned char (1 byte)
621                 // So reserve m*n/4 and 2 integers for the matrix dimensions
622                 numberOfIntNeeded = m * n / 4;
623                 prop_content.resize(prop_content.size() + 2 + numberOfIntNeeded);
624
625                 // Using contiguity of the memory, we save the input into 'prop_content'
626                 memcpy(&prop_content[index + 3], pInt16->get(), m * n * sizeof(unsigned char));
627                 break;
628             }
629             case types::InternalType::ScilabInt16:
630             {
631                 types::Int16* pInt16 = list->get(i)->getAs<types::Int16>();
632                 m = pInt16->getRows();
633                 n = pInt16->getCols();
634
635                 // It takes 1 int (4 bytes) to save 2 short int (2 bytes)
636                 // So reserve m*n/2 and 2 integers for the matrix dimensions
637                 numberOfIntNeeded = m * n / 2;
638                 prop_content.resize(prop_content.size() + 2 + numberOfIntNeeded);
639
640                 // Using contiguity of the memory, we save the input into 'prop_content'
641                 memcpy(&prop_content[index + 3], pInt16->get(), m * n * sizeof(short int));
642                 break;
643             }
644             case types::InternalType::ScilabUInt16:
645             {
646                 types::UInt16* pUInt16 = list->get(i)->getAs<types::UInt16>();
647                 m = pUInt16->getRows();
648                 n = pUInt16->getCols();
649
650                 // It takes 1 int (4 bytes) to save 2 unsigned short int (2 bytes)
651                 // So reserve m*n/2 and 2 integers for the matrix dimensions
652                 numberOfIntNeeded = m * n / 2;
653                 prop_content.resize(prop_content.size() + 2 + numberOfIntNeeded);
654
655                 // Using contiguity of the memory, we save the input into prop_content
656                 memcpy(&prop_content[index + 3], pUInt16->get(), m * n * sizeof(unsigned short int));
657                 break;
658             }
659             case types::InternalType::ScilabInt32:
660             {
661                 types::Int32* pInt32 = list->get(i)->getAs<types::Int32>();
662                 m = pInt32->getRows();
663                 n = pInt32->getCols();
664
665                 // It takes 1 int (4 bytes) to save 1 int (4 bytes)
666                 // So reserve m*n and 2 integers for the matrix dimensions
667                 numberOfIntNeeded = m * n;
668                 prop_content.resize(prop_content.size() + 2 + numberOfIntNeeded);
669
670                 // Using contiguity of the memory, we save the input into 'prop_content'
671                 memcpy(&prop_content[index + 3], pInt32->get(), m * n * sizeof(int));
672                 break;
673             }
674             case types::InternalType::ScilabUInt32:
675             {
676                 types::UInt32* pUInt32 = list->get(i)->getAs<types::UInt32>();
677                 m = pUInt32->getRows();
678                 n = pUInt32->getCols();
679
680                 // It takes 1 int (4 bytes) to save 1 unsigned int (4 bytes)
681                 // So reserve m*n and 2 integers for the matrix dimensions
682                 numberOfIntNeeded = m * n;
683                 prop_content.resize(prop_content.size() + 2 + numberOfIntNeeded);
684
685                 // Using contiguity of the memory, we save the input into 'prop_content'
686                 memcpy(&prop_content[index + 3], pUInt32->get(), m * n * sizeof(unsigned int));
687                 break;
688             }
689             case types::InternalType::ScilabInt64:
690             case types::InternalType::ScilabUInt64:
691                 // int64 and uint64 are not treated yet
692                 return false;
693             case types::InternalType::ScilabString:
694             {
695                 types::String* pString = list->get(i)->getAs<types::String>();
696                 m = pString->getRows();
697                 n = pString->getCols();
698
699                 // For the moment, we don't know how many characters each string is long, so only reserve the matrix size
700                 prop_content.resize(prop_content.size() + 2);
701
702                 for (int j = 0; j < m * n; ++j)
703                 {
704                     // Extract the input string length and reserve as many characters in 'prop_content'
705                     int strLen = static_cast<int>(wcslen(pString->get(j)));
706                     prop_content.resize(prop_content.size() + 1 + strLen);
707                     prop_content[index + 3 + numberOfIntNeeded] = strLen;
708
709                     memcpy(&prop_content[index + 3 + numberOfIntNeeded + 1], pString->get(j), strLen * sizeof(wchar_t));
710                     numberOfIntNeeded += 1 + strLen;
711                 }
712                 break;
713             }
714             case types::InternalType::ScilabBool:
715             {
716                 types::Bool* pBool = list->get(i)->getAs<types::Bool>();
717                 m = pBool->getRows();
718                 n = pBool->getCols();
719
720                 // It takes 1 int (4 bytes) to save 1 bool (1 int: 4 byte)
721                 // So reserve m*n and 2 integers for the matrix dimensions
722                 numberOfIntNeeded = m * n;
723                 prop_content.resize(prop_content.size() + 2 + numberOfIntNeeded);
724
725                 // Using contiguity of the memory, we save the input into 'prop_content'
726                 memcpy(&prop_content[index + 3], pBool->get(), m * n * sizeof(int));
727                 break;
728             }
729             default:
730                 return false;
731         }
732         // Save the matrix dimensions in 'prop_content' and increment index to match the next list element
733         prop_content[index + 1] = m;
734         prop_content[index + 2] = n;
735         index += 3 + numberOfIntNeeded;
736     }
737
738     controller.setObjectProperty(adaptee, BLOCK, prop, prop_content);
739     return true;
740 }
741
742 struct odstate
743 {
744
745     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
746     {
747         return getPropList(adaptor, controller, ODSTATE);
748     }
749
750     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
751     {
752         return setPropList(adaptor, controller, ODSTATE, v);
753     }
754 };
755
756 /*
757  * When setting a diagram in 'rpar', the Superblock's ports must be consistent with the "port blocks" inside it.
758  * By "port blocks", we mean IN_f, OUT_f, CLKIN_f, CLKOUT_f, CLKINV_f, CLKOUTV_f, INIMPL_f and OUTIMPL_f.
759  */
760 bool setInnerBlocksRefs(ModelAdapter& adaptor, const std::vector<ScicosID>& children, Controller& controller)
761 {
762     ScicosID adaptee = adaptor.getAdaptee()->id();
763
764     for (std::vector<ScicosID>::const_iterator it = children.begin(); it != children.end(); ++it)
765     {
766         if (controller.getObject(*it)->kind() == BLOCK) // Rule out Annotations and Links
767         {
768             std::string name;
769             controller.getObjectProperty(*it, BLOCK, SIM_FUNCTION_NAME, name);
770
771             // Find the "port blocks"
772             if (name == input || name == inimpl || name == output || name == outimpl)
773             {
774                 std::vector<int> ipar;
775                 controller.getObjectProperty(*it, BLOCK, IPAR, ipar);
776                 if (ipar.size() != 1)
777                 {
778                     return false;
779                 }
780                 int portIndex = ipar[0];
781
782                 // "name" is not enough to tell the event and data ports apart, so check the block's port.
783                 object_properties_t kind;
784                 std::vector<ScicosID> innerPort;
785                 if (name == input || name == inimpl)
786                 {
787                     controller.getObjectProperty(*it, BLOCK, OUTPUTS, innerPort);
788                     if (!innerPort.empty())
789                     {
790                         kind = INPUTS;
791                     }
792                     else
793                     {
794                         kind = EVENT_INPUTS;
795                     }
796                 }
797                 else
798                 {
799                     controller.getObjectProperty(*it, BLOCK, INPUTS, innerPort);
800                     if (!innerPort.empty())
801                     {
802                         kind = OUTPUTS;
803                     }
804                     else
805                     {
806                         kind = EVENT_OUTPUTS;
807                     }
808                 }
809
810                 std::vector<ScicosID> superPorts;
811                 controller.getObjectProperty(adaptee, BLOCK, kind, superPorts);
812                 if (static_cast<int>(superPorts.size()) < portIndex)
813                 {
814                     return false;
815                 }
816
817                 ScicosID port = superPorts[portIndex - 1];
818
819                 // Check consistency of the implicitness between the inner and outer ports
820                 bool isImplicit;
821                 controller.getObjectProperty(port, PORT, IMPLICIT, isImplicit);
822                 if (name == input || name == output)
823                 {
824                     if (isImplicit)
825                     {
826                         return false;
827                     }
828                 }
829                 else
830                 {
831                     if (!isImplicit)
832                     {
833                         return false;
834                     }
835                 }
836
837                 controller.setObjectProperty(*it, BLOCK, PORT_REFERENCE, port);
838             }
839
840             // Regardless of the ports, use the loop to set each Block's 'parent_block' property
841             controller.setObjectProperty(*it, BLOCK, PARENT_BLOCK, adaptee);
842         }
843     }
844     return true;
845 }
846
847 struct rpar
848 {
849
850     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
851     {
852         ScicosID adaptee = adaptor.getAdaptee()->id();
853
854         std::vector<ScicosID> children;
855         controller.getObjectProperty(adaptee, BLOCK, CHILDREN, children);
856
857         if (children.empty())
858         {
859             std::vector<double> rpar;
860             controller.getObjectProperty(adaptee, BLOCK, RPAR, rpar);
861
862             double *data;
863             types::Double* o = new types::Double((int)rpar.size(), 1, &data);
864 #ifdef _MSC_VER
865             std::copy(rpar.begin(), rpar.end(), stdext::checked_array_iterator<double*>(data, rpar.size()));
866 #else
867             std::copy(rpar.begin(), rpar.end(), data);
868 #endif
869             return o;
870         }
871         else // SuperBlock, return the contained diagram, whose ID is stored in children[0]
872         {
873             // FIXME : leak memory
874             model::Diagram* super = static_cast<model::Diagram*>(controller.getObject(children[0]).get());
875             return new DiagramAdapter(std::shared_ptr<model::Diagram>(super));
876         }
877     }
878
879     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
880     {
881         ScicosID adaptee = adaptor.getAdaptee()->id();
882
883         if (v->getType() == types::InternalType::ScilabDouble)
884         {
885             types::Double* current = v->getAs<types::Double>();
886
887             std::vector<double> rpar (current->getSize());
888             for (int i = 0; i < current->getSize(); ++i)
889             {
890                 rpar[i] = current->get(i);
891             }
892
893             controller.setObjectProperty(adaptee, BLOCK, RPAR, rpar);
894             return true;
895         }
896         else if (v->getType() == types::InternalType::ScilabString)
897         {
898             // Allow Text blocks to define strings in rpar
899             return true;
900         }
901         else if (v->getType() == types::InternalType::ScilabUserType)
902         {
903             // Make sure the input describes a Diagram
904             const Adapters::adapters_index_t adapter_index = Adapters::instance().lookup_by_typename(v->getShortTypeStr());
905             if (adapter_index != Adapters::DIAGRAM_ADAPTER)
906             {
907                 return false;
908             }
909
910             // Translate 'v' to an DiagramAdapter and clone it, updating the new Diagram's children
911             DiagramAdapter* diagram = v->getAs<DiagramAdapter>();
912             ScicosID clone = controller.cloneObject(diagram->getAdaptee()->id());
913
914             // Save the children list, adding the new diagram ID at the beginning
915             std::vector<ScicosID> children;
916             controller.getObjectProperty(clone, DIAGRAM, CHILDREN, children);
917             children.insert(children.begin(), clone);
918             controller.setObjectProperty(adaptee, DIAGRAM, CHILDREN, children);
919
920             // Link the Superblock ports to their inner "port blocks"
921             return setInnerBlocksRefs(adaptor, children, controller);
922         }
923         else
924         {
925             return false;
926         }
927     }
928 };
929
930 double toDouble(const int a)
931 {
932     return static_cast<double>(a);
933 }
934
935 struct ipar
936 {
937
938     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
939     {
940         ScicosID adaptee = adaptor.getAdaptee()->id();
941
942         std::vector<int> ipar;
943         controller.getObjectProperty(adaptee, BLOCK, IPAR, ipar);
944
945         double *data;
946         types::Double* o = new types::Double((int)ipar.size(), 1, &data);
947
948 #ifdef _MSC_VER
949         std::transform(ipar.begin(), ipar.end(), stdext::checked_array_iterator<double*>(data, ipar.size()), toDouble);
950 #else
951         std::transform(ipar.begin(), ipar.end(), data, toDouble);
952 #endif
953         return o;
954     }
955
956     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
957     {
958         ScicosID adaptee = adaptor.getAdaptee()->id();
959
960         if (v->getType() == types::InternalType::ScilabList)
961         {
962             std::vector<int> ipar;
963             controller.setObjectProperty(adaptee, BLOCK, IPAR, ipar);
964             return true;
965         }
966
967         if (v->getType() != types::InternalType::ScilabDouble)
968         {
969             return false;
970         }
971
972         types::Double* current = v->getAs<types::Double>();
973         if (current->getCols() != 0 && current->getCols() != 1)
974         {
975             return false;
976         }
977
978         std::vector<int> ipar (current->getSize());
979         for (int i = 0; i < current->getSize(); ++i)
980         {
981             if (floor(current->get(i)) != current->get(i))
982             {
983                 return false;
984             }
985             ipar[i] = static_cast<int>(current->get(i));
986         }
987
988         controller.setObjectProperty(adaptee, BLOCK, IPAR, ipar);
989         return true;
990     }
991 };
992
993 struct opar
994 {
995
996     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
997     {
998         return getPropList(adaptor, controller, OPAR);
999     }
1000
1001     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1002     {
1003         return setPropList(adaptor, controller, OPAR, v);
1004     }
1005 };
1006
1007 struct blocktype
1008 {
1009
1010     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1011     {
1012         ScicosID adaptee = adaptor.getAdaptee()->id();
1013
1014         std::string type;
1015         controller.getObjectProperty(adaptee, BLOCK, SIM_BLOCKTYPE, type);
1016
1017         types::String* o = new types::String(type.c_str());
1018         return o;
1019     }
1020
1021     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1022     {
1023         ScicosID adaptee = adaptor.getAdaptee()->id();
1024
1025         if (v->getType() != types::InternalType::ScilabString)
1026         {
1027             return false;
1028         }
1029
1030         types::String* current = v->getAs<types::String>();
1031         if (current->getSize() != 1)
1032         {
1033             return false;
1034         }
1035
1036         char* c_str = wide_string_to_UTF8(current->get(0));
1037         std::string type (c_str);
1038         FREE(c_str);
1039
1040         // the value validation is performed on the model
1041         return controller.setObjectProperty(adaptee, BLOCK, SIM_BLOCKTYPE, type) != FAIL;
1042     }
1043 };
1044
1045 struct firing
1046 {
1047
1048     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1049     {
1050         return get_ports_property<ModelAdapter, FIRING>(adaptor, EVENT_OUTPUTS, controller);
1051     }
1052
1053     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1054     {
1055         return set_ports_property<ModelAdapter, FIRING>(adaptor, EVENT_OUTPUTS, controller, v);
1056     }
1057 };
1058
1059 struct dep_ut
1060 {
1061
1062     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1063     {
1064         ScicosID adaptee = adaptor.getAdaptee()->id();
1065
1066         std::vector<int> dep_ut;
1067         controller.getObjectProperty(adaptee, BLOCK, SIM_DEP_UT, dep_ut);
1068
1069         int* dep;
1070         types::Bool* o = new types::Bool(1, 2, &dep);
1071
1072         dep[0] = dep_ut[0];
1073         dep[1] = dep_ut[1];
1074
1075         return o;
1076     }
1077
1078     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1079     {
1080         ScicosID adaptee = adaptor.getAdaptee()->id();
1081
1082         if (v->getType() != types::InternalType::ScilabBool)
1083         {
1084             return false;
1085         }
1086
1087         types::Bool* current = v->getAs<types::Bool>();
1088         if (current->getRows() != 1 || current->getCols() != 2)
1089         {
1090             return false;
1091         }
1092
1093         std::vector<int> dep_ut (2);
1094         dep_ut[0] = current->get(0);
1095         dep_ut[1] = current->get(1);
1096
1097         controller.setObjectProperty(adaptee, BLOCK, SIM_DEP_UT, dep_ut);
1098         return true;
1099     }
1100 };
1101
1102 struct label
1103 {
1104
1105     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1106     {
1107         ScicosID adaptee = adaptor.getAdaptee()->id();
1108
1109         std::string label;
1110         controller.getObjectProperty(adaptee, BLOCK, LABEL, label);
1111
1112         types::String* o = new types::String(1, 1);
1113         o->set(0, label.data());
1114
1115         return o;
1116     }
1117
1118     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1119     {
1120         if (v->getType() != types::InternalType::ScilabString)
1121         {
1122             return false;
1123         }
1124
1125         types::String* current = v->getAs<types::String>();
1126         if (current->getSize() != 1)
1127         {
1128             return false;
1129         }
1130
1131         ScicosID adaptee = adaptor.getAdaptee()->id();
1132
1133         std::string label;
1134         char* c_str = wide_string_to_UTF8(current->get(0));
1135         label = std::string(c_str);
1136         FREE(c_str);
1137
1138         controller.setObjectProperty(adaptee, BLOCK, LABEL, label);
1139         return true;
1140     }
1141 };
1142
1143 struct nzcross
1144 {
1145
1146     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1147     {
1148         ScicosID adaptee = adaptor.getAdaptee()->id();
1149
1150         int nzcross;
1151         controller.getObjectProperty(adaptee, BLOCK, NZCROSS, nzcross);
1152
1153         types::Double* o = new types::Double(static_cast<double>(nzcross));
1154
1155         return o;
1156     }
1157
1158     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1159     {
1160         ScicosID adaptee = adaptor.getAdaptee()->id();
1161
1162         if (v->getType() != types::InternalType::ScilabDouble)
1163         {
1164             return false;
1165         }
1166
1167         types::Double* current = v->getAs<types::Double>();
1168
1169         int nzcross = 0; // Default value
1170         if (current->getSize() != 0)
1171         {
1172             if (current->getSize() != 1)
1173             {
1174                 return false;
1175             }
1176             if (floor(current->get(0)) != current->get(0))
1177             {
1178                 return false;
1179             }
1180
1181             nzcross = static_cast<int>(current->get(0));
1182         }
1183
1184         controller.setObjectProperty(adaptee, BLOCK, NZCROSS, nzcross);
1185         return true;
1186     }
1187 };
1188
1189 struct nmode
1190 {
1191
1192     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1193     {
1194         ScicosID adaptee = adaptor.getAdaptee()->id();
1195
1196         int nmode;
1197         controller.getObjectProperty(adaptee, BLOCK, NMODE, nmode);
1198
1199         types::Double* o = new types::Double(static_cast<double>(nmode));
1200
1201         return o;
1202     }
1203
1204     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1205     {
1206         ScicosID adaptee = adaptor.getAdaptee()->id();
1207
1208         if (v->getType() != types::InternalType::ScilabDouble)
1209         {
1210             return false;
1211         }
1212
1213         types::Double* current = v->getAs<types::Double>();
1214
1215         int nmode = 0; // Default value
1216         if (current->getSize() != 0)
1217         {
1218             if (current->getSize() != 1)
1219             {
1220                 return false;
1221             }
1222             if (floor(current->get(0)) != current->get(0))
1223             {
1224                 return false;
1225             }
1226
1227             nmode = static_cast<int>(current->get(0));
1228         }
1229
1230         controller.setObjectProperty(adaptee, BLOCK, NMODE, nmode);
1231         return true;
1232     }
1233 };
1234
1235 struct equations
1236 {
1237
1238     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1239     {
1240         // silent unused parameter warnings
1241         (void) adaptor;
1242         (void) controller;
1243
1244         // FIXME: implement as a stored modelica equations
1245
1246         // Return a default empty list.
1247         return new types::List();
1248     }
1249
1250     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1251     {
1252         if (v->getType() != types::InternalType::ScilabList)
1253         {
1254             return false;
1255         }
1256
1257         types::List* current = v->getAs<types::List>();
1258
1259         if (current->getSize() == 0)
1260         {
1261             return true;
1262         }
1263         else
1264         {
1265             // silent unused parameter warnings
1266             (void) adaptor;
1267             (void) v;
1268             (void) controller;
1269
1270             // FIXME: implement as a stored modelica equations
1271             // FIXME: get the input list and store it in the equations field
1272             return false;
1273         }
1274     }
1275 };
1276
1277 struct uid
1278 {
1279
1280     static types::InternalType* get(const ModelAdapter& adaptor, const Controller& controller)
1281     {
1282         ScicosID adaptee = adaptor.getAdaptee()->id();
1283
1284         std::string uid;
1285         controller.getObjectProperty(adaptee, BLOCK, UID, uid);
1286
1287         types::String* o = new types::String(1, 1);
1288         o->set(0, uid.data());
1289
1290         return o;
1291     }
1292
1293     static bool set(ModelAdapter& adaptor, types::InternalType* v, Controller& controller)
1294     {
1295         if (v->getType() != types::InternalType::ScilabString)
1296         {
1297             return false;
1298         }
1299
1300         types::String* current = v->getAs<types::String>();
1301         if (current->getSize() != 1)
1302         {
1303             return false;
1304         }
1305
1306         ScicosID adaptee = adaptor.getAdaptee()->id();
1307
1308         std::string uid;
1309         char* c_str = wide_string_to_UTF8(current->get(0));
1310         uid = std::string(c_str);
1311         FREE(c_str);
1312
1313         controller.setObjectProperty(adaptee, BLOCK, UID, uid);
1314         return true;
1315     }
1316 };
1317
1318 } /* namespace */
1319
1320 template<> property<ModelAdapter>::props_t property<ModelAdapter>::fields = property<ModelAdapter>::props_t();
1321
1322 ModelAdapter::ModelAdapter(std::shared_ptr<model::Block> adaptee) :
1323     BaseAdapter<ModelAdapter, org_scilab_modules_scicos::model::Block>(adaptee)
1324 {
1325     if (property<ModelAdapter>::properties_have_not_been_set())
1326     {
1327         property<ModelAdapter>::fields.reserve(23);
1328         property<ModelAdapter>::add_property(L"sim", &sim::get, &sim::set);
1329         property<ModelAdapter>::add_property(L"in", &in::get, &in::set);
1330         property<ModelAdapter>::add_property(L"in2", &in2::get, &in2::set);
1331         property<ModelAdapter>::add_property(L"intyp", &intyp::get, &intyp::set);
1332         property<ModelAdapter>::add_property(L"out", &out::get, &out::set);
1333         property<ModelAdapter>::add_property(L"out2", &out2::get, &out2::set);
1334         property<ModelAdapter>::add_property(L"outtyp", &outtyp::get, &outtyp::set);
1335         property<ModelAdapter>::add_property(L"evtin", &evtin::get, &evtin::set);
1336         property<ModelAdapter>::add_property(L"evtout", &evtout::get, &evtout::set);
1337         property<ModelAdapter>::add_property(L"state", &state::get, &state::set);
1338         property<ModelAdapter>::add_property(L"dstate", &dstate::get, &dstate::set);
1339         property<ModelAdapter>::add_property(L"odstate", &odstate::get, &odstate::set);
1340         property<ModelAdapter>::add_property(L"rpar", &rpar::get, &rpar::set);
1341         property<ModelAdapter>::add_property(L"ipar", &ipar::get, &ipar::set);
1342         property<ModelAdapter>::add_property(L"opar", &opar::get, &opar::set);
1343         property<ModelAdapter>::add_property(L"blocktype", &blocktype::get, &blocktype::set);
1344         property<ModelAdapter>::add_property(L"firing", &firing::get, &firing::set);
1345         property<ModelAdapter>::add_property(L"dep_ut", &dep_ut::get, &dep_ut::set);
1346         property<ModelAdapter>::add_property(L"label", &label::get, &label::set);
1347         property<ModelAdapter>::add_property(L"nzcross", &nzcross::get, &nzcross::set);
1348         property<ModelAdapter>::add_property(L"nmode", &nmode::get, &nmode::set);
1349         property<ModelAdapter>::add_property(L"equations", &equations::get, &equations::set);
1350         property<ModelAdapter>::add_property(L"uid", &uid::get, &uid::set);
1351     }
1352 }
1353
1354 ModelAdapter::ModelAdapter(const ModelAdapter& adapter) :
1355     BaseAdapter<ModelAdapter, org_scilab_modules_scicos::model::Block>(adapter)
1356 {
1357 }
1358
1359 ModelAdapter::~ModelAdapter()
1360 {
1361 }
1362
1363 std::wstring ModelAdapter::getTypeStr()
1364 {
1365     return getSharedTypeStr();
1366 }
1367
1368 std::wstring ModelAdapter::getShortTypeStr()
1369 {
1370     return getSharedTypeStr();
1371 }
1372
1373 } /* namespace view_scilab */
1374 } /* namespace org_scilab_modules_scicos */