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