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