024a69933062ad89b77ee8cb9b928a0b71411d1e
[scilab.git] / scilab / modules / ast / src / cpp / types / tlist.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2010-2010 - DIGITEO - Antoine ELIAS
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-en.txt
10  *
11  */
12
13 #include <cstring>
14 #include <sstream>
15 #include "string.hxx"
16 #include "list.hxx"
17 #include "tlist.hxx"
18 #include "listundefined.hxx"
19 #include "callable.hxx"
20 #include "overload.hxx"
21 #include "execvisitor.hxx"
22
23 #ifndef NDEBUG
24 #include "inspector.hxx"
25 #endif
26
27 extern "C"
28 {
29 #include "os_string.h"
30 }
31
32 namespace types
33 {
34 /**
35 ** Constructor & Destructor (public)
36 */
37 TList::TList() : List()
38 {
39 #ifndef NDEBUG
40     Inspector::addItem(this);
41 #endif
42 }
43
44 TList::~TList()
45 {
46 #ifndef NDEBUG
47     Inspector::removeItem(this);
48 #endif
49 }
50
51 /**
52 ** Clone
53 ** Create a new List and Copy all values.
54 */
55 InternalType* TList::clone()
56 {
57     return new TList(this);
58 }
59
60 bool TList::exists(const std::wstring& _sKey)
61 {
62     if (getSize() < 1)
63     {
64         return false;
65     }
66
67     String* pS = getFieldNames();
68
69     //first field is the tlist type
70     for (int i = 1 ; i < pS->getSize() ; i++)
71     {
72         if (wcscmp(pS->get(i), _sKey.c_str()) == 0)
73         {
74             return true;
75         }
76     }
77     return false;
78 }
79
80 bool TList::invoke(typed_list & in, optional_list & /*opt*/, int _iRetCount, typed_list & out, ast::ConstVisitor & execFunc, const ast::Exp & /*e*/)
81 {
82     if (in.size() == 0)
83     {
84         out.push_back(this);
85         return true;
86     }
87     else if (in.size() == 1)
88     {
89         InternalType * arg = in[0];
90         InternalType * _out = NULL;
91         if (arg->isDouble() || arg->isInt() || arg->isBool() || arg->isImplicitList() || arg->isColon() || arg->isDollar())
92         {
93             _out = List::extract(&in);
94             if (_out == NULL)
95             {
96                 // invalid index
97                 return false;
98             }
99
100             List* pList = _out->getAs<types::List>();
101             for (int i = 0; i < pList->getSize(); i++)
102             {
103                 out.push_back(pList->get(i));
104             }
105
106             delete pList;
107         }
108         else if (arg->isString())
109         {
110             std::list<std::wstring> stFields;
111             String * pString = arg->getAs<types::String>();
112             for (int i = 0; i < pString->getSize(); ++i)
113             {
114                 stFields.push_back(pString->get(i));
115             }
116
117             _out = extractStrings(stFields);
118             if (_out == NULL)
119             {
120                 // invalid index
121                 return false;
122             }
123
124             List* pList = _out->getAs<types::List>();
125             for (int i = 0; i < pList->getSize(); i++)
126             {
127                 out.push_back(pList->get(i));
128             }
129
130             delete pList;
131         }
132
133         if (out.empty() == false)
134         {
135             return true;
136         }
137     }
138
139     Callable::ReturnValue ret;
140     // Overload of extraction need
141     // the tlist from where we extract
142     this->IncreaseRef();
143     in.push_back(this);
144
145     std::wstring stType = getShortTypeStr();
146     try
147     {
148         ret = Overload::call(L"%" + stType + L"_e", in, _iRetCount, out, &execFunc);
149     }
150     catch (ast::ScilabError &se)
151     {
152         try
153         {
154             //to compatibility with scilab 5 code.
155             //tlist/mlist name are truncated to 8 first character
156             if (stType.size() > 8)
157             {
158                 std::wcout << (L"%" + stType.substr(0, 8) + L"_e") << std::endl;
159                 ret = Overload::call(L"%" + stType.substr(0, 8) + L"_e", in, 1, out, &execFunc);
160             }
161             else
162             {
163                 throw se;
164             }
165         }
166         catch (ast::ScilabError & /*se*/)
167         {
168             ret = Overload::call(L"%l_e", in, 1, out, &execFunc);
169         }
170     }
171
172     // Remove this from "in" for keep "in" unchanged.
173     this->DecreaseRef();
174     in.pop_back();
175
176     if (ret == Callable::Error)
177     {
178         throw ast::ScilabError();
179     }
180
181     return true;
182 }
183
184 bool TList::extract(const std::wstring & name, InternalType *& out)
185 {
186     if (exists(name))
187     {
188         out = getField(name);
189         return true;
190     }
191
192     return false;
193 }
194
195 InternalType* TList::getField(const std::wstring& _sKey)
196 {
197     return List::get(getIndexFromString(_sKey));
198 }
199
200 int TList::getIndexFromString(const std::wstring& _sKey)
201 {
202     if (getSize() < 1)
203     {
204         return -1;
205     }
206
207     String* pS = getFieldNames();
208     //first field is the tlist type
209     for (int i = 1 ; i < pS->getSize() ; i++)
210     {
211         if (wcscmp(pS->get(i), _sKey.c_str()) == 0)
212         {
213             return i;
214         }
215     }
216     return -1;
217 }
218
219 InternalType* TList::extractStrings(const std::list<std::wstring>& _stFields)
220 {
221     int i = 0;
222     List* pLResult = new List();
223     std::list<std::wstring>::const_iterator it;
224     for (it = _stFields.begin() ; it != _stFields.end() ; it++)
225     {
226         if (exists(*it) == false)
227         {
228             return pLResult;
229         }
230     }
231
232     for (it = _stFields.begin() ; it != _stFields.end() ; it++, i++)
233     {
234         InternalType* pIT = getField(*it);
235         if (pIT == NULL)
236         {
237             delete pLResult;
238             return NULL;
239         }
240
241         pLResult->set(i, pIT);
242     }
243
244     return pLResult;
245 }
246
247 std::wstring TList::getTypeStr()
248 {
249     if (getSize() < 1)
250     {
251         return L"";
252     }
253
254     return getFieldNames()->get(0);
255 }
256
257 std::wstring TList::getShortTypeStr()
258 {
259     return getTypeStr();
260 }
261
262 bool TList::set(const std::wstring& _sKey, InternalType* _pIT)
263 {
264     return List::set(getIndexFromString(_sKey), _pIT);
265 }
266
267 bool TList::set(const int _iIndex, InternalType* _pIT)
268 {
269     return List::set(_iIndex, _pIT);
270 }
271
272 String* TList::getFieldNames()
273 {
274     return (*m_plData)[0]->getAs<types::String>();
275 }
276
277 /**
278 ** toString to display TLists
279 */
280 bool TList::toString(std::wostringstream& ostr)
281 {
282     //call overload %type_p if exists
283     types::typed_list in;
284     types::typed_list out;
285     ast::ExecVisitor exec;
286
287     IncreaseRef();
288     in.push_back(this);
289
290     try
291     {
292         if (Overload::generateNameAndCall(L"p", in, 1, out, &exec) == Function::Error)
293         {
294             ConfigVariable::setError();
295         }
296
297         ostr.str(L"");
298         DecreaseRef();
299         return true;
300     }
301     catch (ast::ScilabError /* &e */)
302     {
303         // avoid error message about undefined overload %type_p
304         ConfigVariable::resetError();
305     }
306
307     DecreaseRef();
308
309     // special case for lss
310     if (getSize() != 0 &&
311             (*m_plData)[0]->isString() &&
312             (*m_plData)[0]->getAs<types::String>()->getSize() > 0 &&
313             wcscmp((*m_plData)[0]->getAs<types::String>()->get(0), L"lss") == 0)
314     {
315         wchar_t* wcsVarName = os_wcsdup(ostr.str().c_str());
316         int iPosition = 1;
317         const wchar_t * wcsDesc[7] = {L"  (state-space system:)", L"= A matrix =", L"= B matrix =", L"= C matrix =", L"= D matrix =", L"= X0 (initial state) =", L"= Time domain ="};
318         for (auto val : *m_plData)
319         {
320             std::wostringstream nextVarName;
321             ostr.str(L"");
322             nextVarName << " " << wcsVarName << L"(" << iPosition << L")";
323             ostr << std::endl << nextVarName.str() << wcsDesc[iPosition - 1] << std::endl << std::endl;
324             scilabWriteW(ostr.str().c_str());
325             VariableToString(val, nextVarName.str().c_str());
326             iPosition++;
327         }
328         ostr.str(L"");
329         free(wcsVarName);
330         return true;
331     }
332
333     // call normal toString
334     return List::toString(ostr);
335 }
336 } // end namespace types