1 | // |
2 | // Array.cpp |
3 | // |
4 | // Library: JSON |
5 | // Package: JSON |
6 | // Module: Array |
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/Array.h" |
16 | #include "Poco/JSON/Object.h" |
17 | #include "Poco/JSON/Stringifier.h" |
18 | #include "Poco/JSONString.h" |
19 | |
20 | |
21 | using Poco::Dynamic::Var; |
22 | |
23 | |
24 | namespace Poco { |
25 | namespace JSON { |
26 | |
27 | |
28 | Array::Array(int options): _modified(false), |
29 | _escapeUnicode(options & Poco::JSON_ESCAPE_UNICODE) |
30 | { |
31 | } |
32 | |
33 | |
34 | Array::Array(const Array& other) : _values(other._values), |
35 | _pArray(other._pArray), |
36 | _modified(other._modified) |
37 | { |
38 | } |
39 | |
40 | |
41 | Array::Array(Array&& other) : |
42 | _values(std::move(other._values)), |
43 | _pArray(!other._modified ? other._pArray : 0), |
44 | _modified(other._modified) |
45 | { |
46 | _pArray = 0; |
47 | } |
48 | |
49 | |
50 | Array &Array::operator=(const Array& other) |
51 | { |
52 | if (&other != this) |
53 | { |
54 | _values = other._values; |
55 | _pArray = other._pArray; |
56 | _modified = other._modified; |
57 | } |
58 | return *this; |
59 | } |
60 | |
61 | |
62 | Array &Array::operator= (Array&& other) |
63 | { |
64 | if (&other != this) |
65 | { |
66 | _values = std::move(other._values); |
67 | _pArray = other._pArray; |
68 | other._pArray = 0; |
69 | _modified = other._modified; |
70 | } |
71 | return *this; |
72 | } |
73 | |
74 | |
75 | Array::~Array() |
76 | { |
77 | } |
78 | |
79 | |
80 | Var Array::get(unsigned int index) const |
81 | { |
82 | Var value; |
83 | try |
84 | { |
85 | value = _values.at(index); |
86 | } |
87 | catch (std::out_of_range&) |
88 | { |
89 | //Ignore, we return an empty value |
90 | } |
91 | return value; |
92 | } |
93 | |
94 | |
95 | Array::Ptr Array::getArray(unsigned int index) const |
96 | { |
97 | Array::Ptr result; |
98 | |
99 | Var value = get(index); |
100 | if (value.type() == typeid(Array::Ptr)) |
101 | { |
102 | result = value.extract<Array::Ptr>(); |
103 | } |
104 | return result; |
105 | } |
106 | |
107 | |
108 | Object::Ptr Array::getObject(unsigned int index) const |
109 | { |
110 | Object::Ptr result; |
111 | |
112 | Var value = get(index); |
113 | if (value.type() == typeid(Object::Ptr)) |
114 | { |
115 | result = value.extract<Object::Ptr>(); |
116 | } |
117 | return result; |
118 | } |
119 | |
120 | |
121 | bool Array::isNull(unsigned int index) const |
122 | { |
123 | if (index < _values.size()) |
124 | { |
125 | Dynamic::Var value = _values[index]; |
126 | return value.isEmpty(); |
127 | } |
128 | return true; |
129 | } |
130 | |
131 | |
132 | bool Array::isObject(unsigned int index) const |
133 | { |
134 | Var value = get(index); |
135 | return isObject(value); |
136 | } |
137 | |
138 | |
139 | bool Array::isObject(const Dynamic::Var& value) const |
140 | { |
141 | return value.type() == typeid(Object::Ptr); |
142 | } |
143 | |
144 | |
145 | bool Array::isObject(ConstIterator& it) const |
146 | { |
147 | return it!= end() && isObject(*it); |
148 | } |
149 | |
150 | |
151 | void Array::stringify(std::ostream& out, unsigned int indent, int step) const |
152 | { |
153 | int options = Poco::JSON_WRAP_STRINGS; |
154 | options |= _escapeUnicode ? Poco::JSON_ESCAPE_UNICODE : 0; |
155 | |
156 | if (step == -1) step = indent; |
157 | |
158 | out << "[" ; |
159 | |
160 | if (indent > 0) out << std::endl; |
161 | |
162 | for (ValueVec::const_iterator it = _values.begin(); it != _values.end();) |
163 | { |
164 | for (int i = 0; i < indent; i++) out << ' '; |
165 | |
166 | Stringifier::stringify(*it, out, indent + step, step, options); |
167 | |
168 | if (++it != _values.end()) |
169 | { |
170 | out << "," ; |
171 | if (step > 0) out << '\n'; |
172 | } |
173 | } |
174 | |
175 | if (step > 0) out << '\n'; |
176 | |
177 | if (indent >= step) indent -= step; |
178 | |
179 | for (int i = 0; i < indent; i++) out << ' '; |
180 | |
181 | out << "]" ; |
182 | } |
183 | |
184 | |
185 | void Array::resetDynArray() const |
186 | { |
187 | if (!_pArray) |
188 | _pArray = new Poco::Dynamic::Array; |
189 | else |
190 | _pArray->clear(); |
191 | } |
192 | |
193 | |
194 | Array::operator const Poco::Dynamic::Array& () const |
195 | { |
196 | if (!_values.size()) |
197 | { |
198 | resetDynArray(); |
199 | } |
200 | else if (_modified) |
201 | { |
202 | ValueVec::const_iterator it = _values.begin(); |
203 | ValueVec::const_iterator end = _values.end(); |
204 | resetDynArray(); |
205 | int index = 0; |
206 | for (; it != end; ++it, ++index) |
207 | { |
208 | if (isObject(it)) |
209 | { |
210 | _pArray->insert(_pArray->end(), Poco::JSON::Object::makeStruct(getObject(index))); |
211 | } |
212 | else if (isArray(it)) |
213 | { |
214 | _pArray->insert(_pArray->end(), makeArray(getArray(index))); |
215 | } |
216 | else |
217 | { |
218 | _pArray->insert(_pArray->end(), *it); |
219 | } |
220 | } |
221 | _modified = false; |
222 | } |
223 | |
224 | return *_pArray; |
225 | } |
226 | |
227 | |
228 | Poco::Dynamic::Array Array::makeArray(const JSON::Array::Ptr& arr) |
229 | { |
230 | Poco::Dynamic::Array vec; |
231 | |
232 | JSON::Array::ConstIterator it = arr->begin(); |
233 | JSON::Array::ConstIterator end = arr->end(); |
234 | int index = 0; |
235 | for (; it != end; ++it, ++index) |
236 | { |
237 | if (arr->isObject(it)) |
238 | { |
239 | Object::Ptr pObj = arr->getObject(index); |
240 | DynamicStruct str = Poco::JSON::Object::makeStruct(pObj); |
241 | vec.insert(vec.end(), str); |
242 | } |
243 | else if (arr->isArray(it)) |
244 | { |
245 | Array::Ptr pArr = arr->getArray(index); |
246 | std::vector<Poco::Dynamic::Var> v = makeArray(pArr); |
247 | vec.insert(vec.end(), v); |
248 | } |
249 | else |
250 | vec.insert(vec.end(), *it); |
251 | } |
252 | |
253 | return vec; |
254 | } |
255 | |
256 | |
257 | void Array::clear() |
258 | { |
259 | _values.clear(); |
260 | _pArray = 0; |
261 | } |
262 | |
263 | |
264 | } } // namespace Poco::JSON |
265 | |