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
27Object::Object(bool preserveInsOrder):
28 _preserveInsOrder(preserveInsOrder),
29 _modified(false)
30{
31}
32
33
34Object::Object(const Object& copy) : _values(copy._values),
35 _preserveInsOrder(copy._preserveInsOrder),
36 _pStruct(!copy._modified ? copy._pStruct : 0),
37 _modified(copy._modified)
38{
39 if (_preserveInsOrder)
40 {
41 // need to update pointers in _keys to point to copied _values
42 for (KeyPtrList::const_iterator it = copy._keys.begin(); it != copy._keys.end(); ++it)
43 {
44 ValueMap::const_iterator itv = _values.find(**it);
45 poco_assert (itv != _values.end());
46 _keys.push_back(&itv->first);
47 }
48 }
49}
50
51
52Object::Object(Object&& other) :
53 _values(std::move(other._values)),
54 _keys(std::move(other._keys)),
55 _preserveInsOrder(other._preserveInsOrder),
56 _pStruct(!other._modified ? other._pStruct : 0),
57 _modified(other._modified)
58{
59}
60
61
62Object::~Object()
63{
64}
65
66
67Object &Object::operator= (const Object &other)
68{
69 if (&other != this)
70 {
71 _values = other._values;
72 _keys = other._keys;
73 _preserveInsOrder = other._preserveInsOrder;
74 _pStruct = !other._modified ? other._pStruct : 0;
75 _modified = other._modified;
76 }
77 return *this;
78}
79
80
81Object &Object::operator= (Object &&other)
82{
83 if (&other != this)
84 {
85 _values = std::move(other._values);
86 _keys = std::move(other._keys);
87 _preserveInsOrder = other._preserveInsOrder;
88 _pStruct = !other._modified ? other._pStruct : 0;
89 _modified = other._modified;
90 }
91 return *this;
92}
93
94
95Var Object::get(const std::string& key) const
96{
97 ValueMap::const_iterator it = _values.find(key);
98 if (it != _values.end())
99 {
100 return it->second;
101 }
102
103 return Var();
104}
105
106
107Array::Ptr Object::getArray(const std::string& key) const
108{
109 ValueMap::const_iterator it = _values.find(key);
110 if ((it != _values.end()) && (it->second.type() == typeid(Array::Ptr)))
111 {
112 return it->second.extract<Array::Ptr>();
113 }
114
115 return 0;
116}
117
118
119Object::Ptr Object::getObject(const std::string& key) const
120{
121 ValueMap::const_iterator it = _values.find(key);
122 if ((it != _values.end()) && (it->second.type() == typeid(Object::Ptr)))
123 {
124 return it->second.extract<Object::Ptr>();
125 }
126
127 return 0;
128}
129
130
131void Object::getNames(std::vector<std::string>& names) const
132{
133 names.clear();
134 for (ValueMap::const_iterator it = _values.begin(); it != _values.end(); ++it)
135 {
136 names.push_back(it->first);
137 }
138}
139
140
141void Object::stringify(std::ostream& out, unsigned int indent, int step) const
142{
143 if (step < 0) step = indent;
144
145 if (!_preserveInsOrder)
146 doStringify(_values, out, indent, step);
147 else
148 doStringify(_keys, out, indent, step);
149}
150
151
152const std::string& Object::getKey(KeyPtrList::const_iterator& iter) const
153{
154 ValueMap::const_iterator it = _values.begin();
155 ValueMap::const_iterator end = _values.end();
156 for (; it != end; ++it)
157 {
158 if (it->first == **iter) return it->first;
159 }
160
161 throw NotFoundException(**iter);
162}
163
164
165void Object::set(const std::string& key, const Dynamic::Var& value)
166{
167 std::pair<ValueMap::iterator, bool> ret = _values.insert(ValueMap::value_type(key, value));
168 if (!ret.second) ret.first->second = value;
169 if (_preserveInsOrder)
170 {
171 KeyPtrList::iterator it = _keys.begin();
172 KeyPtrList::iterator end = _keys.end();
173 for (; it != end; ++it)
174 {
175 if (key == **it) return;
176 }
177 _keys.push_back(&ret.first->first);
178 }
179 _modified = true;
180}
181
182
183Poco::DynamicStruct Object::makeStruct(const Object::Ptr& obj)
184{
185 Poco::DynamicStruct ds;
186
187 ConstIterator it = obj->begin();
188 ConstIterator end = obj->end();
189 for (; it != end; ++it)
190 {
191 if (obj->isObject(it))
192 {
193 Object::Ptr pObj = obj->getObject(it->first);
194 DynamicStruct str = makeStruct(pObj);
195 ds.insert(it->first, str);
196 }
197 else if (obj->isArray(it))
198 {
199 Array::Ptr pArr = obj->getArray(it->first);
200 std::vector<Poco::Dynamic::Var> v = Poco::JSON::Array::makeArray(pArr);
201 ds.insert(it->first, v);
202 }
203 else
204 ds.insert(it->first, it->second);
205 }
206
207 return ds;
208}
209
210
211void Object::resetDynStruct() const
212{
213 if (!_pStruct)
214 _pStruct = new Poco::DynamicStruct;
215 else
216 _pStruct->clear();
217}
218
219
220Object::operator const Poco::DynamicStruct& () const
221{
222 if (!_values.size())
223 {
224 resetDynStruct();
225 }
226 else if (_modified)
227 {
228 ValueMap::const_iterator it = _values.begin();
229 ValueMap::const_iterator end = _values.end();
230 resetDynStruct();
231 for (; it != end; ++it)
232 {
233 if (isObject(it))
234 {
235 _pStruct->insert(it->first, makeStruct(getObject(it->first)));
236 }
237 else if (isArray(it))
238 {
239 _pStruct->insert(it->first, Poco::JSON::Array::makeArray(getArray(it->first)));
240 }
241 else
242 {
243 _pStruct->insert(it->first, it->second);
244 }
245 }
246 }
247
248 return *_pStruct;
249}
250
251
252void Object::clear()
253{
254 _values.clear();
255 _keys.clear();
256 _pStruct = 0;
257 _modified = true;
258}
259
260
261} } // namespace Poco::JSON
262