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 // cmake/test.cmake selects the C++ standard versions with which to build a 10 // unit test based on the presence of JSON_HAS_CPP_<VERSION> macros. 11 // When using macros that are only defined for particular versions of the standard 12 // (e.g., JSON_HAS_FILESYSTEM for C++17 and up), please mention the corresponding 13 // version macro in a comment close by, like this: 14 // JSON_HAS_CPP_<VERSION> (do not remove; see note at top of file) 15 16 #include "doctest_compatibility.h" 17 18 #include <nlohmann/json.hpp> 19 using nlohmann::json; 20 21 #if JSON_HAS_RANGES 22 #include <algorithm> 23 #include <ranges> 24 #endif 25 26 TEST_CASE("iterators 2") 27 { 28 SECTION("iterator comparisons") 29 { 30 json j_values = {nullptr, true, 42, 42u, 23.23, {{"one", 1}, {"two", 2}}, {1, 2, 3, 4, 5}, "Hello, world"}; 31 32 for (json& j : j_values) 33 { 34 auto it1 = j.begin(); 35 auto it2 = j.begin(); 36 auto it3 = j.begin(); 37 ++it2; 38 ++it3; 39 ++it3; 40 auto it1_c = j.cbegin(); 41 auto it2_c = j.cbegin(); 42 auto it3_c = j.cbegin(); 43 ++it2_c; 44 ++it3_c; 45 ++it3_c; 46 47 // comparison: equal 48 { 49 CHECK(it1 == it1); 50 CHECK(!(it1 == it2)); 51 CHECK(!(it1 == it3)); 52 CHECK(!(it2 == it3)); 53 CHECK(it1_c == it1_c); 54 CHECK(!(it1_c == it2_c)); 55 CHECK(!(it1_c == it3_c)); 56 CHECK(!(it2_c == it3_c)); 57 } 58 59 // comparison: not equal 60 { 61 // check definition 62 CHECK( (it1 != it1) == !(it1 == it1) ); 63 CHECK( (it1 != it2) == !(it1 == it2) ); 64 CHECK( (it1 != it3) == !(it1 == it3) ); 65 CHECK( (it2 != it3) == !(it2 == it3) ); 66 CHECK( (it1_c != it1_c) == !(it1_c == it1_c) ); 67 CHECK( (it1_c != it2_c) == !(it1_c == it2_c) ); 68 CHECK( (it1_c != it3_c) == !(it1_c == it3_c) ); 69 CHECK( (it2_c != it3_c) == !(it2_c == it3_c) ); 70 } 71 72 // comparison: smaller 73 { 74 if (j.type() == json::value_t::object) 75 { 76 #if JSON_DIAGNOSTICS 77 CHECK_THROWS_WITH_AS(it1 < it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 78 CHECK_THROWS_WITH_AS(it1 < it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 79 CHECK_THROWS_WITH_AS(it2 < it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 80 CHECK_THROWS_WITH_AS(it1 < it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 81 CHECK_THROWS_WITH_AS(it1_c < it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 82 CHECK_THROWS_WITH_AS(it1_c < it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 83 CHECK_THROWS_WITH_AS(it2_c < it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 84 CHECK_THROWS_WITH_AS(it1_c < it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 85 #else 86 CHECK_THROWS_WITH_AS(it1 < it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 87 CHECK_THROWS_WITH_AS(it1 < it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 88 CHECK_THROWS_WITH_AS(it2 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 89 CHECK_THROWS_WITH_AS(it1 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 90 CHECK_THROWS_WITH_AS(it1_c < it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 91 CHECK_THROWS_WITH_AS(it1_c < it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 92 CHECK_THROWS_WITH_AS(it2_c < it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 93 CHECK_THROWS_WITH_AS(it1_c < it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 94 #endif 95 } 96 else 97 { 98 CHECK(!(it1 < it1)); 99 CHECK(it1 < it2); 100 CHECK(it1 < it3); 101 CHECK(it2 < it3); 102 CHECK(!(it1_c < it1_c)); 103 CHECK(it1_c < it2_c); 104 CHECK(it1_c < it3_c); 105 CHECK(it2_c < it3_c); 106 } 107 } 108 109 // comparison: less than or equal 110 { 111 if (j.type() == json::value_t::object) 112 { 113 #if JSON_DIAGNOSTICS 114 CHECK_THROWS_WITH_AS(it1 <= it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 115 CHECK_THROWS_WITH_AS(it1 <= it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 116 CHECK_THROWS_WITH_AS(it2 <= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 117 CHECK_THROWS_WITH_AS(it1 <= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 118 CHECK_THROWS_WITH_AS(it1_c <= it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 119 CHECK_THROWS_WITH_AS(it1_c <= it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 120 CHECK_THROWS_WITH_AS(it2_c <= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 121 CHECK_THROWS_WITH_AS(it1_c <= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 122 #else 123 CHECK_THROWS_WITH_AS(it1 <= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 124 CHECK_THROWS_WITH_AS(it1 <= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 125 CHECK_THROWS_WITH_AS(it2 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 126 CHECK_THROWS_WITH_AS(it1 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 127 CHECK_THROWS_WITH_AS(it1_c <= it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 128 CHECK_THROWS_WITH_AS(it1_c <= it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 129 CHECK_THROWS_WITH_AS(it2_c <= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 130 CHECK_THROWS_WITH_AS(it1_c <= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 131 #endif 132 } 133 else 134 { 135 // check definition 136 CHECK( (it1 <= it1) == !(it1 < it1) ); 137 CHECK( (it1 <= it2) == !(it2 < it1) ); 138 CHECK( (it1 <= it3) == !(it3 < it1) ); 139 CHECK( (it2 <= it3) == !(it3 < it2) ); 140 CHECK( (it1_c <= it1_c) == !(it1_c < it1_c) ); 141 CHECK( (it1_c <= it2_c) == !(it2_c < it1_c) ); 142 CHECK( (it1_c <= it3_c) == !(it3_c < it1_c) ); 143 CHECK( (it2_c <= it3_c) == !(it3_c < it2_c) ); 144 } 145 } 146 147 // comparison: greater than 148 { 149 if (j.type() == json::value_t::object) 150 { 151 #if JSON_DIAGNOSTICS 152 CHECK_THROWS_WITH_AS(it1 > it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 153 CHECK_THROWS_WITH_AS(it1 > it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 154 CHECK_THROWS_WITH_AS(it2 > it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 155 CHECK_THROWS_WITH_AS(it1 > it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 156 CHECK_THROWS_WITH_AS(it1_c > it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 157 CHECK_THROWS_WITH_AS(it1_c > it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 158 CHECK_THROWS_WITH_AS(it2_c > it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 159 CHECK_THROWS_WITH_AS(it1_c > it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 160 #else 161 CHECK_THROWS_WITH_AS(it1 > it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 162 CHECK_THROWS_WITH_AS(it1 > it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 163 CHECK_THROWS_WITH_AS(it2 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 164 CHECK_THROWS_WITH_AS(it1 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 165 CHECK_THROWS_WITH_AS(it1_c > it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 166 CHECK_THROWS_WITH_AS(it1_c > it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 167 CHECK_THROWS_WITH_AS(it2_c > it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 168 CHECK_THROWS_WITH_AS(it1_c > it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 169 #endif 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 #if JSON_DIAGNOSTICS 190 CHECK_THROWS_WITH_AS(it1 >= it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 191 CHECK_THROWS_WITH_AS(it1 >= it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 192 CHECK_THROWS_WITH_AS(it2 >= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 193 CHECK_THROWS_WITH_AS(it1 >= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 194 CHECK_THROWS_WITH_AS(it1_c >= it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 195 CHECK_THROWS_WITH_AS(it1_c >= it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 196 CHECK_THROWS_WITH_AS(it2_c >= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 197 CHECK_THROWS_WITH_AS(it1_c >= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 198 #else 199 CHECK_THROWS_WITH_AS(it1 >= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 200 CHECK_THROWS_WITH_AS(it1 >= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 201 CHECK_THROWS_WITH_AS(it2 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 202 CHECK_THROWS_WITH_AS(it1 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 203 CHECK_THROWS_WITH_AS(it1_c >= it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 204 CHECK_THROWS_WITH_AS(it1_c >= it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 205 CHECK_THROWS_WITH_AS(it2_c >= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 206 CHECK_THROWS_WITH_AS(it1_c >= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 207 #endif 208 } 209 else 210 { 211 // check definition 212 CHECK( (it1 >= it1) == !(it1 < it1) ); 213 CHECK( (it1 >= it2) == !(it1 < it2) ); 214 CHECK( (it1 >= it3) == !(it1 < it3) ); 215 CHECK( (it2 >= it3) == !(it2 < it3) ); 216 CHECK( (it1_c >= it1_c) == !(it1_c < it1_c) ); 217 CHECK( (it1_c >= it2_c) == !(it1_c < it2_c) ); 218 CHECK( (it1_c >= it3_c) == !(it1_c < it3_c) ); 219 CHECK( (it2_c >= it3_c) == !(it2_c < it3_c) ); 220 } 221 } 222 } 223 224 // check exceptions if different objects are compared 225 for (auto j : j_values) 226 { 227 for (auto k : j_values) 228 { 229 if (j != k) 230 { 231 #if JSON_DIAGNOSTICS 232 // the output differs in each loop, so we cannot fix a string for the expected exception 233 #else 234 CHECK_THROWS_WITH_AS(j.begin() == k.begin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&); 235 CHECK_THROWS_WITH_AS(j.cbegin() == k.cbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&); 236 CHECK_THROWS_WITH_AS(j.begin() < k.begin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&); 237 CHECK_THROWS_WITH_AS(j.cbegin() < k.cbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&); 238 #endif 239 } 240 } 241 } 242 } 243 244 SECTION("iterator arithmetic") 245 { 246 json j_object = {{"one", 1}, {"two", 2}, {"three", 3}}; 247 json j_array = {1, 2, 3, 4, 5, 6}; 248 json j_null = nullptr; 249 json j_value = 42; 250 251 SECTION("addition and subtraction") 252 { 253 SECTION("object") 254 { 255 { 256 auto it = j_object.begin(); 257 CHECK_THROWS_WITH_AS(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 258 } 259 { 260 auto it = j_object.cbegin(); 261 CHECK_THROWS_WITH_AS(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 262 } 263 { 264 auto it = j_object.begin(); 265 CHECK_THROWS_WITH_AS(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 266 } 267 { 268 auto it = j_object.cbegin(); 269 CHECK_THROWS_WITH_AS(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 270 } 271 { 272 auto it = j_object.begin(); 273 CHECK_THROWS_WITH_AS(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 274 } 275 { 276 auto it = j_object.cbegin(); 277 CHECK_THROWS_WITH_AS(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 278 } 279 { 280 auto it = j_object.begin(); 281 CHECK_THROWS_WITH_AS(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 282 } 283 { 284 auto it = j_object.cbegin(); 285 CHECK_THROWS_WITH_AS(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 286 } 287 { 288 auto it = j_object.begin(); 289 CHECK_THROWS_WITH_AS(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 290 } 291 { 292 auto it = j_object.cbegin(); 293 CHECK_THROWS_WITH_AS(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 294 } 295 { 296 auto it = j_object.begin(); 297 CHECK_THROWS_WITH_AS(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 298 } 299 { 300 auto it = j_object.cbegin(); 301 CHECK_THROWS_WITH_AS(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 302 } 303 } 304 305 SECTION("array") 306 { 307 { 308 auto it = j_array.begin(); 309 it += 3; 310 CHECK((j_array.begin() + 3) == it); 311 CHECK((3 + j_array.begin()) == it); 312 CHECK((it - 3) == j_array.begin()); 313 CHECK((it - j_array.begin()) == 3); 314 CHECK(*it == json(4)); 315 it -= 2; 316 CHECK(*it == json(2)); 317 } 318 { 319 auto it = j_array.cbegin(); 320 it += 3; 321 CHECK((j_array.cbegin() + 3) == it); 322 CHECK((3 + j_array.cbegin()) == it); 323 CHECK((it - 3) == j_array.cbegin()); 324 CHECK((it - j_array.cbegin()) == 3); 325 CHECK(*it == json(4)); 326 it -= 2; 327 CHECK(*it == json(2)); 328 } 329 } 330 331 SECTION("null") 332 { 333 { 334 auto it = j_null.begin(); 335 it += 3; 336 CHECK((j_null.begin() + 3) == it); 337 CHECK((3 + j_null.begin()) == it); 338 CHECK((it - 3) == j_null.begin()); 339 CHECK((it - j_null.begin()) == 3); 340 CHECK(it != j_null.end()); 341 it -= 3; 342 CHECK(it == j_null.end()); 343 } 344 { 345 auto it = j_null.cbegin(); 346 it += 3; 347 CHECK((j_null.cbegin() + 3) == it); 348 CHECK((3 + j_null.cbegin()) == it); 349 CHECK((it - 3) == j_null.cbegin()); 350 CHECK((it - j_null.cbegin()) == 3); 351 CHECK(it != j_null.cend()); 352 it -= 3; 353 CHECK(it == j_null.cend()); 354 } 355 } 356 357 SECTION("value") 358 { 359 { 360 auto it = j_value.begin(); 361 it += 3; 362 CHECK((j_value.begin() + 3) == it); 363 CHECK((3 + j_value.begin()) == it); 364 CHECK((it - 3) == j_value.begin()); 365 CHECK((it - j_value.begin()) == 3); 366 CHECK(it != j_value.end()); 367 it -= 3; 368 CHECK(*it == json(42)); 369 } 370 { 371 auto it = j_value.cbegin(); 372 it += 3; 373 CHECK((j_value.cbegin() + 3) == it); 374 CHECK((3 + j_value.cbegin()) == it); 375 CHECK((it - 3) == j_value.cbegin()); 376 CHECK((it - j_value.cbegin()) == 3); 377 CHECK(it != j_value.cend()); 378 it -= 3; 379 CHECK(*it == json(42)); 380 } 381 } 382 } 383 384 SECTION("subscript operator") 385 { 386 SECTION("object") 387 { 388 { 389 auto it = j_object.begin(); 390 CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators", json::invalid_iterator&); 391 CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators", json::invalid_iterator&); 392 } 393 { 394 auto it = j_object.cbegin(); 395 CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators", json::invalid_iterator&); 396 CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.208] cannot use operator[] for object iterators", json::invalid_iterator&); 397 } 398 } 399 400 SECTION("array") 401 { 402 { 403 auto it = j_array.begin(); 404 CHECK(it[0] == json(1)); 405 CHECK(it[1] == json(2)); 406 CHECK(it[2] == json(3)); 407 CHECK(it[3] == json(4)); 408 CHECK(it[4] == json(5)); 409 CHECK(it[5] == json(6)); 410 } 411 { 412 auto it = j_array.cbegin(); 413 CHECK(it[0] == json(1)); 414 CHECK(it[1] == json(2)); 415 CHECK(it[2] == json(3)); 416 CHECK(it[3] == json(4)); 417 CHECK(it[4] == json(5)); 418 CHECK(it[5] == json(6)); 419 } 420 } 421 422 SECTION("null") 423 { 424 { 425 auto it = j_null.begin(); 426 CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&); 427 CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&); 428 } 429 { 430 auto it = j_null.cbegin(); 431 CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&); 432 CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&); 433 } 434 } 435 436 SECTION("value") 437 { 438 { 439 auto it = j_value.begin(); 440 CHECK(it[0] == json(42)); 441 CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&); 442 } 443 { 444 auto it = j_value.cbegin(); 445 CHECK(it[0] == json(42)); 446 CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&); 447 } 448 } 449 } 450 } 451 452 SECTION("reverse iterator comparisons") 453 { 454 json j_values = {nullptr, true, 42, 42u, 23.23, {{"one", 1}, {"two", 2}}, {1, 2, 3, 4, 5}, "Hello, world"}; 455 456 for (json& j : j_values) 457 { 458 auto it1 = j.rbegin(); 459 auto it2 = j.rbegin(); 460 auto it3 = j.rbegin(); 461 ++it2; 462 ++it3; 463 ++it3; 464 auto it1_c = j.crbegin(); 465 auto it2_c = j.crbegin(); 466 auto it3_c = j.crbegin(); 467 ++it2_c; 468 ++it3_c; 469 ++it3_c; 470 471 // comparison: equal 472 { 473 CHECK(it1 == it1); 474 CHECK(!(it1 == it2)); 475 CHECK(!(it1 == it3)); 476 CHECK(!(it2 == it3)); 477 CHECK(it1_c == it1_c); 478 CHECK(!(it1_c == it2_c)); 479 CHECK(!(it1_c == it3_c)); 480 CHECK(!(it2_c == it3_c)); 481 } 482 483 // comparison: not equal 484 { 485 // check definition 486 CHECK( (it1 != it1) == !(it1 == it1) ); 487 CHECK( (it1 != it2) == !(it1 == it2) ); 488 CHECK( (it1 != it3) == !(it1 == it3) ); 489 CHECK( (it2 != it3) == !(it2 == it3) ); 490 CHECK( (it1_c != it1_c) == !(it1_c == it1_c) ); 491 CHECK( (it1_c != it2_c) == !(it1_c == it2_c) ); 492 CHECK( (it1_c != it3_c) == !(it1_c == it3_c) ); 493 CHECK( (it2_c != it3_c) == !(it2_c == it3_c) ); 494 } 495 496 // comparison: smaller 497 { 498 if (j.type() == json::value_t::object) 499 { 500 #if JSON_DIAGNOSTICS 501 CHECK_THROWS_WITH_AS(it1 < it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 502 CHECK_THROWS_WITH_AS(it1 < it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 503 CHECK_THROWS_WITH_AS(it2 < it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 504 CHECK_THROWS_WITH_AS(it1 < it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 505 CHECK_THROWS_WITH_AS(it1_c < it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 506 CHECK_THROWS_WITH_AS(it1_c < it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 507 CHECK_THROWS_WITH_AS(it2_c < it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 508 CHECK_THROWS_WITH_AS(it1_c < it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 509 #else 510 CHECK_THROWS_WITH_AS(it1 < it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 511 CHECK_THROWS_WITH_AS(it1 < it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 512 CHECK_THROWS_WITH_AS(it2 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 513 CHECK_THROWS_WITH_AS(it1 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 514 CHECK_THROWS_WITH_AS(it1_c < it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 515 CHECK_THROWS_WITH_AS(it1_c < it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 516 CHECK_THROWS_WITH_AS(it2_c < it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 517 CHECK_THROWS_WITH_AS(it1_c < it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 518 #endif 519 } 520 else 521 { 522 CHECK(!(it1 < it1)); 523 CHECK(it1 < it2); 524 CHECK(it1 < it3); 525 CHECK(it2 < it3); 526 CHECK(!(it1_c < it1_c)); 527 CHECK(it1_c < it2_c); 528 CHECK(it1_c < it3_c); 529 CHECK(it2_c < it3_c); 530 } 531 } 532 533 // comparison: less than or equal 534 { 535 if (j.type() == json::value_t::object) 536 { 537 #if JSON_DIAGNOSTICS 538 CHECK_THROWS_WITH_AS(it1 <= it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 539 CHECK_THROWS_WITH_AS(it1 <= it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 540 CHECK_THROWS_WITH_AS(it2 <= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 541 CHECK_THROWS_WITH_AS(it1 <= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 542 CHECK_THROWS_WITH_AS(it1_c <= it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 543 CHECK_THROWS_WITH_AS(it1_c <= it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 544 CHECK_THROWS_WITH_AS(it2_c <= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 545 CHECK_THROWS_WITH_AS(it1_c <= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 546 #else 547 CHECK_THROWS_WITH_AS(it1 <= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 548 CHECK_THROWS_WITH_AS(it1 <= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 549 CHECK_THROWS_WITH_AS(it2 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 550 CHECK_THROWS_WITH_AS(it1 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 551 CHECK_THROWS_WITH_AS(it1_c <= it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 552 CHECK_THROWS_WITH_AS(it1_c <= it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 553 CHECK_THROWS_WITH_AS(it2_c <= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 554 CHECK_THROWS_WITH_AS(it1_c <= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 555 #endif 556 } 557 else 558 { 559 // check definition 560 CHECK( (it1 <= it1) == !(it1 < it1) ); 561 CHECK( (it1 <= it2) == !(it2 < it1) ); 562 CHECK( (it1 <= it3) == !(it3 < it1) ); 563 CHECK( (it2 <= it3) == !(it3 < it2) ); 564 CHECK( (it1_c <= it1_c) == !(it1_c < it1_c) ); 565 CHECK( (it1_c <= it2_c) == !(it2_c < it1_c) ); 566 CHECK( (it1_c <= it3_c) == !(it3_c < it1_c) ); 567 CHECK( (it2_c <= it3_c) == !(it3_c < it2_c) ); 568 } 569 } 570 571 // comparison: greater than 572 { 573 if (j.type() == json::value_t::object) 574 { 575 #if JSON_DIAGNOSTICS 576 CHECK_THROWS_WITH_AS(it1 > it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 577 CHECK_THROWS_WITH_AS(it1 > it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 578 CHECK_THROWS_WITH_AS(it2 > it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 579 CHECK_THROWS_WITH_AS(it1 > it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 580 CHECK_THROWS_WITH_AS(it1_c > it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 581 CHECK_THROWS_WITH_AS(it1_c > it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 582 CHECK_THROWS_WITH_AS(it2_c > it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 583 CHECK_THROWS_WITH_AS(it1_c > it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 584 #else 585 CHECK_THROWS_WITH_AS(it1 > it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 586 CHECK_THROWS_WITH_AS(it1 > it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 587 CHECK_THROWS_WITH_AS(it2 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 588 CHECK_THROWS_WITH_AS(it1 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 589 CHECK_THROWS_WITH_AS(it1_c > it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 590 CHECK_THROWS_WITH_AS(it1_c > it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 591 CHECK_THROWS_WITH_AS(it2_c > it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 592 CHECK_THROWS_WITH_AS(it1_c > it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 593 #endif 594 } 595 else 596 { 597 // check definition 598 CHECK( (it1 > it1) == (it1 < it1) ); 599 CHECK( (it1 > it2) == (it2 < it1) ); 600 CHECK( (it1 > it3) == (it3 < it1) ); 601 CHECK( (it2 > it3) == (it3 < it2) ); 602 CHECK( (it1_c > it1_c) == (it1_c < it1_c) ); 603 CHECK( (it1_c > it2_c) == (it2_c < it1_c) ); 604 CHECK( (it1_c > it3_c) == (it3_c < it1_c) ); 605 CHECK( (it2_c > it3_c) == (it3_c < it2_c) ); 606 } 607 } 608 609 // comparison: greater than or equal 610 { 611 if (j.type() == json::value_t::object) 612 { 613 #if JSON_DIAGNOSTICS 614 CHECK_THROWS_WITH_AS(it1 >= it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 615 CHECK_THROWS_WITH_AS(it1 >= it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 616 CHECK_THROWS_WITH_AS(it2 >= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 617 CHECK_THROWS_WITH_AS(it1 >= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 618 CHECK_THROWS_WITH_AS(it1_c >= it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 619 CHECK_THROWS_WITH_AS(it1_c >= it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 620 CHECK_THROWS_WITH_AS(it2_c >= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 621 CHECK_THROWS_WITH_AS(it1_c >= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&); 622 #else 623 CHECK_THROWS_WITH_AS(it1 >= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 624 CHECK_THROWS_WITH_AS(it1 >= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 625 CHECK_THROWS_WITH_AS(it2 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 626 CHECK_THROWS_WITH_AS(it1 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 627 CHECK_THROWS_WITH_AS(it1_c >= it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 628 CHECK_THROWS_WITH_AS(it1_c >= it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 629 CHECK_THROWS_WITH_AS(it2_c >= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 630 CHECK_THROWS_WITH_AS(it1_c >= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&); 631 #endif 632 } 633 else 634 { 635 // check definition 636 CHECK( (it1 >= it1) == !(it1 < it1) ); 637 CHECK( (it1 >= it2) == !(it1 < it2) ); 638 CHECK( (it1 >= it3) == !(it1 < it3) ); 639 CHECK( (it2 >= it3) == !(it2 < it3) ); 640 CHECK( (it1_c >= it1_c) == !(it1_c < it1_c) ); 641 CHECK( (it1_c >= it2_c) == !(it1_c < it2_c) ); 642 CHECK( (it1_c >= it3_c) == !(it1_c < it3_c) ); 643 CHECK( (it2_c >= it3_c) == !(it2_c < it3_c) ); 644 } 645 } 646 } 647 648 // check exceptions if different objects are compared 649 for (auto j : j_values) 650 { 651 for (auto k : j_values) 652 { 653 if (j != k) 654 { 655 #if JSON_DIAGNOSTICS 656 // the output differs in each loop, so we cannot fix a string for the expected exception 657 #else 658 CHECK_THROWS_WITH_AS(j.rbegin() == k.rbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&); 659 CHECK_THROWS_WITH_AS(j.crbegin() == k.crbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&); 660 CHECK_THROWS_WITH_AS(j.rbegin() < k.rbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&); 661 CHECK_THROWS_WITH_AS(j.crbegin() < k.crbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&); 662 #endif 663 } 664 } 665 } 666 } 667 668 SECTION("reverse iterator arithmetic") 669 { 670 json j_object = {{"one", 1}, {"two", 2}, {"three", 3}}; 671 json j_array = {1, 2, 3, 4, 5, 6}; 672 json j_null = nullptr; 673 json j_value = 42; 674 675 SECTION("addition and subtraction") 676 { 677 SECTION("object") 678 { 679 { 680 auto it = j_object.rbegin(); 681 CHECK_THROWS_WITH_AS(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 682 } 683 { 684 auto it = j_object.crbegin(); 685 CHECK_THROWS_WITH_AS(it += 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 686 } 687 { 688 auto it = j_object.rbegin(); 689 CHECK_THROWS_WITH_AS(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 690 } 691 { 692 auto it = j_object.crbegin(); 693 CHECK_THROWS_WITH_AS(it + 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 694 } 695 { 696 auto it = j_object.rbegin(); 697 CHECK_THROWS_WITH_AS(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 698 } 699 { 700 auto it = j_object.crbegin(); 701 CHECK_THROWS_WITH_AS(1 + it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 702 } 703 { 704 auto it = j_object.rbegin(); 705 CHECK_THROWS_WITH_AS(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 706 } 707 { 708 auto it = j_object.crbegin(); 709 CHECK_THROWS_WITH_AS(it -= 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 710 } 711 { 712 auto it = j_object.rbegin(); 713 CHECK_THROWS_WITH_AS(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 714 } 715 { 716 auto it = j_object.crbegin(); 717 CHECK_THROWS_WITH_AS(it - 1, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 718 } 719 { 720 auto it = j_object.rbegin(); 721 CHECK_THROWS_WITH_AS(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 722 } 723 { 724 auto it = j_object.crbegin(); 725 CHECK_THROWS_WITH_AS(it - it, "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 726 } 727 } 728 729 SECTION("array") 730 { 731 { 732 auto it = j_array.rbegin(); 733 it += 3; 734 CHECK((j_array.rbegin() + 3) == it); 735 CHECK(json::reverse_iterator(3 + j_array.rbegin()) == it); 736 CHECK((it - 3) == j_array.rbegin()); 737 CHECK((it - j_array.rbegin()) == 3); 738 CHECK(*it == json(3)); 739 it -= 2; 740 CHECK(*it == json(5)); 741 } 742 { 743 auto it = j_array.crbegin(); 744 it += 3; 745 CHECK((j_array.crbegin() + 3) == it); 746 CHECK(json::const_reverse_iterator(3 + j_array.crbegin()) == it); 747 CHECK((it - 3) == j_array.crbegin()); 748 CHECK((it - j_array.crbegin()) == 3); 749 CHECK(*it == json(3)); 750 it -= 2; 751 CHECK(*it == json(5)); 752 } 753 } 754 755 SECTION("null") 756 { 757 { 758 auto it = j_null.rbegin(); 759 it += 3; 760 CHECK((j_null.rbegin() + 3) == it); 761 CHECK(json::reverse_iterator(3 + j_null.rbegin()) == it); 762 CHECK((it - 3) == j_null.rbegin()); 763 CHECK((it - j_null.rbegin()) == 3); 764 CHECK(it != j_null.rend()); 765 it -= 3; 766 CHECK(it == j_null.rend()); 767 } 768 { 769 auto it = j_null.crbegin(); 770 it += 3; 771 CHECK((j_null.crbegin() + 3) == it); 772 CHECK(json::const_reverse_iterator(3 + j_null.crbegin()) == it); 773 CHECK((it - 3) == j_null.crbegin()); 774 CHECK((it - j_null.crbegin()) == 3); 775 CHECK(it != j_null.crend()); 776 it -= 3; 777 CHECK(it == j_null.crend()); 778 } 779 } 780 781 SECTION("value") 782 { 783 { 784 auto it = j_value.rbegin(); 785 it += 3; 786 CHECK((j_value.rbegin() + 3) == it); 787 CHECK(json::reverse_iterator(3 + j_value.rbegin()) == it); 788 CHECK((it - 3) == j_value.rbegin()); 789 CHECK((it - j_value.rbegin()) == 3); 790 CHECK(it != j_value.rend()); 791 it -= 3; 792 CHECK(*it == json(42)); 793 } 794 { 795 auto it = j_value.crbegin(); 796 it += 3; 797 CHECK((j_value.crbegin() + 3) == it); 798 CHECK(json::const_reverse_iterator(3 + j_value.crbegin()) == it); 799 CHECK((it - 3) == j_value.crbegin()); 800 CHECK((it - j_value.crbegin()) == 3); 801 CHECK(it != j_value.crend()); 802 it -= 3; 803 CHECK(*it == json(42)); 804 } 805 } 806 } 807 808 SECTION("subscript operator") 809 { 810 SECTION("object") 811 { 812 { 813 auto it = j_object.rbegin(); 814 CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 815 CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 816 } 817 { 818 auto it = j_object.crbegin(); 819 CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 820 CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&); 821 } 822 } 823 824 SECTION("array") 825 { 826 { 827 auto it = j_array.rbegin(); 828 CHECK(it[0] == json(6)); 829 CHECK(it[1] == json(5)); 830 CHECK(it[2] == json(4)); 831 CHECK(it[3] == json(3)); 832 CHECK(it[4] == json(2)); 833 CHECK(it[5] == json(1)); 834 } 835 { 836 auto it = j_array.crbegin(); 837 CHECK(it[0] == json(6)); 838 CHECK(it[1] == json(5)); 839 CHECK(it[2] == json(4)); 840 CHECK(it[3] == json(3)); 841 CHECK(it[4] == json(2)); 842 CHECK(it[5] == json(1)); 843 } 844 } 845 846 SECTION("null") 847 { 848 { 849 auto it = j_null.rbegin(); 850 CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&); 851 CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&); 852 } 853 { 854 auto it = j_null.crbegin(); 855 CHECK_THROWS_WITH_AS(it[0], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&); 856 CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&); 857 } 858 } 859 860 SECTION("value") 861 { 862 { 863 auto it = j_value.rbegin(); 864 CHECK(it[0] == json(42)); 865 CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&); 866 } 867 { 868 auto it = j_value.crbegin(); 869 CHECK(it[0] == json(42)); 870 CHECK_THROWS_WITH_AS(it[1], "[json.exception.invalid_iterator.214] cannot get value", json::invalid_iterator&); 871 } 872 } 873 } 874 } 875 876 877 #if JSON_HAS_RANGES 878 // JSON_HAS_CPP_20 (do not remove; see note at top of file) 879 SECTION("ranges") 880 { 881 SECTION("concepts") 882 { 883 using nlohmann::detail::iteration_proxy_value; 884 CHECK(std::bidirectional_iterator<json::iterator>); 885 CHECK(std::input_iterator<iteration_proxy_value<json::iterator>>); 886 887 CHECK(std::is_same<json::iterator, std::ranges::iterator_t<json>>::value); 888 CHECK(std::ranges::bidirectional_range<json>); 889 890 using nlohmann::detail::iteration_proxy; 891 using items_type = decltype(std::declval<json&>().items()); 892 CHECK(std::is_same<items_type, iteration_proxy<json::iterator>>::value); 893 CHECK(std::is_same<iteration_proxy_value<json::iterator>, std::ranges::iterator_t<items_type>>::value); 894 CHECK(std::ranges::input_range<items_type>); 895 } 896 897 // libstdc++ algorithms don't work with Clang 15 (04/2022) 898 #if !DOCTEST_CLANG || (DOCTEST_CLANG && defined(__GLIBCXX__)) 899 SECTION("algorithms") 900 { 901 SECTION("copy") 902 { 903 json j{"foo", "bar"}; 904 auto j_copied = json::array(); 905 906 std::ranges::copy(j, std::back_inserter(j_copied)); 907 908 CHECK(j == j_copied); 909 } 910 911 SECTION("find_if") 912 { 913 json j{1, 3, 2, 4}; 914 auto j_even = json::array(); 915 916 #if JSON_USE_IMPLICIT_CONVERSIONS 917 auto it = std::ranges::find_if(j, [](int v) noexcept __anon1ab329320102(int v) 918 { 919 return (v % 2) == 0; 920 }); 921 #else 922 auto it = std::ranges::find_if(j, [](const json & j) noexcept __anon1ab329320202(const json & j) 923 { 924 int v; 925 j.get_to(v); 926 return (v % 2) == 0; 927 }); 928 #endif 929 930 CHECK(*it == 2); 931 } 932 } 933 #endif 934 935 // libstdc++ views don't work with Clang 15 (04/2022) 936 // libc++ hides limited ranges implementation behind guard macro 937 #if !(DOCTEST_CLANG && (defined(__GLIBCXX__) || defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES))) 938 SECTION("views") 939 { 940 SECTION("reverse") 941 { 942 json j{1, 2, 3, 4, 5}; 943 json j_expected{5, 4, 3, 2, 1}; 944 945 auto reversed = j | std::views::reverse; 946 CHECK(reversed == j_expected); 947 } 948 949 SECTION("transform") 950 { 951 json j 952 { 953 { "a_key", "a_value"}, 954 { "b_key", "b_value"}, 955 { "c_key", "c_value"}, 956 }; 957 json j_expected{"a_key", "b_key", "c_key"}; 958 959 auto transformed = j.items() | std::views::transform([](const auto & item) __anon1ab329320302(const auto & item) 960 { 961 return item.key(); 962 }); 963 auto j_transformed = json::array(); 964 std::ranges::copy(transformed, std::back_inserter(j_transformed)); 965 966 CHECK(j_transformed == j_expected); 967 } 968 } 969 #endif 970 } 971 #endif 972 } 973