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