1//     __ _____ _____ _____
2//  __|  |   __|     |   | |  JSON for Modern C++ (supporting code)
3// |  |  |__   |  |  | | | |  version 3.11.2
4// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5//
6// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
7// SPDX-License-Identifier: MIT
8
9#include "doctest_compatibility.h"
10
11#define JSON_TESTS_PRIVATE
12#include <nlohmann/json.hpp>
13using nlohmann::json;
14
15TEST_CASE("const_iterator class")
16{
17    SECTION("construction")
18    {
19        SECTION("constructor")
20        {
21            SECTION("null")
22            {
23                json j(json::value_t::null);
24                json::const_iterator it(&j);
25            }
26
27            SECTION("object")
28            {
29                json j(json::value_t::object);
30                json::const_iterator it(&j);
31            }
32
33            SECTION("array")
34            {
35                json j(json::value_t::array);
36                json::const_iterator it(&j);
37            }
38        }
39
40        SECTION("copy assignment")
41        {
42            json j(json::value_t::null);
43            json::const_iterator it(&j);
44            json::const_iterator it2(&j);
45            it2 = it;
46        }
47
48        SECTION("copy constructor from non-const iterator")
49        {
50            SECTION("create from uninitialized iterator")
51            {
52                const json::iterator it {};
53                json::const_iterator cit(it);
54            }
55
56            SECTION("create from initialized iterator")
57            {
58                json j;
59                const json::iterator it = j.begin();
60                json::const_iterator cit(it);
61            }
62        }
63    }
64
65    SECTION("initialization")
66    {
67        SECTION("set_begin")
68        {
69            SECTION("null")
70            {
71                json j(json::value_t::null);
72                json::const_iterator it(&j);
73                it.set_begin();
74                CHECK((it == j.cbegin()));
75            }
76
77            SECTION("object")
78            {
79                json j(json::value_t::object);
80                json::const_iterator it(&j);
81                it.set_begin();
82                CHECK((it == j.cbegin()));
83            }
84
85            SECTION("array")
86            {
87                json j(json::value_t::array);
88                json::const_iterator it(&j);
89                it.set_begin();
90                CHECK((it == j.cbegin()));
91            }
92        }
93
94        SECTION("set_end")
95        {
96            SECTION("null")
97            {
98                json j(json::value_t::null);
99                json::const_iterator it(&j);
100                it.set_end();
101                CHECK((it == j.cend()));
102            }
103
104            SECTION("object")
105            {
106                json j(json::value_t::object);
107                json::const_iterator it(&j);
108                it.set_end();
109                CHECK((it == j.cend()));
110            }
111
112            SECTION("array")
113            {
114                json j(json::value_t::array);
115                json::const_iterator it(&j);
116                it.set_end();
117                CHECK((it == j.cend()));
118            }
119        }
120    }
121
122    SECTION("element access")
123    {
124        SECTION("operator*")
125        {
126            SECTION("null")
127            {
128                json j(json::value_t::null);
129                json::const_iterator it = j.cbegin();
130                CHECK_THROWS_WITH_AS(*it, "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
131            }
132
133            SECTION("number")
134            {
135                json j(17);
136                json::const_iterator it = j.cbegin();
137                CHECK(*it == json(17));
138                it = j.cend();
139                CHECK_THROWS_WITH_AS(*it, "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
140            }
141
142            SECTION("object")
143            {
144                json j({{"foo", "bar"}});
145                json::const_iterator it = j.cbegin();
146                CHECK(*it == json("bar"));
147            }
148
149            SECTION("array")
150            {
151                json j({1, 2, 3, 4});
152                json::const_iterator it = j.cbegin();
153                CHECK(*it == json(1));
154            }
155        }
156
157        SECTION("operator->")
158        {
159            SECTION("null")
160            {
161                json j(json::value_t::null);
162                json::const_iterator it = j.cbegin();
163                CHECK_THROWS_WITH_AS(std::string(it->type_name()), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
164            }
165
166            SECTION("number")
167            {
168                json j(17);
169                json::const_iterator it = j.cbegin();
170                CHECK(std::string(it->type_name()) == "number");
171                it = j.cend();
172                CHECK_THROWS_WITH_AS(std::string(it->type_name()), "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&);
173            }
174
175            SECTION("object")
176            {
177                json j({{"foo", "bar"}});
178                json::const_iterator it = j.cbegin();
179                CHECK(std::string(it->type_name()) == "string");
180            }
181
182            SECTION("array")
183            {
184                json j({1, 2, 3, 4});
185                json::const_iterator it = j.cbegin();
186                CHECK(std::string(it->type_name()) == "number");
187            }
188        }
189    }
190
191    SECTION("increment/decrement")
192    {
193        SECTION("post-increment")
194        {
195            SECTION("null")
196            {
197                json j(json::value_t::null);
198                json::const_iterator it = j.cbegin();
199                CHECK((it.m_it.primitive_iterator.m_it == 1));
200                it++;
201                CHECK((it.m_it.primitive_iterator.m_it != 0 && it.m_it.primitive_iterator.m_it != 1));
202            }
203
204            SECTION("number")
205            {
206                json j(17);
207                json::const_iterator it = j.cbegin();
208                CHECK((it.m_it.primitive_iterator.m_it == 0));
209                it++;
210                CHECK((it.m_it.primitive_iterator.m_it == 1));
211                it++;
212                CHECK((it.m_it.primitive_iterator.m_it != 0 && it.m_it.primitive_iterator.m_it != 1));
213            }
214
215            SECTION("object")
216            {
217                json j({{"foo", "bar"}});
218                json::const_iterator it = j.cbegin();
219                CHECK((it.m_it.object_iterator == it.m_object->m_value.object->begin()));
220                it++;
221                CHECK((it.m_it.object_iterator == it.m_object->m_value.object->end()));
222            }
223
224            SECTION("array")
225            {
226                json j({1, 2, 3, 4});
227                json::const_iterator it = j.cbegin();
228                CHECK((it.m_it.array_iterator == it.m_object->m_value.array->begin()));
229                it++;
230                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
231                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
232                it++;
233                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
234                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
235                it++;
236                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
237                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
238                it++;
239                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
240                CHECK((it.m_it.array_iterator == it.m_object->m_value.array->end()));
241            }
242        }
243
244        SECTION("pre-increment")
245        {
246            SECTION("null")
247            {
248                json j(json::value_t::null);
249                json::const_iterator it = j.cbegin();
250                CHECK((it.m_it.primitive_iterator.m_it == 1));
251                ++it;
252                CHECK((it.m_it.primitive_iterator.m_it != 0 && it.m_it.primitive_iterator.m_it != 1));
253            }
254
255            SECTION("number")
256            {
257                json j(17);
258                json::const_iterator it = j.cbegin();
259                CHECK((it.m_it.primitive_iterator.m_it == 0));
260                ++it;
261                CHECK((it.m_it.primitive_iterator.m_it == 1));
262                ++it;
263                CHECK((it.m_it.primitive_iterator.m_it != 0 && it.m_it.primitive_iterator.m_it != 1));
264            }
265
266            SECTION("object")
267            {
268                json j({{"foo", "bar"}});
269                json::const_iterator it = j.cbegin();
270                CHECK((it.m_it.object_iterator == it.m_object->m_value.object->begin()));
271                ++it;
272                CHECK((it.m_it.object_iterator == it.m_object->m_value.object->end()));
273            }
274
275            SECTION("array")
276            {
277                json j({1, 2, 3, 4});
278                json::const_iterator it = j.cbegin();
279                CHECK((it.m_it.array_iterator == it.m_object->m_value.array->begin()));
280                ++it;
281                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
282                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
283                ++it;
284                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
285                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
286                ++it;
287                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
288                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
289                ++it;
290                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
291                CHECK((it.m_it.array_iterator == it.m_object->m_value.array->end()));
292            }
293        }
294
295        SECTION("post-decrement")
296        {
297            SECTION("null")
298            {
299                json j(json::value_t::null);
300                json::const_iterator it = j.cend();
301                CHECK((it.m_it.primitive_iterator.m_it == 1));
302            }
303
304            SECTION("number")
305            {
306                json j(17);
307                json::const_iterator it = j.cend();
308                CHECK((it.m_it.primitive_iterator.m_it == 1));
309                it--;
310                CHECK((it.m_it.primitive_iterator.m_it == 0));
311                it--;
312                CHECK((it.m_it.primitive_iterator.m_it != 0 && it.m_it.primitive_iterator.m_it != 1));
313            }
314
315            SECTION("object")
316            {
317                json j({{"foo", "bar"}});
318                json::const_iterator it = j.cend();
319                CHECK((it.m_it.object_iterator == it.m_object->m_value.object->end()));
320                it--;
321                CHECK((it.m_it.object_iterator == it.m_object->m_value.object->begin()));
322            }
323
324            SECTION("array")
325            {
326                json j({1, 2, 3, 4});
327                json::const_iterator it = j.cend();
328                CHECK((it.m_it.array_iterator == it.m_object->m_value.array->end()));
329                it--;
330                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
331                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
332                it--;
333                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
334                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
335                it--;
336                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
337                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
338                it--;
339                CHECK((it.m_it.array_iterator == it.m_object->m_value.array->begin()));
340                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
341            }
342        }
343
344        SECTION("pre-decrement")
345        {
346            SECTION("null")
347            {
348                json j(json::value_t::null);
349                json::const_iterator it = j.cend();
350                CHECK((it.m_it.primitive_iterator.m_it == 1));
351            }
352
353            SECTION("number")
354            {
355                json j(17);
356                json::const_iterator it = j.cend();
357                CHECK((it.m_it.primitive_iterator.m_it == 1));
358                --it;
359                CHECK((it.m_it.primitive_iterator.m_it == 0));
360                --it;
361                CHECK((it.m_it.primitive_iterator.m_it != 0 && it.m_it.primitive_iterator.m_it != 1));
362            }
363
364            SECTION("object")
365            {
366                json j({{"foo", "bar"}});
367                json::const_iterator it = j.cend();
368                CHECK((it.m_it.object_iterator == it.m_object->m_value.object->end()));
369                --it;
370                CHECK((it.m_it.object_iterator == it.m_object->m_value.object->begin()));
371            }
372
373            SECTION("array")
374            {
375                json j({1, 2, 3, 4});
376                json::const_iterator it = j.cend();
377                CHECK((it.m_it.array_iterator == it.m_object->m_value.array->end()));
378                --it;
379                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
380                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
381                --it;
382                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
383                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
384                --it;
385                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
386                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
387                --it;
388                CHECK((it.m_it.array_iterator == it.m_object->m_value.array->begin()));
389                CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
390            }
391        }
392    }
393}
394