• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     __ _____ _____ _____
3  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
4 |  |  |__   |  |  | | | |  version 3.9.1
5 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
6 
7 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8 SPDX-License-Identifier: MIT
9 Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
10 
11 Permission is hereby  granted, free of charge, to any  person obtaining a copy
12 of this software and associated  documentation files (the "Software"), to deal
13 in the Software  without restriction, including without  limitation the rights
14 to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
15 copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
16 furnished to do so, subject to the following conditions:
17 
18 The above copyright notice and this permission notice shall be included in all
19 copies or substantial portions of the Software.
20 
21 THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR
22 IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,
23 FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
24 AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
25 LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
27 SOFTWARE.
28 */
29 
30 #include "doctest_compatibility.h"
31 
32 #include <nlohmann/json.hpp>
33 using nlohmann::json;
34 
35 TEST_CASE("iterators 2")
36 {
37     SECTION("iterator comparisons")
38     {
39         json j_values = {nullptr, true, 42, 42u, 23.23, {{"one", 1}, {"two", 2}}, {1, 2, 3, 4, 5}, "Hello, world"};
40 
41         for (json& j : j_values)
42         {
43             auto it1 = j.begin();
44             auto it2 = j.begin();
45             auto it3 = j.begin();
46             ++it2;
47             ++it3;
48             ++it3;
49             auto it1_c = j.cbegin();
50             auto it2_c = j.cbegin();
51             auto it3_c = j.cbegin();
52             ++it2_c;
53             ++it3_c;
54             ++it3_c;
55 
56             // comparison: equal
57             {
58                 CHECK(it1 == it1);
59                 CHECK(!(it1 == it2));
60                 CHECK(!(it1 == it3));
61                 CHECK(!(it2 == it3));
62                 CHECK(it1_c == it1_c);
63                 CHECK(!(it1_c == it2_c));
64                 CHECK(!(it1_c == it3_c));
65                 CHECK(!(it2_c == it3_c));
66             }
67 
68             // comparison: not equal
69             {
70                 // check definition
71                 CHECK( (it1 != it1) == !(it1 == it1) );
72                 CHECK( (it1 != it2) == !(it1 == it2) );
73                 CHECK( (it1 != it3) == !(it1 == it3) );
74                 CHECK( (it2 != it3) == !(it2 == it3) );
75                 CHECK( (it1_c != it1_c) == !(it1_c == it1_c) );
76                 CHECK( (it1_c != it2_c) == !(it1_c == it2_c) );
77                 CHECK( (it1_c != it3_c) == !(it1_c == it3_c) );
78                 CHECK( (it2_c != it3_c) == !(it2_c == it3_c) );
79             }
80 
81             // comparison: smaller
82             {
83                 if (j.type() == json::value_t::object)
84                 {
85                     CHECK_THROWS_AS(it1 < it1, json::invalid_iterator&);
86                     CHECK_THROWS_AS(it1 < it2, json::invalid_iterator&);
87                     CHECK_THROWS_AS(it2 < it3, json::invalid_iterator&);
88                     CHECK_THROWS_AS(it1 < it3, json::invalid_iterator&);
89                     CHECK_THROWS_AS(it1_c < it1_c, json::invalid_iterator&);
90                     CHECK_THROWS_AS(it1_c < it2_c, json::invalid_iterator&);
91                     CHECK_THROWS_AS(it2_c < it3_c, json::invalid_iterator&);
92                     CHECK_THROWS_AS(it1_c < it3_c, json::invalid_iterator&);
93                     CHECK_THROWS_WITH(it1 < it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
94                     CHECK_THROWS_WITH(it1 < it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
95                     CHECK_THROWS_WITH(it2 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
96                     CHECK_THROWS_WITH(it1 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
97                     CHECK_THROWS_WITH(it1_c < it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
98                     CHECK_THROWS_WITH(it1_c < it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
99                     CHECK_THROWS_WITH(it2_c < it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
100                     CHECK_THROWS_WITH(it1_c < it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
101                 }
102                 else
103                 {
104                     CHECK(!(it1 < it1));
105                     CHECK(it1 < it2);
106                     CHECK(it1 < it3);
107                     CHECK(it2 < it3);
108                     CHECK(!(it1_c < it1_c));
109                     CHECK(it1_c < it2_c);
110                     CHECK(it1_c < it3_c);
111                     CHECK(it2_c < it3_c);
112                 }
113             }
114 
115             // comparison: less than or equal
116             {
117                 if (j.type() == json::value_t::object)
118                 {
119                     CHECK_THROWS_AS(it1 <= it1, json::invalid_iterator&);
120                     CHECK_THROWS_AS(it1 <= it2, json::invalid_iterator&);
121                     CHECK_THROWS_AS(it2 <= it3, json::invalid_iterator&);
122                     CHECK_THROWS_AS(it1 <= it3, json::invalid_iterator&);
123                     CHECK_THROWS_AS(it1_c <= it1_c, json::invalid_iterator&);
124                     CHECK_THROWS_AS(it1_c <= it2_c, json::invalid_iterator&);
125                     CHECK_THROWS_AS(it2_c <= it3_c, json::invalid_iterator&);
126                     CHECK_THROWS_AS(it1_c <= it3_c, json::invalid_iterator&);
127                     CHECK_THROWS_WITH(it1 <= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
128                     CHECK_THROWS_WITH(it1 <= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
129                     CHECK_THROWS_WITH(it2 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
130                     CHECK_THROWS_WITH(it1 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
131                     CHECK_THROWS_WITH(it1_c <= it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
132                     CHECK_THROWS_WITH(it1_c <= it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
133                     CHECK_THROWS_WITH(it2_c <= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
134                     CHECK_THROWS_WITH(it1_c <= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
135                 }
136                 else
137                 {
138                     // check definition
139                     CHECK( (it1 <= it1) == !(it1 < it1) );
140                     CHECK( (it1 <= it2) == !(it2 < it1) );
141                     CHECK( (it1 <= it3) == !(it3 < it1) );
142                     CHECK( (it2 <= it3) == !(it3 < it2) );
143                     CHECK( (it1_c <= it1_c) == !(it1_c < it1_c) );
144                     CHECK( (it1_c <= it2_c) == !(it2_c < it1_c) );
145                     CHECK( (it1_c <= it3_c) == !(it3_c < it1_c) );
146                     CHECK( (it2_c <= it3_c) == !(it3_c < it2_c) );
147                 }
148             }
149 
150             // comparison: greater than
151             {
152                 if (j.type() == json::value_t::object)
153                 {
154                     CHECK_THROWS_AS(it1 > it1, json::invalid_iterator&);
155                     CHECK_THROWS_AS(it1 > it2, json::invalid_iterator&);
156                     CHECK_THROWS_AS(it2 > it3, json::invalid_iterator&);
157                     CHECK_THROWS_AS(it1 > it3, json::invalid_iterator&);
158                     CHECK_THROWS_AS(it1_c > it1_c, json::invalid_iterator&);
159                     CHECK_THROWS_AS(it1_c > it2_c, json::invalid_iterator&);
160                     CHECK_THROWS_AS(it2_c > it3_c, json::invalid_iterator&);
161                     CHECK_THROWS_AS(it1_c > it3_c, json::invalid_iterator&);
162                     CHECK_THROWS_WITH(it1 > it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
163                     CHECK_THROWS_WITH(it1 > it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
164                     CHECK_THROWS_WITH(it2 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
165                     CHECK_THROWS_WITH(it1 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
166                     CHECK_THROWS_WITH(it1_c > it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
167                     CHECK_THROWS_WITH(it1_c > it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
168                     CHECK_THROWS_WITH(it2_c > it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
169                     CHECK_THROWS_WITH(it1_c > it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
170                 }
171                 else
172                 {
173                     // check definition
174                     CHECK( (it1 > it1) == (it1 < it1) );
175                     CHECK( (it1 > it2) == (it2 < it1) );
176                     CHECK( (it1 > it3) == (it3 < it1) );
177                     CHECK( (it2 > it3) == (it3 < it2) );
178                     CHECK( (it1_c > it1_c) == (it1_c < it1_c) );
179                     CHECK( (it1_c > it2_c) == (it2_c < it1_c) );
180                     CHECK( (it1_c > it3_c) == (it3_c < it1_c) );
181                     CHECK( (it2_c > it3_c) == (it3_c < it2_c) );
182                 }
183             }
184 
185             // comparison: greater than or equal
186             {
187                 if (j.type() == json::value_t::object)
188                 {
189                     CHECK_THROWS_AS(it1 >= it1, json::invalid_iterator&);
190                     CHECK_THROWS_AS(it1 >= it2, json::invalid_iterator&);
191                     CHECK_THROWS_AS(it2 >= it3, json::invalid_iterator&);
192                     CHECK_THROWS_AS(it1 >= it3, json::invalid_iterator&);
193                     CHECK_THROWS_AS(it1_c >= it1_c, json::invalid_iterator&);
194                     CHECK_THROWS_AS(it1_c >= it2_c, json::invalid_iterator&);
195                     CHECK_THROWS_AS(it2_c >= it3_c, json::invalid_iterator&);
196                     CHECK_THROWS_AS(it1_c >= it3_c, json::invalid_iterator&);
197                     CHECK_THROWS_WITH(it1 >= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
198                     CHECK_THROWS_WITH(it1 >= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
199                     CHECK_THROWS_WITH(it2 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
200                     CHECK_THROWS_WITH(it1 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
201                     CHECK_THROWS_WITH(it1_c >= it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
202                     CHECK_THROWS_WITH(it1_c >= it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
203                     CHECK_THROWS_WITH(it2_c >= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
204                     CHECK_THROWS_WITH(it1_c >= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
205                 }
206                 else
207                 {
208                     // check definition
209                     CHECK( (it1 >= it1) == !(it1 < it1) );
210                     CHECK( (it1 >= it2) == !(it1 < it2) );
211                     CHECK( (it1 >= it3) == !(it1 < it3) );
212                     CHECK( (it2 >= it3) == !(it2 < it3) );
213                     CHECK( (it1_c >= it1_c) == !(it1_c < it1_c) );
214                     CHECK( (it1_c >= it2_c) == !(it1_c < it2_c) );
215                     CHECK( (it1_c >= it3_c) == !(it1_c < it3_c) );
216                     CHECK( (it2_c >= it3_c) == !(it2_c < it3_c) );
217                 }
218             }
219         }
220 
221         // check exceptions if different objects are compared
222         for (auto j : j_values)
223         {
224             for (auto k : j_values)
225             {
226                 if (j != k)
227                 {
228                     CHECK_THROWS_AS(j.begin() == k.begin(), json::invalid_iterator&);
229                     CHECK_THROWS_AS(j.cbegin() == k.cbegin(), json::invalid_iterator&);
230                     CHECK_THROWS_WITH(j.begin() == k.begin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers");
231                     CHECK_THROWS_WITH(j.cbegin() == k.cbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers");
232 
233                     CHECK_THROWS_AS(j.begin() < k.begin(), json::invalid_iterator&);
234                     CHECK_THROWS_AS(j.cbegin() < k.cbegin(), json::invalid_iterator&);
235                     CHECK_THROWS_WITH(j.begin() < k.begin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers");
236                     CHECK_THROWS_WITH(j.cbegin() < k.cbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers");
237                 }
238             }
239         }
240     }
241 
242     SECTION("iterator arithmetic")
243     {
244         json j_object = {{"one", 1}, {"two", 2}, {"three", 3}};
245         json j_array = {1, 2, 3, 4, 5, 6};
246         json j_null = nullptr;
247         json j_value = 42;
248 
249         SECTION("addition and subtraction")
250         {
251             SECTION("object")
252             {
253                 {
254                     auto it = j_object.begin();
255                     CHECK_THROWS_AS(it += 1, json::invalid_iterator&);
256                     CHECK_THROWS_WITH(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
257                 }
258                 {
259                     auto it = j_object.cbegin();
260                     CHECK_THROWS_AS(it += 1, json::invalid_iterator&);
261                     CHECK_THROWS_WITH(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
262                 }
263                 {
264                     auto it = j_object.begin();
265                     CHECK_THROWS_AS(it + 1, json::invalid_iterator&);
266                     CHECK_THROWS_WITH(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
267                 }
268                 {
269                     auto it = j_object.cbegin();
270                     CHECK_THROWS_AS(it + 1, json::invalid_iterator&);
271                     CHECK_THROWS_WITH(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
272                 }
273                 {
274                     auto it = j_object.begin();
275                     CHECK_THROWS_AS(1 + it, json::invalid_iterator&);
276                     CHECK_THROWS_WITH(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
277                 }
278                 {
279                     auto it = j_object.cbegin();
280                     CHECK_THROWS_AS(1 + it, json::invalid_iterator&);
281                     CHECK_THROWS_WITH(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
282                 }
283                 {
284                     auto it = j_object.begin();
285                     CHECK_THROWS_AS(it -= 1, json::invalid_iterator&);
286                     CHECK_THROWS_WITH(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
287                 }
288                 {
289                     auto it = j_object.cbegin();
290                     CHECK_THROWS_AS(it -= 1, json::invalid_iterator&);
291                     CHECK_THROWS_WITH(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
292                 }
293                 {
294                     auto it = j_object.begin();
295                     CHECK_THROWS_AS(it - 1, json::invalid_iterator&);
296                     CHECK_THROWS_WITH(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
297                 }
298                 {
299                     auto it = j_object.cbegin();
300                     CHECK_THROWS_AS(it - 1, json::invalid_iterator&);
301                     CHECK_THROWS_WITH(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
302                 }
303                 {
304                     auto it = j_object.begin();
305                     CHECK_THROWS_AS(it - it, json::invalid_iterator&);
306                     CHECK_THROWS_WITH(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
307                 }
308                 {
309                     auto it = j_object.cbegin();
310                     CHECK_THROWS_AS(it - it, json::invalid_iterator&);
311                     CHECK_THROWS_WITH(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
312                 }
313             }
314 
315             SECTION("array")
316             {
317                 {
318                     auto it = j_array.begin();
319                     it += 3;
320                     CHECK((j_array.begin() + 3) == it);
321                     CHECK((3 + j_array.begin()) == it);
322                     CHECK((it - 3) == j_array.begin());
323                     CHECK((it - j_array.begin()) == 3);
324                     CHECK(*it == json(4));
325                     it -= 2;
326                     CHECK(*it == json(2));
327                 }
328                 {
329                     auto it = j_array.cbegin();
330                     it += 3;
331                     CHECK((j_array.cbegin() + 3) == it);
332                     CHECK((3 + j_array.cbegin()) == it);
333                     CHECK((it - 3) == j_array.cbegin());
334                     CHECK((it - j_array.cbegin()) == 3);
335                     CHECK(*it == json(4));
336                     it -= 2;
337                     CHECK(*it == json(2));
338                 }
339             }
340 
341             SECTION("null")
342             {
343                 {
344                     auto it = j_null.begin();
345                     it += 3;
346                     CHECK((j_null.begin() + 3) == it);
347                     CHECK((3 + j_null.begin()) == it);
348                     CHECK((it - 3) == j_null.begin());
349                     CHECK((it - j_null.begin()) == 3);
350                     CHECK(it != j_null.end());
351                     it -= 3;
352                     CHECK(it == j_null.end());
353                 }
354                 {
355                     auto it = j_null.cbegin();
356                     it += 3;
357                     CHECK((j_null.cbegin() + 3) == it);
358                     CHECK((3 + j_null.cbegin()) == it);
359                     CHECK((it - 3) == j_null.cbegin());
360                     CHECK((it - j_null.cbegin()) == 3);
361                     CHECK(it != j_null.cend());
362                     it -= 3;
363                     CHECK(it == j_null.cend());
364                 }
365             }
366 
367             SECTION("value")
368             {
369                 {
370                     auto it = j_value.begin();
371                     it += 3;
372                     CHECK((j_value.begin() + 3) == it);
373                     CHECK((3 + j_value.begin()) == it);
374                     CHECK((it - 3) == j_value.begin());
375                     CHECK((it - j_value.begin()) == 3);
376                     CHECK(it != j_value.end());
377                     it -= 3;
378                     CHECK(*it == json(42));
379                 }
380                 {
381                     auto it = j_value.cbegin();
382                     it += 3;
383                     CHECK((j_value.cbegin() + 3) == it);
384                     CHECK((3 + j_value.cbegin()) == it);
385                     CHECK((it - 3) == j_value.cbegin());
386                     CHECK((it - j_value.cbegin()) == 3);
387                     CHECK(it != j_value.cend());
388                     it -= 3;
389                     CHECK(*it == json(42));
390                 }
391             }
392         }
393 
394         SECTION("subscript operator")
395         {
396             SECTION("object")
397             {
398                 {
399                     auto it = j_object.begin();
400                     CHECK_THROWS_AS(it[0], json::invalid_iterator&);
401                     CHECK_THROWS_AS(it[1], json::invalid_iterator&);
402                     CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators");
403                     CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators");
404                 }
405                 {
406                     auto it = j_object.cbegin();
407                     CHECK_THROWS_AS(it[0], json::invalid_iterator&);
408                     CHECK_THROWS_AS(it[1], json::invalid_iterator&);
409                     CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators");
410                     CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators");
411                 }
412             }
413 
414             SECTION("array")
415             {
416                 {
417                     auto it = j_array.begin();
418                     CHECK(it[0] == json(1));
419                     CHECK(it[1] == json(2));
420                     CHECK(it[2] == json(3));
421                     CHECK(it[3] == json(4));
422                     CHECK(it[4] == json(5));
423                     CHECK(it[5] == json(6));
424                 }
425                 {
426                     auto it = j_array.cbegin();
427                     CHECK(it[0] == json(1));
428                     CHECK(it[1] == json(2));
429                     CHECK(it[2] == json(3));
430                     CHECK(it[3] == json(4));
431                     CHECK(it[4] == json(5));
432                     CHECK(it[5] == json(6));
433                 }
434             }
435 
436             SECTION("null")
437             {
438                 {
439                     auto it = j_null.begin();
440                     CHECK_THROWS_AS(it[0], json::invalid_iterator&);
441                     CHECK_THROWS_AS(it[1], json::invalid_iterator&);
442                     CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.214] cannot get value");
443                     CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value");
444                 }
445                 {
446                     auto it = j_null.cbegin();
447                     CHECK_THROWS_AS(it[0], json::invalid_iterator&);
448                     CHECK_THROWS_AS(it[1], json::invalid_iterator&);
449                     CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.214] cannot get value");
450                     CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value");
451                 }
452             }
453 
454             SECTION("value")
455             {
456                 {
457                     auto it = j_value.begin();
458                     CHECK(it[0] == json(42));
459                     CHECK_THROWS_AS(it[1], json::invalid_iterator&);
460                     CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value");
461                 }
462                 {
463                     auto it = j_value.cbegin();
464                     CHECK(it[0] == json(42));
465                     CHECK_THROWS_AS(it[1], json::invalid_iterator&);
466                     CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value");
467                 }
468             }
469         }
470     }
471 
472     SECTION("reverse iterator comparisons")
473     {
474         json j_values = {nullptr, true, 42, 42u, 23.23, {{"one", 1}, {"two", 2}}, {1, 2, 3, 4, 5}, "Hello, world"};
475 
476         for (json& j : j_values)
477         {
478             auto it1 = j.rbegin();
479             auto it2 = j.rbegin();
480             auto it3 = j.rbegin();
481             ++it2;
482             ++it3;
483             ++it3;
484             auto it1_c = j.crbegin();
485             auto it2_c = j.crbegin();
486             auto it3_c = j.crbegin();
487             ++it2_c;
488             ++it3_c;
489             ++it3_c;
490 
491             // comparison: equal
492             {
493                 CHECK(it1 == it1);
494                 CHECK(!(it1 == it2));
495                 CHECK(!(it1 == it3));
496                 CHECK(!(it2 == it3));
497                 CHECK(it1_c == it1_c);
498                 CHECK(!(it1_c == it2_c));
499                 CHECK(!(it1_c == it3_c));
500                 CHECK(!(it2_c == it3_c));
501             }
502 
503             // comparison: not equal
504             {
505                 // check definition
506                 CHECK( (it1 != it1) == !(it1 == it1) );
507                 CHECK( (it1 != it2) == !(it1 == it2) );
508                 CHECK( (it1 != it3) == !(it1 == it3) );
509                 CHECK( (it2 != it3) == !(it2 == it3) );
510                 CHECK( (it1_c != it1_c) == !(it1_c == it1_c) );
511                 CHECK( (it1_c != it2_c) == !(it1_c == it2_c) );
512                 CHECK( (it1_c != it3_c) == !(it1_c == it3_c) );
513                 CHECK( (it2_c != it3_c) == !(it2_c == it3_c) );
514             }
515 
516             // comparison: smaller
517             {
518                 if (j.type() == json::value_t::object)
519                 {
520                     CHECK_THROWS_AS(it1 < it1, json::invalid_iterator&);
521                     CHECK_THROWS_AS(it1 < it2, json::invalid_iterator&);
522                     CHECK_THROWS_AS(it2 < it3, json::invalid_iterator&);
523                     CHECK_THROWS_AS(it1 < it3, json::invalid_iterator&);
524                     CHECK_THROWS_AS(it1_c < it1_c, json::invalid_iterator&);
525                     CHECK_THROWS_AS(it1_c < it2_c, json::invalid_iterator&);
526                     CHECK_THROWS_AS(it2_c < it3_c, json::invalid_iterator&);
527                     CHECK_THROWS_AS(it1_c < it3_c, json::invalid_iterator&);
528                     CHECK_THROWS_WITH(it1 < it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
529                     CHECK_THROWS_WITH(it1 < it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
530                     CHECK_THROWS_WITH(it2 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
531                     CHECK_THROWS_WITH(it1 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
532                     CHECK_THROWS_WITH(it1_c < it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
533                     CHECK_THROWS_WITH(it1_c < it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
534                     CHECK_THROWS_WITH(it2_c < it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
535                     CHECK_THROWS_WITH(it1_c < it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
536                 }
537                 else
538                 {
539                     CHECK(!(it1 < it1));
540                     CHECK(it1 < it2);
541                     CHECK(it1 < it3);
542                     CHECK(it2 < it3);
543                     CHECK(!(it1_c < it1_c));
544                     CHECK(it1_c < it2_c);
545                     CHECK(it1_c < it3_c);
546                     CHECK(it2_c < it3_c);
547                 }
548             }
549 
550             // comparison: less than or equal
551             {
552                 if (j.type() == json::value_t::object)
553                 {
554                     CHECK_THROWS_AS(it1 <= it1, json::invalid_iterator&);
555                     CHECK_THROWS_AS(it1 <= it2, json::invalid_iterator&);
556                     CHECK_THROWS_AS(it2 <= it3, json::invalid_iterator&);
557                     CHECK_THROWS_AS(it1 <= it3, json::invalid_iterator&);
558                     CHECK_THROWS_AS(it1_c <= it1_c, json::invalid_iterator&);
559                     CHECK_THROWS_AS(it1_c <= it2_c, json::invalid_iterator&);
560                     CHECK_THROWS_AS(it2_c <= it3_c, json::invalid_iterator&);
561                     CHECK_THROWS_AS(it1_c <= it3_c, json::invalid_iterator&);
562                     CHECK_THROWS_WITH(it1 <= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
563                     CHECK_THROWS_WITH(it1 <= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
564                     CHECK_THROWS_WITH(it2 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
565                     CHECK_THROWS_WITH(it1 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
566                     CHECK_THROWS_WITH(it1_c <= it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
567                     CHECK_THROWS_WITH(it1_c <= it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
568                     CHECK_THROWS_WITH(it2_c <= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
569                     CHECK_THROWS_WITH(it1_c <= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
570                 }
571                 else
572                 {
573                     // check definition
574                     CHECK( (it1 <= it1) == !(it1 < it1) );
575                     CHECK( (it1 <= it2) == !(it2 < it1) );
576                     CHECK( (it1 <= it3) == !(it3 < it1) );
577                     CHECK( (it2 <= it3) == !(it3 < it2) );
578                     CHECK( (it1_c <= it1_c) == !(it1_c < it1_c) );
579                     CHECK( (it1_c <= it2_c) == !(it2_c < it1_c) );
580                     CHECK( (it1_c <= it3_c) == !(it3_c < it1_c) );
581                     CHECK( (it2_c <= it3_c) == !(it3_c < it2_c) );
582                 }
583             }
584 
585             // comparison: greater than
586             {
587                 if (j.type() == json::value_t::object)
588                 {
589                     CHECK_THROWS_AS(it1 > it1, json::invalid_iterator&);
590                     CHECK_THROWS_AS(it1 > it2, json::invalid_iterator&);
591                     CHECK_THROWS_AS(it2 > it3, json::invalid_iterator&);
592                     CHECK_THROWS_AS(it1 > it3, json::invalid_iterator&);
593                     CHECK_THROWS_AS(it1_c > it1_c, json::invalid_iterator&);
594                     CHECK_THROWS_AS(it1_c > it2_c, json::invalid_iterator&);
595                     CHECK_THROWS_AS(it2_c > it3_c, json::invalid_iterator&);
596                     CHECK_THROWS_AS(it1_c > it3_c, json::invalid_iterator&);
597                     CHECK_THROWS_WITH(it1 > it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
598                     CHECK_THROWS_WITH(it1 > it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
599                     CHECK_THROWS_WITH(it2 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
600                     CHECK_THROWS_WITH(it1 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
601                     CHECK_THROWS_WITH(it1_c > it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
602                     CHECK_THROWS_WITH(it1_c > it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
603                     CHECK_THROWS_WITH(it2_c > it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
604                     CHECK_THROWS_WITH(it1_c > it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
605                 }
606                 else
607                 {
608                     // check definition
609                     CHECK( (it1 > it1) == (it1 < it1) );
610                     CHECK( (it1 > it2) == (it2 < it1) );
611                     CHECK( (it1 > it3) == (it3 < it1) );
612                     CHECK( (it2 > it3) == (it3 < it2) );
613                     CHECK( (it1_c > it1_c) == (it1_c < it1_c) );
614                     CHECK( (it1_c > it2_c) == (it2_c < it1_c) );
615                     CHECK( (it1_c > it3_c) == (it3_c < it1_c) );
616                     CHECK( (it2_c > it3_c) == (it3_c < it2_c) );
617                 }
618             }
619 
620             // comparison: greater than or equal
621             {
622                 if (j.type() == json::value_t::object)
623                 {
624                     CHECK_THROWS_AS(it1 >= it1, json::invalid_iterator&);
625                     CHECK_THROWS_AS(it1 >= it2, json::invalid_iterator&);
626                     CHECK_THROWS_AS(it2 >= it3, json::invalid_iterator&);
627                     CHECK_THROWS_AS(it1 >= it3, json::invalid_iterator&);
628                     CHECK_THROWS_AS(it1_c >= it1_c, json::invalid_iterator&);
629                     CHECK_THROWS_AS(it1_c >= it2_c, json::invalid_iterator&);
630                     CHECK_THROWS_AS(it2_c >= it3_c, json::invalid_iterator&);
631                     CHECK_THROWS_AS(it1_c >= it3_c, json::invalid_iterator&);
632                     CHECK_THROWS_WITH(it1 >= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
633                     CHECK_THROWS_WITH(it1 >= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
634                     CHECK_THROWS_WITH(it2 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
635                     CHECK_THROWS_WITH(it1 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
636                     CHECK_THROWS_WITH(it1_c >= it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
637                     CHECK_THROWS_WITH(it1_c >= it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
638                     CHECK_THROWS_WITH(it2_c >= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
639                     CHECK_THROWS_WITH(it1_c >= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators");
640                 }
641                 else
642                 {
643                     // check definition
644                     CHECK( (it1 >= it1) == !(it1 < it1) );
645                     CHECK( (it1 >= it2) == !(it1 < it2) );
646                     CHECK( (it1 >= it3) == !(it1 < it3) );
647                     CHECK( (it2 >= it3) == !(it2 < it3) );
648                     CHECK( (it1_c >= it1_c) == !(it1_c < it1_c) );
649                     CHECK( (it1_c >= it2_c) == !(it1_c < it2_c) );
650                     CHECK( (it1_c >= it3_c) == !(it1_c < it3_c) );
651                     CHECK( (it2_c >= it3_c) == !(it2_c < it3_c) );
652                 }
653             }
654         }
655 
656         // check exceptions if different objects are compared
657         for (auto j : j_values)
658         {
659             for (auto k : j_values)
660             {
661                 if (j != k)
662                 {
663                     CHECK_THROWS_AS(j.rbegin() == k.rbegin(), json::invalid_iterator&);
664                     CHECK_THROWS_AS(j.crbegin() == k.crbegin(), json::invalid_iterator&);
665                     CHECK_THROWS_WITH(j.rbegin() == k.rbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers");
666                     CHECK_THROWS_WITH(j.crbegin() == k.crbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers");
667 
668                     CHECK_THROWS_AS(j.rbegin() < k.rbegin(), json::invalid_iterator&);
669                     CHECK_THROWS_AS(j.crbegin() < k.crbegin(), json::invalid_iterator&);
670                     CHECK_THROWS_WITH(j.rbegin() < k.rbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers");
671                     CHECK_THROWS_WITH(j.crbegin() < k.crbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers");
672                 }
673             }
674         }
675     }
676 
677     SECTION("reverse iterator arithmetic")
678     {
679         json j_object = {{"one", 1}, {"two", 2}, {"three", 3}};
680         json j_array = {1, 2, 3, 4, 5, 6};
681         json j_null = nullptr;
682         json j_value = 42;
683 
684         SECTION("addition and subtraction")
685         {
686             SECTION("object")
687             {
688                 {
689                     auto it = j_object.rbegin();
690                     CHECK_THROWS_AS(it += 1, json::invalid_iterator&);
691                     CHECK_THROWS_WITH(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
692                 }
693                 {
694                     auto it = j_object.crbegin();
695                     CHECK_THROWS_AS(it += 1, json::invalid_iterator&);
696                     CHECK_THROWS_WITH(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
697                 }
698                 {
699                     auto it = j_object.rbegin();
700                     CHECK_THROWS_AS(it + 1, json::invalid_iterator&);
701                     CHECK_THROWS_WITH(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
702                 }
703                 {
704                     auto it = j_object.crbegin();
705                     CHECK_THROWS_AS(it + 1, json::invalid_iterator&);
706                     CHECK_THROWS_WITH(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
707                 }
708                 {
709                     auto it = j_object.rbegin();
710                     CHECK_THROWS_AS(1 + it, json::invalid_iterator&);
711                     CHECK_THROWS_WITH(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
712                 }
713                 {
714                     auto it = j_object.crbegin();
715                     CHECK_THROWS_AS(1 + it, json::invalid_iterator&);
716                     CHECK_THROWS_WITH(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
717                 }
718                 {
719                     auto it = j_object.rbegin();
720                     CHECK_THROWS_AS(it -= 1, json::invalid_iterator&);
721                     CHECK_THROWS_WITH(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
722                 }
723                 {
724                     auto it = j_object.crbegin();
725                     CHECK_THROWS_AS(it -= 1, json::invalid_iterator&);
726                     CHECK_THROWS_WITH(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
727                 }
728                 {
729                     auto it = j_object.rbegin();
730                     CHECK_THROWS_AS(it - 1, json::invalid_iterator&);
731                     CHECK_THROWS_WITH(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
732                 }
733                 {
734                     auto it = j_object.crbegin();
735                     CHECK_THROWS_AS(it - 1, json::invalid_iterator&);
736                     CHECK_THROWS_WITH(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
737                 }
738                 {
739                     auto it = j_object.rbegin();
740                     CHECK_THROWS_AS(it - it, json::invalid_iterator&);
741                     CHECK_THROWS_WITH(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
742                 }
743                 {
744                     auto it = j_object.crbegin();
745                     CHECK_THROWS_AS(it - it, json::invalid_iterator&);
746                     CHECK_THROWS_WITH(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
747                 }
748             }
749 
750             SECTION("array")
751             {
752                 {
753                     auto it = j_array.rbegin();
754                     it += 3;
755                     CHECK((j_array.rbegin() + 3) == it);
756                     CHECK(json::reverse_iterator(3 + j_array.rbegin()) == it);
757                     CHECK((it - 3) == j_array.rbegin());
758                     CHECK((it - j_array.rbegin()) == 3);
759                     CHECK(*it == json(3));
760                     it -= 2;
761                     CHECK(*it == json(5));
762                 }
763                 {
764                     auto it = j_array.crbegin();
765                     it += 3;
766                     CHECK((j_array.crbegin() + 3) == it);
767                     CHECK(json::const_reverse_iterator(3 + j_array.crbegin()) == it);
768                     CHECK((it - 3) == j_array.crbegin());
769                     CHECK((it - j_array.crbegin()) == 3);
770                     CHECK(*it == json(3));
771                     it -= 2;
772                     CHECK(*it == json(5));
773                 }
774             }
775 
776             SECTION("null")
777             {
778                 {
779                     auto it = j_null.rbegin();
780                     it += 3;
781                     CHECK((j_null.rbegin() + 3) == it);
782                     CHECK(json::reverse_iterator(3 + j_null.rbegin()) == it);
783                     CHECK((it - 3) == j_null.rbegin());
784                     CHECK((it - j_null.rbegin()) == 3);
785                     CHECK(it != j_null.rend());
786                     it -= 3;
787                     CHECK(it == j_null.rend());
788                 }
789                 {
790                     auto it = j_null.crbegin();
791                     it += 3;
792                     CHECK((j_null.crbegin() + 3) == it);
793                     CHECK(json::const_reverse_iterator(3 + j_null.crbegin()) == it);
794                     CHECK((it - 3) == j_null.crbegin());
795                     CHECK((it - j_null.crbegin()) == 3);
796                     CHECK(it != j_null.crend());
797                     it -= 3;
798                     CHECK(it == j_null.crend());
799                 }
800             }
801 
802             SECTION("value")
803             {
804                 {
805                     auto it = j_value.rbegin();
806                     it += 3;
807                     CHECK((j_value.rbegin() + 3) == it);
808                     CHECK(json::reverse_iterator(3 + j_value.rbegin()) == it);
809                     CHECK((it - 3) == j_value.rbegin());
810                     CHECK((it - j_value.rbegin()) == 3);
811                     CHECK(it != j_value.rend());
812                     it -= 3;
813                     CHECK(*it == json(42));
814                 }
815                 {
816                     auto it = j_value.crbegin();
817                     it += 3;
818                     CHECK((j_value.crbegin() + 3) == it);
819                     CHECK(json::const_reverse_iterator(3 + j_value.crbegin()) == it);
820                     CHECK((it - 3) == j_value.crbegin());
821                     CHECK((it - j_value.crbegin()) == 3);
822                     CHECK(it != j_value.crend());
823                     it -= 3;
824                     CHECK(*it == json(42));
825                 }
826             }
827         }
828 
829         SECTION("subscript operator")
830         {
831             SECTION("object")
832             {
833                 {
834                     auto it = j_object.rbegin();
835                     CHECK_THROWS_AS(it[0], json::invalid_iterator&);
836                     CHECK_THROWS_AS(it[1], json::invalid_iterator&);
837                     CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
838                     CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
839                 }
840                 {
841                     auto it = j_object.crbegin();
842                     CHECK_THROWS_AS(it[0], json::invalid_iterator&);
843                     CHECK_THROWS_AS(it[1], json::invalid_iterator&);
844                     CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
845                     CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
846                 }
847             }
848 
849             SECTION("array")
850             {
851                 {
852                     auto it = j_array.rbegin();
853                     CHECK(it[0] == json(6));
854                     CHECK(it[1] == json(5));
855                     CHECK(it[2] == json(4));
856                     CHECK(it[3] == json(3));
857                     CHECK(it[4] == json(2));
858                     CHECK(it[5] == json(1));
859                 }
860                 {
861                     auto it = j_array.crbegin();
862                     CHECK(it[0] == json(6));
863                     CHECK(it[1] == json(5));
864                     CHECK(it[2] == json(4));
865                     CHECK(it[3] == json(3));
866                     CHECK(it[4] == json(2));
867                     CHECK(it[5] == json(1));
868                 }
869             }
870 
871             SECTION("null")
872             {
873                 {
874                     auto it = j_null.rbegin();
875                     CHECK_THROWS_AS(it[0], json::invalid_iterator&);
876                     CHECK_THROWS_AS(it[1], json::invalid_iterator&);
877                     CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.214] cannot get value");
878                     CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value");
879                 }
880                 {
881                     auto it = j_null.crbegin();
882                     CHECK_THROWS_AS(it[0], json::invalid_iterator&);
883                     CHECK_THROWS_AS(it[1], json::invalid_iterator&);
884                     CHECK_THROWS_WITH(it[0], "[json.exception.invalid_iterator.214] cannot get value");
885                     CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value");
886                 }
887             }
888 
889             SECTION("value")
890             {
891                 {
892                     auto it = j_value.rbegin();
893                     CHECK(it[0] == json(42));
894                     CHECK_THROWS_AS(it[1], json::invalid_iterator&);
895                     CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value");
896                 }
897                 {
898                     auto it = j_value.crbegin();
899                     CHECK(it[0] == json(42));
900                     CHECK_THROWS_AS(it[1], json::invalid_iterator&);
901                     CHECK_THROWS_WITH(it[1], "[json.exception.invalid_iterator.214] cannot get value");
902                 }
903             }
904         }
905     }
906 }
907