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