List extraction fixed.
[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_wcsdup.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::CallExp & /*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     try
146     {
147         ret = Overload::call(L"%" + getShortTypeStr() + L"_e", in, 1, out, &execFunc);
148     }
149     catch (ast::ScilabError & /*se*/)
150     {
151         ret = Overload::call(L"%l_e", in, 1, out, &execFunc);
152     }
153
154     // Remove this from "in" for keep "in" unchanged.
155     this->DecreaseRef();
156     in.pop_back();
157
158     if (ret == Callable::Error)
159     {
160         throw ast::ScilabError();
161     }
162
163     return true;
164 }
165
166 bool TList::extract(const std::wstring & name, InternalType *& out)
167 {
168     if (exists(name))
169     {
170         out = getField(name);
171         return true;
172     }
173
174     return false;
175 }
176
177 InternalType* TList::getField(const std::wstring& _sKey)
178 {
179     return List::get(getIndexFromString(_sKey));
180 }
181
182 int TList::getIndexFromString(const std::wstring& _sKey)
183 {
184     if (getSize() < 1)
185     {
186         return -1;
187     }
188
189     String* pS = getFieldNames();
190     //first field is the tlist type
191     for (int i = 1 ; i < pS->getSize() ; i++)
192     {
193         if (wcscmp(pS->get(i), _sKey.c_str()) == 0)
194         {
195             return i;
196         }
197     }
198     return -1;
199 }
200
201 InternalType* TList::extractStrings(const std::list<std::wstring>& _stFields)
202 {
203     int i = 0;
204     List* pLResult = new List();
205     std::list<std::wstring>::const_iterator it;
206     for (it = _stFields.begin() ; it != _stFields.end() ; it++)
207     {
208         if (exists(*it) == false)
209         {
210             return pLResult;
211         }
212     }
213
214     for (it = _stFields.begin() ; it != _stFields.end() ; it++, i++)
215     {
216         InternalType* pIT = getField(*it);
217         if (pIT == NULL)
218         {
219             delete pLResult;
220             return NULL;
221         }
222
223         pLResult->set(i, pIT);
224     }
225
226     return pLResult;
227 }
228
229 std::wstring TList::getTypeStr()
230 {
231     if (getSize() < 1)
232     {
233         return L"";
234     }
235
236     return getFieldNames()->get(0);
237 }
238
239 std::wstring TList::getShortTypeStr()
240 {
241     return getTypeStr();
242 }
243
244 bool TList::set(const std::wstring& _sKey, InternalType* _pIT)
245 {
246     return List::set(getIndexFromString(_sKey), _pIT);
247 }
248
249 bool TList::set(const int _iIndex, InternalType* _pIT)
250 {
251     return List::set(_iIndex, _pIT);
252 }
253
254 String* TList::getFieldNames()
255 {
256     return (*m_plData)[0]->getAs<types::String>();
257 }
258
259 /**
260 ** toString to display TLists
261 */
262 bool TList::toString(std::wostringstream& ostr)
263 {
264     //call overload %type_p if exists
265     types::typed_list in;
266     types::typed_list out;
267     ast::ExecVisitor* exec = new ast::ExecVisitor();
268
269     IncreaseRef();
270     in.push_back(this);
271
272     try
273     {
274         if (Overload::generateNameAndCall(L"p", in, 1, out, exec) == Function::OK)
275         {
276             ostr.str(L"");
277             DecreaseRef();
278             delete exec;
279             return true;
280         }
281     }
282     catch (ast::ScilabError /* &e */)
283     {
284         // avoid error message about undefined overload %type_p
285     }
286
287     DecreaseRef();
288     delete exec;
289
290     // special case for lss
291     if (getSize() != 0 &&
292             (*m_plData)[0]->isString() &&
293             (*m_plData)[0]->getAs<types::String>()->getSize() > 0 &&
294             wcscmp((*m_plData)[0]->getAs<types::String>()->get(0), L"lss") == 0)
295     {
296         wchar_t* wcsVarName = os_wcsdup(ostr.str().c_str());
297         int iPosition = 1;
298         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 ="};
299         std::vector<InternalType *>::iterator itValues;
300         for (itValues = m_plData->begin() ; itValues != m_plData->end() ; ++itValues, ++iPosition)
301         {
302             std::wostringstream nextVarName;
303             ostr.str(L"");
304             nextVarName << " " << wcsVarName << L"(" << iPosition << L")";
305             ostr << std::endl << nextVarName.str() << wcsDesc[iPosition - 1] << std::endl << std::endl;
306             scilabWriteW(ostr.str().c_str());
307             VariableToString(*itValues, nextVarName.str().c_str());
308         }
309
310         free(wcsVarName);
311         return true;
312     }
313
314     // call normal toString
315     return List::toString(ostr);
316 }
317 } // end namespace types