utf: io 2
[scilab.git] / scilab / modules / scicos / sci_gateway / cpp / sci_scicos_new.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2014-2014 - Scilab Enterprises - Clement DAVID
4  *
5  *  This file must be used under the terms of the CeCILL.
6  *  This source file is licensed as described in the file COPYING, which
7  *  you should have received as part of this distribution.  The terms
8  *  are also available at
9  *  http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
10  *
11  */
12
13 #include <string>
14 #include <sstream>
15
16 #include "gw_scicos.hxx"
17
18 #include "types.hxx"
19 #include "int.hxx"
20 #include "string.hxx"
21 #include "tlist.hxx"
22 #include "mlist.hxx"
23 #include "list.hxx"
24 #include "function.hxx"
25
26 #include "view_scilab/Adapters.hxx"
27 #include "view_scilab/BaseAdapter.hxx"
28 #include "view_scilab/BlockAdapter.hxx"
29 #include "view_scilab/CprAdapter.hxx"
30 #include "view_scilab/DiagramAdapter.hxx"
31 #include "view_scilab/GraphicsAdapter.hxx"
32 #include "view_scilab/LinkAdapter.hxx"
33 #include "view_scilab/ModelAdapter.hxx"
34 #include "view_scilab/ParamsAdapter.hxx"
35 #include "view_scilab/ScsAdapter.hxx"
36 #include "view_scilab/StateAdapter.hxx"
37 #include "view_scilab/TextAdapter.hxx"
38
39 #include "utilities.hxx"
40 #include "Controller.hxx"
41 #include "model/Annotation.hxx"
42 #include "model/Block.hxx"
43 #include "model/Diagram.hxx"
44 #include "model/Link.hxx"
45
46 extern "C"
47 {
48 #include "Scierror.h"
49 #include "localization.h"
50 }
51
52 static const std::string funame = "scicos_new";
53
54 using namespace org_scilab_modules_scicos;
55
56 template<class Adaptor, class Adaptee>
57 types::InternalType * alloc_and_set(kind_t k, types::String* type_name, types::typed_list &in)
58 {
59     Controller controller;
60
61     // create the associated object
62     ScicosID o = controller.createObject(k);
63     Adaptor* adaptor = new Adaptor(controller, controller.getObject<Adaptee>(o));
64
65     // the first header entry is the type
66     for (int i = 1; i < (int)in.size(); i++)
67     {
68         std::string name (type_name->get(i));
69         if (!adaptor->setProperty(name, in[i], controller))
70         {
71             Scierror(999, _("%s: Wrong value for input argument #%d: unable to set \"%ls\".\n"), funame.data(), i, name.data());
72             delete adaptor;
73             return 0;
74         }
75     }
76
77     return adaptor;
78 }
79
80 template<class Adaptor, class Adaptee>
81 types::InternalType * alloc_and_set_as_tlist(types::String* type_name, types::typed_list &in)
82 {
83     // check header
84     // The default constructor should be implemented for this Adapter
85     Adaptor adaptor;
86     for (int i = 1; i < (int)in.size(); i++)
87     {
88         std::string name(type_name->get(i));
89         if (!adaptor.hasProperty(name))
90         {
91             Scierror(999, _("%s: Wrong value for input argument #%d: unable to set \"%ls\".\n"), funame.data(), i, name.data());
92             return 0;
93         }
94     }
95
96     // copy the data
97     types::TList* tlist = new types::TList();
98     tlist->set(0, type_name->clone());
99     for (int i = 1; i < (int)in.size(); i++)
100     {
101         tlist->set(i, in[i]);
102     }
103
104     return tlist;
105 }
106
107 template<class Adaptor, class Adaptee>
108 types::InternalType * alloc_and_set_as_mlist(types::String* type_name, types::typed_list &in)
109 {
110     // check header
111     // The default constructor should be implemented for this Adapter
112     Adaptor adaptor;
113     for (int i = 1; i < (int)in.size(); i++)
114     {
115         std::string name(type_name->get(i));
116         if (!adaptor.hasProperty(name))
117         {
118             Scierror(999, _("%s: Wrong value for input argument #%d: unable to set \"%ls\".\n"), funame.data(), i, name.data());
119             return 0;
120         }
121     }
122
123     // copy the data
124     types::MList* mlist = new types::MList();
125     mlist->set(0, type_name->clone());
126     for (int i = 1; i < (int)in.size(); i++)
127     {
128         mlist->set(i, in[i]);
129     }
130
131     return mlist;
132 }
133
134 static types::Function::ReturnValue allocate(types::typed_list &in, int _iRetCount, types::typed_list &out)
135 {
136     types::InternalType* type = in[0];
137
138     types::String* type_name = type->getAs<types::String>();
139     if (type_name->getRows() > 1)
140     {
141         Scierror(999, _("%s: Wrong size for input argument #%d: Row vector expected.\n"), funame.data(), 1);
142         return types::Function::Error;
143     }
144
145     if (type_name->getCols() != (int) in.size())
146     {
147         Scierror(999, _("%s: Wrong number of input argument: %d expected.\n"), funame.data(), type_name->getCols());
148         return types::Function::Error;
149     }
150
151     /*
152      * allocate the right adapter then try to set fields values
153      */
154
155     const view_scilab::Adapters::adapters_index_t adapter_index = view_scilab::Adapters::instance().lookup_by_typename(type_name->get(0));
156     types::InternalType* returnType;
157     switch (adapter_index)
158     {
159         case view_scilab::Adapters::BLOCK_ADAPTER:
160             returnType = alloc_and_set<view_scilab::BlockAdapter, model::Block>(BLOCK, type_name, in);
161             if (returnType == nullptr)
162             {
163                 return types::Function::Error;
164             }
165             break;
166         case view_scilab::Adapters::CPR_ADAPTER:
167             returnType = alloc_and_set_as_tlist<view_scilab::CprAdapter, model::Diagram>(type_name, in);
168             if (returnType == nullptr)
169             {
170                 return types::Function::Error;
171             }
172             break;
173         case view_scilab::Adapters::DIAGRAM_ADAPTER:
174             returnType = alloc_and_set<view_scilab::DiagramAdapter, model::Diagram>(DIAGRAM, type_name, in);
175             if (returnType == nullptr)
176             {
177                 return types::Function::Error;
178             }
179             break;
180         case view_scilab::Adapters::GRAPHIC_ADAPTER:
181             returnType = alloc_and_set_as_mlist<view_scilab::GraphicsAdapter, model::Block>(type_name, in);
182             if (returnType == nullptr)
183             {
184                 return types::Function::Error;
185             }
186             break;
187         case view_scilab::Adapters::LINK_ADAPTER:
188             returnType = alloc_and_set<view_scilab::LinkAdapter, model::Link>(LINK, type_name, in);
189             if (returnType == nullptr)
190             {
191                 return types::Function::Error;
192             }
193             break;
194         case view_scilab::Adapters::MODEL_ADAPTER:
195             returnType = alloc_and_set_as_mlist<view_scilab::ModelAdapter, model::Block>(type_name, in);
196             if (returnType == nullptr)
197             {
198                 return types::Function::Error;
199             }
200             break;
201         case view_scilab::Adapters::PARAMS_ADAPTER:
202             returnType = alloc_and_set_as_tlist<view_scilab::ParamsAdapter, model::Diagram>(type_name, in);
203             if (returnType == nullptr)
204             {
205                 return types::Function::Error;
206             }
207             break;
208         case view_scilab::Adapters::SCS_ADAPTER:
209             returnType = alloc_and_set<view_scilab::ScsAdapter, model::Diagram>(DIAGRAM, type_name, in);
210             if (returnType == nullptr)
211             {
212                 return types::Function::Error;
213             }
214             break;
215         case view_scilab::Adapters::STATE_ADAPTER:
216             returnType = alloc_and_set_as_tlist<view_scilab::StateAdapter, model::Diagram>(type_name, in);
217             if (returnType == nullptr)
218             {
219                 return types::Function::Error;
220             }
221             break;
222         case view_scilab::Adapters::TEXT_ADAPTER:
223             returnType = alloc_and_set<view_scilab::TextAdapter, model::Annotation>(ANNOTATION, type_name, in);
224             if (returnType == nullptr)
225             {
226                 return types::Function::Error;
227             }
228             break;
229         default:
230             Scierror(999, _("%s: Wrong value for input argument #%d:  \"%ls\" type is not managed.\n"), funame.data(), 1, type_name->get(0));
231             return types::Function::Error;
232     }
233     out.push_back(returnType);
234
235     return types::Function::OK;
236 }
237
238 static ScicosID get(types::GenericType* UIDs, int index)
239 {
240     ScicosID ret;
241
242     switch (UIDs->getType())
243     {
244         case types::InternalType::ScilabString:
245         {
246             std::istringstream iss(UIDs->getAs<types::String>()->get(index));
247             iss >> std::hex >> ret;
248             break;
249         }
250         case types::InternalType::ScilabInt64:
251             ret = UIDs->getAs<types::Int64>()->get(index);
252             break;
253         default:
254             ret = ScicosID();
255             break;
256     }
257
258     return ret;
259 }
260
261 static types::Function::ReturnValue get(types::GenericType* UIDs, int _iRetCount, types::typed_list &out)
262 {
263     if (UIDs->getSize() != _iRetCount)
264     {
265         Scierror(999, _("%s: Wrong size for input argument #%d: %dx%d expected.\n"), funame.data(), 1, _iRetCount, 1);
266         return types::Function::Error;
267     }
268
269
270     Controller controller;
271     types::Function::ReturnValue retValue = types::Function::OK;
272     for (int i = 0; i < _iRetCount; ++i)
273     {
274         ScicosID uid = get(UIDs, i);
275
276         // create the associated object
277         model::BaseObject* o = controller.getObject(uid);
278         if (o == nullptr)
279         {
280             Scierror(999, _("%s: Wrong value for input argument #%d: invalid UID.\n"), funame.data(), 1);
281             retValue = types::Function::Error;
282             break;
283         }
284
285         switch (o->kind())
286         {
287             case DIAGRAM:
288                 out.push_back(new view_scilab::DiagramAdapter(controller, static_cast<model::Diagram*>(controller.referenceObject(o))));
289                 break;
290             case BLOCK:
291                 out.push_back(new view_scilab::BlockAdapter(controller, static_cast<model::Block*>(controller.referenceObject(o))));
292                 break;
293             case LINK:
294                 out.push_back(new view_scilab::LinkAdapter(controller, static_cast<model::Link*>(controller.referenceObject(o))));
295                 break;
296             default:
297                 Scierror(999, _("%s: Wrong value for input argument #%d: not handled kind.\n"), funame.data(), 1);
298                 retValue = types::Function::Error;
299                 break;
300         }
301     }
302
303     if (retValue != types::Function::OK)
304     {
305         // something goes wrong, release the allocated data
306         for (types::typed_list::iterator it = out.begin(); it != out.end(); ++it)
307         {
308             delete *it;
309         }
310     }
311
312     return retValue;
313 }
314
315 types::Function::ReturnValue sci_scicos_new(types::typed_list &in, int _iRetCount, types::typed_list &out)
316 {
317     if (in.size() < 1)
318     {
319         Scierror(999, _("%s: Wrong number of input arguments: At least %d expected.\n"), funame.data(), 1);
320         return types::Function::Error;
321     }
322     if (_iRetCount > 1)
323     {
324         Scierror(999, _("%s: Wrong number of output arguments: %d expected.\n"), funame.data(), 1);
325         return types::Function::Error;
326     }
327
328     types::InternalType* type = in[0];
329     switch (type->getType())
330     {
331         case types::InternalType::ScilabString:
332             if (in.size() == 1)
333             {
334                 return get(type->getAs<types::String>(), _iRetCount, out);
335             }
336             else
337             {
338                 return allocate(in, _iRetCount, out);
339             }
340         case types::InternalType::ScilabInt64:
341             return get(type->getAs<types::Int64>(), _iRetCount, out);
342         default:
343             Scierror(999, _("%s: Wrong type for input argument #%d: String or ID expected.\n"), funame.data(), 1);
344             return types::Function::Error;
345     }
346 }
347