1//
2// Object.cpp
3//
4// Library: JSON
5// Package: JSON
6// Module: Object
7//
8// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/JSON/Object.h"
16#include <iostream>
17#include <sstream>
18
19
20using Poco::Dynamic::Var;
21
22
23namespace Poco {
24namespace JSON {
25
26
27
28Object::Object(int options):
29 _preserveInsOrder(options & Poco::JSON_PRESERVE_KEY_ORDER),
30 _escapeUnicode(options & Poco::JSON_ESCAPE_UNICODE),
31 _modified(false)
32{
33}
34
35
36Object::Object(const Object& other) : _values(other._values),
37 _preserveInsOrder(other._preserveInsOrder),
38 _escapeUnicode(other._escapeUnicode),
39 _pStruct(!other._modified ? other._pStruct : 0),
40 _modified(other._modified)
41{
42 syncKeys(other._keys);
43}
44
45
46Object::Object(Object&& other) :
47 _values(std::move(other._values)),
48 _keys(std::move(other._keys)),
49 _preserveInsOrder(other._preserveInsOrder),
50 _escapeUnicode(other._escapeUnicode),
51 _pStruct(!other._modified ? other._pStruct : 0),
52 _modified(other._modified)
53{
54 other.clear();
55}
56
57
58Object::~Object()
59{
60}
61
62
63Object &Object::operator= (const Object &other)
64{
65 if (&other != this)
66 {
67 _values = other._values;
68 _preserveInsOrder = other._preserveInsOrder;
69 syncKeys(other._keys);
70 _escapeUnicode = other._escapeUnicode;
71 _pStruct = !other._modified ? other._pStruct : 0;
72 _modified = other._modified;
73 }
74 return *this;
75}
76
77
78Object &Object::operator= (Object &&other)
79{
80 if (&other != this)
81 {
82 _values = std::move(other._values);
83 _keys = std::move(other._keys);
84 _preserveInsOrder = other._preserveInsOrder;
85 _escapeUnicode = other._escapeUnicode;
86 _pStruct = !other._modified ? other._pStruct : 0;
87 _modified = other._modified;
88 other.clear();
89 }
90 return *this;
91}
92
93
94void Object::syncKeys(const KeyList& keys)
95{
96 if(_preserveInsOrder)
97 {
98 // update iterators in _keys to point to copied _values
99 for(KeyList::const_iterator it = keys.begin(); it != keys.end(); ++it)
100 {
101 ValueMap::const_iterator itv = _values.find((*it)->first);
102 poco_assert (itv != _values.end());
103 _keys.push_back(itv);
104 }
105 }
106}
107
108
109Var Object::get(const std::string& key) const
110{
111 ValueMap::const_iterator it = _values.find(key);
112 if (it != _values.end())
113 {
114 return it->second;
115 }
116
117 return Var();
118}
119
120
121Array::Ptr Object::getArray(const std::string& key) const
122{
123 ValueMap::const_iterator it = _values.find(key);
124 if ((it != _values.end()) && (it->second.type() == typeid(Array::Ptr)))
125 {
126 return it->second.extract<Array::Ptr>();
127 }
128
129 return 0;
130}
131
132
133Object::Ptr Object::getObject(const std::string& key) const
134{
135 ValueMap::const_iterator it = _values.find(key);
136 if ((it != _values.end()) && (it->second.type() == typeid(Object::Ptr)))
137 {
138 return it->second.extract<Object::Ptr>();
139 }
140
141 return 0;
142}
143
144
145void Object::getNames(NameList& names) const
146{
147 names.clear();
148 if (_preserveInsOrder)
149 {
150 for(KeyList::const_iterator it = _keys.begin(); it != _keys.end(); ++it)
151 {
152 names.push_back((*it)->first);
153 }
154 }
155 else
156 {
157 for(ValueMap::const_iterator it = _values.begin(); it != _values.end(); ++it)
158 {
159 names.push_back(it->first);
160 }
161 }
162}
163
164
165Object::NameList Object::getNames() const
166{
167 NameList names;
168 getNames(names);
169 return names;
170}
171
172
173void Object::stringify(std::ostream& out, unsigned int indent, int step) const
174{
175 if (step < 0) step = indent;
176
177 if (!_preserveInsOrder)
178 doStringify(_values, out, indent, step);
179 else
180 doStringify(_keys, out, indent, step);
181}
182
183
184const std::string& Object::getKey(KeyList::const_iterator& iter) const
185{
186 ValueMap::const_iterator it = _values.begin();
187 ValueMap::const_iterator end = _values.end();
188 for (; it != end; ++it)
189 {
190 if (it == *iter) return it->first;
191 }
192
193 throw NotFoundException((*iter)->first);
194}
195
196
197Object& Object::set(const std::string& key, const Dynamic::Var& value)
198{
199 std::pair<ValueMap::iterator, bool> ret = _values.insert(ValueMap::value_type(key, value));
200 if (!ret.second) ret.first->second = value;
201 if (_preserveInsOrder)
202 {
203 KeyList::iterator it = _keys.begin();
204 KeyList::iterator end = _keys.end();
205 for (; it != end; ++it)
206 {
207 if (key == (*it)->first) return *this;
208 }
209 _keys.push_back(ret.first);
210 }
211 _modified = true;
212 return *this;
213}
214
215
216Poco::DynamicStruct Object::makeStruct(const Object::Ptr& obj)
217{
218 return makeStructImpl<Poco::DynamicStruct>(obj);
219}
220
221
222#ifdef POCO_ENABLE_CPP11
223
224
225Poco::OrderedDynamicStruct Object::makeOrderedStruct(const Object::Ptr& obj)
226{
227 return makeStructImpl<Poco::OrderedDynamicStruct>(obj);
228}
229
230/*
231void Object::resetOrdDynStruct() const
232{
233 if (!_pOrdStruct)
234 _pOrdStruct = new Poco::OrderedDynamicStruct;
235 else
236 _pOrdStruct->clear();
237}
238*/
239
240#endif // POCO_ENABLE_CPP11
241
242/*
243void Object::resetDynStruct() const
244{
245 if (!_pStruct)
246 _pStruct = new Poco::DynamicStruct;
247 else
248 _pStruct->clear();
249}*/
250
251
252Object::operator const Poco::DynamicStruct& () const
253{
254 if (!_values.size())
255 {
256 resetDynStruct(_pStruct);
257 }
258 else if (_modified)
259 {
260 ValueMap::const_iterator it = _values.begin();
261 ValueMap::const_iterator end = _values.end();
262 resetDynStruct(_pStruct);
263 for (; it != end; ++it)
264 {
265 if (isObject(it))
266 {
267 _pStruct->insert(it->first, makeStruct(getObject(it->first)));
268 }
269 else if (isArray(it))
270 {
271 _pStruct->insert(it->first, Poco::JSON::Array::makeArray(getArray(it->first)));
272 }
273 else
274 {
275 _pStruct->insert(it->first, it->second);
276 }
277 }
278 }
279
280 return *_pStruct;
281}
282
283
284#ifdef POCO_ENABLE_CPP11
285
286
287Object::operator const Poco::OrderedDynamicStruct& () const
288{
289 if (!_values.size())
290 {
291 resetDynStruct(_pOrdStruct);
292 }
293 else if (_modified)
294 {
295 if (_preserveInsOrder)
296 {
297 KeyList::const_iterator it = _keys.begin();
298 KeyList::const_iterator end = _keys.end();
299 resetDynStruct(_pOrdStruct);
300 for (; it != end; ++it)
301 {
302 if (isObject((*it)->first))
303 {
304 _pOrdStruct->insert((*it)->first, makeOrderedStruct(getObject((*it)->first)));
305 }
306 else if (isArray((*it)->first))
307 {
308 _pOrdStruct->insert((*it)->first, Poco::JSON::Array::makeArray(getArray((*it)->first)));
309 }
310 else
311 {
312 _pOrdStruct->insert((*it)->first, (*it)->second);
313 }
314 }
315 }
316 else
317 {
318 ValueMap::const_iterator it = _values.begin();
319 ValueMap::const_iterator end = _values.end();
320 resetDynStruct(_pOrdStruct);
321 for (; it != end; ++it)
322 {
323 if (isObject(it))
324 {
325 _pOrdStruct->insert(it->first, makeOrderedStruct(getObject(it->first)));
326 }
327 else if (isArray(it))
328 {
329 _pOrdStruct->insert(it->first, Poco::JSON::Array::makeArray(getArray(it->first)));
330 }
331 else
332 {
333 _pOrdStruct->insert(it->first, it->second);
334 }
335 }
336 }
337 }
338
339 return *_pOrdStruct;
340}
341
342
343#endif // POCO_ENABLE_CPP11
344
345
346void Object::clear()
347{
348 _values.clear();
349 _keys.clear();
350 _pStruct = 0;
351 _modified = true;
352}
353
354
355} } // namespace Poco::JSON
356