unit.cpp
Go to the documentation of this file.
00001 /*
00002     __ _____ _____ _____
00003  __|  |   __|     |   | |  JSON for Modern C++ (test suite)
00004 |  |  |__   |  |  | | | |  version 2.0.0
00005 |_____|_____|_____|_|___|  https://github.com/nlohmann/json
00006 
00007 Licensed under the MIT License <http://opensource.org/licenses/MIT>.
00008 Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
00009 
00010 Permission is hereby  granted, free of charge, to any  person obtaining a copy
00011 of this software and associated  documentation files (the "Software"), to deal
00012 in the Software  without restriction, including without  limitation the rights
00013 to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
00014 copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
00015 furnished to do so, subject to the following conditions:
00016 
00017 The above copyright notice and this permission notice shall be included in all
00018 copies or substantial portions of the Software.
00019 
00020 THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR
00021 IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,
00022 FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
00023 AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
00024 LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00025 OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
00026 SOFTWARE.
00027 */
00028 
00029 #define CATCH_CONFIG_MAIN
00030 #include "catch.hpp"
00031 
00032 #include <array>
00033 #include <deque>
00034 #include <forward_list>
00035 #include <list>
00036 #include <map>
00037 #include <set>
00038 #include <string>
00039 #include <unordered_map>
00040 #include <unordered_set>
00041 #include <vector>
00042 
00043 #define private public
00044 #include "json.hpp"
00045 using nlohmann::json;
00046 
00047 // disable float-equal warnings on GCC/clang
00048 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
00049     #pragma GCC diagnostic ignored "-Wfloat-equal"
00050 #endif
00051 
00052 TEST_CASE("constructors")
00053 {
00054     SECTION("create an empty value with a given type")
00055     {
00056         SECTION("null")
00057         {
00058             auto t = json::value_t::null;
00059             json j(t);
00060             CHECK(j.type() == t);
00061         }
00062 
00063         SECTION("discarded")
00064         {
00065             auto t = json::value_t::discarded;
00066             json j(t);
00067             CHECK(j.type() == t);
00068         }
00069 
00070         SECTION("object")
00071         {
00072             auto t = json::value_t::object;
00073             json j(t);
00074             CHECK(j.type() == t);
00075         }
00076 
00077         SECTION("array")
00078         {
00079             auto t = json::value_t::array;
00080             json j(t);
00081             CHECK(j.type() == t);
00082         }
00083 
00084         SECTION("boolean")
00085         {
00086             auto t = json::value_t::boolean;
00087             json j(t);
00088             CHECK(j.type() == t);
00089         }
00090 
00091         SECTION("string")
00092         {
00093             auto t = json::value_t::string;
00094             json j(t);
00095             CHECK(j.type() == t);
00096         }
00097 
00098         SECTION("number_integer")
00099         {
00100             auto t = json::value_t::number_integer;
00101             json j(t);
00102             CHECK(j.type() == t);
00103         }
00104 
00105         SECTION("number_unsigned")
00106         {
00107             auto t = json::value_t::number_unsigned;
00108             json j(t);
00109             CHECK(j.type() == t);
00110         }
00111 
00112         SECTION("number_float")
00113         {
00114             auto t = json::value_t::number_float;
00115             json j(t);
00116             CHECK(j.type() == t);
00117         }
00118     }
00119 
00120     SECTION("create a null object (implicitly)")
00121     {
00122         SECTION("no parameter")
00123         {
00124             json j{};
00125             CHECK(j.type() == json::value_t::null);
00126         }
00127     }
00128 
00129     SECTION("create a null object (explicitly)")
00130     {
00131         SECTION("parameter")
00132         {
00133             json j(nullptr);
00134             CHECK(j.type() == json::value_t::null);
00135         }
00136     }
00137 
00138     SECTION("create an object (explicit)")
00139     {
00140         SECTION("empty object")
00141         {
00142             json::object_t o;
00143             json j(o);
00144             CHECK(j.type() == json::value_t::object);
00145         }
00146 
00147         SECTION("filled object")
00148         {
00149             json::object_t o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
00150             json j(o);
00151             CHECK(j.type() == json::value_t::object);
00152         }
00153     }
00154 
00155     SECTION("create an object (implicit)")
00156     {
00157         // reference object
00158         json::object_t o_reference {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
00159         json j_reference(o_reference);
00160 
00161         SECTION("std::map<json::string_t, json>")
00162         {
00163             std::map<json::string_t, json> o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
00164             json j(o);
00165             CHECK(j.type() == json::value_t::object);
00166             CHECK(j == j_reference);
00167         }
00168 
00169         SECTION("std::map<const char*, json>")
00170         {
00171             std::map<const char*, json> o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
00172             json j(o);
00173             CHECK(j.type() == json::value_t::object);
00174             CHECK(j == j_reference);
00175         }
00176 
00177         SECTION("std::multimap<json::string_t, json>")
00178         {
00179             std::multimap<json::string_t, json> o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
00180             json j(o);
00181             CHECK(j.type() == json::value_t::object);
00182             CHECK(j == j_reference);
00183         }
00184 
00185         SECTION("std::unordered_map<json::string_t, json>")
00186         {
00187             std::unordered_map<json::string_t, json> o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
00188             json j(o);
00189             CHECK(j.type() == json::value_t::object);
00190             CHECK(j == j_reference);
00191         }
00192 
00193         SECTION("std::unordered_multimap<json::string_t, json>")
00194         {
00195             std::unordered_multimap<json::string_t, json> o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
00196             json j(o);
00197             CHECK(j.type() == json::value_t::object);
00198             CHECK(j == j_reference);
00199         }
00200 
00201         SECTION("associative container literal")
00202         {
00203             json j({{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}});
00204             CHECK(j.type() == json::value_t::object);
00205             CHECK(j == j_reference);
00206         }
00207     }
00208 
00209     SECTION("create an array (explicit)")
00210     {
00211         SECTION("empty array")
00212         {
00213             json::array_t a;
00214             json j(a);
00215             CHECK(j.type() == json::value_t::array);
00216         }
00217 
00218         SECTION("filled array")
00219         {
00220             json::array_t a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
00221             json j(a);
00222             CHECK(j.type() == json::value_t::array);
00223         }
00224     }
00225 
00226     SECTION("create an array (implicit)")
00227     {
00228         // reference array
00229         json::array_t a_reference {json(1), json(1u), json(2.2), json(false), json("string"), json()};
00230         json j_reference(a_reference);
00231 
00232         SECTION("std::list<json>")
00233         {
00234             std::list<json> a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
00235             json j(a);
00236             CHECK(j.type() == json::value_t::array);
00237             CHECK(j == j_reference);
00238         }
00239 
00240         SECTION("std::forward_list<json>")
00241         {
00242             std::forward_list<json> a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
00243             json j(a);
00244             CHECK(j.type() == json::value_t::array);
00245             CHECK(j == j_reference);
00246         }
00247 
00248         SECTION("std::array<json, 5>")
00249         {
00250             std::array<json, 6> a {{json(1), json(1u), json(2.2), json(false), json("string"), json()}};
00251             json j(a);
00252             CHECK(j.type() == json::value_t::array);
00253             CHECK(j == j_reference);
00254         }
00255 
00256         SECTION("std::vector<json>")
00257         {
00258             std::vector<json> a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
00259             json j(a);
00260             CHECK(j.type() == json::value_t::array);
00261             CHECK(j == j_reference);
00262         }
00263 
00264         SECTION("std::deque<json>")
00265         {
00266             std::deque<json> a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
00267             json j(a);
00268             CHECK(j.type() == json::value_t::array);
00269             CHECK(j == j_reference);
00270         }
00271 
00272         SECTION("std::set<json>")
00273         {
00274             std::set<json> a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
00275             json j(a);
00276             CHECK(j.type() == json::value_t::array);
00277             // we cannot really check for equality here
00278         }
00279 
00280         SECTION("std::unordered_set<json>")
00281         {
00282             std::unordered_set<json> a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
00283             json j(a);
00284             CHECK(j.type() == json::value_t::array);
00285             // we cannot really check for equality here
00286         }
00287 
00288         SECTION("sequence container literal")
00289         {
00290             json j({json(1), json(1u), json(2.2), json(false), json("string"), json()});
00291             CHECK(j.type() == json::value_t::array);
00292             CHECK(j == j_reference);
00293         }
00294     }
00295 
00296     SECTION("create a string (explicit)")
00297     {
00298         SECTION("empty string")
00299         {
00300             json::string_t s;
00301             json j(s);
00302             CHECK(j.type() == json::value_t::string);
00303         }
00304 
00305         SECTION("filled string")
00306         {
00307             json::string_t s {"Hello world"};
00308             json j(s);
00309             CHECK(j.type() == json::value_t::string);
00310         }
00311     }
00312 
00313     SECTION("create a string (implicit)")
00314     {
00315         // reference string
00316         json::string_t s_reference {"Hello world"};
00317         json j_reference(s_reference);
00318 
00319         SECTION("std::string")
00320         {
00321             std::string s {"Hello world"};
00322             json j(s);
00323             CHECK(j.type() == json::value_t::string);
00324             CHECK(j == j_reference);
00325         }
00326 
00327         SECTION("char[]")
00328         {
00329             char s[] {"Hello world"};
00330             json j(s);
00331             CHECK(j.type() == json::value_t::string);
00332             CHECK(j == j_reference);
00333         }
00334 
00335         SECTION("const char*")
00336         {
00337             const char* s {"Hello world"};
00338             json j(s);
00339             CHECK(j.type() == json::value_t::string);
00340             CHECK(j == j_reference);
00341         }
00342 
00343         SECTION("string literal")
00344         {
00345             json j("Hello world");
00346             CHECK(j.type() == json::value_t::string);
00347             CHECK(j == j_reference);
00348         }
00349     }
00350 
00351     SECTION("create a boolean (explicit)")
00352     {
00353         SECTION("empty boolean")
00354         {
00355             json::boolean_t b{};
00356             json j(b);
00357             CHECK(j.type() == json::value_t::boolean);
00358         }
00359 
00360         SECTION("filled boolean (true)")
00361         {
00362             json j(true);
00363             CHECK(j.type() == json::value_t::boolean);
00364         }
00365 
00366         SECTION("filled boolean (false)")
00367         {
00368             json j(false);
00369             CHECK(j.type() == json::value_t::boolean);
00370         }
00371     }
00372 
00373     SECTION("create an integer number (explicit)")
00374     {
00375         SECTION("uninitialized value")
00376         {
00377             json::number_integer_t n{};
00378             json j(n);
00379             CHECK(j.type() == json::value_t::number_integer);
00380         }
00381 
00382         SECTION("initialized value")
00383         {
00384             json::number_integer_t n(42);
00385             json j(n);
00386             CHECK(j.type() == json::value_t::number_integer);
00387         }
00388     }
00389 
00390     SECTION("create an integer number (implicit)")
00391     {
00392         // reference objects
00393         json::number_integer_t n_reference = 42;
00394         json j_reference(n_reference);
00395         json::number_unsigned_t n_unsigned_reference = 42;
00396         json j_unsigned_reference(n_unsigned_reference);
00397 
00398         SECTION("short")
00399         {
00400             short n = 42;
00401             json j(n);
00402             CHECK(j.type() == json::value_t::number_integer);
00403             CHECK(j == j_reference);
00404         }
00405 
00406         SECTION("unsigned short")
00407         {
00408             unsigned short n = 42;
00409             json j(n);
00410             CHECK(j.type() == json::value_t::number_unsigned);
00411             CHECK(j == j_unsigned_reference);
00412         }
00413 
00414         SECTION("int")
00415         {
00416             int n = 42;
00417             json j(n);
00418             CHECK(j.type() == json::value_t::number_integer);
00419             CHECK(j == j_reference);
00420         }
00421 
00422         SECTION("unsigned int")
00423         {
00424             unsigned int n = 42;
00425             json j(n);
00426             CHECK(j.type() == json::value_t::number_unsigned);
00427             CHECK(j == j_unsigned_reference);
00428         }
00429 
00430         SECTION("long")
00431         {
00432             long n = 42;
00433             json j(n);
00434             CHECK(j.type() == json::value_t::number_integer);
00435             CHECK(j == j_reference);
00436         }
00437 
00438         SECTION("unsigned long")
00439         {
00440             unsigned long n = 42;
00441             json j(n);
00442             CHECK(j.type() == json::value_t::number_unsigned);
00443             CHECK(j == j_unsigned_reference);
00444         }
00445 
00446         SECTION("long long")
00447         {
00448             long long n = 42;
00449             json j(n);
00450             CHECK(j.type() == json::value_t::number_integer);
00451             CHECK(j == j_reference);
00452         }
00453 
00454         SECTION("unsigned long long")
00455         {
00456             unsigned long long n = 42;
00457             json j(n);
00458             CHECK(j.type() == json::value_t::number_unsigned);
00459             CHECK(j == j_unsigned_reference);
00460         }
00461 
00462         SECTION("int8_t")
00463         {
00464             int8_t n = 42;
00465             json j(n);
00466             CHECK(j.type() == json::value_t::number_integer);
00467             CHECK(j == j_reference);
00468         }
00469 
00470         SECTION("int16_t")
00471         {
00472             int16_t n = 42;
00473             json j(n);
00474             CHECK(j.type() == json::value_t::number_integer);
00475             CHECK(j == j_reference);
00476         }
00477 
00478         SECTION("int32_t")
00479         {
00480             int32_t n = 42;
00481             json j(n);
00482             CHECK(j.type() == json::value_t::number_integer);
00483             CHECK(j == j_reference);
00484         }
00485 
00486         SECTION("int64_t")
00487         {
00488             int64_t n = 42;
00489             json j(n);
00490             CHECK(j.type() == json::value_t::number_integer);
00491             CHECK(j == j_reference);
00492         }
00493 
00494         SECTION("int_fast8_t")
00495         {
00496             int_fast8_t n = 42;
00497             json j(n);
00498             CHECK(j.type() == json::value_t::number_integer);
00499             CHECK(j == j_reference);
00500         }
00501 
00502         SECTION("int_fast16_t")
00503         {
00504             int_fast16_t n = 42;
00505             json j(n);
00506             CHECK(j.type() == json::value_t::number_integer);
00507             CHECK(j == j_reference);
00508         }
00509 
00510         SECTION("int_fast32_t")
00511         {
00512             int_fast32_t n = 42;
00513             json j(n);
00514             CHECK(j.type() == json::value_t::number_integer);
00515             CHECK(j == j_reference);
00516         }
00517 
00518         SECTION("int_fast64_t")
00519         {
00520             int_fast64_t n = 42;
00521             json j(n);
00522             CHECK(j.type() == json::value_t::number_integer);
00523             CHECK(j == j_reference);
00524         }
00525 
00526         SECTION("int_least8_t")
00527         {
00528             int_least8_t n = 42;
00529             json j(n);
00530             CHECK(j.type() == json::value_t::number_integer);
00531             CHECK(j == j_reference);
00532         }
00533 
00534         SECTION("int_least16_t")
00535         {
00536             int_least16_t n = 42;
00537             json j(n);
00538             CHECK(j.type() == json::value_t::number_integer);
00539             CHECK(j == j_reference);
00540         }
00541 
00542         SECTION("int_least32_t")
00543         {
00544             int_least32_t n = 42;
00545             json j(n);
00546             CHECK(j.type() == json::value_t::number_integer);
00547             CHECK(j == j_reference);
00548         }
00549 
00550         SECTION("int_least64_t")
00551         {
00552             int_least64_t n = 42;
00553             json j(n);
00554             CHECK(j.type() == json::value_t::number_integer);
00555             CHECK(j == j_reference);
00556         }
00557 
00558         SECTION("uint8_t")
00559         {
00560             uint8_t n = 42;
00561             json j(n);
00562             CHECK(j.type() == json::value_t::number_unsigned);
00563             CHECK(j == j_unsigned_reference);
00564         }
00565 
00566         SECTION("uint16_t")
00567         {
00568             uint16_t n = 42;
00569             json j(n);
00570             CHECK(j.type() == json::value_t::number_unsigned);
00571             CHECK(j == j_unsigned_reference);
00572         }
00573 
00574         SECTION("uint32_t")
00575         {
00576             uint32_t n = 42;
00577             json j(n);
00578             CHECK(j.type() == json::value_t::number_unsigned);
00579             CHECK(j == j_unsigned_reference);
00580         }
00581 
00582         SECTION("uint64_t")
00583         {
00584             uint64_t n = 42;
00585             json j(n);
00586             CHECK(j.type() == json::value_t::number_unsigned);
00587             CHECK(j == j_unsigned_reference);
00588         }
00589 
00590         SECTION("uint_fast8_t")
00591         {
00592             uint_fast8_t n = 42;
00593             json j(n);
00594             CHECK(j.type() == json::value_t::number_unsigned);
00595             CHECK(j == j_unsigned_reference);
00596         }
00597 
00598         SECTION("uint_fast16_t")
00599         {
00600             uint_fast16_t n = 42;
00601             json j(n);
00602             CHECK(j.type() == json::value_t::number_unsigned);
00603             CHECK(j == j_unsigned_reference);
00604         }
00605 
00606         SECTION("uint_fast32_t")
00607         {
00608             uint_fast32_t n = 42;
00609             json j(n);
00610             CHECK(j.type() == json::value_t::number_unsigned);
00611             CHECK(j == j_unsigned_reference);
00612         }
00613 
00614         SECTION("uint_fast64_t")
00615         {
00616             uint_fast64_t n = 42;
00617             json j(n);
00618             CHECK(j.type() == json::value_t::number_unsigned);
00619             CHECK(j == j_unsigned_reference);
00620         }
00621 
00622         SECTION("uint_least8_t")
00623         {
00624             uint_least8_t n = 42;
00625             json j(n);
00626             CHECK(j.type() == json::value_t::number_unsigned);
00627             CHECK(j == j_unsigned_reference);
00628         }
00629 
00630         SECTION("uint_least16_t")
00631         {
00632             uint_least16_t n = 42;
00633             json j(n);
00634             CHECK(j.type() == json::value_t::number_unsigned);
00635             CHECK(j == j_unsigned_reference);
00636         }
00637 
00638         SECTION("uint_least32_t")
00639         {
00640             uint_least32_t n = 42;
00641             json j(n);
00642             CHECK(j.type() == json::value_t::number_unsigned);
00643             CHECK(j == j_unsigned_reference);
00644         }
00645 
00646         SECTION("uint_least64_t")
00647         {
00648             uint_least64_t n = 42;
00649             json j(n);
00650             CHECK(j.type() == json::value_t::number_unsigned);
00651             CHECK(j == j_unsigned_reference);
00652         }
00653 
00654         SECTION("integer literal without suffix")
00655         {
00656             json j(42);
00657             CHECK(j.type() == json::value_t::number_integer);
00658             CHECK(j == j_reference);
00659         }
00660 
00661         SECTION("integer literal with u suffix")
00662         {
00663             json j(42u);
00664             CHECK(j.type() == json::value_t::number_unsigned);
00665             CHECK(j == j_unsigned_reference);
00666         }
00667 
00668         SECTION("integer literal with l suffix")
00669         {
00670             json j(42l);
00671             CHECK(j.type() == json::value_t::number_integer);
00672             CHECK(j == j_reference);
00673         }
00674 
00675         SECTION("integer literal with ul suffix")
00676         {
00677             json j(42ul);
00678             CHECK(j.type() == json::value_t::number_unsigned);
00679             CHECK(j == j_unsigned_reference);
00680         }
00681 
00682         SECTION("integer literal with ll suffix")
00683         {
00684             json j(42ll);
00685             CHECK(j.type() == json::value_t::number_integer);
00686             CHECK(j == j_reference);
00687         }
00688 
00689         SECTION("integer literal with ull suffix")
00690         {
00691             json j(42ull);
00692             CHECK(j.type() == json::value_t::number_unsigned);
00693             CHECK(j == j_unsigned_reference);
00694         }
00695     }
00696 
00697     SECTION("create a floating-point number (explicit)")
00698     {
00699         SECTION("uninitialized value")
00700         {
00701             json::number_float_t n{};
00702             json j(n);
00703             CHECK(j.type() == json::value_t::number_float);
00704         }
00705 
00706         SECTION("initialized value")
00707         {
00708             json::number_float_t n(42.23);
00709             json j(n);
00710             CHECK(j.type() == json::value_t::number_float);
00711         }
00712     }
00713 
00714     SECTION("create a floating-point number (implicit)")
00715     {
00716         // reference object
00717         json::number_float_t n_reference = 42.23;
00718         json j_reference(n_reference);
00719 
00720         SECTION("float")
00721         {
00722             float n = 42.23;
00723             json j(n);
00724             CHECK(j.type() == json::value_t::number_float);
00725             CHECK(j.m_value.number_float == Approx(j_reference.m_value.number_float));
00726         }
00727 
00728         SECTION("double")
00729         {
00730             double n = 42.23;
00731             json j(n);
00732             CHECK(j.type() == json::value_t::number_float);
00733             CHECK(j.m_value.number_float == Approx(j_reference.m_value.number_float));
00734         }
00735 
00736         SECTION("long double")
00737         {
00738             long double n = 42.23;
00739             json j(n);
00740             CHECK(j.type() == json::value_t::number_float);
00741             CHECK(j.m_value.number_float == Approx(j_reference.m_value.number_float));
00742         }
00743 
00744         SECTION("floating-point literal without suffix")
00745         {
00746             json j(42.23);
00747             CHECK(j.type() == json::value_t::number_float);
00748             CHECK(j.m_value.number_float == Approx(j_reference.m_value.number_float));
00749         }
00750 
00751         SECTION("integer literal with f suffix")
00752         {
00753             json j(42.23f);
00754             CHECK(j.type() == json::value_t::number_float);
00755             CHECK(j.m_value.number_float == Approx(j_reference.m_value.number_float));
00756         }
00757 
00758         SECTION("integer literal with l suffix")
00759         {
00760             json j(42.23l);
00761             CHECK(j.type() == json::value_t::number_float);
00762             CHECK(j.m_value.number_float == Approx(j_reference.m_value.number_float));
00763         }
00764     }
00765 
00766     SECTION("create a container (array or object) from an initializer list")
00767     {
00768         SECTION("empty initializer list")
00769         {
00770             SECTION("explicit")
00771             {
00772                 std::initializer_list<json> l;
00773                 json j(l);
00774                 CHECK(j.type() == json::value_t::object);
00775             }
00776 
00777             SECTION("implicit")
00778             {
00779                 json j {};
00780                 CHECK(j.type() == json::value_t::null);
00781             }
00782         }
00783 
00784         SECTION("one element")
00785         {
00786             SECTION("array")
00787             {
00788                 SECTION("explicit")
00789                 {
00790                     std::initializer_list<json> l = {json(json::array_t())};
00791                     json j(l);
00792                     CHECK(j.type() == json::value_t::array);
00793                 }
00794 
00795                 SECTION("implicit")
00796                 {
00797                     json j {json::array_t()};
00798                     CHECK(j.type() == json::value_t::array);
00799                 }
00800             }
00801 
00802             SECTION("object")
00803             {
00804                 SECTION("explicit")
00805                 {
00806                     std::initializer_list<json> l = {json(json::object_t())};
00807                     json j(l);
00808                     CHECK(j.type() == json::value_t::array);
00809                 }
00810 
00811                 SECTION("implicit")
00812                 {
00813                     json j {json::object_t()};
00814                     CHECK(j.type() == json::value_t::array);
00815                 }
00816             }
00817 
00818             SECTION("string")
00819             {
00820                 SECTION("explicit")
00821                 {
00822                     std::initializer_list<json> l = {json("Hello world")};
00823                     json j(l);
00824                     CHECK(j.type() == json::value_t::array);
00825                 }
00826 
00827                 SECTION("implicit")
00828                 {
00829                     json j {"Hello world"};
00830                     CHECK(j.type() == json::value_t::array);
00831                 }
00832             }
00833 
00834             SECTION("boolean")
00835             {
00836                 SECTION("explicit")
00837                 {
00838                     std::initializer_list<json> l = {json(true)};
00839                     json j(l);
00840                     CHECK(j.type() == json::value_t::array);
00841                 }
00842 
00843                 SECTION("implicit")
00844                 {
00845                     json j {true};
00846                     CHECK(j.type() == json::value_t::array);
00847                 }
00848             }
00849 
00850             SECTION("number (integer)")
00851             {
00852                 SECTION("explicit")
00853                 {
00854                     std::initializer_list<json> l = {json(1)};
00855                     json j(l);
00856                     CHECK(j.type() == json::value_t::array);
00857                 }
00858 
00859                 SECTION("implicit")
00860                 {
00861                     json j {1};
00862                     CHECK(j.type() == json::value_t::array);
00863                 }
00864             }
00865 
00866             SECTION("number (unsigned)")
00867             {
00868                 SECTION("explicit")
00869                 {
00870                     std::initializer_list<json> l = {json(1u)};
00871                     json j(l);
00872                     CHECK(j.type() == json::value_t::array);
00873                 }
00874 
00875                 SECTION("implicit")
00876                 {
00877                     json j {1u};
00878                     CHECK(j.type() == json::value_t::array);
00879                 }
00880             }
00881 
00882             SECTION("number (floating-point)")
00883             {
00884                 SECTION("explicit")
00885                 {
00886                     std::initializer_list<json> l = {json(42.23)};
00887                     json j(l);
00888                     CHECK(j.type() == json::value_t::array);
00889                 }
00890 
00891                 SECTION("implicit")
00892                 {
00893                     json j {42.23};
00894                     CHECK(j.type() == json::value_t::array);
00895                 }
00896             }
00897         }
00898 
00899         SECTION("more elements")
00900         {
00901             SECTION("explicit")
00902             {
00903                 std::initializer_list<json> l = {1, 1u, 42.23, true, nullptr, json::object_t(), json::array_t()};
00904                 json j(l);
00905                 CHECK(j.type() == json::value_t::array);
00906             }
00907 
00908             SECTION("implicit")
00909             {
00910                 json j {1, 1u, 42.23, true, nullptr, json::object_t(), json::array_t()};
00911                 CHECK(j.type() == json::value_t::array);
00912             }
00913         }
00914 
00915         SECTION("implicit type deduction")
00916         {
00917             SECTION("object")
00918             {
00919                 json j { {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false} };
00920                 CHECK(j.type() == json::value_t::object);
00921             }
00922 
00923             SECTION("array")
00924             {
00925                 json j { {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false} , 13 };
00926                 CHECK(j.type() == json::value_t::array);
00927             }
00928         }
00929 
00930         SECTION("explicit type deduction")
00931         {
00932             SECTION("empty object")
00933             {
00934                 json j = json::object();
00935                 CHECK(j.type() == json::value_t::object);
00936             }
00937 
00938             SECTION("object")
00939             {
00940                 json j = json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false} });
00941                 CHECK(j.type() == json::value_t::object);
00942             }
00943 
00944             SECTION("object with error")
00945             {
00946                 CHECK_THROWS_AS(json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }),
00947                 std::logic_error);
00948                 CHECK_THROWS_WITH(json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }),
00949                 "cannot create object from initializer list");
00950             }
00951 
00952             SECTION("empty array")
00953             {
00954                 json j = json::array();
00955                 CHECK(j.type() == json::value_t::array);
00956             }
00957 
00958             SECTION("array")
00959             {
00960                 json j = json::array({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false} });
00961                 CHECK(j.type() == json::value_t::array);
00962             }
00963         }
00964     }
00965 
00966     SECTION("create an array of n copies of a given value")
00967     {
00968         json v = {1, "foo", 34.23, {1, 2, 3}, {{"A", 1}, {"B", 2u}}};
00969         json arr(3, v);
00970         CHECK(arr.size() == 3);
00971         for (auto& x : arr)
00972         {
00973             CHECK(x == v);
00974         }
00975     }
00976 
00977     SECTION("create a JSON container from an iterator range")
00978     {
00979         SECTION("object")
00980         {
00981             SECTION("json(begin(), end())")
00982             {
00983                 {
00984                     json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
00985                     json j_new(jobject.begin(), jobject.end());
00986                     CHECK(j_new == jobject);
00987                 }
00988                 {
00989                     json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
00990                     json j_new(jobject.cbegin(), jobject.cend());
00991                     CHECK(j_new == jobject);
00992                 }
00993             }
00994 
00995             SECTION("json(begin(), begin())")
00996             {
00997                 {
00998                     json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
00999                     json j_new(jobject.begin(), jobject.begin());
01000                     CHECK(j_new == json::object());
01001                 }
01002                 {
01003                     json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
01004                     json j_new(jobject.cbegin(), jobject.cbegin());
01005                     CHECK(j_new == json::object());
01006                 }
01007             }
01008 
01009             SECTION("construct from subrange")
01010             {
01011                 json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
01012                 json j_new(jobject.find("b"), jobject.find("e"));
01013                 CHECK(j_new == json({{"b", 1}, {"c", 17u}, {"d", false}}));
01014             }
01015 
01016             SECTION("incompatible iterators")
01017             {
01018                 {
01019                     json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
01020                     json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}};
01021                     CHECK_THROWS_AS(json(jobject.begin(), jobject2.end()), std::domain_error);
01022                     CHECK_THROWS_AS(json(jobject2.begin(), jobject.end()), std::domain_error);
01023                     CHECK_THROWS_WITH(json(jobject.begin(), jobject2.end()), "iterators are not compatible");
01024                     CHECK_THROWS_WITH(json(jobject2.begin(), jobject.end()), "iterators are not compatible");
01025                 }
01026                 {
01027                     json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
01028                     json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}};
01029                     CHECK_THROWS_AS(json(jobject.cbegin(), jobject2.cend()), std::domain_error);
01030                     CHECK_THROWS_AS(json(jobject2.cbegin(), jobject.cend()), std::domain_error);
01031                     CHECK_THROWS_WITH(json(jobject.cbegin(), jobject2.cend()), "iterators are not compatible");
01032                     CHECK_THROWS_WITH(json(jobject2.cbegin(), jobject.cend()), "iterators are not compatible");
01033                 }
01034             }
01035         }
01036 
01037         SECTION("array")
01038         {
01039             SECTION("json(begin(), end())")
01040             {
01041                 {
01042                     json jarray = {1, 2, 3, 4, 5};
01043                     json j_new(jarray.begin(), jarray.end());
01044                     CHECK(j_new == jarray);
01045                 }
01046                 {
01047                     json jarray = {1, 2, 3, 4, 5};
01048                     json j_new(jarray.cbegin(), jarray.cend());
01049                     CHECK(j_new == jarray);
01050                 }
01051             }
01052 
01053             SECTION("json(begin(), begin())")
01054             {
01055                 {
01056                     json jarray = {1, 2, 3, 4, 5};
01057                     json j_new(jarray.begin(), jarray.begin());
01058                     CHECK(j_new == json::array());
01059                 }
01060                 {
01061                     json jarray = {1, 2, 3, 4, 5};
01062                     json j_new(jarray.cbegin(), jarray.cbegin());
01063                     CHECK(j_new == json::array());
01064                 }
01065             }
01066 
01067             SECTION("construct from subrange")
01068             {
01069                 {
01070                     json jarray = {1, 2, 3, 4, 5};
01071                     json j_new(jarray.begin() + 1, jarray.begin() + 3);
01072                     CHECK(j_new == json({2, 3}));
01073                 }
01074                 {
01075                     json jarray = {1, 2, 3, 4, 5};
01076                     json j_new(jarray.cbegin() + 1, jarray.cbegin() + 3);
01077                     CHECK(j_new == json({2, 3}));
01078                 }
01079             }
01080 
01081             SECTION("incompatible iterators")
01082             {
01083                 {
01084                     json jarray = {1, 2, 3, 4};
01085                     json jarray2 = {2, 3, 4, 5};
01086                     CHECK_THROWS_AS(json(jarray.begin(), jarray2.end()), std::domain_error);
01087                     CHECK_THROWS_AS(json(jarray2.begin(), jarray.end()), std::domain_error);
01088                     CHECK_THROWS_WITH(json(jarray.begin(), jarray2.end()), "iterators are not compatible");
01089                     CHECK_THROWS_WITH(json(jarray2.begin(), jarray.end()), "iterators are not compatible");
01090                 }
01091                 {
01092                     json jarray = {1, 2, 3, 4};
01093                     json jarray2 = {2, 3, 4, 5};
01094                     CHECK_THROWS_AS(json(jarray.cbegin(), jarray2.cend()), std::domain_error);
01095                     CHECK_THROWS_AS(json(jarray2.cbegin(), jarray.cend()), std::domain_error);
01096                     CHECK_THROWS_WITH(json(jarray.cbegin(), jarray2.cend()), "iterators are not compatible");
01097                     CHECK_THROWS_WITH(json(jarray2.cbegin(), jarray.cend()), "iterators are not compatible");
01098                 }
01099             }
01100         }
01101 
01102         SECTION("other values")
01103         {
01104             SECTION("construct with two valid iterators")
01105             {
01106                 SECTION("null")
01107                 {
01108                     {
01109                         json j;
01110                         CHECK_THROWS_AS(json(j.begin(), j.end()), std::domain_error);
01111                         CHECK_THROWS_WITH(json(j.begin(), j.end()), "cannot use construct with iterators from null");
01112                     }
01113                     {
01114                         json j;
01115                         CHECK_THROWS_AS(json(j.cbegin(), j.cend()), std::domain_error);
01116                         CHECK_THROWS_WITH(json(j.cbegin(), j.cend()), "cannot use construct with iterators from null");
01117                     }
01118                 }
01119 
01120                 SECTION("string")
01121                 {
01122                     {
01123                         json j = "foo";
01124                         json j_new(j.begin(), j.end());
01125                         CHECK(j == j_new);
01126                     }
01127                     {
01128                         json j = "bar";
01129                         json j_new(j.cbegin(), j.cend());
01130                         CHECK(j == j_new);
01131                     }
01132                 }
01133 
01134                 SECTION("number (boolean)")
01135                 {
01136                     {
01137                         json j = false;
01138                         json j_new(j.begin(), j.end());
01139                         CHECK(j == j_new);
01140                     }
01141                     {
01142                         json j = true;
01143                         json j_new(j.cbegin(), j.cend());
01144                         CHECK(j == j_new);
01145                     }
01146                 }
01147 
01148                 SECTION("number (integer)")
01149                 {
01150                     {
01151                         json j = 17;
01152                         json j_new(j.begin(), j.end());
01153                         CHECK(j == j_new);
01154                     }
01155                     {
01156                         json j = 17;
01157                         json j_new(j.cbegin(), j.cend());
01158                         CHECK(j == j_new);
01159                     }
01160                 }
01161 
01162                 SECTION("number (unsigned)")
01163                 {
01164                     {
01165                         json j = 17u;
01166                         json j_new(j.begin(), j.end());
01167                         CHECK(j == j_new);
01168                     }
01169                     {
01170                         json j = 17u;
01171                         json j_new(j.cbegin(), j.cend());
01172                         CHECK(j == j_new);
01173                     }
01174                 }
01175 
01176                 SECTION("number (floating point)")
01177                 {
01178                     {
01179                         json j = 23.42;
01180                         json j_new(j.begin(), j.end());
01181                         CHECK(j == j_new);
01182                     }
01183                     {
01184                         json j = 23.42;
01185                         json j_new(j.cbegin(), j.cend());
01186                         CHECK(j == j_new);
01187                     }
01188                 }
01189             }
01190 
01191             SECTION("construct with two invalid iterators")
01192             {
01193                 SECTION("string")
01194                 {
01195                     {
01196                         json j = "foo";
01197                         CHECK_THROWS_AS(json(j.end(), j.end()), std::out_of_range);
01198                         CHECK_THROWS_AS(json(j.begin(), j.begin()), std::out_of_range);
01199                         CHECK_THROWS_WITH(json(j.end(), j.end()), "iterators out of range");
01200                         CHECK_THROWS_WITH(json(j.begin(), j.begin()), "iterators out of range");
01201                     }
01202                     {
01203                         json j = "bar";
01204                         CHECK_THROWS_AS(json(j.cend(), j.cend()), std::out_of_range);
01205                         CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), std::out_of_range);
01206                         CHECK_THROWS_WITH(json(j.cend(), j.cend()), "iterators out of range");
01207                         CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "iterators out of range");
01208                     }
01209                 }
01210 
01211                 SECTION("number (boolean)")
01212                 {
01213                     {
01214                         json j = false;
01215                         CHECK_THROWS_AS(json(j.end(), j.end()), std::out_of_range);
01216                         CHECK_THROWS_AS(json(j.begin(), j.begin()), std::out_of_range);
01217                         CHECK_THROWS_WITH(json(j.end(), j.end()), "iterators out of range");
01218                         CHECK_THROWS_WITH(json(j.begin(), j.begin()), "iterators out of range");
01219                     }
01220                     {
01221                         json j = true;
01222                         CHECK_THROWS_AS(json(j.cend(), j.cend()), std::out_of_range);
01223                         CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), std::out_of_range);
01224                         CHECK_THROWS_WITH(json(j.cend(), j.cend()), "iterators out of range");
01225                         CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "iterators out of range");
01226                     }
01227                 }
01228 
01229                 SECTION("number (integer)")
01230                 {
01231                     {
01232                         json j = 17;
01233                         CHECK_THROWS_AS(json(j.end(), j.end()), std::out_of_range);
01234                         CHECK_THROWS_AS(json(j.begin(), j.begin()), std::out_of_range);
01235                         CHECK_THROWS_WITH(json(j.end(), j.end()), "iterators out of range");
01236                         CHECK_THROWS_WITH(json(j.begin(), j.begin()), "iterators out of range");
01237                     }
01238                     {
01239                         json j = 17;
01240                         CHECK_THROWS_AS(json(j.cend(), j.cend()), std::out_of_range);
01241                         CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), std::out_of_range);
01242                         CHECK_THROWS_WITH(json(j.cend(), j.cend()), "iterators out of range");
01243                         CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "iterators out of range");
01244                     }
01245                 }
01246 
01247                 SECTION("number (integer)")
01248                 {
01249                     {
01250                         json j = 17u;
01251                         CHECK_THROWS_AS(json(j.end(), j.end()), std::out_of_range);
01252                         CHECK_THROWS_AS(json(j.begin(), j.begin()), std::out_of_range);
01253                         CHECK_THROWS_WITH(json(j.end(), j.end()), "iterators out of range");
01254                         CHECK_THROWS_WITH(json(j.begin(), j.begin()), "iterators out of range");
01255                     }
01256                     {
01257                         json j = 17u;
01258                         CHECK_THROWS_AS(json(j.cend(), j.cend()), std::out_of_range);
01259                         CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), std::out_of_range);
01260                         CHECK_THROWS_WITH(json(j.cend(), j.cend()), "iterators out of range");
01261                         CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "iterators out of range");
01262                     }
01263                 }
01264 
01265                 SECTION("number (floating point)")
01266                 {
01267                     {
01268                         json j = 23.42;
01269                         CHECK_THROWS_AS(json(j.end(), j.end()), std::out_of_range);
01270                         CHECK_THROWS_AS(json(j.begin(), j.begin()), std::out_of_range);
01271                         CHECK_THROWS_WITH(json(j.end(), j.end()), "iterators out of range");
01272                         CHECK_THROWS_WITH(json(j.begin(), j.begin()), "iterators out of range");
01273                     }
01274                     {
01275                         json j = 23.42;
01276                         CHECK_THROWS_AS(json(j.cend(), j.cend()), std::out_of_range);
01277                         CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), std::out_of_range);
01278                         CHECK_THROWS_WITH(json(j.cend(), j.cend()), "iterators out of range");
01279                         CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "iterators out of range");
01280                     }
01281                 }
01282             }
01283         }
01284     }
01285 
01286     SECTION("create a JSON value from an input stream")
01287     {
01288         SECTION("std::stringstream")
01289         {
01290             std::stringstream ss;
01291             ss << "[\"foo\",1,2,3,false,{\"one\":1}]";
01292             json j(ss);
01293             CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
01294         }
01295 
01296         SECTION("with callback function")
01297         {
01298             std::stringstream ss;
01299             ss << "[\"foo\",1,2,3,false,{\"one\":1}]";
01300             json j(ss, [](int, json::parse_event_t, const json & val)
01301             {
01302                 // filter all number(2) elements
01303                 if (val == json(2))
01304                 {
01305                     return false;
01306                 }
01307                 else
01308                 {
01309                     return true;
01310                 }
01311             });
01312             CHECK(j == json({"foo", 1, 3, false, {{"one", 1}}}));
01313         }
01314 
01315         SECTION("std::ifstream")
01316         {
01317             std::ifstream f("test/data/json_tests/pass1.json");
01318             json j(f);
01319         }
01320     }
01321 }
01322 
01323 TEST_CASE("other constructors and destructor")
01324 {
01325     SECTION("copy constructor")
01326     {
01327         SECTION("object")
01328         {
01329             json j {{"foo", 1}, {"bar", false}};
01330             json k(j);
01331             CHECK(j == k);
01332         }
01333 
01334         SECTION("array")
01335         {
01336             json j {"foo", 1, 42.23, false};
01337             json k(j);
01338             CHECK(j == k);
01339         }
01340 
01341         SECTION("null")
01342         {
01343             json j(nullptr);
01344             json k(j);
01345             CHECK(j == k);
01346         }
01347 
01348         SECTION("boolean")
01349         {
01350             json j(true);
01351             json k(j);
01352             CHECK(j == k);
01353         }
01354 
01355         SECTION("string")
01356         {
01357             json j("Hello world");
01358             json k(j);
01359             CHECK(j == k);
01360         }
01361 
01362         SECTION("number (integer)")
01363         {
01364             json j(42);
01365             json k(j);
01366             CHECK(j == k);
01367         }
01368 
01369         SECTION("number (unsigned)")
01370         {
01371             json j(42u);
01372             json k(j);
01373             CHECK(j == k);
01374         }
01375 
01376         SECTION("number (floating-point)")
01377         {
01378             json j(42.23);
01379             json k(j);
01380             CHECK(j == k);
01381         }
01382     }
01383 
01384     SECTION("move constructor")
01385     {
01386         json j {{"foo", "bar"}, {"baz", {1, 2, 3, 4}}, {"a", 42u}, {"b", 42.23}, {"c", nullptr}};
01387         CHECK(j.type() == json::value_t::object);
01388         json k(std::move(j));
01389         CHECK(k.type() == json::value_t::object);
01390         CHECK(j.type() == json::value_t::null);
01391     }
01392 
01393     SECTION("copy assignment")
01394     {
01395         SECTION("object")
01396         {
01397             json j {{"foo", 1}, {"bar", false}};
01398             json k;
01399             k = j;
01400             CHECK(j == k);
01401         }
01402 
01403         SECTION("array")
01404         {
01405             json j {"foo", 1, 42.23, false};
01406             json k;
01407             k = j;
01408             CHECK(j == k);
01409         }
01410 
01411         SECTION("null")
01412         {
01413             json j(nullptr);
01414             json k;
01415             k = j;
01416             CHECK(j == k);
01417         }
01418 
01419         SECTION("boolean")
01420         {
01421             json j(true);
01422             json k;
01423             k = j;
01424             CHECK(j == k);
01425         }
01426 
01427         SECTION("string")
01428         {
01429             json j("Hello world");
01430             json k;
01431             k = j;
01432             CHECK(j == k);
01433         }
01434 
01435         SECTION("number (integer)")
01436         {
01437             json j(42);
01438             json k;
01439             k = j;
01440             CHECK(j == k);
01441         }
01442 
01443         SECTION("number (unsigned)")
01444         {
01445             json j(42u);
01446             json k;
01447             k = j;
01448             CHECK(j == k);
01449         }
01450 
01451         SECTION("number (floating-point)")
01452         {
01453             json j(42.23);
01454             json k;
01455             k = j;
01456             CHECK(j == k);
01457         }
01458     }
01459 
01460     SECTION("destructor")
01461     {
01462         SECTION("object")
01463         {
01464             auto j = new json {{"foo", 1}, {"bar", false}};
01465             delete j;
01466         }
01467 
01468         SECTION("array")
01469         {
01470             auto j = new json {"foo", 1, 1u, false, 23.42};
01471             delete j;
01472         }
01473 
01474         SECTION("string")
01475         {
01476             auto j = new json("Hello world");
01477             delete j;
01478         }
01479     }
01480 }
01481 
01482 TEST_CASE("object inspection")
01483 {
01484     SECTION("convenience type checker")
01485     {
01486         SECTION("object")
01487         {
01488             json j {{"foo", 1}, {"bar", false}};
01489             CHECK(not j.is_null());
01490             CHECK(not j.is_boolean());
01491             CHECK(not j.is_number());
01492             CHECK(not j.is_number_integer());
01493             CHECK(not j.is_number_unsigned());
01494             CHECK(not j.is_number_float());
01495             CHECK(j.is_object());
01496             CHECK(not j.is_array());
01497             CHECK(not j.is_string());
01498             CHECK(not j.is_discarded());
01499             CHECK(not j.is_primitive());
01500             CHECK(j.is_structured());
01501         }
01502 
01503         SECTION("array")
01504         {
01505             json j {"foo", 1, 1u, 42.23, false};
01506             CHECK(not j.is_null());
01507             CHECK(not j.is_boolean());
01508             CHECK(not j.is_number());
01509             CHECK(not j.is_number_integer());
01510             CHECK(not j.is_number_unsigned());
01511             CHECK(not j.is_number_float());
01512             CHECK(not j.is_object());
01513             CHECK(j.is_array());
01514             CHECK(not j.is_string());
01515             CHECK(not j.is_discarded());
01516             CHECK(not j.is_primitive());
01517             CHECK(j.is_structured());
01518         }
01519 
01520         SECTION("null")
01521         {
01522             json j(nullptr);
01523             CHECK(j.is_null());
01524             CHECK(not j.is_boolean());
01525             CHECK(not j.is_number());
01526             CHECK(not j.is_number_integer());
01527             CHECK(not j.is_number_unsigned());
01528             CHECK(not j.is_number_float());
01529             CHECK(not j.is_object());
01530             CHECK(not j.is_array());
01531             CHECK(not j.is_string());
01532             CHECK(not j.is_discarded());
01533             CHECK(j.is_primitive());
01534             CHECK(not j.is_structured());
01535         }
01536 
01537         SECTION("boolean")
01538         {
01539             json j(true);
01540             CHECK(not j.is_null());
01541             CHECK(j.is_boolean());
01542             CHECK(not j.is_number());
01543             CHECK(not j.is_number_integer());
01544             CHECK(not j.is_number_unsigned());
01545             CHECK(not j.is_number_float());
01546             CHECK(not j.is_object());
01547             CHECK(not j.is_array());
01548             CHECK(not j.is_string());
01549             CHECK(not j.is_discarded());
01550             CHECK(j.is_primitive());
01551             CHECK(not j.is_structured());
01552         }
01553 
01554         SECTION("string")
01555         {
01556             json j("Hello world");
01557             CHECK(not j.is_null());
01558             CHECK(not j.is_boolean());
01559             CHECK(not j.is_number());
01560             CHECK(not j.is_number_integer());
01561             CHECK(not j.is_number_unsigned());
01562             CHECK(not j.is_number_float());
01563             CHECK(not j.is_object());
01564             CHECK(not j.is_array());
01565             CHECK(j.is_string());
01566             CHECK(not j.is_discarded());
01567             CHECK(j.is_primitive());
01568             CHECK(not j.is_structured());
01569         }
01570 
01571         SECTION("number (integer)")
01572         {
01573             json j(42);
01574             CHECK(not j.is_null());
01575             CHECK(not j.is_boolean());
01576             CHECK(j.is_number());
01577             CHECK(j.is_number_integer());
01578             CHECK(not j.is_number_unsigned());
01579             CHECK(not j.is_number_float());
01580             CHECK(not j.is_object());
01581             CHECK(not j.is_array());
01582             CHECK(not j.is_string());
01583             CHECK(not j.is_discarded());
01584             CHECK(j.is_primitive());
01585             CHECK(not j.is_structured());
01586         }
01587 
01588         SECTION("number (unsigned)")
01589         {
01590             json j(42u);
01591             CHECK(not j.is_null());
01592             CHECK(not j.is_boolean());
01593             CHECK(j.is_number());
01594             CHECK(j.is_number_integer());
01595             CHECK(j.is_number_unsigned());
01596             CHECK(not j.is_number_float());
01597             CHECK(not j.is_object());
01598             CHECK(not j.is_array());
01599             CHECK(not j.is_string());
01600             CHECK(not j.is_discarded());
01601             CHECK(j.is_primitive());
01602             CHECK(not j.is_structured());
01603         }
01604 
01605         SECTION("number (floating-point)")
01606         {
01607             json j(42.23);
01608             CHECK(not j.is_null());
01609             CHECK(not j.is_boolean());
01610             CHECK(j.is_number());
01611             CHECK(not j.is_number_integer());
01612             CHECK(not j.is_number_unsigned());
01613             CHECK(j.is_number_float());
01614             CHECK(not j.is_object());
01615             CHECK(not j.is_array());
01616             CHECK(not j.is_string());
01617             CHECK(not j.is_discarded());
01618             CHECK(j.is_primitive());
01619             CHECK(not j.is_structured());
01620         }
01621 
01622         SECTION("discarded")
01623         {
01624             json j(json::value_t::discarded);
01625             CHECK(not j.is_null());
01626             CHECK(not j.is_boolean());
01627             CHECK(not j.is_number());
01628             CHECK(not j.is_number_integer());
01629             CHECK(not j.is_number_unsigned());
01630             CHECK(not j.is_number_float());
01631             CHECK(not j.is_object());
01632             CHECK(not j.is_array());
01633             CHECK(not j.is_string());
01634             CHECK(j.is_discarded());
01635             CHECK(not j.is_primitive());
01636             CHECK(not j.is_structured());
01637         }
01638     }
01639 
01640     SECTION("serialization")
01641     {
01642         json j {{"object", json::object()}, {"array", {1, 2, 3, 4}}, {"number", 42}, {"boolean", false}, {"null", nullptr}, {"string", "Hello world"} };
01643 
01644         SECTION("no indent / indent=-1")
01645         {
01646             CHECK(j.dump() ==
01647                   "{\"array\":[1,2,3,4],\"boolean\":false,\"null\":null,\"number\":42,\"object\":{},\"string\":\"Hello world\"}");
01648 
01649             CHECK(j.dump() == j.dump(-1));
01650         }
01651 
01652         SECTION("indent=0")
01653         {
01654             CHECK(j.dump(0) ==
01655                   "{\n\"array\": [\n1,\n2,\n3,\n4\n],\n\"boolean\": false,\n\"null\": null,\n\"number\": 42,\n\"object\": {},\n\"string\": \"Hello world\"\n}");
01656         }
01657 
01658         SECTION("indent=4")
01659         {
01660             CHECK(j.dump(4) ==
01661                   "{\n    \"array\": [\n        1,\n        2,\n        3,\n        4\n    ],\n    \"boolean\": false,\n    \"null\": null,\n    \"number\": 42,\n    \"object\": {},\n    \"string\": \"Hello world\"\n}");
01662         }
01663 
01664         SECTION("dump and floating-point numbers")
01665         {
01666             auto s = json(42.23).dump();
01667             CHECK(s.find("42.23") != std::string::npos);
01668         }
01669 
01670         SECTION("dump and small floating-point numbers")
01671         {
01672             auto s = json(1.23456e-78).dump();
01673             CHECK(s.find("1.23456e-78") != std::string::npos);
01674         }
01675 
01676         SECTION("dump and non-ASCII characters")
01677         {
01678             CHECK(json("ä").dump() == "\"ä\"");
01679             CHECK(json("Ö").dump() == "\"Ö\"");
01680             CHECK(json("❤️").dump() == "\"❤️\"");
01681         }
01682 
01683         SECTION("serialization of discarded element")
01684         {
01685             json j_discarded(json::value_t::discarded);
01686             CHECK(j_discarded.dump() == "<discarded>");
01687         }
01688     }
01689 
01690     SECTION("return the type of the object (explicit)")
01691     {
01692         SECTION("null")
01693         {
01694             json j = nullptr;
01695             CHECK(j.type() == json::value_t::null);
01696         }
01697 
01698         SECTION("object")
01699         {
01700             json j = {{"foo", "bar"}};
01701             CHECK(j.type() == json::value_t::object);
01702         }
01703 
01704         SECTION("array")
01705         {
01706             json j = {1, 2, 3, 4};
01707             CHECK(j.type() == json::value_t::array);
01708         }
01709 
01710         SECTION("boolean")
01711         {
01712             json j = true;
01713             CHECK(j.type() == json::value_t::boolean);
01714         }
01715 
01716         SECTION("string")
01717         {
01718             json j = "Hello world";
01719             CHECK(j.type() == json::value_t::string);
01720         }
01721 
01722         SECTION("number (integer)")
01723         {
01724             json j = 23;
01725             CHECK(j.type() == json::value_t::number_integer);
01726         }
01727 
01728         SECTION("number (unsigned)")
01729         {
01730             json j = 23u;
01731             CHECK(j.type() == json::value_t::number_unsigned);
01732         }
01733 
01734         SECTION("number (floating-point)")
01735         {
01736             json j = 42.23;
01737             CHECK(j.type() == json::value_t::number_float);
01738         }
01739     }
01740 
01741     SECTION("return the type of the object (implicit)")
01742     {
01743         SECTION("null")
01744         {
01745             json j = nullptr;
01746             json::value_t t = j;
01747             CHECK(t == j.type());
01748         }
01749 
01750         SECTION("object")
01751         {
01752             json j = {{"foo", "bar"}};
01753             json::value_t t = j;
01754             CHECK(t == j.type());
01755         }
01756 
01757         SECTION("array")
01758         {
01759             json j = {1, 2, 3, 4};
01760             json::value_t t = j;
01761             CHECK(t == j.type());
01762         }
01763 
01764         SECTION("boolean")
01765         {
01766             json j = true;
01767             json::value_t t = j;
01768             CHECK(t == j.type());
01769         }
01770 
01771         SECTION("string")
01772         {
01773             json j = "Hello world";
01774             json::value_t t = j;
01775             CHECK(t == j.type());
01776         }
01777 
01778         SECTION("number (integer)")
01779         {
01780             json j = 23;
01781             json::value_t t = j;
01782             CHECK(t == j.type());
01783         }
01784 
01785         SECTION("number (unsigned)")
01786         {
01787             json j = 23u;
01788             json::value_t t = j;
01789             CHECK(t == j.type());
01790         }
01791 
01792         SECTION("number (floating-point)")
01793         {
01794             json j = 42.23;
01795             json::value_t t = j;
01796             CHECK(t == j.type());
01797         }
01798     }
01799 }
01800 
01801 TEST_CASE("value conversion")
01802 {
01803     SECTION("get an object (explicit)")
01804     {
01805         json::object_t o_reference = {{"object", json::object()}, {"array", {1, 2, 3, 4}}, {"number", 42}, {"boolean", false}, {"null", nullptr}, {"string", "Hello world"} };
01806         json j(o_reference);
01807 
01808         SECTION("json::object_t")
01809         {
01810             json::object_t o = j.get<json::object_t>();
01811             CHECK(json(o) == j);
01812         }
01813 
01814         SECTION("std::map<json::string_t, json>")
01815         {
01816             std::map<json::string_t, json> o = j.get<std::map<json::string_t, json>>();
01817             CHECK(json(o) == j);
01818         }
01819 
01820         SECTION("std::multimap<json::string_t, json>")
01821         {
01822             std::multimap<json::string_t, json> o = j.get<std::multimap<json::string_t, json>>();
01823             CHECK(json(o) == j);
01824         }
01825 
01826         SECTION("std::unordered_map<json::string_t, json>")
01827         {
01828             std::unordered_map<json::string_t, json> o = j.get<std::unordered_map<json::string_t, json>>();
01829             CHECK(json(o) == j);
01830         }
01831 
01832         SECTION("std::unordered_multimap<json::string_t, json>")
01833         {
01834             std::unordered_multimap<json::string_t, json> o =
01835                 j.get<std::unordered_multimap<json::string_t, json>>();
01836             CHECK(json(o) == j);
01837         }
01838 
01839         SECTION("exception in case of a non-object type")
01840         {
01841             CHECK_THROWS_AS(json(json::value_t::null).get<json::object_t>(), std::logic_error);
01842             CHECK_THROWS_AS(json(json::value_t::array).get<json::object_t>(), std::logic_error);
01843             CHECK_THROWS_AS(json(json::value_t::string).get<json::object_t>(), std::logic_error);
01844             CHECK_THROWS_AS(json(json::value_t::boolean).get<json::object_t>(), std::logic_error);
01845             CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::object_t>(), std::logic_error);
01846             CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<json::object_t>(), std::logic_error);
01847             CHECK_THROWS_AS(json(json::value_t::number_float).get<json::object_t>(), std::logic_error);
01848 
01849             CHECK_THROWS_WITH(json(json::value_t::null).get<json::object_t>(),
01850                               "type must be object, but is null");
01851             CHECK_THROWS_WITH(json(json::value_t::array).get<json::object_t>(),
01852                               "type must be object, but is array");
01853             CHECK_THROWS_WITH(json(json::value_t::string).get<json::object_t>(),
01854                               "type must be object, but is string");
01855             CHECK_THROWS_WITH(json(json::value_t::boolean).get<json::object_t>(),
01856                               "type must be object, but is boolean");
01857             CHECK_THROWS_WITH(json(json::value_t::number_integer).get<json::object_t>(),
01858                               "type must be object, but is number");
01859             CHECK_THROWS_WITH(json(json::value_t::number_unsigned).get<json::object_t>(),
01860                               "type must be object, but is number");
01861             CHECK_THROWS_WITH(json(json::value_t::number_float).get<json::object_t>(),
01862                               "type must be object, but is number");
01863         }
01864     }
01865 
01866     SECTION("get an object (implicit)")
01867     {
01868         json::object_t o_reference = {{"object", json::object()}, {"array", {1, 2, 3, 4}}, {"number", 42}, {"boolean", false}, {"null", nullptr}, {"string", "Hello world"} };
01869         json j(o_reference);
01870 
01871         SECTION("json::object_t")
01872         {
01873             json::object_t o = j;
01874             CHECK(json(o) == j);
01875         }
01876 
01877         SECTION("std::map<json::string_t, json>")
01878         {
01879             std::map<json::string_t, json> o = j;
01880             CHECK(json(o) == j);
01881         }
01882 
01883         SECTION("std::multimap<json::string_t, json>")
01884         {
01885             std::multimap<json::string_t, json> o = j;
01886             CHECK(json(o) == j);
01887         }
01888 
01889         SECTION("std::unordered_map<json::string_t, json>")
01890         {
01891             std::unordered_map<json::string_t, json> o = j;
01892             CHECK(json(o) == j);
01893         }
01894 
01895         SECTION("std::unordered_multimap<json::string_t, json>")
01896         {
01897             std::unordered_multimap<json::string_t, json> o = j;
01898             CHECK(json(o) == j);
01899         }
01900     }
01901 
01902     SECTION("get an array (explicit)")
01903     {
01904         json::array_t a_reference {json(1), json(1u), json(2.2), json(false), json("string"), json()};
01905         json j(a_reference);
01906 
01907         SECTION("json::array_t")
01908         {
01909             json::array_t a = j.get<json::array_t>();
01910             CHECK(json(a) == j);
01911         }
01912 
01913         SECTION("std::list<json>")
01914         {
01915             std::list<json> a = j.get<std::list<json>>();
01916             CHECK(json(a) == j);
01917         }
01918 
01919         SECTION("std::forward_list<json>")
01920         {
01921             std::forward_list<json> a = j.get<std::forward_list<json>>();
01922             CHECK(json(a) == j);
01923         }
01924 
01925         SECTION("std::vector<json>")
01926         {
01927             std::vector<json> a = j.get<std::vector<json>>();
01928             CHECK(json(a) == j);
01929         }
01930 
01931         SECTION("std::deque<json>")
01932         {
01933             std::deque<json> a = j.get<std::deque<json>>();
01934             CHECK(json(a) == j);
01935         }
01936 
01937         SECTION("exception in case of a non-array type")
01938         {
01939             CHECK_THROWS_AS(json(json::value_t::null).get<json::array_t>(), std::logic_error);
01940             CHECK_THROWS_AS(json(json::value_t::object).get<json::array_t>(), std::logic_error);
01941             CHECK_THROWS_AS(json(json::value_t::string).get<json::array_t>(), std::logic_error);
01942             CHECK_THROWS_AS(json(json::value_t::boolean).get<json::array_t>(), std::logic_error);
01943             CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::array_t>(), std::logic_error);
01944             CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<json::array_t>(), std::logic_error);
01945             CHECK_THROWS_AS(json(json::value_t::number_float).get<json::array_t>(), std::logic_error);
01946 
01947             CHECK_THROWS_WITH(json(json::value_t::null).get<json::array_t>(),
01948                               "type must be array, but is null");
01949             CHECK_THROWS_WITH(json(json::value_t::object).get<json::array_t>(),
01950                               "type must be array, but is object");
01951             CHECK_THROWS_WITH(json(json::value_t::string).get<json::array_t>(),
01952                               "type must be array, but is string");
01953             CHECK_THROWS_WITH(json(json::value_t::boolean).get<json::array_t>(),
01954                               "type must be array, but is boolean");
01955             CHECK_THROWS_WITH(json(json::value_t::number_integer).get<json::array_t>(),
01956                               "type must be array, but is number");
01957             CHECK_THROWS_WITH(json(json::value_t::number_unsigned).get<json::array_t>(),
01958                               "type must be array, but is number");
01959             CHECK_THROWS_WITH(json(json::value_t::number_float).get<json::array_t>(),
01960                               "type must be array, but is number");
01961         }
01962     }
01963 
01964     SECTION("get an array (implicit)")
01965     {
01966         json::array_t a_reference {json(1), json(1u), json(2.2), json(false), json("string"), json()};
01967         json j(a_reference);
01968 
01969         SECTION("json::array_t")
01970         {
01971             json::array_t a = j;
01972             CHECK(json(a) == j);
01973         }
01974 
01975         SECTION("std::list<json>")
01976         {
01977             std::list<json> a = j;
01978             CHECK(json(a) == j);
01979         }
01980 
01981         SECTION("std::forward_list<json>")
01982         {
01983             std::forward_list<json> a = j;
01984             CHECK(json(a) == j);
01985         }
01986 
01987         SECTION("std::vector<json>")
01988         {
01989             std::vector<json> a = j;
01990             CHECK(json(a) == j);
01991         }
01992 
01993         SECTION("std::deque<json>")
01994         {
01995             std::deque<json> a = j;
01996             CHECK(json(a) == j);
01997         }
01998     }
01999 
02000     SECTION("get a string (explicit)")
02001     {
02002         json::string_t s_reference {"Hello world"};
02003         json j(s_reference);
02004 
02005         SECTION("string_t")
02006         {
02007             json::string_t s = j.get<json::string_t>();
02008             CHECK(json(s) == j);
02009         }
02010 
02011         SECTION("std::string")
02012         {
02013             std::string s = j.get<std::string>();
02014             CHECK(json(s) == j);
02015         }
02016 
02017         SECTION("exception in case of a non-string type")
02018         {
02019             CHECK_THROWS_AS(json(json::value_t::null).get<json::string_t>(), std::logic_error);
02020             CHECK_THROWS_AS(json(json::value_t::object).get<json::string_t>(), std::logic_error);
02021             CHECK_THROWS_AS(json(json::value_t::array).get<json::string_t>(), std::logic_error);
02022             CHECK_THROWS_AS(json(json::value_t::boolean).get<json::string_t>(), std::logic_error);
02023             CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::string_t>(), std::logic_error);
02024             CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<json::string_t>(), std::logic_error);
02025             CHECK_THROWS_AS(json(json::value_t::number_float).get<json::string_t>(), std::logic_error);
02026 
02027             CHECK_THROWS_WITH(json(json::value_t::null).get<json::string_t>(),
02028                               "type must be string, but is null");
02029             CHECK_THROWS_WITH(json(json::value_t::object).get<json::string_t>(),
02030                               "type must be string, but is object");
02031             CHECK_THROWS_WITH(json(json::value_t::array).get<json::string_t>(),
02032                               "type must be string, but is array");
02033             CHECK_THROWS_WITH(json(json::value_t::boolean).get<json::string_t>(),
02034                               "type must be string, but is boolean");
02035             CHECK_THROWS_WITH(json(json::value_t::number_integer).get<json::string_t>(),
02036                               "type must be string, but is number");
02037             CHECK_THROWS_WITH(json(json::value_t::number_unsigned).get<json::string_t>(),
02038                               "type must be string, but is number");
02039             CHECK_THROWS_WITH(json(json::value_t::number_float).get<json::string_t>(),
02040                               "type must be string, but is number");
02041         }
02042     }
02043 
02044     SECTION("get a string (implicit)")
02045     {
02046         json::string_t s_reference {"Hello world"};
02047         json j(s_reference);
02048 
02049         SECTION("string_t")
02050         {
02051             json::string_t s = j;
02052             CHECK(json(s) == j);
02053         }
02054 
02055         SECTION("std::string")
02056         {
02057             std::string s = j;
02058             CHECK(json(s) == j);
02059         }
02060     }
02061 
02062     SECTION("get a boolean (explicit)")
02063     {
02064         json::boolean_t b_reference {true};
02065         json j(b_reference);
02066 
02067         SECTION("boolean_t")
02068         {
02069             json::boolean_t b = j.get<json::boolean_t>();
02070             CHECK(json(b) == j);
02071         }
02072 
02073         SECTION("bool")
02074         {
02075             bool b = j.get<bool>();
02076             CHECK(json(b) == j);
02077         }
02078 
02079         SECTION("exception in case of a non-string type")
02080         {
02081             CHECK_THROWS_AS(json(json::value_t::null).get<json::boolean_t>(), std::logic_error);
02082             CHECK_THROWS_AS(json(json::value_t::object).get<json::boolean_t>(), std::logic_error);
02083             CHECK_THROWS_AS(json(json::value_t::array).get<json::boolean_t>(), std::logic_error);
02084             CHECK_THROWS_AS(json(json::value_t::string).get<json::boolean_t>(), std::logic_error);
02085             CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::boolean_t>(), std::logic_error);
02086             CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<json::boolean_t>(), std::logic_error);
02087             CHECK_THROWS_AS(json(json::value_t::number_float).get<json::boolean_t>(), std::logic_error);
02088 
02089             CHECK_THROWS_WITH(json(json::value_t::null).get<json::boolean_t>(),
02090                               "type must be boolean, but is null");
02091             CHECK_THROWS_WITH(json(json::value_t::object).get<json::boolean_t>(),
02092                               "type must be boolean, but is object");
02093             CHECK_THROWS_WITH(json(json::value_t::array).get<json::boolean_t>(),
02094                               "type must be boolean, but is array");
02095             CHECK_THROWS_WITH(json(json::value_t::string).get<json::boolean_t>(),
02096                               "type must be boolean, but is string");
02097             CHECK_THROWS_WITH(json(json::value_t::number_integer).get<json::boolean_t>(),
02098                               "type must be boolean, but is number");
02099             CHECK_THROWS_WITH(json(json::value_t::number_unsigned).get<json::boolean_t>(),
02100                               "type must be boolean, but is number");
02101             CHECK_THROWS_WITH(json(json::value_t::number_float).get<json::boolean_t>(),
02102                               "type must be boolean, but is number");
02103         }
02104     }
02105 
02106     SECTION("get a boolean (implicit)")
02107     {
02108         json::boolean_t b_reference {true};
02109         json j(b_reference);
02110 
02111         SECTION("boolean_t")
02112         {
02113             json::boolean_t b = j;
02114             CHECK(json(b) == j);
02115         }
02116 
02117         SECTION("bool")
02118         {
02119             bool b = j;
02120             CHECK(json(b) == j);
02121         }
02122     }
02123 
02124     SECTION("get an integer number (explicit)")
02125     {
02126         json::number_integer_t n_reference {42};
02127         json j(n_reference);
02128         json::number_unsigned_t n_unsigned_reference {42u};
02129         json j_unsigned(n_unsigned_reference);
02130 
02131         SECTION("number_integer_t")
02132         {
02133             json::number_integer_t n = j.get<json::number_integer_t>();
02134             CHECK(json(n) == j);
02135         }
02136 
02137         SECTION("number_unsigned_t")
02138         {
02139             json::number_unsigned_t n = j_unsigned.get<json::number_unsigned_t>();
02140             CHECK(json(n) == j_unsigned);
02141         }
02142 
02143         SECTION("short")
02144         {
02145             short n = j.get<short>();
02146             CHECK(json(n) == j);
02147         }
02148 
02149         SECTION("unsigned short")
02150         {
02151             unsigned short n = j.get<unsigned short>();
02152             CHECK(json(n) == j);
02153         }
02154 
02155         SECTION("int")
02156         {
02157             int n = j.get<int>();
02158             CHECK(json(n) == j);
02159         }
02160 
02161         SECTION("unsigned int")
02162         {
02163             unsigned int n = j.get<unsigned int>();
02164             CHECK(json(n) == j);
02165         }
02166 
02167         SECTION("long")
02168         {
02169             long n = j.get<long>();
02170             CHECK(json(n) == j);
02171         }
02172 
02173         SECTION("unsigned long")
02174         {
02175             unsigned long n = j.get<unsigned long>();
02176             CHECK(json(n) == j);
02177         }
02178 
02179         SECTION("long long")
02180         {
02181             long long n = j.get<long long>();
02182             CHECK(json(n) == j);
02183         }
02184 
02185         SECTION("unsigned long long")
02186         {
02187             unsigned long long n = j.get<unsigned long long>();
02188             CHECK(json(n) == j);
02189         }
02190 
02191         SECTION("int8_t")
02192         {
02193             int8_t n = j.get<int8_t>();
02194             CHECK(json(n) == j);
02195         }
02196 
02197         SECTION("int16_t")
02198         {
02199             int16_t n = j.get<int16_t>();
02200             CHECK(json(n) == j);
02201         }
02202 
02203         SECTION("int32_t")
02204         {
02205             int32_t n = j.get<int32_t>();
02206             CHECK(json(n) == j);
02207         }
02208 
02209         SECTION("int64_t")
02210         {
02211             int64_t n = j.get<int64_t>();
02212             CHECK(json(n) == j);
02213         }
02214 
02215         SECTION("int8_fast_t")
02216         {
02217             int_fast8_t n = j.get<int_fast8_t>();
02218             CHECK(json(n) == j);
02219         }
02220 
02221         SECTION("int16_fast_t")
02222         {
02223             int_fast16_t n = j.get<int_fast16_t>();
02224             CHECK(json(n) == j);
02225         }
02226 
02227         SECTION("int32_fast_t")
02228         {
02229             int_fast32_t n = j.get<int_fast32_t>();
02230             CHECK(json(n) == j);
02231         }
02232 
02233         SECTION("int64_fast_t")
02234         {
02235             int_fast64_t n = j.get<int_fast64_t>();
02236             CHECK(json(n) == j);
02237         }
02238 
02239         SECTION("int8_least_t")
02240         {
02241             int_least8_t n = j.get<int_least8_t>();
02242             CHECK(json(n) == j);
02243         }
02244 
02245         SECTION("int16_least_t")
02246         {
02247             int_least16_t n = j.get<int_least16_t>();
02248             CHECK(json(n) == j);
02249         }
02250 
02251         SECTION("int32_least_t")
02252         {
02253             int_least32_t n = j.get<int_least32_t>();
02254             CHECK(json(n) == j);
02255         }
02256 
02257         SECTION("int64_least_t")
02258         {
02259             int_least64_t n = j.get<int_least64_t>();
02260             CHECK(json(n) == j);
02261         }
02262 
02263         SECTION("uint8_t")
02264         {
02265             uint8_t n = j.get<uint8_t>();
02266             CHECK(json(n) == j);
02267         }
02268 
02269         SECTION("uint16_t")
02270         {
02271             uint16_t n = j.get<uint16_t>();
02272             CHECK(json(n) == j);
02273         }
02274 
02275         SECTION("uint32_t")
02276         {
02277             uint32_t n = j.get<uint32_t>();
02278             CHECK(json(n) == j);
02279         }
02280 
02281         SECTION("uint64_t")
02282         {
02283             uint64_t n = j.get<uint64_t>();
02284             CHECK(json(n) == j);
02285         }
02286 
02287         SECTION("uint8_fast_t")
02288         {
02289             uint_fast8_t n = j.get<uint_fast8_t>();
02290             CHECK(json(n) == j);
02291         }
02292 
02293         SECTION("uint16_fast_t")
02294         {
02295             uint_fast16_t n = j.get<uint_fast16_t>();
02296             CHECK(json(n) == j);
02297         }
02298 
02299         SECTION("uint32_fast_t")
02300         {
02301             uint_fast32_t n = j.get<uint_fast32_t>();
02302             CHECK(json(n) == j);
02303         }
02304 
02305         SECTION("uint64_fast_t")
02306         {
02307             uint_fast64_t n = j.get<uint_fast64_t>();
02308             CHECK(json(n) == j);
02309         }
02310 
02311         SECTION("uint8_least_t")
02312         {
02313             uint_least8_t n = j.get<uint_least8_t>();
02314             CHECK(json(n) == j);
02315         }
02316 
02317         SECTION("uint16_least_t")
02318         {
02319             uint_least16_t n = j.get<uint_least16_t>();
02320             CHECK(json(n) == j);
02321         }
02322 
02323         SECTION("uint32_least_t")
02324         {
02325             uint_least32_t n = j.get<uint_least32_t>();
02326             CHECK(json(n) == j);
02327         }
02328 
02329         SECTION("uint64_least_t")
02330         {
02331             uint_least64_t n = j.get<uint_least64_t>();
02332             CHECK(json(n) == j);
02333         }
02334 
02335         SECTION("exception in case of a non-number type")
02336         {
02337             CHECK_THROWS_AS(json(json::value_t::null).get<json::number_integer_t>(), std::logic_error);
02338             CHECK_THROWS_AS(json(json::value_t::object).get<json::number_integer_t>(), std::logic_error);
02339             CHECK_THROWS_AS(json(json::value_t::array).get<json::number_integer_t>(), std::logic_error);
02340             CHECK_THROWS_AS(json(json::value_t::string).get<json::number_integer_t>(), std::logic_error);
02341             CHECK_THROWS_AS(json(json::value_t::boolean).get<json::number_integer_t>(), std::logic_error);
02342 
02343             CHECK_THROWS_WITH(json(json::value_t::null).get<json::number_integer_t>(),
02344                               "type must be number, but is null");
02345             CHECK_THROWS_WITH(json(json::value_t::object).get<json::number_integer_t>(),
02346                               "type must be number, but is object");
02347             CHECK_THROWS_WITH(json(json::value_t::array).get<json::number_integer_t>(),
02348                               "type must be number, but is array");
02349             CHECK_THROWS_WITH(json(json::value_t::string).get<json::number_integer_t>(),
02350                               "type must be number, but is string");
02351             CHECK_THROWS_WITH(json(json::value_t::boolean).get<json::number_integer_t>(),
02352                               "type must be number, but is boolean");
02353 
02354             CHECK_NOTHROW(json(json::value_t::number_float).get<json::number_integer_t>());
02355             CHECK_NOTHROW(json(json::value_t::number_float).get<json::number_unsigned_t>());
02356         }
02357     }
02358 
02359     SECTION("get an integer number (implicit)")
02360     {
02361         json::number_integer_t n_reference {42};
02362         json j(n_reference);
02363         json::number_unsigned_t n_unsigned_reference {42u};
02364         json j_unsigned(n_unsigned_reference);
02365 
02366         SECTION("number_integer_t")
02367         {
02368             json::number_integer_t n = j.get<json::number_integer_t>();
02369             CHECK(json(n) == j);
02370         }
02371 
02372         SECTION("number_unsigned_t")
02373         {
02374             json::number_unsigned_t n = j_unsigned.get<json::number_unsigned_t>();
02375             CHECK(json(n) == j_unsigned);
02376         }
02377 
02378         SECTION("short")
02379         {
02380             short n = j;
02381             CHECK(json(n) == j);
02382         }
02383 
02384         SECTION("unsigned short")
02385         {
02386             unsigned short n = j_unsigned;
02387             CHECK(json(n) == j_unsigned);
02388         }
02389 
02390         SECTION("int")
02391         {
02392             int n = j;
02393             CHECK(json(n) == j);
02394         }
02395 
02396         SECTION("unsigned int")
02397         {
02398             unsigned int n = j_unsigned;
02399             CHECK(json(n) == j_unsigned);
02400         }
02401 
02402         SECTION("long")
02403         {
02404             long n = j;
02405             CHECK(json(n) == j);
02406         }
02407 
02408         SECTION("unsigned long")
02409         {
02410             unsigned long n = j_unsigned;
02411             CHECK(json(n) == j_unsigned);
02412         }
02413 
02414         SECTION("long long")
02415         {
02416             long long n = j;
02417             CHECK(json(n) == j);
02418         }
02419 
02420         SECTION("unsigned long long")
02421         {
02422             unsigned long long n = j_unsigned;
02423             CHECK(json(n) == j_unsigned);
02424         }
02425 
02426         SECTION("int8_t")
02427         {
02428             int8_t n = j;
02429             CHECK(json(n) == j);
02430         }
02431 
02432         SECTION("int16_t")
02433         {
02434             int16_t n = j;
02435             CHECK(json(n) == j);
02436         }
02437 
02438         SECTION("int32_t")
02439         {
02440             int32_t n = j;
02441             CHECK(json(n) == j);
02442         }
02443 
02444         SECTION("int64_t")
02445         {
02446             int64_t n = j;
02447             CHECK(json(n) == j);
02448         }
02449 
02450         SECTION("int8_fast_t")
02451         {
02452             int_fast8_t n = j;
02453             CHECK(json(n) == j);
02454         }
02455 
02456         SECTION("int16_fast_t")
02457         {
02458             int_fast16_t n = j;
02459             CHECK(json(n) == j);
02460         }
02461 
02462         SECTION("int32_fast_t")
02463         {
02464             int_fast32_t n = j;
02465             CHECK(json(n) == j);
02466         }
02467 
02468         SECTION("int64_fast_t")
02469         {
02470             int_fast64_t n = j;
02471             CHECK(json(n) == j);
02472         }
02473 
02474         SECTION("int8_least_t")
02475         {
02476             int_least8_t n = j;
02477             CHECK(json(n) == j);
02478         }
02479 
02480         SECTION("int16_least_t")
02481         {
02482             int_least16_t n = j;
02483             CHECK(json(n) == j);
02484         }
02485 
02486         SECTION("int32_least_t")
02487         {
02488             int_least32_t n = j;
02489             CHECK(json(n) == j);
02490         }
02491 
02492         SECTION("int64_least_t")
02493         {
02494             int_least64_t n = j;
02495             CHECK(json(n) == j);
02496         }
02497 
02498         SECTION("uint8_t")
02499         {
02500             uint8_t n = j_unsigned;
02501             CHECK(json(n) == j_unsigned);
02502         }
02503 
02504         SECTION("uint16_t")
02505         {
02506             uint16_t n = j_unsigned;
02507             CHECK(json(n) == j_unsigned);
02508         }
02509 
02510         SECTION("uint32_t")
02511         {
02512             uint32_t n = j_unsigned;
02513             CHECK(json(n) == j_unsigned);
02514         }
02515 
02516         SECTION("uint64_t")
02517         {
02518             uint64_t n = j_unsigned;
02519             CHECK(json(n) == j_unsigned);
02520         }
02521 
02522         SECTION("uint8_fast_t")
02523         {
02524             uint_fast8_t n = j_unsigned;
02525             CHECK(json(n) == j_unsigned);
02526         }
02527 
02528         SECTION("uint16_fast_t")
02529         {
02530             uint_fast16_t n = j_unsigned;
02531             CHECK(json(n) == j_unsigned);
02532         }
02533 
02534         SECTION("uint32_fast_t")
02535         {
02536             uint_fast32_t n = j_unsigned;
02537             CHECK(json(n) == j_unsigned);
02538         }
02539 
02540         SECTION("uint64_fast_t")
02541         {
02542             uint_fast64_t n = j_unsigned;
02543             CHECK(json(n) == j_unsigned);
02544         }
02545 
02546         SECTION("uint8_least_t")
02547         {
02548             uint_least8_t n = j_unsigned;
02549             CHECK(json(n) == j_unsigned);
02550         }
02551 
02552         SECTION("uint16_least_t")
02553         {
02554             uint_least16_t n = j_unsigned;
02555             CHECK(json(n) == j_unsigned);
02556         }
02557 
02558         SECTION("uint32_least_t")
02559         {
02560             uint_least32_t n = j_unsigned;
02561             CHECK(json(n) == j_unsigned);
02562         }
02563 
02564         SECTION("uint64_least_t")
02565         {
02566             uint_least64_t n = j_unsigned;
02567             CHECK(json(n) == j_unsigned);
02568         }
02569     }
02570 
02571     SECTION("get a floating-point number (explicit)")
02572     {
02573         json::number_float_t n_reference {42.23};
02574         json j(n_reference);
02575 
02576         SECTION("number_float_t")
02577         {
02578             json::number_float_t n = j.get<json::number_float_t>();
02579             CHECK(json(n).m_value.number_float == Approx(j.m_value.number_float));
02580         }
02581 
02582         SECTION("float")
02583         {
02584             float n = j.get<float>();
02585             CHECK(json(n).m_value.number_float == Approx(j.m_value.number_float));
02586         }
02587 
02588         SECTION("double")
02589         {
02590             double n = j.get<double>();
02591             CHECK(json(n).m_value.number_float == Approx(j.m_value.number_float));
02592         }
02593 
02594         SECTION("exception in case of a non-string type")
02595         {
02596             CHECK_THROWS_AS(json(json::value_t::null).get<json::number_float_t>(), std::logic_error);
02597             CHECK_THROWS_AS(json(json::value_t::object).get<json::number_float_t>(), std::logic_error);
02598             CHECK_THROWS_AS(json(json::value_t::array).get<json::number_float_t>(), std::logic_error);
02599             CHECK_THROWS_AS(json(json::value_t::string).get<json::number_float_t>(), std::logic_error);
02600             CHECK_THROWS_AS(json(json::value_t::boolean).get<json::number_float_t>(), std::logic_error);
02601 
02602             CHECK_THROWS_WITH(json(json::value_t::null).get<json::number_float_t>(),
02603                               "type must be number, but is null");
02604             CHECK_THROWS_WITH(json(json::value_t::object).get<json::number_float_t>(),
02605                               "type must be number, but is object");
02606             CHECK_THROWS_WITH(json(json::value_t::array).get<json::number_float_t>(),
02607                               "type must be number, but is array");
02608             CHECK_THROWS_WITH(json(json::value_t::string).get<json::number_float_t>(),
02609                               "type must be number, but is string");
02610             CHECK_THROWS_WITH(json(json::value_t::boolean).get<json::number_float_t>(),
02611                               "type must be number, but is boolean");
02612 
02613             CHECK_NOTHROW(json(json::value_t::number_integer).get<json::number_float_t>());
02614             CHECK_NOTHROW(json(json::value_t::number_unsigned).get<json::number_float_t>());
02615         }
02616     }
02617 
02618     SECTION("get a floating-point number (implicit)")
02619     {
02620         json::number_float_t n_reference {42.23};
02621         json j(n_reference);
02622 
02623         SECTION("number_float_t")
02624         {
02625             json::number_float_t n = j;
02626             CHECK(json(n).m_value.number_float == Approx(j.m_value.number_float));
02627         }
02628 
02629         SECTION("float")
02630         {
02631             float n = j;
02632             CHECK(json(n).m_value.number_float == Approx(j.m_value.number_float));
02633         }
02634 
02635         SECTION("double")
02636         {
02637             double n = j;
02638             CHECK(json(n).m_value.number_float == Approx(j.m_value.number_float));
02639         }
02640     }
02641 
02642     SECTION("more involved conversions")
02643     {
02644         SECTION("object-like STL containers")
02645         {
02646             json j1 = {{"one", 1}, {"two", 2}, {"three", 3}};
02647             json j2 = {{"one", 1u}, {"two", 2u}, {"three", 3u}};
02648             json j3 = {{"one", 1.1}, {"two", 2.2}, {"three", 3.3}};
02649             json j4 = {{"one", true}, {"two", false}, {"three", true}};
02650             json j5 = {{"one", "eins"}, {"two", "zwei"}, {"three", "drei"}};
02651 
02652             SECTION("std::map")
02653             {
02654                 auto m1 = j1.get<std::map<std::string, int>>();
02655                 auto m2 = j2.get<std::map<std::string, unsigned int>>();
02656                 auto m3 = j3.get<std::map<std::string, double>>();
02657                 auto m4 = j4.get<std::map<std::string, bool>>();
02658                 //auto m5 = j5.get<std::map<std::string, std::string>>();
02659             }
02660 
02661             SECTION("std::unordered_map")
02662             {
02663                 auto m1 = j1.get<std::unordered_map<std::string, int>>();
02664                 auto m2 = j2.get<std::unordered_map<std::string, unsigned int>>();
02665                 auto m3 = j3.get<std::unordered_map<std::string, double>>();
02666                 auto m4 = j4.get<std::unordered_map<std::string, bool>>();
02667                 //auto m5 = j5.get<std::unordered_map<std::string, std::string>>();
02668                 //CHECK(m5["one"] == "eins");
02669             }
02670 
02671             SECTION("std::multimap")
02672             {
02673                 auto m1 = j1.get<std::multimap<std::string, int>>();
02674                 auto m2 = j2.get<std::multimap<std::string, unsigned int>>();
02675                 auto m3 = j3.get<std::multimap<std::string, double>>();
02676                 auto m4 = j4.get<std::multimap<std::string, bool>>();
02677                 //auto m5 = j5.get<std::multimap<std::string, std::string>>();
02678                 //CHECK(m5["one"] == "eins");
02679             }
02680 
02681             SECTION("std::unordered_multimap")
02682             {
02683                 auto m1 = j1.get<std::unordered_multimap<std::string, int>>();
02684                 auto m2 = j2.get<std::unordered_multimap<std::string, unsigned int>>();
02685                 auto m3 = j3.get<std::unordered_multimap<std::string, double>>();
02686                 auto m4 = j4.get<std::unordered_multimap<std::string, bool>>();
02687                 //auto m5 = j5.get<std::unordered_multimap<std::string, std::string>>();
02688                 //CHECK(m5["one"] == "eins");
02689             }
02690 
02691             SECTION("exception in case of a non-object type")
02692             {
02693                 CHECK_THROWS_AS((json().get<std::map<std::string, int>>()), std::logic_error);
02694                 CHECK_THROWS_WITH((json().get<std::map<std::string, int>>()), "type must be object, but is null");
02695             }
02696         }
02697 
02698         SECTION("array-like STL containers")
02699         {
02700             json j1 = {1, 2, 3, 4};
02701             json j2 = {1u, 2u, 3u, 4u};
02702             json j3 = {1.2, 2.3, 3.4, 4.5};
02703             json j4 = {true, false, true};
02704             json j5 = {"one", "two", "three"};
02705 
02706             SECTION("std::list")
02707             {
02708                 auto m1 = j1.get<std::list<int>>();
02709                 auto m2 = j2.get<std::list<unsigned int>>();
02710                 auto m3 = j3.get<std::list<double>>();
02711                 auto m4 = j4.get<std::list<bool>>();
02712                 auto m5 = j5.get<std::list<std::string>>();
02713             }
02714 
02715             //SECTION("std::forward_list")
02716             //{
02717             //    auto m1 = j1.get<std::forward_list<int>>();
02718             //    auto m2 = j2.get<std::forward_list<unsigned int>>();
02719             //    auto m3 = j3.get<std::forward_list<double>>();
02720             //    auto m4 = j4.get<std::forward_list<bool>>();
02721             //    auto m5 = j5.get<std::forward_list<std::string>>();
02722             //}
02723 
02724             SECTION("std::vector")
02725             {
02726                 auto m1 = j1.get<std::vector<int>>();
02727                 auto m2 = j2.get<std::vector<unsigned int>>();
02728                 auto m3 = j3.get<std::vector<double>>();
02729                 auto m4 = j4.get<std::vector<bool>>();
02730                 auto m5 = j5.get<std::vector<std::string>>();
02731             }
02732 
02733             SECTION("std::deque")
02734             {
02735                 auto m1 = j1.get<std::deque<int>>();
02736                 auto m2 = j2.get<std::deque<unsigned int>>();
02737                 auto m3 = j2.get<std::deque<double>>();
02738                 auto m4 = j4.get<std::deque<bool>>();
02739                 auto m5 = j5.get<std::deque<std::string>>();
02740             }
02741 
02742             SECTION("std::set")
02743             {
02744                 auto m1 = j1.get<std::set<int>>();
02745                 auto m2 = j2.get<std::set<unsigned int>>();
02746                 auto m3 = j3.get<std::set<double>>();
02747                 auto m4 = j4.get<std::set<bool>>();
02748                 auto m5 = j5.get<std::set<std::string>>();
02749             }
02750 
02751             SECTION("std::unordered_set")
02752             {
02753                 auto m1 = j1.get<std::unordered_set<int>>();
02754                 auto m2 = j2.get<std::unordered_set<unsigned int>>();
02755                 auto m3 = j3.get<std::unordered_set<double>>();
02756                 auto m4 = j4.get<std::unordered_set<bool>>();
02757                 auto m5 = j5.get<std::unordered_set<std::string>>();
02758             }
02759 
02760             SECTION("exception in case of a non-object type")
02761             {
02762                 CHECK_THROWS_AS((json().get<std::list<int>>()), std::logic_error);
02763                 CHECK_THROWS_AS((json().get<std::vector<int>>()), std::logic_error);
02764                 CHECK_THROWS_AS((json().get<std::vector<json>>()), std::logic_error);
02765                 CHECK_THROWS_AS((json().get<std::list<json>>()), std::logic_error);
02766 
02767                 CHECK_THROWS_WITH((json().get<std::list<int>>()), "type must be array, but is null");
02768                 CHECK_THROWS_WITH((json().get<std::vector<int>>()), "type must be array, but is null");
02769                 CHECK_THROWS_WITH((json().get<std::vector<json>>()), "type must be array, but is null");
02770                 CHECK_THROWS_WITH((json().get<std::list<json>>()), "type must be array, but is null");
02771             }
02772         }
02773     }
02774 }
02775 
02776 TEST_CASE("pointer access")
02777 {
02778     // create a JSON value with different types
02779     json json_types =
02780     {
02781         {"boolean", true},
02782         {
02783             "number", {
02784                 {"integer", 42},
02785                 {"unsigned", 42u},
02786                 {"floating-point", 17.23}
02787             }
02788         },
02789         {"string", "Hello, world!"},
02790         {"array", {1, 2, 3, 4, 5}},
02791         {"null", nullptr}
02792     };
02793 
02794     SECTION("pointer access to object_t")
02795     {
02796         using test_type = json::object_t;
02797         json value = {{"one", 1}, {"two", 2}};
02798 
02799         // check if pointers are returned correctly
02800         test_type* p1 = value.get_ptr<test_type*>();
02801         CHECK(p1 == value.get_ptr<test_type*>());
02802         CHECK(*p1 == value.get<test_type>());
02803 
02804         const test_type* p2 = value.get_ptr<const test_type*>();
02805         CHECK(p1 == value.get_ptr<const test_type*>());
02806         CHECK(*p2 == value.get<test_type>());
02807 
02808         const test_type* const p3 = value.get_ptr<const test_type* const>();
02809         CHECK(p1 == value.get_ptr<const test_type* const>());
02810         CHECK(*p3 == value.get<test_type>());
02811 
02812         // check if null pointers are returned correctly
02813         CHECK(value.get_ptr<json::object_t*>() != nullptr);
02814         CHECK(value.get_ptr<json::array_t*>() == nullptr);
02815         CHECK(value.get_ptr<json::string_t*>() == nullptr);
02816         CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
02817         CHECK(value.get_ptr<json::number_integer_t*>() == nullptr);
02818         CHECK(value.get_ptr<json::number_unsigned_t*>() == nullptr);
02819         CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
02820     }
02821 
02822     SECTION("pointer access to const object_t")
02823     {
02824         using test_type = json::object_t;
02825         const json value = {{"one", 1}, {"two", 2}};
02826 
02827         // this should not compile
02828         // test_type* p1 = value.get_ptr<test_type*>();
02829 
02830         // check if pointers are returned correctly
02831         const test_type* p2 = value.get_ptr<const test_type*>();
02832         CHECK(*p2 == value.get<test_type>());
02833 
02834         const test_type* const p3 = value.get_ptr<const test_type* const>();
02835         CHECK(p2 == p3);
02836     }
02837 
02838     SECTION("pointer access to array_t")
02839     {
02840         using test_type = json::array_t;
02841         json value = {1, 2, 3, 4};
02842 
02843         // check if pointers are returned correctly
02844         test_type* p1 = value.get_ptr<test_type*>();
02845         CHECK(p1 == value.get_ptr<test_type*>());
02846         CHECK(*p1 == value.get<test_type>());
02847 
02848         const test_type* p2 = value.get_ptr<const test_type*>();
02849         CHECK(p1 == value.get_ptr<const test_type*>());
02850         CHECK(*p2 == value.get<test_type>());
02851 
02852         const test_type* const p3 = value.get_ptr<const test_type* const>();
02853         CHECK(p1 == value.get_ptr<const test_type* const>());
02854         CHECK(*p3 == value.get<test_type>());
02855 
02856         // check if null pointers are returned correctly
02857         CHECK(value.get_ptr<json::object_t*>() == nullptr);
02858         CHECK(value.get_ptr<json::array_t*>() != nullptr);
02859         CHECK(value.get_ptr<json::string_t*>() == nullptr);
02860         CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
02861         CHECK(value.get_ptr<json::number_integer_t*>() == nullptr);
02862         CHECK(value.get_ptr<json::number_unsigned_t*>() == nullptr);
02863         CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
02864     }
02865 
02866     SECTION("pointer access to string_t")
02867     {
02868         using test_type = json::string_t;
02869         json value = "hello";
02870 
02871         // check if pointers are returned correctly
02872         test_type* p1 = value.get_ptr<test_type*>();
02873         CHECK(p1 == value.get_ptr<test_type*>());
02874         CHECK(*p1 == value.get<test_type>());
02875 
02876         const test_type* p2 = value.get_ptr<const test_type*>();
02877         CHECK(p1 == value.get_ptr<const test_type*>());
02878         CHECK(*p2 == value.get<test_type>());
02879 
02880         const test_type* const p3 = value.get_ptr<const test_type* const>();
02881         CHECK(p1 == value.get_ptr<const test_type* const>());
02882         CHECK(*p3 == value.get<test_type>());
02883 
02884         // check if null pointers are returned correctly
02885         CHECK(value.get_ptr<json::object_t*>() == nullptr);
02886         CHECK(value.get_ptr<json::array_t*>() == nullptr);
02887         CHECK(value.get_ptr<json::string_t*>() != nullptr);
02888         CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
02889         CHECK(value.get_ptr<json::number_integer_t*>() == nullptr);
02890         CHECK(value.get_ptr<json::number_unsigned_t*>() == nullptr);
02891         CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
02892     }
02893 
02894     SECTION("pointer access to boolean_t")
02895     {
02896         using test_type = json::boolean_t;
02897         json value = false;
02898 
02899         // check if pointers are returned correctly
02900         test_type* p1 = value.get_ptr<test_type*>();
02901         CHECK(p1 == value.get_ptr<test_type*>());
02902         CHECK(*p1 == value.get<test_type>());
02903 
02904         const test_type* p2 = value.get_ptr<const test_type*>();
02905         CHECK(p1 == value.get_ptr<const test_type*>());
02906         CHECK(*p2 == value.get<test_type>());
02907 
02908         const test_type* const p3 = value.get_ptr<const test_type* const>();
02909         CHECK(p1 == value.get_ptr<const test_type* const>());
02910         CHECK(*p3 == value.get<test_type>());
02911 
02912         // check if null pointers are returned correctly
02913         CHECK(value.get_ptr<json::object_t*>() == nullptr);
02914         CHECK(value.get_ptr<json::array_t*>() == nullptr);
02915         CHECK(value.get_ptr<json::string_t*>() == nullptr);
02916         CHECK(value.get_ptr<json::boolean_t*>() != nullptr);
02917         CHECK(value.get_ptr<json::number_integer_t*>() == nullptr);
02918         CHECK(value.get_ptr<json::number_unsigned_t*>() == nullptr);
02919         CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
02920     }
02921 
02922     SECTION("pointer access to number_integer_t")
02923     {
02924         using test_type = json::number_integer_t;
02925         json value = 23;
02926 
02927         // check if pointers are returned correctly
02928         test_type* p1 = value.get_ptr<test_type*>();
02929         CHECK(p1 == value.get_ptr<test_type*>());
02930         CHECK(*p1 == value.get<test_type>());
02931 
02932         const test_type* p2 = value.get_ptr<const test_type*>();
02933         CHECK(p1 == value.get_ptr<const test_type*>());
02934         CHECK(*p2 == value.get<test_type>());
02935 
02936         const test_type* const p3 = value.get_ptr<const test_type* const>();
02937         CHECK(p1 == value.get_ptr<const test_type* const>());
02938         CHECK(*p3 == value.get<test_type>());
02939 
02940         // check if null pointers are returned correctly
02941         CHECK(value.get_ptr<json::object_t*>() == nullptr);
02942         CHECK(value.get_ptr<json::array_t*>() == nullptr);
02943         CHECK(value.get_ptr<json::string_t*>() == nullptr);
02944         CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
02945         CHECK(value.get_ptr<json::number_integer_t*>() != nullptr);
02946         CHECK(value.get_ptr<json::number_unsigned_t*>() == nullptr);
02947         CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
02948     }
02949 
02950     SECTION("pointer access to number_unsigned_t")
02951     {
02952         using test_type = json::number_unsigned_t;
02953         json value = 23u;
02954 
02955         // check if pointers are returned correctly
02956         test_type* p1 = value.get_ptr<test_type*>();
02957         CHECK(p1 == value.get_ptr<test_type*>());
02958         CHECK(*p1 == value.get<test_type>());
02959 
02960         const test_type* p2 = value.get_ptr<const test_type*>();
02961         CHECK(p1 == value.get_ptr<const test_type*>());
02962         CHECK(*p2 == value.get<test_type>());
02963 
02964         const test_type* const p3 = value.get_ptr<const test_type* const>();
02965         CHECK(p1 == value.get_ptr<const test_type* const>());
02966         CHECK(*p3 == value.get<test_type>());
02967 
02968         // check if null pointers are returned correctly
02969         CHECK(value.get_ptr<json::object_t*>() == nullptr);
02970         CHECK(value.get_ptr<json::array_t*>() == nullptr);
02971         CHECK(value.get_ptr<json::string_t*>() == nullptr);
02972         CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
02973         CHECK(value.get_ptr<json::number_integer_t*>() != nullptr);
02974         CHECK(value.get_ptr<json::number_unsigned_t*>() != nullptr);
02975         CHECK(value.get_ptr<json::number_float_t*>() == nullptr);
02976     }
02977 
02978     SECTION("pointer access to number_float_t")
02979     {
02980         using test_type = json::number_float_t;
02981         json value = 42.23;
02982 
02983         // check if pointers are returned correctly
02984         test_type* p1 = value.get_ptr<test_type*>();
02985         CHECK(p1 == value.get_ptr<test_type*>());
02986         CHECK(*p1 == Approx(value.get<test_type>()));
02987 
02988         const test_type* p2 = value.get_ptr<const test_type*>();
02989         CHECK(p1 == value.get_ptr<const test_type*>());
02990         CHECK(*p2 == Approx(value.get<test_type>()));
02991 
02992         const test_type* const p3 = value.get_ptr<const test_type* const>();
02993         CHECK(p1 == value.get_ptr<const test_type* const>());
02994         CHECK(*p3 == Approx(value.get<test_type>()));
02995 
02996         // check if null pointers are returned correctly
02997         CHECK(value.get_ptr<json::object_t*>() == nullptr);
02998         CHECK(value.get_ptr<json::array_t*>() == nullptr);
02999         CHECK(value.get_ptr<json::string_t*>() == nullptr);
03000         CHECK(value.get_ptr<json::boolean_t*>() == nullptr);
03001         CHECK(value.get_ptr<json::number_integer_t*>() == nullptr);
03002         CHECK(value.get_ptr<json::number_unsigned_t*>() == nullptr);
03003         CHECK(value.get_ptr<json::number_float_t*>() != nullptr);
03004     }
03005 }
03006 
03007 TEST_CASE("reference access")
03008 {
03009     // create a JSON value with different types
03010     json json_types =
03011     {
03012         {"boolean", true},
03013         {
03014             "number", {
03015                 {"integer", 42},
03016                 {"floating-point", 17.23}
03017             }
03018         },
03019         {"string", "Hello, world!"},
03020         {"array", {1, 2, 3, 4, 5}},
03021         {"null", nullptr}
03022     };
03023 
03024     SECTION("reference access to object_t")
03025     {
03026         using test_type = json::object_t;
03027         json value = {{"one", 1}, {"two", 2}};
03028 
03029         // check if references are returned correctly
03030         test_type& p1 = value.get_ref<test_type&>();
03031         CHECK(&p1 == value.get_ptr<test_type*>());
03032         CHECK(p1 == value.get<test_type>());
03033 
03034         const test_type& p2 = value.get_ref<const test_type&>();
03035         CHECK(&p2 == value.get_ptr<const test_type*>());
03036         CHECK(p2 == value.get<test_type>());
03037 
03038         // check if mismatching references throw correctly
03039         CHECK_NOTHROW(value.get_ref<json::object_t&>());
03040         CHECK_THROWS(value.get_ref<json::array_t&>());
03041         CHECK_THROWS(value.get_ref<json::string_t&>());
03042         CHECK_THROWS(value.get_ref<json::boolean_t&>());
03043         CHECK_THROWS(value.get_ref<json::number_integer_t&>());
03044         CHECK_THROWS(value.get_ref<json::number_float_t&>());
03045     }
03046 
03047     SECTION("const reference access to const object_t")
03048     {
03049         using test_type = json::object_t;
03050         const json value = {{"one", 1}, {"two", 2}};
03051 
03052         // this should not compile
03053         // test_type& p1 = value.get_ref<test_type&>();
03054 
03055         // check if references are returned correctly
03056         const test_type& p2 = value.get_ref<const test_type&>();
03057         CHECK(&p2 == value.get_ptr<const test_type*>());
03058         CHECK(p2 == value.get<test_type>());
03059     }
03060 
03061     SECTION("reference access to array_t")
03062     {
03063         using test_type = json::array_t;
03064         json value = {1, 2, 3, 4};
03065 
03066         // check if references are returned correctly
03067         test_type& p1 = value.get_ref<test_type&>();
03068         CHECK(&p1 == value.get_ptr<test_type*>());
03069         CHECK(p1 == value.get<test_type>());
03070 
03071         const test_type& p2 = value.get_ref<const test_type&>();
03072         CHECK(&p2 == value.get_ptr<const test_type*>());
03073         CHECK(p2 == value.get<test_type>());
03074 
03075         // check if mismatching references throw correctly
03076         CHECK_THROWS(value.get_ref<json::object_t&>());
03077         CHECK_NOTHROW(value.get_ref<json::array_t&>());
03078         CHECK_THROWS(value.get_ref<json::string_t&>());
03079         CHECK_THROWS(value.get_ref<json::boolean_t&>());
03080         CHECK_THROWS(value.get_ref<json::number_integer_t&>());
03081         CHECK_THROWS(value.get_ref<json::number_float_t&>());
03082     }
03083 
03084     SECTION("reference access to string_t")
03085     {
03086         using test_type = json::string_t;
03087         json value = "hello";
03088 
03089         // check if references are returned correctly
03090         test_type& p1 = value.get_ref<test_type&>();
03091         CHECK(&p1 == value.get_ptr<test_type*>());
03092         CHECK(p1 == value.get<test_type>());
03093 
03094         const test_type& p2 = value.get_ref<const test_type&>();
03095         CHECK(&p2 == value.get_ptr<const test_type*>());
03096         CHECK(p2 == value.get<test_type>());
03097 
03098         // check if mismatching references throw correctly
03099         CHECK_THROWS(value.get_ref<json::object_t&>());
03100         CHECK_THROWS(value.get_ref<json::array_t&>());
03101         CHECK_NOTHROW(value.get_ref<json::string_t&>());
03102         CHECK_THROWS(value.get_ref<json::boolean_t&>());
03103         CHECK_THROWS(value.get_ref<json::number_integer_t&>());
03104         CHECK_THROWS(value.get_ref<json::number_float_t&>());
03105     }
03106 
03107     SECTION("reference access to boolean_t")
03108     {
03109         using test_type = json::boolean_t;
03110         json value = false;
03111 
03112         // check if references are returned correctly
03113         test_type& p1 = value.get_ref<test_type&>();
03114         CHECK(&p1 == value.get_ptr<test_type*>());
03115         CHECK(p1 == value.get<test_type>());
03116 
03117         const test_type& p2 = value.get_ref<const test_type&>();
03118         CHECK(&p2 == value.get_ptr<const test_type*>());
03119         CHECK(p2 == value.get<test_type>());
03120 
03121         // check if mismatching references throw correctly
03122         CHECK_THROWS(value.get_ref<json::object_t&>());
03123         CHECK_THROWS(value.get_ref<json::array_t&>());
03124         CHECK_THROWS(value.get_ref<json::string_t&>());
03125         CHECK_NOTHROW(value.get_ref<json::boolean_t&>());
03126         CHECK_THROWS(value.get_ref<json::number_integer_t&>());
03127         CHECK_THROWS(value.get_ref<json::number_float_t&>());
03128     }
03129 
03130     SECTION("reference access to number_integer_t")
03131     {
03132         using test_type = json::number_integer_t;
03133         json value = 23;
03134 
03135         // check if references are returned correctly
03136         test_type& p1 = value.get_ref<test_type&>();
03137         CHECK(&p1 == value.get_ptr<test_type*>());
03138         CHECK(p1 == value.get<test_type>());
03139 
03140         const test_type& p2 = value.get_ref<const test_type&>();
03141         CHECK(&p2 == value.get_ptr<const test_type*>());
03142         CHECK(p2 == value.get<test_type>());
03143 
03144         // check if mismatching references throw correctly
03145         CHECK_THROWS(value.get_ref<json::object_t&>());
03146         CHECK_THROWS(value.get_ref<json::array_t&>());
03147         CHECK_THROWS(value.get_ref<json::string_t&>());
03148         CHECK_THROWS(value.get_ref<json::boolean_t&>());
03149         CHECK_NOTHROW(value.get_ref<json::number_integer_t&>());
03150         CHECK_THROWS(value.get_ref<json::number_float_t&>());
03151     }
03152 
03153     SECTION("reference access to number_float_t")
03154     {
03155         using test_type = json::number_float_t;
03156         json value = 42.23;
03157 
03158         // check if references are returned correctly
03159         test_type& p1 = value.get_ref<test_type&>();
03160         CHECK(&p1 == value.get_ptr<test_type*>());
03161         CHECK(p1 == value.get<test_type>());
03162 
03163         const test_type& p2 = value.get_ref<const test_type&>();
03164         CHECK(&p2 == value.get_ptr<const test_type*>());
03165         CHECK(p2 == value.get<test_type>());
03166 
03167         // check if mismatching references throw correctly
03168         CHECK_THROWS(value.get_ref<json::object_t&>());
03169         CHECK_THROWS(value.get_ref<json::array_t&>());
03170         CHECK_THROWS(value.get_ref<json::string_t&>());
03171         CHECK_THROWS(value.get_ref<json::boolean_t&>());
03172         CHECK_THROWS(value.get_ref<json::number_integer_t&>());
03173         CHECK_NOTHROW(value.get_ref<json::number_float_t&>());
03174     }
03175 }
03176 
03177 TEST_CASE("element access")
03178 {
03179     SECTION("array")
03180     {
03181         json j = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03182         const json j_const = j;
03183 
03184         SECTION("access specified element with bounds checking")
03185         {
03186             SECTION("access within bounds")
03187             {
03188                 CHECK(j.at(0) == json(1));
03189                 CHECK(j.at(1) == json(1u));
03190                 CHECK(j.at(2) == json(true));
03191                 CHECK(j.at(3) == json(nullptr));
03192                 CHECK(j.at(4) == json("string"));
03193                 CHECK(j.at(5) == json(42.23));
03194                 CHECK(j.at(6) == json(json::object()));
03195                 CHECK(j.at(7) == json({1, 2, 3}));
03196 
03197                 CHECK(j_const.at(0) == json(1));
03198                 CHECK(j_const.at(1) == json(1u));
03199                 CHECK(j_const.at(2) == json(true));
03200                 CHECK(j_const.at(3) == json(nullptr));
03201                 CHECK(j_const.at(4) == json("string"));
03202                 CHECK(j_const.at(5) == json(42.23));
03203                 CHECK(j_const.at(6) == json(json::object()));
03204                 CHECK(j_const.at(7) == json({1, 2, 3}));
03205             }
03206 
03207             SECTION("access outside bounds")
03208             {
03209                 CHECK_THROWS_AS(j.at(8), std::out_of_range);
03210                 CHECK_THROWS_AS(j_const.at(8), std::out_of_range);
03211 
03212                 CHECK_THROWS_WITH(j.at(8), "array index 8 is out of range");
03213                 CHECK_THROWS_WITH(j_const.at(8), "array index 8 is out of range");
03214             }
03215 
03216             SECTION("access on non-array type")
03217             {
03218                 SECTION("null")
03219                 {
03220                     json j_nonarray(json::value_t::null);
03221                     const json j_nonarray_const(j_nonarray);
03222                     CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error);
03223                     CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error);
03224 
03225                     CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with null");
03226                     CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with null");
03227                 }
03228 
03229                 SECTION("boolean")
03230                 {
03231                     json j_nonarray(json::value_t::boolean);
03232                     const json j_nonarray_const(j_nonarray);
03233                     CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error);
03234                     CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error);
03235 
03236                     CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with boolean");
03237                     CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with boolean");
03238                 }
03239 
03240                 SECTION("string")
03241                 {
03242                     json j_nonarray(json::value_t::string);
03243                     const json j_nonarray_const(j_nonarray);
03244                     CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error);
03245                     CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error);
03246 
03247                     CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with string");
03248                     CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with string");
03249                 }
03250 
03251                 SECTION("object")
03252                 {
03253                     json j_nonarray(json::value_t::object);
03254                     const json j_nonarray_const(j_nonarray);
03255                     CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error);
03256                     CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error);
03257 
03258                     CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with object");
03259                     CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with object");
03260                 }
03261 
03262                 SECTION("number (integer)")
03263                 {
03264                     json j_nonarray(json::value_t::number_integer);
03265                     const json j_nonarray_const(j_nonarray);
03266                     CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error);
03267                     CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error);
03268 
03269                     CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with number");
03270                     CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with number");
03271                 }
03272 
03273                 SECTION("number (unsigned)")
03274                 {
03275                     json j_nonarray(json::value_t::number_unsigned);
03276                     const json j_nonarray_const(j_nonarray);
03277                     CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error);
03278                     CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error);
03279 
03280                     CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with number");
03281                     CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with number");
03282                 }
03283 
03284                 SECTION("number (floating-point)")
03285                 {
03286                     json j_nonarray(json::value_t::number_float);
03287                     const json j_nonarray_const(j_nonarray);
03288                     CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error);
03289                     CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error);
03290 
03291                     CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with number");
03292                     CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with number");
03293                 }
03294             }
03295         }
03296 
03297         SECTION("front and back")
03298         {
03299             CHECK(j.front() == json(1));
03300             CHECK(j_const.front() == json(1));
03301             CHECK(j.back() == json({1, 2, 3}));
03302             CHECK(j_const.back() == json({1, 2, 3}));
03303         }
03304 
03305         SECTION("access specified element")
03306         {
03307             SECTION("access within bounds")
03308             {
03309                 CHECK(j[0] == json(1));
03310                 CHECK(j[1] == json(1u));
03311                 CHECK(j[2] == json(true));
03312                 CHECK(j[3] == json(nullptr));
03313                 CHECK(j[4] == json("string"));
03314                 CHECK(j[5] == json(42.23));
03315                 CHECK(j[6] == json(json::object()));
03316                 CHECK(j[7] == json({1, 2, 3}));
03317 
03318                 CHECK(j_const[0] == json(1));
03319                 CHECK(j_const[1] == json(1u));
03320                 CHECK(j_const[2] == json(true));
03321                 CHECK(j_const[3] == json(nullptr));
03322                 CHECK(j_const[4] == json("string"));
03323                 CHECK(j_const[5] == json(42.23));
03324                 CHECK(j_const[6] == json(json::object()));
03325                 CHECK(j_const[7] == json({1, 2, 3}));
03326             }
03327 
03328             SECTION("access on non-array type")
03329             {
03330                 SECTION("null")
03331                 {
03332                     SECTION("standard tests")
03333                     {
03334                         json j_nonarray(json::value_t::null);
03335                         const json j_nonarray_const(j_nonarray);
03336                         CHECK_NOTHROW(j_nonarray[0]);
03337                         CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error);
03338                         CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with null");
03339                     }
03340 
03341                     SECTION("implicit transformation to properly filled array")
03342                     {
03343                         json j_nonarray;
03344                         j_nonarray[3] = 42;
03345                         CHECK(j_nonarray == json({nullptr, nullptr, nullptr, 42}));
03346                     }
03347                 }
03348 
03349                 SECTION("boolean")
03350                 {
03351                     json j_nonarray(json::value_t::boolean);
03352                     const json j_nonarray_const(j_nonarray);
03353                     CHECK_THROWS_AS(j_nonarray[0], std::domain_error);
03354                     CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error);
03355                     CHECK_THROWS_WITH(j_nonarray[0], "cannot use operator[] with boolean");
03356                     CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with boolean");
03357                 }
03358 
03359                 SECTION("string")
03360                 {
03361                     json j_nonarray(json::value_t::string);
03362                     const json j_nonarray_const(j_nonarray);
03363                     CHECK_THROWS_AS(j_nonarray[0], std::domain_error);
03364                     CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error);
03365                     CHECK_THROWS_WITH(j_nonarray[0], "cannot use operator[] with string");
03366                     CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with string");
03367                 }
03368 
03369                 SECTION("object")
03370                 {
03371                     json j_nonarray(json::value_t::object);
03372                     const json j_nonarray_const(j_nonarray);
03373                     CHECK_THROWS_AS(j_nonarray[0], std::domain_error);
03374                     CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error);
03375                     CHECK_THROWS_WITH(j_nonarray[0], "cannot use operator[] with object");
03376                     CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with object");
03377                 }
03378 
03379                 SECTION("number (integer)")
03380                 {
03381                     json j_nonarray(json::value_t::number_integer);
03382                     const json j_nonarray_const(j_nonarray);
03383                     CHECK_THROWS_AS(j_nonarray[0], std::domain_error);
03384                     CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error);
03385                     CHECK_THROWS_WITH(j_nonarray[0], "cannot use operator[] with number");
03386                     CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with number");
03387                 }
03388 
03389                 SECTION("number (unsigned)")
03390                 {
03391                     json j_nonarray(json::value_t::number_unsigned);
03392                     const json j_nonarray_const(j_nonarray);
03393                     CHECK_THROWS_AS(j_nonarray[0], std::domain_error);
03394                     CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error);
03395                     CHECK_THROWS_WITH(j_nonarray[0], "cannot use operator[] with number");
03396                     CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with number");
03397                 }
03398 
03399                 SECTION("number (floating-point)")
03400                 {
03401                     json j_nonarray(json::value_t::number_float);
03402                     const json j_nonarray_const(j_nonarray);
03403                     CHECK_THROWS_AS(j_nonarray[0], std::domain_error);
03404                     CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error);
03405                     CHECK_THROWS_WITH(j_nonarray[0], "cannot use operator[] with number");
03406                     CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with number");
03407                 }
03408             }
03409         }
03410 
03411         SECTION("remove specified element")
03412         {
03413             SECTION("remove element by index")
03414             {
03415                 {
03416                     json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03417                     jarray.erase(0);
03418                     CHECK(jarray == json({1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
03419                 }
03420                 {
03421                     json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03422                     jarray.erase(1);
03423                     CHECK(jarray == json({1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
03424                 }
03425                 {
03426                     json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03427                     jarray.erase(2);
03428                     CHECK(jarray == json({1, 1u, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
03429                 }
03430                 {
03431                     json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03432                     jarray.erase(3);
03433                     CHECK(jarray == json({1, 1u, true, "string", 42.23, json::object(), {1, 2, 3}}));
03434                 }
03435                 {
03436                     json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03437                     jarray.erase(4);
03438                     CHECK(jarray == json({1, 1u, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
03439                 }
03440                 {
03441                     json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03442                     jarray.erase(5);
03443                     CHECK(jarray == json({1, 1u, true, nullptr, "string", json::object(), {1, 2, 3}}));
03444                 }
03445                 {
03446                     json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03447                     jarray.erase(6);
03448                     CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, {1, 2, 3}}));
03449                 }
03450                 {
03451                     json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03452                     jarray.erase(7);
03453                     CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, json::object()}));
03454                 }
03455                 {
03456                     json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03457                     CHECK_THROWS_AS(jarray.erase(8), std::out_of_range);
03458                     CHECK_THROWS_WITH(jarray.erase(8), "array index 8 is out of range");
03459                 }
03460             }
03461 
03462             SECTION("remove element by iterator")
03463             {
03464                 SECTION("erase(begin())")
03465                 {
03466                     {
03467                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03468                         json::iterator it2 = jarray.erase(jarray.begin());
03469                         CHECK(jarray == json({1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
03470                         CHECK(*it2 == json(1u));
03471                     }
03472                     {
03473                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03474                         json::const_iterator it2 = jarray.erase(jarray.cbegin());
03475                         CHECK(jarray == json({1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
03476                         CHECK(*it2 == json(1u));
03477                     }
03478                 }
03479 
03480                 SECTION("erase(begin(), end())")
03481                 {
03482                     {
03483                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03484                         json::iterator it2 = jarray.erase(jarray.begin(), jarray.end());
03485                         CHECK(jarray == json::array());
03486                         CHECK(it2 == jarray.end());
03487                     }
03488                     {
03489                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03490                         json::const_iterator it2 = jarray.erase(jarray.cbegin(), jarray.cend());
03491                         CHECK(jarray == json::array());
03492                         CHECK(it2 == jarray.cend());
03493                     }
03494                 }
03495 
03496                 SECTION("erase(begin(), begin())")
03497                 {
03498                     {
03499                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03500                         json::iterator it2 = jarray.erase(jarray.begin(), jarray.begin());
03501                         CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
03502                         CHECK(*it2 == json(1));
03503                     }
03504                     {
03505                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03506                         json::const_iterator it2 = jarray.erase(jarray.cbegin(), jarray.cbegin());
03507                         CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
03508                         CHECK(*it2 == json(1));
03509                     }
03510                 }
03511 
03512                 SECTION("erase at offset")
03513                 {
03514                     {
03515                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03516                         json::iterator it = jarray.begin() + 4;
03517                         json::iterator it2 = jarray.erase(it);
03518                         CHECK(jarray == json({1, 1u, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
03519                         CHECK(*it2 == json(42.23));
03520                     }
03521                     {
03522                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03523                         json::const_iterator it = jarray.cbegin() + 4;
03524                         json::const_iterator it2 = jarray.erase(it);
03525                         CHECK(jarray == json({1, 1u, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
03526                         CHECK(*it2 == json(42.23));
03527                     }
03528                 }
03529 
03530                 SECTION("erase subrange")
03531                 {
03532                     {
03533                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03534                         json::iterator it2 = jarray.erase(jarray.begin() + 3, jarray.begin() + 6);
03535                         CHECK(jarray == json({1, 1u, true, json::object(), {1, 2, 3}}));
03536                         CHECK(*it2 == json::object());
03537                     }
03538                     {
03539                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03540                         json::const_iterator it2 = jarray.erase(jarray.cbegin() + 3, jarray.cbegin() + 6);
03541                         CHECK(jarray == json({1, 1u, true, json::object(), {1, 2, 3}}));
03542                         CHECK(*it2 == json::object());
03543                     }
03544                 }
03545 
03546                 SECTION("different arrays")
03547                 {
03548                     {
03549                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03550                         json jarray2 = {"foo", "bar"};
03551                         CHECK_THROWS_AS(jarray.erase(jarray2.begin()), std::domain_error);
03552                         CHECK_THROWS_AS(jarray.erase(jarray.begin(), jarray2.end()), std::domain_error);
03553                         CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray.end()), std::domain_error);
03554                         CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray2.end()), std::domain_error);
03555 
03556                         CHECK_THROWS_WITH(jarray.erase(jarray2.begin()), "iterator does not fit current value");
03557                         CHECK_THROWS_WITH(jarray.erase(jarray.begin(), jarray2.end()),
03558                                           "iterators do not fit current value");
03559                         CHECK_THROWS_WITH(jarray.erase(jarray2.begin(), jarray.end()),
03560                                           "iterators do not fit current value");
03561                         CHECK_THROWS_WITH(jarray.erase(jarray2.begin(), jarray2.end()),
03562                                           "iterators do not fit current value");
03563                     }
03564                     {
03565                         json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
03566                         json jarray2 = {"foo", "bar"};
03567                         CHECK_THROWS_AS(jarray.erase(jarray2.cbegin()), std::domain_error);
03568                         CHECK_THROWS_AS(jarray.erase(jarray.cbegin(), jarray2.cend()), std::domain_error);
03569                         CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray.cend()), std::domain_error);
03570                         CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray2.cend()), std::domain_error);
03571 
03572                         CHECK_THROWS_WITH(jarray.erase(jarray2.cbegin()), "iterator does not fit current value");
03573                         CHECK_THROWS_WITH(jarray.erase(jarray.cbegin(), jarray2.cend()),
03574                                           "iterators do not fit current value");
03575                         CHECK_THROWS_WITH(jarray.erase(jarray2.cbegin(), jarray.cend()),
03576                                           "iterators do not fit current value");
03577                         CHECK_THROWS_WITH(jarray.erase(jarray2.cbegin(), jarray2.cend()),
03578                                           "iterators do not fit current value");
03579                     }
03580                 }
03581             }
03582 
03583             SECTION("remove element by index in non-array type")
03584             {
03585                 SECTION("null")
03586                 {
03587                     json j_nonobject(json::value_t::null);
03588                     CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error);
03589                     CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with null");
03590                 }
03591 
03592                 SECTION("boolean")
03593                 {
03594                     json j_nonobject(json::value_t::boolean);
03595                     CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error);
03596                     CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with boolean");
03597                 }
03598 
03599                 SECTION("string")
03600                 {
03601                     json j_nonobject(json::value_t::string);
03602                     CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error);
03603                     CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with string");
03604                 }
03605 
03606                 SECTION("object")
03607                 {
03608                     json j_nonobject(json::value_t::object);
03609                     CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error);
03610                     CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with object");
03611                 }
03612 
03613                 SECTION("number (integer)")
03614                 {
03615                     json j_nonobject(json::value_t::number_integer);
03616                     CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error);
03617                     CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with number");
03618                 }
03619 
03620                 SECTION("number (unsigned)")
03621                 {
03622                     json j_nonobject(json::value_t::number_unsigned);
03623                     CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error);
03624                     CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with number");
03625                 }
03626 
03627                 SECTION("number (floating-point)")
03628                 {
03629                     json j_nonobject(json::value_t::number_float);
03630                     CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error);
03631                     CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with number");
03632                 }
03633             }
03634         }
03635     }
03636 
03637     SECTION("object")
03638     {
03639         json j = {{"integer", 1}, {"unsigned", 1u}, {"floating", 42.23}, {"null", nullptr}, {"string", "hello world"}, {"boolean", true}, {"object", json::object()}, {"array", {1, 2, 3}}};
03640         const json j_const = j;
03641 
03642         SECTION("access specified element with bounds checking")
03643         {
03644             SECTION("access within bounds")
03645             {
03646                 CHECK(j.at("integer") == json(1));
03647                 CHECK(j.at("unsigned") == json(1u));
03648                 CHECK(j.at("boolean") == json(true));
03649                 CHECK(j.at("null") == json(nullptr));
03650                 CHECK(j.at("string") == json("hello world"));
03651                 CHECK(j.at("floating") == json(42.23));
03652                 CHECK(j.at("object") == json(json::object()));
03653                 CHECK(j.at("array") == json({1, 2, 3}));
03654 
03655                 CHECK(j_const.at("integer") == json(1));
03656                 CHECK(j_const.at("unsigned") == json(1u));
03657                 CHECK(j_const.at("boolean") == json(true));
03658                 CHECK(j_const.at("null") == json(nullptr));
03659                 CHECK(j_const.at("string") == json("hello world"));
03660                 CHECK(j_const.at("floating") == json(42.23));
03661                 CHECK(j_const.at("object") == json(json::object()));
03662                 CHECK(j_const.at("array") == json({1, 2, 3}));
03663             }
03664 
03665             SECTION("access outside bounds")
03666             {
03667                 CHECK_THROWS_AS(j.at("foo"), std::out_of_range);
03668                 CHECK_THROWS_AS(j_const.at("foo"), std::out_of_range);
03669                 CHECK_THROWS_WITH(j.at("foo"), "key 'foo' not found");
03670                 CHECK_THROWS_WITH(j_const.at("foo"), "key 'foo' not found");
03671             }
03672 
03673             SECTION("access on non-object type")
03674             {
03675                 SECTION("null")
03676                 {
03677                     json j_nonobject(json::value_t::null);
03678                     const json j_nonobject_const(j_nonobject);
03679                     CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error);
03680                     CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error);
03681                     CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with null");
03682                     CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with null");
03683                 }
03684 
03685                 SECTION("boolean")
03686                 {
03687                     json j_nonobject(json::value_t::boolean);
03688                     const json j_nonobject_const(j_nonobject);
03689                     CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error);
03690                     CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error);
03691                     CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with boolean");
03692                     CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with boolean");
03693                 }
03694 
03695                 SECTION("string")
03696                 {
03697                     json j_nonobject(json::value_t::string);
03698                     const json j_nonobject_const(j_nonobject);
03699                     CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error);
03700                     CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error);
03701                     CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with string");
03702                     CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with string");
03703                 }
03704 
03705                 SECTION("array")
03706                 {
03707                     json j_nonobject(json::value_t::array);
03708                     const json j_nonobject_const(j_nonobject);
03709                     CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error);
03710                     CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error);
03711                     CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with array");
03712                     CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with array");
03713                 }
03714 
03715                 SECTION("number (integer)")
03716                 {
03717                     json j_nonobject(json::value_t::number_integer);
03718                     const json j_nonobject_const(j_nonobject);
03719                     CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error);
03720                     CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error);
03721                     CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with number");
03722                     CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with number");
03723                 }
03724 
03725                 SECTION("number (unsigned)")
03726                 {
03727                     json j_nonobject(json::value_t::number_unsigned);
03728                     const json j_nonobject_const(j_nonobject);
03729                     CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error);
03730                     CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error);
03731                     CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with number");
03732                     CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with number");
03733                 }
03734 
03735                 SECTION("number (floating-point)")
03736                 {
03737                     json j_nonobject(json::value_t::number_float);
03738                     const json j_nonobject_const(j_nonobject);
03739                     CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error);
03740                     CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error);
03741                     CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with number");
03742                     CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with number");
03743                 }
03744             }
03745         }
03746 
03747         SECTION("access specified element with default value")
03748         {
03749             SECTION("access existing value")
03750             {
03751                 CHECK(j.value("integer", 2) == 1);
03752                 CHECK(j.value("integer", 1.0) == Approx(1));
03753                 CHECK(j.value("unsigned", 2) == 1u);
03754                 CHECK(j.value("unsigned", 1.0) == Approx(1u));
03755                 CHECK(j.value("null", json(1)) == json());
03756                 CHECK(j.value("boolean", false) == true);
03757                 CHECK(j.value("string", "bar") == "hello world");
03758                 CHECK(j.value("string", std::string("bar")) == "hello world");
03759                 CHECK(j.value("floating", 12.34) == Approx(42.23));
03760                 CHECK(j.value("floating", 12) == 42);
03761                 CHECK(j.value("object", json({{"foo", "bar"}})) == json(json::object()));
03762                 CHECK(j.value("array", json({10, 100})) == json({1, 2, 3}));
03763 
03764                 CHECK(j_const.value("integer", 2) == 1);
03765                 CHECK(j_const.value("integer", 1.0) == Approx(1));
03766                 CHECK(j_const.value("unsigned", 2) == 1u);
03767                 CHECK(j_const.value("unsigned", 1.0) == Approx(1u));
03768                 CHECK(j_const.value("boolean", false) == true);
03769                 CHECK(j_const.value("string", "bar") == "hello world");
03770                 CHECK(j_const.value("string", std::string("bar")) == "hello world");
03771                 CHECK(j_const.value("floating", 12.34) == Approx(42.23));
03772                 CHECK(j_const.value("floating", 12) == 42);
03773                 CHECK(j_const.value("object", json({{"foo", "bar"}})) == json(json::object()));
03774                 CHECK(j_const.value("array", json({10, 100})) == json({1, 2, 3}));
03775             }
03776 
03777             SECTION("access non-existing value")
03778             {
03779                 CHECK(j.value("_", 2) == 2);
03780                 CHECK(j.value("_", 2u) == 2u);
03781                 CHECK(j.value("_", false) == false);
03782                 CHECK(j.value("_", "bar") == "bar");
03783                 CHECK(j.value("_", 12.34) == Approx(12.34));
03784                 CHECK(j.value("_", json({{"foo", "bar"}})) == json({{"foo", "bar"}}));
03785                 CHECK(j.value("_", json({10, 100})) == json({10, 100}));
03786 
03787                 CHECK(j_const.value("_", 2) == 2);
03788                 CHECK(j_const.value("_", 2u) == 2u);
03789                 CHECK(j_const.value("_", false) == false);
03790                 CHECK(j_const.value("_", "bar") == "bar");
03791                 CHECK(j_const.value("_", 12.34) == Approx(12.34));
03792                 CHECK(j_const.value("_", json({{"foo", "bar"}})) == json({{"foo", "bar"}}));
03793                 CHECK(j_const.value("_", json({10, 100})) == json({10, 100}));
03794             }
03795 
03796             SECTION("access on non-object type")
03797             {
03798                 SECTION("null")
03799                 {
03800                     json j_nonobject(json::value_t::null);
03801                     const json j_nonobject_const(j_nonobject);
03802                     CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error);
03803                     CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error);
03804                     CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with null");
03805                     CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with null");
03806                 }
03807 
03808                 SECTION("boolean")
03809                 {
03810                     json j_nonobject(json::value_t::boolean);
03811                     const json j_nonobject_const(j_nonobject);
03812                     CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error);
03813                     CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error);
03814                     CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with boolean");
03815                     CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with boolean");
03816                 }
03817 
03818                 SECTION("string")
03819                 {
03820                     json j_nonobject(json::value_t::string);
03821                     const json j_nonobject_const(j_nonobject);
03822                     CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error);
03823                     CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error);
03824                     CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with string");
03825                     CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with string");
03826                 }
03827 
03828                 SECTION("array")
03829                 {
03830                     json j_nonobject(json::value_t::array);
03831                     const json j_nonobject_const(j_nonobject);
03832                     CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error);
03833                     CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error);
03834                     CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with array");
03835                     CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with array");
03836                 }
03837 
03838                 SECTION("number (integer)")
03839                 {
03840                     json j_nonobject(json::value_t::number_integer);
03841                     const json j_nonobject_const(j_nonobject);
03842                     CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error);
03843                     CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error);
03844                     CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with number");
03845                     CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with number");
03846                 }
03847 
03848                 SECTION("number (unsigned)")
03849                 {
03850                     json j_nonobject(json::value_t::number_unsigned);
03851                     const json j_nonobject_const(j_nonobject);
03852                     CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error);
03853                     CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error);
03854                     CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with number");
03855                     CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with number");
03856                 }
03857 
03858                 SECTION("number (floating-point)")
03859                 {
03860                     json j_nonobject(json::value_t::number_float);
03861                     const json j_nonobject_const(j_nonobject);
03862                     CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error);
03863                     CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error);
03864                     CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with number");
03865                     CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with number");
03866                 }
03867             }
03868         }
03869 
03870         SECTION("front and back")
03871         {
03872             // "array" is the smallest key
03873             CHECK(j.front() == json({1, 2, 3}));
03874             CHECK(j_const.front() == json({1, 2, 3}));
03875             // "unsigned" is the largest key
03876             CHECK(j.back() == json(1u));
03877             CHECK(j_const.back() == json(1u));
03878         }
03879 
03880         SECTION("access specified element")
03881         {
03882             SECTION("access within bounds")
03883             {
03884                 CHECK(j["integer"] == json(1));
03885                 CHECK(j[json::object_t::key_type("integer")] == j["integer"]);
03886 
03887                 CHECK(j["unsigned"] == json(1u));
03888                 CHECK(j[json::object_t::key_type("unsigned")] == j["unsigned"]);
03889 
03890                 CHECK(j["boolean"] == json(true));
03891                 CHECK(j[json::object_t::key_type("boolean")] == j["boolean"]);
03892 
03893                 CHECK(j["null"] == json(nullptr));
03894                 CHECK(j[json::object_t::key_type("null")] == j["null"]);
03895 
03896                 CHECK(j["string"] == json("hello world"));
03897                 CHECK(j[json::object_t::key_type("string")] == j["string"]);
03898 
03899                 CHECK(j["floating"] == json(42.23));
03900                 CHECK(j[json::object_t::key_type("floating")] == j["floating"]);
03901 
03902                 CHECK(j["object"] == json(json::object()));
03903                 CHECK(j[json::object_t::key_type("object")] == j["object"]);
03904 
03905                 CHECK(j["array"] == json({1, 2, 3}));
03906                 CHECK(j[json::object_t::key_type("array")] == j["array"]);
03907 
03908                 CHECK(j_const["integer"] == json(1));
03909                 CHECK(j_const[json::object_t::key_type("integer")] == j["integer"]);
03910 
03911                 CHECK(j_const["boolean"] == json(true));
03912                 CHECK(j_const[json::object_t::key_type("boolean")] == j["boolean"]);
03913 
03914                 CHECK(j_const["null"] == json(nullptr));
03915                 CHECK(j_const[json::object_t::key_type("null")] == j["null"]);
03916 
03917                 CHECK(j_const["string"] == json("hello world"));
03918                 CHECK(j_const[json::object_t::key_type("string")] == j["string"]);
03919 
03920                 CHECK(j_const["floating"] == json(42.23));
03921                 CHECK(j_const[json::object_t::key_type("floating")] == j["floating"]);
03922 
03923                 CHECK(j_const["object"] == json(json::object()));
03924                 CHECK(j_const[json::object_t::key_type("object")] == j["object"]);
03925 
03926                 CHECK(j_const["array"] == json({1, 2, 3}));
03927                 CHECK(j_const[json::object_t::key_type("array")] == j["array"]);
03928             }
03929 
03930             SECTION("access on non-object type")
03931             {
03932                 SECTION("null")
03933                 {
03934                     json j_nonobject(json::value_t::null);
03935                     json j_nonobject2(json::value_t::null);
03936                     const json j_const_nonobject(j_nonobject);
03937                     CHECK_NOTHROW(j_nonobject["foo"]);
03938                     CHECK_NOTHROW(j_nonobject2[json::object_t::key_type("foo")]);
03939                     CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
03940                     CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
03941                     CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with null");
03942                     CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")],
03943                                       "cannot use operator[] with null");
03944                 }
03945 
03946                 SECTION("boolean")
03947                 {
03948                     json j_nonobject(json::value_t::boolean);
03949                     const json j_const_nonobject(j_nonobject);
03950                     CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
03951                     CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
03952                     CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
03953                     CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
03954                     CHECK_THROWS_WITH(j_nonobject["foo"], "cannot use operator[] with boolean");
03955                     CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")],
03956                                       "cannot use operator[] with boolean");
03957                     CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with boolean");
03958                     CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")],
03959                                       "cannot use operator[] with boolean");
03960                 }
03961 
03962                 SECTION("string")
03963                 {
03964                     json j_nonobject(json::value_t::string);
03965                     const json j_const_nonobject(j_nonobject);
03966                     CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
03967                     CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
03968                     CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
03969                     CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
03970                     CHECK_THROWS_WITH(j_nonobject["foo"], "cannot use operator[] with string");
03971                     CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")],
03972                                       "cannot use operator[] with string");
03973                     CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with string");
03974                     CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")],
03975                                       "cannot use operator[] with string");
03976                 }
03977 
03978                 SECTION("array")
03979                 {
03980                     json j_nonobject(json::value_t::array);
03981                     const json j_const_nonobject(j_nonobject);
03982                     CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
03983                     CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
03984                     CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
03985                     CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
03986                     CHECK_THROWS_WITH(j_nonobject["foo"], "cannot use operator[] with array");
03987                     CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")], "cannot use operator[] with array");
03988                     CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with array");
03989                     CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")],
03990                                       "cannot use operator[] with array");
03991                 }
03992 
03993                 SECTION("number (integer)")
03994                 {
03995                     json j_nonobject(json::value_t::number_integer);
03996                     const json j_const_nonobject(j_nonobject);
03997                     CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
03998                     CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
03999                     CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
04000                     CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
04001                     CHECK_THROWS_WITH(j_nonobject["foo"], "cannot use operator[] with number");
04002                     CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")],
04003                                       "cannot use operator[] with number");
04004                     CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with number");
04005                     CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")],
04006                                       "cannot use operator[] with number");
04007                 }
04008 
04009                 SECTION("number (unsigned)")
04010                 {
04011                     json j_nonobject(json::value_t::number_unsigned);
04012                     const json j_const_nonobject(j_nonobject);
04013                     CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
04014                     CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
04015                     CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
04016                     CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
04017                     CHECK_THROWS_WITH(j_nonobject["foo"], "cannot use operator[] with number");
04018                     CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")],
04019                                       "cannot use operator[] with number");
04020                     CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with number");
04021                     CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")],
04022                                       "cannot use operator[] with number");
04023                 }
04024 
04025                 SECTION("number (floating-point)")
04026                 {
04027                     json j_nonobject(json::value_t::number_float);
04028                     const json j_const_nonobject(j_nonobject);
04029                     CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error);
04030                     CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error);
04031                     CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error);
04032                     CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error);
04033                     CHECK_THROWS_WITH(j_nonobject["foo"], "cannot use operator[] with number");
04034                     CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")],
04035                                       "cannot use operator[] with number");
04036                     CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with number");
04037                     CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")],
04038                                       "cannot use operator[] with number");
04039                 }
04040             }
04041         }
04042 
04043         SECTION("remove specified element")
04044         {
04045             SECTION("remove element by key")
04046             {
04047                 CHECK(j.find("integer") != j.end());
04048                 CHECK(j.erase("integer") == 1);
04049                 CHECK(j.find("integer") == j.end());
04050                 CHECK(j.erase("integer") == 0);
04051 
04052                 CHECK(j.find("unsigned") != j.end());
04053                 CHECK(j.erase("unsigned") == 1);
04054                 CHECK(j.find("unsigned") == j.end());
04055                 CHECK(j.erase("unsigned") == 0);
04056 
04057                 CHECK(j.find("boolean") != j.end());
04058                 CHECK(j.erase("boolean") == 1);
04059                 CHECK(j.find("boolean") == j.end());
04060                 CHECK(j.erase("boolean") == 0);
04061 
04062                 CHECK(j.find("null") != j.end());
04063                 CHECK(j.erase("null") == 1);
04064                 CHECK(j.find("null") == j.end());
04065                 CHECK(j.erase("null") == 0);
04066 
04067                 CHECK(j.find("string") != j.end());
04068                 CHECK(j.erase("string") == 1);
04069                 CHECK(j.find("string") == j.end());
04070                 CHECK(j.erase("string") == 0);
04071 
04072                 CHECK(j.find("floating") != j.end());
04073                 CHECK(j.erase("floating") == 1);
04074                 CHECK(j.find("floating") == j.end());
04075                 CHECK(j.erase("floating") == 0);
04076 
04077                 CHECK(j.find("object") != j.end());
04078                 CHECK(j.erase("object") == 1);
04079                 CHECK(j.find("object") == j.end());
04080                 CHECK(j.erase("object") == 0);
04081 
04082                 CHECK(j.find("array") != j.end());
04083                 CHECK(j.erase("array") == 1);
04084                 CHECK(j.find("array") == j.end());
04085                 CHECK(j.erase("array") == 0);
04086             }
04087 
04088             SECTION("remove element by iterator")
04089             {
04090                 SECTION("erase(begin())")
04091                 {
04092                     {
04093                         json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
04094                         json::iterator it2 = jobject.erase(jobject.begin());
04095                         CHECK(jobject == json({{"b", 1}, {"c", 17u}}));
04096                         CHECK(*it2 == json(1));
04097                     }
04098                     {
04099                         json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
04100                         json::const_iterator it2 = jobject.erase(jobject.cbegin());
04101                         CHECK(jobject == json({{"b", 1}, {"c", 17u}}));
04102                         CHECK(*it2 == json(1));
04103                     }
04104                 }
04105 
04106                 SECTION("erase(begin(), end())")
04107                 {
04108                     {
04109                         json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
04110                         json::iterator it2 = jobject.erase(jobject.begin(), jobject.end());
04111                         CHECK(jobject == json::object());
04112                         CHECK(it2 == jobject.end());
04113                     }
04114                     {
04115                         json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
04116                         json::const_iterator it2 = jobject.erase(jobject.cbegin(), jobject.cend());
04117                         CHECK(jobject == json::object());
04118                         CHECK(it2 == jobject.cend());
04119                     }
04120                 }
04121 
04122                 SECTION("erase(begin(), begin())")
04123                 {
04124                     {
04125                         json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
04126                         json::iterator it2 = jobject.erase(jobject.begin(), jobject.begin());
04127                         CHECK(jobject == json({{"a", "a"}, {"b", 1}, {"c", 17u}}));
04128                         CHECK(*it2 == json("a"));
04129                     }
04130                     {
04131                         json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
04132                         json::const_iterator it2 = jobject.erase(jobject.cbegin(), jobject.cbegin());
04133                         CHECK(jobject == json({{"a", "a"}, {"b", 1}, {"c", 17u}}));
04134                         CHECK(*it2 == json("a"));
04135                     }
04136                 }
04137 
04138                 SECTION("erase at offset")
04139                 {
04140                     {
04141                         json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
04142                         json::iterator it = jobject.find("b");
04143                         json::iterator it2 = jobject.erase(it);
04144                         CHECK(jobject == json({{"a", "a"}, {"c", 17u}}));
04145                         CHECK(*it2 == json(17));
04146                     }
04147                     {
04148                         json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
04149                         json::const_iterator it = jobject.find("b");
04150                         json::const_iterator it2 = jobject.erase(it);
04151                         CHECK(jobject == json({{"a", "a"}, {"c", 17u}}));
04152                         CHECK(*it2 == json(17));
04153                     }
04154                 }
04155 
04156                 SECTION("erase subrange")
04157                 {
04158                     {
04159                         json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
04160                         json::iterator it2 = jobject.erase(jobject.find("b"), jobject.find("e"));
04161                         CHECK(jobject == json({{"a", "a"}, {"e", true}}));
04162                         CHECK(*it2 == json(true));
04163                     }
04164                     {
04165                         json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
04166                         json::const_iterator it2 = jobject.erase(jobject.find("b"), jobject.find("e"));
04167                         CHECK(jobject == json({{"a", "a"}, {"e", true}}));
04168                         CHECK(*it2 == json(true));
04169                     }
04170                 }
04171 
04172                 SECTION("different objects")
04173                 {
04174                     {
04175                         json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
04176                         json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}};
04177                         CHECK_THROWS_AS(jobject.erase(jobject2.begin()), std::domain_error);
04178                         CHECK_THROWS_AS(jobject.erase(jobject.begin(), jobject2.end()), std::domain_error);
04179                         CHECK_THROWS_AS(jobject.erase(jobject2.begin(), jobject.end()), std::domain_error);
04180                         CHECK_THROWS_AS(jobject.erase(jobject2.begin(), jobject2.end()), std::domain_error);
04181                         CHECK_THROWS_WITH(jobject.erase(jobject2.begin()), "iterator does not fit current value");
04182                         CHECK_THROWS_WITH(jobject.erase(jobject.begin(), jobject2.end()),
04183                                           "iterators do not fit current value");
04184                         CHECK_THROWS_WITH(jobject.erase(jobject2.begin(), jobject.end()),
04185                                           "iterators do not fit current value");
04186                         CHECK_THROWS_WITH(jobject.erase(jobject2.begin(), jobject2.end()),
04187                                           "iterators do not fit current value");
04188                     }
04189                     {
04190                         json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
04191                         json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}};
04192                         CHECK_THROWS_AS(jobject.erase(jobject2.cbegin()), std::domain_error);
04193                         CHECK_THROWS_AS(jobject.erase(jobject.cbegin(), jobject2.cend()), std::domain_error);
04194                         CHECK_THROWS_AS(jobject.erase(jobject2.cbegin(), jobject.cend()), std::domain_error);
04195                         CHECK_THROWS_AS(jobject.erase(jobject2.cbegin(), jobject2.cend()), std::domain_error);
04196                         CHECK_THROWS_WITH(jobject.erase(jobject2.cbegin()), "iterator does not fit current value");
04197                         CHECK_THROWS_WITH(jobject.erase(jobject.cbegin(), jobject2.cend()),
04198                                           "iterators do not fit current value");
04199                         CHECK_THROWS_WITH(jobject.erase(jobject2.cbegin(), jobject.cend()),
04200                                           "iterators do not fit current value");
04201                         CHECK_THROWS_WITH(jobject.erase(jobject2.cbegin(), jobject2.cend()),
04202                                           "iterators do not fit current value");
04203                     }
04204                 }
04205             }
04206 
04207             SECTION("remove element by key in non-object type")
04208             {
04209                 SECTION("null")
04210                 {
04211                     json j_nonobject(json::value_t::null);
04212                     CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error);
04213                     CHECK_THROWS_WITH(j_nonobject.erase("foo"), "cannot use erase() with null");
04214                 }
04215 
04216                 SECTION("boolean")
04217                 {
04218                     json j_nonobject(json::value_t::boolean);
04219                     CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error);
04220                     CHECK_THROWS_WITH(j_nonobject.erase("foo"), "cannot use erase() with boolean");
04221                 }
04222 
04223                 SECTION("string")
04224                 {
04225                     json j_nonobject(json::value_t::string);
04226                     CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error);
04227                     CHECK_THROWS_WITH(j_nonobject.erase("foo"), "cannot use erase() with string");
04228                 }
04229 
04230                 SECTION("array")
04231                 {
04232                     json j_nonobject(json::value_t::array);
04233                     CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error);
04234                     CHECK_THROWS_WITH(j_nonobject.erase("foo"), "cannot use erase() with array");
04235                 }
04236 
04237                 SECTION("number (integer)")
04238                 {
04239                     json j_nonobject(json::value_t::number_integer);
04240                     CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error);
04241                     CHECK_THROWS_WITH(j_nonobject.erase("foo"), "cannot use erase() with number");
04242                 }
04243 
04244                 SECTION("number (floating-point)")
04245                 {
04246                     json j_nonobject(json::value_t::number_float);
04247                     CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error);
04248                     CHECK_THROWS_WITH(j_nonobject.erase("foo"), "cannot use erase() with number");
04249                 }
04250             }
04251         }
04252 
04253         SECTION("find an element in an object")
04254         {
04255             SECTION("existing element")
04256             {
04257                 for (auto key :
04258                         {"integer", "unsigned", "floating", "null", "string", "boolean", "object", "array"
04259                         })
04260                 {
04261                     CHECK(j.find(key) != j.end());
04262                     CHECK(*j.find(key) == j.at(key));
04263                     CHECK(j_const.find(key) != j_const.end());
04264                     CHECK(*j_const.find(key) == j_const.at(key));
04265                 }
04266             }
04267 
04268             SECTION("nonexisting element")
04269             {
04270                 CHECK(j.find("foo") == j.end());
04271                 CHECK(j_const.find("foo") == j_const.end());
04272             }
04273 
04274             SECTION("all types")
04275             {
04276                 SECTION("null")
04277                 {
04278                     json j_nonarray(json::value_t::null);
04279                     const json j_nonarray_const(j_nonarray);
04280                     CHECK(j_nonarray.find("foo") == j_nonarray.end());
04281                     CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
04282                 }
04283 
04284                 SECTION("string")
04285                 {
04286                     json j_nonarray(json::value_t::string);
04287                     const json j_nonarray_const(j_nonarray);
04288                     CHECK(j_nonarray.find("foo") == j_nonarray.end());
04289                     CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
04290                 }
04291 
04292                 SECTION("object")
04293                 {
04294                     json j_nonarray(json::value_t::object);
04295                     const json j_nonarray_const(j_nonarray);
04296                     CHECK(j_nonarray.find("foo") == j_nonarray.end());
04297                     CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
04298                 }
04299 
04300                 SECTION("array")
04301                 {
04302                     json j_nonarray(json::value_t::array);
04303                     const json j_nonarray_const(j_nonarray);
04304                     CHECK(j_nonarray.find("foo") == j_nonarray.end());
04305                     CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
04306                 }
04307 
04308                 SECTION("boolean")
04309                 {
04310                     json j_nonarray(json::value_t::boolean);
04311                     const json j_nonarray_const(j_nonarray);
04312                     CHECK(j_nonarray.find("foo") == j_nonarray.end());
04313                     CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
04314                 }
04315 
04316                 SECTION("number (integer)")
04317                 {
04318                     json j_nonarray(json::value_t::number_integer);
04319                     const json j_nonarray_const(j_nonarray);
04320                     CHECK(j_nonarray.find("foo") == j_nonarray.end());
04321                     CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
04322                 }
04323 
04324                 SECTION("number (unsigned)")
04325                 {
04326                     json j_nonarray(json::value_t::number_unsigned);
04327                     const json j_nonarray_const(j_nonarray);
04328                     CHECK(j_nonarray.find("foo") == j_nonarray.end());
04329                     CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
04330                 }
04331 
04332                 SECTION("number (floating-point)")
04333                 {
04334                     json j_nonarray(json::value_t::number_float);
04335                     const json j_nonarray_const(j_nonarray);
04336                     CHECK(j_nonarray.find("foo") == j_nonarray.end());
04337                     CHECK(j_nonarray_const.find("foo") == j_nonarray_const.end());
04338                 }
04339             }
04340         }
04341 
04342         SECTION("count keys in an object")
04343         {
04344             SECTION("existing element")
04345             {
04346                 for (auto key :
04347                         {"integer", "unsigned", "floating", "null", "string", "boolean", "object", "array"
04348                         })
04349                 {
04350                     CHECK(j.count(key) == 1);
04351                     CHECK(j_const.count(key) == 1);
04352                 }
04353             }
04354 
04355             SECTION("nonexisting element")
04356             {
04357                 CHECK(j.count("foo") == 0);
04358                 CHECK(j_const.count("foo") == 0);
04359             }
04360 
04361             SECTION("all types")
04362             {
04363                 SECTION("null")
04364                 {
04365                     json j_nonobject(json::value_t::null);
04366                     const json j_nonobject_const(j_nonobject);
04367                     CHECK(j_nonobject.count("foo") == 0);
04368                     CHECK(j_nonobject_const.count("foo") == 0);
04369                 }
04370 
04371                 SECTION("string")
04372                 {
04373                     json j_nonobject(json::value_t::string);
04374                     const json j_nonobject_const(j_nonobject);
04375                     CHECK(j_nonobject.count("foo") == 0);
04376                     CHECK(j_nonobject_const.count("foo") == 0);
04377                 }
04378 
04379                 SECTION("object")
04380                 {
04381                     json j_nonobject(json::value_t::object);
04382                     const json j_nonobject_const(j_nonobject);
04383                     CHECK(j_nonobject.count("foo") == 0);
04384                     CHECK(j_nonobject_const.count("foo") == 0);
04385                 }
04386 
04387                 SECTION("array")
04388                 {
04389                     json j_nonobject(json::value_t::array);
04390                     const json j_nonobject_const(j_nonobject);
04391                     CHECK(j_nonobject.count("foo") == 0);
04392                     CHECK(j_nonobject_const.count("foo") == 0);
04393                 }
04394 
04395                 SECTION("boolean")
04396                 {
04397                     json j_nonobject(json::value_t::boolean);
04398                     const json j_nonobject_const(j_nonobject);
04399                     CHECK(j_nonobject.count("foo") == 0);
04400                     CHECK(j_nonobject_const.count("foo") == 0);
04401                 }
04402 
04403                 SECTION("number (integer)")
04404                 {
04405                     json j_nonobject(json::value_t::number_integer);
04406                     const json j_nonobject_const(j_nonobject);
04407                     CHECK(j_nonobject.count("foo") == 0);
04408                     CHECK(j_nonobject_const.count("foo") == 0);
04409                 }
04410 
04411                 SECTION("number (unsigned)")
04412                 {
04413                     json j_nonobject(json::value_t::number_unsigned);
04414                     const json j_nonobject_const(j_nonobject);
04415                     CHECK(j_nonobject.count("foo") == 0);
04416                     CHECK(j_nonobject_const.count("foo") == 0);
04417                 }
04418 
04419                 SECTION("number (floating-point)")
04420                 {
04421                     json j_nonobject(json::value_t::number_float);
04422                     const json j_nonobject_const(j_nonobject);
04423                     CHECK(j_nonobject.count("foo") == 0);
04424                     CHECK(j_nonobject_const.count("foo") == 0);
04425                 }
04426             }
04427         }
04428     }
04429 
04430     SECTION("other values")
04431     {
04432         SECTION("front and back")
04433         {
04434             SECTION("null")
04435             {
04436                 {
04437                     json j;
04438                     CHECK_THROWS_AS(j.front(), std::out_of_range);
04439                     CHECK_THROWS_AS(j.back(), std::out_of_range);
04440                     CHECK_THROWS_WITH(j.front(), "cannot get value");
04441                     CHECK_THROWS_WITH(j.back(), "cannot get value");
04442                 }
04443                 {
04444                     const json j{};
04445                     CHECK_THROWS_AS(j.front(), std::out_of_range);
04446                     CHECK_THROWS_AS(j.back(), std::out_of_range);
04447                     CHECK_THROWS_WITH(j.front(), "cannot get value");
04448                     CHECK_THROWS_WITH(j.back(), "cannot get value");
04449                 }
04450             }
04451 
04452             SECTION("string")
04453             {
04454                 {
04455                     json j = "foo";
04456                     CHECK(j.front() == j);
04457                     CHECK(j.back() == j);
04458                 }
04459                 {
04460                     const json j = "bar";
04461                     CHECK(j.front() == j);
04462                     CHECK(j.back() == j);
04463                 }
04464             }
04465 
04466             SECTION("number (boolean)")
04467             {
04468                 {
04469                     json j = false;
04470                     CHECK(j.front() == j);
04471                     CHECK(j.back() == j);
04472                 }
04473                 {
04474                     const json j = true;
04475                     CHECK(j.front() == j);
04476                     CHECK(j.back() == j);
04477                 }
04478             }
04479 
04480             SECTION("number (integer)")
04481             {
04482                 {
04483                     json j = 17;
04484                     CHECK(j.front() == j);
04485                     CHECK(j.back() == j);
04486                 }
04487                 {
04488                     const json j = 17;
04489                     CHECK(j.front() == j);
04490                     CHECK(j.back() == j);
04491                 }
04492             }
04493 
04494             SECTION("number (unsigned)")
04495             {
04496                 {
04497                     json j = 17u;
04498                     CHECK(j.front() == j);
04499                     CHECK(j.back() == j);
04500                 }
04501                 {
04502                     const json j = 17u;
04503                     CHECK(j.front() == j);
04504                     CHECK(j.back() == j);
04505                 }
04506             }
04507 
04508             SECTION("number (floating point)")
04509             {
04510                 {
04511                     json j = 23.42;
04512                     CHECK(j.front() == j);
04513                     CHECK(j.back() == j);
04514                 }
04515                 {
04516                     const json j = 23.42;
04517                     CHECK(j.front() == j);
04518                     CHECK(j.back() == j);
04519                 }
04520             }
04521         }
04522 
04523         SECTION("erase with one valid iterator")
04524         {
04525             SECTION("null")
04526             {
04527                 {
04528                     json j;
04529                     CHECK_THROWS_AS(j.erase(j.begin()), std::domain_error);
04530                     CHECK_THROWS_WITH(j.erase(j.begin()), "cannot use erase() with null");
04531                 }
04532                 {
04533                     json j;
04534                     CHECK_THROWS_AS(j.erase(j.cbegin()), std::domain_error);
04535                     CHECK_THROWS_WITH(j.erase(j.begin()), "cannot use erase() with null");
04536                 }
04537             }
04538 
04539             SECTION("string")
04540             {
04541                 {
04542                     json j = "foo";
04543                     json::iterator it = j.erase(j.begin());
04544                     CHECK(j.type() == json::value_t::null);
04545                     CHECK(it == j.end());
04546                 }
04547                 {
04548                     json j = "bar";
04549                     json::const_iterator it = j.erase(j.cbegin());
04550                     CHECK(j.type() == json::value_t::null);
04551                     CHECK(it == j.end());
04552                 }
04553             }
04554 
04555             SECTION("number (boolean)")
04556             {
04557                 {
04558                     json j = false;
04559                     json::iterator it = j.erase(j.begin());
04560                     CHECK(j.type() == json::value_t::null);
04561                     CHECK(it == j.end());
04562                 }
04563                 {
04564                     json j = true;
04565                     json::const_iterator it = j.erase(j.cbegin());
04566                     CHECK(j.type() == json::value_t::null);
04567                     CHECK(it == j.end());
04568                 }
04569             }
04570 
04571             SECTION("number (integer)")
04572             {
04573                 {
04574                     json j = 17;
04575                     json::iterator it = j.erase(j.begin());
04576                     CHECK(j.type() == json::value_t::null);
04577                     CHECK(it == j.end());
04578                 }
04579                 {
04580                     json j = 17;
04581                     json::const_iterator it = j.erase(j.cbegin());
04582                     CHECK(j.type() == json::value_t::null);
04583                     CHECK(it == j.end());
04584                 }
04585             }
04586 
04587             SECTION("number (unsigned)")
04588             {
04589                 {
04590                     json j = 17u;
04591                     json::iterator it = j.erase(j.begin());
04592                     CHECK(j.type() == json::value_t::null);
04593                     CHECK(it == j.end());
04594                 }
04595                 {
04596                     json j = 17u;
04597                     json::const_iterator it = j.erase(j.cbegin());
04598                     CHECK(j.type() == json::value_t::null);
04599                     CHECK(it == j.end());
04600                 }
04601             }
04602 
04603             SECTION("number (floating point)")
04604             {
04605                 {
04606                     json j = 23.42;
04607                     json::iterator it = j.erase(j.begin());
04608                     CHECK(j.type() == json::value_t::null);
04609                     CHECK(it == j.end());
04610                 }
04611                 {
04612                     json j = 23.42;
04613                     json::const_iterator it = j.erase(j.cbegin());
04614                     CHECK(j.type() == json::value_t::null);
04615                     CHECK(it == j.end());
04616                 }
04617             }
04618         }
04619 
04620         SECTION("erase with one invalid iterator")
04621         {
04622             SECTION("string")
04623             {
04624                 {
04625                     json j = "foo";
04626                     CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range);
04627                     CHECK_THROWS_WITH(j.erase(j.end()), "iterator out of range");
04628                 }
04629                 {
04630                     json j = "bar";
04631                     CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range);
04632                     CHECK_THROWS_WITH(j.erase(j.cend()), "iterator out of range");
04633                 }
04634             }
04635 
04636             SECTION("number (boolean)")
04637             {
04638                 {
04639                     json j = false;
04640                     CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range);
04641                     CHECK_THROWS_WITH(j.erase(j.end()), "iterator out of range");
04642                 }
04643                 {
04644                     json j = true;
04645                     CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range);
04646                     CHECK_THROWS_WITH(j.erase(j.cend()), "iterator out of range");
04647                 }
04648             }
04649 
04650             SECTION("number (integer)")
04651             {
04652                 {
04653                     json j = 17;
04654                     CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range);
04655                     CHECK_THROWS_WITH(j.erase(j.end()), "iterator out of range");
04656                 }
04657                 {
04658                     json j = 17;
04659                     CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range);
04660                     CHECK_THROWS_WITH(j.erase(j.cend()), "iterator out of range");
04661                 }
04662             }
04663 
04664             SECTION("number (unsigned)")
04665             {
04666                 {
04667                     json j = 17u;
04668                     CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range);
04669                     CHECK_THROWS_WITH(j.erase(j.end()), "iterator out of range");
04670                 }
04671                 {
04672                     json j = 17u;
04673                     CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range);
04674                     CHECK_THROWS_WITH(j.erase(j.cend()), "iterator out of range");
04675                 }
04676             }
04677 
04678             SECTION("number (floating point)")
04679             {
04680                 {
04681                     json j = 23.42;
04682                     CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range);
04683                     CHECK_THROWS_WITH(j.erase(j.end()), "iterator out of range");
04684                 }
04685                 {
04686                     json j = 23.42;
04687                     CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range);
04688                     CHECK_THROWS_WITH(j.erase(j.cend()), "iterator out of range");
04689                 }
04690             }
04691         }
04692 
04693         SECTION("erase with two valid iterators")
04694         {
04695             SECTION("null")
04696             {
04697                 {
04698                     json j;
04699                     CHECK_THROWS_AS(j.erase(j.begin(), j.end()), std::domain_error);
04700                     CHECK_THROWS_WITH(j.erase(j.begin(), j.end()), "cannot use erase() with null");
04701                 }
04702                 {
04703                     json j;
04704                     CHECK_THROWS_AS(j.erase(j.cbegin(), j.cend()), std::domain_error);
04705                     CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cend()), "cannot use erase() with null");
04706                 }
04707             }
04708 
04709             SECTION("string")
04710             {
04711                 {
04712                     json j = "foo";
04713                     json::iterator it = j.erase(j.begin(), j.end());
04714                     CHECK(j.type() == json::value_t::null);
04715                     CHECK(it == j.end());
04716                 }
04717                 {
04718                     json j = "bar";
04719                     json::const_iterator it = j.erase(j.cbegin(), j.cend());
04720                     CHECK(j.type() == json::value_t::null);
04721                     CHECK(it == j.end());
04722                 }
04723             }
04724 
04725             SECTION("number (boolean)")
04726             {
04727                 {
04728                     json j = false;
04729                     json::iterator it = j.erase(j.begin(), j.end());
04730                     CHECK(j.type() == json::value_t::null);
04731                     CHECK(it == j.end());
04732                 }
04733                 {
04734                     json j = true;
04735                     json::const_iterator it = j.erase(j.cbegin(), j.cend());
04736                     CHECK(j.type() == json::value_t::null);
04737                     CHECK(it == j.end());
04738                 }
04739             }
04740 
04741             SECTION("number (integer)")
04742             {
04743                 {
04744                     json j = 17;
04745                     json::iterator it = j.erase(j.begin(), j.end());
04746                     CHECK(j.type() == json::value_t::null);
04747                     CHECK(it == j.end());
04748                 }
04749                 {
04750                     json j = 17;
04751                     json::const_iterator it = j.erase(j.cbegin(), j.cend());
04752                     CHECK(j.type() == json::value_t::null);
04753                     CHECK(it == j.end());
04754                 }
04755             }
04756 
04757             SECTION("number (unsigned)")
04758             {
04759                 {
04760                     json j = 17u;
04761                     json::iterator it = j.erase(j.begin(), j.end());
04762                     CHECK(j.type() == json::value_t::null);
04763                     CHECK(it == j.end());
04764                 }
04765                 {
04766                     json j = 17u;
04767                     json::const_iterator it = j.erase(j.cbegin(), j.cend());
04768                     CHECK(j.type() == json::value_t::null);
04769                     CHECK(it == j.end());
04770                 }
04771             }
04772 
04773             SECTION("number (floating point)")
04774             {
04775                 {
04776                     json j = 23.42;
04777                     json::iterator it = j.erase(j.begin(), j.end());
04778                     CHECK(j.type() == json::value_t::null);
04779                     CHECK(it == j.end());
04780                 }
04781                 {
04782                     json j = 23.42;
04783                     json::const_iterator it = j.erase(j.cbegin(), j.cend());
04784                     CHECK(j.type() == json::value_t::null);
04785                     CHECK(it == j.end());
04786                 }
04787             }
04788         }
04789 
04790         SECTION("erase with two invalid iterators")
04791         {
04792             SECTION("string")
04793             {
04794                 {
04795                     json j = "foo";
04796                     CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range);
04797                     CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range);
04798                     CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "iterators out of range");
04799                     CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "iterators out of range");
04800                 }
04801                 {
04802                     json j = "bar";
04803                     CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range);
04804                     CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range);
04805                     CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "iterators out of range");
04806                     CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "iterators out of range");
04807                 }
04808             }
04809 
04810             SECTION("number (boolean)")
04811             {
04812                 {
04813                     json j = false;
04814                     CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range);
04815                     CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range);
04816                     CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "iterators out of range");
04817                     CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "iterators out of range");
04818                 }
04819                 {
04820                     json j = true;
04821                     CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range);
04822                     CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range);
04823                     CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "iterators out of range");
04824                     CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "iterators out of range");
04825                 }
04826             }
04827 
04828             SECTION("number (integer)")
04829             {
04830                 {
04831                     json j = 17;
04832                     CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range);
04833                     CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range);
04834                     CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "iterators out of range");
04835                     CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "iterators out of range");
04836                 }
04837                 {
04838                     json j = 17;
04839                     CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range);
04840                     CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range);
04841                     CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "iterators out of range");
04842                     CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "iterators out of range");
04843                 }
04844             }
04845 
04846             SECTION("number (unsigned)")
04847             {
04848                 {
04849                     json j = 17u;
04850                     CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range);
04851                     CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range);
04852                     CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "iterators out of range");
04853                     CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "iterators out of range");
04854                 }
04855                 {
04856                     json j = 17u;
04857                     CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range);
04858                     CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range);
04859                     CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "iterators out of range");
04860                     CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "iterators out of range");
04861                 }
04862             }
04863 
04864             SECTION("number (floating point)")
04865             {
04866                 {
04867                     json j = 23.42;
04868                     CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range);
04869                     CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range);
04870                     CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "iterators out of range");
04871                     CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "iterators out of range");
04872                 }
04873                 {
04874                     json j = 23.42;
04875                     CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range);
04876                     CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range);
04877                     CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "iterators out of range");
04878                     CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "iterators out of range");
04879                 }
04880             }
04881         }
04882     }
04883 }
04884 
04885 TEST_CASE("iterators")
04886 {
04887     SECTION("basic behavior")
04888     {
04889         SECTION("uninitialized")
04890         {
04891             json::iterator it;
04892             CHECK(it.m_object == nullptr);
04893 
04894             json::const_iterator cit;
04895             CHECK(cit.m_object == nullptr);
04896         }
04897 
04898         SECTION("boolean")
04899         {
04900             json j = true;
04901             json j_const(j);
04902 
04903             SECTION("json + begin/end")
04904             {
04905                 json::iterator it = j.begin();
04906                 CHECK(it != j.end());
04907                 CHECK(*it == j);
04908 
04909                 it++;
04910                 CHECK(it != j.begin());
04911                 CHECK(it == j.end());
04912 
04913                 it--;
04914                 CHECK(it == j.begin());
04915                 CHECK(it != j.end());
04916                 CHECK(*it == j);
04917 
04918                 ++it;
04919                 CHECK(it != j.begin());
04920                 CHECK(it == j.end());
04921 
04922                 --it;
04923                 CHECK(it == j.begin());
04924                 CHECK(it != j.end());
04925                 CHECK(*it == j);
04926             }
04927 
04928             SECTION("const json + begin/end")
04929             {
04930                 json::const_iterator it = j_const.begin();
04931                 CHECK(it != j_const.end());
04932                 CHECK(*it == j_const);
04933 
04934                 it++;
04935                 CHECK(it != j_const.begin());
04936                 CHECK(it == j_const.end());
04937 
04938                 it--;
04939                 CHECK(it == j_const.begin());
04940                 CHECK(it != j_const.end());
04941                 CHECK(*it == j_const);
04942 
04943                 ++it;
04944                 CHECK(it != j_const.begin());
04945                 CHECK(it == j_const.end());
04946 
04947                 --it;
04948                 CHECK(it == j_const.begin());
04949                 CHECK(it != j_const.end());
04950                 CHECK(*it == j_const);
04951             }
04952 
04953             SECTION("json + cbegin/cend")
04954             {
04955                 json::const_iterator it = j.cbegin();
04956                 CHECK(it != j.cend());
04957                 CHECK(*it == j);
04958 
04959                 it++;
04960                 CHECK(it != j.cbegin());
04961                 CHECK(it == j.cend());
04962 
04963                 it--;
04964                 CHECK(it == j.cbegin());
04965                 CHECK(it != j.cend());
04966                 CHECK(*it == j);
04967 
04968                 ++it;
04969                 CHECK(it != j.cbegin());
04970                 CHECK(it == j.cend());
04971 
04972                 --it;
04973                 CHECK(it == j.cbegin());
04974                 CHECK(it != j.cend());
04975                 CHECK(*it == j);
04976             }
04977 
04978             SECTION("const json + cbegin/cend")
04979             {
04980                 json::const_iterator it = j_const.cbegin();
04981                 CHECK(it != j_const.cend());
04982                 CHECK(*it == j_const);
04983 
04984                 it++;
04985                 CHECK(it != j_const.cbegin());
04986                 CHECK(it == j_const.cend());
04987 
04988                 it--;
04989                 CHECK(it == j_const.cbegin());
04990                 CHECK(it != j_const.cend());
04991                 CHECK(*it == j_const);
04992 
04993                 ++it;
04994                 CHECK(it != j_const.cbegin());
04995                 CHECK(it == j_const.cend());
04996 
04997                 --it;
04998                 CHECK(it == j_const.cbegin());
04999                 CHECK(it != j_const.cend());
05000                 CHECK(*it == j_const);
05001             }
05002 
05003             SECTION("json + rbegin/rend")
05004             {
05005                 json::reverse_iterator it = j.rbegin();
05006                 CHECK(it != j.rend());
05007                 CHECK(*it == j);
05008 
05009                 it++;
05010                 CHECK(it != j.rbegin());
05011                 CHECK(it == j.rend());
05012 
05013                 it--;
05014                 CHECK(it == j.rbegin());
05015                 CHECK(it != j.rend());
05016                 CHECK(*it == j);
05017 
05018                 ++it;
05019                 CHECK(it != j.rbegin());
05020                 CHECK(it == j.rend());
05021 
05022                 --it;
05023                 CHECK(it == j.rbegin());
05024                 CHECK(it != j.rend());
05025                 CHECK(*it == j);
05026             }
05027 
05028             SECTION("json + crbegin/crend")
05029             {
05030                 json::const_reverse_iterator it = j.crbegin();
05031                 CHECK(it != j.crend());
05032                 CHECK(*it == j);
05033 
05034                 it++;
05035                 CHECK(it != j.crbegin());
05036                 CHECK(it == j.crend());
05037 
05038                 it--;
05039                 CHECK(it == j.crbegin());
05040                 CHECK(it != j.crend());
05041                 CHECK(*it == j);
05042 
05043                 ++it;
05044                 CHECK(it != j.crbegin());
05045                 CHECK(it == j.crend());
05046 
05047                 --it;
05048                 CHECK(it == j.crbegin());
05049                 CHECK(it != j.crend());
05050                 CHECK(*it == j);
05051             }
05052 
05053             SECTION("const json + crbegin/crend")
05054             {
05055                 json::const_reverse_iterator it = j_const.crbegin();
05056                 CHECK(it != j_const.crend());
05057                 CHECK(*it == j_const);
05058 
05059                 it++;
05060                 CHECK(it != j_const.crbegin());
05061                 CHECK(it == j_const.crend());
05062 
05063                 it--;
05064                 CHECK(it == j_const.crbegin());
05065                 CHECK(it != j_const.crend());
05066                 CHECK(*it == j_const);
05067 
05068                 ++it;
05069                 CHECK(it != j_const.crbegin());
05070                 CHECK(it == j_const.crend());
05071 
05072                 --it;
05073                 CHECK(it == j_const.crbegin());
05074                 CHECK(it != j_const.crend());
05075                 CHECK(*it == j_const);
05076             }
05077 
05078             SECTION("key/value")
05079             {
05080                 auto it = j.begin();
05081                 auto cit = j_const.cbegin();
05082                 CHECK_THROWS_AS(it.key(), std::domain_error);
05083                 CHECK_THROWS_WITH(it.key(), "cannot use key() for non-object iterators");
05084                 CHECK(it.value() == json(true));
05085                 CHECK_THROWS_AS(cit.key(), std::domain_error);
05086                 CHECK_THROWS_WITH(cit.key(), "cannot use key() for non-object iterators");
05087                 CHECK(cit.value() == json(true));
05088 
05089                 auto rit = j.rend();
05090                 auto crit = j.crend();
05091                 CHECK_THROWS_AS(rit.key(), std::domain_error);
05092                 CHECK_THROWS_AS(rit.value(), std::out_of_range);
05093                 CHECK_THROWS_AS(crit.key(), std::domain_error);
05094                 CHECK_THROWS_AS(crit.value(), std::out_of_range);
05095                 CHECK_THROWS_WITH(rit.key(), "cannot use key() for non-object iterators");
05096                 CHECK_THROWS_WITH(rit.value(), "cannot get value");
05097                 CHECK_THROWS_WITH(crit.key(), "cannot use key() for non-object iterators");
05098                 CHECK_THROWS_WITH(crit.value(), "cannot get value");
05099             }
05100         }
05101 
05102         SECTION("string")
05103         {
05104             json j = "hello world";
05105             json j_const(j);
05106 
05107             SECTION("json + begin/end")
05108             {
05109                 json::iterator it = j.begin();
05110                 CHECK(it != j.end());
05111                 CHECK(*it == j);
05112 
05113                 it++;
05114                 CHECK(it != j.begin());
05115                 CHECK(it == j.end());
05116 
05117                 it--;
05118                 CHECK(it == j.begin());
05119                 CHECK(it != j.end());
05120                 CHECK(*it == j);
05121 
05122                 ++it;
05123                 CHECK(it != j.begin());
05124                 CHECK(it == j.end());
05125 
05126                 --it;
05127                 CHECK(it == j.begin());
05128                 CHECK(it != j.end());
05129                 CHECK(*it == j);
05130             }
05131 
05132             SECTION("const json + begin/end")
05133             {
05134                 json::const_iterator it = j_const.begin();
05135                 CHECK(it != j_const.end());
05136                 CHECK(*it == j_const);
05137 
05138                 it++;
05139                 CHECK(it != j_const.begin());
05140                 CHECK(it == j_const.end());
05141 
05142                 it--;
05143                 CHECK(it == j_const.begin());
05144                 CHECK(it != j_const.end());
05145                 CHECK(*it == j_const);
05146 
05147                 ++it;
05148                 CHECK(it != j_const.begin());
05149                 CHECK(it == j_const.end());
05150 
05151                 --it;
05152                 CHECK(it == j_const.begin());
05153                 CHECK(it != j_const.end());
05154                 CHECK(*it == j_const);
05155             }
05156 
05157             SECTION("json + cbegin/cend")
05158             {
05159                 json::const_iterator it = j.cbegin();
05160                 CHECK(it != j.cend());
05161                 CHECK(*it == j);
05162 
05163                 it++;
05164                 CHECK(it != j.cbegin());
05165                 CHECK(it == j.cend());
05166 
05167                 it--;
05168                 CHECK(it == j.cbegin());
05169                 CHECK(it != j.cend());
05170                 CHECK(*it == j);
05171 
05172                 ++it;
05173                 CHECK(it != j.cbegin());
05174                 CHECK(it == j.cend());
05175 
05176                 --it;
05177                 CHECK(it == j.cbegin());
05178                 CHECK(it != j.cend());
05179                 CHECK(*it == j);
05180             }
05181 
05182             SECTION("const json + cbegin/cend")
05183             {
05184                 json::const_iterator it = j_const.cbegin();
05185                 CHECK(it != j_const.cend());
05186                 CHECK(*it == j_const);
05187 
05188                 it++;
05189                 CHECK(it != j_const.cbegin());
05190                 CHECK(it == j_const.cend());
05191 
05192                 it--;
05193                 CHECK(it == j_const.cbegin());
05194                 CHECK(it != j_const.cend());
05195                 CHECK(*it == j_const);
05196 
05197                 ++it;
05198                 CHECK(it != j_const.cbegin());
05199                 CHECK(it == j_const.cend());
05200 
05201                 --it;
05202                 CHECK(it == j_const.cbegin());
05203                 CHECK(it != j_const.cend());
05204                 CHECK(*it == j_const);
05205             }
05206 
05207             SECTION("json + rbegin/rend")
05208             {
05209                 json::reverse_iterator it = j.rbegin();
05210                 CHECK(it != j.rend());
05211                 CHECK(*it == j);
05212 
05213                 it++;
05214                 CHECK(it != j.rbegin());
05215                 CHECK(it == j.rend());
05216 
05217                 it--;
05218                 CHECK(it == j.rbegin());
05219                 CHECK(it != j.rend());
05220                 CHECK(*it == j);
05221 
05222                 ++it;
05223                 CHECK(it != j.rbegin());
05224                 CHECK(it == j.rend());
05225 
05226                 --it;
05227                 CHECK(it == j.rbegin());
05228                 CHECK(it != j.rend());
05229                 CHECK(*it == j);
05230             }
05231 
05232             SECTION("json + crbegin/crend")
05233             {
05234                 json::const_reverse_iterator it = j.crbegin();
05235                 CHECK(it != j.crend());
05236                 CHECK(*it == j);
05237 
05238                 it++;
05239                 CHECK(it != j.crbegin());
05240                 CHECK(it == j.crend());
05241 
05242                 it--;
05243                 CHECK(it == j.crbegin());
05244                 CHECK(it != j.crend());
05245                 CHECK(*it == j);
05246 
05247                 ++it;
05248                 CHECK(it != j.crbegin());
05249                 CHECK(it == j.crend());
05250 
05251                 --it;
05252                 CHECK(it == j.crbegin());
05253                 CHECK(it != j.crend());
05254                 CHECK(*it == j);
05255             }
05256 
05257             SECTION("const json + crbegin/crend")
05258             {
05259                 json::const_reverse_iterator it = j_const.crbegin();
05260                 CHECK(it != j_const.crend());
05261                 CHECK(*it == j_const);
05262 
05263                 it++;
05264                 CHECK(it != j_const.crbegin());
05265                 CHECK(it == j_const.crend());
05266 
05267                 it--;
05268                 CHECK(it == j_const.crbegin());
05269                 CHECK(it != j_const.crend());
05270                 CHECK(*it == j_const);
05271 
05272                 ++it;
05273                 CHECK(it != j_const.crbegin());
05274                 CHECK(it == j_const.crend());
05275 
05276                 --it;
05277                 CHECK(it == j_const.crbegin());
05278                 CHECK(it != j_const.crend());
05279                 CHECK(*it == j_const);
05280             }
05281 
05282             SECTION("key/value")
05283             {
05284                 auto it = j.begin();
05285                 auto cit = j_const.cbegin();
05286                 CHECK_THROWS_AS(it.key(), std::domain_error);
05287                 CHECK_THROWS_WITH(it.key(), "cannot use key() for non-object iterators");
05288                 CHECK(it.value() == json("hello world"));
05289                 CHECK_THROWS_AS(cit.key(), std::domain_error);
05290                 CHECK_THROWS_WITH(cit.key(), "cannot use key() for non-object iterators");
05291                 CHECK(cit.value() == json("hello world"));
05292 
05293                 auto rit = j.rend();
05294                 auto crit = j.crend();
05295                 CHECK_THROWS_AS(rit.key(), std::domain_error);
05296                 CHECK_THROWS_AS(rit.value(), std::out_of_range);
05297                 CHECK_THROWS_AS(crit.key(), std::domain_error);
05298                 CHECK_THROWS_AS(crit.value(), std::out_of_range);
05299                 CHECK_THROWS_WITH(rit.key(), "cannot use key() for non-object iterators");
05300                 CHECK_THROWS_WITH(rit.value(), "cannot get value");
05301                 CHECK_THROWS_WITH(crit.key(), "cannot use key() for non-object iterators");
05302                 CHECK_THROWS_WITH(crit.value(), "cannot get value");
05303             }
05304         }
05305 
05306         SECTION("array")
05307         {
05308             json j = {1, 2, 3};
05309             json j_const(j);
05310 
05311             SECTION("json + begin/end")
05312             {
05313                 json::iterator it_begin = j.begin();
05314                 json::iterator it_end = j.end();
05315 
05316                 auto it = it_begin;
05317                 CHECK(it != it_end);
05318                 CHECK(*it == j[0]);
05319 
05320                 it++;
05321                 CHECK(it != it_begin);
05322                 CHECK(it != it_end);
05323                 CHECK(*it == j[1]);
05324 
05325                 ++it;
05326                 CHECK(it != it_begin);
05327                 CHECK(it != it_end);
05328                 CHECK(*it == j[2]);
05329 
05330                 ++it;
05331                 CHECK(it != it_begin);
05332                 CHECK(it == it_end);
05333             }
05334 
05335             SECTION("const json + begin/end")
05336             {
05337                 json::const_iterator it_begin = j_const.begin();
05338                 json::const_iterator it_end = j_const.end();
05339 
05340                 auto it = it_begin;
05341                 CHECK(it != it_end);
05342                 CHECK(*it == j_const[0]);
05343 
05344                 it++;
05345                 CHECK(it != it_begin);
05346                 CHECK(it != it_end);
05347                 CHECK(*it == j_const[1]);
05348 
05349                 ++it;
05350                 CHECK(it != it_begin);
05351                 CHECK(it != it_end);
05352                 CHECK(*it == j_const[2]);
05353 
05354                 ++it;
05355                 CHECK(it != it_begin);
05356                 CHECK(it == it_end);
05357             }
05358 
05359             SECTION("json + cbegin/cend")
05360             {
05361                 json::const_iterator it_begin = j.cbegin();
05362                 json::const_iterator it_end = j.cend();
05363 
05364                 auto it = it_begin;
05365                 CHECK(it != it_end);
05366                 CHECK(*it == j[0]);
05367 
05368                 it++;
05369                 CHECK(it != it_begin);
05370                 CHECK(it != it_end);
05371                 CHECK(*it == j[1]);
05372 
05373                 ++it;
05374                 CHECK(it != it_begin);
05375                 CHECK(it != it_end);
05376                 CHECK(*it == j[2]);
05377 
05378                 ++it;
05379                 CHECK(it != it_begin);
05380                 CHECK(it == it_end);
05381             }
05382 
05383             SECTION("const json + cbegin/cend")
05384             {
05385                 json::const_iterator it_begin = j_const.cbegin();
05386                 json::const_iterator it_end = j_const.cend();
05387 
05388                 auto it = it_begin;
05389                 CHECK(it != it_end);
05390                 CHECK(*it == j[0]);
05391 
05392                 it++;
05393                 CHECK(it != it_begin);
05394                 CHECK(it != it_end);
05395                 CHECK(*it == j[1]);
05396 
05397                 ++it;
05398                 CHECK(it != it_begin);
05399                 CHECK(it != it_end);
05400                 CHECK(*it == j[2]);
05401 
05402                 ++it;
05403                 CHECK(it != it_begin);
05404                 CHECK(it == it_end);
05405             }
05406 
05407             SECTION("json + rbegin/rend")
05408             {
05409                 json::reverse_iterator it_begin = j.rbegin();
05410                 json::reverse_iterator it_end = j.rend();
05411 
05412                 auto it = it_begin;
05413                 CHECK(it != it_end);
05414                 CHECK(*it == j[2]);
05415 
05416                 it++;
05417                 CHECK(it != it_begin);
05418                 CHECK(it != it_end);
05419                 CHECK(*it == j[1]);
05420 
05421                 ++it;
05422                 CHECK(it != it_begin);
05423                 CHECK(it != it_end);
05424                 CHECK(*it == j[0]);
05425 
05426                 ++it;
05427                 CHECK(it != it_begin);
05428                 CHECK(it == it_end);
05429             }
05430 
05431             SECTION("json + crbegin/crend")
05432             {
05433                 json::const_reverse_iterator it_begin = j.crbegin();
05434                 json::const_reverse_iterator it_end = j.crend();
05435 
05436                 auto it = it_begin;
05437                 CHECK(it != it_end);
05438                 CHECK(*it == j[2]);
05439 
05440                 it++;
05441                 CHECK(it != it_begin);
05442                 CHECK(it != it_end);
05443                 CHECK(*it == j[1]);
05444 
05445                 ++it;
05446                 CHECK(it != it_begin);
05447                 CHECK(it != it_end);
05448                 CHECK(*it == j[0]);
05449 
05450                 ++it;
05451                 CHECK(it != it_begin);
05452                 CHECK(it == it_end);
05453             }
05454 
05455             SECTION("const json + crbegin/crend")
05456             {
05457                 json::const_reverse_iterator it_begin = j_const.crbegin();
05458                 json::const_reverse_iterator it_end = j_const.crend();
05459 
05460                 auto it = it_begin;
05461                 CHECK(it != it_end);
05462                 CHECK(*it == j[2]);
05463 
05464                 it++;
05465                 CHECK(it != it_begin);
05466                 CHECK(it != it_end);
05467                 CHECK(*it == j[1]);
05468 
05469                 ++it;
05470                 CHECK(it != it_begin);
05471                 CHECK(it != it_end);
05472                 CHECK(*it == j[0]);
05473 
05474                 ++it;
05475                 CHECK(it != it_begin);
05476                 CHECK(it == it_end);
05477             }
05478 
05479             SECTION("key/value")
05480             {
05481                 auto it = j.begin();
05482                 auto cit = j_const.cbegin();
05483                 CHECK_THROWS_AS(it.key(), std::domain_error);
05484                 CHECK_THROWS_WITH(it.key(), "cannot use key() for non-object iterators");
05485                 CHECK(it.value() == json(1));
05486                 CHECK_THROWS_AS(cit.key(), std::domain_error);
05487                 CHECK_THROWS_WITH(cit.key(), "cannot use key() for non-object iterators");
05488                 CHECK(cit.value() == json(1));
05489             }
05490         }
05491 
05492         SECTION("object")
05493         {
05494             json j = {{"A", 1}, {"B", 2}, {"C", 3}};
05495             json j_const(j);
05496 
05497             SECTION("json + begin/end")
05498             {
05499                 json::iterator it_begin = j.begin();
05500                 json::iterator it_end = j.end();
05501 
05502                 auto it = it_begin;
05503                 CHECK(it != it_end);
05504                 CHECK(*it == j["A"]);
05505 
05506                 it++;
05507                 CHECK(it != it_begin);
05508                 CHECK(it != it_end);
05509                 CHECK(*it == j["B"]);
05510 
05511                 ++it;
05512                 CHECK(it != it_begin);
05513                 CHECK(it != it_end);
05514                 CHECK(*it == j["C"]);
05515 
05516                 ++it;
05517                 CHECK(it != it_begin);
05518                 CHECK(it == it_end);
05519             }
05520 
05521             SECTION("const json + begin/end")
05522             {
05523                 json::const_iterator it_begin = j_const.begin();
05524                 json::const_iterator it_end = j_const.end();
05525 
05526                 auto it = it_begin;
05527                 CHECK(it != it_end);
05528                 CHECK(*it == j_const["A"]);
05529 
05530                 it++;
05531                 CHECK(it != it_begin);
05532                 CHECK(it != it_end);
05533                 CHECK(*it == j_const["B"]);
05534 
05535                 ++it;
05536                 CHECK(it != it_begin);
05537                 CHECK(it != it_end);
05538                 CHECK(*it == j_const["C"]);
05539 
05540                 ++it;
05541                 CHECK(it != it_begin);
05542                 CHECK(it == it_end);
05543             }
05544 
05545             SECTION("json + cbegin/cend")
05546             {
05547                 json::const_iterator it_begin = j.cbegin();
05548                 json::const_iterator it_end = j.cend();
05549 
05550                 auto it = it_begin;
05551                 CHECK(it != it_end);
05552                 CHECK(*it == j["A"]);
05553 
05554                 it++;
05555                 CHECK(it != it_begin);
05556                 CHECK(it != it_end);
05557                 CHECK(*it == j["B"]);
05558 
05559                 ++it;
05560                 CHECK(it != it_begin);
05561                 CHECK(it != it_end);
05562                 CHECK(*it == j["C"]);
05563 
05564                 ++it;
05565                 CHECK(it != it_begin);
05566                 CHECK(it == it_end);
05567             }
05568 
05569             SECTION("const json + cbegin/cend")
05570             {
05571                 json::const_iterator it_begin = j_const.cbegin();
05572                 json::const_iterator it_end = j_const.cend();
05573 
05574                 auto it = it_begin;
05575                 CHECK(it != it_end);
05576                 CHECK(*it == j_const["A"]);
05577 
05578                 it++;
05579                 CHECK(it != it_begin);
05580                 CHECK(it != it_end);
05581                 CHECK(*it == j_const["B"]);
05582 
05583                 ++it;
05584                 CHECK(it != it_begin);
05585                 CHECK(it != it_end);
05586                 CHECK(*it == j_const["C"]);
05587 
05588                 ++it;
05589                 CHECK(it != it_begin);
05590                 CHECK(it == it_end);
05591             }
05592 
05593             SECTION("json + rbegin/rend")
05594             {
05595                 json::reverse_iterator it_begin = j.rbegin();
05596                 json::reverse_iterator it_end = j.rend();
05597 
05598                 auto it = it_begin;
05599                 CHECK(it != it_end);
05600                 CHECK(*it == j["C"]);
05601 
05602                 it++;
05603                 CHECK(it != it_begin);
05604                 CHECK(it != it_end);
05605                 CHECK(*it == j["B"]);
05606 
05607                 ++it;
05608                 CHECK(it != it_begin);
05609                 CHECK(it != it_end);
05610                 CHECK(*it == j["A"]);
05611 
05612                 ++it;
05613                 CHECK(it != it_begin);
05614                 CHECK(it == it_end);
05615             }
05616 
05617             SECTION("json + crbegin/crend")
05618             {
05619                 json::const_reverse_iterator it_begin = j.crbegin();
05620                 json::const_reverse_iterator it_end = j.crend();
05621 
05622                 auto it = it_begin;
05623                 CHECK(it != it_end);
05624                 CHECK(*it == j["C"]);
05625 
05626                 it++;
05627                 CHECK(it != it_begin);
05628                 CHECK(it != it_end);
05629                 CHECK(*it == j["B"]);
05630 
05631                 ++it;
05632                 CHECK(it != it_begin);
05633                 CHECK(it != it_end);
05634                 CHECK(*it == j["A"]);
05635 
05636                 ++it;
05637                 CHECK(it != it_begin);
05638                 CHECK(it == it_end);
05639             }
05640 
05641             SECTION("const json + crbegin/crend")
05642             {
05643                 json::const_reverse_iterator it_begin = j_const.crbegin();
05644                 json::const_reverse_iterator it_end = j_const.crend();
05645 
05646                 auto it = it_begin;
05647                 CHECK(it != it_end);
05648                 CHECK(*it == j["C"]);
05649 
05650                 it++;
05651                 CHECK(it != it_begin);
05652                 CHECK(it != it_end);
05653                 CHECK(*it == j["B"]);
05654 
05655                 ++it;
05656                 CHECK(it != it_begin);
05657                 CHECK(it != it_end);
05658                 CHECK(*it == j["A"]);
05659 
05660                 ++it;
05661                 CHECK(it != it_begin);
05662                 CHECK(it == it_end);
05663             }
05664 
05665             SECTION("key/value")
05666             {
05667                 auto it = j.begin();
05668                 auto cit = j_const.cbegin();
05669                 CHECK(it.key() == "A");
05670                 CHECK(it.value() == json(1));
05671                 CHECK(cit.key() == "A");
05672                 CHECK(cit.value() == json(1));
05673             }
05674         }
05675 
05676         SECTION("number (integer)")
05677         {
05678             json j = 23;
05679             json j_const(j);
05680 
05681             SECTION("json + begin/end")
05682             {
05683                 json::iterator it = j.begin();
05684                 CHECK(it != j.end());
05685                 CHECK(*it == j);
05686 
05687                 it++;
05688                 CHECK(it != j.begin());
05689                 CHECK(it == j.end());
05690 
05691                 it--;
05692                 CHECK(it == j.begin());
05693                 CHECK(it != j.end());
05694                 CHECK(*it == j);
05695 
05696                 ++it;
05697                 CHECK(it != j.begin());
05698                 CHECK(it == j.end());
05699 
05700                 --it;
05701                 CHECK(it == j.begin());
05702                 CHECK(it != j.end());
05703                 CHECK(*it == j);
05704             }
05705 
05706             SECTION("const json + begin/end")
05707             {
05708                 json::const_iterator it = j_const.begin();
05709                 CHECK(it != j_const.end());
05710                 CHECK(*it == j_const);
05711 
05712                 it++;
05713                 CHECK(it != j_const.begin());
05714                 CHECK(it == j_const.end());
05715 
05716                 it--;
05717                 CHECK(it == j_const.begin());
05718                 CHECK(it != j_const.end());
05719                 CHECK(*it == j_const);
05720 
05721                 ++it;
05722                 CHECK(it != j_const.begin());
05723                 CHECK(it == j_const.end());
05724 
05725                 --it;
05726                 CHECK(it == j_const.begin());
05727                 CHECK(it != j_const.end());
05728                 CHECK(*it == j_const);
05729             }
05730 
05731             SECTION("json + cbegin/cend")
05732             {
05733                 json::const_iterator it = j.cbegin();
05734                 CHECK(it != j.cend());
05735                 CHECK(*it == j);
05736 
05737                 it++;
05738                 CHECK(it != j.cbegin());
05739                 CHECK(it == j.cend());
05740 
05741                 it--;
05742                 CHECK(it == j.cbegin());
05743                 CHECK(it != j.cend());
05744                 CHECK(*it == j);
05745 
05746                 ++it;
05747                 CHECK(it != j.cbegin());
05748                 CHECK(it == j.cend());
05749 
05750                 --it;
05751                 CHECK(it == j.cbegin());
05752                 CHECK(it != j.cend());
05753                 CHECK(*it == j);
05754             }
05755 
05756             SECTION("const json + cbegin/cend")
05757             {
05758                 json::const_iterator it = j_const.cbegin();
05759                 CHECK(it != j_const.cend());
05760                 CHECK(*it == j_const);
05761 
05762                 it++;
05763                 CHECK(it != j_const.cbegin());
05764                 CHECK(it == j_const.cend());
05765 
05766                 it--;
05767                 CHECK(it == j_const.cbegin());
05768                 CHECK(it != j_const.cend());
05769                 CHECK(*it == j_const);
05770 
05771                 ++it;
05772                 CHECK(it != j_const.cbegin());
05773                 CHECK(it == j_const.cend());
05774 
05775                 --it;
05776                 CHECK(it == j_const.cbegin());
05777                 CHECK(it != j_const.cend());
05778                 CHECK(*it == j_const);
05779             }
05780 
05781             SECTION("json + rbegin/rend")
05782             {
05783                 json::reverse_iterator it = j.rbegin();
05784                 CHECK(it != j.rend());
05785                 CHECK(*it == j);
05786 
05787                 it++;
05788                 CHECK(it != j.rbegin());
05789                 CHECK(it == j.rend());
05790 
05791                 it--;
05792                 CHECK(it == j.rbegin());
05793                 CHECK(it != j.rend());
05794                 CHECK(*it == j);
05795 
05796                 ++it;
05797                 CHECK(it != j.rbegin());
05798                 CHECK(it == j.rend());
05799 
05800                 --it;
05801                 CHECK(it == j.rbegin());
05802                 CHECK(it != j.rend());
05803                 CHECK(*it == j);
05804             }
05805 
05806             SECTION("json + crbegin/crend")
05807             {
05808                 json::const_reverse_iterator it = j.crbegin();
05809                 CHECK(it != j.crend());
05810                 CHECK(*it == j);
05811 
05812                 it++;
05813                 CHECK(it != j.crbegin());
05814                 CHECK(it == j.crend());
05815 
05816                 it--;
05817                 CHECK(it == j.crbegin());
05818                 CHECK(it != j.crend());
05819                 CHECK(*it == j);
05820 
05821                 ++it;
05822                 CHECK(it != j.crbegin());
05823                 CHECK(it == j.crend());
05824 
05825                 --it;
05826                 CHECK(it == j.crbegin());
05827                 CHECK(it != j.crend());
05828                 CHECK(*it == j);
05829             }
05830 
05831             SECTION("const json + crbegin/crend")
05832             {
05833                 json::const_reverse_iterator it = j_const.crbegin();
05834                 CHECK(it != j_const.crend());
05835                 CHECK(*it == j_const);
05836 
05837                 it++;
05838                 CHECK(it != j_const.crbegin());
05839                 CHECK(it == j_const.crend());
05840 
05841                 it--;
05842                 CHECK(it == j_const.crbegin());
05843                 CHECK(it != j_const.crend());
05844                 CHECK(*it == j_const);
05845 
05846                 ++it;
05847                 CHECK(it != j_const.crbegin());
05848                 CHECK(it == j_const.crend());
05849 
05850                 --it;
05851                 CHECK(it == j_const.crbegin());
05852                 CHECK(it != j_const.crend());
05853                 CHECK(*it == j_const);
05854             }
05855 
05856             SECTION("key/value")
05857             {
05858                 auto it = j.begin();
05859                 auto cit = j_const.cbegin();
05860                 CHECK_THROWS_AS(it.key(), std::domain_error);
05861                 CHECK_THROWS_WITH(it.key(), "cannot use key() for non-object iterators");
05862                 CHECK(it.value() == json(23));
05863                 CHECK_THROWS_AS(cit.key(), std::domain_error);
05864                 CHECK_THROWS_WITH(cit.key(), "cannot use key() for non-object iterators");
05865                 CHECK(cit.value() == json(23));
05866 
05867                 auto rit = j.rend();
05868                 auto crit = j.crend();
05869                 CHECK_THROWS_AS(rit.key(), std::domain_error);
05870                 CHECK_THROWS_AS(rit.value(), std::out_of_range);
05871                 CHECK_THROWS_AS(crit.key(), std::domain_error);
05872                 CHECK_THROWS_AS(crit.value(), std::out_of_range);
05873                 CHECK_THROWS_WITH(rit.key(), "cannot use key() for non-object iterators");
05874                 CHECK_THROWS_WITH(rit.value(), "cannot get value");
05875                 CHECK_THROWS_WITH(crit.key(), "cannot use key() for non-object iterators");
05876                 CHECK_THROWS_WITH(crit.value(), "cannot get value");
05877             }
05878         }
05879 
05880         SECTION("number (unsigned)")
05881         {
05882             json j = 23u;
05883             json j_const(j);
05884 
05885             SECTION("json + begin/end")
05886             {
05887                 json::iterator it = j.begin();
05888                 CHECK(it != j.end());
05889                 CHECK(*it == j);
05890 
05891                 it++;
05892                 CHECK(it != j.begin());
05893                 CHECK(it == j.end());
05894 
05895                 it--;
05896                 CHECK(it == j.begin());
05897                 CHECK(it != j.end());
05898                 CHECK(*it == j);
05899 
05900                 ++it;
05901                 CHECK(it != j.begin());
05902                 CHECK(it == j.end());
05903 
05904                 --it;
05905                 CHECK(it == j.begin());
05906                 CHECK(it != j.end());
05907                 CHECK(*it == j);
05908             }
05909 
05910             SECTION("const json + begin/end")
05911             {
05912                 json::const_iterator it = j_const.begin();
05913                 CHECK(it != j_const.end());
05914                 CHECK(*it == j_const);
05915 
05916                 it++;
05917                 CHECK(it != j_const.begin());
05918                 CHECK(it == j_const.end());
05919 
05920                 it--;
05921                 CHECK(it == j_const.begin());
05922                 CHECK(it != j_const.end());
05923                 CHECK(*it == j_const);
05924 
05925                 ++it;
05926                 CHECK(it != j_const.begin());
05927                 CHECK(it == j_const.end());
05928 
05929                 --it;
05930                 CHECK(it == j_const.begin());
05931                 CHECK(it != j_const.end());
05932                 CHECK(*it == j_const);
05933             }
05934 
05935             SECTION("json + cbegin/cend")
05936             {
05937                 json::const_iterator it = j.cbegin();
05938                 CHECK(it != j.cend());
05939                 CHECK(*it == j);
05940 
05941                 it++;
05942                 CHECK(it != j.cbegin());
05943                 CHECK(it == j.cend());
05944 
05945                 it--;
05946                 CHECK(it == j.cbegin());
05947                 CHECK(it != j.cend());
05948                 CHECK(*it == j);
05949 
05950                 ++it;
05951                 CHECK(it != j.cbegin());
05952                 CHECK(it == j.cend());
05953 
05954                 --it;
05955                 CHECK(it == j.cbegin());
05956                 CHECK(it != j.cend());
05957                 CHECK(*it == j);
05958             }
05959 
05960             SECTION("const json + cbegin/cend")
05961             {
05962                 json::const_iterator it = j_const.cbegin();
05963                 CHECK(it != j_const.cend());
05964                 CHECK(*it == j_const);
05965 
05966                 it++;
05967                 CHECK(it != j_const.cbegin());
05968                 CHECK(it == j_const.cend());
05969 
05970                 it--;
05971                 CHECK(it == j_const.cbegin());
05972                 CHECK(it != j_const.cend());
05973                 CHECK(*it == j_const);
05974 
05975                 ++it;
05976                 CHECK(it != j_const.cbegin());
05977                 CHECK(it == j_const.cend());
05978 
05979                 --it;
05980                 CHECK(it == j_const.cbegin());
05981                 CHECK(it != j_const.cend());
05982                 CHECK(*it == j_const);
05983             }
05984 
05985             SECTION("json + rbegin/rend")
05986             {
05987                 json::reverse_iterator it = j.rbegin();
05988                 CHECK(it != j.rend());
05989                 CHECK(*it == j);
05990 
05991                 it++;
05992                 CHECK(it != j.rbegin());
05993                 CHECK(it == j.rend());
05994 
05995                 it--;
05996                 CHECK(it == j.rbegin());
05997                 CHECK(it != j.rend());
05998                 CHECK(*it == j);
05999 
06000                 ++it;
06001                 CHECK(it != j.rbegin());
06002                 CHECK(it == j.rend());
06003 
06004                 --it;
06005                 CHECK(it == j.rbegin());
06006                 CHECK(it != j.rend());
06007                 CHECK(*it == j);
06008             }
06009 
06010             SECTION("json + crbegin/crend")
06011             {
06012                 json::const_reverse_iterator it = j.crbegin();
06013                 CHECK(it != j.crend());
06014                 CHECK(*it == j);
06015 
06016                 it++;
06017                 CHECK(it != j.crbegin());
06018                 CHECK(it == j.crend());
06019 
06020                 it--;
06021                 CHECK(it == j.crbegin());
06022                 CHECK(it != j.crend());
06023                 CHECK(*it == j);
06024 
06025                 ++it;
06026                 CHECK(it != j.crbegin());
06027                 CHECK(it == j.crend());
06028 
06029                 --it;
06030                 CHECK(it == j.crbegin());
06031                 CHECK(it != j.crend());
06032                 CHECK(*it == j);
06033             }
06034 
06035             SECTION("const json + crbegin/crend")
06036             {
06037                 json::const_reverse_iterator it = j_const.crbegin();
06038                 CHECK(it != j_const.crend());
06039                 CHECK(*it == j_const);
06040 
06041                 it++;
06042                 CHECK(it != j_const.crbegin());
06043                 CHECK(it == j_const.crend());
06044 
06045                 it--;
06046                 CHECK(it == j_const.crbegin());
06047                 CHECK(it != j_const.crend());
06048                 CHECK(*it == j_const);
06049 
06050                 ++it;
06051                 CHECK(it != j_const.crbegin());
06052                 CHECK(it == j_const.crend());
06053 
06054                 --it;
06055                 CHECK(it == j_const.crbegin());
06056                 CHECK(it != j_const.crend());
06057                 CHECK(*it == j_const);
06058             }
06059 
06060             SECTION("key/value")
06061             {
06062                 auto it = j.begin();
06063                 auto cit = j_const.cbegin();
06064                 CHECK_THROWS_AS(it.key(), std::domain_error);
06065                 CHECK_THROWS_WITH(it.key(), "cannot use key() for non-object iterators");
06066                 CHECK(it.value() == json(23));
06067                 CHECK_THROWS_AS(cit.key(), std::domain_error);
06068                 CHECK_THROWS_WITH(cit.key(), "cannot use key() for non-object iterators");
06069                 CHECK(cit.value() == json(23));
06070 
06071                 auto rit = j.rend();
06072                 auto crit = j.crend();
06073                 CHECK_THROWS_AS(rit.key(), std::domain_error);
06074                 CHECK_THROWS_AS(rit.value(), std::out_of_range);
06075                 CHECK_THROWS_AS(crit.key(), std::domain_error);
06076                 CHECK_THROWS_AS(crit.value(), std::out_of_range);
06077                 CHECK_THROWS_WITH(rit.key(), "cannot use key() for non-object iterators");
06078                 CHECK_THROWS_WITH(rit.value(), "cannot get value");
06079                 CHECK_THROWS_WITH(crit.key(), "cannot use key() for non-object iterators");
06080                 CHECK_THROWS_WITH(crit.value(), "cannot get value");
06081             }
06082         }
06083 
06084         SECTION("number (float)")
06085         {
06086             json j = 23.42;
06087             json j_const(j);
06088 
06089             SECTION("json + begin/end")
06090             {
06091                 json::iterator it = j.begin();
06092                 CHECK(it != j.end());
06093                 CHECK(*it == j);
06094 
06095                 it++;
06096                 CHECK(it != j.begin());
06097                 CHECK(it == j.end());
06098 
06099                 it--;
06100                 CHECK(it == j.begin());
06101                 CHECK(it != j.end());
06102                 CHECK(*it == j);
06103 
06104                 ++it;
06105                 CHECK(it != j.begin());
06106                 CHECK(it == j.end());
06107 
06108                 --it;
06109                 CHECK(it == j.begin());
06110                 CHECK(it != j.end());
06111                 CHECK(*it == j);
06112             }
06113 
06114             SECTION("const json + begin/end")
06115             {
06116                 json::const_iterator it = j_const.begin();
06117                 CHECK(it != j_const.end());
06118                 CHECK(*it == j_const);
06119 
06120                 it++;
06121                 CHECK(it != j_const.begin());
06122                 CHECK(it == j_const.end());
06123 
06124                 it--;
06125                 CHECK(it == j_const.begin());
06126                 CHECK(it != j_const.end());
06127                 CHECK(*it == j_const);
06128 
06129                 ++it;
06130                 CHECK(it != j_const.begin());
06131                 CHECK(it == j_const.end());
06132 
06133                 --it;
06134                 CHECK(it == j_const.begin());
06135                 CHECK(it != j_const.end());
06136                 CHECK(*it == j_const);
06137             }
06138 
06139             SECTION("json + cbegin/cend")
06140             {
06141                 json::const_iterator it = j.cbegin();
06142                 CHECK(it != j.cend());
06143                 CHECK(*it == j);
06144 
06145                 it++;
06146                 CHECK(it != j.cbegin());
06147                 CHECK(it == j.cend());
06148 
06149                 it--;
06150                 CHECK(it == j.cbegin());
06151                 CHECK(it != j.cend());
06152                 CHECK(*it == j);
06153 
06154                 ++it;
06155                 CHECK(it != j.cbegin());
06156                 CHECK(it == j.cend());
06157 
06158                 --it;
06159                 CHECK(it == j.cbegin());
06160                 CHECK(it != j.cend());
06161                 CHECK(*it == j);
06162             }
06163 
06164             SECTION("const json + cbegin/cend")
06165             {
06166                 json::const_iterator it = j_const.cbegin();
06167                 CHECK(it != j_const.cend());
06168                 CHECK(*it == j_const);
06169 
06170                 it++;
06171                 CHECK(it != j_const.cbegin());
06172                 CHECK(it == j_const.cend());
06173 
06174                 it--;
06175                 CHECK(it == j_const.cbegin());
06176                 CHECK(it != j_const.cend());
06177                 CHECK(*it == j_const);
06178 
06179                 ++it;
06180                 CHECK(it != j_const.cbegin());
06181                 CHECK(it == j_const.cend());
06182 
06183                 --it;
06184                 CHECK(it == j_const.cbegin());
06185                 CHECK(it != j_const.cend());
06186                 CHECK(*it == j_const);
06187             }
06188 
06189             SECTION("json + rbegin/rend")
06190             {
06191                 json::reverse_iterator it = j.rbegin();
06192                 CHECK(it != j.rend());
06193                 CHECK(*it == j);
06194 
06195                 it++;
06196                 CHECK(it != j.rbegin());
06197                 CHECK(it == j.rend());
06198 
06199                 it--;
06200                 CHECK(it == j.rbegin());
06201                 CHECK(it != j.rend());
06202                 CHECK(*it == j);
06203 
06204                 ++it;
06205                 CHECK(it != j.rbegin());
06206                 CHECK(it == j.rend());
06207 
06208                 --it;
06209                 CHECK(it == j.rbegin());
06210                 CHECK(it != j.rend());
06211                 CHECK(*it == j);
06212             }
06213 
06214             SECTION("json + crbegin/crend")
06215             {
06216                 json::const_reverse_iterator it = j.crbegin();
06217                 CHECK(it != j.crend());
06218                 CHECK(*it == j);
06219 
06220                 it++;
06221                 CHECK(it != j.crbegin());
06222                 CHECK(it == j.crend());
06223 
06224                 it--;
06225                 CHECK(it == j.crbegin());
06226                 CHECK(it != j.crend());
06227                 CHECK(*it == j);
06228 
06229                 ++it;
06230                 CHECK(it != j.crbegin());
06231                 CHECK(it == j.crend());
06232 
06233                 --it;
06234                 CHECK(it == j.crbegin());
06235                 CHECK(it != j.crend());
06236                 CHECK(*it == j);
06237             }
06238 
06239             SECTION("const json + crbegin/crend")
06240             {
06241                 json::const_reverse_iterator it = j_const.crbegin();
06242                 CHECK(it != j_const.crend());
06243                 CHECK(*it == j_const);
06244 
06245                 it++;
06246                 CHECK(it != j_const.crbegin());
06247                 CHECK(it == j_const.crend());
06248 
06249                 it--;
06250                 CHECK(it == j_const.crbegin());
06251                 CHECK(it != j_const.crend());
06252                 CHECK(*it == j_const);
06253 
06254                 ++it;
06255                 CHECK(it != j_const.crbegin());
06256                 CHECK(it == j_const.crend());
06257 
06258                 --it;
06259                 CHECK(it == j_const.crbegin());
06260                 CHECK(it != j_const.crend());
06261                 CHECK(*it == j_const);
06262             }
06263 
06264             SECTION("key/value")
06265             {
06266                 auto it = j.begin();
06267                 auto cit = j_const.cbegin();
06268                 CHECK_THROWS_AS(it.key(), std::domain_error);
06269                 CHECK_THROWS_WITH(it.key(), "cannot use key() for non-object iterators");
06270                 CHECK(it.value() == json(23.42));
06271                 CHECK_THROWS_AS(cit.key(), std::domain_error);
06272                 CHECK_THROWS_WITH(cit.key(), "cannot use key() for non-object iterators");
06273                 CHECK(cit.value() == json(23.42));
06274 
06275                 auto rit = j.rend();
06276                 auto crit = j.crend();
06277                 CHECK_THROWS_AS(rit.key(), std::domain_error);
06278                 CHECK_THROWS_AS(rit.value(), std::out_of_range);
06279                 CHECK_THROWS_AS(crit.key(), std::domain_error);
06280                 CHECK_THROWS_AS(crit.value(), std::out_of_range);
06281                 CHECK_THROWS_WITH(rit.key(), "cannot use key() for non-object iterators");
06282                 CHECK_THROWS_WITH(rit.value(), "cannot get value");
06283                 CHECK_THROWS_WITH(crit.key(), "cannot use key() for non-object iterators");
06284                 CHECK_THROWS_WITH(crit.value(), "cannot get value");
06285             }
06286         }
06287 
06288         SECTION("null")
06289         {
06290             json j = nullptr;
06291             json j_const(j);
06292 
06293             SECTION("json + begin/end")
06294             {
06295                 json::iterator it = j.begin();
06296                 CHECK(it == j.end());
06297             }
06298 
06299             SECTION("const json + begin/end")
06300             {
06301                 json::const_iterator it_begin = j_const.begin();
06302                 json::const_iterator it_end = j_const.end();
06303                 CHECK(it_begin == it_end);
06304             }
06305 
06306             SECTION("json + cbegin/cend")
06307             {
06308                 json::const_iterator it_begin = j.cbegin();
06309                 json::const_iterator it_end = j.cend();
06310                 CHECK(it_begin == it_end);
06311             }
06312 
06313             SECTION("const json + cbegin/cend")
06314             {
06315                 json::const_iterator it_begin = j_const.cbegin();
06316                 json::const_iterator it_end = j_const.cend();
06317                 CHECK(it_begin == it_end);
06318             }
06319 
06320             SECTION("json + rbegin/rend")
06321             {
06322                 json::reverse_iterator it = j.rbegin();
06323                 CHECK(it == j.rend());
06324             }
06325 
06326             SECTION("json + crbegin/crend")
06327             {
06328                 json::const_reverse_iterator it = j.crbegin();
06329                 CHECK(it == j.crend());
06330             }
06331 
06332             SECTION("const json + crbegin/crend")
06333             {
06334                 json::const_reverse_iterator it = j_const.crbegin();
06335                 CHECK(it == j_const.crend());
06336             }
06337 
06338             SECTION("key/value")
06339             {
06340                 auto it = j.begin();
06341                 auto cit = j_const.cbegin();
06342                 CHECK_THROWS_AS(it.key(), std::domain_error);
06343                 CHECK_THROWS_AS(it.value(), std::out_of_range);
06344                 CHECK_THROWS_AS(cit.key(), std::domain_error);
06345                 CHECK_THROWS_AS(cit.value(), std::out_of_range);
06346                 CHECK_THROWS_WITH(it.key(), "cannot use key() for non-object iterators");
06347                 CHECK_THROWS_WITH(it.value(), "cannot get value");
06348                 CHECK_THROWS_WITH(cit.key(), "cannot use key() for non-object iterators");
06349                 CHECK_THROWS_WITH(cit.value(), "cannot get value");
06350 
06351                 auto rit = j.rend();
06352                 auto crit = j.crend();
06353                 CHECK_THROWS_AS(rit.key(), std::domain_error);
06354                 CHECK_THROWS_AS(rit.value(), std::out_of_range);
06355                 CHECK_THROWS_AS(crit.key(), std::domain_error);
06356                 CHECK_THROWS_AS(crit.value(), std::out_of_range);
06357                 CHECK_THROWS_WITH(rit.key(), "cannot use key() for non-object iterators");
06358                 CHECK_THROWS_WITH(rit.value(), "cannot get value");
06359                 CHECK_THROWS_WITH(crit.key(), "cannot use key() for non-object iterators");
06360                 CHECK_THROWS_WITH(crit.value(), "cannot get value");
06361             }
06362         }
06363     }
06364 
06365     SECTION("iterator comparisons")
06366     {
06367         json j_values = {nullptr, true, 42, 42u, 23.23, {{"one", 1}, {"two", 2}}, {1, 2, 3, 4, 5}, "Hello, world"};
06368 
06369         for (json& j : j_values)
06370         {
06371             auto it1 = j.begin();
06372             auto it2 = j.begin();
06373             auto it3 = j.begin();
06374             ++it2;
06375             ++it3;
06376             ++it3;
06377             auto it1_c = j.cbegin();
06378             auto it2_c = j.cbegin();
06379             auto it3_c = j.cbegin();
06380             ++it2_c;
06381             ++it3_c;
06382             ++it3_c;
06383 
06384             // comparison: equal
06385             {
06386                 CHECK(it1 == it1);
06387                 CHECK(not (it1 == it2));
06388                 CHECK(not (it1 == it3));
06389                 CHECK(not (it2 == it3));
06390                 CHECK(it1_c == it1_c);
06391                 CHECK(not (it1_c == it2_c));
06392                 CHECK(not (it1_c == it3_c));
06393                 CHECK(not (it2_c == it3_c));
06394             }
06395 
06396             // comparison: not equal
06397             {
06398                 // check definition
06399                 CHECK( (it1 != it1) == not(it1 == it1) );
06400                 CHECK( (it1 != it2) == not(it1 == it2) );
06401                 CHECK( (it1 != it3) == not(it1 == it3) );
06402                 CHECK( (it2 != it3) == not(it2 == it3) );
06403                 CHECK( (it1_c != it1_c) == not(it1_c == it1_c) );
06404                 CHECK( (it1_c != it2_c) == not(it1_c == it2_c) );
06405                 CHECK( (it1_c != it3_c) == not(it1_c == it3_c) );
06406                 CHECK( (it2_c != it3_c) == not(it2_c == it3_c) );
06407             }
06408 
06409             // comparison: smaller
06410             {
06411                 if (j.type() == json::value_t::object)
06412                 {
06413                     CHECK_THROWS_AS(it1 < it1, std::domain_error);
06414                     CHECK_THROWS_AS(it1 < it2, std::domain_error);
06415                     CHECK_THROWS_AS(it2 < it3, std::domain_error);
06416                     CHECK_THROWS_AS(it1 < it3, std::domain_error);
06417                     CHECK_THROWS_AS(it1_c < it1_c, std::domain_error);
06418                     CHECK_THROWS_AS(it1_c < it2_c, std::domain_error);
06419                     CHECK_THROWS_AS(it2_c < it3_c, std::domain_error);
06420                     CHECK_THROWS_AS(it1_c < it3_c, std::domain_error);
06421                     CHECK_THROWS_WITH(it1 < it1, "cannot compare order of object iterators");
06422                     CHECK_THROWS_WITH(it1 < it2, "cannot compare order of object iterators");
06423                     CHECK_THROWS_WITH(it2 < it3, "cannot compare order of object iterators");
06424                     CHECK_THROWS_WITH(it1 < it3, "cannot compare order of object iterators");
06425                     CHECK_THROWS_WITH(it1_c < it1_c, "cannot compare order of object iterators");
06426                     CHECK_THROWS_WITH(it1_c < it2_c, "cannot compare order of object iterators");
06427                     CHECK_THROWS_WITH(it2_c < it3_c, "cannot compare order of object iterators");
06428                     CHECK_THROWS_WITH(it1_c < it3_c, "cannot compare order of object iterators");
06429                 }
06430                 else
06431                 {
06432                     CHECK(not (it1 < it1));
06433                     CHECK(it1 < it2);
06434                     CHECK(it1 < it3);
06435                     CHECK(it2 < it3);
06436                     CHECK(not (it1_c < it1_c));
06437                     CHECK(it1_c < it2_c);
06438                     CHECK(it1_c < it3_c);
06439                     CHECK(it2_c < it3_c);
06440                 }
06441             }
06442 
06443             // comparison: less than or equal
06444             {
06445                 if (j.type() == json::value_t::object)
06446                 {
06447                     CHECK_THROWS_AS(it1 <= it1, std::domain_error);
06448                     CHECK_THROWS_AS(it1 <= it2, std::domain_error);
06449                     CHECK_THROWS_AS(it2 <= it3, std::domain_error);
06450                     CHECK_THROWS_AS(it1 <= it3, std::domain_error);
06451                     CHECK_THROWS_AS(it1_c <= it1_c, std::domain_error);
06452                     CHECK_THROWS_AS(it1_c <= it2_c, std::domain_error);
06453                     CHECK_THROWS_AS(it2_c <= it3_c, std::domain_error);
06454                     CHECK_THROWS_AS(it1_c <= it3_c, std::domain_error);
06455                     CHECK_THROWS_WITH(it1 <= it1, "cannot compare order of object iterators");
06456                     CHECK_THROWS_WITH(it1 <= it2, "cannot compare order of object iterators");
06457                     CHECK_THROWS_WITH(it2 <= it3, "cannot compare order of object iterators");
06458                     CHECK_THROWS_WITH(it1 <= it3, "cannot compare order of object iterators");
06459                     CHECK_THROWS_WITH(it1_c <= it1_c, "cannot compare order of object iterators");
06460                     CHECK_THROWS_WITH(it1_c <= it2_c, "cannot compare order of object iterators");
06461                     CHECK_THROWS_WITH(it2_c <= it3_c, "cannot compare order of object iterators");
06462                     CHECK_THROWS_WITH(it1_c <= it3_c, "cannot compare order of object iterators");
06463                 }
06464                 else
06465                 {
06466                     // check definition
06467                     CHECK( (it1 <= it1) == not(it1 < it1) );
06468                     CHECK( (it1 <= it2) == not(it2 < it1) );
06469                     CHECK( (it1 <= it3) == not(it3 < it1) );
06470                     CHECK( (it2 <= it3) == not(it3 < it2) );
06471                     CHECK( (it1_c <= it1_c) == not(it1_c < it1_c) );
06472                     CHECK( (it1_c <= it2_c) == not(it2_c < it1_c) );
06473                     CHECK( (it1_c <= it3_c) == not(it3_c < it1_c) );
06474                     CHECK( (it2_c <= it3_c) == not(it3_c < it2_c) );
06475                 }
06476             }
06477 
06478             // comparison: greater than
06479             {
06480                 if (j.type() == json::value_t::object)
06481                 {
06482                     CHECK_THROWS_AS(it1 > it1, std::domain_error);
06483                     CHECK_THROWS_AS(it1 > it2, std::domain_error);
06484                     CHECK_THROWS_AS(it2 > it3, std::domain_error);
06485                     CHECK_THROWS_AS(it1 > it3, std::domain_error);
06486                     CHECK_THROWS_AS(it1_c > it1_c, std::domain_error);
06487                     CHECK_THROWS_AS(it1_c > it2_c, std::domain_error);
06488                     CHECK_THROWS_AS(it2_c > it3_c, std::domain_error);
06489                     CHECK_THROWS_AS(it1_c > it3_c, std::domain_error);
06490                     CHECK_THROWS_WITH(it1 > it1, "cannot compare order of object iterators");
06491                     CHECK_THROWS_WITH(it1 > it2, "cannot compare order of object iterators");
06492                     CHECK_THROWS_WITH(it2 > it3, "cannot compare order of object iterators");
06493                     CHECK_THROWS_WITH(it1 > it3, "cannot compare order of object iterators");
06494                     CHECK_THROWS_WITH(it1_c > it1_c, "cannot compare order of object iterators");
06495                     CHECK_THROWS_WITH(it1_c > it2_c, "cannot compare order of object iterators");
06496                     CHECK_THROWS_WITH(it2_c > it3_c, "cannot compare order of object iterators");
06497                     CHECK_THROWS_WITH(it1_c > it3_c, "cannot compare order of object iterators");
06498                 }
06499                 else
06500                 {
06501                     // check definition
06502                     CHECK( (it1 > it1) == (it1 < it1) );
06503                     CHECK( (it1 > it2) == (it2 < it1) );
06504                     CHECK( (it1 > it3) == (it3 < it1) );
06505                     CHECK( (it2 > it3) == (it3 < it2) );
06506                     CHECK( (it1_c > it1_c) == (it1_c < it1_c) );
06507                     CHECK( (it1_c > it2_c) == (it2_c < it1_c) );
06508                     CHECK( (it1_c > it3_c) == (it3_c < it1_c) );
06509                     CHECK( (it2_c > it3_c) == (it3_c < it2_c) );
06510                 }
06511             }
06512 
06513             // comparison: greater than or equal
06514             {
06515                 if (j.type() == json::value_t::object)
06516                 {
06517                     CHECK_THROWS_AS(it1 >= it1, std::domain_error);
06518                     CHECK_THROWS_AS(it1 >= it2, std::domain_error);
06519                     CHECK_THROWS_AS(it2 >= it3, std::domain_error);
06520                     CHECK_THROWS_AS(it1 >= it3, std::domain_error);
06521                     CHECK_THROWS_AS(it1_c >= it1_c, std::domain_error);
06522                     CHECK_THROWS_AS(it1_c >= it2_c, std::domain_error);
06523                     CHECK_THROWS_AS(it2_c >= it3_c, std::domain_error);
06524                     CHECK_THROWS_AS(it1_c >= it3_c, std::domain_error);
06525                     CHECK_THROWS_WITH(it1 >= it1, "cannot compare order of object iterators");
06526                     CHECK_THROWS_WITH(it1 >= it2, "cannot compare order of object iterators");
06527                     CHECK_THROWS_WITH(it2 >= it3, "cannot compare order of object iterators");
06528                     CHECK_THROWS_WITH(it1 >= it3, "cannot compare order of object iterators");
06529                     CHECK_THROWS_WITH(it1_c >= it1_c, "cannot compare order of object iterators");
06530                     CHECK_THROWS_WITH(it1_c >= it2_c, "cannot compare order of object iterators");
06531                     CHECK_THROWS_WITH(it2_c >= it3_c, "cannot compare order of object iterators");
06532                     CHECK_THROWS_WITH(it1_c >= it3_c, "cannot compare order of object iterators");
06533                 }
06534                 else
06535                 {
06536                     // check definition
06537                     CHECK( (it1 >= it1) == not(it1 < it1) );
06538                     CHECK( (it1 >= it2) == not(it1 < it2) );
06539                     CHECK( (it1 >= it3) == not(it1 < it3) );
06540                     CHECK( (it2 >= it3) == not(it2 < it3) );
06541                     CHECK( (it1_c >= it1_c) == not(it1_c < it1_c) );
06542                     CHECK( (it1_c >= it2_c) == not(it1_c < it2_c) );
06543                     CHECK( (it1_c >= it3_c) == not(it1_c < it3_c) );
06544                     CHECK( (it2_c >= it3_c) == not(it2_c < it3_c) );
06545                 }
06546             }
06547         }
06548 
06549         // check exceptions if different objects are compared
06550         for (auto j : j_values)
06551         {
06552             for (auto k : j_values)
06553             {
06554                 if (j != k)
06555                 {
06556                     CHECK_THROWS_AS(j.begin() == k.begin(), std::domain_error);
06557                     CHECK_THROWS_AS(j.cbegin() == k.cbegin(), std::domain_error);
06558                     CHECK_THROWS_WITH(j.begin() == k.begin(), "cannot compare iterators of different containers");
06559                     CHECK_THROWS_WITH(j.cbegin() == k.cbegin(), "cannot compare iterators of different containers");
06560 
06561                     CHECK_THROWS_AS(j.begin() < k.begin(), std::domain_error);
06562                     CHECK_THROWS_AS(j.cbegin() < k.cbegin(), std::domain_error);
06563                     CHECK_THROWS_WITH(j.begin() < k.begin(), "cannot compare iterators of different containers");
06564                     CHECK_THROWS_WITH(j.cbegin() < k.cbegin(), "cannot compare iterators of different containers");
06565                 }
06566             }
06567         }
06568     }
06569 
06570     SECTION("iterator arithmetic")
06571     {
06572         json j_object = {{"one", 1}, {"two", 2}, {"three", 3}};
06573         json j_array = {1, 2, 3, 4, 5, 6};
06574         json j_null = nullptr;
06575         json j_value = 42;
06576 
06577         SECTION("addition and subtraction")
06578         {
06579             SECTION("object")
06580             {
06581                 {
06582                     auto it = j_object.begin();
06583                     CHECK_THROWS_AS(it += 1, std::domain_error);
06584                     CHECK_THROWS_WITH(it += 1, "cannot use offsets with object iterators");
06585                 }
06586                 {
06587                     auto it = j_object.cbegin();
06588                     CHECK_THROWS_AS(it += 1, std::domain_error);
06589                     CHECK_THROWS_WITH(it += 1, "cannot use offsets with object iterators");
06590                 }
06591                 {
06592                     auto it = j_object.begin();
06593                     CHECK_THROWS_AS(it + 1, std::domain_error);
06594                     CHECK_THROWS_WITH(it + 1, "cannot use offsets with object iterators");
06595                 }
06596                 {
06597                     auto it = j_object.cbegin();
06598                     CHECK_THROWS_AS(it + 1, std::domain_error);
06599                     CHECK_THROWS_WITH(it + 1, "cannot use offsets with object iterators");
06600                 }
06601                 {
06602                     auto it = j_object.begin();
06603                     CHECK_THROWS_AS(it -= 1, std::domain_error);
06604                     CHECK_THROWS_WITH(it -= 1, "cannot use offsets with object iterators");
06605                 }
06606                 {
06607                     auto it = j_object.cbegin();
06608                     CHECK_THROWS_AS(it -= 1, std::domain_error);
06609                     CHECK_THROWS_WITH(it -= 1, "cannot use offsets with object iterators");
06610                 }
06611                 {
06612                     auto it = j_object.begin();
06613                     CHECK_THROWS_AS(it - 1, std::domain_error);
06614                     CHECK_THROWS_WITH(it - 1, "cannot use offsets with object iterators");
06615                 }
06616                 {
06617                     auto it = j_object.cbegin();
06618                     CHECK_THROWS_AS(it - 1, std::domain_error);
06619                     CHECK_THROWS_WITH(it - 1, "cannot use offsets with object iterators");
06620                 }
06621                 {
06622                     auto it = j_object.begin();
06623                     CHECK_THROWS_AS(it - it, std::domain_error);
06624                     CHECK_THROWS_WITH(it - it, "cannot use offsets with object iterators");
06625                 }
06626                 {
06627                     auto it = j_object.cbegin();
06628                     CHECK_THROWS_AS(it - it, std::domain_error);
06629                     CHECK_THROWS_WITH(it - it, "cannot use offsets with object iterators");
06630                 }
06631             }
06632 
06633             SECTION("array")
06634             {
06635                 {
06636                     auto it = j_array.begin();
06637                     it += 3;
06638                     CHECK((j_array.begin() + 3) == it);
06639                     CHECK((it - 3) == j_array.begin());
06640                     CHECK((it - j_array.begin()) == 3);
06641                     CHECK(*it == json(4));
06642                     it -= 2;
06643                     CHECK(*it == json(2));
06644                 }
06645                 {
06646                     auto it = j_array.cbegin();
06647                     it += 3;
06648                     CHECK((j_array.cbegin() + 3) == it);
06649                     CHECK((it - 3) == j_array.cbegin());
06650                     CHECK((it - j_array.cbegin()) == 3);
06651                     CHECK(*it == json(4));
06652                     it -= 2;
06653                     CHECK(*it == json(2));
06654                 }
06655             }
06656 
06657             SECTION("null")
06658             {
06659                 {
06660                     auto it = j_null.begin();
06661                     it += 3;
06662                     CHECK((j_null.begin() + 3) == it);
06663                     CHECK((it - 3) == j_null.begin());
06664                     CHECK((it - j_null.begin()) == 3);
06665                     CHECK(it != j_null.end());
06666                     it -= 3;
06667                     CHECK(it == j_null.end());
06668                 }
06669                 {
06670                     auto it = j_null.cbegin();
06671                     it += 3;
06672                     CHECK((j_null.cbegin() + 3) == it);
06673                     CHECK((it - 3) == j_null.cbegin());
06674                     CHECK((it - j_null.cbegin()) == 3);
06675                     CHECK(it != j_null.cend());
06676                     it -= 3;
06677                     CHECK(it == j_null.cend());
06678                 }
06679             }
06680 
06681             SECTION("value")
06682             {
06683                 {
06684                     auto it = j_value.begin();
06685                     it += 3;
06686                     CHECK((j_value.begin() + 3) == it);
06687                     CHECK((it - 3) == j_value.begin());
06688                     CHECK((it - j_value.begin()) == 3);
06689                     CHECK(it != j_value.end());
06690                     it -= 3;
06691                     CHECK(*it == json(42));
06692                 }
06693                 {
06694                     auto it = j_value.cbegin();
06695                     it += 3;
06696                     CHECK((j_value.cbegin() + 3) == it);
06697                     CHECK((it - 3) == j_value.cbegin());
06698                     CHECK((it - j_value.cbegin()) == 3);
06699                     CHECK(it != j_value.cend());
06700                     it -= 3;
06701                     CHECK(*it == json(42));
06702                 }
06703             }
06704         }
06705 
06706         SECTION("subscript operator")
06707         {
06708             SECTION("object")
06709             {
06710                 {
06711                     auto it = j_object.begin();
06712                     CHECK_THROWS_AS(it[0], std::domain_error);
06713                     CHECK_THROWS_AS(it[1], std::domain_error);
06714                     CHECK_THROWS_WITH(it[0], "cannot use operator[] for object iterators");
06715                     CHECK_THROWS_WITH(it[1], "cannot use operator[] for object iterators");
06716                 }
06717                 {
06718                     auto it = j_object.cbegin();
06719                     CHECK_THROWS_AS(it[0], std::domain_error);
06720                     CHECK_THROWS_AS(it[1], std::domain_error);
06721                     CHECK_THROWS_WITH(it[0], "cannot use operator[] for object iterators");
06722                     CHECK_THROWS_WITH(it[1], "cannot use operator[] for object iterators");
06723                 }
06724             }
06725 
06726             SECTION("array")
06727             {
06728                 {
06729                     auto it = j_array.begin();
06730                     CHECK(it[0] == json(1));
06731                     CHECK(it[1] == json(2));
06732                     CHECK(it[2] == json(3));
06733                     CHECK(it[3] == json(4));
06734                     CHECK(it[4] == json(5));
06735                     CHECK(it[5] == json(6));
06736                 }
06737                 {
06738                     auto it = j_array.cbegin();
06739                     CHECK(it[0] == json(1));
06740                     CHECK(it[1] == json(2));
06741                     CHECK(it[2] == json(3));
06742                     CHECK(it[3] == json(4));
06743                     CHECK(it[4] == json(5));
06744                     CHECK(it[5] == json(6));
06745                 }
06746             }
06747 
06748             SECTION("null")
06749             {
06750                 {
06751                     auto it = j_null.begin();
06752                     CHECK_THROWS_AS(it[0], std::out_of_range);
06753                     CHECK_THROWS_AS(it[1], std::out_of_range);
06754                     CHECK_THROWS_WITH(it[0], "cannot get value");
06755                     CHECK_THROWS_WITH(it[1], "cannot get value");
06756                 }
06757                 {
06758                     auto it = j_null.cbegin();
06759                     CHECK_THROWS_AS(it[0], std::out_of_range);
06760                     CHECK_THROWS_AS(it[1], std::out_of_range);
06761                     CHECK_THROWS_WITH(it[0], "cannot get value");
06762                     CHECK_THROWS_WITH(it[1], "cannot get value");
06763                 }
06764             }
06765 
06766             SECTION("value")
06767             {
06768                 {
06769                     auto it = j_value.begin();
06770                     CHECK(it[0] == json(42));
06771                     CHECK_THROWS_AS(it[1], std::out_of_range);
06772                     CHECK_THROWS_WITH(it[1], "cannot get value");
06773                 }
06774                 {
06775                     auto it = j_value.cbegin();
06776                     CHECK(it[0] == json(42));
06777                     CHECK_THROWS_AS(it[1], std::out_of_range);
06778                     CHECK_THROWS_WITH(it[1], "cannot get value");
06779                 }
06780             }
06781         }
06782     }
06783 
06784     SECTION("reverse iterator comparisons")
06785     {
06786         json j_values = {nullptr, true, 42, 42u, 23.23, {{"one", 1}, {"two", 2}}, {1, 2, 3, 4, 5}, "Hello, world"};
06787 
06788         for (json& j : j_values)
06789         {
06790             auto it1 = j.rbegin();
06791             auto it2 = j.rbegin();
06792             auto it3 = j.rbegin();
06793             ++it2;
06794             ++it3;
06795             ++it3;
06796             auto it1_c = j.crbegin();
06797             auto it2_c = j.crbegin();
06798             auto it3_c = j.crbegin();
06799             ++it2_c;
06800             ++it3_c;
06801             ++it3_c;
06802 
06803             // comparison: equal
06804             {
06805                 CHECK(it1 == it1);
06806                 CHECK(not (it1 == it2));
06807                 CHECK(not (it1 == it3));
06808                 CHECK(not (it2 == it3));
06809                 CHECK(it1_c == it1_c);
06810                 CHECK(not (it1_c == it2_c));
06811                 CHECK(not (it1_c == it3_c));
06812                 CHECK(not (it2_c == it3_c));
06813             }
06814 
06815             // comparison: not equal
06816             {
06817                 // check definition
06818                 CHECK( (it1 != it1) == not(it1 == it1) );
06819                 CHECK( (it1 != it2) == not(it1 == it2) );
06820                 CHECK( (it1 != it3) == not(it1 == it3) );
06821                 CHECK( (it2 != it3) == not(it2 == it3) );
06822                 CHECK( (it1_c != it1_c) == not(it1_c == it1_c) );
06823                 CHECK( (it1_c != it2_c) == not(it1_c == it2_c) );
06824                 CHECK( (it1_c != it3_c) == not(it1_c == it3_c) );
06825                 CHECK( (it2_c != it3_c) == not(it2_c == it3_c) );
06826             }
06827 
06828             // comparison: smaller
06829             {
06830                 if (j.type() == json::value_t::object)
06831                 {
06832                     CHECK_THROWS_AS(it1 < it1, std::domain_error);
06833                     CHECK_THROWS_AS(it1 < it2, std::domain_error);
06834                     CHECK_THROWS_AS(it2 < it3, std::domain_error);
06835                     CHECK_THROWS_AS(it1 < it3, std::domain_error);
06836                     CHECK_THROWS_AS(it1_c < it1_c, std::domain_error);
06837                     CHECK_THROWS_AS(it1_c < it2_c, std::domain_error);
06838                     CHECK_THROWS_AS(it2_c < it3_c, std::domain_error);
06839                     CHECK_THROWS_AS(it1_c < it3_c, std::domain_error);
06840                     CHECK_THROWS_WITH(it1 < it1, "cannot compare order of object iterators");
06841                     CHECK_THROWS_WITH(it1 < it2, "cannot compare order of object iterators");
06842                     CHECK_THROWS_WITH(it2 < it3, "cannot compare order of object iterators");
06843                     CHECK_THROWS_WITH(it1 < it3, "cannot compare order of object iterators");
06844                     CHECK_THROWS_WITH(it1_c < it1_c, "cannot compare order of object iterators");
06845                     CHECK_THROWS_WITH(it1_c < it2_c, "cannot compare order of object iterators");
06846                     CHECK_THROWS_WITH(it2_c < it3_c, "cannot compare order of object iterators");
06847                     CHECK_THROWS_WITH(it1_c < it3_c, "cannot compare order of object iterators");
06848                 }
06849                 else
06850                 {
06851                     CHECK(not (it1 < it1));
06852                     CHECK(it1 < it2);
06853                     CHECK(it1 < it3);
06854                     CHECK(it2 < it3);
06855                     CHECK(not (it1_c < it1_c));
06856                     CHECK(it1_c < it2_c);
06857                     CHECK(it1_c < it3_c);
06858                     CHECK(it2_c < it3_c);
06859                 }
06860             }
06861 
06862             // comparison: less than or equal
06863             {
06864                 if (j.type() == json::value_t::object)
06865                 {
06866                     CHECK_THROWS_AS(it1 <= it1, std::domain_error);
06867                     CHECK_THROWS_AS(it1 <= it2, std::domain_error);
06868                     CHECK_THROWS_AS(it2 <= it3, std::domain_error);
06869                     CHECK_THROWS_AS(it1 <= it3, std::domain_error);
06870                     CHECK_THROWS_AS(it1_c <= it1_c, std::domain_error);
06871                     CHECK_THROWS_AS(it1_c <= it2_c, std::domain_error);
06872                     CHECK_THROWS_AS(it2_c <= it3_c, std::domain_error);
06873                     CHECK_THROWS_AS(it1_c <= it3_c, std::domain_error);
06874                     CHECK_THROWS_WITH(it1 <= it1, "cannot compare order of object iterators");
06875                     CHECK_THROWS_WITH(it1 <= it2, "cannot compare order of object iterators");
06876                     CHECK_THROWS_WITH(it2 <= it3, "cannot compare order of object iterators");
06877                     CHECK_THROWS_WITH(it1 <= it3, "cannot compare order of object iterators");
06878                     CHECK_THROWS_WITH(it1_c <= it1_c, "cannot compare order of object iterators");
06879                     CHECK_THROWS_WITH(it1_c <= it2_c, "cannot compare order of object iterators");
06880                     CHECK_THROWS_WITH(it2_c <= it3_c, "cannot compare order of object iterators");
06881                     CHECK_THROWS_WITH(it1_c <= it3_c, "cannot compare order of object iterators");
06882                 }
06883                 else
06884                 {
06885                     // check definition
06886                     CHECK( (it1 <= it1) == not(it1 < it1) );
06887                     CHECK( (it1 <= it2) == not(it2 < it1) );
06888                     CHECK( (it1 <= it3) == not(it3 < it1) );
06889                     CHECK( (it2 <= it3) == not(it3 < it2) );
06890                     CHECK( (it1_c <= it1_c) == not(it1_c < it1_c) );
06891                     CHECK( (it1_c <= it2_c) == not(it2_c < it1_c) );
06892                     CHECK( (it1_c <= it3_c) == not(it3_c < it1_c) );
06893                     CHECK( (it2_c <= it3_c) == not(it3_c < it2_c) );
06894                 }
06895             }
06896 
06897             // comparison: greater than
06898             {
06899                 if (j.type() == json::value_t::object)
06900                 {
06901                     CHECK_THROWS_AS(it1 > it1, std::domain_error);
06902                     CHECK_THROWS_AS(it1 > it2, std::domain_error);
06903                     CHECK_THROWS_AS(it2 > it3, std::domain_error);
06904                     CHECK_THROWS_AS(it1 > it3, std::domain_error);
06905                     CHECK_THROWS_AS(it1_c > it1_c, std::domain_error);
06906                     CHECK_THROWS_AS(it1_c > it2_c, std::domain_error);
06907                     CHECK_THROWS_AS(it2_c > it3_c, std::domain_error);
06908                     CHECK_THROWS_AS(it1_c > it3_c, std::domain_error);
06909                     CHECK_THROWS_WITH(it1 > it1, "cannot compare order of object iterators");
06910                     CHECK_THROWS_WITH(it1 > it2, "cannot compare order of object iterators");
06911                     CHECK_THROWS_WITH(it2 > it3, "cannot compare order of object iterators");
06912                     CHECK_THROWS_WITH(it1 > it3, "cannot compare order of object iterators");
06913                     CHECK_THROWS_WITH(it1_c > it1_c, "cannot compare order of object iterators");
06914                     CHECK_THROWS_WITH(it1_c > it2_c, "cannot compare order of object iterators");
06915                     CHECK_THROWS_WITH(it2_c > it3_c, "cannot compare order of object iterators");
06916                     CHECK_THROWS_WITH(it1_c > it3_c, "cannot compare order of object iterators");
06917                 }
06918                 else
06919                 {
06920                     // check definition
06921                     CHECK( (it1 > it1) == (it1 < it1) );
06922                     CHECK( (it1 > it2) == (it2 < it1) );
06923                     CHECK( (it1 > it3) == (it3 < it1) );
06924                     CHECK( (it2 > it3) == (it3 < it2) );
06925                     CHECK( (it1_c > it1_c) == (it1_c < it1_c) );
06926                     CHECK( (it1_c > it2_c) == (it2_c < it1_c) );
06927                     CHECK( (it1_c > it3_c) == (it3_c < it1_c) );
06928                     CHECK( (it2_c > it3_c) == (it3_c < it2_c) );
06929                 }
06930             }
06931 
06932             // comparison: greater than or equal
06933             {
06934                 if (j.type() == json::value_t::object)
06935                 {
06936                     CHECK_THROWS_AS(it1 >= it1, std::domain_error);
06937                     CHECK_THROWS_AS(it1 >= it2, std::domain_error);
06938                     CHECK_THROWS_AS(it2 >= it3, std::domain_error);
06939                     CHECK_THROWS_AS(it1 >= it3, std::domain_error);
06940                     CHECK_THROWS_AS(it1_c >= it1_c, std::domain_error);
06941                     CHECK_THROWS_AS(it1_c >= it2_c, std::domain_error);
06942                     CHECK_THROWS_AS(it2_c >= it3_c, std::domain_error);
06943                     CHECK_THROWS_AS(it1_c >= it3_c, std::domain_error);
06944                     CHECK_THROWS_WITH(it1 >= it1, "cannot compare order of object iterators");
06945                     CHECK_THROWS_WITH(it1 >= it2, "cannot compare order of object iterators");
06946                     CHECK_THROWS_WITH(it2 >= it3, "cannot compare order of object iterators");
06947                     CHECK_THROWS_WITH(it1 >= it3, "cannot compare order of object iterators");
06948                     CHECK_THROWS_WITH(it1_c >= it1_c, "cannot compare order of object iterators");
06949                     CHECK_THROWS_WITH(it1_c >= it2_c, "cannot compare order of object iterators");
06950                     CHECK_THROWS_WITH(it2_c >= it3_c, "cannot compare order of object iterators");
06951                     CHECK_THROWS_WITH(it1_c >= it3_c, "cannot compare order of object iterators");
06952                 }
06953                 else
06954                 {
06955                     // check definition
06956                     CHECK( (it1 >= it1) == not(it1 < it1) );
06957                     CHECK( (it1 >= it2) == not(it1 < it2) );
06958                     CHECK( (it1 >= it3) == not(it1 < it3) );
06959                     CHECK( (it2 >= it3) == not(it2 < it3) );
06960                     CHECK( (it1_c >= it1_c) == not(it1_c < it1_c) );
06961                     CHECK( (it1_c >= it2_c) == not(it1_c < it2_c) );
06962                     CHECK( (it1_c >= it3_c) == not(it1_c < it3_c) );
06963                     CHECK( (it2_c >= it3_c) == not(it2_c < it3_c) );
06964                 }
06965             }
06966         }
06967 
06968         // check exceptions if different objects are compared
06969         for (auto j : j_values)
06970         {
06971             for (auto k : j_values)
06972             {
06973                 if (j != k)
06974                 {
06975                     CHECK_THROWS_AS(j.rbegin() == k.rbegin(), std::domain_error);
06976                     CHECK_THROWS_AS(j.crbegin() == k.crbegin(), std::domain_error);
06977                     CHECK_THROWS_WITH(j.rbegin() == k.rbegin(), "cannot compare iterators of different containers");
06978                     CHECK_THROWS_WITH(j.crbegin() == k.crbegin(), "cannot compare iterators of different containers");
06979 
06980                     CHECK_THROWS_AS(j.rbegin() < k.rbegin(), std::domain_error);
06981                     CHECK_THROWS_AS(j.crbegin() < k.crbegin(), std::domain_error);
06982                     CHECK_THROWS_WITH(j.rbegin() < k.rbegin(), "cannot compare iterators of different containers");
06983                     CHECK_THROWS_WITH(j.crbegin() < k.crbegin(), "cannot compare iterators of different containers");
06984                 }
06985             }
06986         }
06987     }
06988 
06989     SECTION("reverse iterator arithmetic")
06990     {
06991         json j_object = {{"one", 1}, {"two", 2}, {"three", 3}};
06992         json j_array = {1, 2, 3, 4, 5, 6};
06993         json j_null = nullptr;
06994         json j_value = 42;
06995 
06996         SECTION("addition and subtraction")
06997         {
06998             SECTION("object")
06999             {
07000                 {
07001                     auto it = j_object.rbegin();
07002                     CHECK_THROWS_AS(it += 1, std::domain_error);
07003                     CHECK_THROWS_WITH(it += 1, "cannot use offsets with object iterators");
07004                 }
07005                 {
07006                     auto it = j_object.crbegin();
07007                     CHECK_THROWS_AS(it += 1, std::domain_error);
07008                     CHECK_THROWS_WITH(it += 1, "cannot use offsets with object iterators");
07009                 }
07010                 {
07011                     auto it = j_object.rbegin();
07012                     CHECK_THROWS_AS(it + 1, std::domain_error);
07013                     CHECK_THROWS_WITH(it + 1, "cannot use offsets with object iterators");
07014                 }
07015                 {
07016                     auto it = j_object.crbegin();
07017                     CHECK_THROWS_AS(it + 1, std::domain_error);
07018                     CHECK_THROWS_WITH(it + 1, "cannot use offsets with object iterators");
07019                 }
07020                 {
07021                     auto it = j_object.rbegin();
07022                     CHECK_THROWS_AS(it -= 1, std::domain_error);
07023                     CHECK_THROWS_WITH(it -= 1, "cannot use offsets with object iterators");
07024                 }
07025                 {
07026                     auto it = j_object.crbegin();
07027                     CHECK_THROWS_AS(it -= 1, std::domain_error);
07028                     CHECK_THROWS_WITH(it -= 1, "cannot use offsets with object iterators");
07029                 }
07030                 {
07031                     auto it = j_object.rbegin();
07032                     CHECK_THROWS_AS(it - 1, std::domain_error);
07033                     CHECK_THROWS_WITH(it - 1, "cannot use offsets with object iterators");
07034                 }
07035                 {
07036                     auto it = j_object.crbegin();
07037                     CHECK_THROWS_AS(it - 1, std::domain_error);
07038                     CHECK_THROWS_WITH(it - 1, "cannot use offsets with object iterators");
07039                 }
07040                 {
07041                     auto it = j_object.rbegin();
07042                     CHECK_THROWS_AS(it - it, std::domain_error);
07043                     CHECK_THROWS_WITH(it - it, "cannot use offsets with object iterators");
07044                 }
07045                 {
07046                     auto it = j_object.crbegin();
07047                     CHECK_THROWS_AS(it - it, std::domain_error);
07048                     CHECK_THROWS_WITH(it - it, "cannot use offsets with object iterators");
07049                 }
07050             }
07051 
07052             SECTION("array")
07053             {
07054                 {
07055                     auto it = j_array.rbegin();
07056                     it += 3;
07057                     CHECK((j_array.rbegin() + 3) == it);
07058                     CHECK((it - 3) == j_array.rbegin());
07059                     CHECK((j_array.rbegin() - it) == 3);
07060                     CHECK(*it == json(3));
07061                     it -= 2;
07062                     CHECK(*it == json(5));
07063                 }
07064                 {
07065                     auto it = j_array.crbegin();
07066                     it += 3;
07067                     CHECK((j_array.crbegin() + 3) == it);
07068                     CHECK((it - 3) == j_array.crbegin());
07069                     CHECK((j_array.crbegin() - it) == 3);
07070                     CHECK(*it == json(3));
07071                     it -= 2;
07072                     CHECK(*it == json(5));
07073                 }
07074             }
07075 
07076             SECTION("null")
07077             {
07078                 {
07079                     auto it = j_null.rbegin();
07080                     it += 3;
07081                     CHECK((j_null.rbegin() + 3) == it);
07082                     CHECK((it - 3) == j_null.rbegin());
07083                     CHECK((j_null.rbegin() - it) == 3);
07084                     CHECK(it != j_null.rend());
07085                     it -= 3;
07086                     CHECK(it == j_null.rend());
07087                 }
07088                 {
07089                     auto it = j_null.crbegin();
07090                     it += 3;
07091                     CHECK((j_null.crbegin() + 3) == it);
07092                     CHECK((it - 3) == j_null.crbegin());
07093                     CHECK((j_null.crbegin() - it) == 3);
07094                     CHECK(it != j_null.crend());
07095                     it -= 3;
07096                     CHECK(it == j_null.crend());
07097                 }
07098             }
07099 
07100             SECTION("value")
07101             {
07102                 {
07103                     auto it = j_value.rbegin();
07104                     it += 3;
07105                     CHECK((j_value.rbegin() + 3) == it);
07106                     CHECK((it - 3) == j_value.rbegin());
07107                     CHECK((j_value.rbegin() - it) == 3);
07108                     CHECK(it != j_value.rend());
07109                     it -= 3;
07110                     CHECK(*it == json(42));
07111                 }
07112                 {
07113                     auto it = j_value.crbegin();
07114                     it += 3;
07115                     CHECK((j_value.crbegin() + 3) == it);
07116                     CHECK((it - 3) == j_value.crbegin());
07117                     CHECK((j_value.crbegin() - it) == 3);
07118                     CHECK(it != j_value.crend());
07119                     it -= 3;
07120                     CHECK(*it == json(42));
07121                 }
07122             }
07123         }
07124 
07125         SECTION("subscript operator")
07126         {
07127             SECTION("object")
07128             {
07129                 {
07130                     auto it = j_object.rbegin();
07131                     CHECK_THROWS_AS(it[0], std::domain_error);
07132                     CHECK_THROWS_AS(it[1], std::domain_error);
07133                     CHECK_THROWS_WITH(it[0], "cannot use offsets with object iterators");
07134                     CHECK_THROWS_WITH(it[1], "cannot use offsets with object iterators");
07135                 }
07136                 {
07137                     auto it = j_object.crbegin();
07138                     CHECK_THROWS_AS(it[0], std::domain_error);
07139                     CHECK_THROWS_AS(it[1], std::domain_error);
07140                     CHECK_THROWS_WITH(it[0], "cannot use offsets with object iterators");
07141                     CHECK_THROWS_WITH(it[1], "cannot use offsets with object iterators");
07142                 }
07143             }
07144 
07145             SECTION("array")
07146             {
07147                 {
07148                     auto it = j_array.rbegin();
07149                     CHECK(it[0] == json(6));
07150                     CHECK(it[1] == json(5));
07151                     CHECK(it[2] == json(4));
07152                     CHECK(it[3] == json(3));
07153                     CHECK(it[4] == json(2));
07154                     CHECK(it[5] == json(1));
07155                 }
07156                 {
07157                     auto it = j_array.crbegin();
07158                     CHECK(it[0] == json(6));
07159                     CHECK(it[1] == json(5));
07160                     CHECK(it[2] == json(4));
07161                     CHECK(it[3] == json(3));
07162                     CHECK(it[4] == json(2));
07163                     CHECK(it[5] == json(1));
07164                 }
07165             }
07166 
07167             SECTION("null")
07168             {
07169                 {
07170                     auto it = j_null.rbegin();
07171                     CHECK_THROWS_AS(it[0], std::out_of_range);
07172                     CHECK_THROWS_AS(it[1], std::out_of_range);
07173                     CHECK_THROWS_WITH(it[0], "cannot get value");
07174                     CHECK_THROWS_WITH(it[1], "cannot get value");
07175                 }
07176                 {
07177                     auto it = j_null.crbegin();
07178                     CHECK_THROWS_AS(it[0], std::out_of_range);
07179                     CHECK_THROWS_AS(it[1], std::out_of_range);
07180                     CHECK_THROWS_WITH(it[0], "cannot get value");
07181                     CHECK_THROWS_WITH(it[1], "cannot get value");
07182                 }
07183             }
07184 
07185             SECTION("value")
07186             {
07187                 {
07188                     auto it = j_value.rbegin();
07189                     CHECK(it[0] == json(42));
07190                     CHECK_THROWS_AS(it[1], std::out_of_range);
07191                     CHECK_THROWS_WITH(it[1], "cannot get value");
07192                 }
07193                 {
07194                     auto it = j_value.crbegin();
07195                     CHECK(it[0] == json(42));
07196                     CHECK_THROWS_AS(it[1], std::out_of_range);
07197                     CHECK_THROWS_WITH(it[1], "cannot get value");
07198                 }
07199             }
07200         }
07201     }
07202 }
07203 
07204 TEST_CASE("capacity")
07205 {
07206     SECTION("empty()")
07207     {
07208         SECTION("boolean")
07209         {
07210             json j = true;
07211             json j_const(j);
07212 
07213             SECTION("result of empty")
07214             {
07215                 CHECK(j.empty() == false);
07216                 CHECK(j_const.empty() == false);
07217             }
07218 
07219             SECTION("definition of empty")
07220             {
07221                 CHECK(j.begin() != j.end());
07222                 CHECK(j_const.begin() != j_const.end());
07223             }
07224         }
07225 
07226         SECTION("string")
07227         {
07228             json j = "hello world";
07229             json j_const(j);
07230 
07231             SECTION("result of empty")
07232             {
07233                 CHECK(j.empty() == false);
07234                 CHECK(j_const.empty() == false);
07235             }
07236 
07237             SECTION("definition of empty")
07238             {
07239                 CHECK(j.begin() != j.end());
07240                 CHECK(j_const.begin() != j_const.end());
07241             }
07242         }
07243 
07244         SECTION("array")
07245         {
07246             SECTION("empty array")
07247             {
07248                 json j = json::array();
07249                 json j_const(j);
07250 
07251                 SECTION("result of empty")
07252                 {
07253                     CHECK(j.empty() == true);
07254                     CHECK(j_const.empty() == true);
07255                 }
07256 
07257                 SECTION("definition of empty")
07258                 {
07259                     CHECK(j.begin() == j.end());
07260                     CHECK(j_const.begin() == j_const.end());
07261                 }
07262             }
07263 
07264             SECTION("filled array")
07265             {
07266                 json j = {1, 2, 3};
07267                 json j_const(j);
07268 
07269                 SECTION("result of empty")
07270                 {
07271                     CHECK(j.empty() == false);
07272                     CHECK(j_const.empty() == false);
07273                 }
07274 
07275                 SECTION("definition of empty")
07276                 {
07277                     CHECK(j.begin() != j.end());
07278                     CHECK(j_const.begin() != j_const.end());
07279                 }
07280             }
07281         }
07282 
07283         SECTION("object")
07284         {
07285             SECTION("empty object")
07286             {
07287                 json j = json::object();
07288                 json j_const(j);
07289 
07290                 SECTION("result of empty")
07291                 {
07292                     CHECK(j.empty() == true);
07293                     CHECK(j_const.empty() == true);
07294                 }
07295 
07296                 SECTION("definition of empty")
07297                 {
07298                     CHECK(j.begin() == j.end());
07299                     CHECK(j_const.begin() == j_const.end());
07300                 }
07301             }
07302 
07303             SECTION("filled object")
07304             {
07305                 json j = {{"one", 1}, {"two", 2}, {"three", 3}};
07306                 json j_const(j);
07307 
07308                 SECTION("result of empty")
07309                 {
07310                     CHECK(j.empty() == false);
07311                     CHECK(j_const.empty() == false);
07312                 }
07313 
07314                 SECTION("definition of empty")
07315                 {
07316                     CHECK(j.begin() != j.end());
07317                     CHECK(j_const.begin() != j_const.end());
07318                 }
07319             }
07320         }
07321 
07322         SECTION("number (integer)")
07323         {
07324             json j = 23;
07325             json j_const(j);
07326 
07327             SECTION("result of empty")
07328             {
07329                 CHECK(j.empty() == false);
07330                 CHECK(j_const.empty() == false);
07331             }
07332 
07333             SECTION("definition of empty")
07334             {
07335                 CHECK(j.begin() != j.end());
07336                 CHECK(j_const.begin() != j_const.end());
07337             }
07338         }
07339 
07340         SECTION("number (unsigned)")
07341         {
07342             json j = 23u;
07343             json j_const(j);
07344 
07345             SECTION("result of empty")
07346             {
07347                 CHECK(j.empty() == false);
07348                 CHECK(j_const.empty() == false);
07349             }
07350 
07351             SECTION("definition of empty")
07352             {
07353                 CHECK(j.begin() != j.end());
07354                 CHECK(j_const.begin() != j_const.end());
07355             }
07356         }
07357 
07358         SECTION("number (float)")
07359         {
07360             json j = 23.42;
07361             json j_const(j);
07362 
07363             SECTION("result of empty")
07364             {
07365                 CHECK(j.empty() == false);
07366                 CHECK(j_const.empty() == false);
07367             }
07368 
07369             SECTION("definition of empty")
07370             {
07371                 CHECK(j.begin() != j.end());
07372                 CHECK(j_const.begin() != j_const.end());
07373             }
07374         }
07375 
07376         SECTION("null")
07377         {
07378             json j = nullptr;
07379             json j_const(j);
07380 
07381             SECTION("result of empty")
07382             {
07383                 CHECK(j.empty() == true);
07384                 CHECK(j_const.empty() == true);
07385             }
07386 
07387             SECTION("definition of empty")
07388             {
07389                 CHECK(j.begin() == j.end());
07390                 CHECK(j_const.begin() == j_const.end());
07391             }
07392         }
07393     }
07394 
07395     SECTION("size()")
07396     {
07397         SECTION("boolean")
07398         {
07399             json j = true;
07400             json j_const(j);
07401 
07402             SECTION("result of size")
07403             {
07404                 CHECK(j.size() == 1);
07405                 CHECK(j_const.size() == 1);
07406             }
07407 
07408             SECTION("definition of size")
07409             {
07410                 CHECK(std::distance(j.begin(), j.end()) == j.size());
07411                 CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
07412                 CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
07413                 CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
07414             }
07415         }
07416 
07417         SECTION("string")
07418         {
07419             json j = "hello world";
07420             json j_const(j);
07421 
07422             SECTION("result of size")
07423             {
07424                 CHECK(j.size() == 1);
07425                 CHECK(j_const.size() == 1);
07426             }
07427 
07428             SECTION("definition of size")
07429             {
07430                 CHECK(std::distance(j.begin(), j.end()) == j.size());
07431                 CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
07432                 CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
07433                 CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
07434             }
07435         }
07436 
07437         SECTION("array")
07438         {
07439             SECTION("empty array")
07440             {
07441                 json j = json::array();
07442                 json j_const(j);
07443 
07444                 SECTION("result of size")
07445                 {
07446                     CHECK(j.size() == 0);
07447                     CHECK(j_const.size() == 0);
07448                 }
07449 
07450                 SECTION("definition of size")
07451                 {
07452                     CHECK(std::distance(j.begin(), j.end()) == j.size());
07453                     CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
07454                     CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
07455                     CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
07456                 }
07457             }
07458 
07459             SECTION("filled array")
07460             {
07461                 json j = {1, 2, 3};
07462                 json j_const(j);
07463 
07464                 SECTION("result of size")
07465                 {
07466                     CHECK(j.size() == 3);
07467                     CHECK(j_const.size() == 3);
07468                 }
07469 
07470                 SECTION("definition of size")
07471                 {
07472                     CHECK(std::distance(j.begin(), j.end()) == j.size());
07473                     CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
07474                     CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
07475                     CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
07476                 }
07477             }
07478         }
07479 
07480         SECTION("object")
07481         {
07482             SECTION("empty object")
07483             {
07484                 json j = json::object();
07485                 json j_const(j);
07486 
07487                 SECTION("result of size")
07488                 {
07489                     CHECK(j.size() == 0);
07490                     CHECK(j_const.size() == 0);
07491                 }
07492 
07493                 SECTION("definition of size")
07494                 {
07495                     CHECK(std::distance(j.begin(), j.end()) == j.size());
07496                     CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
07497                     CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
07498                     CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
07499                 }
07500             }
07501 
07502             SECTION("filled object")
07503             {
07504                 json j = {{"one", 1}, {"two", 2}, {"three", 3}};
07505                 json j_const(j);
07506 
07507                 SECTION("result of size")
07508                 {
07509                     CHECK(j.size() == 3);
07510                     CHECK(j_const.size() == 3);
07511                 }
07512 
07513                 SECTION("definition of size")
07514                 {
07515                     CHECK(std::distance(j.begin(), j.end()) == j.size());
07516                     CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
07517                     CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
07518                     CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
07519                 }
07520             }
07521         }
07522 
07523         SECTION("number (integer)")
07524         {
07525             json j = 23;
07526             json j_const(j);
07527 
07528             SECTION("result of size")
07529             {
07530                 CHECK(j.size() == 1);
07531                 CHECK(j_const.size() == 1);
07532             }
07533 
07534             SECTION("definition of size")
07535             {
07536                 CHECK(std::distance(j.begin(), j.end()) == j.size());
07537                 CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
07538                 CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
07539                 CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
07540             }
07541         }
07542 
07543         SECTION("number (unsigned)")
07544         {
07545             json j = 23u;
07546             json j_const(j);
07547 
07548             SECTION("result of size")
07549             {
07550                 CHECK(j.size() == 1);
07551                 CHECK(j_const.size() == 1);
07552             }
07553 
07554             SECTION("definition of size")
07555             {
07556                 CHECK(std::distance(j.begin(), j.end()) == j.size());
07557                 CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
07558                 CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
07559                 CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
07560             }
07561         }
07562 
07563         SECTION("number (float)")
07564         {
07565             json j = 23.42;
07566             json j_const(j);
07567 
07568             SECTION("result of size")
07569             {
07570                 CHECK(j.size() == 1);
07571                 CHECK(j_const.size() == 1);
07572             }
07573 
07574             SECTION("definition of size")
07575             {
07576                 CHECK(std::distance(j.begin(), j.end()) == j.size());
07577                 CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
07578                 CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
07579                 CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
07580             }
07581         }
07582 
07583         SECTION("null")
07584         {
07585             json j = nullptr;
07586             json j_const(j);
07587 
07588             SECTION("result of size")
07589             {
07590                 CHECK(j.size() == 0);
07591                 CHECK(j_const.size() == 0);
07592             }
07593 
07594             SECTION("definition of size")
07595             {
07596                 CHECK(std::distance(j.begin(), j.end()) == j.size());
07597                 CHECK(std::distance(j_const.begin(), j_const.end()) == j_const.size());
07598                 CHECK(std::distance(j.rbegin(), j.rend()) == j.size());
07599                 CHECK(std::distance(j_const.crbegin(), j_const.crend()) == j_const.size());
07600             }
07601         }
07602     }
07603 
07604     SECTION("max_size()")
07605     {
07606         SECTION("boolean")
07607         {
07608             json j = true;
07609             json j_const(j);
07610 
07611             SECTION("result of max_size")
07612             {
07613                 CHECK(j.max_size() == 1);
07614                 CHECK(j_const.max_size() == 1);
07615             }
07616         }
07617 
07618         SECTION("string")
07619         {
07620             json j = "hello world";
07621             json j_const(j);
07622 
07623             SECTION("result of max_size")
07624             {
07625                 CHECK(j.max_size() == 1);
07626                 CHECK(j_const.max_size() == 1);
07627             }
07628         }
07629 
07630         SECTION("array")
07631         {
07632             SECTION("empty array")
07633             {
07634                 json j = json::array();
07635                 json j_const(j);
07636 
07637                 SECTION("result of max_size")
07638                 {
07639                     CHECK(j.max_size() >= j.size());
07640                     CHECK(j_const.max_size() >= j_const.size());
07641                 }
07642             }
07643 
07644             SECTION("filled array")
07645             {
07646                 json j = {1, 2, 3};
07647                 json j_const(j);
07648 
07649                 SECTION("result of max_size")
07650                 {
07651                     CHECK(j.max_size() >= j.size());
07652                     CHECK(j_const.max_size() >= j_const.size());
07653                 }
07654             }
07655         }
07656 
07657         SECTION("object")
07658         {
07659             SECTION("empty object")
07660             {
07661                 json j = json::object();
07662                 json j_const(j);
07663 
07664                 SECTION("result of max_size")
07665                 {
07666                     CHECK(j.max_size() >= j.size());
07667                     CHECK(j_const.max_size() >= j_const.size());
07668                 }
07669             }
07670 
07671             SECTION("filled object")
07672             {
07673                 json j = {{"one", 1}, {"two", 2}, {"three", 3}};
07674                 json j_const(j);
07675 
07676                 SECTION("result of max_size")
07677                 {
07678                     CHECK(j.max_size() >= j.size());
07679                     CHECK(j_const.max_size() >= j_const.size());
07680                 }
07681             }
07682         }
07683 
07684         SECTION("number (integer)")
07685         {
07686             json j = 23;
07687             json j_const(j);
07688 
07689             SECTION("result of max_size")
07690             {
07691                 CHECK(j.max_size() == 1);
07692                 CHECK(j_const.max_size() == 1);
07693             }
07694         }
07695 
07696         SECTION("number (unsigned)")
07697         {
07698             json j = 23u;
07699             json j_const(j);
07700 
07701             SECTION("result of max_size")
07702             {
07703                 CHECK(j.max_size() == 1);
07704                 CHECK(j_const.max_size() == 1);
07705             }
07706         }
07707 
07708         SECTION("number (float)")
07709         {
07710             json j = 23.42;
07711             json j_const(j);
07712 
07713             SECTION("result of max_size")
07714             {
07715                 CHECK(j.max_size() == 1);
07716                 CHECK(j_const.max_size() == 1);
07717             }
07718         }
07719 
07720         SECTION("null")
07721         {
07722             json j = nullptr;
07723             json j_const(j);
07724 
07725             SECTION("result of max_size")
07726             {
07727                 CHECK(j.max_size() == 0);
07728                 CHECK(j_const.max_size() == 0);
07729             }
07730         }
07731     }
07732 }
07733 
07734 TEST_CASE("modifiers")
07735 {
07736     SECTION("clear()")
07737     {
07738         SECTION("boolean")
07739         {
07740             json j = true;
07741 
07742             j.clear();
07743             CHECK(j == json(json::value_t::boolean));
07744         }
07745 
07746         SECTION("string")
07747         {
07748             json j = "hello world";
07749 
07750             j.clear();
07751             CHECK(j == json(json::value_t::string));
07752         }
07753 
07754         SECTION("array")
07755         {
07756             SECTION("empty array")
07757             {
07758                 json j = json::array();
07759 
07760                 j.clear();
07761                 CHECK(j.empty());
07762                 CHECK(j == json(json::value_t::array));
07763             }
07764 
07765             SECTION("filled array")
07766             {
07767                 json j = {1, 2, 3};
07768 
07769                 j.clear();
07770                 CHECK(j.empty());
07771                 CHECK(j == json(json::value_t::array));
07772             }
07773         }
07774 
07775         SECTION("object")
07776         {
07777             SECTION("empty object")
07778             {
07779                 json j = json::object();
07780 
07781                 j.clear();
07782                 CHECK(j.empty());
07783                 CHECK(j == json(json::value_t::object));
07784             }
07785 
07786             SECTION("filled object")
07787             {
07788                 json j = {{"one", 1}, {"two", 2}, {"three", 3}};
07789 
07790                 j.clear();
07791                 CHECK(j.empty());
07792                 CHECK(j == json(json::value_t::object));
07793             }
07794         }
07795 
07796         SECTION("number (integer)")
07797         {
07798             json j = 23;
07799 
07800             j.clear();
07801             CHECK(j == json(json::value_t::number_integer));
07802         }
07803 
07804         SECTION("number (unsigned)")
07805         {
07806             json j = 23u;
07807 
07808             j.clear();
07809             CHECK(j == json(json::value_t::number_integer));
07810         }
07811 
07812         SECTION("number (float)")
07813         {
07814             json j = 23.42;
07815 
07816             j.clear();
07817             CHECK(j == json(json::value_t::number_float));
07818         }
07819 
07820         SECTION("null")
07821         {
07822             json j = nullptr;
07823 
07824             j.clear();
07825             CHECK(j == json(json::value_t::null));
07826         }
07827     }
07828 
07829     SECTION("push_back()")
07830     {
07831         SECTION("to array")
07832         {
07833             SECTION("json&&")
07834             {
07835                 SECTION("null")
07836                 {
07837                     json j;
07838                     j.push_back(1);
07839                     j.push_back(2);
07840                     CHECK(j.type() == json::value_t::array);
07841                     CHECK(j == json({1, 2}));
07842                 }
07843 
07844                 SECTION("array")
07845                 {
07846                     json j = {1, 2, 3};
07847                     j.push_back("Hello");
07848                     CHECK(j.type() == json::value_t::array);
07849                     CHECK(j == json({1, 2, 3, "Hello"}));
07850                 }
07851 
07852                 SECTION("other type")
07853                 {
07854                     json j = 1;
07855                     CHECK_THROWS_AS(j.push_back("Hello"), std::domain_error);
07856                     CHECK_THROWS_WITH(j.push_back("Hello"), "cannot use push_back() with number");
07857                 }
07858             }
07859 
07860             SECTION("const json&")
07861             {
07862                 SECTION("null")
07863                 {
07864                     json j;
07865                     json k(1);
07866                     j.push_back(k);
07867                     j.push_back(k);
07868                     CHECK(j.type() == json::value_t::array);
07869                     CHECK(j == json({1, 1}));
07870                 }
07871 
07872                 SECTION("array")
07873                 {
07874                     json j = {1, 2, 3};
07875                     json k("Hello");
07876                     j.push_back(k);
07877                     CHECK(j.type() == json::value_t::array);
07878                     CHECK(j == json({1, 2, 3, "Hello"}));
07879                 }
07880 
07881                 SECTION("other type")
07882                 {
07883                     json j = 1;
07884                     json k("Hello");
07885                     CHECK_THROWS_AS(j.push_back(k), std::domain_error);
07886                     CHECK_THROWS_WITH(j.push_back(k), "cannot use push_back() with number");
07887                 }
07888             }
07889         }
07890 
07891         SECTION("to object")
07892         {
07893             SECTION("null")
07894             {
07895                 json j;
07896                 j.push_back(json::object_t::value_type({"one", 1}));
07897                 j.push_back(json::object_t::value_type({"two", 2}));
07898                 CHECK(j.type() == json::value_t::object);
07899                 CHECK(j.size() == 2);
07900                 CHECK(j["one"] == json(1));
07901                 CHECK(j["two"] == json(2));
07902             }
07903 
07904             SECTION("object")
07905             {
07906                 json j(json::value_t::object);
07907                 j.push_back(json::object_t::value_type({"one", 1}));
07908                 j.push_back(json::object_t::value_type({"two", 2}));
07909                 CHECK(j.size() == 2);
07910                 CHECK(j["one"] == json(1));
07911                 CHECK(j["two"] == json(2));
07912             }
07913 
07914             SECTION("other type")
07915             {
07916                 json j = 1;
07917                 json k("Hello");
07918                 CHECK_THROWS_AS(j.push_back(json::object_t::value_type({"one", 1})), std::domain_error);
07919                 CHECK_THROWS_WITH(j.push_back(json::object_t::value_type({"one", 1})),
07920                                   "cannot use push_back() with number");
07921             }
07922         }
07923 
07924         SECTION("with initializer_list")
07925         {
07926             SECTION("null")
07927             {
07928                 json j;
07929                 j.push_back({"foo", "bar"});
07930                 CHECK(j == json::array({{"foo", "bar"}}));
07931 
07932                 json k;
07933                 k.push_back({1, 2, 3});
07934                 CHECK(k == json::array({{1, 2, 3}}));
07935             }
07936 
07937             SECTION("array")
07938             {
07939                 json j = {1, 2, 3};
07940                 j.push_back({"foo", "bar"});
07941                 CHECK(j == json({1, 2, 3, {"foo", "bar"}}));
07942 
07943                 json k = {1, 2, 3};
07944                 k.push_back({1, 2, 3});
07945                 CHECK(k == json({1, 2, 3, {1, 2, 3}}));
07946             }
07947 
07948             SECTION("object")
07949             {
07950                 json j = {{"key1", 1}};
07951                 j.push_back({"key2", "bar"});
07952                 CHECK(j == json({{"key1", 1}, {"key2", "bar"}}));
07953 
07954                 json k = {{"key1", 1}};
07955                 CHECK_THROWS_AS(k.push_back({1, 2, 3, 4}), std::domain_error);
07956                 CHECK_THROWS_WITH(k.push_back({1, 2, 3, 4}), "cannot use push_back() with object");
07957             }
07958         }
07959     }
07960 
07961     SECTION("operator+=")
07962     {
07963         SECTION("to array")
07964         {
07965             SECTION("json&&")
07966             {
07967                 SECTION("null")
07968                 {
07969                     json j;
07970                     j += 1;
07971                     j += 2;
07972                     CHECK(j.type() == json::value_t::array);
07973                     CHECK(j == json({1, 2}));
07974                 }
07975 
07976                 SECTION("array")
07977                 {
07978                     json j = {1, 2, 3};
07979                     j += "Hello";
07980                     CHECK(j.type() == json::value_t::array);
07981                     CHECK(j == json({1, 2, 3, "Hello"}));
07982                 }
07983 
07984                 SECTION("other type")
07985                 {
07986                     json j = 1;
07987                     CHECK_THROWS_AS(j += "Hello", std::domain_error);
07988                     CHECK_THROWS_WITH(j += "Hello", "cannot use push_back() with number");
07989                 }
07990             }
07991 
07992             SECTION("const json&")
07993             {
07994                 SECTION("null")
07995                 {
07996                     json j;
07997                     json k(1);
07998                     j += k;
07999                     j += k;
08000                     CHECK(j.type() == json::value_t::array);
08001                     CHECK(j == json({1, 1}));
08002                 }
08003 
08004                 SECTION("array")
08005                 {
08006                     json j = {1, 2, 3};
08007                     json k("Hello");
08008                     j += k;
08009                     CHECK(j.type() == json::value_t::array);
08010                     CHECK(j == json({1, 2, 3, "Hello"}));
08011                 }
08012 
08013                 SECTION("other type")
08014                 {
08015                     json j = 1;
08016                     json k("Hello");
08017                     CHECK_THROWS_AS(j += k, std::domain_error);
08018                     CHECK_THROWS_WITH(j += k, "cannot use push_back() with number");
08019                 }
08020             }
08021         }
08022 
08023         SECTION("to object")
08024         {
08025             SECTION("null")
08026             {
08027                 json j;
08028                 j += json::object_t::value_type({"one", 1});
08029                 j += json::object_t::value_type({"two", 2});
08030                 CHECK(j.type() == json::value_t::object);
08031                 CHECK(j.size() == 2);
08032                 CHECK(j["one"] == json(1));
08033                 CHECK(j["two"] == json(2));
08034             }
08035 
08036             SECTION("object")
08037             {
08038                 json j(json::value_t::object);
08039                 j += json::object_t::value_type({"one", 1});
08040                 j += json::object_t::value_type({"two", 2});
08041                 CHECK(j.size() == 2);
08042                 CHECK(j["one"] == json(1));
08043                 CHECK(j["two"] == json(2));
08044             }
08045 
08046             SECTION("other type")
08047             {
08048                 json j = 1;
08049                 json k("Hello");
08050                 CHECK_THROWS_AS(j += json::object_t::value_type({"one", 1}), std::domain_error);
08051                 CHECK_THROWS_WITH(j += json::object_t::value_type({"one", 1}),
08052                                   "cannot use push_back() with number");
08053             }
08054         }
08055 
08056         SECTION("with initializer_list")
08057         {
08058             SECTION("null")
08059             {
08060                 json j;
08061                 j += {"foo", "bar"};
08062                 CHECK(j == json::array({{"foo", "bar"}}));
08063 
08064                 json k;
08065                 k += {1, 2, 3};
08066                 CHECK(k == json::array({{1, 2, 3}}));
08067             }
08068 
08069             SECTION("array")
08070             {
08071                 json j = {1, 2, 3};
08072                 j += {"foo", "bar"};
08073                 CHECK(j == json({1, 2, 3, {"foo", "bar"}}));
08074 
08075                 json k = {1, 2, 3};
08076                 k += {1, 2, 3};
08077                 CHECK(k == json({1, 2, 3, {1, 2, 3}}));
08078             }
08079 
08080             SECTION("object")
08081             {
08082                 json j = {{"key1", 1}};
08083                 j += {"key2", "bar"};
08084                 CHECK(j == json({{"key1", 1}, {"key2", "bar"}}));
08085 
08086                 json k = {{"key1", 1}};
08087                 CHECK_THROWS_AS((k += {1, 2, 3, 4}), std::domain_error);
08088                 CHECK_THROWS_WITH((k += {1, 2, 3, 4}), "cannot use push_back() with object");
08089             }
08090         }
08091     }
08092 
08093     SECTION("insert")
08094     {
08095         json j_array = {1, 2, 3, 4};
08096         json j_value = 5;
08097 
08098         SECTION("value at position")
08099         {
08100             SECTION("insert before begin()")
08101             {
08102                 auto it = j_array.insert(j_array.begin(), j_value);
08103                 CHECK(j_array.size() == 5);
08104                 CHECK(*it == j_value);
08105                 CHECK(j_array.begin() == it);
08106                 CHECK(j_array == json({5, 1, 2, 3, 4}));
08107             }
08108 
08109             SECTION("insert in the middle")
08110             {
08111                 auto it = j_array.insert(j_array.begin() + 2, j_value);
08112                 CHECK(j_array.size() == 5);
08113                 CHECK(*it == j_value);
08114                 CHECK((it - j_array.begin()) == 2);
08115                 CHECK(j_array == json({1, 2, 5, 3, 4}));
08116             }
08117 
08118             SECTION("insert before end()")
08119             {
08120                 auto it = j_array.insert(j_array.end(), j_value);
08121                 CHECK(j_array.size() == 5);
08122                 CHECK(*it == j_value);
08123                 CHECK((j_array.end() - it) == 1);
08124                 CHECK(j_array == json({1, 2, 3, 4, 5}));
08125             }
08126         }
08127 
08128         SECTION("rvalue at position")
08129         {
08130             SECTION("insert before begin()")
08131             {
08132                 auto it = j_array.insert(j_array.begin(), 5);
08133                 CHECK(j_array.size() == 5);
08134                 CHECK(*it == j_value);
08135                 CHECK(j_array.begin() == it);
08136                 CHECK(j_array == json({5, 1, 2, 3, 4}));
08137             }
08138 
08139             SECTION("insert in the middle")
08140             {
08141                 auto it = j_array.insert(j_array.begin() + 2, 5);
08142                 CHECK(j_array.size() == 5);
08143                 CHECK(*it == j_value);
08144                 CHECK((it - j_array.begin()) == 2);
08145                 CHECK(j_array == json({1, 2, 5, 3, 4}));
08146             }
08147 
08148             SECTION("insert before end()")
08149             {
08150                 auto it = j_array.insert(j_array.end(), 5);
08151                 CHECK(j_array.size() == 5);
08152                 CHECK(*it == j_value);
08153                 CHECK((j_array.end() - it) == 1);
08154                 CHECK(j_array == json({1, 2, 3, 4, 5}));
08155             }
08156         }
08157 
08158         SECTION("copies at position")
08159         {
08160             SECTION("insert before begin()")
08161             {
08162                 auto it = j_array.insert(j_array.begin(), 3, 5);
08163                 CHECK(j_array.size() == 7);
08164                 CHECK(*it == j_value);
08165                 CHECK(j_array.begin() == it);
08166                 CHECK(j_array == json({5, 5, 5, 1, 2, 3, 4}));
08167             }
08168 
08169             SECTION("insert in the middle")
08170             {
08171                 auto it = j_array.insert(j_array.begin() + 2, 3, 5);
08172                 CHECK(j_array.size() == 7);
08173                 CHECK(*it == j_value);
08174                 CHECK((it - j_array.begin()) == 2);
08175                 CHECK(j_array == json({1, 2, 5, 5, 5, 3, 4}));
08176             }
08177 
08178             SECTION("insert before end()")
08179             {
08180                 auto it = j_array.insert(j_array.end(), 3, 5);
08181                 CHECK(j_array.size() == 7);
08182                 CHECK(*it == j_value);
08183                 CHECK((j_array.end() - it) == 3);
08184                 CHECK(j_array == json({1, 2, 3, 4, 5, 5, 5}));
08185             }
08186 
08187             SECTION("insert nothing (count = 0)")
08188             {
08189                 auto pos = j_array.end();
08190                 auto it = j_array.insert(j_array.end(), 0, 5);
08191                 CHECK(j_array.size() == 4);
08192                 CHECK(it == pos);
08193                 CHECK(j_array == json({1, 2, 3, 4}));
08194             }
08195         }
08196 
08197         SECTION("range")
08198         {
08199             json j_other_array = {"first", "second"};
08200 
08201             SECTION("proper usage")
08202             {
08203                 auto it = j_array.insert(j_array.end(), j_other_array.begin(), j_other_array.end());
08204                 CHECK(j_array.size() == 6);
08205                 CHECK(*it == *j_other_array.begin());
08206                 CHECK((j_array.end() - it) == 2);
08207                 CHECK(j_array == json({1, 2, 3, 4, "first", "second"}));
08208             }
08209 
08210             SECTION("empty range")
08211             {
08212                 auto it = j_array.insert(j_array.end(), j_other_array.begin(), j_other_array.begin());
08213                 CHECK(j_array.size() == 4);
08214                 CHECK(it == j_array.end());
08215                 CHECK(j_array == json({1, 2, 3, 4}));
08216             }
08217 
08218             SECTION("invalid iterators")
08219             {
08220                 json j_other_array2 = {"first", "second"};
08221 
08222                 CHECK_THROWS_AS(j_array.insert(j_array.end(), j_array.begin(), j_array.end()), std::domain_error);
08223                 CHECK_THROWS_AS(j_array.insert(j_array.end(), j_other_array.begin(), j_other_array2.end()),
08224                                 std::domain_error);
08225 
08226                 CHECK_THROWS_WITH(j_array.insert(j_array.end(), j_array.begin(), j_array.end()),
08227                                   "passed iterators may not belong to container");
08228                 CHECK_THROWS_WITH(j_array.insert(j_array.end(), j_other_array.begin(), j_other_array2.end()),
08229                                   "iterators do not fit");
08230             }
08231         }
08232 
08233         SECTION("initializer list at position")
08234         {
08235             SECTION("insert before begin()")
08236             {
08237                 auto it = j_array.insert(j_array.begin(), {7, 8, 9});
08238                 CHECK(j_array.size() == 7);
08239                 CHECK(*it == json(7));
08240                 CHECK(j_array.begin() == it);
08241                 CHECK(j_array == json({7, 8, 9, 1, 2, 3, 4}));
08242             }
08243 
08244             SECTION("insert in the middle")
08245             {
08246                 auto it = j_array.insert(j_array.begin() + 2, {7, 8, 9});
08247                 CHECK(j_array.size() == 7);
08248                 CHECK(*it == json(7));
08249                 CHECK((it - j_array.begin()) == 2);
08250                 CHECK(j_array == json({1, 2, 7, 8, 9, 3, 4}));
08251             }
08252 
08253             SECTION("insert before end()")
08254             {
08255                 auto it = j_array.insert(j_array.end(), {7, 8, 9});
08256                 CHECK(j_array.size() == 7);
08257                 CHECK(*it == json(7));
08258                 CHECK((j_array.end() - it) == 3);
08259                 CHECK(j_array == json({1, 2, 3, 4, 7, 8, 9}));
08260             }
08261         }
08262 
08263         SECTION("invalid iterator")
08264         {
08265             // pass iterator to a different array
08266             json j_another_array = {1, 2};
08267             json j_yet_another_array = {"first", "second"};
08268             CHECK_THROWS_AS(j_array.insert(j_another_array.end(), 10), std::domain_error);
08269             CHECK_THROWS_AS(j_array.insert(j_another_array.end(), j_value), std::domain_error);
08270             CHECK_THROWS_AS(j_array.insert(j_another_array.end(), 10, 11), std::domain_error);
08271             CHECK_THROWS_AS(j_array.insert(j_another_array.end(), j_yet_another_array.begin(),
08272                                            j_yet_another_array.end()), std::domain_error);
08273             CHECK_THROWS_AS(j_array.insert(j_another_array.end(), {1, 2, 3, 4}), std::domain_error);
08274 
08275             CHECK_THROWS_WITH(j_array.insert(j_another_array.end(), 10), "iterator does not fit current value");
08276             CHECK_THROWS_WITH(j_array.insert(j_another_array.end(), j_value),
08277                               "iterator does not fit current value");
08278             CHECK_THROWS_WITH(j_array.insert(j_another_array.end(), 10, 11),
08279                               "iterator does not fit current value");
08280             CHECK_THROWS_WITH(j_array.insert(j_another_array.end(), j_yet_another_array.begin(),
08281                                              j_yet_another_array.end()), "iterator does not fit current value");
08282             CHECK_THROWS_WITH(j_array.insert(j_another_array.end(), {1, 2, 3, 4}),
08283                               "iterator does not fit current value");
08284         }
08285 
08286         SECTION("non-array type")
08287         {
08288             // call insert on a non-array type
08289             json j_nonarray = 3;
08290             json j_yet_another_array = {"first", "second"};
08291             CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), 10), std::domain_error);
08292             CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), j_value), std::domain_error);
08293             CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), 10, 11), std::domain_error);
08294             CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), j_yet_another_array.begin(),
08295                                               j_yet_another_array.end()), std::domain_error);
08296             CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), {1, 2, 3, 4}), std::domain_error);
08297 
08298             CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), 10), "cannot use insert() with number");
08299             CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), j_value), "cannot use insert() with number");
08300             CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), 10, 11), "cannot use insert() with number");
08301             CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), j_yet_another_array.begin(),
08302                                                 j_yet_another_array.end()), "cannot use insert() with number");
08303             CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), {1, 2, 3, 4}),
08304                               "cannot use insert() with number");
08305         }
08306     }
08307 
08308     SECTION("swap()")
08309     {
08310         SECTION("json")
08311         {
08312             SECTION("member swap")
08313             {
08314                 json j("hello world");
08315                 json k(42.23);
08316 
08317                 j.swap(k);
08318 
08319                 CHECK(j == json(42.23));
08320                 CHECK(k == json("hello world"));
08321             }
08322 
08323             SECTION("nonmember swap")
08324             {
08325                 json j("hello world");
08326                 json k(42.23);
08327 
08328                 std::swap(j, k);
08329 
08330                 CHECK(j == json(42.23));
08331                 CHECK(k == json("hello world"));
08332             }
08333         }
08334 
08335         SECTION("array_t")
08336         {
08337             SECTION("array_t type")
08338             {
08339                 json j = {1, 2, 3, 4};
08340                 json::array_t a = {"foo", "bar", "baz"};
08341 
08342                 j.swap(a);
08343 
08344                 CHECK(j == json({"foo", "bar", "baz"}));
08345 
08346                 j.swap(a);
08347 
08348                 CHECK(j == json({1, 2, 3, 4}));
08349             }
08350 
08351             SECTION("non-array_t type")
08352             {
08353                 json j = 17;
08354                 json::array_t a = {"foo", "bar", "baz"};
08355 
08356                 CHECK_THROWS_AS(j.swap(a), std::domain_error);
08357                 CHECK_THROWS_WITH(j.swap(a), "cannot use swap() with number");
08358             }
08359         }
08360 
08361         SECTION("object_t")
08362         {
08363             SECTION("object_t type")
08364             {
08365                 json j = {{"one", 1}, {"two", 2}};
08366                 json::object_t o = {{"cow", "Kuh"}, {"chicken", "Huhn"}};
08367 
08368                 j.swap(o);
08369 
08370                 CHECK(j == json({{"cow", "Kuh"}, {"chicken", "Huhn"}}));
08371 
08372                 j.swap(o);
08373 
08374                 CHECK(j == json({{"one", 1}, {"two", 2}}));
08375             }
08376 
08377             SECTION("non-object_t type")
08378             {
08379                 json j = 17;
08380                 json::object_t o = {{"cow", "Kuh"}, {"chicken", "Huhn"}};
08381 
08382                 CHECK_THROWS_AS(j.swap(o), std::domain_error);
08383                 CHECK_THROWS_WITH(j.swap(o), "cannot use swap() with number");
08384             }
08385         }
08386 
08387         SECTION("string_t")
08388         {
08389             SECTION("string_t type")
08390             {
08391                 json j = "Hello world";
08392                 json::string_t s = "Hallo Welt";
08393 
08394                 j.swap(s);
08395 
08396                 CHECK(j == json("Hallo Welt"));
08397 
08398                 j.swap(s);
08399 
08400                 CHECK(j == json("Hello world"));
08401             }
08402 
08403             SECTION("non-string_t type")
08404             {
08405                 json j = 17;
08406                 json::string_t s = "Hallo Welt";
08407 
08408                 CHECK_THROWS_AS(j.swap(s), std::domain_error);
08409                 CHECK_THROWS_WITH(j.swap(s), "cannot use swap() with number");
08410             }
08411         }
08412     }
08413 }
08414 
08415 TEST_CASE("lexicographical comparison operators")
08416 {
08417     SECTION("types")
08418     {
08419         std::vector<json::value_t> j_types =
08420         {
08421             json::value_t::null,
08422             json::value_t::boolean,
08423             json::value_t::number_integer,
08424             json::value_t::number_unsigned,
08425             json::value_t::number_float,
08426             json::value_t::object,
08427             json::value_t::array,
08428             json::value_t::string
08429         };
08430 
08431         SECTION("comparison: less")
08432         {
08433             std::vector<std::vector<bool>> expected =
08434             {
08435                 {false, true, true, true, true, true, true, true},
08436                 {false, false, true, true, true, true, true, true},
08437                 {false, false, false, false, false, true, true, true},
08438                 {false, false, false, false, false, true, true, true},
08439                 {false, false, false, false, false, true, true, true},
08440                 {false, false, false, false, false, false, true, true},
08441                 {false, false, false, false, false, false, false, true},
08442                 {false, false, false, false, false, false, false, false}
08443             };
08444 
08445             for (size_t i = 0; i < j_types.size(); ++i)
08446             {
08447                 for (size_t j = 0; j < j_types.size(); ++j)
08448                 {
08449                     CAPTURE(i);
08450                     CAPTURE(j);
08451                     // check precomputed values
08452                     CHECK(operator<(j_types[i], j_types[j]) == expected[i][j]);
08453                 }
08454             }
08455         }
08456     }
08457 
08458     SECTION("values")
08459     {
08460         json j_values =
08461         {
08462             nullptr, nullptr,
08463             17, 42,
08464             8u, 13u,
08465             3.14159, 23.42,
08466             "foo", "bar",
08467             true, false,
08468             {1, 2, 3}, {"one", "two", "three"},
08469             {{"first", 1}, {"second", 2}}, {{"a", "A"}, {"b", {"B"}}}
08470         };
08471 
08472         SECTION("comparison: equal")
08473         {
08474             std::vector<std::vector<bool>> expected =
08475             {
08476                 {true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false},
08477                 {true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false},
08478                 {false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false},
08479                 {false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false},
08480                 {false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false},
08481                 {false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false},
08482                 {false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false},
08483                 {false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false},
08484                 {false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false},
08485                 {false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false},
08486                 {false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false},
08487                 {false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false},
08488                 {false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false},
08489                 {false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false},
08490                 {false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false},
08491                 {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true}
08492             };
08493 
08494             for (size_t i = 0; i < j_values.size(); ++i)
08495             {
08496                 for (size_t j = 0; j < j_values.size(); ++j)
08497                 {
08498                     CAPTURE(i);
08499                     CAPTURE(j);
08500                     // check precomputed values
08501                     CHECK( (j_values[i] == j_values[j]) == expected[i][j] );
08502                 }
08503             }
08504 
08505             // comparison with discarded elements
08506             json j_discarded(json::value_t::discarded);
08507             for (size_t i = 0; i < j_values.size(); ++i)
08508             {
08509                 CHECK( (j_values[i] == j_discarded) == false);
08510                 CHECK( (j_discarded == j_values[i]) == false);
08511                 CHECK( (j_discarded == j_discarded) == false);
08512             }
08513 
08514             // compare with null pointer
08515             json j_null;
08516             CHECK(j_null == nullptr);
08517             CHECK(nullptr == j_null);
08518         }
08519 
08520         SECTION("comparison: not equal")
08521         {
08522             for (size_t i = 0; i < j_values.size(); ++i)
08523             {
08524                 for (size_t j = 0; j < j_values.size(); ++j)
08525                 {
08526                     CAPTURE(i);
08527                     CAPTURE(j);
08528                     // check definition
08529                     CHECK( (j_values[i] != j_values[j]) == not(j_values[i] == j_values[j]) );
08530                 }
08531             }
08532 
08533             // compare with null pointer
08534             json j_null;
08535             CHECK( (j_null != nullptr) == false);
08536             CHECK( (nullptr != j_null) == false);
08537             CHECK( (j_null != nullptr) == not(j_null == nullptr));
08538             CHECK( (nullptr != j_null) == not(nullptr == j_null));
08539         }
08540 
08541         SECTION("comparison: less")
08542         {
08543             std::vector<std::vector<bool>> expected =
08544             {
08545                 {false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true},
08546                 {false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true},
08547                 {false, false, false, true, false, false, false, true, true, true, false, false, true, true, true, true},
08548                 {false, false, false, false, false, false, false, false, true, true, false, false, true, true, true, true},
08549                 {false, false, true, true, false, true, false, true, true, true, false, false, true, true, true, true},
08550                 {false, false, true, true, false, false, false, true, true, true, false, false, true, true, true, true},
08551                 {false, false, true, true, true, true, false, true, true, true, false, false, true, true, true, true},
08552                 {false, false, false, true, false, false, false, false, true, true, false, false, true, true, true, true},
08553                 {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false},
08554                 {false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false},
08555                 {false, false, true, true, true, true, true, true, true, true, false, false, true, true, true, true},
08556                 {false, false, true, true, true, true, true, true, true, true, true, false, true, true, true, true},
08557                 {false, false, false, false, false, false, false, false, true, true, false, false, false, true, false, false},
08558                 {false, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false},
08559                 {false, false, false, false, false, false, false, false, true, true, false, false, true, true, false, false},
08560                 {false, false, false, false, false, false, false, false, true, true, false, false, true, true, true, false}
08561             };
08562 
08563             for (size_t i = 0; i < j_values.size(); ++i)
08564             {
08565                 for (size_t j = 0; j < j_values.size(); ++j)
08566                 {
08567                     CAPTURE(i);
08568                     CAPTURE(j);
08569                     // check precomputed values
08570                     CHECK( (j_values[i] < j_values[j]) == expected[i][j] );
08571                 }
08572             }
08573 
08574             // comparison with discarded elements
08575             json j_discarded(json::value_t::discarded);
08576             for (size_t i = 0; i < j_values.size(); ++i)
08577             {
08578                 CAPTURE(i);
08579                 CHECK( (j_values[i] < j_discarded) == false);
08580                 CHECK( (j_discarded < j_values[i]) == false);
08581                 CHECK( (j_discarded < j_discarded) == false);
08582             }
08583         }
08584 
08585         SECTION("comparison: less than or equal equal")
08586         {
08587             for (size_t i = 0; i < j_values.size(); ++i)
08588             {
08589                 for (size_t j = 0; j < j_values.size(); ++j)
08590                 {
08591                     CAPTURE(i);
08592                     CAPTURE(j);
08593                     // check definition
08594                     CHECK( (j_values[i] <= j_values[j]) == not(j_values[j] < j_values[i]) );
08595                 }
08596             }
08597         }
08598 
08599         SECTION("comparison: greater than")
08600         {
08601             for (size_t i = 0; i < j_values.size(); ++i)
08602             {
08603                 for (size_t j = 0; j < j_values.size(); ++j)
08604                 {
08605                     CAPTURE(i);
08606                     CAPTURE(j);
08607                     // check definition
08608                     CHECK( (j_values[i] > j_values[j]) == (j_values[j] < j_values[i]) );
08609                 }
08610             }
08611         }
08612 
08613         SECTION("comparison: greater than or equal")
08614         {
08615             for (size_t i = 0; i < j_values.size(); ++i)
08616             {
08617                 for (size_t j = 0; j < j_values.size(); ++j)
08618                 {
08619                     CAPTURE(i);
08620                     CAPTURE(j);
08621                     // check definition
08622                     CHECK( (j_values[i] >= j_values[j]) == not(j_values[i] < j_values[j]) );
08623                 }
08624             }
08625         }
08626     }
08627 }
08628 
08629 TEST_CASE("serialization")
08630 {
08631     SECTION("operator<<")
08632     {
08633         SECTION("no given width")
08634         {
08635             std::stringstream ss;
08636             json j = {"foo", 1, 2, 3, false, {{"one", 1}}};
08637             ss << j;
08638             CHECK(ss.str() == "[\"foo\",1,2,3,false,{\"one\":1}]");
08639         }
08640 
08641         SECTION("given width")
08642         {
08643             std::stringstream ss;
08644             json j = {"foo", 1, 2, 3, false, {{"one", 1}}};
08645             ss << std::setw(4) << j;
08646             CHECK(ss.str() ==
08647                   "[\n    \"foo\",\n    1,\n    2,\n    3,\n    false,\n    {\n        \"one\": 1\n    }\n]");
08648         }
08649     }
08650 
08651     SECTION("operator>>")
08652     {
08653         SECTION("no given width")
08654         {
08655             std::stringstream ss;
08656             json j = {"foo", 1, 2, 3, false, {{"one", 1}}};
08657             j >> ss;
08658             CHECK(ss.str() == "[\"foo\",1,2,3,false,{\"one\":1}]");
08659         }
08660 
08661         SECTION("given width")
08662         {
08663             std::stringstream ss;
08664             json j = {"foo", 1, 2, 3, false, {{"one", 1}}};
08665             ss.width(4);
08666             j >> ss;
08667             CHECK(ss.str() ==
08668                   "[\n    \"foo\",\n    1,\n    2,\n    3,\n    false,\n    {\n        \"one\": 1\n    }\n]");
08669         }
08670     }
08671 }
08672 
08673 TEST_CASE("deserialization")
08674 {
08675     SECTION("stream")
08676     {
08677         std::stringstream ss;
08678         ss << "[\"foo\",1,2,3,false,{\"one\":1}]";
08679         json j = json::parse(ss);
08680         CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
08681     }
08682 
08683     SECTION("string")
08684     {
08685         auto s = "[\"foo\",1,2,3,false,{\"one\":1}]";
08686         json j = json::parse(s);
08687         CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
08688     }
08689 
08690     SECTION("operator<<")
08691     {
08692         std::stringstream ss;
08693         ss << "[\"foo\",1,2,3,false,{\"one\":1}]";
08694         json j;
08695         j << ss;
08696         CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
08697     }
08698 
08699     SECTION("operator>>")
08700     {
08701         std::stringstream ss;
08702         ss << "[\"foo\",1,2,3,false,{\"one\":1}]";
08703         json j;
08704         ss >> j;
08705         CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
08706     }
08707 
08708     SECTION("user-defined string literal")
08709     {
08710         CHECK("[\"foo\",1,2,3,false,{\"one\":1}]"_json == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
08711     }
08712 }
08713 
08714 TEST_CASE("iterator class")
08715 {
08716     SECTION("construction")
08717     {
08718         SECTION("constructor")
08719         {
08720             SECTION("null")
08721             {
08722                 json j(json::value_t::null);
08723                 json::iterator it(&j);
08724             }
08725 
08726             SECTION("object")
08727             {
08728                 json j(json::value_t::object);
08729                 json::iterator it(&j);
08730             }
08731 
08732             SECTION("array")
08733             {
08734                 json j(json::value_t::array);
08735                 json::iterator it(&j);
08736             }
08737         }
08738 
08739         SECTION("copy assignment")
08740         {
08741             json j(json::value_t::null);
08742             json::iterator it(&j);
08743             json::iterator it2(&j);
08744             it2 = it;
08745         }
08746     }
08747 
08748     SECTION("initialization")
08749     {
08750         SECTION("set_begin")
08751         {
08752             SECTION("null")
08753             {
08754                 json j(json::value_t::null);
08755                 json::iterator it(&j);
08756                 it.set_begin();
08757                 CHECK(it == j.begin());
08758             }
08759 
08760             SECTION("object")
08761             {
08762                 json j(json::value_t::object);
08763                 json::iterator it(&j);
08764                 it.set_begin();
08765                 CHECK(it == j.begin());
08766             }
08767 
08768             SECTION("array")
08769             {
08770                 json j(json::value_t::array);
08771                 json::iterator it(&j);
08772                 it.set_begin();
08773                 CHECK(it == j.begin());
08774             }
08775         }
08776 
08777         SECTION("set_end")
08778         {
08779             SECTION("null")
08780             {
08781                 json j(json::value_t::null);
08782                 json::iterator it(&j);
08783                 it.set_end();
08784                 CHECK(it == j.end());
08785             }
08786 
08787             SECTION("object")
08788             {
08789                 json j(json::value_t::object);
08790                 json::iterator it(&j);
08791                 it.set_end();
08792                 CHECK(it == j.end());
08793             }
08794 
08795             SECTION("array")
08796             {
08797                 json j(json::value_t::array);
08798                 json::iterator it(&j);
08799                 it.set_end();
08800                 CHECK(it == j.end());
08801             }
08802         }
08803     }
08804 
08805     SECTION("element access")
08806     {
08807         SECTION("operator*")
08808         {
08809             SECTION("null")
08810             {
08811                 json j(json::value_t::null);
08812                 json::iterator it = j.begin();
08813                 CHECK_THROWS_AS(*it, std::out_of_range);
08814                 CHECK_THROWS_WITH(*it, "cannot get value");
08815             }
08816 
08817             SECTION("number")
08818             {
08819                 json j(17);
08820                 json::iterator it = j.begin();
08821                 CHECK(*it == json(17));
08822                 it = j.end();
08823                 CHECK_THROWS_AS(*it, std::out_of_range);
08824                 CHECK_THROWS_WITH(*it, "cannot get value");
08825             }
08826 
08827             SECTION("object")
08828             {
08829                 json j({{"foo", "bar"}});
08830                 json::iterator it = j.begin();
08831                 CHECK(*it == json("bar"));
08832             }
08833 
08834             SECTION("array")
08835             {
08836                 json j({1, 2, 3, 4});
08837                 json::iterator it = j.begin();
08838                 CHECK(*it == json(1));
08839             }
08840         }
08841 
08842         SECTION("operator->")
08843         {
08844             SECTION("null")
08845             {
08846                 json j(json::value_t::null);
08847                 json::iterator it = j.begin();
08848                 CHECK_THROWS_AS(it->type_name(), std::out_of_range);
08849                 CHECK_THROWS_WITH(it->type_name(), "cannot get value");
08850             }
08851 
08852             SECTION("number")
08853             {
08854                 json j(17);
08855                 json::iterator it = j.begin();
08856                 CHECK(it->type_name() == "number");
08857                 it = j.end();
08858                 CHECK_THROWS_AS(it->type_name(), std::out_of_range);
08859                 CHECK_THROWS_WITH(it->type_name(), "cannot get value");
08860             }
08861 
08862             SECTION("object")
08863             {
08864                 json j({{"foo", "bar"}});
08865                 json::iterator it = j.begin();
08866                 CHECK(it->type_name() == "string");
08867             }
08868 
08869             SECTION("array")
08870             {
08871                 json j({1, 2, 3, 4});
08872                 json::iterator it = j.begin();
08873                 CHECK(it->type_name() == "number");
08874             }
08875         }
08876     }
08877 
08878     SECTION("increment/decrement")
08879     {
08880         SECTION("post-increment")
08881         {
08882             SECTION("null")
08883             {
08884                 json j(json::value_t::null);
08885                 json::iterator it = j.begin();
08886                 CHECK(it.m_it.primitive_iterator == 1);
08887                 it++;
08888                 CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
08889             }
08890 
08891             SECTION("number")
08892             {
08893                 json j(17);
08894                 json::iterator it = j.begin();
08895                 CHECK(it.m_it.primitive_iterator == 0);
08896                 it++;
08897                 CHECK(it.m_it.primitive_iterator == 1);
08898                 it++;
08899                 CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
08900             }
08901 
08902             SECTION("object")
08903             {
08904                 json j({{"foo", "bar"}});
08905                 json::iterator it = j.begin();
08906                 CHECK(it.m_it.object_iterator == it.m_object->m_value.object->begin());
08907                 it++;
08908                 CHECK(it.m_it.object_iterator == it.m_object->m_value.object->end());
08909             }
08910 
08911             SECTION("array")
08912             {
08913                 json j({1, 2, 3, 4});
08914                 json::iterator it = j.begin();
08915                 CHECK(it.m_it.array_iterator == it.m_object->m_value.array->begin());
08916                 it++;
08917                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
08918                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
08919                 it++;
08920                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
08921                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
08922                 it++;
08923                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
08924                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
08925                 it++;
08926                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
08927                 CHECK(it.m_it.array_iterator == it.m_object->m_value.array->end());
08928             }
08929         }
08930 
08931         SECTION("pre-increment")
08932         {
08933             SECTION("null")
08934             {
08935                 json j(json::value_t::null);
08936                 json::iterator it = j.begin();
08937                 CHECK(it.m_it.primitive_iterator == 1);
08938                 ++it;
08939                 CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
08940             }
08941 
08942             SECTION("number")
08943             {
08944                 json j(17);
08945                 json::iterator it = j.begin();
08946                 CHECK(it.m_it.primitive_iterator == 0);
08947                 ++it;
08948                 CHECK(it.m_it.primitive_iterator == 1);
08949                 ++it;
08950                 CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
08951             }
08952 
08953             SECTION("object")
08954             {
08955                 json j({{"foo", "bar"}});
08956                 json::iterator it = j.begin();
08957                 CHECK(it.m_it.object_iterator == it.m_object->m_value.object->begin());
08958                 ++it;
08959                 CHECK(it.m_it.object_iterator == it.m_object->m_value.object->end());
08960             }
08961 
08962             SECTION("array")
08963             {
08964                 json j({1, 2, 3, 4});
08965                 json::iterator it = j.begin();
08966                 CHECK(it.m_it.array_iterator == it.m_object->m_value.array->begin());
08967                 ++it;
08968                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
08969                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
08970                 ++it;
08971                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
08972                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
08973                 ++it;
08974                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
08975                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
08976                 ++it;
08977                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
08978                 CHECK(it.m_it.array_iterator == it.m_object->m_value.array->end());
08979             }
08980         }
08981 
08982         SECTION("post-decrement")
08983         {
08984             SECTION("null")
08985             {
08986                 json j(json::value_t::null);
08987                 json::iterator it = j.end();
08988                 CHECK(it.m_it.primitive_iterator == 1);
08989             }
08990 
08991             SECTION("number")
08992             {
08993                 json j(17);
08994                 json::iterator it = j.end();
08995                 CHECK(it.m_it.primitive_iterator == 1);
08996                 it--;
08997                 CHECK(it.m_it.primitive_iterator == 0);
08998                 it--;
08999                 CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
09000             }
09001 
09002             SECTION("object")
09003             {
09004                 json j({{"foo", "bar"}});
09005                 json::iterator it = j.end();
09006                 CHECK(it.m_it.object_iterator == it.m_object->m_value.object->end());
09007                 it--;
09008                 CHECK(it.m_it.object_iterator == it.m_object->m_value.object->begin());
09009             }
09010 
09011             SECTION("array")
09012             {
09013                 json j({1, 2, 3, 4});
09014                 json::iterator it = j.end();
09015                 CHECK(it.m_it.array_iterator == it.m_object->m_value.array->end());
09016                 it--;
09017                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
09018                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09019                 it--;
09020                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
09021                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09022                 it--;
09023                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
09024                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09025                 it--;
09026                 CHECK(it.m_it.array_iterator == it.m_object->m_value.array->begin());
09027                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09028             }
09029         }
09030 
09031         SECTION("pre-decrement")
09032         {
09033             SECTION("null")
09034             {
09035                 json j(json::value_t::null);
09036                 json::iterator it = j.end();
09037                 CHECK(it.m_it.primitive_iterator == 1);
09038             }
09039 
09040             SECTION("number")
09041             {
09042                 json j(17);
09043                 json::iterator it = j.end();
09044                 CHECK(it.m_it.primitive_iterator == 1);
09045                 --it;
09046                 CHECK(it.m_it.primitive_iterator == 0);
09047                 --it;
09048                 CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
09049             }
09050 
09051             SECTION("object")
09052             {
09053                 json j({{"foo", "bar"}});
09054                 json::iterator it = j.end();
09055                 CHECK(it.m_it.object_iterator == it.m_object->m_value.object->end());
09056                 --it;
09057                 CHECK(it.m_it.object_iterator == it.m_object->m_value.object->begin());
09058             }
09059 
09060             SECTION("array")
09061             {
09062                 json j({1, 2, 3, 4});
09063                 json::iterator it = j.end();
09064                 CHECK(it.m_it.array_iterator == it.m_object->m_value.array->end());
09065                 --it;
09066                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
09067                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09068                 --it;
09069                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
09070                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09071                 --it;
09072                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
09073                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09074                 --it;
09075                 CHECK(it.m_it.array_iterator == it.m_object->m_value.array->begin());
09076                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09077             }
09078         }
09079     }
09080 }
09081 
09082 TEST_CASE("const_iterator class")
09083 {
09084     SECTION("construction")
09085     {
09086         SECTION("constructor")
09087         {
09088             SECTION("null")
09089             {
09090                 json j(json::value_t::null);
09091                 json::const_iterator it(&j);
09092             }
09093 
09094             SECTION("object")
09095             {
09096                 json j(json::value_t::object);
09097                 json::const_iterator it(&j);
09098             }
09099 
09100             SECTION("array")
09101             {
09102                 json j(json::value_t::array);
09103                 json::const_iterator it(&j);
09104             }
09105         }
09106 
09107         SECTION("copy assignment")
09108         {
09109             json j(json::value_t::null);
09110             json::const_iterator it(&j);
09111             json::const_iterator it2(&j);
09112             it2 = it;
09113         }
09114     }
09115 
09116     SECTION("initialization")
09117     {
09118         SECTION("set_begin")
09119         {
09120             SECTION("null")
09121             {
09122                 json j(json::value_t::null);
09123                 json::const_iterator it(&j);
09124                 it.set_begin();
09125                 CHECK(it == j.cbegin());
09126             }
09127 
09128             SECTION("object")
09129             {
09130                 json j(json::value_t::object);
09131                 json::const_iterator it(&j);
09132                 it.set_begin();
09133                 CHECK(it == j.cbegin());
09134             }
09135 
09136             SECTION("array")
09137             {
09138                 json j(json::value_t::array);
09139                 json::const_iterator it(&j);
09140                 it.set_begin();
09141                 CHECK(it == j.cbegin());
09142             }
09143         }
09144 
09145         SECTION("set_end")
09146         {
09147             SECTION("null")
09148             {
09149                 json j(json::value_t::null);
09150                 json::const_iterator it(&j);
09151                 it.set_end();
09152                 CHECK(it == j.cend());
09153             }
09154 
09155             SECTION("object")
09156             {
09157                 json j(json::value_t::object);
09158                 json::const_iterator it(&j);
09159                 it.set_end();
09160                 CHECK(it == j.cend());
09161             }
09162 
09163             SECTION("array")
09164             {
09165                 json j(json::value_t::array);
09166                 json::const_iterator it(&j);
09167                 it.set_end();
09168                 CHECK(it == j.cend());
09169             }
09170         }
09171     }
09172 
09173     SECTION("element access")
09174     {
09175         SECTION("operator*")
09176         {
09177             SECTION("null")
09178             {
09179                 json j(json::value_t::null);
09180                 json::const_iterator it = j.cbegin();
09181                 CHECK_THROWS_AS(*it, std::out_of_range);
09182                 CHECK_THROWS_WITH(*it, "cannot get value");
09183             }
09184 
09185             SECTION("number")
09186             {
09187                 json j(17);
09188                 json::const_iterator it = j.cbegin();
09189                 CHECK(*it == json(17));
09190                 it = j.cend();
09191                 CHECK_THROWS_AS(*it, std::out_of_range);
09192                 CHECK_THROWS_WITH(*it, "cannot get value");
09193             }
09194 
09195             SECTION("object")
09196             {
09197                 json j({{"foo", "bar"}});
09198                 json::const_iterator it = j.cbegin();
09199                 CHECK(*it == json("bar"));
09200             }
09201 
09202             SECTION("array")
09203             {
09204                 json j({1, 2, 3, 4});
09205                 json::const_iterator it = j.cbegin();
09206                 CHECK(*it == json(1));
09207             }
09208         }
09209 
09210         SECTION("operator->")
09211         {
09212             SECTION("null")
09213             {
09214                 json j(json::value_t::null);
09215                 json::const_iterator it = j.cbegin();
09216                 CHECK_THROWS_AS(it->type_name(), std::out_of_range);
09217                 CHECK_THROWS_WITH(it->type_name(), "cannot get value");
09218             }
09219 
09220             SECTION("number")
09221             {
09222                 json j(17);
09223                 json::const_iterator it = j.cbegin();
09224                 CHECK(it->type_name() == "number");
09225                 it = j.cend();
09226                 CHECK_THROWS_AS(it->type_name(), std::out_of_range);
09227                 CHECK_THROWS_WITH(it->type_name(), "cannot get value");
09228             }
09229 
09230             SECTION("object")
09231             {
09232                 json j({{"foo", "bar"}});
09233                 json::const_iterator it = j.cbegin();
09234                 CHECK(it->type_name() == "string");
09235             }
09236 
09237             SECTION("array")
09238             {
09239                 json j({1, 2, 3, 4});
09240                 json::const_iterator it = j.cbegin();
09241                 CHECK(it->type_name() == "number");
09242             }
09243         }
09244     }
09245 
09246     SECTION("increment/decrement")
09247     {
09248         SECTION("post-increment")
09249         {
09250             SECTION("null")
09251             {
09252                 json j(json::value_t::null);
09253                 json::const_iterator it = j.cbegin();
09254                 CHECK(it.m_it.primitive_iterator == 1);
09255                 it++;
09256                 CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
09257             }
09258 
09259             SECTION("number")
09260             {
09261                 json j(17);
09262                 json::const_iterator it = j.cbegin();
09263                 CHECK(it.m_it.primitive_iterator == 0);
09264                 it++;
09265                 CHECK(it.m_it.primitive_iterator == 1);
09266                 it++;
09267                 CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
09268             }
09269 
09270             SECTION("object")
09271             {
09272                 json j({{"foo", "bar"}});
09273                 json::const_iterator it = j.cbegin();
09274                 CHECK(it.m_it.object_iterator == it.m_object->m_value.object->begin());
09275                 it++;
09276                 CHECK(it.m_it.object_iterator == it.m_object->m_value.object->end());
09277             }
09278 
09279             SECTION("array")
09280             {
09281                 json j({1, 2, 3, 4});
09282                 json::const_iterator it = j.cbegin();
09283                 CHECK(it.m_it.array_iterator == it.m_object->m_value.array->begin());
09284                 it++;
09285                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
09286                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09287                 it++;
09288                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
09289                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09290                 it++;
09291                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
09292                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09293                 it++;
09294                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
09295                 CHECK(it.m_it.array_iterator == it.m_object->m_value.array->end());
09296             }
09297         }
09298 
09299         SECTION("pre-increment")
09300         {
09301             SECTION("null")
09302             {
09303                 json j(json::value_t::null);
09304                 json::const_iterator it = j.cbegin();
09305                 CHECK(it.m_it.primitive_iterator == 1);
09306                 ++it;
09307                 CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
09308             }
09309 
09310             SECTION("number")
09311             {
09312                 json j(17);
09313                 json::const_iterator it = j.cbegin();
09314                 CHECK(it.m_it.primitive_iterator == 0);
09315                 ++it;
09316                 CHECK(it.m_it.primitive_iterator == 1);
09317                 ++it;
09318                 CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
09319             }
09320 
09321             SECTION("object")
09322             {
09323                 json j({{"foo", "bar"}});
09324                 json::const_iterator it = j.cbegin();
09325                 CHECK(it.m_it.object_iterator == it.m_object->m_value.object->begin());
09326                 ++it;
09327                 CHECK(it.m_it.object_iterator == it.m_object->m_value.object->end());
09328             }
09329 
09330             SECTION("array")
09331             {
09332                 json j({1, 2, 3, 4});
09333                 json::const_iterator it = j.cbegin();
09334                 CHECK(it.m_it.array_iterator == it.m_object->m_value.array->begin());
09335                 ++it;
09336                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
09337                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09338                 ++it;
09339                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
09340                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09341                 ++it;
09342                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
09343                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09344                 ++it;
09345                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
09346                 CHECK(it.m_it.array_iterator == it.m_object->m_value.array->end());
09347             }
09348         }
09349 
09350         SECTION("post-decrement")
09351         {
09352             SECTION("null")
09353             {
09354                 json j(json::value_t::null);
09355                 json::const_iterator it = j.cend();
09356                 CHECK(it.m_it.primitive_iterator == 1);
09357             }
09358 
09359             SECTION("number")
09360             {
09361                 json j(17);
09362                 json::const_iterator it = j.cend();
09363                 CHECK(it.m_it.primitive_iterator == 1);
09364                 it--;
09365                 CHECK(it.m_it.primitive_iterator == 0);
09366                 it--;
09367                 CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
09368             }
09369 
09370             SECTION("object")
09371             {
09372                 json j({{"foo", "bar"}});
09373                 json::const_iterator it = j.cend();
09374                 CHECK(it.m_it.object_iterator == it.m_object->m_value.object->end());
09375                 it--;
09376                 CHECK(it.m_it.object_iterator == it.m_object->m_value.object->begin());
09377             }
09378 
09379             SECTION("array")
09380             {
09381                 json j({1, 2, 3, 4});
09382                 json::const_iterator it = j.cend();
09383                 CHECK(it.m_it.array_iterator == it.m_object->m_value.array->end());
09384                 it--;
09385                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
09386                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09387                 it--;
09388                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
09389                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09390                 it--;
09391                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
09392                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09393                 it--;
09394                 CHECK(it.m_it.array_iterator == it.m_object->m_value.array->begin());
09395                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09396             }
09397         }
09398 
09399         SECTION("pre-decrement")
09400         {
09401             SECTION("null")
09402             {
09403                 json j(json::value_t::null);
09404                 json::const_iterator it = j.cend();
09405                 CHECK(it.m_it.primitive_iterator == 1);
09406             }
09407 
09408             SECTION("number")
09409             {
09410                 json j(17);
09411                 json::const_iterator it = j.cend();
09412                 CHECK(it.m_it.primitive_iterator == 1);
09413                 --it;
09414                 CHECK(it.m_it.primitive_iterator == 0);
09415                 --it;
09416                 CHECK((it.m_it.primitive_iterator != 0 and it.m_it.primitive_iterator != 1));
09417             }
09418 
09419             SECTION("object")
09420             {
09421                 json j({{"foo", "bar"}});
09422                 json::const_iterator it = j.cend();
09423                 CHECK(it.m_it.object_iterator == it.m_object->m_value.object->end());
09424                 --it;
09425                 CHECK(it.m_it.object_iterator == it.m_object->m_value.object->begin());
09426             }
09427 
09428             SECTION("array")
09429             {
09430                 json j({1, 2, 3, 4});
09431                 json::const_iterator it = j.cend();
09432                 CHECK(it.m_it.array_iterator == it.m_object->m_value.array->end());
09433                 --it;
09434                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
09435                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09436                 --it;
09437                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
09438                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09439                 --it;
09440                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->begin());
09441                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09442                 --it;
09443                 CHECK(it.m_it.array_iterator == it.m_object->m_value.array->begin());
09444                 CHECK(it.m_it.array_iterator != it.m_object->m_value.array->end());
09445             }
09446         }
09447     }
09448 }
09449 
09450 TEST_CASE("convenience functions")
09451 {
09452     SECTION("type name as string")
09453     {
09454         CHECK(json(json::value_t::null).type_name() == "null");
09455         CHECK(json(json::value_t::object).type_name() == "object");
09456         CHECK(json(json::value_t::array).type_name() == "array");
09457         CHECK(json(json::value_t::number_integer).type_name() == "number");
09458         CHECK(json(json::value_t::number_float).type_name() == "number");
09459         CHECK(json(json::value_t::boolean).type_name() == "boolean");
09460         CHECK(json(json::value_t::string).type_name() == "string");
09461         CHECK(json(json::value_t::discarded).type_name() == "discarded");
09462     }
09463 
09464     SECTION("string escape")
09465     {
09466         CHECK(json::escape_string("\"") == "\\\"");
09467         CHECK(json::escape_string("\\") == "\\\\");
09468         CHECK(json::escape_string("\b") == "\\b");
09469         CHECK(json::escape_string("\f") == "\\f");
09470         CHECK(json::escape_string("\n") == "\\n");
09471         CHECK(json::escape_string("\r") == "\\r");
09472         CHECK(json::escape_string("\t") == "\\t");
09473 
09474         CHECK(json::escape_string("\x01") == "\\u0001");
09475         CHECK(json::escape_string("\x02") == "\\u0002");
09476         CHECK(json::escape_string("\x03") == "\\u0003");
09477         CHECK(json::escape_string("\x04") == "\\u0004");
09478         CHECK(json::escape_string("\x05") == "\\u0005");
09479         CHECK(json::escape_string("\x06") == "\\u0006");
09480         CHECK(json::escape_string("\x07") == "\\u0007");
09481         CHECK(json::escape_string("\x08") == "\\b");
09482         CHECK(json::escape_string("\x09") == "\\t");
09483         CHECK(json::escape_string("\x0a") == "\\n");
09484         CHECK(json::escape_string("\x0b") == "\\u000b");
09485         CHECK(json::escape_string("\x0c") == "\\f");
09486         CHECK(json::escape_string("\x0d") == "\\r");
09487         CHECK(json::escape_string("\x0e") == "\\u000e");
09488         CHECK(json::escape_string("\x0f") == "\\u000f");
09489         CHECK(json::escape_string("\x10") == "\\u0010");
09490         CHECK(json::escape_string("\x11") == "\\u0011");
09491         CHECK(json::escape_string("\x12") == "\\u0012");
09492         CHECK(json::escape_string("\x13") == "\\u0013");
09493         CHECK(json::escape_string("\x14") == "\\u0014");
09494         CHECK(json::escape_string("\x15") == "\\u0015");
09495         CHECK(json::escape_string("\x16") == "\\u0016");
09496         CHECK(json::escape_string("\x17") == "\\u0017");
09497         CHECK(json::escape_string("\x18") == "\\u0018");
09498         CHECK(json::escape_string("\x19") == "\\u0019");
09499         CHECK(json::escape_string("\x1a") == "\\u001a");
09500         CHECK(json::escape_string("\x1b") == "\\u001b");
09501         CHECK(json::escape_string("\x1c") == "\\u001c");
09502         CHECK(json::escape_string("\x1d") == "\\u001d");
09503         CHECK(json::escape_string("\x1e") == "\\u001e");
09504         CHECK(json::escape_string("\x1f") == "\\u001f");
09505     }
09506 }
09507 
09508 TEST_CASE("lexer class")
09509 {
09510     SECTION("scan")
09511     {
09512         SECTION("structural characters")
09513         {
09514             CHECK(json::lexer("[").scan() == json::lexer::token_type::begin_array);
09515             CHECK(json::lexer("]").scan() == json::lexer::token_type::end_array);
09516             CHECK(json::lexer("{").scan() == json::lexer::token_type::begin_object);
09517             CHECK(json::lexer("}").scan() == json::lexer::token_type::end_object);
09518             CHECK(json::lexer(",").scan() == json::lexer::token_type::value_separator);
09519             CHECK(json::lexer(":").scan() == json::lexer::token_type::name_separator);
09520         }
09521 
09522         SECTION("literal names")
09523         {
09524             CHECK(json::lexer("null").scan() == json::lexer::token_type::literal_null);
09525             CHECK(json::lexer("true").scan() == json::lexer::token_type::literal_true);
09526             CHECK(json::lexer("false").scan() == json::lexer::token_type::literal_false);
09527         }
09528 
09529         SECTION("numbers")
09530         {
09531             CHECK(json::lexer("0").scan() == json::lexer::token_type::value_number);
09532             CHECK(json::lexer("1").scan() == json::lexer::token_type::value_number);
09533             CHECK(json::lexer("2").scan() == json::lexer::token_type::value_number);
09534             CHECK(json::lexer("3").scan() == json::lexer::token_type::value_number);
09535             CHECK(json::lexer("4").scan() == json::lexer::token_type::value_number);
09536             CHECK(json::lexer("5").scan() == json::lexer::token_type::value_number);
09537             CHECK(json::lexer("6").scan() == json::lexer::token_type::value_number);
09538             CHECK(json::lexer("7").scan() == json::lexer::token_type::value_number);
09539             CHECK(json::lexer("8").scan() == json::lexer::token_type::value_number);
09540             CHECK(json::lexer("9").scan() == json::lexer::token_type::value_number);
09541         }
09542 
09543         SECTION("whitespace")
09544         {
09545             // result is end_of_input, because not token is following
09546             CHECK(json::lexer(" ").scan() == json::lexer::token_type::end_of_input);
09547             CHECK(json::lexer("\t").scan() == json::lexer::token_type::end_of_input);
09548             CHECK(json::lexer("\n").scan() == json::lexer::token_type::end_of_input);
09549             CHECK(json::lexer("\r").scan() == json::lexer::token_type::end_of_input);
09550             CHECK(json::lexer(" \t\n\r\n\t ").scan() == json::lexer::token_type::end_of_input);
09551         }
09552     }
09553 
09554     SECTION("token_type_name")
09555     {
09556         CHECK(json::lexer::token_type_name(json::lexer::token_type::uninitialized) == "<uninitialized>");
09557         CHECK(json::lexer::token_type_name(json::lexer::token_type::literal_true) == "true literal");
09558         CHECK(json::lexer::token_type_name(json::lexer::token_type::literal_false) == "false literal");
09559         CHECK(json::lexer::token_type_name(json::lexer::token_type::literal_null) == "null literal");
09560         CHECK(json::lexer::token_type_name(json::lexer::token_type::value_string) == "string literal");
09561         CHECK(json::lexer::token_type_name(json::lexer::token_type::value_number) == "number literal");
09562         CHECK(json::lexer::token_type_name(json::lexer::token_type::begin_array) == "'['");
09563         CHECK(json::lexer::token_type_name(json::lexer::token_type::begin_object) == "'{'");
09564         CHECK(json::lexer::token_type_name(json::lexer::token_type::end_array) == "']'");
09565         CHECK(json::lexer::token_type_name(json::lexer::token_type::end_object) == "'}'");
09566         CHECK(json::lexer::token_type_name(json::lexer::token_type::name_separator) == "':'");
09567         CHECK(json::lexer::token_type_name(json::lexer::token_type::value_separator) == "','");
09568         CHECK(json::lexer::token_type_name(json::lexer::token_type::parse_error) == "<parse error>");
09569         CHECK(json::lexer::token_type_name(json::lexer::token_type::end_of_input) == "end of input");
09570     }
09571 
09572     SECTION("parse errors on first character")
09573     {
09574         for (int c = 1; c < 128; ++c)
09575         {
09576             auto s = std::string(1, c);
09577 
09578             switch (c)
09579             {
09580                 // single characters that are valid tokens
09581                 case ('['):
09582                 case (']'):
09583                 case ('{'):
09584                 case ('}'):
09585                 case (','):
09586                 case (':'):
09587                 case ('0'):
09588                 case ('1'):
09589                 case ('2'):
09590                 case ('3'):
09591                 case ('4'):
09592                 case ('5'):
09593                 case ('6'):
09594                 case ('7'):
09595                 case ('8'):
09596                 case ('9'):
09597                 {
09598                     CHECK(json::lexer(s.c_str()).scan() != json::lexer::token_type::parse_error);
09599                     break;
09600                 }
09601 
09602                 // whitespace
09603                 case (' '):
09604                 case ('\t'):
09605                 case ('\n'):
09606                 case ('\r'):
09607                 {
09608                     CHECK(json::lexer(s.c_str()).scan() == json::lexer::token_type::end_of_input);
09609                     break;
09610                 }
09611 
09612                 // anything else is not expected
09613                 default:
09614                 {
09615                     CHECK(json::lexer(s.c_str()).scan() == json::lexer::token_type::parse_error);
09616                     break;
09617                 }
09618             }
09619         }
09620     }
09621 
09622     SECTION("to_unicode")
09623     {
09624         CHECK(json::lexer::to_unicode(0x1F4A9) == "💩");
09625         CHECK_THROWS_AS(json::lexer::to_unicode(0x200000), std::out_of_range);
09626         CHECK_THROWS_WITH(json::lexer::to_unicode(0x200000), "code points above 0x10FFFF are invalid");
09627     }
09628 }
09629 
09630 TEST_CASE("parser class")
09631 {
09632     SECTION("parse")
09633     {
09634         SECTION("null")
09635         {
09636             CHECK(json::parser("null").parse() == json(nullptr));
09637         }
09638 
09639         SECTION("true")
09640         {
09641             CHECK(json::parser("true").parse() == json(true));
09642         }
09643 
09644         SECTION("false")
09645         {
09646             CHECK(json::parser("false").parse() == json(false));
09647         }
09648 
09649         SECTION("array")
09650         {
09651             SECTION("empty array")
09652             {
09653                 CHECK(json::parser("[]").parse() == json(json::value_t::array));
09654                 CHECK(json::parser("[ ]").parse() == json(json::value_t::array));
09655             }
09656 
09657             SECTION("nonempty array")
09658             {
09659                 CHECK(json::parser("[true, false, null]").parse() == json({true, false, nullptr}));
09660             }
09661         }
09662 
09663         SECTION("object")
09664         {
09665             SECTION("empty object")
09666             {
09667                 CHECK(json::parser("{}").parse() == json(json::value_t::object));
09668                 CHECK(json::parser("{ }").parse() == json(json::value_t::object));
09669             }
09670 
09671             SECTION("nonempty object")
09672             {
09673                 CHECK(json::parser("{\"\": true, \"one\": 1, \"two\": null}").parse() == json({{"", true}, {"one", 1}, {"two", nullptr}}));
09674             }
09675         }
09676 
09677         SECTION("string")
09678         {
09679             // empty string
09680             CHECK(json::parser("\"\"").parse() == json(json::value_t::string));
09681 
09682             SECTION("errors")
09683             {
09684                 // error: tab in string
09685                 CHECK_THROWS_AS(json::parser("\"\t\"").parse(), std::invalid_argument);
09686                 CHECK_THROWS_WITH(json::parser("\"\t\"").parse(), "parse error - unexpected '\"'");
09687                 // error: newline in string
09688                 CHECK_THROWS_AS(json::parser("\"\n\"").parse(), std::invalid_argument);
09689                 CHECK_THROWS_AS(json::parser("\"\r\"").parse(), std::invalid_argument);
09690                 CHECK_THROWS_WITH(json::parser("\"\n\"").parse(), "parse error - unexpected '\"'");
09691                 CHECK_THROWS_WITH(json::parser("\"\r\"").parse(), "parse error - unexpected '\"'");
09692                 // error: backspace in string
09693                 CHECK_THROWS_AS(json::parser("\"\b\"").parse(), std::invalid_argument);
09694                 CHECK_THROWS_WITH(json::parser("\"\b\"").parse(), "parse error - unexpected '\"'");
09695                 // improve code coverage
09696                 CHECK_THROWS_AS(json::parser("\uFF01").parse(), std::invalid_argument);
09697             }
09698 
09699             SECTION("escaped")
09700             {
09701                 // quotation mark "\""
09702                 auto r1 = R"("\"")"_json;
09703                 CHECK(json::parser("\"\\\"\"").parse() == r1);
09704                 // reverse solidus "\\"
09705                 auto r2 = R"("\\")"_json;
09706                 CHECK(json::parser("\"\\\\\"").parse() == r2);
09707                 // solidus
09708                 CHECK(json::parser("\"\\/\"").parse() == R"("/")"_json);
09709                 // backspace
09710                 CHECK(json::parser("\"\\b\"").parse() == json("\b"));
09711                 // formfeed
09712                 CHECK(json::parser("\"\\f\"").parse() == json("\f"));
09713                 // newline
09714                 CHECK(json::parser("\"\\n\"").parse() == json("\n"));
09715                 // carriage return
09716                 CHECK(json::parser("\"\\r\"").parse() == json("\r"));
09717                 // horizontal tab
09718                 CHECK(json::parser("\"\\t\"").parse() == json("\t"));
09719 
09720                 CHECK(json::parser("\"\\u0001\"").parse().get<json::string_t>() == "\x01");
09721                 CHECK(json::parser("\"\\u000a\"").parse().get<json::string_t>() == "\n");
09722                 CHECK(json::parser("\"\\u00b0\"").parse().get<json::string_t>() == "°");
09723                 CHECK(json::parser("\"\\u0c00\"").parse().get<json::string_t>() == "ఀ");
09724                 CHECK(json::parser("\"\\ud000\"").parse().get<json::string_t>() == "퀀");
09725                 CHECK(json::parser("\"\\u000E\"").parse().get<json::string_t>() == "\x0E");
09726                 CHECK(json::parser("\"\\u00F0\"").parse().get<json::string_t>() == "ð");
09727                 CHECK(json::parser("\"\\u0100\"").parse().get<json::string_t>() == "Ā");
09728                 CHECK(json::parser("\"\\u2000\"").parse().get<json::string_t>() == " ");
09729                 CHECK(json::parser("\"\\uFFFF\"").parse().get<json::string_t>() == "￿");
09730                 CHECK(json::parser("\"\\u20AC\"").parse().get<json::string_t>() == "€");
09731                 CHECK(json::parser("\"€\"").parse().get<json::string_t>() == "€");
09732                 CHECK(json::parser("\"🎈\"").parse().get<json::string_t>() == "🎈");
09733 
09734                 CHECK(json::parse("\"\\ud80c\\udc60\"").get<json::string_t>() == u8"\U00013060");
09735                 CHECK(json::parse("\"\\ud83c\\udf1e\"").get<json::string_t>() == "🌞");
09736             }
09737         }
09738 
09739         SECTION("number")
09740         {
09741             SECTION("integers")
09742             {
09743                 SECTION("without exponent")
09744                 {
09745                     CHECK(json::parser("-128").parse() == json(-128));
09746                     CHECK(json::parser("-0").parse() == json(-0));
09747                     CHECK(json::parser("0").parse() == json(0));
09748                     CHECK(json::parser("128").parse() == json(128));
09749                 }
09750 
09751                 SECTION("with exponent")
09752                 {
09753                     CHECK(json::parser("0e1").parse() == json(0e1));
09754                     CHECK(json::parser("0E1").parse() == json(0e1));
09755 
09756                     CHECK(json::parser("10000E-4").parse() == json(10000e-4));
09757                     CHECK(json::parser("10000E-3").parse() == json(10000e-3));
09758                     CHECK(json::parser("10000E-2").parse() == json(10000e-2));
09759                     CHECK(json::parser("10000E-1").parse() == json(10000e-1));
09760                     CHECK(json::parser("10000E0").parse() == json(10000e0));
09761                     CHECK(json::parser("10000E1").parse() == json(10000e1));
09762                     CHECK(json::parser("10000E2").parse() == json(10000e2));
09763                     CHECK(json::parser("10000E3").parse() == json(10000e3));
09764                     CHECK(json::parser("10000E4").parse() == json(10000e4));
09765 
09766                     CHECK(json::parser("10000e-4").parse() == json(10000e-4));
09767                     CHECK(json::parser("10000e-3").parse() == json(10000e-3));
09768                     CHECK(json::parser("10000e-2").parse() == json(10000e-2));
09769                     CHECK(json::parser("10000e-1").parse() == json(10000e-1));
09770                     CHECK(json::parser("10000e0").parse() == json(10000e0));
09771                     CHECK(json::parser("10000e1").parse() == json(10000e1));
09772                     CHECK(json::parser("10000e2").parse() == json(10000e2));
09773                     CHECK(json::parser("10000e3").parse() == json(10000e3));
09774                     CHECK(json::parser("10000e4").parse() == json(10000e4));
09775 
09776                     CHECK(json::parser("-0e1").parse() == json(-0e1));
09777                     CHECK(json::parser("-0E1").parse() == json(-0e1));
09778                     CHECK(json::parser("-0E123").parse() == json(-0e123));
09779                 }
09780 
09781                 SECTION("edge cases")
09782                 {
09783                     // From RFC7159, Section 6:
09784                     // Note that when such software is used, numbers that are
09785                     // integers and are in the range [-(2**53)+1, (2**53)-1]
09786                     // are interoperable in the sense that implementations will
09787                     // agree exactly on their numeric values.
09788 
09789                     // -(2**53)+1
09790                     CHECK(json::parser("-9007199254740991").parse().get<int64_t>() == -9007199254740991);
09791                     // (2**53)-1
09792                     CHECK(json::parser("9007199254740991").parse().get<int64_t>() == 9007199254740991);
09793                 }
09794 
09795                 SECTION("over the edge cases")  // issue #178 - Integer conversion to unsigned (incorrect handling of 64 bit integers)
09796                 {
09797                     // While RFC7159, Section 6 specifies a preference for support
09798                     // for ranges in range of IEEE 754-2008 binary64 (double precision)
09799                     // this does not accommodate 64 bit integers without loss of accuracy.
09800                     // As 64 bit integers are now widely used in software, it is desirable
09801                     // to expand support to to the full 64 bit (signed and unsigned) range
09802                     // i.e. -(2**63) -> (2**64)-1.
09803 
09804                     // -(2**63)    ** Note: compilers see negative literals as negated positive numbers (hence the -1))
09805                     CHECK(json::parser("-9223372036854775808").parse().get<int64_t>() == -9223372036854775807 - 1);
09806                     // (2**63)-1
09807                     CHECK(json::parser("9223372036854775807").parse().get<int64_t>() == 9223372036854775807);
09808                     // (2**64)-1
09809                     CHECK(json::parser("18446744073709551615").parse().get<uint64_t>() == 18446744073709551615u);
09810                 }
09811             }
09812 
09813             SECTION("floating-point")
09814             {
09815                 SECTION("without exponent")
09816                 {
09817                     CHECK(json::parser("-128.5").parse() == json(-128.5));
09818                     CHECK(json::parser("0.999").parse() == json(0.999));
09819                     CHECK(json::parser("128.5").parse() == json(128.5));
09820                     CHECK(json::parser("-0.0").parse() == json(-0.0));
09821                 }
09822 
09823                 SECTION("with exponent")
09824                 {
09825                     CHECK(json::parser("-128.5E3").parse() == json(-128.5E3));
09826                     CHECK(json::parser("-128.5E-3").parse() == json(-128.5E-3));
09827                     CHECK(json::parser("-0.0e1").parse() == json(-0.0e1));
09828                     CHECK(json::parser("-0.0E1").parse() == json(-0.0e1));
09829                 }
09830             }
09831 
09832             SECTION("invalid numbers")
09833             {
09834                 CHECK_THROWS_AS(json::parser("01").parse(), std::invalid_argument);
09835                 CHECK_THROWS_AS(json::parser("--1").parse(), std::invalid_argument);
09836                 CHECK_THROWS_AS(json::parser("1.").parse(), std::invalid_argument);
09837                 CHECK_THROWS_AS(json::parser("1E").parse(), std::invalid_argument);
09838                 CHECK_THROWS_AS(json::parser("1E-").parse(), std::invalid_argument);
09839                 CHECK_THROWS_AS(json::parser("1.E1").parse(), std::invalid_argument);
09840                 CHECK_THROWS_AS(json::parser("-1E").parse(), std::invalid_argument);
09841                 CHECK_THROWS_AS(json::parser("-0E#").parse(), std::invalid_argument);
09842                 CHECK_THROWS_AS(json::parser("-0E-#").parse(), std::invalid_argument);
09843                 CHECK_THROWS_AS(json::parser("-0#").parse(), std::invalid_argument);
09844                 CHECK_THROWS_AS(json::parser("-0.0:").parse(), std::invalid_argument);
09845                 CHECK_THROWS_AS(json::parser("-0.0Z").parse(), std::invalid_argument);
09846                 CHECK_THROWS_AS(json::parser("-0E123:").parse(), std::invalid_argument);
09847                 CHECK_THROWS_AS(json::parser("-0e0-:").parse(), std::invalid_argument);
09848                 CHECK_THROWS_AS(json::parser("-0e-:").parse(), std::invalid_argument);
09849                 CHECK_THROWS_AS(json::parser("-0f").parse(), std::invalid_argument);
09850 
09851                 // numbers must not begin with "+"
09852                 CHECK_THROWS_AS(json::parser("+1").parse(), std::invalid_argument);
09853                 CHECK_THROWS_AS(json::parser("+0").parse(), std::invalid_argument);
09854 
09855                 CHECK_THROWS_WITH(json::parser("01").parse(),
09856                                   "parse error - unexpected number literal; expected end of input");
09857                 CHECK_THROWS_WITH(json::parser("--1").parse(), "parse error - unexpected '-'");
09858                 CHECK_THROWS_WITH(json::parser("1.").parse(),
09859                                   "parse error - unexpected '.'; expected end of input");
09860                 CHECK_THROWS_WITH(json::parser("1E").parse(),
09861                                   "parse error - unexpected 'E'; expected end of input");
09862                 CHECK_THROWS_WITH(json::parser("1E-").parse(),
09863                                   "parse error - unexpected 'E'; expected end of input");
09864                 CHECK_THROWS_WITH(json::parser("1.E1").parse(),
09865                                   "parse error - unexpected '.'; expected end of input");
09866                 CHECK_THROWS_WITH(json::parser("-1E").parse(),
09867                                   "parse error - unexpected 'E'; expected end of input");
09868                 CHECK_THROWS_WITH(json::parser("-0E#").parse(),
09869                                   "parse error - unexpected 'E'; expected end of input");
09870                 CHECK_THROWS_WITH(json::parser("-0E-#").parse(),
09871                                   "parse error - unexpected 'E'; expected end of input");
09872                 CHECK_THROWS_WITH(json::parser("-0#").parse(),
09873                                   "parse error - unexpected '#'; expected end of input");
09874                 CHECK_THROWS_WITH(json::parser("-0.0:").parse(),
09875                                   "parse error - unexpected ':'; expected end of input");
09876                 CHECK_THROWS_WITH(json::parser("-0.0Z").parse(),
09877                                   "parse error - unexpected 'Z'; expected end of input");
09878                 CHECK_THROWS_WITH(json::parser("-0E123:").parse(),
09879                                   "parse error - unexpected ':'; expected end of input");
09880                 CHECK_THROWS_WITH(json::parser("-0e0-:").parse(),
09881                                   "parse error - unexpected '-'; expected end of input");
09882                 CHECK_THROWS_WITH(json::parser("-0e-:").parse(),
09883                                   "parse error - unexpected 'e'; expected end of input");
09884                 CHECK_THROWS_WITH(json::parser("-0f").parse(),
09885                                   "parse error - unexpected 'f'; expected end of input");
09886             }
09887         }
09888     }
09889 
09890     SECTION("parse errors")
09891     {
09892         // unexpected end of number
09893         CHECK_THROWS_AS(json::parser("0.").parse(), std::invalid_argument);
09894         CHECK_THROWS_AS(json::parser("-").parse(), std::invalid_argument);
09895         CHECK_THROWS_AS(json::parser("--").parse(), std::invalid_argument);
09896         CHECK_THROWS_AS(json::parser("-0.").parse(), std::invalid_argument);
09897         CHECK_THROWS_AS(json::parser("-.").parse(), std::invalid_argument);
09898         CHECK_THROWS_AS(json::parser("-:").parse(), std::invalid_argument);
09899         CHECK_THROWS_AS(json::parser("0.:").parse(), std::invalid_argument);
09900         CHECK_THROWS_AS(json::parser("e.").parse(), std::invalid_argument);
09901         CHECK_THROWS_AS(json::parser("1e.").parse(), std::invalid_argument);
09902         CHECK_THROWS_AS(json::parser("1e/").parse(), std::invalid_argument);
09903         CHECK_THROWS_AS(json::parser("1e:").parse(), std::invalid_argument);
09904         CHECK_THROWS_AS(json::parser("1E.").parse(), std::invalid_argument);
09905         CHECK_THROWS_AS(json::parser("1E/").parse(), std::invalid_argument);
09906         CHECK_THROWS_AS(json::parser("1E:").parse(), std::invalid_argument);
09907         CHECK_THROWS_WITH(json::parser("0.").parse(),
09908                           "parse error - unexpected '.'; expected end of input");
09909         CHECK_THROWS_WITH(json::parser("-").parse(), "parse error - unexpected '-'");
09910         CHECK_THROWS_WITH(json::parser("--").parse(),
09911                           "parse error - unexpected '-'");
09912         CHECK_THROWS_WITH(json::parser("-0.").parse(),
09913                           "parse error - unexpected '.'; expected end of input");
09914         CHECK_THROWS_WITH(json::parser("-.").parse(),
09915                           "parse error - unexpected '-'");
09916         CHECK_THROWS_WITH(json::parser("-:").parse(),
09917                           "parse error - unexpected '-'");
09918         CHECK_THROWS_WITH(json::parser("0.:").parse(),
09919                           "parse error - unexpected '.'; expected end of input");
09920         CHECK_THROWS_WITH(json::parser("e.").parse(),
09921                           "parse error - unexpected 'e'");
09922         CHECK_THROWS_WITH(json::parser("1e.").parse(),
09923                           "parse error - unexpected 'e'; expected end of input");
09924         CHECK_THROWS_WITH(json::parser("1e/").parse(),
09925                           "parse error - unexpected 'e'; expected end of input");
09926         CHECK_THROWS_WITH(json::parser("1e:").parse(),
09927                           "parse error - unexpected 'e'; expected end of input");
09928         CHECK_THROWS_WITH(json::parser("1E.").parse(),
09929                           "parse error - unexpected 'E'; expected end of input");
09930         CHECK_THROWS_WITH(json::parser("1E/").parse(),
09931                           "parse error - unexpected 'E'; expected end of input");
09932         CHECK_THROWS_WITH(json::parser("1E:").parse(),
09933                           "parse error - unexpected 'E'; expected end of input");
09934 
09935         // unexpected end of null
09936         CHECK_THROWS_AS(json::parser("n").parse(), std::invalid_argument);
09937         CHECK_THROWS_AS(json::parser("nu").parse(), std::invalid_argument);
09938         CHECK_THROWS_AS(json::parser("nul").parse(), std::invalid_argument);
09939         CHECK_THROWS_WITH(json::parser("n").parse(), "parse error - unexpected 'n'");
09940         CHECK_THROWS_WITH(json::parser("nu").parse(),
09941                           "parse error - unexpected 'n'");
09942         CHECK_THROWS_WITH(json::parser("nul").parse(),
09943                           "parse error - unexpected 'n'");
09944 
09945         // unexpected end of true
09946         CHECK_THROWS_AS(json::parser("t").parse(), std::invalid_argument);
09947         CHECK_THROWS_AS(json::parser("tr").parse(), std::invalid_argument);
09948         CHECK_THROWS_AS(json::parser("tru").parse(), std::invalid_argument);
09949         CHECK_THROWS_WITH(json::parser("t").parse(), "parse error - unexpected 't'");
09950         CHECK_THROWS_WITH(json::parser("tr").parse(),
09951                           "parse error - unexpected 't'");
09952         CHECK_THROWS_WITH(json::parser("tru").parse(),
09953                           "parse error - unexpected 't'");
09954 
09955         // unexpected end of false
09956         CHECK_THROWS_AS(json::parser("f").parse(), std::invalid_argument);
09957         CHECK_THROWS_AS(json::parser("fa").parse(), std::invalid_argument);
09958         CHECK_THROWS_AS(json::parser("fal").parse(), std::invalid_argument);
09959         CHECK_THROWS_AS(json::parser("fals").parse(), std::invalid_argument);
09960         CHECK_THROWS_WITH(json::parser("f").parse(), "parse error - unexpected 'f'");
09961         CHECK_THROWS_WITH(json::parser("fa").parse(),
09962                           "parse error - unexpected 'f'");
09963         CHECK_THROWS_WITH(json::parser("fal").parse(),
09964                           "parse error - unexpected 'f'");
09965         CHECK_THROWS_WITH(json::parser("fals").parse(),
09966                           "parse error - unexpected 'f'");
09967 
09968         // missing/unexpected end of array
09969         CHECK_THROWS_AS(json::parser("[").parse(), std::invalid_argument);
09970         CHECK_THROWS_AS(json::parser("[1").parse(), std::invalid_argument);
09971         CHECK_THROWS_AS(json::parser("[1,").parse(), std::invalid_argument);
09972         CHECK_THROWS_AS(json::parser("[1,]").parse(), std::invalid_argument);
09973         CHECK_THROWS_AS(json::parser("]").parse(), std::invalid_argument);
09974         CHECK_THROWS_WITH(json::parser("[").parse(),
09975                           "parse error - unexpected end of input");
09976         CHECK_THROWS_WITH(json::parser("[1").parse(),
09977                           "parse error - unexpected end of input; expected ']'");
09978         CHECK_THROWS_WITH(json::parser("[1,").parse(),
09979                           "parse error - unexpected end of input");
09980         CHECK_THROWS_WITH(json::parser("[1,]").parse(),
09981                           "parse error - unexpected ']'");
09982         CHECK_THROWS_WITH(json::parser("]").parse(), "parse error - unexpected ']'");
09983 
09984         // missing/unexpected end of object
09985         CHECK_THROWS_AS(json::parser("{").parse(), std::invalid_argument);
09986         CHECK_THROWS_AS(json::parser("{\"foo\"").parse(), std::invalid_argument);
09987         CHECK_THROWS_AS(json::parser("{\"foo\":").parse(), std::invalid_argument);
09988         CHECK_THROWS_AS(json::parser("{\"foo\":}").parse(), std::invalid_argument);
09989         CHECK_THROWS_AS(json::parser("{\"foo\":1,}").parse(), std::invalid_argument);
09990         CHECK_THROWS_AS(json::parser("}").parse(), std::invalid_argument);
09991         CHECK_THROWS_WITH(json::parser("{").parse(),
09992                           "parse error - unexpected end of input; expected string literal");
09993         CHECK_THROWS_WITH(json::parser("{\"foo\"").parse(),
09994                           "parse error - unexpected end of input; expected ':'");
09995         CHECK_THROWS_WITH(json::parser("{\"foo\":").parse(),
09996                           "parse error - unexpected end of input");
09997         CHECK_THROWS_WITH(json::parser("{\"foo\":}").parse(),
09998                           "parse error - unexpected '}'");
09999         CHECK_THROWS_WITH(json::parser("{\"foo\":1,}").parse(),
10000                           "parse error - unexpected '}'; expected string literal");
10001         CHECK_THROWS_WITH(json::parser("}").parse(), "parse error - unexpected '}'");
10002 
10003         // missing/unexpected end of string
10004         CHECK_THROWS_AS(json::parser("\"").parse(), std::invalid_argument);
10005         CHECK_THROWS_AS(json::parser("\"\\\"").parse(), std::invalid_argument);
10006         CHECK_THROWS_AS(json::parser("\"\\u\"").parse(), std::invalid_argument);
10007         CHECK_THROWS_AS(json::parser("\"\\u0\"").parse(), std::invalid_argument);
10008         CHECK_THROWS_AS(json::parser("\"\\u01\"").parse(), std::invalid_argument);
10009         CHECK_THROWS_AS(json::parser("\"\\u012\"").parse(), std::invalid_argument);
10010         CHECK_THROWS_WITH(json::parser("\"").parse(),
10011                           "parse error - unexpected '\"'");
10012         CHECK_THROWS_WITH(json::parser("\"\\\"").parse(),
10013                           "parse error - unexpected '\"'");
10014         CHECK_THROWS_WITH(json::parser("\"\\u\"").parse(),
10015                           "parse error - unexpected '\"'");
10016         CHECK_THROWS_WITH(json::parser("\"\\u0\"").parse(),
10017                           "parse error - unexpected '\"'");
10018         CHECK_THROWS_WITH(json::parser("\"\\u01\"").parse(),
10019                           "parse error - unexpected '\"'");
10020         CHECK_THROWS_WITH(json::parser("\"\\u012\"").parse(),
10021                           "parse error - unexpected '\"'");
10022 
10023         // invalid escapes
10024         for (int c = 1; c < 128; ++c)
10025         {
10026             auto s = std::string("\"\\") + std::string(1, c) + "\"";
10027 
10028             switch (c)
10029             {
10030                 // valid escapes
10031                 case ('"'):
10032                 case ('\\'):
10033                 case ('/'):
10034                 case ('b'):
10035                 case ('f'):
10036                 case ('n'):
10037                 case ('r'):
10038                 case ('t'):
10039                 {
10040                     CHECK_NOTHROW(json::parser(s).parse());
10041                     break;
10042                 }
10043 
10044                 // \u must be followed with four numbers, so we skip it here
10045                 case ('u'):
10046                 {
10047                     break;
10048                 }
10049 
10050                 // any other combination of backslash and character is invalid
10051                 default:
10052                 {
10053                     CHECK_THROWS_AS(json::parser(s).parse(), std::invalid_argument);
10054                     CHECK_THROWS_WITH(json::parser(s).parse(), "parse error - unexpected '\"'");
10055                     break;
10056                 }
10057             }
10058         }
10059 
10060         // invalid \uxxxx escapes
10061         {
10062             // check whether character is a valid hex character
10063             const auto valid = [](int c)
10064             {
10065                 switch (c)
10066                 {
10067                     case ('0'):
10068                     case ('1'):
10069                     case ('2'):
10070                     case ('3'):
10071                     case ('4'):
10072                     case ('5'):
10073                     case ('6'):
10074                     case ('7'):
10075                     case ('8'):
10076                     case ('9'):
10077                     case ('a'):
10078                     case ('b'):
10079                     case ('c'):
10080                     case ('d'):
10081                     case ('e'):
10082                     case ('f'):
10083                     case ('A'):
10084                     case ('B'):
10085                     case ('C'):
10086                     case ('D'):
10087                     case ('E'):
10088                     case ('F'):
10089                     {
10090                         return true;
10091                     }
10092 
10093                     default:
10094                     {
10095                         return false;
10096                     }
10097                 }
10098             };
10099 
10100             for (int c = 1; c < 128; ++c)
10101             {
10102                 std::string s = "\"\\u";
10103 
10104                 // create a string with the iterated character at each position
10105                 auto s1 = s + "000" + std::string(1, c) + "\"";
10106                 auto s2 = s + "00" + std::string(1, c) + "0\"";
10107                 auto s3 = s + "0" + std::string(1, c) + "00\"";
10108                 auto s4 = s + std::string(1, c) + "000\"";
10109 
10110                 if (valid(c))
10111                 {
10112                     CHECK_NOTHROW(json::parser(s1).parse());
10113                     CHECK_NOTHROW(json::parser(s2).parse());
10114                     CHECK_NOTHROW(json::parser(s3).parse());
10115                     CHECK_NOTHROW(json::parser(s4).parse());
10116                 }
10117                 else
10118                 {
10119                     CHECK_THROWS_AS(json::parser(s1).parse(), std::invalid_argument);
10120                     CHECK_THROWS_AS(json::parser(s2).parse(), std::invalid_argument);
10121                     CHECK_THROWS_AS(json::parser(s3).parse(), std::invalid_argument);
10122                     CHECK_THROWS_AS(json::parser(s4).parse(), std::invalid_argument);
10123 
10124                     CHECK_THROWS_WITH(json::parser(s1).parse(), "parse error - unexpected '\"'");
10125                     CHECK_THROWS_WITH(json::parser(s2).parse(), "parse error - unexpected '\"'");
10126                     CHECK_THROWS_WITH(json::parser(s3).parse(), "parse error - unexpected '\"'");
10127                     CHECK_THROWS_WITH(json::parser(s4).parse(), "parse error - unexpected '\"'");
10128                 }
10129             }
10130         }
10131 
10132         // missing part of a surrogate pair
10133         CHECK_THROWS_AS(json::parse("\"\\uD80C\""), std::invalid_argument);
10134         CHECK_THROWS_WITH(json::parse("\"\\uD80C\""), "missing low surrogate");
10135         // invalid surrogate pair
10136         CHECK_THROWS_AS(json::parse("\"\\uD80C\\uD80C\""), std::invalid_argument);
10137         CHECK_THROWS_AS(json::parse("\"\\uD80C\\u0000\""), std::invalid_argument);
10138         CHECK_THROWS_AS(json::parse("\"\\uD80C\\uFFFF\""), std::invalid_argument);
10139         CHECK_THROWS_WITH(json::parse("\"\\uD80C\\uD80C\""),
10140                           "missing or wrong low surrogate");
10141         CHECK_THROWS_WITH(json::parse("\"\\uD80C\\u0000\""),
10142                           "missing or wrong low surrogate");
10143         CHECK_THROWS_WITH(json::parse("\"\\uD80C\\uFFFF\""),
10144                           "missing or wrong low surrogate");
10145     }
10146 
10147     SECTION("callback function")
10148     {
10149         auto s_object = R"(
10150             {
10151                 "foo": 2,
10152                 "bar": {
10153                     "baz": 1
10154                 }
10155             }
10156         )";
10157 
10158         auto s_array = R"(
10159             [1,2,[3,4,5],4,5]
10160         )";
10161 
10162         SECTION("filter nothing")
10163         {
10164             json j_object = json::parse(s_object, [](int, json::parse_event_t, const json&)
10165             {
10166                 return true;
10167             });
10168 
10169             CHECK (j_object == json({{"foo", 2}, {"bar", {{"baz", 1}}}}));
10170 
10171             json j_array = json::parse(s_array, [](int, json::parse_event_t, const json&)
10172             {
10173                 return true;
10174             });
10175 
10176             CHECK (j_array == json({1, 2, {3, 4, 5}, 4, 5}));
10177         }
10178 
10179         SECTION("filter everything")
10180         {
10181             json j_object = json::parse(s_object, [](int, json::parse_event_t, const json&)
10182             {
10183                 return false;
10184             });
10185 
10186             // the top-level object will be discarded, leaving a null
10187             CHECK (j_object.is_null());
10188 
10189             json j_array = json::parse(s_array, [](int, json::parse_event_t, const json&)
10190             {
10191                 return false;
10192             });
10193 
10194             // the top-level array will be discarded, leaving a null
10195             CHECK (j_array.is_null());
10196         }
10197 
10198         SECTION("filter specific element")
10199         {
10200             json j_object = json::parse(s_object, [](int, json::parse_event_t, const json & j)
10201             {
10202                 // filter all number(2) elements
10203                 if (j == json(2))
10204                 {
10205                     return false;
10206                 }
10207                 else
10208                 {
10209                     return true;
10210                 }
10211             });
10212 
10213             CHECK (j_object == json({{"bar", {{"baz", 1}}}}));
10214 
10215             json j_array = json::parse(s_array, [](int, json::parse_event_t, const json & j)
10216             {
10217                 if (j == json(2))
10218                 {
10219                     return false;
10220                 }
10221                 else
10222                 {
10223                     return true;
10224                 }
10225             });
10226 
10227             CHECK (j_array == json({1, {3, 4, 5}, 4, 5}));
10228         }
10229 
10230         SECTION("filter specific events")
10231         {
10232             SECTION("first closing event")
10233             {
10234                 {
10235                     json j_object = json::parse(s_object, [](int, json::parse_event_t e, const json&)
10236                     {
10237                         static bool first = true;
10238                         if (e == json::parse_event_t::object_end and first)
10239                         {
10240                             first = false;
10241                             return false;
10242                         }
10243                         else
10244                         {
10245                             return true;
10246                         }
10247                     });
10248 
10249                     // the first completed object will be discarded
10250                     CHECK (j_object == json({{"foo", 2}}));
10251                 }
10252 
10253                 {
10254                     json j_array = json::parse(s_array, [](int, json::parse_event_t e, const json&)
10255                     {
10256                         static bool first = true;
10257                         if (e == json::parse_event_t::array_end and first)
10258                         {
10259                             first = false;
10260                             return false;
10261                         }
10262                         else
10263                         {
10264                             return true;
10265                         }
10266                     });
10267 
10268                     // the first completed array will be discarded
10269                     CHECK (j_array == json({1, 2, 4, 5}));
10270                 }
10271             }
10272         }
10273 
10274         SECTION("special cases")
10275         {
10276             // the following test cases cover the situation in which an empty
10277             // object and array is discarded only after the closing character
10278             // has been read
10279 
10280             json j_empty_object = json::parse("{}", [](int, json::parse_event_t e, const json&)
10281             {
10282                 if (e == json::parse_event_t::object_end)
10283                 {
10284                     return false;
10285                 }
10286                 else
10287                 {
10288                     return true;
10289                 }
10290             });
10291             CHECK(j_empty_object == json());
10292 
10293             json j_empty_array = json::parse("[]", [](int, json::parse_event_t e, const json&)
10294             {
10295                 if (e == json::parse_event_t::array_end)
10296                 {
10297                     return false;
10298                 }
10299                 else
10300                 {
10301                     return true;
10302                 }
10303             });
10304             CHECK(j_empty_array == json());
10305         }
10306     }
10307 }
10308 
10309 TEST_CASE("README", "[hide]")
10310 {
10311     {
10312         // create an empty structure (null)
10313         json j;
10314 
10315         // add a number that is stored as double (note the implicit conversion of j to an object)
10316         j["pi"] = 3.141;
10317 
10318         // add a Boolean that is stored as bool
10319         j["happy"] = true;
10320 
10321         // add a string that is stored as std::string
10322         j["name"] = "Niels";
10323 
10324         // add another null object by passing nullptr
10325         j["nothing"] = nullptr;
10326 
10327         // add an object inside the object
10328         j["answer"]["everything"] = 42;
10329 
10330         // add an array that is stored as std::vector (using an initializer list)
10331         j["list"] = { 1, 0, 2 };
10332 
10333         // add another object (using an initializer list of pairs)
10334         j["object"] = { {"currency", "USD"}, {"value", 42.99} };
10335 
10336         // instead, you could also write (which looks very similar to the JSON above)
10337         json j2 =
10338         {
10339             {"pi", 3.141},
10340             {"happy", true},
10341             {"name", "Niels"},
10342             {"nothing", nullptr},
10343             {
10344                 "answer", {
10345                     {"everything", 42}
10346                 }
10347             },
10348             {"list", {1, 0, 2}},
10349             {
10350                 "object", {
10351                     {"currency", "USD"},
10352                     {"value", 42.99}
10353                 }
10354             }
10355         };
10356     }
10357 
10358     {
10359         // ways to express the empty array []
10360         json empty_array_implicit = {{}};
10361         json empty_array_explicit = json::array();
10362 
10363         // a way to express the empty object {}
10364         json empty_object_explicit = json::object();
10365 
10366         // a way to express an _array_ of key/value pairs [["currency", "USD"], ["value", 42.99]]
10367         json array_not_object = { json::array({"currency", "USD"}), json::array({"value", 42.99}) };
10368     }
10369 
10370     {
10371         // create object from string literal
10372         json j = "{ \"happy\": true, \"pi\": 3.141 }"_json;
10373 
10374         // or even nicer with a raw string literal
10375         auto j2 = R"(
10376           {
10377             "happy": true,
10378             "pi": 3.141
10379           }
10380         )"_json;
10381 
10382         // or explicitly
10383         auto j3 = json::parse("{ \"happy\": true, \"pi\": 3.141 }");
10384 
10385         // explicit conversion to string
10386         std::string s = j.dump();    // {\"happy\":true,\"pi\":3.141}
10387 
10388         // serialization with pretty printing
10389         // pass in the amount of spaces to indent
10390         std::cout << j.dump(4) << std::endl;
10391         // {
10392         //     "happy": true,
10393         //     "pi": 3.141
10394         // }
10395 
10396         std::cout << std::setw(2) << j << std::endl;
10397     }
10398 
10399     {
10400         // create an array using push_back
10401         json j;
10402         j.push_back("foo");
10403         j.push_back(1);
10404         j.push_back(true);
10405 
10406         // iterate the array
10407         for (json::iterator it = j.begin(); it != j.end(); ++it)
10408         {
10409             std::cout << *it << '\n';
10410         }
10411 
10412         // range-based for
10413         for (auto element : j)
10414         {
10415             std::cout << element << '\n';
10416         }
10417 
10418         // getter/setter
10419         const std::string tmp = j[0];
10420         j[1] = 42;
10421         bool foo = j.at(2);
10422 
10423         // other stuff
10424         j.size();     // 3 entries
10425         j.empty();    // false
10426         j.type();     // json::value_t::array
10427         j.clear();    // the array is empty again
10428 
10429         // comparison
10430         j == "[\"foo\", 1, true]"_json;  // true
10431 
10432         // create an object
10433         json o;
10434         o["foo"] = 23;
10435         o["bar"] = false;
10436         o["baz"] = 3.141;
10437 
10438         // find an entry
10439         if (o.find("foo") != o.end())
10440         {
10441             // there is an entry with key "foo"
10442         }
10443     }
10444 
10445     {
10446         std::vector<int> c_vector {1, 2, 3, 4};
10447         json j_vec(c_vector);
10448         // [1, 2, 3, 4]
10449 
10450         std::deque<float> c_deque {1.2f, 2.3f, 3.4f, 5.6f};
10451         json j_deque(c_deque);
10452         // [1.2, 2.3, 3.4, 5.6]
10453 
10454         std::list<bool> c_list {true, true, false, true};
10455         json j_list(c_list);
10456         // [true, true, false, true]
10457 
10458         std::forward_list<int64_t> c_flist {12345678909876, 23456789098765, 34567890987654, 45678909876543};
10459         json j_flist(c_flist);
10460         // [12345678909876, 23456789098765, 34567890987654, 45678909876543]
10461 
10462         std::array<unsigned long, 4> c_array {{1, 2, 3, 4}};
10463         json j_array(c_array);
10464         // [1, 2, 3, 4]
10465 
10466         std::set<std::string> c_set {"one", "two", "three", "four", "one"};
10467         json j_set(c_set); // only one entry for "one" is used
10468         // ["four", "one", "three", "two"]
10469 
10470         std::unordered_set<std::string> c_uset {"one", "two", "three", "four", "one"};
10471         json j_uset(c_uset); // only one entry for "one" is used
10472         // maybe ["two", "three", "four", "one"]
10473 
10474         std::multiset<std::string> c_mset {"one", "two", "one", "four"};
10475         json j_mset(c_mset); // only one entry for "one" is used
10476         // maybe ["one", "two", "four"]
10477 
10478         std::unordered_multiset<std::string> c_umset {"one", "two", "one", "four"};
10479         json j_umset(c_umset); // both entries for "one" are used
10480         // maybe ["one", "two", "one", "four"]
10481     }
10482 
10483     {
10484         std::map<std::string, int> c_map { {"one", 1}, {"two", 2}, {"three", 3} };
10485         json j_map(c_map);
10486         // {"one": 1, "two": 2, "three": 3}
10487 
10488         std::unordered_map<const char*, float> c_umap { {"one", 1.2f}, {"two", 2.3f}, {"three", 3.4f} };
10489         json j_umap(c_umap);
10490         // {"one": 1.2, "two": 2.3, "three": 3.4}
10491 
10492         std::multimap<std::string, bool> c_mmap { {"one", true}, {"two", true}, {"three", false}, {"three", true} };
10493         json j_mmap(c_mmap); // only one entry for key "three" is used
10494         // maybe {"one": true, "two": true, "three": true}
10495 
10496         std::unordered_multimap<std::string, bool> c_ummap { {"one", true}, {"two", true}, {"three", false}, {"three", true} };
10497         json j_ummap(c_ummap); // only one entry for key "three" is used
10498         // maybe {"one": true, "two": true, "three": true}
10499     }
10500 
10501     {
10502         // strings
10503         std::string s1 = "Hello, world!";
10504         json js = s1;
10505         std::string s2 = js;
10506 
10507         // Booleans
10508         bool b1 = true;
10509         json jb = b1;
10510         bool b2 = jb;
10511 
10512         // numbers
10513         int i = 42;
10514         json jn = i;
10515         double f = jn;
10516 
10517         // etc.
10518 
10519         std::string vs = js.get<std::string>();
10520         bool vb = jb.get<bool>();
10521         int vi = jn.get<int>();
10522 
10523         // etc.
10524     }
10525 
10526     {
10527         // a JSON value
10528         json j_original = R"({
10529           "baz": ["one", "two", "three"],
10530           "foo": "bar"
10531         })"_json;
10532 
10533         // access members with a JSON pointer (RFC 6901)
10534         j_original["/baz/2"_json_pointer];
10535         // "two"
10536 
10537         // a JSON patch (RFC 6902)
10538         json j_patch = R"([
10539           { "op": "replace", "path": "/baz", "value": "boo" },
10540           { "op": "add", "path": "/hello", "value": ["world"] },
10541           { "op": "remove", "path": "/foo"}
10542         ])"_json;
10543 
10544         // apply the patch
10545         json j_result = j_original.patch(j_patch);
10546         // {
10547         //    "baz": "boo",
10548         //    "hello": ["world"]
10549         // }
10550 
10551         // calculate a JSON patch from two JSON values
10552         json::diff(j_result, j_original);
10553         // [
10554         //   { "op":" replace", "path": "/baz", "value": ["one", "two", "three"] },
10555         //   { "op":"remove","path":"/hello" },
10556         //   { "op":"add","path":"/foo","value":"bar" }
10557         // ]
10558     }
10559 }
10560 
10561 TEST_CASE("algorithms")
10562 {
10563     json j_array = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz"};
10564     json j_object = {{"one", 1}, {"two", 2}};
10565 
10566     SECTION("non-modifying sequence operations")
10567     {
10568         SECTION("std::all_of")
10569         {
10570             CHECK(std::all_of(j_array.begin(), j_array.end(), [](const json & value)
10571             {
10572                 return value.size() > 0;
10573             }));
10574             CHECK(std::all_of(j_object.begin(), j_object.end(), [](const json & value)
10575             {
10576                 return value.type() == json::value_t::number_integer;
10577             }));
10578         }
10579 
10580         SECTION("std::any_of")
10581         {
10582             CHECK(std::any_of(j_array.begin(), j_array.end(), [](const json & value)
10583             {
10584                 return value.is_string() and value.get<std::string>() == "foo";
10585             }));
10586             CHECK(std::any_of(j_object.begin(), j_object.end(), [](const json & value)
10587             {
10588                 return value.get<int>() > 1;
10589             }));
10590         }
10591 
10592         SECTION("std::none_of")
10593         {
10594             CHECK(std::none_of(j_array.begin(), j_array.end(), [](const json & value)
10595             {
10596                 return value.size() == 0;
10597             }));
10598             CHECK(std::none_of(j_object.begin(), j_object.end(), [](const json & value)
10599             {
10600                 return value.get<int>() <= 0;
10601             }));
10602         }
10603 
10604         SECTION("std::for_each")
10605         {
10606             SECTION("reading")
10607             {
10608                 int sum = 0;
10609 
10610                 std::for_each(j_array.cbegin(), j_array.cend(), [&sum](const json & value)
10611                 {
10612                     if (value.is_number())
10613                     {
10614                         sum += static_cast<int>(value);
10615                     }
10616                 });
10617 
10618                 CHECK(sum == 45);
10619             }
10620 
10621             SECTION("writing")
10622             {
10623                 auto add17 = [](json & value)
10624                 {
10625                     if (value.is_array())
10626                     {
10627                         value.push_back(17);
10628                     }
10629                 };
10630 
10631                 std::for_each(j_array.begin(), j_array.end(), add17);
10632 
10633                 CHECK(j_array[6] == json({1, 2, 3, 17}));
10634             }
10635         }
10636 
10637         SECTION("std::count")
10638         {
10639             CHECK(std::count(j_array.begin(), j_array.end(), json(true)) == 1);
10640         }
10641 
10642         SECTION("std::count_if")
10643         {
10644             CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json & value)
10645             {
10646                 return (value.is_number());
10647             }) == 3);
10648             CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json&)
10649             {
10650                 return true;
10651             }) == 9);
10652         }
10653 
10654         SECTION("std::mismatch")
10655         {
10656             json j_array2 = {13, 29, 3, {{"one", 1}, {"two", 2}, {"three", 3}}, true, false, {1, 2, 3}, "foo", "baz"};
10657             auto res = std::mismatch(j_array.begin(), j_array.end(), j_array2.begin());
10658             CHECK(*res.first == json({{"one", 1}, {"two", 2}}));
10659             CHECK(*res.second == json({{"one", 1}, {"two", 2}, {"three", 3}}));
10660         }
10661 
10662         SECTION("std::equal")
10663         {
10664             SECTION("using operator==")
10665             {
10666                 CHECK(std::equal(j_array.begin(), j_array.end(), j_array.begin()));
10667                 CHECK(std::equal(j_object.begin(), j_object.end(), j_object.begin()));
10668                 CHECK(not std::equal(j_array.begin(), j_array.end(), j_object.begin()));
10669             }
10670 
10671             SECTION("using user-defined comparison")
10672             {
10673                 // compare objects only by size of its elements
10674                 json j_array2 = {13, 29, 3, {"Hello", "World"}, true, false, {{"one", 1}, {"two", 2}, {"three", 3}}, "foo", "baz"};
10675                 CHECK(not std::equal(j_array.begin(), j_array.end(), j_array2.begin()));
10676                 CHECK(std::equal(j_array.begin(), j_array.end(), j_array2.begin(),
10677                                  [](const json & a, const json & b)
10678                 {
10679                     return (a.size() == b.size());
10680                 }));
10681             }
10682         }
10683 
10684         SECTION("std::find")
10685         {
10686             auto it = std::find(j_array.begin(), j_array.end(), json(false));
10687             CHECK(std::distance(j_array.begin(), it) == 5);
10688         }
10689 
10690         SECTION("std::find_if")
10691         {
10692             auto it = std::find_if(j_array.begin(), j_array.end(),
10693                                    [](const json & value)
10694             {
10695                 return value.is_boolean();
10696             });
10697             CHECK(std::distance(j_array.begin(), it) == 4);
10698         }
10699 
10700         SECTION("std::find_if_not")
10701         {
10702             auto it = std::find_if_not(j_array.begin(), j_array.end(),
10703                                        [](const json & value)
10704             {
10705                 return value.is_number();
10706             });
10707             CHECK(std::distance(j_array.begin(), it) == 3);
10708         }
10709 
10710         SECTION("std::adjacent_find")
10711         {
10712             CHECK(std::adjacent_find(j_array.begin(), j_array.end()) == j_array.end());
10713             CHECK(std::adjacent_find(j_array.begin(), j_array.end(),
10714                                      [](const json & v1, const json & v2)
10715             {
10716                 return v1.type() == v2.type();
10717             }) == j_array.begin());
10718         }
10719     }
10720 
10721     SECTION("modifying sequence operations")
10722     {
10723         SECTION("std::reverse")
10724         {
10725             std::reverse(j_array.begin(), j_array.end());
10726             CHECK(j_array == json({"baz", "foo", {1, 2, 3}, false, true, {{"one", 1}, {"two", 2}}, 3, 29, 13}));
10727         }
10728 
10729         SECTION("std::rotate")
10730         {
10731             std::rotate(j_array.begin(), j_array.begin() + 1, j_array.end());
10732             CHECK(j_array == json({29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", 13}));
10733         }
10734 
10735         SECTION("std::partition")
10736         {
10737             auto it = std::partition(j_array.begin(), j_array.end(), [](const json & v)
10738             {
10739                 return v.is_string();
10740             });
10741             CHECK(std::distance(j_array.begin(), it) == 2);
10742             CHECK(not it[2].is_string());
10743         }
10744     }
10745 
10746     SECTION("sorting operations")
10747     {
10748         SECTION("std::sort")
10749         {
10750             SECTION("with standard comparison")
10751             {
10752                 json j = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", nullptr};
10753                 std::sort(j.begin(), j.end());
10754                 CHECK(j == json({nullptr, false, true, 3, 13, 29, {{"one", 1}, {"two", 2}}, {1, 2, 3}, "baz", "foo"}));
10755             }
10756 
10757             SECTION("with user-defined comparison")
10758             {
10759                 json j = {3, {{"one", 1}, {"two", 2}}, {1, 2, 3}, nullptr};
10760                 std::sort(j.begin(), j.end(), [](const json & a, const json & b)
10761                 {
10762                     return a.size() < b.size();
10763                 });
10764                 CHECK(j == json({nullptr, 3, {{"one", 1}, {"two", 2}}, {1, 2, 3}}));
10765             }
10766 
10767             SECTION("sorting an object")
10768             {
10769                 json j({{"one", 1}, {"two", 2}});
10770                 CHECK_THROWS_AS(std::sort(j.begin(), j.end()), std::domain_error);
10771                 CHECK_THROWS_WITH(std::sort(j.begin(), j.end()), "cannot use offsets with object iterators");
10772             }
10773         }
10774 
10775         SECTION("std::partial_sort")
10776         {
10777             json j = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", nullptr};
10778             std::partial_sort(j.begin(), j.begin() + 4, j.end());
10779             CHECK(j == json({nullptr, false, true, 3, {{"one", 1}, {"two", 2}}, 29, {1, 2, 3}, "foo", "baz", 13}));
10780         }
10781     }
10782 
10783     SECTION("set operations")
10784     {
10785         SECTION("std::merge")
10786         {
10787             {
10788                 json j1 = {2, 4, 6, 8};
10789                 json j2 = {1, 2, 3, 5, 7};
10790                 json j3;
10791 
10792                 std::merge(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
10793                 CHECK(j3 == json({1, 2, 2, 3, 4, 5, 6, 7, 8}));
10794             }
10795         }
10796 
10797         SECTION("std::set_difference")
10798         {
10799             json j1 = {1, 2, 3, 4, 5, 6, 7, 8};
10800             json j2 = {1, 2, 3, 5, 7};
10801             json j3;
10802 
10803             std::set_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
10804             CHECK(j3 == json({4, 6, 8}));
10805         }
10806 
10807         SECTION("std::set_intersection")
10808         {
10809             json j1 = {1, 2, 3, 4, 5, 6, 7, 8};
10810             json j2 = {1, 2, 3, 5, 7};
10811             json j3;
10812 
10813             std::set_intersection(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
10814             CHECK(j3 == json({1, 2, 3, 5, 7}));
10815         }
10816 
10817         SECTION("std::set_union")
10818         {
10819             json j1 = {2, 4, 6, 8};
10820             json j2 = {1, 2, 3, 5, 7};
10821             json j3;
10822 
10823             std::set_union(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
10824             CHECK(j3 == json({1, 2, 3, 4, 5, 6, 7, 8}));
10825         }
10826 
10827         SECTION("std::set_symmetric_difference")
10828         {
10829             json j1 = {2, 4, 6, 8};
10830             json j2 = {1, 2, 3, 5, 7};
10831             json j3;
10832 
10833             std::set_symmetric_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
10834             CHECK(j3 == json({1, 3, 4, 5, 6, 7, 8}));
10835         }
10836     }
10837 
10838     SECTION("heap operations")
10839     {
10840         std::make_heap(j_array.begin(), j_array.end());
10841         CHECK(std::is_heap(j_array.begin(), j_array.end()));
10842         std::sort_heap(j_array.begin(), j_array.end());
10843         CHECK(j_array == json({false, true, 3, 13, 29, {{"one", 1}, {"two", 2}}, {1, 2, 3}, "baz", "foo"}));
10844     }
10845 }
10846 
10847 TEST_CASE("concepts")
10848 {
10849     SECTION("container requirements for json")
10850     {
10851         // X: container class: json
10852         // T: type of objects: json
10853         // a, b: values of type X: json
10854 
10855         // TABLE 96 - Container Requirements
10856 
10857         // X::value_type must return T
10858         CHECK((std::is_same<json::value_type, json>::value));
10859 
10860         // X::reference must return lvalue of T
10861         CHECK((std::is_same<json::reference, json&>::value));
10862 
10863         // X::const_reference must return const lvalue of T
10864         CHECK((std::is_same<json::const_reference, const json&>::value));
10865 
10866         // X::iterator must return iterator whose value_type is T
10867         CHECK((std::is_same<json::iterator::value_type, json>::value));
10868         // X::iterator must meet the forward iterator requirements
10869         CHECK((std::is_base_of<std::forward_iterator_tag, typename std::iterator_traits<json::iterator>::iterator_category>::value));
10870         // X::iterator must be convertible to X::const_iterator
10871         CHECK((std::is_convertible<json::iterator, json::const_iterator>::value));
10872 
10873         // X::const_iterator must return iterator whose value_type is T
10874         CHECK((std::is_same<json::const_iterator::value_type, json>::value));
10875         // X::const_iterator must meet the forward iterator requirements
10876         CHECK((std::is_base_of<std::forward_iterator_tag, typename std::iterator_traits<json::const_iterator>::iterator_category>::value));
10877 
10878         // X::difference_type must return a signed integer
10879         CHECK((std::is_signed<json::difference_type>::value));
10880         // X::difference_type must be identical to X::iterator::difference_type
10881         CHECK((std::is_same<json::difference_type, json::iterator::difference_type>::value));
10882         // X::difference_type must be identical to X::const_iterator::difference_type
10883         CHECK((std::is_same<json::difference_type, json::const_iterator::difference_type>::value));
10884 
10885         // X::size_type must return an unsigned integer
10886         CHECK((std::is_unsigned<json::size_type>::value));
10887         // X::size_type can represent any non-negative value of X::difference_type
10888         CHECK(std::numeric_limits<json::difference_type>::max() <=
10889               std::numeric_limits<json::size_type>::max());
10890 
10891         // the expression "X u" has the post-condition "u.empty()"
10892         {
10893             json u;
10894             CHECK(u.empty());
10895         }
10896 
10897         // the expression "X()" has the post-condition "X().empty()"
10898         CHECK(json().empty());
10899     }
10900 
10901     SECTION("class json")
10902     {
10903         SECTION("DefaultConstructible")
10904         {
10905             CHECK(std::is_nothrow_default_constructible<json>::value);
10906         }
10907 
10908         SECTION("MoveConstructible")
10909         {
10910             CHECK(std::is_nothrow_move_constructible<json>::value);
10911         }
10912 
10913         SECTION("CopyConstructible")
10914         {
10915             CHECK(std::is_copy_constructible<json>::value);
10916         }
10917 
10918         SECTION("MoveAssignable")
10919         {
10920             CHECK(std::is_nothrow_move_assignable<json>::value);
10921         }
10922 
10923         SECTION("CopyAssignable")
10924         {
10925             CHECK(std::is_copy_assignable<json>::value);
10926         }
10927 
10928         SECTION("Destructible")
10929         {
10930             CHECK(std::is_nothrow_destructible<json>::value);
10931         }
10932 
10933         SECTION("StandardLayoutType")
10934         {
10935             CHECK(std::is_standard_layout<json>::value);
10936         }
10937     }
10938 
10939     SECTION("class iterator")
10940     {
10941         SECTION("CopyConstructible")
10942         {
10943             CHECK(std::is_nothrow_copy_constructible<json::iterator>::value);
10944             CHECK(std::is_nothrow_copy_constructible<json::const_iterator>::value);
10945         }
10946 
10947         SECTION("CopyAssignable")
10948         {
10949             // STL iterators used by json::iterator don't pass this test in Debug mode
10950 #if !defined(_MSC_VER) || (_ITERATOR_DEBUG_LEVEL == 0)
10951             CHECK(std::is_nothrow_copy_assignable<json::iterator>::value);
10952             CHECK(std::is_nothrow_copy_assignable<json::const_iterator>::value);
10953 #endif
10954         }
10955 
10956         SECTION("Destructible")
10957         {
10958             CHECK(std::is_nothrow_destructible<json::iterator>::value);
10959             CHECK(std::is_nothrow_destructible<json::const_iterator>::value);
10960         }
10961 
10962         SECTION("Swappable")
10963         {
10964             {
10965                 json j {1, 2, 3};
10966                 json::iterator it1 = j.begin();
10967                 json::iterator it2 = j.end();
10968                 std::swap(it1, it2);
10969                 CHECK(it1 == j.end());
10970                 CHECK(it2 == j.begin());
10971             }
10972             {
10973                 json j {1, 2, 3};
10974                 json::const_iterator it1 = j.cbegin();
10975                 json::const_iterator it2 = j.cend();
10976                 std::swap(it1, it2);
10977                 CHECK(it1 == j.end());
10978                 CHECK(it2 == j.begin());
10979             }
10980         }
10981     }
10982 }
10983 
10984 TEST_CASE("iterator_wrapper")
10985 {
10986     SECTION("object")
10987     {
10988         SECTION("value")
10989         {
10990             json j = {{"A", 1}, {"B", 2}};
10991             int counter = 1;
10992 
10993             for (auto i : json::iterator_wrapper(j))
10994             {
10995                 switch (counter++)
10996                 {
10997                     case 1:
10998                     {
10999                         CHECK(i.key() == "A");
11000                         CHECK(i.value() == json(1));
11001                         break;
11002                     }
11003 
11004                     case 2:
11005                     {
11006                         CHECK(i.key() == "B");
11007                         CHECK(i.value() == json(2));
11008                         break;
11009                     }
11010 
11011                     default:
11012                     {
11013                         break;
11014                     }
11015                 }
11016             }
11017 
11018             CHECK(counter == 3);
11019         }
11020 
11021         SECTION("reference")
11022         {
11023             json j = {{"A", 1}, {"B", 2}};
11024             int counter = 1;
11025 
11026             for (auto& i : json::iterator_wrapper(j))
11027             {
11028                 switch (counter++)
11029                 {
11030                     case 1:
11031                     {
11032                         CHECK(i.key() == "A");
11033                         CHECK(i.value() == json(1));
11034 
11035                         // change the value
11036                         i.value() = json(11);
11037                         CHECK(i.value() == json(11));
11038                         break;
11039                     }
11040 
11041                     case 2:
11042                     {
11043                         CHECK(i.key() == "B");
11044                         CHECK(i.value() == json(2));
11045 
11046                         // change the value
11047                         i.value() = json(22);
11048                         CHECK(i.value() == json(22));
11049                         break;
11050                     }
11051 
11052                     default:
11053                     {
11054                         break;
11055                     }
11056                 }
11057             }
11058 
11059             CHECK(counter == 3);
11060 
11061             // check if values where changed
11062             CHECK(j == json({{"A", 11}, {"B", 22}}));
11063         }
11064 
11065         SECTION("const value")
11066         {
11067             json j = {{"A", 1}, {"B", 2}};
11068             int counter = 1;
11069 
11070             for (const auto i : json::iterator_wrapper(j))
11071             {
11072                 switch (counter++)
11073                 {
11074                     case 1:
11075                     {
11076                         CHECK(i.key() == "A");
11077                         CHECK(i.value() == json(1));
11078                         break;
11079                     }
11080 
11081                     case 2:
11082                     {
11083                         CHECK(i.key() == "B");
11084                         CHECK(i.value() == json(2));
11085                         break;
11086                     }
11087 
11088                     default:
11089                     {
11090                         break;
11091                     }
11092                 }
11093             }
11094 
11095             CHECK(counter == 3);
11096         }
11097 
11098         SECTION("const reference")
11099         {
11100             json j = {{"A", 1}, {"B", 2}};
11101             int counter = 1;
11102 
11103             for (const auto& i : json::iterator_wrapper(j))
11104             {
11105                 switch (counter++)
11106                 {
11107                     case 1:
11108                     {
11109                         CHECK(i.key() == "A");
11110                         CHECK(i.value() == json(1));
11111                         break;
11112                     }
11113 
11114                     case 2:
11115                     {
11116                         CHECK(i.key() == "B");
11117                         CHECK(i.value() == json(2));
11118                         break;
11119                     }
11120 
11121                     default:
11122                     {
11123                         break;
11124                     }
11125                 }
11126             }
11127 
11128             CHECK(counter == 3);
11129         }
11130     }
11131 
11132     SECTION("const object")
11133     {
11134         SECTION("value")
11135         {
11136             const json j = {{"A", 1}, {"B", 2}};
11137             int counter = 1;
11138 
11139             for (auto i : json::iterator_wrapper(j))
11140             {
11141                 switch (counter++)
11142                 {
11143                     case 1:
11144                     {
11145                         CHECK(i.key() == "A");
11146                         CHECK(i.value() == json(1));
11147                         break;
11148                     }
11149 
11150                     case 2:
11151                     {
11152                         CHECK(i.key() == "B");
11153                         CHECK(i.value() == json(2));
11154                         break;
11155                     }
11156 
11157                     default:
11158                     {
11159                         break;
11160                     }
11161                 }
11162             }
11163 
11164             CHECK(counter == 3);
11165         }
11166 
11167         SECTION("reference")
11168         {
11169             const json j = {{"A", 1}, {"B", 2}};
11170             int counter = 1;
11171 
11172             for (auto& i : json::iterator_wrapper(j))
11173             {
11174                 switch (counter++)
11175                 {
11176                     case 1:
11177                     {
11178                         CHECK(i.key() == "A");
11179                         CHECK(i.value() == json(1));
11180                         break;
11181                     }
11182 
11183                     case 2:
11184                     {
11185                         CHECK(i.key() == "B");
11186                         CHECK(i.value() == json(2));
11187                         break;
11188                     }
11189 
11190                     default:
11191                     {
11192                         break;
11193                     }
11194                 }
11195             }
11196 
11197             CHECK(counter == 3);
11198         }
11199 
11200         SECTION("const value")
11201         {
11202             const json j = {{"A", 1}, {"B", 2}};
11203             int counter = 1;
11204 
11205             for (const auto i : json::iterator_wrapper(j))
11206             {
11207                 switch (counter++)
11208                 {
11209                     case 1:
11210                     {
11211                         CHECK(i.key() == "A");
11212                         CHECK(i.value() == json(1));
11213                         break;
11214                     }
11215 
11216                     case 2:
11217                     {
11218                         CHECK(i.key() == "B");
11219                         CHECK(i.value() == json(2));
11220                         break;
11221                     }
11222 
11223                     default:
11224                     {
11225                         break;
11226                     }
11227                 }
11228             }
11229 
11230             CHECK(counter == 3);
11231         }
11232 
11233         SECTION("const reference")
11234         {
11235             const json j = {{"A", 1}, {"B", 2}};
11236             int counter = 1;
11237 
11238             for (const auto& i : json::iterator_wrapper(j))
11239             {
11240                 switch (counter++)
11241                 {
11242                     case 1:
11243                     {
11244                         CHECK(i.key() == "A");
11245                         CHECK(i.value() == json(1));
11246                         break;
11247                     }
11248 
11249                     case 2:
11250                     {
11251                         CHECK(i.key() == "B");
11252                         CHECK(i.value() == json(2));
11253                         break;
11254                     }
11255 
11256                     default:
11257                     {
11258                         break;
11259                     }
11260                 }
11261             }
11262 
11263             CHECK(counter == 3);
11264         }
11265     }
11266 
11267     SECTION("array")
11268     {
11269         SECTION("value")
11270         {
11271             json j = {"A", "B"};
11272             int counter = 1;
11273 
11274             for (auto i : json::iterator_wrapper(j))
11275             {
11276                 switch (counter++)
11277                 {
11278                     case 1:
11279                     {
11280                         CHECK(i.key() == "0");
11281                         CHECK(i.value() == "A");
11282                         break;
11283                     }
11284 
11285                     case 2:
11286                     {
11287                         CHECK(i.key() == "1");
11288                         CHECK(i.value() == "B");
11289                         break;
11290                     }
11291 
11292                     default:
11293                     {
11294                         break;
11295                     }
11296                 }
11297             }
11298 
11299             CHECK(counter == 3);
11300         }
11301 
11302         SECTION("reference")
11303         {
11304             json j = {"A", "B"};
11305             int counter = 1;
11306 
11307             for (auto& i : json::iterator_wrapper(j))
11308             {
11309                 switch (counter++)
11310                 {
11311                     case 1:
11312                     {
11313                         CHECK(i.key() == "0");
11314                         CHECK(i.value() == "A");
11315 
11316                         // change the value
11317                         i.value() = "AA";
11318                         CHECK(i.value() == "AA");
11319                         break;
11320                     }
11321 
11322                     case 2:
11323                     {
11324                         CHECK(i.key() == "1");
11325                         CHECK(i.value() == "B");
11326 
11327                         // change the value
11328                         i.value() = "BB";
11329                         CHECK(i.value() == "BB");
11330                         break;
11331                     }
11332 
11333                     default:
11334                     {
11335                         break;
11336                     }
11337                 }
11338             }
11339 
11340             CHECK(counter == 3);
11341 
11342             // check if values where changed
11343             CHECK(j == json({"AA", "BB"}));
11344         }
11345 
11346         SECTION("const value")
11347         {
11348             json j = {"A", "B"};
11349             int counter = 1;
11350 
11351             for (const auto i : json::iterator_wrapper(j))
11352             {
11353                 switch (counter++)
11354                 {
11355                     case 1:
11356                     {
11357                         CHECK(i.key() == "0");
11358                         CHECK(i.value() == "A");
11359                         break;
11360                     }
11361 
11362                     case 2:
11363                     {
11364                         CHECK(i.key() == "1");
11365                         CHECK(i.value() == "B");
11366                         break;
11367                     }
11368 
11369                     default:
11370                     {
11371                         break;
11372                     }
11373                 }
11374             }
11375 
11376             CHECK(counter == 3);
11377         }
11378 
11379         SECTION("const reference")
11380         {
11381             json j = {"A", "B"};
11382             int counter = 1;
11383 
11384             for (const auto& i : json::iterator_wrapper(j))
11385             {
11386                 switch (counter++)
11387                 {
11388                     case 1:
11389                     {
11390                         CHECK(i.key() == "0");
11391                         CHECK(i.value() == "A");
11392                         break;
11393                     }
11394 
11395                     case 2:
11396                     {
11397                         CHECK(i.key() == "1");
11398                         CHECK(i.value() == "B");
11399                         break;
11400                     }
11401 
11402                     default:
11403                     {
11404                         break;
11405                     }
11406                 }
11407             }
11408 
11409             CHECK(counter == 3);
11410         }
11411     }
11412 
11413     SECTION("const array")
11414     {
11415         SECTION("value")
11416         {
11417             const json j = {"A", "B"};
11418             int counter = 1;
11419 
11420             for (auto i : json::iterator_wrapper(j))
11421             {
11422                 switch (counter++)
11423                 {
11424                     case 1:
11425                     {
11426                         CHECK(i.key() == "0");
11427                         CHECK(i.value() == "A");
11428                         break;
11429                     }
11430 
11431                     case 2:
11432                     {
11433                         CHECK(i.key() == "1");
11434                         CHECK(i.value() == "B");
11435                         break;
11436                     }
11437 
11438                     default:
11439                     {
11440                         break;
11441                     }
11442                 }
11443             }
11444 
11445             CHECK(counter == 3);
11446         }
11447 
11448         SECTION("reference")
11449         {
11450             const json j = {"A", "B"};
11451             int counter = 1;
11452 
11453             for (auto& i : json::iterator_wrapper(j))
11454             {
11455                 switch (counter++)
11456                 {
11457                     case 1:
11458                     {
11459                         CHECK(i.key() == "0");
11460                         CHECK(i.value() == "A");
11461                         break;
11462                     }
11463 
11464                     case 2:
11465                     {
11466                         CHECK(i.key() == "1");
11467                         CHECK(i.value() == "B");
11468                         break;
11469                     }
11470 
11471                     default:
11472                     {
11473                         break;
11474                     }
11475                 }
11476             }
11477 
11478             CHECK(counter == 3);
11479         }
11480 
11481         SECTION("const value")
11482         {
11483             const json j = {"A", "B"};
11484             int counter = 1;
11485 
11486             for (const auto i : json::iterator_wrapper(j))
11487             {
11488                 switch (counter++)
11489                 {
11490                     case 1:
11491                     {
11492                         CHECK(i.key() == "0");
11493                         CHECK(i.value() == "A");
11494                         break;
11495                     }
11496 
11497                     case 2:
11498                     {
11499                         CHECK(i.key() == "1");
11500                         CHECK(i.value() == "B");
11501                         break;
11502                     }
11503 
11504                     default:
11505                     {
11506                         break;
11507                     }
11508                 }
11509             }
11510 
11511             CHECK(counter == 3);
11512         }
11513 
11514         SECTION("const reference")
11515         {
11516             const json j = {"A", "B"};
11517             int counter = 1;
11518 
11519             for (const auto& i : json::iterator_wrapper(j))
11520             {
11521                 switch (counter++)
11522                 {
11523                     case 1:
11524                     {
11525                         CHECK(i.key() == "0");
11526                         CHECK(i.value() == "A");
11527                         break;
11528                     }
11529 
11530                     case 2:
11531                     {
11532                         CHECK(i.key() == "1");
11533                         CHECK(i.value() == "B");
11534                         break;
11535                     }
11536 
11537                     default:
11538                     {
11539                         break;
11540                     }
11541                 }
11542             }
11543 
11544             CHECK(counter == 3);
11545         }
11546     }
11547 
11548     SECTION("primitive")
11549     {
11550         SECTION("value")
11551         {
11552             json j = 1;
11553             int counter = 1;
11554 
11555             for (auto i : json::iterator_wrapper(j))
11556             {
11557                 ++counter;
11558                 CHECK(i.key() == "");
11559                 CHECK(i.value() == json(1));
11560             }
11561 
11562             CHECK(counter == 2);
11563         }
11564 
11565         SECTION("reference")
11566         {
11567             json j = 1;
11568             int counter = 1;
11569 
11570             for (auto& i : json::iterator_wrapper(j))
11571             {
11572                 ++counter;
11573                 CHECK(i.key() == "");
11574                 CHECK(i.value() == json(1));
11575 
11576                 // change value
11577                 i.value() = json(2);
11578             }
11579 
11580             CHECK(counter == 2);
11581 
11582             // check if value has changed
11583             CHECK(j == json(2));
11584         }
11585 
11586         SECTION("const value")
11587         {
11588             json j = 1;
11589             int counter = 1;
11590 
11591             for (const auto i : json::iterator_wrapper(j))
11592             {
11593                 ++counter;
11594                 CHECK(i.key() == "");
11595                 CHECK(i.value() == json(1));
11596             }
11597 
11598             CHECK(counter == 2);
11599         }
11600 
11601         SECTION("const reference")
11602         {
11603             json j = 1;
11604             int counter = 1;
11605 
11606             for (const auto& i : json::iterator_wrapper(j))
11607             {
11608                 ++counter;
11609                 CHECK(i.key() == "");
11610                 CHECK(i.value() == json(1));
11611             }
11612 
11613             CHECK(counter == 2);
11614         }
11615     }
11616 
11617     SECTION("const primitive")
11618     {
11619         SECTION("value")
11620         {
11621             const json j = 1;
11622             int counter = 1;
11623 
11624             for (auto i : json::iterator_wrapper(j))
11625             {
11626                 ++counter;
11627                 CHECK(i.key() == "");
11628                 CHECK(i.value() == json(1));
11629             }
11630 
11631             CHECK(counter == 2);
11632         }
11633 
11634         SECTION("reference")
11635         {
11636             const json j = 1;
11637             int counter = 1;
11638 
11639             for (auto& i : json::iterator_wrapper(j))
11640             {
11641                 ++counter;
11642                 CHECK(i.key() == "");
11643                 CHECK(i.value() == json(1));
11644             }
11645 
11646             CHECK(counter == 2);
11647         }
11648 
11649         SECTION("const value")
11650         {
11651             const json j = 1;
11652             int counter = 1;
11653 
11654             for (const auto i : json::iterator_wrapper(j))
11655             {
11656                 ++counter;
11657                 CHECK(i.key() == "");
11658                 CHECK(i.value() == json(1));
11659             }
11660 
11661             CHECK(counter == 2);
11662         }
11663 
11664         SECTION("const reference")
11665         {
11666             const json j = 1;
11667             int counter = 1;
11668 
11669             for (const auto& i : json::iterator_wrapper(j))
11670             {
11671                 ++counter;
11672                 CHECK(i.key() == "");
11673                 CHECK(i.value() == json(1));
11674             }
11675 
11676             CHECK(counter == 2);
11677         }
11678     }
11679 }
11680 
11681 TEST_CASE("compliance tests from json.org")
11682 {
11683     // test cases are from http://json.org/JSON_checker/
11684 
11685     SECTION("expected failures")
11686     {
11687         for (auto filename :
11688                 {
11689                     //"test/data/json_tests/fail1.json",
11690                     "test/data/json_tests/fail2.json",
11691                     "test/data/json_tests/fail3.json",
11692                     "test/data/json_tests/fail4.json",
11693                     "test/data/json_tests/fail5.json",
11694                     "test/data/json_tests/fail6.json",
11695                     "test/data/json_tests/fail7.json",
11696                     "test/data/json_tests/fail8.json",
11697                     "test/data/json_tests/fail9.json",
11698                     "test/data/json_tests/fail10.json",
11699                     "test/data/json_tests/fail11.json",
11700                     "test/data/json_tests/fail12.json",
11701                     "test/data/json_tests/fail13.json",
11702                     "test/data/json_tests/fail14.json",
11703                     "test/data/json_tests/fail15.json",
11704                     "test/data/json_tests/fail16.json",
11705                     "test/data/json_tests/fail17.json",
11706                     //"test/data/json_tests/fail18.json",
11707                     "test/data/json_tests/fail19.json",
11708                     "test/data/json_tests/fail20.json",
11709                     "test/data/json_tests/fail21.json",
11710                     "test/data/json_tests/fail22.json",
11711                     "test/data/json_tests/fail23.json",
11712                     "test/data/json_tests/fail24.json",
11713                     "test/data/json_tests/fail25.json",
11714                     "test/data/json_tests/fail26.json",
11715                     "test/data/json_tests/fail27.json",
11716                     "test/data/json_tests/fail28.json",
11717                     "test/data/json_tests/fail29.json",
11718                     "test/data/json_tests/fail30.json",
11719                     "test/data/json_tests/fail31.json",
11720                     "test/data/json_tests/fail32.json",
11721                     "test/data/json_tests/fail33.json"
11722                 })
11723         {
11724             CAPTURE(filename);
11725             json j;
11726             std::ifstream f(filename);
11727             CHECK_THROWS_AS(j << f, std::invalid_argument);
11728         }
11729     }
11730 
11731     SECTION("expected passes")
11732     {
11733         for (auto filename :
11734                 {
11735                     "test/data/json_tests/pass1.json",
11736                     "test/data/json_tests/pass2.json",
11737                     "test/data/json_tests/pass3.json"
11738                 })
11739         {
11740             CAPTURE(filename);
11741             json j;
11742             std::ifstream f(filename);
11743             CHECK_NOTHROW(j << f);
11744         }
11745     }
11746 }
11747 
11748 TEST_CASE("compliance tests from nativejson-benchmark")
11749 {
11750     // test cases from https://github.com/miloyip/nativejson-benchmark/blob/master/src/main.cpp
11751 
11752     SECTION("doubles")
11753     {
11754         auto TEST_DOUBLE = [](const std::string & json_string, const double expected)
11755         {
11756             CAPTURE(json_string);
11757             CAPTURE(expected);
11758             CHECK(json::parse(json_string)[0].get<double>() == Approx(expected));
11759         };
11760 
11761         TEST_DOUBLE("[0.0]", 0.0);
11762         TEST_DOUBLE("[-0.0]", -0.0);
11763         TEST_DOUBLE("[1.0]", 1.0);
11764         TEST_DOUBLE("[-1.0]", -1.0);
11765         TEST_DOUBLE("[1.5]", 1.5);
11766         TEST_DOUBLE("[-1.5]", -1.5);
11767         TEST_DOUBLE("[3.1416]", 3.1416);
11768         TEST_DOUBLE("[1E10]", 1E10);
11769         TEST_DOUBLE("[1e10]", 1e10);
11770         TEST_DOUBLE("[1E+10]", 1E+10);
11771         TEST_DOUBLE("[1E-10]", 1E-10);
11772         TEST_DOUBLE("[-1E10]", -1E10);
11773         TEST_DOUBLE("[-1e10]", -1e10);
11774         TEST_DOUBLE("[-1E+10]", -1E+10);
11775         TEST_DOUBLE("[-1E-10]", -1E-10);
11776         TEST_DOUBLE("[1.234E+10]", 1.234E+10);
11777         TEST_DOUBLE("[1.234E-10]", 1.234E-10);
11778         TEST_DOUBLE("[1.79769e+308]", 1.79769e+308);
11779         TEST_DOUBLE("[2.22507e-308]", 2.22507e-308);
11780         TEST_DOUBLE("[-1.79769e+308]", -1.79769e+308);
11781         TEST_DOUBLE("[-2.22507e-308]", -2.22507e-308);
11782         TEST_DOUBLE("[4.9406564584124654e-324]", 4.9406564584124654e-324); // minimum denormal
11783         TEST_DOUBLE("[2.2250738585072009e-308]", 2.2250738585072009e-308); // Max subnormal double
11784         TEST_DOUBLE("[2.2250738585072014e-308]", 2.2250738585072014e-308); // Min normal positive double
11785         TEST_DOUBLE("[1.7976931348623157e+308]", 1.7976931348623157e+308); // Max double
11786         TEST_DOUBLE("[1e-10000]", 0.0);                                   // must underflow
11787         TEST_DOUBLE("[18446744073709551616]",
11788                     18446744073709551616.0);    // 2^64 (max of uint64_t + 1, force to use double)
11789         TEST_DOUBLE("[-9223372036854775809]",
11790                     -9223372036854775809.0);    // -2^63 - 1(min of int64_t + 1, force to use double)
11791         TEST_DOUBLE("[0.9868011474609375]",
11792                     0.9868011474609375);          // https://github.com/miloyip/rapidjson/issues/120
11793         TEST_DOUBLE("[123e34]", 123e34);                                  // Fast Path Cases In Disguise
11794         TEST_DOUBLE("[45913141877270640000.0]", 45913141877270640000.0);
11795         TEST_DOUBLE("[2.2250738585072011e-308]",
11796                     2.2250738585072011e-308);
11797         //TEST_DOUBLE("[1e-00011111111111]", 0.0);
11798         //TEST_DOUBLE("[-1e-00011111111111]", -0.0);
11799         TEST_DOUBLE("[1e-214748363]", 0.0);
11800         TEST_DOUBLE("[1e-214748364]", 0.0);
11801         //TEST_DOUBLE("[1e-21474836311]", 0.0);
11802         TEST_DOUBLE("[0.017976931348623157e+310]", 1.7976931348623157e+308); // Max double in another form
11803 
11804         // Since
11805         // abs((2^-1022 - 2^-1074) - 2.2250738585072012e-308) = 3.109754131239141401123495768877590405345064751974375599... ¡Á 10^-324
11806         // abs((2^-1022) - 2.2250738585072012e-308) = 1.830902327173324040642192159804623318305533274168872044... ¡Á 10 ^ -324
11807         // So 2.2250738585072012e-308 should round to 2^-1022 = 2.2250738585072014e-308
11808         TEST_DOUBLE("[2.2250738585072012e-308]",
11809                     2.2250738585072014e-308);
11810 
11811         // More closer to normal/subnormal boundary
11812         // boundary = 2^-1022 - 2^-1075 = 2.225073858507201136057409796709131975934819546351645648... ¡Á 10^-308
11813         TEST_DOUBLE("[2.22507385850720113605740979670913197593481954635164564e-308]",
11814                     2.2250738585072009e-308);
11815         TEST_DOUBLE("[2.22507385850720113605740979670913197593481954635164565e-308]",
11816                     2.2250738585072014e-308);
11817 
11818         // 1.0 is in (1.0 - 2^-54, 1.0 + 2^-53)
11819         // 1.0 - 2^-54 = 0.999999999999999944488848768742172978818416595458984375
11820         TEST_DOUBLE("[0.999999999999999944488848768742172978818416595458984375]", 1.0); // round to even
11821         TEST_DOUBLE("[0.999999999999999944488848768742172978818416595458984374]",
11822                     0.99999999999999989); // previous double
11823         TEST_DOUBLE("[0.999999999999999944488848768742172978818416595458984376]", 1.0); // next double
11824         // 1.0 + 2^-53 = 1.00000000000000011102230246251565404236316680908203125
11825         TEST_DOUBLE("[1.00000000000000011102230246251565404236316680908203125]", 1.0); // round to even
11826         TEST_DOUBLE("[1.00000000000000011102230246251565404236316680908203124]", 1.0); // previous double
11827         TEST_DOUBLE("[1.00000000000000011102230246251565404236316680908203126]",
11828                     1.00000000000000022); // next double
11829 
11830         // Numbers from https://github.com/floitsch/double-conversion/blob/master/test/cctest/test-strtod.cc
11831 
11832         TEST_DOUBLE("[72057594037927928.0]", 72057594037927928.0);
11833         TEST_DOUBLE("[72057594037927936.0]", 72057594037927936.0);
11834         TEST_DOUBLE("[72057594037927932.0]", 72057594037927936.0);
11835         TEST_DOUBLE("[7205759403792793199999e-5]", 72057594037927928.0);
11836         TEST_DOUBLE("[7205759403792793200001e-5]", 72057594037927936.0);
11837 
11838         TEST_DOUBLE("[9223372036854774784.0]", 9223372036854774784.0);
11839         TEST_DOUBLE("[9223372036854775808.0]", 9223372036854775808.0);
11840         TEST_DOUBLE("[9223372036854775296.0]", 9223372036854775808.0);
11841         TEST_DOUBLE("[922337203685477529599999e-5]", 9223372036854774784.0);
11842         TEST_DOUBLE("[922337203685477529600001e-5]", 9223372036854775808.0);
11843 
11844         TEST_DOUBLE("[10141204801825834086073718800384]", 10141204801825834086073718800384.0);
11845         TEST_DOUBLE("[10141204801825835211973625643008]", 10141204801825835211973625643008.0);
11846         TEST_DOUBLE("[10141204801825834649023672221696]", 10141204801825835211973625643008.0);
11847         TEST_DOUBLE("[1014120480182583464902367222169599999e-5]", 10141204801825834086073718800384.0);
11848         TEST_DOUBLE("[1014120480182583464902367222169600001e-5]", 10141204801825835211973625643008.0);
11849 
11850         TEST_DOUBLE("[5708990770823838890407843763683279797179383808]",
11851                     5708990770823838890407843763683279797179383808.0);
11852         TEST_DOUBLE("[5708990770823839524233143877797980545530986496]",
11853                     5708990770823839524233143877797980545530986496.0);
11854         TEST_DOUBLE("[5708990770823839207320493820740630171355185152]",
11855                     5708990770823839524233143877797980545530986496.0);
11856         TEST_DOUBLE("[5708990770823839207320493820740630171355185151999e-3]",
11857                     5708990770823838890407843763683279797179383808.0);
11858         TEST_DOUBLE("[5708990770823839207320493820740630171355185152001e-3]",
11859                     5708990770823839524233143877797980545530986496.0);
11860 
11861         {
11862             char n1e308[312];   // '1' followed by 308 '0'
11863             n1e308[0] = '[';
11864             n1e308[1] = '1';
11865             for (int j = 2; j < 310; j++)
11866             {
11867                 n1e308[j] = '0';
11868             }
11869             n1e308[310] = ']';
11870             n1e308[311] = '\0';
11871             TEST_DOUBLE(n1e308, 1E308);
11872         }
11873 
11874         // Cover trimming
11875         TEST_DOUBLE(
11876             "[2.22507385850720113605740979670913197593481954635164564802342610972482222202107694551652952390813508"
11877             "7914149158913039621106870086438694594645527657207407820621743379988141063267329253552286881372149012"
11878             "9811224514518898490572223072852551331557550159143974763979834118019993239625482890171070818506906306"
11879             "6665599493827577257201576306269066333264756530000924588831643303777979186961204949739037782970490505"
11880             "1080609940730262937128958950003583799967207254304360284078895771796150945516748243471030702609144621"
11881             "5722898802581825451803257070188608721131280795122334262883686223215037756666225039825343359745688844"
11882             "2390026549819838548794829220689472168983109969836584681402285424333066033985088644580400103493397042"
11883             "7567186443383770486037861622771738545623065874679014086723327636718751234567890123456789012345678901"
11884             "e-308]",
11885             2.2250738585072014e-308);
11886     }
11887 
11888     SECTION("strings")
11889     {
11890         auto TEST_STRING = [](const std::string & json_string, const std::string & expected)
11891         {
11892             CAPTURE(json_string);
11893             CAPTURE(expected);
11894             CHECK(json::parse(json_string)[0].get<std::string>() == expected);
11895         };
11896 
11897         TEST_STRING("[\"\"]", "");
11898         TEST_STRING("[\"Hello\"]", "Hello");
11899         TEST_STRING("[\"Hello\\nWorld\"]", "Hello\nWorld");
11900         //TEST_STRING("[\"Hello\\u0000World\"]", "Hello\0World");
11901         TEST_STRING("[\"\\\"\\\\/\\b\\f\\n\\r\\t\"]", "\"\\/\b\f\n\r\t");
11902         TEST_STRING("[\"\\u0024\"]", "\x24");         // Dollar sign U+0024
11903         TEST_STRING("[\"\\u00A2\"]", "\xC2\xA2");     // Cents sign U+00A2
11904         TEST_STRING("[\"\\u20AC\"]", "\xE2\x82\xAC"); // Euro sign U+20AC
11905         TEST_STRING("[\"\\uD834\\uDD1E\"]", "\xF0\x9D\x84\x9E");  // G clef sign U+1D11E
11906     }
11907 
11908     SECTION("roundtrip")
11909     {
11910         // test cases are from https://github.com/miloyip/nativejson-benchmark/tree/master/test/data/roundtrip
11911 
11912         for (auto filename :
11913                 {
11914                     "test/data/json_roundtrip/roundtrip01.json",
11915                     "test/data/json_roundtrip/roundtrip02.json",
11916                     "test/data/json_roundtrip/roundtrip03.json",
11917                     "test/data/json_roundtrip/roundtrip04.json",
11918                     "test/data/json_roundtrip/roundtrip05.json",
11919                     "test/data/json_roundtrip/roundtrip06.json",
11920                     "test/data/json_roundtrip/roundtrip07.json",
11921                     "test/data/json_roundtrip/roundtrip08.json",
11922                     "test/data/json_roundtrip/roundtrip09.json",
11923                     "test/data/json_roundtrip/roundtrip10.json",
11924                     "test/data/json_roundtrip/roundtrip11.json",
11925                     "test/data/json_roundtrip/roundtrip12.json",
11926                     "test/data/json_roundtrip/roundtrip13.json",
11927                     "test/data/json_roundtrip/roundtrip14.json",
11928                     "test/data/json_roundtrip/roundtrip15.json",
11929                     "test/data/json_roundtrip/roundtrip16.json",
11930                     "test/data/json_roundtrip/roundtrip17.json",
11931                     "test/data/json_roundtrip/roundtrip18.json",
11932                     "test/data/json_roundtrip/roundtrip19.json",
11933                     "test/data/json_roundtrip/roundtrip20.json",
11934                     "test/data/json_roundtrip/roundtrip21.json",
11935                     "test/data/json_roundtrip/roundtrip22.json",
11936                     "test/data/json_roundtrip/roundtrip23.json",
11937                     //"test/data/json_roundtrip/roundtrip24.json", // roundtrip error
11938                     //"test/data/json_roundtrip/roundtrip25.json", // roundtrip error
11939                     //"test/data/json_roundtrip/roundtrip26.json", // roundtrip error
11940                     //"test/data/json_roundtrip/roundtrip27.json", // roundtrip error
11941                     //"test/data/json_roundtrip/roundtrip28.json", // roundtrip error
11942                     "test/data/json_roundtrip/roundtrip29.json",
11943                     //"test/data/json_roundtrip/roundtrip30.json", // roundtrip error
11944                     //"test/data/json_roundtrip/roundtrip31.json", // roundtrip error
11945                     "test/data/json_roundtrip/roundtrip32.json"
11946                 })
11947         {
11948             CAPTURE(filename);
11949             std::ifstream f(filename);
11950             std::string json_string( (std::istreambuf_iterator<char>(f) ),
11951                                      (std::istreambuf_iterator<char>()) );
11952 
11953             json j = json::parse(json_string);
11954             CHECK(j.dump() == json_string);
11955         }
11956     }
11957 }
11958 
11959 TEST_CASE("test suite from json-test-suite")
11960 {
11961     SECTION("read all sample.json")
11962     {
11963         // read a file with all unicode characters stored as single-character
11964         // strings in a JSON array
11965         std::ifstream f("test/data/json_testsuite/sample.json");
11966         json j;
11967         CHECK_NOTHROW(j << f);
11968 
11969         // the array has 3 elements
11970         CHECK(j.size() == 3);
11971     }
11972 }
11973 
11974 TEST_CASE("json.org examples")
11975 {
11976     // here, we list all JSON values from http://json.org/example
11977 
11978     SECTION("1.json")
11979     {
11980         std::ifstream f("test/data/json.org/1.json");
11981         json j;
11982         CHECK_NOTHROW(j << f);
11983     }
11984 
11985     SECTION("2.json")
11986     {
11987         std::ifstream f("test/data/json.org/2.json");
11988         json j;
11989         CHECK_NOTHROW(j << f);
11990     }
11991 
11992     SECTION("3.json")
11993     {
11994         std::ifstream f("test/data/json.org/3.json");
11995         json j;
11996         CHECK_NOTHROW(j << f);
11997     }
11998 
11999     SECTION("4.json")
12000     {
12001         std::ifstream f("test/data/json.org/4.json");
12002         json j;
12003         CHECK_NOTHROW(j << f);
12004     }
12005 
12006     SECTION("5.json")
12007     {
12008         std::ifstream f("test/data/json.org/5.json");
12009         json j;
12010         CHECK_NOTHROW(j << f);
12011     }
12012 }
12013 
12014 TEST_CASE("RFC 7159 examples")
12015 {
12016     // here, we list all JSON values from the RFC 7159 document
12017 
12018     SECTION("7. Strings")
12019     {
12020         CHECK(json::parse("\"\\u005C\"") == json("\\"));
12021         CHECK(json::parse("\"\\uD834\\uDD1E\"") == json("𝄞"));
12022         CHECK(json::parse("\"𝄞\"") == json("𝄞"));
12023     }
12024 
12025     SECTION("8.3 String Comparison")
12026     {
12027         CHECK(json::parse("\"a\\b\"") == json::parse("\"a\u005Cb\""));
12028     }
12029 
12030     SECTION("13 Examples")
12031     {
12032         {
12033             CHECK_NOTHROW(json(R"(
12034             {
12035                  "Image": {
12036                      "Width":  800,
12037                      "Height": 600,
12038                      "Title":  "View from 15th Floor",
12039                      "Thumbnail": {
12040                          "Url":    "http://www.example.com/image/481989943",
12041                          "Height": 125,
12042                          "Width":  100
12043                      },
12044                      "Animated" : false,
12045                      "IDs": [116, 943, 234, 38793]
12046                    }
12047                }
12048             )"));
12049         }
12050 
12051         {
12052             CHECK_NOTHROW(json(R"(
12053                 [
12054                     {
12055                        "precision": "zip",
12056                        "Latitude":  37.7668,
12057                        "Longitude": -122.3959,
12058                        "Address":   "",
12059                        "City":      "SAN FRANCISCO",
12060                        "State":     "CA",
12061                        "Zip":       "94107",
12062                        "Country":   "US"
12063                     },
12064                     {
12065                        "precision": "zip",
12066                        "Latitude":  37.371991,
12067                        "Longitude": -122.026020,
12068                        "Address":   "",
12069                        "City":      "SUNNYVALE",
12070                        "State":     "CA",
12071                        "Zip":       "94085",
12072                        "Country":   "US"
12073                     }
12074             ])"));
12075         }
12076 
12077         CHECK(json::parse("\"Hello world!\"") == json("Hello world!"));
12078         CHECK(json::parse("42") == json(42));
12079         CHECK(json::parse("true") == json(true));
12080     }
12081 }
12082 
12083 TEST_CASE("Unicode", "[hide]")
12084 {
12085     SECTION("full enumeration of Unicode codepoints")
12086     {
12087         // create a string from a codepoint
12088         auto codepoint_to_unicode = [](std::size_t cp)
12089         {
12090             char* buffer = new char[10];
12091             sprintf(buffer, "\\u%04lx", cp);
12092             std::string result(buffer);
12093             delete[] buffer;
12094             return result;
12095         };
12096 
12097         // generate all codepoints
12098         for (std::size_t cp = 0; cp <= 0x10FFFFu; ++cp)
12099         {
12100             // The Unicode standard permanently reserves these code point
12101             // values for UTF-16 encoding of the high and low surrogates, and
12102             // they will never be assigned a character, so there should be no
12103             // reason to encode them. The official Unicode standard says that
12104             // no UTF forms, including UTF-16, can encode these code points.
12105             if (cp >= 0xD800u and cp <= 0xDFFFu)
12106             {
12107                 continue;
12108             }
12109 
12110             std::string res;
12111 
12112             if (cp < 0x10000u)
12113             {
12114                 // codepoint can be represented with 16 bit
12115                 res += codepoint_to_unicode(cp);
12116             }
12117             else
12118             {
12119                 // codepoint can be represented with a pair
12120                 res += codepoint_to_unicode(0xd800u + (((cp - 0x10000u) >> 10) & 0x3ffu));
12121                 res += codepoint_to_unicode(0xdc00u + ((cp - 0x10000u) & 0x3ffu));
12122             }
12123 
12124             try
12125             {
12126                 json j1, j2;
12127                 CHECK_NOTHROW(j1 = json::parse("\"" + res + "\""));
12128                 CHECK_NOTHROW(j2 = json::parse(j1.dump()));
12129                 CHECK(j1 == j2);
12130             }
12131             catch (std::invalid_argument)
12132             {
12133                 // we ignore parsing errors
12134             }
12135         }
12136     }
12137 
12138     SECTION("read all unicode characters")
12139     {
12140         // read a file with all unicode characters stored as single-character
12141         // strings in a JSON array
12142         std::ifstream f("test/data/json_nlohmann_tests/all_unicode.json");
12143         json j;
12144         CHECK_NOTHROW(j << f);
12145 
12146         // the array has 1112064 + 1 elemnts (a terminating "null" value)
12147         CHECK(j.size() == 1112065);
12148 
12149         SECTION("check JSON Pointers")
12150         {
12151             for (auto s : j)
12152             {
12153                 // skip non-string JSON values
12154                 if (not s.is_string())
12155                 {
12156                     continue;
12157                 }
12158 
12159                 std::string ptr = s;
12160 
12161                 // tilde must be followed by 0 or 1
12162                 if (ptr == "~")
12163                 {
12164                     ptr += "0";
12165                 }
12166 
12167                 // JSON Pointers must begin with "/"
12168                 ptr = "/" + ptr;
12169 
12170                 CHECK_NOTHROW(json::json_pointer("/" + ptr));
12171 
12172                 // check escape/unescape roundtrip
12173                 auto escaped = json::json_pointer::escape(ptr);
12174                 json::json_pointer::unescape(escaped);
12175                 CHECK(escaped == ptr);
12176             }
12177         }
12178     }
12179 
12180     SECTION("ignore byte-order-mark")
12181     {
12182         // read a file with a UTF-8 BOM
12183         std::ifstream f("test/data/json_nlohmann_tests/bom.json");
12184         json j;
12185         CHECK_NOTHROW(j << f);
12186     }
12187 
12188     SECTION("error for incomplete/wrong BOM")
12189     {
12190         CHECK_THROWS_AS(json::parse("\xef\xbb"), std::invalid_argument);
12191         CHECK_THROWS_AS(json::parse("\xef\xbb\xbb"), std::invalid_argument);
12192     }
12193 }
12194 
12195 TEST_CASE("JSON pointers")
12196 {
12197     SECTION("errors")
12198     {
12199         CHECK_THROWS_AS(json::json_pointer("foo"), std::domain_error);
12200         CHECK_THROWS_WITH(json::json_pointer("foo"), "JSON pointer must be empty or begin with '/'");
12201 
12202         CHECK_THROWS_AS(json::json_pointer("/~~"), std::domain_error);
12203         CHECK_THROWS_WITH(json::json_pointer("/~~"), "escape error: '~' must be followed with '0' or '1'");
12204 
12205         CHECK_THROWS_AS(json::json_pointer("/~"), std::domain_error);
12206         CHECK_THROWS_WITH(json::json_pointer("/~"), "escape error: '~' must be followed with '0' or '1'");
12207 
12208         json::json_pointer p;
12209         CHECK_THROWS_AS(p.top(), std::domain_error);
12210         CHECK_THROWS_WITH(p.top(), "JSON pointer has no parent");
12211         CHECK_THROWS_AS(p.pop_back(), std::domain_error);
12212         CHECK_THROWS_WITH(p.pop_back(), "JSON pointer has no parent");
12213     }
12214 
12215     SECTION("examples from RFC 6901")
12216     {
12217         SECTION("nonconst access")
12218         {
12219             json j = R"(
12220             {
12221                 "foo": ["bar", "baz"],
12222                 "": 0,
12223                 "a/b": 1,
12224                 "c%d": 2,
12225                 "e^f": 3,
12226                 "g|h": 4,
12227                 "i\\j": 5,
12228                 "k\"l": 6,
12229                 " ": 7,
12230                 "m~n": 8
12231             }
12232             )"_json;
12233 
12234             // the whole document
12235             CHECK(j[json::json_pointer()] == j);
12236             CHECK(j[json::json_pointer("")] == j);
12237 
12238             // array access
12239             CHECK(j[json::json_pointer("/foo")] == j["foo"]);
12240             CHECK(j[json::json_pointer("/foo/0")] == j["foo"][0]);
12241             CHECK(j[json::json_pointer("/foo/1")] == j["foo"][1]);
12242             CHECK(j["/foo/1"_json_pointer] == j["foo"][1]);
12243 
12244             // checked array access
12245             CHECK(j.at(json::json_pointer("/foo/0")) == j["foo"][0]);
12246             CHECK(j.at(json::json_pointer("/foo/1")) == j["foo"][1]);
12247 
12248             // empty string access
12249             CHECK(j[json::json_pointer("/")] == j[""]);
12250 
12251             // other cases
12252             CHECK(j[json::json_pointer("/ ")] == j[" "]);
12253             CHECK(j[json::json_pointer("/c%d")] == j["c%d"]);
12254             CHECK(j[json::json_pointer("/e^f")] == j["e^f"]);
12255             CHECK(j[json::json_pointer("/g|h")] == j["g|h"]);
12256             CHECK(j[json::json_pointer("/i\\j")] == j["i\\j"]);
12257             CHECK(j[json::json_pointer("/k\"l")] == j["k\"l"]);
12258 
12259             // checked access
12260             CHECK(j.at(json::json_pointer("/ ")) == j[" "]);
12261             CHECK(j.at(json::json_pointer("/c%d")) == j["c%d"]);
12262             CHECK(j.at(json::json_pointer("/e^f")) == j["e^f"]);
12263             CHECK(j.at(json::json_pointer("/g|h")) == j["g|h"]);
12264             CHECK(j.at(json::json_pointer("/i\\j")) == j["i\\j"]);
12265             CHECK(j.at(json::json_pointer("/k\"l")) == j["k\"l"]);
12266 
12267             // escaped access
12268             CHECK(j[json::json_pointer("/a~1b")] == j["a/b"]);
12269             CHECK(j[json::json_pointer("/m~0n")] == j["m~n"]);
12270 
12271             // unescaped access
12272             CHECK_THROWS_AS(j[json::json_pointer("/a/b")], std::out_of_range);
12273             CHECK_THROWS_WITH(j[json::json_pointer("/a/b")], "unresolved reference token 'b'");
12274             // "/a/b" works for JSON {"a": {"b": 42}}
12275             CHECK(json({{"a", {{"b", 42}}}})[json::json_pointer("/a/b")] == json(42));
12276 
12277             // unresolved access
12278             json j_primitive = 1;
12279             CHECK_THROWS_AS(j_primitive["/foo"_json_pointer], std::out_of_range);
12280             CHECK_THROWS_WITH(j_primitive["/foo"_json_pointer], "unresolved reference token 'foo'");
12281             CHECK_THROWS_AS(j_primitive.at("/foo"_json_pointer), std::out_of_range);
12282             CHECK_THROWS_WITH(j_primitive.at("/foo"_json_pointer), "unresolved reference token 'foo'");
12283         }
12284 
12285         SECTION("const access")
12286         {
12287             const json j = R"(
12288             {
12289                 "foo": ["bar", "baz"],
12290                 "": 0,
12291                 "a/b": 1,
12292                 "c%d": 2,
12293                 "e^f": 3,
12294                 "g|h": 4,
12295                 "i\\j": 5,
12296                 "k\"l": 6,
12297                 " ": 7,
12298                 "m~n": 8
12299             }
12300             )"_json;
12301 
12302             // the whole document
12303             CHECK(j[json::json_pointer()] == j);
12304             CHECK(j[json::json_pointer("")] == j);
12305 
12306             // array access
12307             CHECK(j[json::json_pointer("/foo")] == j["foo"]);
12308             CHECK(j[json::json_pointer("/foo/0")] == j["foo"][0]);
12309             CHECK(j[json::json_pointer("/foo/1")] == j["foo"][1]);
12310             CHECK(j["/foo/1"_json_pointer] == j["foo"][1]);
12311 
12312             // checked array access
12313             CHECK(j.at(json::json_pointer("/foo/0")) == j["foo"][0]);
12314             CHECK(j.at(json::json_pointer("/foo/1")) == j["foo"][1]);
12315 
12316             // empty string access
12317             CHECK(j[json::json_pointer("/")] == j[""]);
12318 
12319             // other cases
12320             CHECK(j[json::json_pointer("/ ")] == j[" "]);
12321             CHECK(j[json::json_pointer("/c%d")] == j["c%d"]);
12322             CHECK(j[json::json_pointer("/e^f")] == j["e^f"]);
12323             CHECK(j[json::json_pointer("/g|h")] == j["g|h"]);
12324             CHECK(j[json::json_pointer("/i\\j")] == j["i\\j"]);
12325             CHECK(j[json::json_pointer("/k\"l")] == j["k\"l"]);
12326 
12327             // checked access
12328             CHECK(j.at(json::json_pointer("/ ")) == j[" "]);
12329             CHECK(j.at(json::json_pointer("/c%d")) == j["c%d"]);
12330             CHECK(j.at(json::json_pointer("/e^f")) == j["e^f"]);
12331             CHECK(j.at(json::json_pointer("/g|h")) == j["g|h"]);
12332             CHECK(j.at(json::json_pointer("/i\\j")) == j["i\\j"]);
12333             CHECK(j.at(json::json_pointer("/k\"l")) == j["k\"l"]);
12334 
12335             // escaped access
12336             CHECK(j[json::json_pointer("/a~1b")] == j["a/b"]);
12337             CHECK(j[json::json_pointer("/m~0n")] == j["m~n"]);
12338 
12339             // unescaped access
12340             CHECK_THROWS_AS(j.at(json::json_pointer("/a/b")), std::out_of_range);
12341             CHECK_THROWS_WITH(j.at(json::json_pointer("/a/b")), "key 'a' not found");
12342 
12343             // unresolved access
12344             const json j_primitive = 1;
12345             CHECK_THROWS_AS(j_primitive["/foo"_json_pointer], std::out_of_range);
12346             CHECK_THROWS_WITH(j_primitive["/foo"_json_pointer], "unresolved reference token 'foo'");
12347             CHECK_THROWS_AS(j_primitive.at("/foo"_json_pointer), std::out_of_range);
12348             CHECK_THROWS_WITH(j_primitive.at("/foo"_json_pointer), "unresolved reference token 'foo'");
12349         }
12350 
12351         SECTION("user-defined string literal")
12352         {
12353             json j = R"(
12354             {
12355                 "foo": ["bar", "baz"],
12356                 "": 0,
12357                 "a/b": 1,
12358                 "c%d": 2,
12359                 "e^f": 3,
12360                 "g|h": 4,
12361                 "i\\j": 5,
12362                 "k\"l": 6,
12363                 " ": 7,
12364                 "m~n": 8
12365             }
12366             )"_json;
12367 
12368             // the whole document
12369             CHECK(j[""_json_pointer] == j);
12370 
12371             // array access
12372             CHECK(j["/foo"_json_pointer] == j["foo"]);
12373             CHECK(j["/foo/0"_json_pointer] == j["foo"][0]);
12374             CHECK(j["/foo/1"_json_pointer] == j["foo"][1]);
12375         }
12376     }
12377 
12378     SECTION("array access")
12379     {
12380         SECTION("nonconst access")
12381         {
12382             json j = {1, 2, 3};
12383             const json j_const = j;
12384 
12385             // check reading access
12386             CHECK(j["/0"_json_pointer] == j[0]);
12387             CHECK(j["/1"_json_pointer] == j[1]);
12388             CHECK(j["/2"_json_pointer] == j[2]);
12389 
12390             // assign to existing index
12391             j["/1"_json_pointer] = 13;
12392             CHECK(j[1] == json(13));
12393 
12394             // assign to nonexisting index
12395             j["/3"_json_pointer] = 33;
12396             CHECK(j[3] == json(33));
12397 
12398             // assign to nonexisting index (with gap)
12399             j["/5"_json_pointer] = 55;
12400             CHECK(j == json({1, 13, 3, 33, nullptr, 55}));
12401 
12402             // error with leading 0
12403             CHECK_THROWS_AS(j["/01"_json_pointer], std::domain_error);
12404             CHECK_THROWS_WITH(j["/01"_json_pointer], "array index must not begin with '0'");
12405             CHECK_THROWS_AS(j_const["/01"_json_pointer], std::domain_error);
12406             CHECK_THROWS_WITH(j_const["/01"_json_pointer], "array index must not begin with '0'");
12407             CHECK_THROWS_AS(j.at("/01"_json_pointer), std::domain_error);
12408             CHECK_THROWS_WITH(j.at("/01"_json_pointer), "array index must not begin with '0'");
12409             CHECK_THROWS_AS(j_const.at("/01"_json_pointer), std::domain_error);
12410             CHECK_THROWS_WITH(j_const.at("/01"_json_pointer), "array index must not begin with '0'");
12411 
12412             // error with incorrect numbers
12413             CHECK_THROWS_AS(j["/one"_json_pointer] = 1, std::invalid_argument);
12414 
12415             // assign to "-"
12416             j["/-"_json_pointer] = 99;
12417             CHECK(j == json({1, 13, 3, 33, nullptr, 55, 99}));
12418 
12419             // error when using "-" in const object
12420             CHECK_THROWS_AS(j_const["/-"_json_pointer], std::out_of_range);
12421             CHECK_THROWS_WITH(j_const["/-"_json_pointer], "array index '-' (3) is out of range");
12422 
12423             // error when using "-" with at
12424             CHECK_THROWS_AS(j.at("/-"_json_pointer), std::out_of_range);
12425             CHECK_THROWS_WITH(j.at("/-"_json_pointer), "array index '-' (7) is out of range");
12426             CHECK_THROWS_AS(j_const.at("/-"_json_pointer), std::out_of_range);
12427             CHECK_THROWS_WITH(j_const.at("/-"_json_pointer), "array index '-' (3) is out of range");
12428         }
12429 
12430         SECTION("const access")
12431         {
12432             const json j = {1, 2, 3};
12433 
12434             // check reading access
12435             CHECK(j["/0"_json_pointer] == j[0]);
12436             CHECK(j["/1"_json_pointer] == j[1]);
12437             CHECK(j["/2"_json_pointer] == j[2]);
12438 
12439             // assign to nonexisting index
12440             CHECK_THROWS_AS(j.at("/3"_json_pointer), std::out_of_range);
12441             CHECK_THROWS_WITH(j.at("/3"_json_pointer), "array index 3 is out of range");
12442 
12443             // assign to nonexisting index (with gap)
12444             CHECK_THROWS_AS(j.at("/5"_json_pointer), std::out_of_range);
12445             CHECK_THROWS_WITH(j.at("/5"_json_pointer), "array index 5 is out of range");
12446 
12447             // assign to "-"
12448             CHECK_THROWS_AS(j["/-"_json_pointer], std::out_of_range);
12449             CHECK_THROWS_WITH(j["/-"_json_pointer], "array index '-' (3) is out of range");
12450             CHECK_THROWS_AS(j.at("/-"_json_pointer), std::out_of_range);
12451             CHECK_THROWS_WITH(j.at("/-"_json_pointer), "array index '-' (3) is out of range");
12452         }
12453 
12454     }
12455 
12456     SECTION("flatten")
12457     {
12458         json j =
12459         {
12460             {"pi", 3.141},
12461             {"happy", true},
12462             {"name", "Niels"},
12463             {"nothing", nullptr},
12464             {
12465                 "answer", {
12466                     {"everything", 42}
12467                 }
12468             },
12469             {"list", {1, 0, 2}},
12470             {
12471                 "object", {
12472                     {"currency", "USD"},
12473                     {"value", 42.99},
12474                     {"", "empty string"},
12475                     {"/", "slash"},
12476                     {"~", "tilde"},
12477                     {"~1", "tilde1"}
12478                 }
12479             }
12480         };
12481 
12482         json j_flatten =
12483         {
12484             {"/pi", 3.141},
12485             {"/happy", true},
12486             {"/name", "Niels"},
12487             {"/nothing", nullptr},
12488             {"/answer/everything", 42},
12489             {"/list/0", 1},
12490             {"/list/1", 0},
12491             {"/list/2", 2},
12492             {"/object/currency", "USD"},
12493             {"/object/value", 42.99},
12494             {"/object/", "empty string"},
12495             {"/object/~1", "slash"},
12496             {"/object/~0", "tilde"},
12497             {"/object/~01", "tilde1"}
12498         };
12499 
12500         // check if flattened result is as expected
12501         CHECK(j.flatten() == j_flatten);
12502 
12503         // check if unflattened result is as expected
12504         CHECK(j_flatten.unflatten() == j);
12505 
12506         // error for nonobjects
12507         CHECK_THROWS_AS(json(1).unflatten(), std::domain_error);
12508         CHECK_THROWS_WITH(json(1).unflatten(), "only objects can be unflattened");
12509 
12510         // error for nonprimitve values
12511         CHECK_THROWS_AS(json({{"/1", {1, 2, 3}}}).unflatten(), std::domain_error);
12512         CHECK_THROWS_WITH(json({{"/1", {1, 2, 3}}}).unflatten(), "values in object must be primitive");
12513 
12514         // error for conflicting values
12515         json j_error = {{"", 42}, {"/foo", 17}};
12516         CHECK_THROWS_AS(j_error.unflatten(), std::domain_error);
12517         CHECK_THROWS_WITH(j_error.unflatten(), "invalid value to unflatten");
12518 
12519         // explicit roundtrip check
12520         CHECK(j.flatten().unflatten() == j);
12521 
12522         // roundtrip for primitive values
12523         json j_null;
12524         CHECK(j_null.flatten().unflatten() == j_null);
12525         json j_number = 42;
12526         CHECK(j_number.flatten().unflatten() == j_number);
12527         json j_boolean = false;
12528         CHECK(j_boolean.flatten().unflatten() == j_boolean);
12529         json j_string = "foo";
12530         CHECK(j_string.flatten().unflatten() == j_string);
12531 
12532         // roundtrip for empty structured values (will be unflattened to null)
12533         json j_array(json::value_t::array);
12534         CHECK(j_array.flatten().unflatten() == json());
12535         json j_object(json::value_t::object);
12536         CHECK(j_object.flatten().unflatten() == json());
12537     }
12538 
12539     SECTION("string representation")
12540     {
12541         for (auto ptr :
12542                 {"", "/foo", "/foo/0", "/", "/a~1b", "/c%d", "/e^f", "/g|h", "/i\\j", "/k\"l", "/ ", "/m~0n"
12543                 })
12544         {
12545             CHECK(json::json_pointer(ptr).to_string() == ptr);
12546         }
12547     }
12548 }
12549 
12550 TEST_CASE("JSON patch")
12551 {
12552     SECTION("examples from RFC 6902")
12553     {
12554         SECTION("4. Operations")
12555         {
12556             // the ordering of members in JSON objects is not significant:
12557             json op1 = R"({ "op": "add", "path": "/a/b/c", "value": "foo" })"_json;
12558             json op2 = R"({ "path": "/a/b/c", "op": "add", "value": "foo" })"_json;
12559             json op3 = R"({ "value": "foo", "path": "/a/b/c", "op": "add" })"_json;
12560 
12561             // check if the operation objects are equivalent
12562             CHECK(op1 == op2);
12563             CHECK(op1 == op3);
12564         }
12565 
12566         SECTION("4.1 add")
12567         {
12568             json patch = R"([{ "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] }])"_json;
12569 
12570             // However, the object itself or an array containing it does need
12571             // to exist, and it remains an error for that not to be the case.
12572             // For example, an "add" with a target location of "/a/b" starting
12573             // with this document
12574             json doc1 = R"({ "a": { "foo": 1 } })"_json;
12575 
12576             // is not an error, because "a" exists, and "b" will be added to
12577             // its value.
12578             CHECK_NOTHROW(doc1.patch(patch));
12579             CHECK(doc1.patch(patch) == R"(
12580                 {
12581                     "a": {
12582                         "foo": 1,
12583                         "b": {
12584                             "c": [ "foo", "bar" ]
12585                         }
12586                     }
12587                 }
12588             )"_json);
12589 
12590             // It is an error in this document:
12591             json doc2 = R"({ "q": { "bar": 2 } })"_json;
12592 
12593             // because "a" does not exist.
12594             CHECK_THROWS_AS(doc2.patch(patch), std::out_of_range);
12595             CHECK_THROWS_WITH(doc2.patch(patch), "key 'a' not found");
12596         }
12597 
12598         SECTION("4.2 remove")
12599         {
12600             // If removing an element from an array, any elements above the
12601             // specified index are shifted one position to the left.
12602             json doc = {1, 2, 3, 4};
12603             json patch = {{{"op", "remove"}, {"path", "/1"}}};
12604             CHECK(doc.patch(patch) == json({1, 3, 4}));
12605         }
12606 
12607         SECTION("A.1. Adding an Object Member")
12608         {
12609             // An example target JSON document:
12610             json doc = R"(
12611                     { "foo": "bar"}
12612                 )"_json;
12613 
12614             // A JSON Patch document:
12615             json patch = R"(
12616                     [
12617                         { "op": "add", "path": "/baz", "value": "qux" }
12618                     ]
12619                 )"_json;
12620 
12621             // The resulting JSON document:
12622             json expected = R"(
12623                     {
12624                         "baz": "qux",
12625                         "foo": "bar"
12626                     }
12627                 )"_json;
12628 
12629             // check if patched value is as expected
12630             CHECK(doc.patch(patch) == expected);
12631 
12632             // check roundtrip
12633             CHECK(doc.patch(json::diff(doc, expected)) == expected);
12634         }
12635 
12636         SECTION("A.2. Adding an Array Element")
12637         {
12638             // An example target JSON document:
12639             json doc = R"(
12640                     { "foo": [ "bar", "baz" ] }
12641                 )"_json;
12642 
12643             // A JSON Patch document:
12644             json patch = R"(
12645                     [
12646                         { "op": "add", "path": "/foo/1", "value": "qux" }
12647                     ]
12648                 )"_json;
12649 
12650             // The resulting JSON document:
12651             json expected = R"(
12652                     { "foo": [ "bar", "qux", "baz" ] }
12653                 )"_json;
12654 
12655             // check if patched value is as expected
12656             CHECK(doc.patch(patch) == expected);
12657 
12658             // check roundtrip
12659             CHECK(doc.patch(json::diff(doc, expected)) == expected);
12660         }
12661 
12662         SECTION("A.3. Removing an Object Member")
12663         {
12664             // An example target JSON document:
12665             json doc = R"(
12666                     {
12667                         "baz": "qux",
12668                         "foo": "bar"
12669                     }
12670                 )"_json;
12671 
12672             // A JSON Patch document:
12673             json patch = R"(
12674                     [
12675                         { "op": "remove", "path": "/baz" }
12676                     ]
12677                 )"_json;
12678 
12679             // The resulting JSON document:
12680             json expected = R"(
12681                     { "foo": "bar" }
12682                 )"_json;
12683 
12684             // check if patched value is as expected
12685             CHECK(doc.patch(patch) == expected);
12686 
12687             // check roundtrip
12688             CHECK(doc.patch(json::diff(doc, expected)) == expected);
12689         }
12690 
12691         SECTION("A.4. Removing an Array Element")
12692         {
12693             // An example target JSON document:
12694             json doc = R"(
12695                     { "foo": [ "bar", "qux", "baz" ] }
12696                 )"_json;
12697 
12698             // A JSON Patch document:
12699             json patch = R"(
12700                     [
12701                         { "op": "remove", "path": "/foo/1" }
12702                     ]
12703                 )"_json;
12704 
12705             // The resulting JSON document:
12706             json expected = R"(
12707                     { "foo": [ "bar", "baz" ] }
12708                 )"_json;
12709 
12710             // check if patched value is as expected
12711             CHECK(doc.patch(patch) == expected);
12712 
12713             // check roundtrip
12714             CHECK(doc.patch(json::diff(doc, expected)) == expected);
12715         }
12716 
12717         SECTION("A.5. Replacing a Value")
12718         {
12719             // An example target JSON document:
12720             json doc = R"(
12721                     {
12722                         "baz": "qux",
12723                         "foo": "bar"
12724                     }
12725                 )"_json;
12726 
12727             // A JSON Patch document:
12728             json patch = R"(
12729                     [
12730                         { "op": "replace", "path": "/baz", "value": "boo" }
12731                     ]
12732                 )"_json;
12733 
12734             json expected = R"(
12735                     {
12736                         "baz": "boo",
12737                         "foo": "bar"
12738                     }
12739                 )"_json;
12740 
12741             // check if patched value is as expected
12742             CHECK(doc.patch(patch) == expected);
12743 
12744             // check roundtrip
12745             CHECK(doc.patch(json::diff(doc, expected)) == expected);
12746         }
12747 
12748         SECTION("A.6. Moving a Value")
12749         {
12750             // An example target JSON document:
12751             json doc = R"(
12752                     {
12753                         "foo": {
12754                            "bar": "baz",
12755                             "waldo": "fred"
12756                         },
12757                         "qux": {
12758                             "corge": "grault"
12759                         }
12760                     }
12761                 )"_json;
12762 
12763             // A JSON Patch document:
12764             json patch = R"(
12765                     [
12766                         { "op": "move", "from": "/foo/waldo", "path": "/qux/thud" }
12767                     ]
12768                 )"_json;
12769 
12770             // The resulting JSON document:
12771             json expected = R"(
12772                     {
12773                         "foo": {
12774                            "bar": "baz"
12775                         },
12776                         "qux": {
12777                             "corge": "grault",
12778                             "thud": "fred"
12779                         }
12780                     }
12781                 )"_json;
12782 
12783             // check if patched value is as expected
12784             CHECK(doc.patch(patch) == expected);
12785 
12786             // check roundtrip
12787             CHECK(doc.patch(json::diff(doc, expected)) == expected);
12788         }
12789 
12790         SECTION("A.7. Moving a Value")
12791         {
12792             // An example target JSON document:
12793             json doc = R"(
12794                     { "foo": [ "all", "grass", "cows", "eat" ] }
12795                 )"_json;
12796 
12797             // A JSON Patch document:
12798             json patch = R"(
12799                     [
12800                         { "op": "move", "from": "/foo/1", "path": "/foo/3" }
12801                     ]
12802                 )"_json;
12803 
12804             // The resulting JSON document:
12805             json expected = R"(
12806                     { "foo": [ "all", "cows", "eat", "grass" ] }
12807                 )"_json;
12808 
12809             // check if patched value is as expected
12810             CHECK(doc.patch(patch) == expected);
12811 
12812             // check roundtrip
12813             CHECK(doc.patch(json::diff(doc, expected)) == expected);
12814         }
12815 
12816         SECTION("A.8. Testing a Value: Success")
12817         {
12818             // An example target JSON document:
12819             json doc = R"(
12820                     {
12821                          "baz": "qux",
12822                          "foo": [ "a", 2, "c" ]
12823                     }
12824                 )"_json;
12825 
12826             // A JSON Patch document that will result in successful evaluation:
12827             json patch = R"(
12828                     [
12829                         { "op": "test", "path": "/baz", "value": "qux" },
12830                         { "op": "test", "path": "/foo/1", "value": 2 }
12831                     ]
12832                 )"_json;
12833 
12834             // check if evaluation does not throw
12835             CHECK_NOTHROW(doc.patch(patch));
12836             // check if patched document is unchanged
12837             CHECK(doc.patch(patch) == doc);
12838         }
12839 
12840         SECTION("A.9. Testing a Value: Error")
12841         {
12842             // An example target JSON document:
12843             json doc = R"(
12844                     { "baz": "qux" }
12845                 )"_json;
12846 
12847             // A JSON Patch document that will result in an error condition:
12848             json patch = R"(
12849                     [
12850                         { "op": "test", "path": "/baz", "value": "bar" }
12851                     ]
12852                 )"_json;
12853 
12854             // check that evaluation throws
12855             CHECK_THROWS_AS(doc.patch(patch), std::domain_error);
12856             CHECK_THROWS_WITH(doc.patch(patch), "unsuccessful: " + patch[0].dump());
12857         }
12858 
12859         SECTION("A.10. Adding a Nested Member Object")
12860         {
12861             // An example target JSON document:
12862             json doc = R"(
12863                     { "foo": "bar" }
12864                 )"_json;
12865 
12866             // A JSON Patch document:
12867             json patch = R"(
12868                     [
12869                         { "op": "add", "path": "/child", "value": { "grandchild": { } } }
12870                     ]
12871                 )"_json;
12872 
12873             // The resulting JSON document:
12874             json expected = R"(
12875                 {
12876                     "foo": "bar",
12877                     "child": {
12878                         "grandchild": {
12879                         }
12880                     }
12881                 }
12882                 )"_json;
12883 
12884             // check if patched value is as expected
12885             CHECK(doc.patch(patch) == expected);
12886 
12887             // check roundtrip
12888             CHECK(doc.patch(json::diff(doc, expected)) == expected);
12889         }
12890 
12891         SECTION("A.11. Ignoring Unrecognized Elements")
12892         {
12893             // An example target JSON document:
12894             json doc = R"(
12895                     { "foo": "bar" }
12896                 )"_json;
12897 
12898             // A JSON Patch document:
12899             json patch = R"(
12900                     [
12901                         { "op": "add", "path": "/baz", "value": "qux", "xyz": 123 }
12902                     ]
12903                 )"_json;
12904 
12905             json expected = R"(
12906                     {
12907                         "foo": "bar",
12908                         "baz": "qux"
12909                     } 
12910                 )"_json;
12911 
12912             // check if patched value is as expected
12913             CHECK(doc.patch(patch) == expected);
12914 
12915             // check roundtrip
12916             CHECK(doc.patch(json::diff(doc, expected)) == expected);
12917         }
12918 
12919         SECTION("A.12. Adding to a Nonexistent Target")
12920         {
12921             // An example target JSON document:
12922             json doc = R"(
12923                     { "foo": "bar" }
12924                 )"_json;
12925 
12926             // A JSON Patch document:
12927             json patch = R"(
12928                     [
12929                         { "op": "add", "path": "/baz/bat", "value": "qux" }
12930                     ]
12931                 )"_json;
12932 
12933             // This JSON Patch document, applied to the target JSON document
12934             // above, would result in an error (therefore, it would not be
12935             // applied), because the "add" operation's target location that
12936             // references neither the root of the document, nor a member of
12937             // an existing object, nor a member of an existing array.
12938 
12939             CHECK_THROWS_AS(doc.patch(patch), std::out_of_range);
12940             CHECK_THROWS_WITH(doc.patch(patch), "key 'baz' not found");
12941         }
12942 
12943         // A.13. Invalid JSON Patch Document
12944         // not applicable
12945 
12946         SECTION("A.14. Escape Ordering")
12947         {
12948             // An example target JSON document:
12949             json doc = R"(
12950                     {
12951                         "/": 9,
12952                         "~1": 10
12953                     }
12954                 )"_json;
12955 
12956             // A JSON Patch document:
12957             json patch = R"(
12958                     [
12959                         {"op": "test", "path": "/~01", "value": 10}
12960                     ]
12961                 )"_json;
12962 
12963             json expected = R"(
12964                     {
12965                         "/": 9,
12966                         "~1": 10
12967                     } 
12968                 )"_json;
12969 
12970             // check if patched value is as expected
12971             CHECK(doc.patch(patch) == expected);
12972 
12973             // check roundtrip
12974             CHECK(doc.patch(json::diff(doc, expected)) == expected);
12975         }
12976 
12977         SECTION("A.15. Comparing Strings and Numbers")
12978         {
12979             // An example target JSON document:
12980             json doc = R"(
12981                     {
12982                         "/": 9,
12983                         "~1": 10
12984                     } 
12985                 )"_json;
12986 
12987             // A JSON Patch document that will result in an error condition:
12988             json patch = R"(
12989                     [
12990                         {"op": "test", "path": "/~01", "value": "10"}
12991                     ]
12992                 )"_json;
12993 
12994             // check that evaluation throws
12995             CHECK_THROWS_AS(doc.patch(patch), std::domain_error);
12996             CHECK_THROWS_WITH(doc.patch(patch), "unsuccessful: " + patch[0].dump());
12997         }
12998 
12999         SECTION("A.16. Adding an Array Value")
13000         {
13001             // An example target JSON document:
13002             json doc = R"(
13003                     { "foo": ["bar"] }
13004                 )"_json;
13005 
13006             // A JSON Patch document:
13007             json patch = R"(
13008                     [
13009                         { "op": "add", "path": "/foo/-", "value": ["abc", "def"] }
13010                     ]
13011                 )"_json;
13012 
13013             // The resulting JSON document:
13014             json expected = R"(
13015                     { "foo": ["bar", ["abc", "def"]] }
13016                 )"_json;
13017 
13018             // check if patched value is as expected
13019             CHECK(doc.patch(patch) == expected);
13020 
13021             // check roundtrip
13022             CHECK(doc.patch(json::diff(doc, expected)) == expected);
13023         }
13024     }
13025 
13026     SECTION("own examples")
13027     {
13028         SECTION("add")
13029         {
13030             SECTION("add to the root element")
13031             {
13032                 // If the path is the root of the target document - the
13033                 // specified value becomes the entire content of the target
13034                 // document.
13035 
13036                 // An example target JSON document:
13037                 json doc = 17;
13038 
13039                 // A JSON Patch document:
13040                 json patch = R"(
13041                         [
13042                             { "op": "add", "path": "", "value": [1,2,3] }
13043                         ]
13044                     )"_json;
13045 
13046                 // The resulting JSON document:
13047                 json expected = {1, 2, 3};
13048 
13049                 // check if patched value is as expected
13050                 CHECK(doc.patch(patch) == expected);
13051 
13052                 // check roundtrip
13053                 CHECK(doc.patch(json::diff(doc, expected)) == expected);
13054             }
13055 
13056             SECTION("add to end of the array")
13057             {
13058                 // The specified index MUST NOT be greater than the number of
13059                 // elements in the array. The example below uses and index of
13060                 // exactly the number of elements in the array which is legal.
13061 
13062                 // An example target JSON document:
13063                 json doc = {0, 1, 2};
13064 
13065                 // A JSON Patch document:
13066                 json patch = R"(
13067                     [
13068                         { "op": "add", "path": "/3", "value": 3 }
13069                     ]
13070                 )"_json;
13071 
13072                 // The resulting JSON document:
13073                 json expected = {0, 1, 2, 3};
13074 
13075                 // check if patched value is as expected
13076                 CHECK(doc.patch(patch) == expected);
13077 
13078                 // check roundtrip
13079                 CHECK(doc.patch(json::diff(doc, expected)) == expected);
13080             }
13081         }
13082 
13083         SECTION("copy")
13084         {
13085             // An example target JSON document:
13086             json doc = R"(
13087                 {
13088                     "foo": {
13089                         "bar": "baz",
13090                         "waldo": "fred"
13091                     },
13092                     "qux": {
13093                        "corge": "grault"
13094                     }
13095                 }
13096             )"_json;
13097 
13098             // A JSON Patch document:
13099             json patch = R"(
13100                 [
13101                     { "op": "copy", "from": "/foo/waldo", "path": "/qux/thud" }
13102                 ]
13103             )"_json;
13104 
13105             // The resulting JSON document:
13106             json expected = R"(
13107                 {
13108                     "foo": {
13109                         "bar": "baz",
13110                         "waldo": "fred"
13111                     },
13112                     "qux": {
13113                        "corge": "grault",
13114                        "thud": "fred"
13115                     }
13116                 }
13117             )"_json;
13118 
13119             // check if patched value is as expected
13120             CHECK(doc.patch(patch) == expected);
13121 
13122             // check roundtrip
13123             CHECK(doc.patch(json::diff(doc, expected)) == expected);
13124         }
13125 
13126         SECTION("replace")
13127         {
13128             json j = "string";
13129             json patch = {{{"op", "replace"}, {"path", ""}, {"value", 1}}};
13130             CHECK(j.patch(patch) == json(1));
13131         }
13132 
13133         SECTION("documentation GIF")
13134         {
13135             {
13136                 // a JSON patch
13137                 json p1 = R"(
13138                      [{"op": "add", "path": "/GB", "value": "London"}]
13139                     )"_json;
13140 
13141                 // a JSON value
13142                 json source = R"(
13143                       {"D": "Berlin", "F": "Paris"}
13144                     )"_json;
13145 
13146                 // apply the patch
13147                 json target = source.patch(p1);
13148                 // target = { "D": "Berlin", "F": "Paris", "GB": "London" }
13149                 CHECK(target == R"({ "D": "Berlin", "F": "Paris", "GB": "London" })"_json);
13150 
13151                 // create a diff from two JSONs
13152                 json p2 = json::diff(target, source);
13153                 // p2 = [{"op": "delete", "path": "/GB"}]
13154                 CHECK(p2 == R"([{"op":"remove","path":"/GB"}])"_json);
13155             }
13156             {
13157                 // a JSON value
13158                 json j = {"good", "bad", "ugly"};
13159 
13160                 // a JSON pointer
13161                 auto ptr = json::json_pointer("/2");
13162 
13163                 // use to access elements
13164                 j[ptr] = {{"it", "cattivo"}};
13165                 CHECK(j == R"(["good","bad",{"it":"cattivo"}])"_json);
13166 
13167                 // use user-defined string literal
13168                 j["/2/en"_json_pointer] = "ugly";
13169                 CHECK(j == R"(["good","bad",{"en":"ugly","it":"cattivo"}])"_json);
13170 
13171                 json flat = j.flatten();
13172                 CHECK(flat == R"({"/0":"good","/1":"bad","/2/en":"ugly","/2/it":"cattivo"})"_json);
13173             }
13174         }
13175     }
13176 
13177     SECTION("errors")
13178     {
13179         SECTION("unknown operation")
13180         {
13181             SECTION("not an array")
13182             {
13183                 json j;
13184                 json patch = {{"op", "add"}, {"path", ""}, {"value", 1}};
13185                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13186                 CHECK_THROWS_WITH(j.patch(patch), "JSON patch must be an array of objects");
13187             }
13188 
13189             SECTION("not an array of objects")
13190             {
13191                 json j;
13192                 json patch = {"op", "add", "path", "", "value", 1};
13193                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13194                 CHECK_THROWS_WITH(j.patch(patch), "JSON patch must be an array of objects");
13195             }
13196 
13197             SECTION("missing 'op'")
13198             {
13199                 json j;
13200                 json patch = {{{"foo", "bar"}}};
13201                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13202                 CHECK_THROWS_WITH(j.patch(patch), "operation must have member 'op'");
13203             }
13204 
13205             SECTION("non-string 'op'")
13206             {
13207                 json j;
13208                 json patch = {{{"op", 1}}};
13209                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13210                 CHECK_THROWS_WITH(j.patch(patch), "operation must have string member 'op'");
13211             }
13212 
13213             SECTION("invalid operation")
13214             {
13215                 json j;
13216                 json patch = {{{"op", "foo"}, {"path", ""}}};
13217                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13218                 CHECK_THROWS_WITH(j.patch(patch), "operation value 'foo' is invalid");
13219             }
13220         }
13221 
13222         SECTION("add")
13223         {
13224             SECTION("missing 'path'")
13225             {
13226                 json j;
13227                 json patch = {{{"op", "add"}}};
13228                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13229                 CHECK_THROWS_WITH(j.patch(patch), "operation 'add' must have member 'path'");
13230             }
13231 
13232             SECTION("non-string 'path'")
13233             {
13234                 json j;
13235                 json patch = {{{"op", "add"}, {"path", 1}}};
13236                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13237                 CHECK_THROWS_WITH(j.patch(patch), "operation 'add' must have string member 'path'");
13238             }
13239 
13240             SECTION("missing 'value'")
13241             {
13242                 json j;
13243                 json patch = {{{"op", "add"}, {"path", ""}}};
13244                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13245                 CHECK_THROWS_WITH(j.patch(patch), "operation 'add' must have member 'value'");
13246             }
13247 
13248             SECTION("invalid array index")
13249             {
13250                 json j = {1, 2};
13251                 json patch = {{{"op", "add"}, {"path", "/4"}, {"value", 4}}};
13252                 CHECK_THROWS_AS(j.patch(patch), std::out_of_range);
13253                 CHECK_THROWS_WITH(j.patch(patch), "array index 4 is out of range");
13254             }
13255         }
13256 
13257         SECTION("remove")
13258         {
13259             SECTION("missing 'path'")
13260             {
13261                 json j;
13262                 json patch = {{{"op", "remove"}}};
13263                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13264                 CHECK_THROWS_WITH(j.patch(patch), "operation 'remove' must have member 'path'");
13265             }
13266 
13267             SECTION("non-string 'path'")
13268             {
13269                 json j;
13270                 json patch = {{{"op", "remove"}, {"path", 1}}};
13271                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13272                 CHECK_THROWS_WITH(j.patch(patch), "operation 'remove' must have string member 'path'");
13273             }
13274 
13275             SECTION("nonexisting target location (array)")
13276             {
13277                 json j = {1, 2, 3};
13278                 json patch = {{{"op", "remove"}, {"path", "/17"}}};
13279                 CHECK_THROWS_AS(j.patch(patch), std::out_of_range);
13280                 CHECK_THROWS_WITH(j.patch(patch), "array index 17 is out of range");
13281             }
13282 
13283             SECTION("nonexisting target location (object)")
13284             {
13285                 json j = {{"foo", 1}, {"bar", 2}};
13286                 json patch = {{{"op", "remove"}, {"path", "/baz"}}};
13287                 CHECK_THROWS_AS(j.patch(patch), std::out_of_range);
13288                 CHECK_THROWS_WITH(j.patch(patch), "key 'baz' not found");
13289             }
13290 
13291             SECTION("root element as target location")
13292             {
13293                 json j = "string";
13294                 json patch = {{{"op", "remove"}, {"path", ""}}};
13295                 CHECK_THROWS_AS(j.patch(patch), std::domain_error);
13296                 CHECK_THROWS_WITH(j.patch(patch), "JSON pointer has no parent");
13297             }
13298         }
13299 
13300         SECTION("replace")
13301         {
13302             SECTION("missing 'path'")
13303             {
13304                 json j;
13305                 json patch = {{{"op", "replace"}}};
13306                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13307                 CHECK_THROWS_WITH(j.patch(patch), "operation 'replace' must have member 'path'");
13308             }
13309 
13310             SECTION("non-string 'path'")
13311             {
13312                 json j;
13313                 json patch = {{{"op", "replace"}, {"path", 1}}};
13314                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13315                 CHECK_THROWS_WITH(j.patch(patch), "operation 'replace' must have string member 'path'");
13316             }
13317 
13318             SECTION("missing 'value'")
13319             {
13320                 json j;
13321                 json patch = {{{"op", "replace"}, {"path", ""}}};
13322                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13323                 CHECK_THROWS_WITH(j.patch(patch), "operation 'replace' must have member 'value'");
13324             }
13325 
13326             SECTION("nonexisting target location (array)")
13327             {
13328                 json j = {1, 2, 3};
13329                 json patch = {{{"op", "replace"}, {"path", "/17"}, {"value", 19}}};
13330                 CHECK_THROWS_AS(j.patch(patch), std::out_of_range);
13331                 CHECK_THROWS_WITH(j.patch(patch), "array index 17 is out of range");
13332             }
13333 
13334             SECTION("nonexisting target location (object)")
13335             {
13336                 json j = {{"foo", 1}, {"bar", 2}};
13337                 json patch = {{{"op", "replace"}, {"path", "/baz"}, {"value", 3}}};
13338                 CHECK_THROWS_AS(j.patch(patch), std::out_of_range);
13339                 CHECK_THROWS_WITH(j.patch(patch), "key 'baz' not found");
13340             }
13341         }
13342 
13343         SECTION("move")
13344         {
13345             SECTION("missing 'path'")
13346             {
13347                 json j;
13348                 json patch = {{{"op", "move"}}};
13349                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13350                 CHECK_THROWS_WITH(j.patch(patch), "operation 'move' must have member 'path'");
13351             }
13352 
13353             SECTION("non-string 'path'")
13354             {
13355                 json j;
13356                 json patch = {{{"op", "move"}, {"path", 1}}};
13357                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13358                 CHECK_THROWS_WITH(j.patch(patch), "operation 'move' must have string member 'path'");
13359             }
13360 
13361             SECTION("missing 'from'")
13362             {
13363                 json j;
13364                 json patch = {{{"op", "move"}, {"path", ""}}};
13365                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13366                 CHECK_THROWS_WITH(j.patch(patch), "operation 'move' must have member 'from'");
13367             }
13368 
13369             SECTION("non-string 'from'")
13370             {
13371                 json j;
13372                 json patch = {{{"op", "move"}, {"path", ""}, {"from", 1}}};
13373                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13374                 CHECK_THROWS_WITH(j.patch(patch), "operation 'move' must have string member 'from'");
13375             }
13376 
13377             SECTION("nonexisting from location (array)")
13378             {
13379                 json j = {1, 2, 3};
13380                 json patch = {{{"op", "move"}, {"path", "/0"}, {"from", "/5"}}};
13381                 CHECK_THROWS_AS(j.patch(patch), std::out_of_range);
13382                 CHECK_THROWS_WITH(j.patch(patch), "array index 5 is out of range");
13383             }
13384 
13385             SECTION("nonexisting from location (object)")
13386             {
13387                 json j = {{"foo", 1}, {"bar", 2}};
13388                 json patch = {{{"op", "move"}, {"path", "/baz"}, {"from", "/baz"}}};
13389                 CHECK_THROWS_AS(j.patch(patch), std::out_of_range);
13390                 CHECK_THROWS_WITH(j.patch(patch), "key 'baz' not found");
13391             }
13392         }
13393 
13394         SECTION("copy")
13395         {
13396             SECTION("missing 'path'")
13397             {
13398                 json j;
13399                 json patch = {{{"op", "copy"}}};
13400                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13401                 CHECK_THROWS_WITH(j.patch(patch), "operation 'copy' must have member 'path'");
13402             }
13403 
13404             SECTION("non-string 'path'")
13405             {
13406                 json j;
13407                 json patch = {{{"op", "copy"}, {"path", 1}}};
13408                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13409                 CHECK_THROWS_WITH(j.patch(patch), "operation 'copy' must have string member 'path'");
13410             }
13411 
13412             SECTION("missing 'from'")
13413             {
13414                 json j;
13415                 json patch = {{{"op", "copy"}, {"path", ""}}};
13416                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13417                 CHECK_THROWS_WITH(j.patch(patch), "operation 'copy' must have member 'from'");
13418             }
13419 
13420             SECTION("non-string 'from'")
13421             {
13422                 json j;
13423                 json patch = {{{"op", "copy"}, {"path", ""}, {"from", 1}}};
13424                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13425                 CHECK_THROWS_WITH(j.patch(patch), "operation 'copy' must have string member 'from'");
13426             }
13427 
13428             SECTION("nonexisting from location (array)")
13429             {
13430                 json j = {1, 2, 3};
13431                 json patch = {{{"op", "copy"}, {"path", "/0"}, {"from", "/5"}}};
13432                 CHECK_THROWS_AS(j.patch(patch), std::out_of_range);
13433                 CHECK_THROWS_WITH(j.patch(patch), "array index 5 is out of range");
13434             }
13435 
13436             SECTION("nonexisting from location (object)")
13437             {
13438                 json j = {{"foo", 1}, {"bar", 2}};
13439                 json patch = {{{"op", "copy"}, {"path", "/fob"}, {"from", "/baz"}}};
13440                 CHECK_THROWS_AS(j.patch(patch), std::out_of_range);
13441                 CHECK_THROWS_WITH(j.patch(patch), "key 'baz' not found");
13442             }
13443         }
13444 
13445         SECTION("test")
13446         {
13447             SECTION("missing 'path'")
13448             {
13449                 json j;
13450                 json patch = {{{"op", "test"}}};
13451                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13452                 CHECK_THROWS_WITH(j.patch(patch), "operation 'test' must have member 'path'");
13453             }
13454 
13455             SECTION("non-string 'path'")
13456             {
13457                 json j;
13458                 json patch = {{{"op", "test"}, {"path", 1}}};
13459                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13460                 CHECK_THROWS_WITH(j.patch(patch), "operation 'test' must have string member 'path'");
13461             }
13462 
13463             SECTION("missing 'value'")
13464             {
13465                 json j;
13466                 json patch = {{{"op", "test"}, {"path", ""}}};
13467                 CHECK_THROWS_AS(j.patch(patch), std::invalid_argument);
13468                 CHECK_THROWS_WITH(j.patch(patch), "operation 'test' must have member 'value'");
13469             }
13470         }
13471     }
13472 
13473     SECTION("Examples from jsonpatch.com")
13474     {
13475         SECTION("Simple Example")
13476         {
13477             // The original document
13478             json doc = R"(
13479                 {
13480                   "baz": "qux",
13481                   "foo": "bar"
13482                 }
13483             )"_json;
13484 
13485             // The patch
13486             json patch = R"(
13487                 [
13488                   { "op": "replace", "path": "/baz", "value": "boo" },
13489                   { "op": "add", "path": "/hello", "value": ["world"] },
13490                   { "op": "remove", "path": "/foo"}
13491                 ]
13492             )"_json;
13493 
13494             // The result
13495             json result = R"(
13496                 {
13497                    "baz": "boo",
13498                    "hello": ["world"]
13499                 }
13500             )"_json;
13501 
13502             // check if patched value is as expected
13503             CHECK(doc.patch(patch) == result);
13504 
13505             // check roundtrip
13506             CHECK(doc.patch(json::diff(doc, result)) == result);
13507         }
13508 
13509         SECTION("Operations")
13510         {
13511             // The original document
13512             json doc = R"(
13513                 {
13514                   "biscuits": [
13515                     {"name":"Digestive"},
13516                     {"name": "Choco Liebniz"}
13517                   ]
13518                 }
13519             )"_json;
13520 
13521             SECTION("add")
13522             {
13523                 // The patch
13524                 json patch = R"(
13525                     [
13526                         {"op": "add", "path": "/biscuits/1", "value": {"name": "Ginger Nut"}}
13527                     ]
13528                 )"_json;
13529 
13530                 // The result
13531                 json result = R"(
13532                     {
13533                       "biscuits": [
13534                         {"name": "Digestive"},
13535                         {"name": "Ginger Nut"},
13536                         {"name": "Choco Liebniz"}
13537                       ]
13538                     }
13539                 )"_json;
13540 
13541                 // check if patched value is as expected
13542                 CHECK(doc.patch(patch) == result);
13543 
13544                 // check roundtrip
13545                 CHECK(doc.patch(json::diff(doc, result)) == result);
13546             }
13547 
13548             SECTION("remove")
13549             {
13550                 // The patch
13551                 json patch = R"(
13552                     [
13553                         {"op": "remove", "path": "/biscuits"}
13554                     ]
13555                 )"_json;
13556 
13557                 // The result
13558                 json result = R"(
13559                     {}
13560                 )"_json;
13561 
13562                 // check if patched value is as expected
13563                 CHECK(doc.patch(patch) == result);
13564 
13565                 // check roundtrip
13566                 CHECK(doc.patch(json::diff(doc, result)) == result);
13567             }
13568 
13569             SECTION("replace")
13570             {
13571                 // The patch
13572                 json patch = R"(
13573                     [
13574                         {"op": "replace", "path": "/biscuits/0/name", "value": "Chocolate Digestive"}
13575                     ]
13576                 )"_json;
13577 
13578                 // The result
13579                 json result = R"(
13580                     {
13581                       "biscuits": [
13582                         {"name": "Chocolate Digestive"},
13583                         {"name": "Choco Liebniz"}
13584                       ]
13585                     }
13586                 )"_json;
13587 
13588                 // check if patched value is as expected
13589                 CHECK(doc.patch(patch) == result);
13590 
13591                 // check roundtrip
13592                 CHECK(doc.patch(json::diff(doc, result)) == result);
13593             }
13594 
13595             SECTION("copy")
13596             {
13597                 // The patch
13598                 json patch = R"(
13599                     [
13600                         {"op": "copy", "from": "/biscuits/0", "path": "/best_biscuit"}
13601                     ]
13602                 )"_json;
13603 
13604                 // The result
13605                 json result = R"(
13606                     {
13607                       "biscuits": [
13608                         {"name": "Digestive"},
13609                         {"name": "Choco Liebniz"}
13610                       ],
13611                       "best_biscuit": {
13612                         "name": "Digestive"
13613                       }
13614                     }
13615                 )"_json;
13616 
13617                 // check if patched value is as expected
13618                 CHECK(doc.patch(patch) == result);
13619 
13620                 // check roundtrip
13621                 CHECK(doc.patch(json::diff(doc, result)) == result);
13622             }
13623 
13624             SECTION("move")
13625             {
13626                 // The patch
13627                 json patch = R"(
13628                     [
13629                         {"op": "move", "from": "/biscuits", "path": "/cookies"}
13630                     ]
13631                 )"_json;
13632 
13633                 // The result
13634                 json result = R"(
13635                     {
13636                       "cookies": [
13637                         {"name": "Digestive"},
13638                         {"name": "Choco Liebniz"}
13639                       ]
13640                     }
13641                 )"_json;
13642 
13643                 // check if patched value is as expected
13644                 CHECK(doc.patch(patch) == result);
13645 
13646                 // check roundtrip
13647                 CHECK(doc.patch(json::diff(doc, result)) == result);
13648             }
13649 
13650             SECTION("test")
13651             {
13652                 // The patch
13653                 json patch = R"(
13654                     [
13655                         {"op": "test", "path": "/best_biscuit/name", "value": "Choco Liebniz"}
13656                     ]
13657                 )"_json;
13658 
13659                 // the test will fail
13660                 CHECK_THROWS_AS(doc.patch(patch), std::domain_error);
13661                 CHECK_THROWS_WITH(doc.patch(patch), "unsuccessful: " + patch[0].dump());
13662             }
13663         }
13664     }
13665 
13666     SECTION("Examples from bruth.github.io/jsonpatch-js")
13667     {
13668         SECTION("add")
13669         {
13670             CHECK(R"( {} )"_json.patch(
13671                       R"( [{"op": "add", "path": "/foo", "value": "bar"}] )"_json
13672                   ) == R"( {"foo": "bar"} )"_json);
13673 
13674             CHECK(R"( {"foo": [1, 3]} )"_json.patch(
13675                       R"( [{"op": "add", "path": "/foo", "value": "bar"}] )"_json
13676                   ) == R"( {"foo": "bar"} )"_json);
13677 
13678             CHECK(R"( {"foo": [{}]} )"_json.patch(
13679                       R"( [{"op": "add", "path": "/foo/0/bar", "value": "baz"}] )"_json
13680                   ) == R"( {"foo": [{"bar": "baz"}]} )"_json);
13681         }
13682 
13683         SECTION("remove")
13684         {
13685             CHECK(R"( {"foo": "bar"} )"_json.patch(
13686                       R"( [{"op": "remove", "path": "/foo"}] )"_json
13687                   ) == R"( {} )"_json);
13688 
13689             CHECK(R"( {"foo": [1, 2, 3]} )"_json.patch(
13690                       R"( [{"op": "remove", "path": "/foo/1"}] )"_json
13691                   ) == R"( {"foo": [1, 3]} )"_json);
13692 
13693             CHECK(R"( {"foo": [{"bar": "baz"}]} )"_json.patch(
13694                       R"( [{"op": "remove", "path": "/foo/0/bar"}] )"_json
13695                   ) == R"( {"foo": [{}]} )"_json);
13696         }
13697 
13698         SECTION("replace")
13699         {
13700             CHECK(R"( {"foo": "bar"} )"_json.patch(
13701                       R"( [{"op": "replace", "path": "/foo", "value": 1}] )"_json
13702                   ) == R"( {"foo": 1} )"_json);
13703 
13704             CHECK(R"( {"foo": [1, 2, 3]} )"_json.patch(
13705                       R"( [{"op": "replace", "path": "/foo/1", "value": 4}] )"_json
13706                   ) == R"( {"foo": [1, 4, 3]} )"_json);
13707 
13708             CHECK(R"( {"foo": [{"bar": "baz"}]} )"_json.patch(
13709                       R"( [{"op": "replace", "path": "/foo/0/bar", "value": 1}] )"_json
13710                   ) == R"( {"foo": [{"bar": 1}]} )"_json);
13711         }
13712 
13713         SECTION("move")
13714         {
13715             CHECK(R"( {"foo": [1, 2, 3]} )"_json.patch(
13716                       R"( [{"op": "move", "from": "/foo", "path": "/bar"}] )"_json
13717                   ) == R"( {"bar": [1, 2, 3]} )"_json);
13718         }
13719 
13720         SECTION("copy")
13721         {
13722             CHECK(R"( {"foo": [1, 2, 3]} )"_json.patch(
13723                       R"( [{"op": "copy", "from": "/foo/1", "path": "/bar"}] )"_json
13724                   ) == R"( {"foo": [1, 2, 3], "bar": 2} )"_json);
13725         }
13726 
13727         SECTION("copy")
13728         {
13729             CHECK_NOTHROW(R"( {"foo": "bar"} )"_json.patch(
13730                               R"( [{"op": "test", "path": "/foo", "value": "bar"}] )"_json));
13731         }
13732     }
13733 }
13734 
13735 TEST_CASE("regression tests")
13736 {
13737     SECTION("issue #60 - Double quotation mark is not parsed correctly")
13738     {
13739         SECTION("escape_dobulequote")
13740         {
13741             auto s = "[\"\\\"foo\\\"\"]";
13742             json j = json::parse(s);
13743             auto expected = R"(["\"foo\""])"_json;
13744             CHECK(j == expected);
13745         }
13746     }
13747 
13748     SECTION("issue #70 - Handle infinity and NaN cases")
13749     {
13750         SECTION("NAN value")
13751         {
13752             CHECK(json(NAN) == json());
13753             CHECK(json(json::number_float_t(NAN)) == json());
13754         }
13755 
13756         SECTION("infinity")
13757         {
13758             CHECK(json(INFINITY) == json());
13759             CHECK(json(json::number_float_t(INFINITY)) == json());
13760         }
13761     }
13762 
13763     SECTION("pull request #71 - handle enum type")
13764     {
13765         enum { t = 0 };
13766         json j = json::array();
13767         j.push_back(t);
13768 
13769         j.push_back(json::object(
13770         {
13771             {"game_type", t}
13772         }));
13773     }
13774 
13775     SECTION("issue #76 - dump() / parse() not idempotent")
13776     {
13777         // create JSON object
13778         json fields;
13779         fields["one"] = std::string("one");
13780         fields["two"] = std::string("two three");
13781         fields["three"] = std::string("three \"four\"");
13782 
13783         // create another JSON object by deserializing the serialization
13784         std::string payload = fields.dump();
13785         json parsed_fields = json::parse(payload);
13786 
13787         // check individual fields to match both objects
13788         CHECK(parsed_fields["one"] == fields["one"]);
13789         CHECK(parsed_fields["two"] == fields["two"]);
13790         CHECK(parsed_fields["three"] == fields["three"]);
13791 
13792         // check individual fields to match original input
13793         CHECK(parsed_fields["one"] == std::string("one"));
13794         CHECK(parsed_fields["two"] == std::string("two three"));
13795         CHECK(parsed_fields["three"] == std::string("three \"four\""));
13796 
13797         // check equality of the objects
13798         CHECK(parsed_fields == fields);
13799 
13800         // check equality of the serialized objects
13801         CHECK(fields.dump() == parsed_fields.dump());
13802 
13803         // check everything in one line
13804         CHECK(fields == json::parse(fields.dump()));
13805     }
13806 
13807     SECTION("issue #82 - lexer::get_number return NAN")
13808     {
13809         const auto content = R"(
13810         {
13811             "Test":"Test1",
13812             "Number":100,
13813             "Foo":42.42
13814         })";
13815 
13816         std::stringstream ss;
13817         ss << content;
13818         json j;
13819         ss >> j;
13820 
13821         std::string test = j["Test"];
13822         CHECK(test == "Test1");
13823         int number = j["Number"];
13824         CHECK(number == 100);
13825         float foo = j["Foo"];
13826         CHECK(foo == Approx(42.42));
13827     }
13828 
13829     SECTION("issue #89 - nonstandard integer type")
13830     {
13831         // create JSON class with nonstandard integer number type
13832         using custom_json =
13833             nlohmann::basic_json<std::map, std::vector, std::string, bool, int32_t, uint32_t, float>;
13834         custom_json j;
13835         j["int_1"] = 1;
13836         // we need to cast to int to compile with Catch - the value is int32_t
13837         CHECK(static_cast<int>(j["int_1"]) == 1);
13838 
13839         // tests for correct handling of non-standard integers that overflow the type selected by the user
13840 
13841         // unsigned integer object creation - expected to wrap and still be stored as an integer
13842         j = 4294967296U; // 2^32
13843         CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_unsigned));
13844         CHECK(j.get<uint32_t>() == 0);  // Wrap
13845 
13846         // unsigned integer parsing - expected to overflow and be stored as a float
13847         j = custom_json::parse("4294967296"); // 2^32
13848         CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_float));
13849         CHECK(j.get<float>() == 4294967296.0f);
13850 
13851         // integer object creation - expected to wrap and still be stored as an integer
13852         j = -2147483649LL; // -2^31-1
13853         CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_integer));
13854         CHECK(j.get<int32_t>() == 2147483647);  // Wrap
13855 
13856         // integer parsing - expected to overflow and be stored as a float with rounding
13857         j = custom_json::parse("-2147483649"); // -2^31
13858         CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_float));
13859         CHECK(j.get<float>() == -2147483650.0f);
13860     }
13861 
13862     SECTION("issue #93 reverse_iterator operator inheritance problem")
13863     {
13864         {
13865             json a = {1, 2, 3};
13866             json::reverse_iterator rit = a.rbegin();
13867             ++rit;
13868             CHECK(*rit == json(2));
13869             CHECK(rit.value() == json(2));
13870         }
13871         {
13872             json a = {1, 2, 3};
13873             json::reverse_iterator rit = ++a.rbegin();
13874         }
13875         {
13876             json a = {1, 2, 3};
13877             json::reverse_iterator rit = a.rbegin();
13878             ++rit;
13879             json b = {0, 0, 0};
13880             std::transform(rit, a.rend(), b.rbegin(), [](json el)
13881             {
13882                 return el;
13883             });
13884             CHECK(b == json({0, 1, 2}));
13885         }
13886         {
13887             json a = {1, 2, 3};
13888             json b = {0, 0, 0};
13889             std::transform(++a.rbegin(), a.rend(), b.rbegin(), [](json el)
13890             {
13891                 return el;
13892             });
13893             CHECK(b == json({0, 1, 2}));
13894         }
13895     }
13896 
13897     SECTION("issue #100 - failed to iterator json object with reverse_iterator")
13898     {
13899         json config =
13900         {
13901             { "111", 111 },
13902             { "112", 112 },
13903             { "113", 113 }
13904         };
13905 
13906         std::stringstream ss;
13907 
13908         for (auto it = config.begin(); it != config.end(); ++it)
13909         {
13910             ss << it.key() << ": " << it.value() << '\n';
13911         }
13912 
13913         for (auto it = config.rbegin(); it != config.rend(); ++it)
13914         {
13915             ss << it.key() << ": " << it.value() << '\n';
13916         }
13917 
13918         CHECK(ss.str() == "111: 111\n112: 112\n113: 113\n113: 113\n112: 112\n111: 111\n");
13919     }
13920 
13921     SECTION("issue #101 - binary string causes numbers to be dumped as hex")
13922     {
13923         int64_t number = 10;
13924         std::string bytes{"\x00" "asdf\n", 6};
13925         json j;
13926         j["int64"] = number;
13927         j["binary string"] = bytes;
13928         // make sure the number is really printed as decimal "10" and not as
13929         // hexadecimal "a"
13930         CHECK(j.dump() == "{\"binary string\":\"\\u0000asdf\\n\",\"int64\":10}");
13931     }
13932 
13933     SECTION("issue #111 - subsequent unicode chars")
13934     {
13935         std::string bytes{0x7, 0x7};
13936         json j;
13937         j["string"] = bytes;
13938         CHECK(j["string"] == "\u0007\u0007");
13939     }
13940 
13941     SECTION("issue #144 - implicit assignment to std::string fails")
13942     {
13943         json o = {{"name", "value"}};
13944 
13945         std::string s1 = o["name"];
13946         CHECK(s1 == "value");
13947 
13948         std::string s2;
13949         s2 = o["name"];
13950 
13951         CHECK(s2 == "value");
13952     }
13953 
13954     SECTION("issue #146 - character following a surrogate pair is skipped")
13955     {
13956         CHECK(json::parse("\"\\ud80c\\udc60abc\"").get<json::string_t>() == u8"\U00013060abc");
13957     }
13958 
13959     SECTION("issue #171 - Cannot index by key of type static constexpr const char*")
13960     {
13961         json j;
13962 
13963         // Non-const access with key as "char []"
13964         char array_key[] = "Key1";
13965         CHECK_NOTHROW(j[array_key] = 1);
13966         CHECK(j[array_key] == json(1));
13967 
13968         // Non-const access with key as "const char[]"
13969         const char const_array_key[] = "Key2";
13970         CHECK_NOTHROW(j[const_array_key] = 2);
13971         CHECK(j[const_array_key] == json(2));
13972 
13973         // Non-const access with key as "char *"
13974         char _ptr_key[] = "Key3";
13975         char* ptr_key = &_ptr_key[0];
13976         CHECK_NOTHROW(j[ptr_key] = 3);
13977         CHECK(j[ptr_key] == json(3));
13978 
13979         // Non-const access with key as "const char *"
13980         const char* const_ptr_key = "Key4";
13981         CHECK_NOTHROW(j[const_ptr_key] = 4);
13982         CHECK(j[const_ptr_key] == json(4));
13983 
13984         // Non-const access with key as "static constexpr const char *"
13985         static constexpr const char* constexpr_ptr_key = "Key5";
13986         CHECK_NOTHROW(j[constexpr_ptr_key] = 5);
13987         CHECK(j[constexpr_ptr_key] == json(5));
13988 
13989         const json j_const = j;
13990 
13991         // Const access with key as "char []"
13992         CHECK(j_const[array_key] == json(1));
13993 
13994         // Const access with key as "const char[]"
13995         CHECK(j_const[const_array_key] == json(2));
13996 
13997         // Const access with key as "char *"
13998         CHECK(j_const[ptr_key] == json(3));
13999 
14000         // Const access with key as "const char *"
14001         CHECK(j_const[const_ptr_key] == json(4));
14002 
14003         // Const access with key as "static constexpr const char *"
14004         CHECK(j_const[constexpr_ptr_key] == json(5));
14005     }
14006 
14007     SECTION("issue #186 miloyip/nativejson-benchmark: floating-point parsing")
14008     {
14009         json j;
14010 
14011         j = json::parse("-0.0");
14012         CHECK(j.get<double>() == -0.0);
14013 
14014         j = json::parse("2.22507385850720113605740979670913197593481954635164564e-308");
14015         CHECK(j.get<double>() == 2.2250738585072009e-308);
14016 
14017         j = json::parse("0.999999999999999944488848768742172978818416595458984374");
14018         CHECK(j.get<double>() == 0.99999999999999989);
14019 
14020         j = json::parse("1.00000000000000011102230246251565404236316680908203126");
14021         CHECK(j.get<double>() == 1.00000000000000022);
14022 
14023         j = json::parse("7205759403792793199999e-5");
14024         CHECK(j.get<double>() == 72057594037927928.0);
14025 
14026         j = json::parse("922337203685477529599999e-5");
14027         CHECK(j.get<double>() == 9223372036854774784.0);
14028 
14029         j = json::parse("1014120480182583464902367222169599999e-5");
14030         CHECK(j.get<double>() == 10141204801825834086073718800384.0);
14031 
14032         j = json::parse("5708990770823839207320493820740630171355185151999e-3");
14033         CHECK(j.get<double>() == 5708990770823838890407843763683279797179383808.0);
14034 
14035         // create JSON class with nonstandard float number type
14036 
14037         // float
14038         nlohmann::basic_json<std::map, std::vector, std::string, bool, int32_t, uint32_t, float> j_float =
14039             1.23e25f;
14040         CHECK(j_float.get<float>() == 1.23e25f);
14041 
14042         // double
14043         nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, double> j_double =
14044             1.23e35f;
14045         CHECK(j_double.get<double>() == 1.23e35f);
14046 
14047         // long double
14048         nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, long double>
14049         j_long_double = 1.23e45L;
14050         CHECK(j_long_double.get<long double>() == 1.23e45L);
14051     }
14052 
14053     SECTION("issue #228 - double values are serialized with commas as decimal points")
14054     {
14055         json j1a = 23.42;
14056         json j1b = json::parse("23.42");
14057 
14058         json j2a = 2342e-2;
14059         //issue #230
14060         //json j2b = json::parse("2342e-2");
14061 
14062         json j3a = 10E3;
14063         json j3b = json::parse("10E3");
14064         json j3c = json::parse("10e3");
14065 
14066         // class to create a locale that would use a comma for decimals
14067         class CommaDecimalSeparator : public std::numpunct<char>
14068         {
14069           protected:
14070             char do_decimal_point() const
14071             {
14072                 return ',';
14073             }
14074         };
14075 
14076         // change locale to mess with decimal points
14077         std::locale::global(std::locale(std::locale(), new CommaDecimalSeparator));
14078 
14079         CHECK(j1a.dump() == "23.42");
14080         CHECK(j1b.dump() == "23.42");
14081 
14082         CHECK(j2a.dump() == "23.42");
14083         //issue #230
14084         //CHECK(j2b.dump() == "23.42");
14085 
14086         CHECK(j3a.dump() == "10000");
14087         CHECK(j3b.dump() == "10000");
14088         CHECK(j3c.dump() == "10000");
14089         //CHECK(j3b.dump() == "1E04"); // roundtrip error
14090         //CHECK(j3c.dump() == "1e04"); // roundtrip error
14091     }
14092 
14093     SECTION("issue #233 - Can't use basic_json::iterator as a base iterator for std::move_iterator")
14094     {
14095         json source = {"a", "b", "c"};
14096         json expected = {"a", "b"};
14097         json dest;
14098 
14099         std::copy_n(std::make_move_iterator(source.begin()), 2, std::back_inserter(dest));
14100 
14101         CHECK(dest == expected);
14102     }
14103 
14104     SECTION("issue #235 - ambiguous overload for 'push_back' and 'operator+='")
14105     {
14106         json data = {{"key", "value"}};
14107         data.push_back({"key2", "value2"});
14108         data += {"key3", "value3"};
14109 
14110         CHECK(data == json({{"key", "value"}, {"key2", "value2"}, {"key3", "value3"}}));
14111     }
14112 
14113     SECTION("issue #269 - diff generates incorrect patch when removing multiple array elements")
14114     {
14115         json doc = R"( { "arr1": [1, 2, 3, 4] } )"_json;
14116         json expected = R"( { "arr1": [1, 2] } )"_json;
14117 
14118         // check roundtrip
14119         CHECK(doc.patch(json::diff(doc, expected)) == expected);
14120     }
14121 }
14122 
14123 // special test case to check if memory is leaked if constructor throws
14124 
14125 template<class T>
14126 struct my_allocator : std::allocator<T>
14127 {
14128     template<class... Args>
14129     void construct(T*, Args&& ...)
14130     {
14131         throw std::bad_alloc();
14132     }
14133 };
14134 
14135 TEST_CASE("bad_alloc")
14136 {
14137     SECTION("bad_alloc")
14138     {
14139         // create JSON type using the throwing allocator
14140         using my_json = nlohmann::basic_json<std::map,
14141               std::vector,
14142               std::string,
14143               bool,
14144               std::int64_t,
14145               std::uint64_t,
14146               double,
14147               my_allocator>;
14148 
14149         // creating an object should throw
14150         CHECK_THROWS_AS(my_json j(my_json::value_t::object), std::bad_alloc);
14151     }
14152 }


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:07