Merge remote-tracking branch 'origin/master' into jit
[scilab.git] / scilab / modules / ast / src / cpp / types / singlestruct.cpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2011 - 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 <sstream>
14 #include "symbol.hxx"
15 #include "singlestruct.hxx"
16 #include "string.hxx"
17 #include "double.hxx"
18 #include "localization.hxx"
19 #include "scilabWrite.hxx"
20
21 namespace types
22 {
23 SingleStruct::SingleStruct()
24 {
25 #ifndef NDEBUG
26     Inspector::addItem(this);
27 #endif
28 }
29
30 SingleStruct::~SingleStruct()
31 {
32     if (isDeletable() == true)
33     {
34         for (auto data : m_Data)
35         {
36             data->DecreaseRef();
37             data->killMe();
38         }
39     }
40 #ifndef NDEBUG
41     Inspector::removeItem(this);
42 #endif
43 }
44
45 SingleStruct::SingleStruct(SingleStruct *_oSingleStructCopyMe) : m_wstFields(_oSingleStructCopyMe->getFields()), m_Data(_oSingleStructCopyMe->getData())
46 {
47     for (auto data : m_Data)
48     {
49         data->IncreaseRef();
50     }
51 #ifndef NDEBUG
52     Inspector::addItem(this);
53 #endif
54 }
55
56 std::vector<InternalType *> & SingleStruct::getData()
57 {
58     return m_Data;
59 }
60
61 std::unordered_map<std::wstring, int> & SingleStruct::getFields()
62 {
63     return m_wstFields;
64 }
65
66 int SingleStruct::getFieldIndex(const std::wstring & _field)
67 {
68     const auto i = m_wstFields.find(_field);
69     if (i != m_wstFields.end())
70     {
71         return i->second;
72     }
73
74     return -1;
75 }
76
77 bool SingleStruct::set(const std::wstring& _sKey, InternalType *_typedValue)
78 {
79     const int index = getFieldIndex(_sKey);
80     if (index == -1)
81     {
82         return false;
83     }
84
85     InternalType* pOld = m_Data[index];
86     if (pOld != _typedValue)
87     {
88         /* Look if we are replacing some existing value */
89         if (pOld != nullptr)
90         {
91             pOld->DecreaseRef();
92             pOld->killMe();
93         }
94
95         if (_typedValue)
96         {
97             _typedValue->IncreaseRef();
98             m_Data[index] = _typedValue;
99         }
100         else
101         {
102             m_Data[index] = nullptr;
103         }
104     }
105     return true;
106 }
107
108
109 InternalType* SingleStruct::get(const std::wstring& _sKey)
110 {
111     int index = getFieldIndex(_sKey);
112     if (index == -1)
113     {
114         return nullptr;
115     }
116
117     return m_Data[index];
118 }
119
120 bool SingleStruct::exists(const std::wstring& _sKey)
121 {
122     return (getFieldIndex(_sKey) != -1);
123 }
124
125 SingleStruct* SingleStruct::clone()
126 {
127     return new SingleStruct(this);
128 }
129
130 InternalType* SingleStruct::insert(typed_list* _pArgs, InternalType* _pSource)
131 {
132     //check input param
133     if (_pArgs->size() != 1)
134     {
135         std::wostringstream os;
136         os << _W("Unable to insert multiple item in a struct.\n");
137         throw ast::InternalError(os.str());
138     }
139
140     if ((*_pArgs)[0]->isString() == false)
141     {
142         std::wostringstream os;
143         os << _W("Assignment between unlike types is not allowed.\n");
144         throw ast::InternalError(os.str());
145     }
146
147     String* pstKey = (*_pArgs)[0]->getAs<String>();
148     for (int i = 0 ; i < pstKey->getSize() ; ++i)
149     {
150         set(pstKey->get(i), _pSource);
151     }
152
153     return this;
154 }
155
156 std::vector<InternalType*> SingleStruct::extract(std::vector<std::wstring> & _stFields)
157 {
158     std::vector<InternalType*> Result;
159
160     for (const auto & f : _stFields)
161     {
162         if (!exists(f))
163         {
164             return Result;
165         }
166     }
167
168     for (const auto & f : _stFields)
169     {
170         Result.push_back(get(f));
171     }
172
173     return Result;
174 }
175
176 String* SingleStruct::getFieldNames()
177 {
178     String* pOut = new String((int)m_wstFields.size(), 1);
179     for (const auto & field : m_wstFields)
180     {
181         pOut->set(field.second, field.first.data());
182     }
183     return pOut;
184 }
185
186 bool SingleStruct::removeField(const std::wstring & _sKey)
187 {
188     const auto i = m_wstFields.find(_sKey);
189     if (i != m_wstFields.end())
190     {
191         const int pos = i->second;
192         m_Data[pos]->DecreaseRef();
193         m_Data[pos]->killMe();
194         m_wstFields.erase(i);
195
196         for (auto & p : m_wstFields)
197         {
198             if (p.second > pos)
199             {
200                 --p.second;
201             }
202         }
203
204         m_Data.erase(m_Data.begin() + pos);
205     }
206
207     return true;
208 }
209
210 bool SingleStruct::addField(const std::wstring& _sKey)
211 {
212     if (exists(_sKey))
213     {
214         //field already exists, do nothing and return false
215         return false;
216     }
217
218     //not found so add field with []
219     InternalType* pIT = Double::Empty();
220     pIT->IncreaseRef();
221     m_Data.push_back(pIT);
222     m_wstFields.emplace(_sKey, m_Data.size() - 1);
223
224     return true;
225 }
226
227 bool SingleStruct::addFieldFront(const std::wstring& _sKey)
228 {
229     if (exists(_sKey))
230     {
231         //field already exists, do nothing and return false
232         return false;
233     }
234
235     //not found so add field with []
236     InternalType* pIT = Double::Empty();
237     pIT->IncreaseRef();
238     m_Data.insert(m_Data.begin(), pIT);
239
240     for (auto & p : m_wstFields)
241     {
242         p.second++;
243     }
244
245     m_wstFields.emplace(_sKey, 0);
246     return true;
247 }
248
249 bool SingleStruct::toString(std::wostringstream& ostr)
250 {
251     if (m_Data.size() == 0)
252     {
253         ostr << L"empty SingleStruct";
254         return true;
255     }
256     else
257     {
258
259         for (auto & p : m_wstFields)
260         {
261             ostr << p.first << L" : " << m_Data[p.second]->getTypeStr() << std::endl;
262         }
263     }
264
265     return true;
266 }
267
268 bool SingleStruct::operator==(const InternalType& it)
269 {
270     if (const_cast<InternalType &>(it).isSingleStruct() == false)
271     {
272         return false;
273     }
274
275     SingleStruct* other = const_cast<InternalType &>(it).getAs<SingleStruct>();
276
277     std::unordered_map<std::wstring, int> & otherFieldNames = other->getFields();
278     std::vector<InternalType*> & otherFieldData = other->getData();
279
280     if (m_wstFields.size() != otherFieldNames.size())
281     {
282         return false;
283     }
284
285     for (const auto & p : m_wstFields)
286     {
287         const auto i = otherFieldNames.find(p.first);
288         if (i == otherFieldNames.end() || (*m_Data[p.second] != *otherFieldData[i->second]))
289         {
290             return false;
291         }
292     }
293
294     return true;
295 }
296
297 bool SingleStruct::operator!=(const InternalType& it)
298 {
299     return !(*this == it);
300 }
301 }