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