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