about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorStar Rauchenberger <fefferburbia@gmail.com>2022-11-15 17:44:56 -0500
committerStar Rauchenberger <fefferburbia@gmail.com>2022-11-15 17:44:56 -0500
commit12b25928d0ec2b18dda075b8c3b37b8a7e6f1172 (patch)
treecb61f94bff879401288d19655200b20433871155
parente6f5d46db4245a27ac9dba90dcbb08caf9ee8a97 (diff)
downloadrawr-ebooks-12b25928d0ec2b18dda075b8c3b37b8a7e6f1172.tar.gz
rawr-ebooks-12b25928d0ec2b18dda075b8c3b37b8a7e6f1172.tar.bz2
rawr-ebooks-12b25928d0ec2b18dda075b8c3b37b8a7e6f1172.zip
Bot now posts to Mastodon instead of Twitter
-rw-r--r--.gitmodules6
-rw-r--r--CMakeLists.txt21
-rw-r--r--ebooks.cpp79
-rw-r--r--timeline.cpp66
-rw-r--r--timeline.h24
m---------vendor/hkutil0
-rw-r--r--vendor/json/json.hpp24596
m---------vendor/libtwittercpp0
8 files changed, 24739 insertions, 53 deletions
diff --git a/.gitmodules b/.gitmodules index e1d506f..bdd9482 100644 --- a/.gitmodules +++ b/.gitmodules
@@ -1,3 +1,3 @@
1[submodule "vendor/libtwittercpp"] 1[submodule "vendor/hkutil"]
2 path = vendor/libtwittercpp 2 path = vendor/hkutil
3 url = https://github.com/hatkirby/libtwittercpp 3 url = git@github.com:hatkirby/hkutil.git
diff --git a/CMakeLists.txt b/CMakeLists.txt index 68b80ba..83106e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -1,29 +1,34 @@
1cmake_minimum_required (VERSION 3.1) 1cmake_minimum_required (VERSION 3.1)
2project (rawr-ebooks) 2project (rawr-ebooks)
3 3
4add_subdirectory(vendor/libtwittercpp)
5
6find_package(ASPELL REQUIRED) 4find_package(ASPELL REQUIRED)
7 5
8find_package(PkgConfig) 6find_package(PkgConfig)
9pkg_check_modules(yaml-cpp yaml-cpp REQUIRED) 7pkg_check_modules(yaml-cpp yaml-cpp REQUIRED)
8pkg_check_modules(mastodonpp mastodonpp REQUIRED)
10 9
11include_directories( 10include_directories(
12 vendor/libtwittercpp/src 11 vendor/json
12 vendor/hkutil
13 ${mastodonpp_INCLUDE_DIRS}
13 ${ASPELL_INCLUDE_DIR} 14 ${ASPELL_INCLUDE_DIR}
14 ${yaml-cpp_INCLUDE_DIRS}) 15 ${yaml-cpp_INCLUDE_DIRS})
15 16
17link_directories(
18 ${mastodonpp_LIBRARY_DIRS}
19 ${yaml-cpp_LIBRARY_DIRS})
20
16add_library(rawr kgramstats.cpp prefix_search.cpp) 21add_library(rawr kgramstats.cpp prefix_search.cpp)
17set_property(TARGET rawr PROPERTY CXX_STANDARD 11) 22set_property(TARGET rawr PROPERTY CXX_STANDARD 17)
18set_property(TARGET rawr PROPERTY CXX_STANDARD_REQUIRED ON) 23set_property(TARGET rawr PROPERTY CXX_STANDARD_REQUIRED ON)
19target_link_libraries(rawr ${ASPELL_LIBRARIES}) 24target_link_libraries(rawr ${ASPELL_LIBRARIES})
20 25
21add_executable(rawr-ebooks ebooks.cpp) 26add_executable(rawr-ebooks ebooks.cpp timeline.cpp)
22set_property(TARGET rawr-ebooks PROPERTY CXX_STANDARD 11) 27set_property(TARGET rawr-ebooks PROPERTY CXX_STANDARD 17)
23set_property(TARGET rawr-ebooks PROPERTY CXX_STANDARD_REQUIRED ON) 28set_property(TARGET rawr-ebooks PROPERTY CXX_STANDARD_REQUIRED ON)
24target_link_libraries(rawr-ebooks rawr ${yaml-cpp_LIBRARIES} twitter++) 29target_link_libraries(rawr-ebooks rawr ${yaml-cpp_LIBRARIES} ${mastodonpp_LIBRARIES})
25 30
26add_executable(rawr-gen gen.cpp) 31add_executable(rawr-gen gen.cpp)
27set_property(TARGET rawr-gen PROPERTY CXX_STANDARD 11) 32set_property(TARGET rawr-gen PROPERTY CXX_STANDARD 17)
28set_property(TARGET rawr-gen PROPERTY CXX_STANDARD_REQUIRED ON) 33set_property(TARGET rawr-gen PROPERTY CXX_STANDARD_REQUIRED ON)
29target_link_libraries(rawr-gen rawr) 34target_link_libraries(rawr-gen rawr)
diff --git a/ebooks.cpp b/ebooks.cpp index 3918b78..08be38e 100644 --- a/ebooks.cpp +++ b/ebooks.cpp
@@ -4,12 +4,13 @@
4#include "kgramstats.h" 4#include "kgramstats.h"
5#include <fstream> 5#include <fstream>
6#include <iostream> 6#include <iostream>
7#include <twitter.h> 7#include <mastodonpp/mastodonpp.hpp>
8#include <yaml-cpp/yaml.h> 8#include <yaml-cpp/yaml.h>
9#include <thread> 9#include <thread>
10#include <chrono> 10#include <chrono>
11#include <algorithm> 11#include <algorithm>
12#include <random> 12#include <random>
13#include "timeline.h"
13 14
14const auto QUEUE_TIMEOUT = std::chrono::minutes(1); 15const auto QUEUE_TIMEOUT = std::chrono::minutes(1);
15const auto POLL_TIMEOUT = std::chrono::minutes(5); 16const auto POLL_TIMEOUT = std::chrono::minutes(5);
@@ -22,13 +23,13 @@ int main(int argc, char** args)
22 YAML::Node config = YAML::LoadFile("config.yml"); 23 YAML::Node config = YAML::LoadFile("config.yml");
23 int delay = config["delay"].as<int>(); 24 int delay = config["delay"].as<int>();
24 25
25 twitter::auth auth( 26 mastodonpp::Instance instance{
26 config["consumer_key"].as<std::string>(), 27 config["mastodon_instance"].as<std::string>(),
27 config["consumer_secret"].as<std::string>(), 28 config["mastodon_token"].as<std::string>()};
28 config["access_key"].as<std::string>(), 29 mastodonpp::Connection connection{instance};
29 config["access_secret"].as<std::string>());
30 30
31 twitter::client client(auth); 31 timeline mentions(mastodonpp::API::v1::notifications);
32 mentions.poll(connection); // just ignore the results
32 33
33 std::ifstream infile(config["corpus"].as<std::string>().c_str()); 34 std::ifstream infile(config["corpus"].as<std::string>().c_str());
34 std::string corpus; 35 std::string corpus;
@@ -78,7 +79,7 @@ int main(int argc, char** args)
78 return form; 79 return form;
79 }); 80 });
80 81
81 std::list<std::tuple<std::string, bool, twitter::tweet_id>> postQueue; 82 std::list<std::tuple<std::string, bool, std::string>> postQueue;
82 83
83 auto startedTime = std::chrono::system_clock::now(); 84 auto startedTime = std::chrono::system_clock::now();
84 85
@@ -93,13 +94,11 @@ int main(int argc, char** args)
93 if (currentTime >= genTimer) 94 if (currentTime >= genTimer)
94 { 95 {
95 std::string doc = kgramstats.randomSentence(140, rng); 96 std::string doc = kgramstats.randomSentence(140, rng);
96 doc.resize(140); 97 doc.resize(500);
97 98
98 postQueue.emplace_back(std::move(doc), false, 0); 99 postQueue.emplace_back(std::move(doc), false, "");
99 100
100 int genwait = std::uniform_int_distribution<int>(1, delay)(rng); 101 genTimer = currentTime + std::chrono::seconds(delay);
101
102 genTimer = currentTime + std::chrono::seconds(genwait);
103 } 102 }
104 103
105 if (currentTime >= pollTimer) 104 if (currentTime >= pollTimer)
@@ -108,36 +107,27 @@ int main(int argc, char** args)
108 107
109 try 108 try
110 { 109 {
111 std::list<twitter::tweet> newTweets = 110 std::list<nlohmann::json> newNotifs = mentions.poll(connection);
112 client.getMentionsTimeline().poll();
113 111
114 for (const twitter::tweet& tweet : newTweets) 112 for (const nlohmann::json& notif : newNotifs)
115 { 113 {
116 auto createdTime =
117 std::chrono::system_clock::from_time_t(tweet.getCreatedAt());
118
119 if ( 114 if (
120 // Ignore tweets from before the bot started up 115 notif["type"].get<std::string>() == "mention"
121 createdTime > startedTime
122 // Ignore retweets 116 // Ignore retweets
123 && !tweet.isRetweet() 117 && notif["status"]["reblog"].is_null())
124 // Ignore tweets from yourself
125 && tweet.getAuthor() != client.getUser())
126 { 118 {
127 std::string doc = tweet.generateReplyPrefill(client.getUser()); 119 std::string doc = "@" + notif["status"]["account"]["acct"].get<std::string>() + " ";
128 doc += kgramstats.randomSentence(140 - doc.length(), rng); 120 doc += kgramstats.randomSentence(500 - doc.length(), rng);
129 doc.resize(140); 121 doc.resize(500);
130 122
131 postQueue.emplace_back(std::move(doc), true, tweet.getID()); 123 postQueue.emplace_back(std::move(doc), true, notif["status"]["id"]);
132 } 124 }
133 } 125 }
134 } catch (const twitter::rate_limit_exceeded&) 126 } catch (const std::exception& e)
135 { 127 {
128 std::cout << "Twitter error while polling: " << e.what() << std::endl;
136 // Wait out the rate limit (10 minutes here and 5 below = 15). 129 // Wait out the rate limit (10 minutes here and 5 below = 15).
137 pollTimer += std::chrono::minutes(10); 130 pollTimer += std::chrono::minutes(10);
138 } catch (const twitter::twitter_error& e)
139 {
140 std::cout << "Twitter error while polling: " << e.what() << std::endl;
141 } 131 }
142 132
143 pollTimer += std::chrono::minutes(POLL_TIMEOUT); 133 pollTimer += std::chrono::minutes(POLL_TIMEOUT);
@@ -145,21 +135,26 @@ int main(int argc, char** args)
145 135
146 if ((currentTime >= queueTimer) && (!postQueue.empty())) 136 if ((currentTime >= queueTimer) && (!postQueue.empty()))
147 { 137 {
148 auto post = postQueue.front(); 138 auto [result, isReply, replyTo] = postQueue.front();
149 postQueue.pop_front(); 139 postQueue.pop_front();
150 140
151 try 141 mastodonpp::parametermap parameters{{"status", result}};
142 if (isReply) {
143 parameters["in_reply_to_id"] = replyTo;
144 }
145
146 auto answer{connection.post(mastodonpp::API::v1::statuses, parameters)};
147 if (!answer)
152 { 148 {
153 if (std::get<1>(post)) 149 if (answer.curl_error_code == 0)
154 { 150 {
155 client.replyToTweet(std::get<0>(post), std::get<2>(post)); 151 std::cout << "HTTP status: " << answer.http_status << std::endl;
156 } else { 152 }
157 client.updateStatus(std::get<0>(post)); 153 else
154 {
155 std::cout << "libcurl error " << std::to_string(answer.curl_error_code)
156 << ": " << answer.error_message << std::endl;
158 } 157 }
159 } catch (const twitter::twitter_error& error)
160 {
161 std::cout << "Twitter error while tweeting: " << error.what()
162 << std::endl;
163 } 158 }
164 159
165 queueTimer = currentTime + std::chrono::minutes(QUEUE_TIMEOUT); 160 queueTimer = currentTime + std::chrono::minutes(QUEUE_TIMEOUT);
diff --git a/timeline.cpp b/timeline.cpp new file mode 100644 index 0000000..bc34329 --- /dev/null +++ b/timeline.cpp
@@ -0,0 +1,66 @@
1#include "timeline.h"
2#include <sstream>
3#include <hkutil/string.h>
4#include <iostream>
5
6timeline::timeline(mastodonpp::API::endpoint_type endpoint) : endpoint_(endpoint)
7{
8}
9
10std::list<nlohmann::json> timeline::poll(mastodonpp::Connection& connection)
11{
12 std::string maxId;
13 std::list<nlohmann::json> result;
14
15 for (int i = 0; i < 5; i++)
16 {
17 mastodonpp::parametermap arguments;
18
19 if (i > 0)
20 {
21 arguments["max_id"] = maxId;
22 }
23
24 if (hasSince_)
25 {
26 arguments["since_id"] = sinceId_;
27 }
28
29 auto answer{connection.get(endpoint_, arguments)};
30 if (!answer)
31 {
32 if (answer.curl_error_code == 0)
33 {
34 std::cout << "HTTP status: " << answer.http_status << std::endl;
35 }
36 else
37 {
38 std::cout << "libcurl error " << std::to_string(answer.curl_error_code)
39 << ": " << answer.error_message << std::endl;
40 }
41 return {};
42 }
43
44 nlohmann::json rjs = nlohmann::json::parse(answer.body);
45
46 if (rjs.empty())
47 {
48 break;
49 }
50
51 for (auto& single : rjs)
52 {
53 result.push_back(single);
54 }
55
56 maxId = result.back()["id"].get<std::string>();
57 }
58
59 if (!result.empty())
60 {
61 sinceId_ = result.front()["id"].get<std::string>();
62 hasSince_ = true;
63 }
64
65 return result;
66}
diff --git a/timeline.h b/timeline.h new file mode 100644 index 0000000..1cfc5bf --- /dev/null +++ b/timeline.h
@@ -0,0 +1,24 @@
1#ifndef TIMELINE_H_FE90F0DC
2#define TIMELINE_H_FE90F0DC
3
4#include <functional>
5#include <list>
6#include <string>
7#include <mastodonpp/mastodonpp.hpp>
8#include <json.hpp>
9
10class timeline {
11public:
12
13 explicit timeline(mastodonpp::API::endpoint_type endpoint);
14
15 std::list<nlohmann::json> poll(mastodonpp::Connection& connection);
16
17private:
18
19 mastodonpp::API::endpoint_type endpoint_;
20 bool hasSince_ = false;
21 std::string sinceId_;
22};
23
24#endif /* end of include guard: TIMELINE_H_FE90F0DC */
diff --git a/vendor/hkutil b/vendor/hkutil new file mode 160000
Subproject a9a5996310bb33207d3338f353aab97b9ed3a5e
diff --git a/vendor/json/json.hpp b/vendor/json/json.hpp new file mode 100644 index 0000000..4d1a37a --- /dev/null +++ b/vendor/json/json.hpp
@@ -0,0 +1,24596 @@
1// __ _____ _____ _____
2// __| | __| | | | JSON for Modern C++
3// | | |__ | | | | | | version 3.11.2
4// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5//
6// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
7// SPDX-License-Identifier: MIT
8
9/****************************************************************************\
10 * Note on documentation: The source files contain links to the online *
11 * documentation of the public API at https://json.nlohmann.me. This URL *
12 * contains the most recent documentation and should also be applicable to *
13 * previous versions; documentation for deprecated functions is not *
14 * removed, but marked deprecated. See "Generate documentation" section in *
15 * file docs/README.md. *
16\****************************************************************************/
17
18#ifndef INCLUDE_NLOHMANN_JSON_HPP_
19#define INCLUDE_NLOHMANN_JSON_HPP_
20
21#include <algorithm> // all_of, find, for_each
22#include <cstddef> // nullptr_t, ptrdiff_t, size_t
23#include <functional> // hash, less
24#include <initializer_list> // initializer_list
25#ifndef JSON_NO_IO
26 #include <iosfwd> // istream, ostream
27#endif // JSON_NO_IO
28#include <iterator> // random_access_iterator_tag
29#include <memory> // unique_ptr
30#include <numeric> // accumulate
31#include <string> // string, stoi, to_string
32#include <utility> // declval, forward, move, pair, swap
33#include <vector> // vector
34
35// #include <nlohmann/adl_serializer.hpp>
36// __ _____ _____ _____
37// __| | __| | | | JSON for Modern C++
38// | | |__ | | | | | | version 3.11.2
39// |_____|_____|_____|_|___| https://github.com/nlohmann/json
40//
41// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
42// SPDX-License-Identifier: MIT
43
44
45
46#include <utility>
47
48// #include <nlohmann/detail/abi_macros.hpp>
49// __ _____ _____ _____
50// __| | __| | | | JSON for Modern C++
51// | | |__ | | | | | | version 3.11.2
52// |_____|_____|_____|_|___| https://github.com/nlohmann/json
53//
54// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
55// SPDX-License-Identifier: MIT
56
57
58
59// This file contains all macro definitions affecting or depending on the ABI
60
61#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
62 #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
63 #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 2
64 #warning "Already included a different version of the library!"
65 #endif
66 #endif
67#endif
68
69#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
70#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum)
71#define NLOHMANN_JSON_VERSION_PATCH 2 // NOLINT(modernize-macro-to-enum)
72
73#ifndef JSON_DIAGNOSTICS
74 #define JSON_DIAGNOSTICS 0
75#endif
76
77#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
78 #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
79#endif
80
81#if JSON_DIAGNOSTICS
82 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
83#else
84 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
85#endif
86
87#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
88 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
89#else
90 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
91#endif
92
93#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
94 #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
95#endif
96
97// Construct the namespace ABI tags component
98#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
99#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
100 NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
101
102#define NLOHMANN_JSON_ABI_TAGS \
103 NLOHMANN_JSON_ABI_TAGS_CONCAT( \
104 NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
105 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
106
107// Construct the namespace version component
108#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
109 _v ## major ## _ ## minor ## _ ## patch
110#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
111 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
112
113#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
114#define NLOHMANN_JSON_NAMESPACE_VERSION
115#else
116#define NLOHMANN_JSON_NAMESPACE_VERSION \
117 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
118 NLOHMANN_JSON_VERSION_MINOR, \
119 NLOHMANN_JSON_VERSION_PATCH)
120#endif
121
122// Combine namespace components
123#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
124#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
125 NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
126
127#ifndef NLOHMANN_JSON_NAMESPACE
128#define NLOHMANN_JSON_NAMESPACE \
129 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
130 NLOHMANN_JSON_ABI_TAGS, \
131 NLOHMANN_JSON_NAMESPACE_VERSION)
132#endif
133
134#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
135#define NLOHMANN_JSON_NAMESPACE_BEGIN \
136 namespace nlohmann \
137 { \
138 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
139 NLOHMANN_JSON_ABI_TAGS, \
140 NLOHMANN_JSON_NAMESPACE_VERSION) \
141 {
142#endif
143
144#ifndef NLOHMANN_JSON_NAMESPACE_END
145#define NLOHMANN_JSON_NAMESPACE_END \
146 } /* namespace (inline namespace) NOLINT(readability/namespace) */ \
147 } // namespace nlohmann
148#endif
149
150// #include <nlohmann/detail/conversions/from_json.hpp>
151// __ _____ _____ _____
152// __| | __| | | | JSON for Modern C++
153// | | |__ | | | | | | version 3.11.2
154// |_____|_____|_____|_|___| https://github.com/nlohmann/json
155//
156// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
157// SPDX-License-Identifier: MIT
158
159
160
161#include <algorithm> // transform
162#include <array> // array
163#include <forward_list> // forward_list
164#include <iterator> // inserter, front_inserter, end
165#include <map> // map
166#include <string> // string
167#include <tuple> // tuple, make_tuple
168#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
169#include <unordered_map> // unordered_map
170#include <utility> // pair, declval
171#include <valarray> // valarray
172
173// #include <nlohmann/detail/exceptions.hpp>
174// __ _____ _____ _____
175// __| | __| | | | JSON for Modern C++
176// | | |__ | | | | | | version 3.11.2
177// |_____|_____|_____|_|___| https://github.com/nlohmann/json
178//
179// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
180// SPDX-License-Identifier: MIT
181
182
183
184#include <cstddef> // nullptr_t
185#include <exception> // exception
186#include <stdexcept> // runtime_error
187#include <string> // to_string
188#include <vector> // vector
189
190// #include <nlohmann/detail/value_t.hpp>
191// __ _____ _____ _____
192// __| | __| | | | JSON for Modern C++
193// | | |__ | | | | | | version 3.11.2
194// |_____|_____|_____|_|___| https://github.com/nlohmann/json
195//
196// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
197// SPDX-License-Identifier: MIT
198
199
200
201#include <array> // array
202#include <cstddef> // size_t
203#include <cstdint> // uint8_t
204#include <string> // string
205
206// #include <nlohmann/detail/macro_scope.hpp>
207// __ _____ _____ _____
208// __| | __| | | | JSON for Modern C++
209// | | |__ | | | | | | version 3.11.2
210// |_____|_____|_____|_|___| https://github.com/nlohmann/json
211//
212// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
213// SPDX-License-Identifier: MIT
214
215
216
217#include <utility> // declval, pair
218// #include <nlohmann/detail/meta/detected.hpp>
219// __ _____ _____ _____
220// __| | __| | | | JSON for Modern C++
221// | | |__ | | | | | | version 3.11.2
222// |_____|_____|_____|_|___| https://github.com/nlohmann/json
223//
224// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
225// SPDX-License-Identifier: MIT
226
227
228
229#include <type_traits>
230
231// #include <nlohmann/detail/meta/void_t.hpp>
232// __ _____ _____ _____
233// __| | __| | | | JSON for Modern C++
234// | | |__ | | | | | | version 3.11.2
235// |_____|_____|_____|_|___| https://github.com/nlohmann/json
236//
237// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
238// SPDX-License-Identifier: MIT
239
240
241
242// #include <nlohmann/detail/abi_macros.hpp>
243
244
245NLOHMANN_JSON_NAMESPACE_BEGIN
246namespace detail
247{
248
249template<typename ...Ts> struct make_void
250{
251 using type = void;
252};
253template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
254
255} // namespace detail
256NLOHMANN_JSON_NAMESPACE_END
257
258
259NLOHMANN_JSON_NAMESPACE_BEGIN
260namespace detail
261{
262
263// https://en.cppreference.com/w/cpp/experimental/is_detected
264struct nonesuch
265{
266 nonesuch() = delete;
267 ~nonesuch() = delete;
268 nonesuch(nonesuch const&) = delete;
269 nonesuch(nonesuch const&&) = delete;
270 void operator=(nonesuch const&) = delete;
271 void operator=(nonesuch&&) = delete;
272};
273
274template<class Default,
275 class AlwaysVoid,
276 template<class...> class Op,
277 class... Args>
278struct detector
279{
280 using value_t = std::false_type;
281 using type = Default;
282};
283
284template<class Default, template<class...> class Op, class... Args>
285struct detector<Default, void_t<Op<Args...>>, Op, Args...>
286{
287 using value_t = std::true_type;
288 using type = Op<Args...>;
289};
290
291template<template<class...> class Op, class... Args>
292using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
293
294template<template<class...> class Op, class... Args>
295struct is_detected_lazy : is_detected<Op, Args...> { };
296
297template<template<class...> class Op, class... Args>
298using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
299
300template<class Default, template<class...> class Op, class... Args>
301using detected_or = detector<Default, void, Op, Args...>;
302
303template<class Default, template<class...> class Op, class... Args>
304using detected_or_t = typename detected_or<Default, Op, Args...>::type;
305
306template<class Expected, template<class...> class Op, class... Args>
307using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
308
309template<class To, template<class...> class Op, class... Args>
310using is_detected_convertible =
311 std::is_convertible<detected_t<Op, Args...>, To>;
312
313} // namespace detail
314NLOHMANN_JSON_NAMESPACE_END
315
316// #include <nlohmann/thirdparty/hedley/hedley.hpp>
317
318
319// __ _____ _____ _____
320// __| | __| | | | JSON for Modern C++
321// | | |__ | | | | | | version 3.11.2
322// |_____|_____|_____|_|___| https://github.com/nlohmann/json
323//
324// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
325// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson <evan@nemerson.com>
326// SPDX-License-Identifier: MIT
327
328/* Hedley - https://nemequ.github.io/hedley
329 * Created by Evan Nemerson <evan@nemerson.com>
330 */
331
332#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
333#if defined(JSON_HEDLEY_VERSION)
334 #undef JSON_HEDLEY_VERSION
335#endif
336#define JSON_HEDLEY_VERSION 15
337
338#if defined(JSON_HEDLEY_STRINGIFY_EX)
339 #undef JSON_HEDLEY_STRINGIFY_EX
340#endif
341#define JSON_HEDLEY_STRINGIFY_EX(x) #x
342
343#if defined(JSON_HEDLEY_STRINGIFY)
344 #undef JSON_HEDLEY_STRINGIFY
345#endif
346#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
347
348#if defined(JSON_HEDLEY_CONCAT_EX)
349 #undef JSON_HEDLEY_CONCAT_EX
350#endif
351#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
352
353#if defined(JSON_HEDLEY_CONCAT)
354 #undef JSON_HEDLEY_CONCAT
355#endif
356#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
357
358#if defined(JSON_HEDLEY_CONCAT3_EX)
359 #undef JSON_HEDLEY_CONCAT3_EX
360#endif
361#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
362
363#if defined(JSON_HEDLEY_CONCAT3)
364 #undef JSON_HEDLEY_CONCAT3
365#endif
366#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
367
368#if defined(JSON_HEDLEY_VERSION_ENCODE)
369 #undef JSON_HEDLEY_VERSION_ENCODE
370#endif
371#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
372
373#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
374 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
375#endif
376#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
377
378#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
379 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
380#endif
381#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
382
383#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
384 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
385#endif
386#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
387
388#if defined(JSON_HEDLEY_GNUC_VERSION)
389 #undef JSON_HEDLEY_GNUC_VERSION
390#endif
391#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
392 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
393#elif defined(__GNUC__)
394 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
395#endif
396
397#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
398 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
399#endif
400#if defined(JSON_HEDLEY_GNUC_VERSION)
401 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
402#else
403 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
404#endif
405
406#if defined(JSON_HEDLEY_MSVC_VERSION)
407 #undef JSON_HEDLEY_MSVC_VERSION
408#endif
409#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
410 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
411#elif defined(_MSC_FULL_VER) && !defined(__ICL)
412 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
413#elif defined(_MSC_VER) && !defined(__ICL)
414 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
415#endif
416
417#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
418 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
419#endif
420#if !defined(JSON_HEDLEY_MSVC_VERSION)
421 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
422#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
423 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
424#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
425 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
426#else
427 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
428#endif
429
430#if defined(JSON_HEDLEY_INTEL_VERSION)
431 #undef JSON_HEDLEY_INTEL_VERSION
432#endif
433#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
434 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
435#elif defined(__INTEL_COMPILER) && !defined(__ICL)
436 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
437#endif
438
439#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
440 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
441#endif
442#if defined(JSON_HEDLEY_INTEL_VERSION)
443 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
444#else
445 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
446#endif
447
448#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
449 #undef JSON_HEDLEY_INTEL_CL_VERSION
450#endif
451#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
452 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
453#endif
454
455#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
456 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
457#endif
458#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
459 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
460#else
461 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
462#endif
463
464#if defined(JSON_HEDLEY_PGI_VERSION)
465 #undef JSON_HEDLEY_PGI_VERSION
466#endif
467#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
468 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
469#endif
470
471#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
472 #undef JSON_HEDLEY_PGI_VERSION_CHECK
473#endif
474#if defined(JSON_HEDLEY_PGI_VERSION)
475 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
476#else
477 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
478#endif
479
480#if defined(JSON_HEDLEY_SUNPRO_VERSION)
481 #undef JSON_HEDLEY_SUNPRO_VERSION
482#endif
483#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
484 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
485#elif defined(__SUNPRO_C)
486 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
487#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
488 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
489#elif defined(__SUNPRO_CC)
490 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
491#endif
492
493#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
494 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
495#endif
496#if defined(JSON_HEDLEY_SUNPRO_VERSION)
497 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
498#else
499 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
500#endif
501
502#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
503 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
504#endif
505#if defined(__EMSCRIPTEN__)
506 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
507#endif
508
509#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
510 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
511#endif
512#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
513 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
514#else
515 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
516#endif
517
518#if defined(JSON_HEDLEY_ARM_VERSION)
519 #undef JSON_HEDLEY_ARM_VERSION
520#endif
521#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
522 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
523#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
524 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
525#endif
526
527#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
528 #undef JSON_HEDLEY_ARM_VERSION_CHECK
529#endif
530#if defined(JSON_HEDLEY_ARM_VERSION)
531 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
532#else
533 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
534#endif
535
536#if defined(JSON_HEDLEY_IBM_VERSION)
537 #undef JSON_HEDLEY_IBM_VERSION
538#endif
539#if defined(__ibmxl__)
540 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
541#elif defined(__xlC__) && defined(__xlC_ver__)
542 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
543#elif defined(__xlC__)
544 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
545#endif
546
547#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
548 #undef JSON_HEDLEY_IBM_VERSION_CHECK
549#endif
550#if defined(JSON_HEDLEY_IBM_VERSION)
551 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
552#else
553 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
554#endif
555
556#if defined(JSON_HEDLEY_TI_VERSION)
557 #undef JSON_HEDLEY_TI_VERSION
558#endif
559#if \
560 defined(__TI_COMPILER_VERSION__) && \
561 ( \
562 defined(__TMS470__) || defined(__TI_ARM__) || \
563 defined(__MSP430__) || \
564 defined(__TMS320C2000__) \
565 )
566#if (__TI_COMPILER_VERSION__ >= 16000000)
567 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
568#endif
569#endif
570
571#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
572 #undef JSON_HEDLEY_TI_VERSION_CHECK
573#endif
574#if defined(JSON_HEDLEY_TI_VERSION)
575 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
576#else
577 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
578#endif
579
580#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
581 #undef JSON_HEDLEY_TI_CL2000_VERSION
582#endif
583#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
584 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
585#endif
586
587#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
588 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
589#endif
590#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
591 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
592#else
593 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
594#endif
595
596#if defined(JSON_HEDLEY_TI_CL430_VERSION)
597 #undef JSON_HEDLEY_TI_CL430_VERSION
598#endif
599#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
600 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
601#endif
602
603#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
604 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
605#endif
606#if defined(JSON_HEDLEY_TI_CL430_VERSION)
607 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
608#else
609 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
610#endif
611
612#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
613 #undef JSON_HEDLEY_TI_ARMCL_VERSION
614#endif
615#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
616 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
617#endif
618
619#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
620 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
621#endif
622#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
623 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
624#else
625 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
626#endif
627
628#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
629 #undef JSON_HEDLEY_TI_CL6X_VERSION
630#endif
631#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
632 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
633#endif
634
635#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
636 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
637#endif
638#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
639 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
640#else
641 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
642#endif
643
644#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
645 #undef JSON_HEDLEY_TI_CL7X_VERSION
646#endif
647#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
648 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
649#endif
650
651#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
652 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
653#endif
654#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
655 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
656#else
657 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
658#endif
659
660#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
661 #undef JSON_HEDLEY_TI_CLPRU_VERSION
662#endif
663#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
664 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
665#endif
666
667#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
668 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
669#endif
670#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
671 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
672#else
673 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
674#endif
675
676#if defined(JSON_HEDLEY_CRAY_VERSION)
677 #undef JSON_HEDLEY_CRAY_VERSION
678#endif
679#if defined(_CRAYC)
680 #if defined(_RELEASE_PATCHLEVEL)
681 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
682 #else
683 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
684 #endif
685#endif
686
687#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
688 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
689#endif
690#if defined(JSON_HEDLEY_CRAY_VERSION)
691 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
692#else
693 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
694#endif
695
696#if defined(JSON_HEDLEY_IAR_VERSION)
697 #undef JSON_HEDLEY_IAR_VERSION
698#endif
699#if defined(__IAR_SYSTEMS_ICC__)
700 #if __VER__ > 1000
701 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
702 #else
703 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
704 #endif
705#endif
706
707#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
708 #undef JSON_HEDLEY_IAR_VERSION_CHECK
709#endif
710#if defined(JSON_HEDLEY_IAR_VERSION)
711 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
712#else
713 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
714#endif
715
716#if defined(JSON_HEDLEY_TINYC_VERSION)
717 #undef JSON_HEDLEY_TINYC_VERSION
718#endif
719#if defined(__TINYC__)
720 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
721#endif
722
723#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
724 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
725#endif
726#if defined(JSON_HEDLEY_TINYC_VERSION)
727 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
728#else
729 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
730#endif
731
732#if defined(JSON_HEDLEY_DMC_VERSION)
733 #undef JSON_HEDLEY_DMC_VERSION
734#endif
735#if defined(__DMC__)
736 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
737#endif
738
739#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
740 #undef JSON_HEDLEY_DMC_VERSION_CHECK
741#endif
742#if defined(JSON_HEDLEY_DMC_VERSION)
743 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
744#else
745 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
746#endif
747
748#if defined(JSON_HEDLEY_COMPCERT_VERSION)
749 #undef JSON_HEDLEY_COMPCERT_VERSION
750#endif
751#if defined(__COMPCERT_VERSION__)
752 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
753#endif
754
755#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
756 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
757#endif
758#if defined(JSON_HEDLEY_COMPCERT_VERSION)
759 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
760#else
761 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
762#endif
763
764#if defined(JSON_HEDLEY_PELLES_VERSION)
765 #undef JSON_HEDLEY_PELLES_VERSION
766#endif
767#if defined(__POCC__)
768 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
769#endif
770
771#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
772 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
773#endif
774#if defined(JSON_HEDLEY_PELLES_VERSION)
775 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
776#else
777 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
778#endif
779
780#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
781 #undef JSON_HEDLEY_MCST_LCC_VERSION
782#endif
783#if defined(__LCC__) && defined(__LCC_MINOR__)
784 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
785#endif
786
787#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
788 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
789#endif
790#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
791 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
792#else
793 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
794#endif
795
796#if defined(JSON_HEDLEY_GCC_VERSION)
797 #undef JSON_HEDLEY_GCC_VERSION
798#endif
799#if \
800 defined(JSON_HEDLEY_GNUC_VERSION) && \
801 !defined(__clang__) && \
802 !defined(JSON_HEDLEY_INTEL_VERSION) && \
803 !defined(JSON_HEDLEY_PGI_VERSION) && \
804 !defined(JSON_HEDLEY_ARM_VERSION) && \
805 !defined(JSON_HEDLEY_CRAY_VERSION) && \
806 !defined(JSON_HEDLEY_TI_VERSION) && \
807 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
808 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
809 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
810 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
811 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
812 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
813 !defined(__COMPCERT__) && \
814 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
815 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
816#endif
817
818#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
819 #undef JSON_HEDLEY_GCC_VERSION_CHECK
820#endif
821#if defined(JSON_HEDLEY_GCC_VERSION)
822 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
823#else
824 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
825#endif
826
827#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
828 #undef JSON_HEDLEY_HAS_ATTRIBUTE
829#endif
830#if \
831 defined(__has_attribute) && \
832 ( \
833 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
834 )
835# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
836#else
837# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
838#endif
839
840#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
841 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
842#endif
843#if defined(__has_attribute)
844 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
845#else
846 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
847#endif
848
849#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
850 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
851#endif
852#if defined(__has_attribute)
853 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
854#else
855 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
856#endif
857
858#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
859 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
860#endif
861#if \
862 defined(__has_cpp_attribute) && \
863 defined(__cplusplus) && \
864 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
865 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
866#else
867 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
868#endif
869
870#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
871 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
872#endif
873#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
874 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
875#elif \
876 !defined(JSON_HEDLEY_PGI_VERSION) && \
877 !defined(JSON_HEDLEY_IAR_VERSION) && \
878 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
879 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
880 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
881#else
882 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
883#endif
884
885#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
886 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
887#endif
888#if defined(__has_cpp_attribute) && defined(__cplusplus)
889 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
890#else
891 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
892#endif
893
894#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
895 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
896#endif
897#if defined(__has_cpp_attribute) && defined(__cplusplus)
898 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
899#else
900 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
901#endif
902
903#if defined(JSON_HEDLEY_HAS_BUILTIN)
904 #undef JSON_HEDLEY_HAS_BUILTIN
905#endif
906#if defined(__has_builtin)
907 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
908#else
909 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
910#endif
911
912#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
913 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
914#endif
915#if defined(__has_builtin)
916 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
917#else
918 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
919#endif
920
921#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
922 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
923#endif
924#if defined(__has_builtin)
925 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
926#else
927 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
928#endif
929
930#if defined(JSON_HEDLEY_HAS_FEATURE)
931 #undef JSON_HEDLEY_HAS_FEATURE
932#endif
933#if defined(__has_feature)
934 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
935#else
936 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
937#endif
938
939#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
940 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
941#endif
942#if defined(__has_feature)
943 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
944#else
945 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
946#endif
947
948#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
949 #undef JSON_HEDLEY_GCC_HAS_FEATURE
950#endif
951#if defined(__has_feature)
952 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
953#else
954 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
955#endif
956
957#if defined(JSON_HEDLEY_HAS_EXTENSION)
958 #undef JSON_HEDLEY_HAS_EXTENSION
959#endif
960#if defined(__has_extension)
961 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
962#else
963 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
964#endif
965
966#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
967 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
968#endif
969#if defined(__has_extension)
970 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
971#else
972 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
973#endif
974
975#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
976 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
977#endif
978#if defined(__has_extension)
979 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
980#else
981 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
982#endif
983
984#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
985 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
986#endif
987#if defined(__has_declspec_attribute)
988 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
989#else
990 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
991#endif
992
993#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
994 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
995#endif
996#if defined(__has_declspec_attribute)
997 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
998#else
999 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1000#endif
1001
1002#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
1003 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
1004#endif
1005#if defined(__has_declspec_attribute)
1006 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1007#else
1008 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1009#endif
1010
1011#if defined(JSON_HEDLEY_HAS_WARNING)
1012 #undef JSON_HEDLEY_HAS_WARNING
1013#endif
1014#if defined(__has_warning)
1015 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
1016#else
1017 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
1018#endif
1019
1020#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
1021 #undef JSON_HEDLEY_GNUC_HAS_WARNING
1022#endif
1023#if defined(__has_warning)
1024 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1025#else
1026 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1027#endif
1028
1029#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
1030 #undef JSON_HEDLEY_GCC_HAS_WARNING
1031#endif
1032#if defined(__has_warning)
1033 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1034#else
1035 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1036#endif
1037
1038#if \
1039 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1040 defined(__clang__) || \
1041 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1042 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1043 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1044 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1045 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1046 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1047 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1048 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1049 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1050 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
1051 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1052 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1053 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
1054 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
1055 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
1056 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
1057 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
1058#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1059 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
1060#else
1061 #define JSON_HEDLEY_PRAGMA(value)
1062#endif
1063
1064#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
1065 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
1066#endif
1067#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
1068 #undef JSON_HEDLEY_DIAGNOSTIC_POP
1069#endif
1070#if defined(__clang__)
1071 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
1072 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
1073#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1074 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1075 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1076#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1077 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
1078 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
1079#elif \
1080 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
1081 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1082 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
1083 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
1084#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
1085 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
1086 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
1087#elif \
1088 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1089 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1090 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
1091 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1092 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1093 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1094 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
1095 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
1096#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1097 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1098 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1099#else
1100 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
1101 #define JSON_HEDLEY_DIAGNOSTIC_POP
1102#endif
1103
1104/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
1105 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1106#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1107 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
1108#endif
1109#if defined(__cplusplus)
1110# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
1111# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
1112# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
1113# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1114 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1115 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1116 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1117 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
1118 xpr \
1119 JSON_HEDLEY_DIAGNOSTIC_POP
1120# else
1121# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1122 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1123 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1124 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1125 xpr \
1126 JSON_HEDLEY_DIAGNOSTIC_POP
1127# endif
1128# else
1129# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1130 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1131 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1132 xpr \
1133 JSON_HEDLEY_DIAGNOSTIC_POP
1134# endif
1135# endif
1136#endif
1137#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1138 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1139#endif
1140
1141#if defined(JSON_HEDLEY_CONST_CAST)
1142 #undef JSON_HEDLEY_CONST_CAST
1143#endif
1144#if defined(__cplusplus)
1145# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1146#elif \
1147 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1148 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1149 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1150# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1151 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1152 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1153 ((T) (expr)); \
1154 JSON_HEDLEY_DIAGNOSTIC_POP \
1155 }))
1156#else
1157# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1158#endif
1159
1160#if defined(JSON_HEDLEY_REINTERPRET_CAST)
1161 #undef JSON_HEDLEY_REINTERPRET_CAST
1162#endif
1163#if defined(__cplusplus)
1164 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1165#else
1166 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1167#endif
1168
1169#if defined(JSON_HEDLEY_STATIC_CAST)
1170 #undef JSON_HEDLEY_STATIC_CAST
1171#endif
1172#if defined(__cplusplus)
1173 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1174#else
1175 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1176#endif
1177
1178#if defined(JSON_HEDLEY_CPP_CAST)
1179 #undef JSON_HEDLEY_CPP_CAST
1180#endif
1181#if defined(__cplusplus)
1182# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1183# define JSON_HEDLEY_CPP_CAST(T, expr) \
1184 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1185 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1186 ((T) (expr)) \
1187 JSON_HEDLEY_DIAGNOSTIC_POP
1188# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1189# define JSON_HEDLEY_CPP_CAST(T, expr) \
1190 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1191 _Pragma("diag_suppress=Pe137") \
1192 JSON_HEDLEY_DIAGNOSTIC_POP
1193# else
1194# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1195# endif
1196#else
1197# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1198#endif
1199
1200#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1201 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1202#endif
1203#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1204 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1205#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1206 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1207#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1208 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1209#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1210 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1211#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1212 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1213#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1214 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1215#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1216 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1217#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1218 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1219#elif \
1220 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1221 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1222 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1223 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1224 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1225 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1226 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1227 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1228 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1229 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1230 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1231 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1232#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1233 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1234#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1235 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1236#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1237 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1238#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1239 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1240#else
1241 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1242#endif
1243
1244#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1245 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1246#endif
1247#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1248 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1249#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1250 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1251#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1252 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1253#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1254 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1255#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1256 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1257#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1258 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1259#elif \
1260 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1261 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1262 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1263 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1264 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1265#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1266 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1267#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1268 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1269#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1270 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1271#else
1272 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1273#endif
1274
1275#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1276 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1277#endif
1278#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1279 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1280#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1281 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1282#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1283 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1284#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1285 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1286#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1287 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1288#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1289 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1290#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1291 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1292#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1293 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1294#elif \
1295 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1296 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1297 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1298 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1299#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1300 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1301#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1302 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1303#else
1304 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1305#endif
1306
1307#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1308 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1309#endif
1310#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1311 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1312#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1313 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1314#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1315 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1316#else
1317 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1318#endif
1319
1320#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1321 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1322#endif
1323#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1324 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1325#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1326 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1327#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1328 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1329#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1330 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1331#else
1332 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1333#endif
1334
1335#if defined(JSON_HEDLEY_DEPRECATED)
1336 #undef JSON_HEDLEY_DEPRECATED
1337#endif
1338#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1339 #undef JSON_HEDLEY_DEPRECATED_FOR
1340#endif
1341#if \
1342 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1343 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1344 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1345 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1346#elif \
1347 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1348 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1349 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1350 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1351 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1352 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1353 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1354 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1355 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1356 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1357 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1358 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1359 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1360 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1361#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1362 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1363 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1364#elif \
1365 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1366 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1367 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1368 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1369 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1370 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1371 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1372 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1373 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1374 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1375 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1376 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1377 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1378 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1379 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1380 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1381 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1382 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1383#elif \
1384 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1385 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1386 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1387 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1388 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1389#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1390 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1391 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1392#else
1393 #define JSON_HEDLEY_DEPRECATED(since)
1394 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1395#endif
1396
1397#if defined(JSON_HEDLEY_UNAVAILABLE)
1398 #undef JSON_HEDLEY_UNAVAILABLE
1399#endif
1400#if \
1401 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1402 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1403 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1404 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1405 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1406#else
1407 #define JSON_HEDLEY_UNAVAILABLE(available_since)
1408#endif
1409
1410#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1411 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1412#endif
1413#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1414 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1415#endif
1416#if \
1417 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1418 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1419 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1420 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1421 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1422 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1423 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1424 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1425 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1426 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1427 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1428 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1429 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1430 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1431 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1432 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1433 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1434 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1435 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1436#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1437 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1438 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1439#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1440 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1441 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1442#elif defined(_Check_return_) /* SAL */
1443 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1444 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1445#else
1446 #define JSON_HEDLEY_WARN_UNUSED_RESULT
1447 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1448#endif
1449
1450#if defined(JSON_HEDLEY_SENTINEL)
1451 #undef JSON_HEDLEY_SENTINEL
1452#endif
1453#if \
1454 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1455 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1456 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1457 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1458 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1459 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1460#else
1461 #define JSON_HEDLEY_SENTINEL(position)
1462#endif
1463
1464#if defined(JSON_HEDLEY_NO_RETURN)
1465 #undef JSON_HEDLEY_NO_RETURN
1466#endif
1467#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1468 #define JSON_HEDLEY_NO_RETURN __noreturn
1469#elif \
1470 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1471 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1472 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1473#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1474 #define JSON_HEDLEY_NO_RETURN _Noreturn
1475#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1476 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1477#elif \
1478 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1479 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1480 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1481 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1482 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1483 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1484 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1485 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1486 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1487 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1488 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1489 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1490 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1491 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1492 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1493 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1494 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1495 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1496#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1497 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1498#elif \
1499 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1500 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1501 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1502#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1503 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1504#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1505 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1506#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1507 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1508#else
1509 #define JSON_HEDLEY_NO_RETURN
1510#endif
1511
1512#if defined(JSON_HEDLEY_NO_ESCAPE)
1513 #undef JSON_HEDLEY_NO_ESCAPE
1514#endif
1515#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1516 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1517#else
1518 #define JSON_HEDLEY_NO_ESCAPE
1519#endif
1520
1521#if defined(JSON_HEDLEY_UNREACHABLE)
1522 #undef JSON_HEDLEY_UNREACHABLE
1523#endif
1524#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1525 #undef JSON_HEDLEY_UNREACHABLE_RETURN
1526#endif
1527#if defined(JSON_HEDLEY_ASSUME)
1528 #undef JSON_HEDLEY_ASSUME
1529#endif
1530#if \
1531 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1532 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1533 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1534 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1535#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1536 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1537#elif \
1538 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1539 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1540 #if defined(__cplusplus)
1541 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1542 #else
1543 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1544 #endif
1545#endif
1546#if \
1547 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1548 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1549 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1550 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1551 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1552 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1553 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1554 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1555#elif defined(JSON_HEDLEY_ASSUME)
1556 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1557#endif
1558#if !defined(JSON_HEDLEY_ASSUME)
1559 #if defined(JSON_HEDLEY_UNREACHABLE)
1560 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1561 #else
1562 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1563 #endif
1564#endif
1565#if defined(JSON_HEDLEY_UNREACHABLE)
1566 #if \
1567 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1568 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1569 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1570 #else
1571 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1572 #endif
1573#else
1574 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1575#endif
1576#if !defined(JSON_HEDLEY_UNREACHABLE)
1577 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1578#endif
1579
1580JSON_HEDLEY_DIAGNOSTIC_PUSH
1581#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1582 #pragma clang diagnostic ignored "-Wpedantic"
1583#endif
1584#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1585 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1586#endif
1587#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1588 #if defined(__clang__)
1589 #pragma clang diagnostic ignored "-Wvariadic-macros"
1590 #elif defined(JSON_HEDLEY_GCC_VERSION)
1591 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1592 #endif
1593#endif
1594#if defined(JSON_HEDLEY_NON_NULL)
1595 #undef JSON_HEDLEY_NON_NULL
1596#endif
1597#if \
1598 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1599 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1600 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1601 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1602 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1603#else
1604 #define JSON_HEDLEY_NON_NULL(...)
1605#endif
1606JSON_HEDLEY_DIAGNOSTIC_POP
1607
1608#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1609 #undef JSON_HEDLEY_PRINTF_FORMAT
1610#endif
1611#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1612 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1613#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1614 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1615#elif \
1616 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1617 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1618 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1619 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1620 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1621 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1622 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1623 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1624 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1625 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1626 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1627 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1628 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1629 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1630 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1631 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1632 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1633 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1634#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1635 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1636#else
1637 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1638#endif
1639
1640#if defined(JSON_HEDLEY_CONSTEXPR)
1641 #undef JSON_HEDLEY_CONSTEXPR
1642#endif
1643#if defined(__cplusplus)
1644 #if __cplusplus >= 201103L
1645 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1646 #endif
1647#endif
1648#if !defined(JSON_HEDLEY_CONSTEXPR)
1649 #define JSON_HEDLEY_CONSTEXPR
1650#endif
1651
1652#if defined(JSON_HEDLEY_PREDICT)
1653 #undef JSON_HEDLEY_PREDICT
1654#endif
1655#if defined(JSON_HEDLEY_LIKELY)
1656 #undef JSON_HEDLEY_LIKELY
1657#endif
1658#if defined(JSON_HEDLEY_UNLIKELY)
1659 #undef JSON_HEDLEY_UNLIKELY
1660#endif
1661#if defined(JSON_HEDLEY_UNPREDICTABLE)
1662 #undef JSON_HEDLEY_UNPREDICTABLE
1663#endif
1664#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1665 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1666#endif
1667#if \
1668 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1669 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1670 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1671# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1672# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1673# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1674# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1675# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1676#elif \
1677 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1678 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1679 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1680 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1681 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1682 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1683 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1684 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1685 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1686 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1687 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1688 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1689 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1690 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1691 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1692 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1693# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1694 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1695# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1696 (__extension__ ({ \
1697 double hedley_probability_ = (probability); \
1698 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1699 }))
1700# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1701 (__extension__ ({ \
1702 double hedley_probability_ = (probability); \
1703 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1704 }))
1705# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1706# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1707#else
1708# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1709# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1710# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1711# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1712# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1713#endif
1714#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1715 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1716#endif
1717
1718#if defined(JSON_HEDLEY_MALLOC)
1719 #undef JSON_HEDLEY_MALLOC
1720#endif
1721#if \
1722 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1723 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1724 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1725 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1726 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1727 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1728 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1729 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1730 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1731 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1732 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1733 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1734 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1735 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1736 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1737 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1738 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1739 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1740 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1741#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1742 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1743#elif \
1744 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1745 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1746 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1747#else
1748 #define JSON_HEDLEY_MALLOC
1749#endif
1750
1751#if defined(JSON_HEDLEY_PURE)
1752 #undef JSON_HEDLEY_PURE
1753#endif
1754#if \
1755 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1756 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1757 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1758 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1759 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1760 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1761 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1762 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1763 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1764 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1765 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1766 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1767 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1768 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1769 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1770 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1771 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1772 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1773 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1774# define JSON_HEDLEY_PURE __attribute__((__pure__))
1775#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1776# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1777#elif defined(__cplusplus) && \
1778 ( \
1779 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1780 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1781 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1782 )
1783# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1784#else
1785# define JSON_HEDLEY_PURE
1786#endif
1787
1788#if defined(JSON_HEDLEY_CONST)
1789 #undef JSON_HEDLEY_CONST
1790#endif
1791#if \
1792 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1793 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1794 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1795 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1796 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1797 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1798 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1799 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1800 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1801 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1802 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1803 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1804 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1805 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1806 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1807 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1808 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1809 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1810 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1811 #define JSON_HEDLEY_CONST __attribute__((__const__))
1812#elif \
1813 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1814 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1815#else
1816 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1817#endif
1818
1819#if defined(JSON_HEDLEY_RESTRICT)
1820 #undef JSON_HEDLEY_RESTRICT
1821#endif
1822#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1823 #define JSON_HEDLEY_RESTRICT restrict
1824#elif \
1825 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1826 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1827 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1828 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1829 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1830 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1831 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1832 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1833 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1834 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1835 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1836 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1837 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1838 defined(__clang__) || \
1839 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1840 #define JSON_HEDLEY_RESTRICT __restrict
1841#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1842 #define JSON_HEDLEY_RESTRICT _Restrict
1843#else
1844 #define JSON_HEDLEY_RESTRICT
1845#endif
1846
1847#if defined(JSON_HEDLEY_INLINE)
1848 #undef JSON_HEDLEY_INLINE
1849#endif
1850#if \
1851 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1852 (defined(__cplusplus) && (__cplusplus >= 199711L))
1853 #define JSON_HEDLEY_INLINE inline
1854#elif \
1855 defined(JSON_HEDLEY_GCC_VERSION) || \
1856 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1857 #define JSON_HEDLEY_INLINE __inline__
1858#elif \
1859 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1860 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1861 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1862 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1863 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1864 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1865 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1866 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1867 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1868 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1869 #define JSON_HEDLEY_INLINE __inline
1870#else
1871 #define JSON_HEDLEY_INLINE
1872#endif
1873
1874#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1875 #undef JSON_HEDLEY_ALWAYS_INLINE
1876#endif
1877#if \
1878 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1879 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1880 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1881 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1882 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1883 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1884 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1885 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1886 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1887 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1888 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1889 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1890 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1891 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1892 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1893 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1894 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1895 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1896 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1897# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1898#elif \
1899 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1900 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1901# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1902#elif defined(__cplusplus) && \
1903 ( \
1904 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1905 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1906 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1907 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1908 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1909 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1910 )
1911# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1912#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1913# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1914#else
1915# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1916#endif
1917
1918#if defined(JSON_HEDLEY_NEVER_INLINE)
1919 #undef JSON_HEDLEY_NEVER_INLINE
1920#endif
1921#if \
1922 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1923 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1924 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1925 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1926 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1927 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1928 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1929 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1930 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1931 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1932 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1933 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1934 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1935 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1936 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1937 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1938 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1939 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1940 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1941 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1942#elif \
1943 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1944 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1945 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1946#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1947 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1948#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1949 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1950#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1951 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1952#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1953 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1954#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1955 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1956#else
1957 #define JSON_HEDLEY_NEVER_INLINE
1958#endif
1959
1960#if defined(JSON_HEDLEY_PRIVATE)
1961 #undef JSON_HEDLEY_PRIVATE
1962#endif
1963#if defined(JSON_HEDLEY_PUBLIC)
1964 #undef JSON_HEDLEY_PUBLIC
1965#endif
1966#if defined(JSON_HEDLEY_IMPORT)
1967 #undef JSON_HEDLEY_IMPORT
1968#endif
1969#if defined(_WIN32) || defined(__CYGWIN__)
1970# define JSON_HEDLEY_PRIVATE
1971# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1972# define JSON_HEDLEY_IMPORT __declspec(dllimport)
1973#else
1974# if \
1975 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1976 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1977 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1978 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1979 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1980 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1981 ( \
1982 defined(__TI_EABI__) && \
1983 ( \
1984 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1985 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
1986 ) \
1987 ) || \
1988 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1989# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
1990# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
1991# else
1992# define JSON_HEDLEY_PRIVATE
1993# define JSON_HEDLEY_PUBLIC
1994# endif
1995# define JSON_HEDLEY_IMPORT extern
1996#endif
1997
1998#if defined(JSON_HEDLEY_NO_THROW)
1999 #undef JSON_HEDLEY_NO_THROW
2000#endif
2001#if \
2002 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
2003 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
2004 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2005 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2006 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
2007#elif \
2008 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
2009 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
2010 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
2011 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
2012#else
2013 #define JSON_HEDLEY_NO_THROW
2014#endif
2015
2016#if defined(JSON_HEDLEY_FALL_THROUGH)
2017 #undef JSON_HEDLEY_FALL_THROUGH
2018#endif
2019#if \
2020 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
2021 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
2022 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2023 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
2024#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
2025 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
2026#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
2027 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
2028#elif defined(__fallthrough) /* SAL */
2029 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
2030#else
2031 #define JSON_HEDLEY_FALL_THROUGH
2032#endif
2033
2034#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
2035 #undef JSON_HEDLEY_RETURNS_NON_NULL
2036#endif
2037#if \
2038 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
2039 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2040 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2041 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
2042#elif defined(_Ret_notnull_) /* SAL */
2043 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
2044#else
2045 #define JSON_HEDLEY_RETURNS_NON_NULL
2046#endif
2047
2048#if defined(JSON_HEDLEY_ARRAY_PARAM)
2049 #undef JSON_HEDLEY_ARRAY_PARAM
2050#endif
2051#if \
2052 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
2053 !defined(__STDC_NO_VLA__) && \
2054 !defined(__cplusplus) && \
2055 !defined(JSON_HEDLEY_PGI_VERSION) && \
2056 !defined(JSON_HEDLEY_TINYC_VERSION)
2057 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
2058#else
2059 #define JSON_HEDLEY_ARRAY_PARAM(name)
2060#endif
2061
2062#if defined(JSON_HEDLEY_IS_CONSTANT)
2063 #undef JSON_HEDLEY_IS_CONSTANT
2064#endif
2065#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
2066 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
2067#endif
2068/* JSON_HEDLEY_IS_CONSTEXPR_ is for
2069 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
2070#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2071 #undef JSON_HEDLEY_IS_CONSTEXPR_
2072#endif
2073#if \
2074 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
2075 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2076 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2077 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
2078 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
2079 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2080 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
2081 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
2082 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2083 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2084 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
2085#endif
2086#if !defined(__cplusplus)
2087# if \
2088 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
2089 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2090 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2091 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2092 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2093 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
2094 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
2095#if defined(__INTPTR_TYPE__)
2096 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
2097#else
2098 #include <stdint.h>
2099 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
2100#endif
2101# elif \
2102 ( \
2103 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
2104 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
2105 !defined(JSON_HEDLEY_PGI_VERSION) && \
2106 !defined(JSON_HEDLEY_IAR_VERSION)) || \
2107 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
2108 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2109 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
2110 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
2111 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
2112#if defined(__INTPTR_TYPE__)
2113 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
2114#else
2115 #include <stdint.h>
2116 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
2117#endif
2118# elif \
2119 defined(JSON_HEDLEY_GCC_VERSION) || \
2120 defined(JSON_HEDLEY_INTEL_VERSION) || \
2121 defined(JSON_HEDLEY_TINYC_VERSION) || \
2122 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
2123 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
2124 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
2125 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
2126 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
2127 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
2128 defined(__clang__)
2129# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
2130 sizeof(void) != \
2131 sizeof(*( \
2132 1 ? \
2133 ((void*) ((expr) * 0L) ) : \
2134((struct { char v[sizeof(void) * 2]; } *) 1) \
2135 ) \
2136 ) \
2137 )
2138# endif
2139#endif
2140#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2141 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2142 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2143 #endif
2144 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2145#else
2146 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2147 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2148 #endif
2149 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2150#endif
2151
2152#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2153 #undef JSON_HEDLEY_BEGIN_C_DECLS
2154#endif
2155#if defined(JSON_HEDLEY_END_C_DECLS)
2156 #undef JSON_HEDLEY_END_C_DECLS
2157#endif
2158#if defined(JSON_HEDLEY_C_DECL)
2159 #undef JSON_HEDLEY_C_DECL
2160#endif
2161#if defined(__cplusplus)
2162 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2163 #define JSON_HEDLEY_END_C_DECLS }
2164 #define JSON_HEDLEY_C_DECL extern "C"
2165#else
2166 #define JSON_HEDLEY_BEGIN_C_DECLS
2167 #define JSON_HEDLEY_END_C_DECLS
2168 #define JSON_HEDLEY_C_DECL
2169#endif
2170
2171#if defined(JSON_HEDLEY_STATIC_ASSERT)
2172 #undef JSON_HEDLEY_STATIC_ASSERT
2173#endif
2174#if \
2175 !defined(__cplusplus) && ( \
2176 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2177 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2178 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2179 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2180 defined(_Static_assert) \
2181 )
2182# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2183#elif \
2184 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2185 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2186 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2187# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2188#else
2189# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2190#endif
2191
2192#if defined(JSON_HEDLEY_NULL)
2193 #undef JSON_HEDLEY_NULL
2194#endif
2195#if defined(__cplusplus)
2196 #if __cplusplus >= 201103L
2197 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2198 #elif defined(NULL)
2199 #define JSON_HEDLEY_NULL NULL
2200 #else
2201 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2202 #endif
2203#elif defined(NULL)
2204 #define JSON_HEDLEY_NULL NULL
2205#else
2206 #define JSON_HEDLEY_NULL ((void*) 0)
2207#endif
2208
2209#if defined(JSON_HEDLEY_MESSAGE)
2210 #undef JSON_HEDLEY_MESSAGE
2211#endif
2212#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2213# define JSON_HEDLEY_MESSAGE(msg) \
2214 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2215 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2216 JSON_HEDLEY_PRAGMA(message msg) \
2217 JSON_HEDLEY_DIAGNOSTIC_POP
2218#elif \
2219 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2220 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2221# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2222#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2223# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2224#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2225# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2226#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2227# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2228#else
2229# define JSON_HEDLEY_MESSAGE(msg)
2230#endif
2231
2232#if defined(JSON_HEDLEY_WARNING)
2233 #undef JSON_HEDLEY_WARNING
2234#endif
2235#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2236# define JSON_HEDLEY_WARNING(msg) \
2237 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2238 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2239 JSON_HEDLEY_PRAGMA(clang warning msg) \
2240 JSON_HEDLEY_DIAGNOSTIC_POP
2241#elif \
2242 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2243 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2244 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2245# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2246#elif \
2247 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2248 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2249# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2250#else
2251# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2252#endif
2253
2254#if defined(JSON_HEDLEY_REQUIRE)
2255 #undef JSON_HEDLEY_REQUIRE
2256#endif
2257#if defined(JSON_HEDLEY_REQUIRE_MSG)
2258 #undef JSON_HEDLEY_REQUIRE_MSG
2259#endif
2260#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2261# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2262# define JSON_HEDLEY_REQUIRE(expr) \
2263 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2264 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2265 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2266 JSON_HEDLEY_DIAGNOSTIC_POP
2267# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2268 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2269 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2270 __attribute__((diagnose_if(!(expr), msg, "error"))) \
2271 JSON_HEDLEY_DIAGNOSTIC_POP
2272# else
2273# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2274# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2275# endif
2276#else
2277# define JSON_HEDLEY_REQUIRE(expr)
2278# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2279#endif
2280
2281#if defined(JSON_HEDLEY_FLAGS)
2282 #undef JSON_HEDLEY_FLAGS
2283#endif
2284#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2285 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2286#else
2287 #define JSON_HEDLEY_FLAGS
2288#endif
2289
2290#if defined(JSON_HEDLEY_FLAGS_CAST)
2291 #undef JSON_HEDLEY_FLAGS_CAST
2292#endif
2293#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2294# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2295 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2296 _Pragma("warning(disable:188)") \
2297 ((T) (expr)); \
2298 JSON_HEDLEY_DIAGNOSTIC_POP \
2299 }))
2300#else
2301# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2302#endif
2303
2304#if defined(JSON_HEDLEY_EMPTY_BASES)
2305 #undef JSON_HEDLEY_EMPTY_BASES
2306#endif
2307#if \
2308 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2309 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2310 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2311#else
2312 #define JSON_HEDLEY_EMPTY_BASES
2313#endif
2314
2315/* Remaining macros are deprecated. */
2316
2317#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2318 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2319#endif
2320#if defined(__clang__)
2321 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2322#else
2323 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2324#endif
2325
2326#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2327 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2328#endif
2329#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2330
2331#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2332 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2333#endif
2334#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2335
2336#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2337 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2338#endif
2339#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2340
2341#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2342 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2343#endif
2344#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2345
2346#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2347 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2348#endif
2349#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2350
2351#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2352 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2353#endif
2354#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2355
2356#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2357 #undef JSON_HEDLEY_CLANG_HAS_WARNING
2358#endif
2359#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2360
2361#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2362
2363
2364// This file contains all internal macro definitions (except those affecting ABI)
2365// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2366
2367// #include <nlohmann/detail/abi_macros.hpp>
2368
2369
2370// exclude unsupported compilers
2371#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2372 #if defined(__clang__)
2373 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2374 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2375 #endif
2376 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2377 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2378 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2379 #endif
2380 #endif
2381#endif
2382
2383// C++ language standard detection
2384// if the user manually specified the used c++ version this is skipped
2385#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2386 #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2387 #define JSON_HAS_CPP_20
2388 #define JSON_HAS_CPP_17
2389 #define JSON_HAS_CPP_14
2390 #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2391 #define JSON_HAS_CPP_17
2392 #define JSON_HAS_CPP_14
2393 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2394 #define JSON_HAS_CPP_14
2395 #endif
2396 // the cpp 11 flag is always specified because it is the minimal required version
2397 #define JSON_HAS_CPP_11
2398#endif
2399
2400#ifdef __has_include
2401 #if __has_include(<version>)
2402 #include <version>
2403 #endif
2404#endif
2405
2406#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2407 #ifdef JSON_HAS_CPP_17
2408 #if defined(__cpp_lib_filesystem)
2409 #define JSON_HAS_FILESYSTEM 1
2410 #elif defined(__cpp_lib_experimental_filesystem)
2411 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2412 #elif !defined(__has_include)
2413 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2414 #elif __has_include(<filesystem>)
2415 #define JSON_HAS_FILESYSTEM 1
2416 #elif __has_include(<experimental/filesystem>)
2417 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2418 #endif
2419
2420 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2421 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2422 #undef JSON_HAS_FILESYSTEM
2423 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2424 #endif
2425
2426 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2427 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2428 #undef JSON_HAS_FILESYSTEM
2429 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2430 #endif
2431
2432 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2433 #if defined(__clang_major__) && __clang_major__ < 7
2434 #undef JSON_HAS_FILESYSTEM
2435 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2436 #endif
2437
2438 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2439 #if defined(_MSC_VER) && _MSC_VER < 1914
2440 #undef JSON_HAS_FILESYSTEM
2441 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2442 #endif
2443
2444 // no filesystem support before iOS 13
2445 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2446 #undef JSON_HAS_FILESYSTEM
2447 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2448 #endif
2449
2450 // no filesystem support before macOS Catalina
2451 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2452 #undef JSON_HAS_FILESYSTEM
2453 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2454 #endif
2455 #endif
2456#endif
2457
2458#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2459 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2460#endif
2461
2462#ifndef JSON_HAS_FILESYSTEM
2463 #define JSON_HAS_FILESYSTEM 0
2464#endif
2465
2466#ifndef JSON_HAS_THREE_WAY_COMPARISON
2467 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
2468 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2469 #define JSON_HAS_THREE_WAY_COMPARISON 1
2470 #else
2471 #define JSON_HAS_THREE_WAY_COMPARISON 0
2472 #endif
2473#endif
2474
2475#ifndef JSON_HAS_RANGES
2476 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error
2477 #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2478 #define JSON_HAS_RANGES 0
2479 #elif defined(__cpp_lib_ranges)
2480 #define JSON_HAS_RANGES 1
2481 #else
2482 #define JSON_HAS_RANGES 0
2483 #endif
2484#endif
2485
2486#ifdef JSON_HAS_CPP_17
2487 #define JSON_INLINE_VARIABLE inline
2488#else
2489 #define JSON_INLINE_VARIABLE
2490#endif
2491
2492#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2493 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2494#else
2495 #define JSON_NO_UNIQUE_ADDRESS
2496#endif
2497
2498// disable documentation warnings on clang
2499#if defined(__clang__)
2500 #pragma clang diagnostic push
2501 #pragma clang diagnostic ignored "-Wdocumentation"
2502 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2503#endif
2504
2505// allow disabling exceptions
2506#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2507 #define JSON_THROW(exception) throw exception
2508 #define JSON_TRY try
2509 #define JSON_CATCH(exception) catch(exception)
2510 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2511#else
2512 #include <cstdlib>
2513 #define JSON_THROW(exception) std::abort()
2514 #define JSON_TRY if(true)
2515 #define JSON_CATCH(exception) if(false)
2516 #define JSON_INTERNAL_CATCH(exception) if(false)
2517#endif
2518
2519// override exception macros
2520#if defined(JSON_THROW_USER)
2521 #undef JSON_THROW
2522 #define JSON_THROW JSON_THROW_USER
2523#endif
2524#if defined(JSON_TRY_USER)
2525 #undef JSON_TRY
2526 #define JSON_TRY JSON_TRY_USER
2527#endif
2528#if defined(JSON_CATCH_USER)
2529 #undef JSON_CATCH
2530 #define JSON_CATCH JSON_CATCH_USER
2531 #undef JSON_INTERNAL_CATCH
2532 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2533#endif
2534#if defined(JSON_INTERNAL_CATCH_USER)
2535 #undef JSON_INTERNAL_CATCH
2536 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2537#endif
2538
2539// allow overriding assert
2540#if !defined(JSON_ASSERT)
2541 #include <cassert> // assert
2542 #define JSON_ASSERT(x) assert(x)
2543#endif
2544
2545// allow to access some private functions (needed by the test suite)
2546#if defined(JSON_TESTS_PRIVATE)
2547 #define JSON_PRIVATE_UNLESS_TESTED public
2548#else
2549 #define JSON_PRIVATE_UNLESS_TESTED private
2550#endif
2551
2552/*!
2553@brief macro to briefly define a mapping between an enum and JSON
2554@def NLOHMANN_JSON_SERIALIZE_ENUM
2555@since version 3.4.0
2556*/
2557#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2558 template<typename BasicJsonType> \
2559 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2560 { \
2561 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2562 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2563 auto it = std::find_if(std::begin(m), std::end(m), \
2564 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2565 { \
2566 return ej_pair.first == e; \
2567 }); \
2568 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2569 } \
2570 template<typename BasicJsonType> \
2571 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2572 { \
2573 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2574 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2575 auto it = std::find_if(std::begin(m), std::end(m), \
2576 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2577 { \
2578 return ej_pair.second == j; \
2579 }); \
2580 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2581 }
2582
2583// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2584// may be removed in the future once the class is split.
2585
2586#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2587 template<template<typename, typename, typename...> class ObjectType, \
2588 template<typename, typename...> class ArrayType, \
2589 class StringType, class BooleanType, class NumberIntegerType, \
2590 class NumberUnsignedType, class NumberFloatType, \
2591 template<typename> class AllocatorType, \
2592 template<typename, typename = void> class JSONSerializer, \
2593 class BinaryType>
2594
2595#define NLOHMANN_BASIC_JSON_TPL \
2596 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2597 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2598 AllocatorType, JSONSerializer, BinaryType>
2599
2600// Macros to simplify conversion from/to types
2601
2602#define NLOHMANN_JSON_EXPAND( x ) x
2603#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
2604#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2605 NLOHMANN_JSON_PASTE64, \
2606 NLOHMANN_JSON_PASTE63, \
2607 NLOHMANN_JSON_PASTE62, \
2608 NLOHMANN_JSON_PASTE61, \
2609 NLOHMANN_JSON_PASTE60, \
2610 NLOHMANN_JSON_PASTE59, \
2611 NLOHMANN_JSON_PASTE58, \
2612 NLOHMANN_JSON_PASTE57, \
2613 NLOHMANN_JSON_PASTE56, \
2614 NLOHMANN_JSON_PASTE55, \
2615 NLOHMANN_JSON_PASTE54, \
2616 NLOHMANN_JSON_PASTE53, \
2617 NLOHMANN_JSON_PASTE52, \
2618 NLOHMANN_JSON_PASTE51, \
2619 NLOHMANN_JSON_PASTE50, \
2620 NLOHMANN_JSON_PASTE49, \
2621 NLOHMANN_JSON_PASTE48, \
2622 NLOHMANN_JSON_PASTE47, \
2623 NLOHMANN_JSON_PASTE46, \
2624 NLOHMANN_JSON_PASTE45, \
2625 NLOHMANN_JSON_PASTE44, \
2626 NLOHMANN_JSON_PASTE43, \
2627 NLOHMANN_JSON_PASTE42, \
2628 NLOHMANN_JSON_PASTE41, \
2629 NLOHMANN_JSON_PASTE40, \
2630 NLOHMANN_JSON_PASTE39, \
2631 NLOHMANN_JSON_PASTE38, \
2632 NLOHMANN_JSON_PASTE37, \
2633 NLOHMANN_JSON_PASTE36, \
2634 NLOHMANN_JSON_PASTE35, \
2635 NLOHMANN_JSON_PASTE34, \
2636 NLOHMANN_JSON_PASTE33, \
2637 NLOHMANN_JSON_PASTE32, \
2638 NLOHMANN_JSON_PASTE31, \
2639 NLOHMANN_JSON_PASTE30, \
2640 NLOHMANN_JSON_PASTE29, \
2641 NLOHMANN_JSON_PASTE28, \
2642 NLOHMANN_JSON_PASTE27, \
2643 NLOHMANN_JSON_PASTE26, \
2644 NLOHMANN_JSON_PASTE25, \
2645 NLOHMANN_JSON_PASTE24, \
2646 NLOHMANN_JSON_PASTE23, \
2647 NLOHMANN_JSON_PASTE22, \
2648 NLOHMANN_JSON_PASTE21, \
2649 NLOHMANN_JSON_PASTE20, \
2650 NLOHMANN_JSON_PASTE19, \
2651 NLOHMANN_JSON_PASTE18, \
2652 NLOHMANN_JSON_PASTE17, \
2653 NLOHMANN_JSON_PASTE16, \
2654 NLOHMANN_JSON_PASTE15, \
2655 NLOHMANN_JSON_PASTE14, \
2656 NLOHMANN_JSON_PASTE13, \
2657 NLOHMANN_JSON_PASTE12, \
2658 NLOHMANN_JSON_PASTE11, \
2659 NLOHMANN_JSON_PASTE10, \
2660 NLOHMANN_JSON_PASTE9, \
2661 NLOHMANN_JSON_PASTE8, \
2662 NLOHMANN_JSON_PASTE7, \
2663 NLOHMANN_JSON_PASTE6, \
2664 NLOHMANN_JSON_PASTE5, \
2665 NLOHMANN_JSON_PASTE4, \
2666 NLOHMANN_JSON_PASTE3, \
2667 NLOHMANN_JSON_PASTE2, \
2668 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2669#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2670#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2671#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2672#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2673#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2674#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
2675#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
2676#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
2677#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
2678#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
2679#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
2680#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
2681#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
2682#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
2683#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
2684#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
2685#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
2686#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
2687#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
2688#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
2689#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
2690#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
2691#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
2692#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
2693#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
2694#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
2695#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
2696#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
2697#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
2698#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
2699#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
2700#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
2701#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
2702#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
2703#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
2704#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
2705#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
2706#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
2707#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
2708#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
2709#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
2710#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
2711#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
2712#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
2713#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
2714#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
2715#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
2716#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
2717#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
2718#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
2719#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
2720#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
2721#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
2722#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
2723#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
2724#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
2725#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
2726#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
2727#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
2728#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
2729#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
2730#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
2731#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
2732
2733#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2734#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2735#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
2736
2737/*!
2738@brief macro
2739@def NLOHMANN_DEFINE_TYPE_INTRUSIVE
2740@since version 3.9.0
2741*/
2742#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2743 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2744 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2745
2746#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2747 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2748 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2749
2750/*!
2751@brief macro
2752@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
2753@since version 3.9.0
2754*/
2755#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2756 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2757 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2758
2759#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2760 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2761 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2762
2763
2764// inspired from https://stackoverflow.com/a/26745591
2765// allows to call any std function as if (e.g. with begin):
2766// using std::begin; begin(x);
2767//
2768// it allows using the detected idiom to retrieve the return type
2769// of such an expression
2770#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2771 namespace detail { \
2772 using std::std_name; \
2773 \
2774 template<typename... T> \
2775 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2776 } \
2777 \
2778 namespace detail2 { \
2779 struct std_name##_tag \
2780 { \
2781 }; \
2782 \
2783 template<typename... T> \
2784 std_name##_tag std_name(T&&...); \
2785 \
2786 template<typename... T> \
2787 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2788 \
2789 template<typename... T> \
2790 struct would_call_std_##std_name \
2791 { \
2792 static constexpr auto const value = ::nlohmann::detail:: \
2793 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2794 }; \
2795 } /* namespace detail2 */ \
2796 \
2797 template<typename... T> \
2798 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2799 { \
2800 }
2801
2802#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2803 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2804#endif
2805
2806#if JSON_USE_IMPLICIT_CONVERSIONS
2807 #define JSON_EXPLICIT
2808#else
2809 #define JSON_EXPLICIT explicit
2810#endif
2811
2812#ifndef JSON_DISABLE_ENUM_SERIALIZATION
2813 #define JSON_DISABLE_ENUM_SERIALIZATION 0
2814#endif
2815
2816#ifndef JSON_USE_GLOBAL_UDLS
2817 #define JSON_USE_GLOBAL_UDLS 1
2818#endif
2819
2820#if JSON_HAS_THREE_WAY_COMPARISON
2821 #include <compare> // partial_ordering
2822#endif
2823
2824NLOHMANN_JSON_NAMESPACE_BEGIN
2825namespace detail
2826{
2827
2828///////////////////////////
2829// JSON type enumeration //
2830///////////////////////////
2831
2832/*!
2833@brief the JSON type enumeration
2834
2835This enumeration collects the different JSON types. It is internally used to
2836distinguish the stored values, and the functions @ref basic_json::is_null(),
2837@ref basic_json::is_object(), @ref basic_json::is_array(),
2838@ref basic_json::is_string(), @ref basic_json::is_boolean(),
2839@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
2840@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
2841@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
2842@ref basic_json::is_structured() rely on it.
2843
2844@note There are three enumeration entries (number_integer, number_unsigned, and
2845number_float), because the library distinguishes these three types for numbers:
2846@ref basic_json::number_unsigned_t is used for unsigned integers,
2847@ref basic_json::number_integer_t is used for signed integers, and
2848@ref basic_json::number_float_t is used for floating-point numbers or to
2849approximate integers which do not fit in the limits of their respective type.
2850
2851@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON
2852value with the default value for a given type
2853
2854@since version 1.0.0
2855*/
2856enum class value_t : std::uint8_t
2857{
2858 null, ///< null value
2859 object, ///< object (unordered set of name/value pairs)
2860 array, ///< array (ordered collection of values)
2861 string, ///< string value
2862 boolean, ///< boolean value
2863 number_integer, ///< number value (signed integer)
2864 number_unsigned, ///< number value (unsigned integer)
2865 number_float, ///< number value (floating-point)
2866 binary, ///< binary array (ordered collection of bytes)
2867 discarded ///< discarded by the parser callback function
2868};
2869
2870/*!
2871@brief comparison operator for JSON types
2872
2873Returns an ordering that is similar to Python:
2874- order: null < boolean < number < object < array < string < binary
2875- furthermore, each type is not smaller than itself
2876- discarded values are not comparable
2877- binary is represented as a b"" string in python and directly comparable to a
2878 string; however, making a binary array directly comparable with a string would
2879 be surprising behavior in a JSON file.
2880
2881@since version 1.0.0
2882*/
2883#if JSON_HAS_THREE_WAY_COMPARISON
2884 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
2885#else
2886 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2887#endif
2888{
2889 static constexpr std::array<std::uint8_t, 9> order = {{
2890 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
2891 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
2892 6 /* binary */
2893 }
2894 };
2895
2896 const auto l_index = static_cast<std::size_t>(lhs);
2897 const auto r_index = static_cast<std::size_t>(rhs);
2898#if JSON_HAS_THREE_WAY_COMPARISON
2899 if (l_index < order.size() && r_index < order.size())
2900 {
2901 return order[l_index] <=> order[r_index]; // *NOPAD*
2902 }
2903 return std::partial_ordering::unordered;
2904#else
2905 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
2906#endif
2907}
2908
2909// GCC selects the built-in operator< over an operator rewritten from
2910// a user-defined spaceship operator
2911// Clang, MSVC, and ICC select the rewritten candidate
2912// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
2913#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
2914inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2915{
2916 return std::is_lt(lhs <=> rhs); // *NOPAD*
2917}
2918#endif
2919
2920} // namespace detail
2921NLOHMANN_JSON_NAMESPACE_END
2922
2923// #include <nlohmann/detail/string_escape.hpp>
2924// __ _____ _____ _____
2925// __| | __| | | | JSON for Modern C++
2926// | | |__ | | | | | | version 3.11.2
2927// |_____|_____|_____|_|___| https://github.com/nlohmann/json
2928//
2929// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
2930// SPDX-License-Identifier: MIT
2931
2932
2933
2934// #include <nlohmann/detail/abi_macros.hpp>
2935
2936
2937NLOHMANN_JSON_NAMESPACE_BEGIN
2938namespace detail
2939{
2940
2941/*!
2942@brief replace all occurrences of a substring by another string
2943
2944@param[in,out] s the string to manipulate; changed so that all
2945 occurrences of @a f are replaced with @a t
2946@param[in] f the substring to replace with @a t
2947@param[in] t the string to replace @a f
2948
2949@pre The search string @a f must not be empty. **This precondition is
2950enforced with an assertion.**
2951
2952@since version 2.0.0
2953*/
2954template<typename StringType>
2955inline void replace_substring(StringType& s, const StringType& f,
2956 const StringType& t)
2957{
2958 JSON_ASSERT(!f.empty());
2959 for (auto pos = s.find(f); // find first occurrence of f
2960 pos != StringType::npos; // make sure f was found
2961 s.replace(pos, f.size(), t), // replace with t, and
2962 pos = s.find(f, pos + t.size())) // find next occurrence of f
2963 {}
2964}
2965
2966/*!
2967 * @brief string escaping as described in RFC 6901 (Sect. 4)
2968 * @param[in] s string to escape
2969 * @return escaped string
2970 *
2971 * Note the order of escaping "~" to "~0" and "/" to "~1" is important.
2972 */
2973template<typename StringType>
2974inline StringType escape(StringType s)
2975{
2976 replace_substring(s, StringType{"~"}, StringType{"~0"});
2977 replace_substring(s, StringType{"/"}, StringType{"~1"});
2978 return s;
2979}
2980
2981/*!
2982 * @brief string unescaping as described in RFC 6901 (Sect. 4)
2983 * @param[in] s string to unescape
2984 * @return unescaped string
2985 *
2986 * Note the order of escaping "~1" to "/" and "~0" to "~" is important.
2987 */
2988template<typename StringType>
2989static void unescape(StringType& s)
2990{
2991 replace_substring(s, StringType{"~1"}, StringType{"/"});
2992 replace_substring(s, StringType{"~0"}, StringType{"~"});
2993}
2994
2995} // namespace detail
2996NLOHMANN_JSON_NAMESPACE_END
2997
2998// #include <nlohmann/detail/input/position_t.hpp>
2999// __ _____ _____ _____
3000// __| | __| | | | JSON for Modern C++
3001// | | |__ | | | | | | version 3.11.2
3002// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3003//
3004// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3005// SPDX-License-Identifier: MIT
3006
3007
3008
3009#include <cstddef> // size_t
3010
3011// #include <nlohmann/detail/abi_macros.hpp>
3012
3013
3014NLOHMANN_JSON_NAMESPACE_BEGIN
3015namespace detail
3016{
3017
3018/// struct to capture the start position of the current token
3019struct position_t
3020{
3021 /// the total number of characters read
3022 std::size_t chars_read_total = 0;
3023 /// the number of characters read in the current line
3024 std::size_t chars_read_current_line = 0;
3025 /// the number of lines read
3026 std::size_t lines_read = 0;
3027
3028 /// conversion to size_t to preserve SAX interface
3029 constexpr operator size_t() const
3030 {
3031 return chars_read_total;
3032 }
3033};
3034
3035} // namespace detail
3036NLOHMANN_JSON_NAMESPACE_END
3037
3038// #include <nlohmann/detail/macro_scope.hpp>
3039
3040// #include <nlohmann/detail/meta/cpp_future.hpp>
3041// __ _____ _____ _____
3042// __| | __| | | | JSON for Modern C++
3043// | | |__ | | | | | | version 3.11.2
3044// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3045//
3046// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3047// SPDX-FileCopyrightText: 2018 The Abseil Authors
3048// SPDX-License-Identifier: MIT
3049
3050
3051
3052#include <array> // array
3053#include <cstddef> // size_t
3054#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3055#include <utility> // index_sequence, make_index_sequence, index_sequence_for
3056
3057// #include <nlohmann/detail/macro_scope.hpp>
3058
3059
3060NLOHMANN_JSON_NAMESPACE_BEGIN
3061namespace detail
3062{
3063
3064template<typename T>
3065using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3066
3067#ifdef JSON_HAS_CPP_14
3068
3069// the following utilities are natively available in C++14
3070using std::enable_if_t;
3071using std::index_sequence;
3072using std::make_index_sequence;
3073using std::index_sequence_for;
3074
3075#else
3076
3077// alias templates to reduce boilerplate
3078template<bool B, typename T = void>
3079using enable_if_t = typename std::enable_if<B, T>::type;
3080
3081// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3082// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3083
3084//// START OF CODE FROM GOOGLE ABSEIL
3085
3086// integer_sequence
3087//
3088// Class template representing a compile-time integer sequence. An instantiation
3089// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3090// type through its template arguments (which is a common need when
3091// working with C++11 variadic templates). `absl::integer_sequence` is designed
3092// to be a drop-in replacement for C++14's `std::integer_sequence`.
3093//
3094// Example:
3095//
3096// template< class T, T... Ints >
3097// void user_function(integer_sequence<T, Ints...>);
3098//
3099// int main()
3100// {
3101// // user_function's `T` will be deduced to `int` and `Ints...`
3102// // will be deduced to `0, 1, 2, 3, 4`.
3103// user_function(make_integer_sequence<int, 5>());
3104// }
3105template <typename T, T... Ints>
3106struct integer_sequence
3107{
3108 using value_type = T;
3109 static constexpr std::size_t size() noexcept
3110 {
3111 return sizeof...(Ints);
3112 }
3113};
3114
3115// index_sequence
3116//
3117// A helper template for an `integer_sequence` of `size_t`,
3118// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3119// `std::index_sequence`.
3120template <size_t... Ints>
3121using index_sequence = integer_sequence<size_t, Ints...>;
3122
3123namespace utility_internal
3124{
3125
3126template <typename Seq, size_t SeqSize, size_t Rem>
3127struct Extend;
3128
3129// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3130template <typename T, T... Ints, size_t SeqSize>
3131struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3132{
3133 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3134};
3135
3136template <typename T, T... Ints, size_t SeqSize>
3137struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3138{
3139 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3140};
3141
3142// Recursion helper for 'make_integer_sequence<T, N>'.
3143// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3144template <typename T, size_t N>
3145struct Gen
3146{
3147 using type =
3148 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3149};
3150
3151template <typename T>
3152struct Gen<T, 0>
3153{
3154 using type = integer_sequence<T>;
3155};
3156
3157} // namespace utility_internal
3158
3159// Compile-time sequences of integers
3160
3161// make_integer_sequence
3162//
3163// This template alias is equivalent to
3164// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3165// replacement for C++14's `std::make_integer_sequence`.
3166template <typename T, T N>
3167using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
3168
3169// make_index_sequence
3170//
3171// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3172// and is designed to be a drop-in replacement for C++14's
3173// `std::make_index_sequence`.
3174template <size_t N>
3175using make_index_sequence = make_integer_sequence<size_t, N>;
3176
3177// index_sequence_for
3178//
3179// Converts a typename pack into an index sequence of the same length, and
3180// is designed to be a drop-in replacement for C++14's
3181// `std::index_sequence_for()`
3182template <typename... Ts>
3183using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
3184
3185//// END OF CODE FROM GOOGLE ABSEIL
3186
3187#endif
3188
3189// dispatch utility (taken from ranges-v3)
3190template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3191template<> struct priority_tag<0> {};
3192
3193// taken from ranges-v3
3194template<typename T>
3195struct static_const
3196{
3197 static JSON_INLINE_VARIABLE constexpr T value{};
3198};
3199
3200#ifndef JSON_HAS_CPP_17
3201 template<typename T>
3202 constexpr T static_const<T>::value;
3203#endif
3204
3205template<typename T, typename... Args>
3206inline constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
3207{
3208 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
3209}
3210
3211} // namespace detail
3212NLOHMANN_JSON_NAMESPACE_END
3213
3214// #include <nlohmann/detail/meta/type_traits.hpp>
3215// __ _____ _____ _____
3216// __| | __| | | | JSON for Modern C++
3217// | | |__ | | | | | | version 3.11.2
3218// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3219//
3220// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3221// SPDX-License-Identifier: MIT
3222
3223
3224
3225#include <limits> // numeric_limits
3226#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3227#include <utility> // declval
3228#include <tuple> // tuple
3229
3230// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3231// __ _____ _____ _____
3232// __| | __| | | | JSON for Modern C++
3233// | | |__ | | | | | | version 3.11.2
3234// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3235//
3236// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3237// SPDX-License-Identifier: MIT
3238
3239
3240
3241#include <iterator> // random_access_iterator_tag
3242
3243// #include <nlohmann/detail/abi_macros.hpp>
3244
3245// #include <nlohmann/detail/meta/void_t.hpp>
3246
3247// #include <nlohmann/detail/meta/cpp_future.hpp>
3248
3249
3250NLOHMANN_JSON_NAMESPACE_BEGIN
3251namespace detail
3252{
3253
3254template<typename It, typename = void>
3255struct iterator_types {};
3256
3257template<typename It>
3258struct iterator_types <
3259 It,
3260 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3261 typename It::reference, typename It::iterator_category >>
3262{
3263 using difference_type = typename It::difference_type;
3264 using value_type = typename It::value_type;
3265 using pointer = typename It::pointer;
3266 using reference = typename It::reference;
3267 using iterator_category = typename It::iterator_category;
3268};
3269
3270// This is required as some compilers implement std::iterator_traits in a way that
3271// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3272template<typename T, typename = void>
3273struct iterator_traits
3274{
3275};
3276
3277template<typename T>
3278struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3279 : iterator_types<T>
3280{
3281};
3282
3283template<typename T>
3284struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
3285{
3286 using iterator_category = std::random_access_iterator_tag;
3287 using value_type = T;
3288 using difference_type = ptrdiff_t;
3289 using pointer = T*;
3290 using reference = T&;
3291};
3292
3293} // namespace detail
3294NLOHMANN_JSON_NAMESPACE_END
3295
3296// #include <nlohmann/detail/macro_scope.hpp>
3297
3298// #include <nlohmann/detail/meta/call_std/begin.hpp>
3299// __ _____ _____ _____
3300// __| | __| | | | JSON for Modern C++
3301// | | |__ | | | | | | version 3.11.2
3302// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3303//
3304// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3305// SPDX-License-Identifier: MIT
3306
3307
3308
3309// #include <nlohmann/detail/macro_scope.hpp>
3310
3311
3312NLOHMANN_JSON_NAMESPACE_BEGIN
3313
3314NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
3315
3316NLOHMANN_JSON_NAMESPACE_END
3317
3318// #include <nlohmann/detail/meta/call_std/end.hpp>
3319// __ _____ _____ _____
3320// __| | __| | | | JSON for Modern C++
3321// | | |__ | | | | | | version 3.11.2
3322// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3323//
3324// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3325// SPDX-License-Identifier: MIT
3326
3327
3328
3329// #include <nlohmann/detail/macro_scope.hpp>
3330
3331
3332NLOHMANN_JSON_NAMESPACE_BEGIN
3333
3334NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
3335
3336NLOHMANN_JSON_NAMESPACE_END
3337
3338// #include <nlohmann/detail/meta/cpp_future.hpp>
3339
3340// #include <nlohmann/detail/meta/detected.hpp>
3341
3342// #include <nlohmann/json_fwd.hpp>
3343// __ _____ _____ _____
3344// __| | __| | | | JSON for Modern C++
3345// | | |__ | | | | | | version 3.11.2
3346// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3347//
3348// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3349// SPDX-License-Identifier: MIT
3350
3351#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3352 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3353
3354 #include <cstdint> // int64_t, uint64_t
3355 #include <map> // map
3356 #include <memory> // allocator
3357 #include <string> // string
3358 #include <vector> // vector
3359
3360 // #include <nlohmann/detail/abi_macros.hpp>
3361
3362
3363 /*!
3364 @brief namespace for Niels Lohmann
3365 @see https://github.com/nlohmann
3366 @since version 1.0.0
3367 */
3368 NLOHMANN_JSON_NAMESPACE_BEGIN
3369
3370 /*!
3371 @brief default JSONSerializer template argument
3372
3373 This serializer ignores the template arguments and uses ADL
3374 ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
3375 for serialization.
3376 */
3377 template<typename T = void, typename SFINAE = void>
3378 struct adl_serializer;
3379
3380 /// a class to store JSON values
3381 /// @sa https://json.nlohmann.me/api/basic_json/
3382 template<template<typename U, typename V, typename... Args> class ObjectType =
3383 std::map,
3384 template<typename U, typename... Args> class ArrayType = std::vector,
3385 class StringType = std::string, class BooleanType = bool,
3386 class NumberIntegerType = std::int64_t,
3387 class NumberUnsignedType = std::uint64_t,
3388 class NumberFloatType = double,
3389 template<typename U> class AllocatorType = std::allocator,
3390 template<typename T, typename SFINAE = void> class JSONSerializer =
3391 adl_serializer,
3392 class BinaryType = std::vector<std::uint8_t>>
3393 class basic_json;
3394
3395 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
3396 /// @sa https://json.nlohmann.me/api/json_pointer/
3397 template<typename RefStringType>
3398 class json_pointer;
3399
3400 /*!
3401 @brief default specialization
3402 @sa https://json.nlohmann.me/api/json/
3403 */
3404 using json = basic_json<>;
3405
3406 /// @brief a minimal map-like container that preserves insertion order
3407 /// @sa https://json.nlohmann.me/api/ordered_map/
3408 template<class Key, class T, class IgnoredLess, class Allocator>
3409 struct ordered_map;
3410
3411 /// @brief specialization that maintains the insertion order of object keys
3412 /// @sa https://json.nlohmann.me/api/ordered_json/
3413 using ordered_json = basic_json<nlohmann::ordered_map>;
3414
3415 NLOHMANN_JSON_NAMESPACE_END
3416
3417#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3418
3419
3420NLOHMANN_JSON_NAMESPACE_BEGIN
3421/*!
3422@brief detail namespace with internal helper functions
3423
3424This namespace collects functions that should not be exposed,
3425implementations of some @ref basic_json methods, and meta-programming helpers.
3426
3427@since version 2.1.0
3428*/
3429namespace detail
3430{
3431
3432/////////////
3433// helpers //
3434/////////////
3435
3436// Note to maintainers:
3437//
3438// Every trait in this file expects a non CV-qualified type.
3439// The only exceptions are in the 'aliases for detected' section
3440// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
3441//
3442// In this case, T has to be properly CV-qualified to constraint the function arguments
3443// (e.g. to_json(BasicJsonType&, const T&))
3444
3445template<typename> struct is_basic_json : std::false_type {};
3446
3447NLOHMANN_BASIC_JSON_TPL_DECLARATION
3448struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3449
3450// used by exceptions create() member functions
3451// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
3452// false_type otherwise
3453template<typename BasicJsonContext>
3454struct is_basic_json_context :
3455 std::integral_constant < bool,
3456 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3457 || std::is_same<BasicJsonContext, std::nullptr_t>::value >
3458{};
3459
3460//////////////////////
3461// json_ref helpers //
3462//////////////////////
3463
3464template<typename>
3465class json_ref;
3466
3467template<typename>
3468struct is_json_ref : std::false_type {};
3469
3470template<typename T>
3471struct is_json_ref<json_ref<T>> : std::true_type {};
3472
3473//////////////////////////
3474// aliases for detected //
3475//////////////////////////
3476
3477template<typename T>
3478using mapped_type_t = typename T::mapped_type;
3479
3480template<typename T>
3481using key_type_t = typename T::key_type;
3482
3483template<typename T>
3484using value_type_t = typename T::value_type;
3485
3486template<typename T>
3487using difference_type_t = typename T::difference_type;
3488
3489template<typename T>
3490using pointer_t = typename T::pointer;
3491
3492template<typename T>
3493using reference_t = typename T::reference;
3494
3495template<typename T>
3496using iterator_category_t = typename T::iterator_category;
3497
3498template<typename T, typename... Args>
3499using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3500
3501template<typename T, typename... Args>
3502using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3503
3504template<typename T, typename U>
3505using get_template_function = decltype(std::declval<T>().template get<U>());
3506
3507// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3508template<typename BasicJsonType, typename T, typename = void>
3509struct has_from_json : std::false_type {};
3510
3511// trait checking if j.get<T> is valid
3512// use this trait instead of std::is_constructible or std::is_convertible,
3513// both rely on, or make use of implicit conversions, and thus fail when T
3514// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3515template <typename BasicJsonType, typename T>
3516struct is_getable
3517{
3518 static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
3519};
3520
3521template<typename BasicJsonType, typename T>
3522struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3523{
3524 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3525
3526 static constexpr bool value =
3527 is_detected_exact<void, from_json_function, serializer,
3528 const BasicJsonType&, T&>::value;
3529};
3530
3531// This trait checks if JSONSerializer<T>::from_json(json const&) exists
3532// this overload is used for non-default-constructible user-defined-types
3533template<typename BasicJsonType, typename T, typename = void>
3534struct has_non_default_from_json : std::false_type {};
3535
3536template<typename BasicJsonType, typename T>
3537struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3538{
3539 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3540
3541 static constexpr bool value =
3542 is_detected_exact<T, from_json_function, serializer,
3543 const BasicJsonType&>::value;
3544};
3545
3546// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3547// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3548template<typename BasicJsonType, typename T, typename = void>
3549struct has_to_json : std::false_type {};
3550
3551template<typename BasicJsonType, typename T>
3552struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3553{
3554 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3555
3556 static constexpr bool value =
3557 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3558 T>::value;
3559};
3560
3561template<typename T>
3562using detect_key_compare = typename T::key_compare;
3563
3564template<typename T>
3565struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3566
3567// obtains the actual object key comparator
3568template<typename BasicJsonType>
3569struct actual_object_comparator
3570{
3571 using object_t = typename BasicJsonType::object_t;
3572 using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3573 using type = typename std::conditional < has_key_compare<object_t>::value,
3574 typename object_t::key_compare, object_comparator_t>::type;
3575};
3576
3577template<typename BasicJsonType>
3578using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type;
3579
3580///////////////////
3581// is_ functions //
3582///////////////////
3583
3584// https://en.cppreference.com/w/cpp/types/conjunction
3585template<class...> struct conjunction : std::true_type { };
3586template<class B> struct conjunction<B> : B { };
3587template<class B, class... Bn>
3588struct conjunction<B, Bn...>
3589: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3590
3591// https://en.cppreference.com/w/cpp/types/negation
3592template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3593
3594// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3595// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3596// This causes compile errors in e.g. clang 3.5 or gcc 4.9.
3597template <typename T>
3598struct is_default_constructible : std::is_default_constructible<T> {};
3599
3600template <typename T1, typename T2>
3601struct is_default_constructible<std::pair<T1, T2>>
3602 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3603
3604template <typename T1, typename T2>
3605struct is_default_constructible<const std::pair<T1, T2>>
3606 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3607
3608template <typename... Ts>
3609struct is_default_constructible<std::tuple<Ts...>>
3610 : conjunction<is_default_constructible<Ts>...> {};
3611
3612template <typename... Ts>
3613struct is_default_constructible<const std::tuple<Ts...>>
3614 : conjunction<is_default_constructible<Ts>...> {};
3615
3616
3617template <typename T, typename... Args>
3618struct is_constructible : std::is_constructible<T, Args...> {};
3619
3620template <typename T1, typename T2>
3621struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3622
3623template <typename T1, typename T2>
3624struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3625
3626template <typename... Ts>
3627struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3628
3629template <typename... Ts>
3630struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3631
3632
3633template<typename T, typename = void>
3634struct is_iterator_traits : std::false_type {};
3635
3636template<typename T>
3637struct is_iterator_traits<iterator_traits<T>>
3638{
3639 private:
3640 using traits = iterator_traits<T>;
3641
3642 public:
3643 static constexpr auto value =
3644 is_detected<value_type_t, traits>::value &&
3645 is_detected<difference_type_t, traits>::value &&
3646 is_detected<pointer_t, traits>::value &&
3647 is_detected<iterator_category_t, traits>::value &&
3648 is_detected<reference_t, traits>::value;
3649};
3650
3651template<typename T>
3652struct is_range
3653{
3654 private:
3655 using t_ref = typename std::add_lvalue_reference<T>::type;
3656
3657 using iterator = detected_t<result_of_begin, t_ref>;
3658 using sentinel = detected_t<result_of_end, t_ref>;
3659
3660 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3661 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3662 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3663 static constexpr auto is_iterator_begin =
3664 is_iterator_traits<iterator_traits<iterator>>::value;
3665
3666 public:
3667 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3668};
3669
3670template<typename R>
3671using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3672
3673template<typename T>
3674using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
3675
3676// The following implementation of is_complete_type is taken from
3677// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3678// and is written by Xiang Fan who agreed to using it in this library.
3679
3680template<typename T, typename = void>
3681struct is_complete_type : std::false_type {};
3682
3683template<typename T>
3684struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3685
3686template<typename BasicJsonType, typename CompatibleObjectType,
3687 typename = void>
3688struct is_compatible_object_type_impl : std::false_type {};
3689
3690template<typename BasicJsonType, typename CompatibleObjectType>
3691struct is_compatible_object_type_impl <
3692 BasicJsonType, CompatibleObjectType,
3693 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3694 is_detected<key_type_t, CompatibleObjectType>::value >>
3695{
3696 using object_t = typename BasicJsonType::object_t;
3697
3698 // macOS's is_constructible does not play well with nonesuch...
3699 static constexpr bool value =
3700 is_constructible<typename object_t::key_type,
3701 typename CompatibleObjectType::key_type>::value &&
3702 is_constructible<typename object_t::mapped_type,
3703 typename CompatibleObjectType::mapped_type>::value;
3704};
3705
3706template<typename BasicJsonType, typename CompatibleObjectType>
3707struct is_compatible_object_type
3708 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3709
3710template<typename BasicJsonType, typename ConstructibleObjectType,
3711 typename = void>
3712struct is_constructible_object_type_impl : std::false_type {};
3713
3714template<typename BasicJsonType, typename ConstructibleObjectType>
3715struct is_constructible_object_type_impl <
3716 BasicJsonType, ConstructibleObjectType,
3717 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3718 is_detected<key_type_t, ConstructibleObjectType>::value >>
3719{
3720 using object_t = typename BasicJsonType::object_t;
3721
3722 static constexpr bool value =
3723 (is_default_constructible<ConstructibleObjectType>::value &&
3724 (std::is_move_assignable<ConstructibleObjectType>::value ||
3725 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3726 (is_constructible<typename ConstructibleObjectType::key_type,
3727 typename object_t::key_type>::value &&
3728 std::is_same <
3729 typename object_t::mapped_type,
3730 typename ConstructibleObjectType::mapped_type >::value)) ||
3731 (has_from_json<BasicJsonType,
3732 typename ConstructibleObjectType::mapped_type>::value ||
3733 has_non_default_from_json <
3734 BasicJsonType,
3735 typename ConstructibleObjectType::mapped_type >::value);
3736};
3737
3738template<typename BasicJsonType, typename ConstructibleObjectType>
3739struct is_constructible_object_type
3740 : is_constructible_object_type_impl<BasicJsonType,
3741 ConstructibleObjectType> {};
3742
3743template<typename BasicJsonType, typename CompatibleStringType>
3744struct is_compatible_string_type
3745{
3746 static constexpr auto value =
3747 is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
3748};
3749
3750template<typename BasicJsonType, typename ConstructibleStringType>
3751struct is_constructible_string_type
3752{
3753 // launder type through decltype() to fix compilation failure on ICPC
3754#ifdef __INTEL_COMPILER
3755 using laundered_type = decltype(std::declval<ConstructibleStringType>());
3756#else
3757 using laundered_type = ConstructibleStringType;
3758#endif
3759
3760 static constexpr auto value =
3761 conjunction <
3762 is_constructible<laundered_type, typename BasicJsonType::string_t>,
3763 is_detected_exact<typename BasicJsonType::string_t::value_type,
3764 value_type_t, laundered_type >>::value;
3765};
3766
3767template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3768struct is_compatible_array_type_impl : std::false_type {};
3769
3770template<typename BasicJsonType, typename CompatibleArrayType>
3771struct is_compatible_array_type_impl <
3772 BasicJsonType, CompatibleArrayType,
3773 enable_if_t <
3774 is_detected<iterator_t, CompatibleArrayType>::value&&
3775 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
3776// special case for types like std::filesystem::path whose iterator's value_type are themselves
3777// c.f. https://github.com/nlohmann/json/pull/3073
3778 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
3779{
3780 static constexpr bool value =
3781 is_constructible<BasicJsonType,
3782 range_value_t<CompatibleArrayType>>::value;
3783};
3784
3785template<typename BasicJsonType, typename CompatibleArrayType>
3786struct is_compatible_array_type
3787 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3788
3789template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3790struct is_constructible_array_type_impl : std::false_type {};
3791
3792template<typename BasicJsonType, typename ConstructibleArrayType>
3793struct is_constructible_array_type_impl <
3794 BasicJsonType, ConstructibleArrayType,
3795 enable_if_t<std::is_same<ConstructibleArrayType,
3796 typename BasicJsonType::value_type>::value >>
3797 : std::true_type {};
3798
3799template<typename BasicJsonType, typename ConstructibleArrayType>
3800struct is_constructible_array_type_impl <
3801 BasicJsonType, ConstructibleArrayType,
3802 enable_if_t < !std::is_same<ConstructibleArrayType,
3803 typename BasicJsonType::value_type>::value&&
3804 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
3805 is_default_constructible<ConstructibleArrayType>::value&&
3806(std::is_move_assignable<ConstructibleArrayType>::value ||
3807 std::is_copy_assignable<ConstructibleArrayType>::value)&&
3808is_detected<iterator_t, ConstructibleArrayType>::value&&
3809is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
3810is_detected<range_value_t, ConstructibleArrayType>::value&&
3811// special case for types like std::filesystem::path whose iterator's value_type are themselves
3812// c.f. https://github.com/nlohmann/json/pull/3073
3813!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
3814 is_complete_type <
3815 detected_t<range_value_t, ConstructibleArrayType >>::value >>
3816{
3817 using value_type = range_value_t<ConstructibleArrayType>;
3818
3819 static constexpr bool value =
3820 std::is_same<value_type,
3821 typename BasicJsonType::array_t::value_type>::value ||
3822 has_from_json<BasicJsonType,
3823 value_type>::value ||
3824 has_non_default_from_json <
3825 BasicJsonType,
3826 value_type >::value;
3827};
3828
3829template<typename BasicJsonType, typename ConstructibleArrayType>
3830struct is_constructible_array_type
3831 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
3832
3833template<typename RealIntegerType, typename CompatibleNumberIntegerType,
3834 typename = void>
3835struct is_compatible_integer_type_impl : std::false_type {};
3836
3837template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3838struct is_compatible_integer_type_impl <
3839 RealIntegerType, CompatibleNumberIntegerType,
3840 enable_if_t < std::is_integral<RealIntegerType>::value&&
3841 std::is_integral<CompatibleNumberIntegerType>::value&&
3842 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
3843{
3844 // is there an assert somewhere on overflows?
3845 using RealLimits = std::numeric_limits<RealIntegerType>;
3846 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3847
3848 static constexpr auto value =
3849 is_constructible<RealIntegerType,
3850 CompatibleNumberIntegerType>::value &&
3851 CompatibleLimits::is_integer &&
3852 RealLimits::is_signed == CompatibleLimits::is_signed;
3853};
3854
3855template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3856struct is_compatible_integer_type
3857 : is_compatible_integer_type_impl<RealIntegerType,
3858 CompatibleNumberIntegerType> {};
3859
3860template<typename BasicJsonType, typename CompatibleType, typename = void>
3861struct is_compatible_type_impl: std::false_type {};
3862
3863template<typename BasicJsonType, typename CompatibleType>
3864struct is_compatible_type_impl <
3865 BasicJsonType, CompatibleType,
3866 enable_if_t<is_complete_type<CompatibleType>::value >>
3867{
3868 static constexpr bool value =
3869 has_to_json<BasicJsonType, CompatibleType>::value;
3870};
3871
3872template<typename BasicJsonType, typename CompatibleType>
3873struct is_compatible_type
3874 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
3875
3876template<typename T1, typename T2>
3877struct is_constructible_tuple : std::false_type {};
3878
3879template<typename T1, typename... Args>
3880struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
3881
3882template<typename BasicJsonType, typename T>
3883struct is_json_iterator_of : std::false_type {};
3884
3885template<typename BasicJsonType>
3886struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
3887
3888template<typename BasicJsonType>
3889struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
3890{};
3891
3892// checks if a given type T is a template specialization of Primary
3893template<template <typename...> class Primary, typename T>
3894struct is_specialization_of : std::false_type {};
3895
3896template<template <typename...> class Primary, typename... Args>
3897struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
3898
3899template<typename T>
3900using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>;
3901
3902// checks if A and B are comparable using Compare functor
3903template<typename Compare, typename A, typename B, typename = void>
3904struct is_comparable : std::false_type {};
3905
3906template<typename Compare, typename A, typename B>
3907struct is_comparable<Compare, A, B, void_t<
3908decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
3909decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
3910>> : std::true_type {};
3911
3912template<typename T>
3913using detect_is_transparent = typename T::is_transparent;
3914
3915// type trait to check if KeyType can be used as object key (without a BasicJsonType)
3916// see is_usable_as_basic_json_key_type below
3917template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
3918 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
3919using is_usable_as_key_type = typename std::conditional <
3920 is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value
3921 && !(ExcludeObjectKeyType && std::is_same<KeyType,
3922 ObjectKeyType>::value)
3923 && (!RequireTransparentComparator
3924 || is_detected <detect_is_transparent, Comparator>::value)
3925 && !is_json_pointer<KeyType>::value,
3926 std::true_type,
3927 std::false_type >::type;
3928
3929// type trait to check if KeyType can be used as object key
3930// true if:
3931// - KeyType is comparable with BasicJsonType::object_t::key_type
3932// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
3933// - the comparator is transparent or RequireTransparentComparator is false
3934// - KeyType is not a JSON iterator or json_pointer
3935template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
3936 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
3937using is_usable_as_basic_json_key_type = typename std::conditional <
3938 is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
3939 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
3940 RequireTransparentComparator, ExcludeObjectKeyType>::value
3941 && !is_json_iterator_of<BasicJsonType, KeyType>::value,
3942 std::true_type,
3943 std::false_type >::type;
3944
3945template<typename ObjectType, typename KeyType>
3946using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
3947
3948// type trait to check if object_t has an erase() member functions accepting KeyType
3949template<typename BasicJsonType, typename KeyType>
3950using has_erase_with_key_type = typename std::conditional <
3951 is_detected <
3952 detect_erase_with_key_type,
3953 typename BasicJsonType::object_t, KeyType >::value,
3954 std::true_type,
3955 std::false_type >::type;
3956
3957// a naive helper to check if a type is an ordered_map (exploits the fact that
3958// ordered_map inherits capacity() from std::vector)
3959template <typename T>
3960struct is_ordered_map
3961{
3962 using one = char;
3963
3964 struct two
3965 {
3966 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
3967 };
3968
3969 template <typename C> static one test( decltype(&C::capacity) ) ;
3970 template <typename C> static two test(...);
3971
3972 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
3973};
3974
3975// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
3976template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
3977T conditional_static_cast(U value)
3978{
3979 return static_cast<T>(value);
3980}
3981
3982template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
3983T conditional_static_cast(U value)
3984{
3985 return value;
3986}
3987
3988template<typename... Types>
3989using all_integral = conjunction<std::is_integral<Types>...>;
3990
3991template<typename... Types>
3992using all_signed = conjunction<std::is_signed<Types>...>;
3993
3994template<typename... Types>
3995using all_unsigned = conjunction<std::is_unsigned<Types>...>;
3996
3997// there's a disjunction trait in another PR; replace when merged
3998template<typename... Types>
3999using same_sign = std::integral_constant < bool,
4000 all_signed<Types...>::value || all_unsigned<Types...>::value >;
4001
4002template<typename OfType, typename T>
4003using never_out_of_range = std::integral_constant < bool,
4004 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
4005 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
4006
4007template<typename OfType, typename T,
4008 bool OfTypeSigned = std::is_signed<OfType>::value,
4009 bool TSigned = std::is_signed<T>::value>
4010struct value_in_range_of_impl2;
4011
4012template<typename OfType, typename T>
4013struct value_in_range_of_impl2<OfType, T, false, false>
4014{
4015 static constexpr bool test(T val)
4016 {
4017 using CommonType = typename std::common_type<OfType, T>::type;
4018 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4019 }
4020};
4021
4022template<typename OfType, typename T>
4023struct value_in_range_of_impl2<OfType, T, true, false>
4024{
4025 static constexpr bool test(T val)
4026 {
4027 using CommonType = typename std::common_type<OfType, T>::type;
4028 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4029 }
4030};
4031
4032template<typename OfType, typename T>
4033struct value_in_range_of_impl2<OfType, T, false, true>
4034{
4035 static constexpr bool test(T val)
4036 {
4037 using CommonType = typename std::common_type<OfType, T>::type;
4038 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4039 }
4040};
4041
4042
4043template<typename OfType, typename T>
4044struct value_in_range_of_impl2<OfType, T, true, true>
4045{
4046 static constexpr bool test(T val)
4047 {
4048 using CommonType = typename std::common_type<OfType, T>::type;
4049 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
4050 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4051 }
4052};
4053
4054template<typename OfType, typename T,
4055 bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4056 typename = detail::enable_if_t<all_integral<OfType, T>::value>>
4057struct value_in_range_of_impl1;
4058
4059template<typename OfType, typename T>
4060struct value_in_range_of_impl1<OfType, T, false>
4061{
4062 static constexpr bool test(T val)
4063 {
4064 return value_in_range_of_impl2<OfType, T>::test(val);
4065 }
4066};
4067
4068template<typename OfType, typename T>
4069struct value_in_range_of_impl1<OfType, T, true>
4070{
4071 static constexpr bool test(T /*val*/)
4072 {
4073 return true;
4074 }
4075};
4076
4077template<typename OfType, typename T>
4078inline constexpr bool value_in_range_of(T val)
4079{
4080 return value_in_range_of_impl1<OfType, T>::test(val);
4081}
4082
4083template<bool Value>
4084using bool_constant = std::integral_constant<bool, Value>;
4085
4086///////////////////////////////////////////////////////////////////////////////
4087// is_c_string
4088///////////////////////////////////////////////////////////////////////////////
4089
4090namespace impl
4091{
4092
4093template<typename T>
4094inline constexpr bool is_c_string()
4095{
4096 using TUnExt = typename std::remove_extent<T>::type;
4097 using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4098 using TUnPtr = typename std::remove_pointer<T>::type;
4099 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4100 return
4101 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4102 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4103}
4104
4105} // namespace impl
4106
4107// checks whether T is a [cv] char */[cv] char[] C string
4108template<typename T>
4109struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4110
4111template<typename T>
4112using is_c_string_uncvref = is_c_string<uncvref_t<T>>;
4113
4114///////////////////////////////////////////////////////////////////////////////
4115// is_transparent
4116///////////////////////////////////////////////////////////////////////////////
4117
4118namespace impl
4119{
4120
4121template<typename T>
4122inline constexpr bool is_transparent()
4123{
4124 return is_detected<detect_is_transparent, T>::value;
4125}
4126
4127} // namespace impl
4128
4129// checks whether T has a member named is_transparent
4130template<typename T>
4131struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4132
4133///////////////////////////////////////////////////////////////////////////////
4134
4135} // namespace detail
4136NLOHMANN_JSON_NAMESPACE_END
4137
4138// #include <nlohmann/detail/string_concat.hpp>
4139// __ _____ _____ _____
4140// __| | __| | | | JSON for Modern C++
4141// | | |__ | | | | | | version 3.11.2
4142// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4143//
4144// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
4145// SPDX-License-Identifier: MIT
4146
4147
4148
4149#include <cstring> // strlen
4150#include <string> // string
4151#include <utility> // forward
4152
4153// #include <nlohmann/detail/meta/cpp_future.hpp>
4154
4155// #include <nlohmann/detail/meta/detected.hpp>
4156
4157
4158NLOHMANN_JSON_NAMESPACE_BEGIN
4159namespace detail
4160{
4161
4162inline std::size_t concat_length()
4163{
4164 return 0;
4165}
4166
4167template<typename... Args>
4168inline std::size_t concat_length(const char* cstr, Args&& ... rest);
4169
4170template<typename StringType, typename... Args>
4171inline std::size_t concat_length(const StringType& str, Args&& ... rest);
4172
4173template<typename... Args>
4174inline std::size_t concat_length(const char /*c*/, Args&& ... rest)
4175{
4176 return 1 + concat_length(std::forward<Args>(rest)...);
4177}
4178
4179template<typename... Args>
4180inline std::size_t concat_length(const char* cstr, Args&& ... rest)
4181{
4182 // cppcheck-suppress ignoredReturnValue
4183 return ::strlen(cstr) + concat_length(std::forward<Args>(rest)...);
4184}
4185
4186template<typename StringType, typename... Args>
4187inline std::size_t concat_length(const StringType& str, Args&& ... rest)
4188{
4189 return str.size() + concat_length(std::forward<Args>(rest)...);
4190}
4191
4192template<typename OutStringType>
4193inline void concat_into(OutStringType& /*out*/)
4194{}
4195
4196template<typename StringType, typename Arg>
4197using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
4198
4199template<typename StringType, typename Arg>
4200using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
4201
4202template<typename StringType, typename Arg>
4203using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
4204
4205template<typename StringType, typename Arg>
4206using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
4207
4208template<typename StringType, typename Arg>
4209using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4210
4211template<typename StringType, typename Arg>
4212using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>;
4213
4214template<typename StringType, typename Arg>
4215using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4216
4217template<typename StringType, typename Arg>
4218using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
4219
4220template < typename OutStringType, typename Arg, typename... Args,
4221 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4222 && detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 >
4223inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
4224
4225template < typename OutStringType, typename Arg, typename... Args,
4226 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4227 && !detect_string_can_append_op<OutStringType, Arg>::value
4228 && detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 >
4229inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4230
4231template < typename OutStringType, typename Arg, typename... Args,
4232 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4233 && !detect_string_can_append_op<OutStringType, Arg>::value
4234 && !detect_string_can_append_iter<OutStringType, Arg>::value
4235 && detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 >
4236inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4237
4238template<typename OutStringType, typename Arg, typename... Args,
4239 enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
4240inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
4241{
4242 out.append(std::forward<Arg>(arg));
4243 concat_into(out, std::forward<Args>(rest)...);
4244}
4245
4246template < typename OutStringType, typename Arg, typename... Args,
4247 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4248 && detect_string_can_append_op<OutStringType, Arg>::value, int > >
4249inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4250{
4251 out += std::forward<Arg>(arg);
4252 concat_into(out, std::forward<Args>(rest)...);
4253}
4254
4255template < typename OutStringType, typename Arg, typename... Args,
4256 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4257 && !detect_string_can_append_op<OutStringType, Arg>::value
4258 && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
4259inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4260{
4261 out.append(arg.begin(), arg.end());
4262 concat_into(out, std::forward<Args>(rest)...);
4263}
4264
4265template < typename OutStringType, typename Arg, typename... Args,
4266 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4267 && !detect_string_can_append_op<OutStringType, Arg>::value
4268 && !detect_string_can_append_iter<OutStringType, Arg>::value
4269 && detect_string_can_append_data<OutStringType, Arg>::value, int > >
4270inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4271{
4272 out.append(arg.data(), arg.size());
4273 concat_into(out, std::forward<Args>(rest)...);
4274}
4275
4276template<typename OutStringType = std::string, typename... Args>
4277inline OutStringType concat(Args && ... args)
4278{
4279 OutStringType str;
4280 str.reserve(concat_length(std::forward<Args>(args)...));
4281 concat_into(str, std::forward<Args>(args)...);
4282 return str;
4283}
4284
4285} // namespace detail
4286NLOHMANN_JSON_NAMESPACE_END
4287
4288
4289
4290NLOHMANN_JSON_NAMESPACE_BEGIN
4291namespace detail
4292{
4293
4294////////////////
4295// exceptions //
4296////////////////
4297
4298/// @brief general exception of the @ref basic_json class
4299/// @sa https://json.nlohmann.me/api/basic_json/exception/
4300class exception : public std::exception
4301{
4302 public:
4303 /// returns the explanatory string
4304 const char* what() const noexcept override
4305 {
4306 return m.what();
4307 }
4308
4309 /// the id of the exception
4310 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4311
4312 protected:
4313 JSON_HEDLEY_NON_NULL(3)
4314 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4315
4316 static std::string name(const std::string& ename, int id_)
4317 {
4318 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4319 }
4320
4321 static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4322 {
4323 return "";
4324 }
4325
4326 template<typename BasicJsonType>
4327 static std::string diagnostics(const BasicJsonType* leaf_element)
4328 {
4329#if JSON_DIAGNOSTICS
4330 std::vector<std::string> tokens;
4331 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4332 {
4333 switch (current->m_parent->type())
4334 {
4335 case value_t::array:
4336 {
4337 for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i)
4338 {
4339 if (&current->m_parent->m_value.array->operator[](i) == current)
4340 {
4341 tokens.emplace_back(std::to_string(i));
4342 break;
4343 }
4344 }
4345 break;
4346 }
4347
4348 case value_t::object:
4349 {
4350 for (const auto& element : *current->m_parent->m_value.object)
4351 {
4352 if (&element.second == current)
4353 {
4354 tokens.emplace_back(element.first.c_str());
4355 break;
4356 }
4357 }
4358 break;
4359 }
4360
4361 case value_t::null: // LCOV_EXCL_LINE
4362 case value_t::string: // LCOV_EXCL_LINE
4363 case value_t::boolean: // LCOV_EXCL_LINE
4364 case value_t::number_integer: // LCOV_EXCL_LINE
4365 case value_t::number_unsigned: // LCOV_EXCL_LINE
4366 case value_t::number_float: // LCOV_EXCL_LINE
4367 case value_t::binary: // LCOV_EXCL_LINE
4368 case value_t::discarded: // LCOV_EXCL_LINE
4369 default: // LCOV_EXCL_LINE
4370 break; // LCOV_EXCL_LINE
4371 }
4372 }
4373
4374 if (tokens.empty())
4375 {
4376 return "";
4377 }
4378
4379 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4380 [](const std::string & a, const std::string & b)
4381 {
4382 return concat(a, '/', detail::escape(b));
4383 });
4384 return concat('(', str, ") ");
4385#else
4386 static_cast<void>(leaf_element);
4387 return "";
4388#endif
4389 }
4390
4391 private:
4392 /// an exception object as storage for error messages
4393 std::runtime_error m;
4394};
4395
4396/// @brief exception indicating a parse error
4397/// @sa https://json.nlohmann.me/api/basic_json/parse_error/
4398class parse_error : public exception
4399{
4400 public:
4401 /*!
4402 @brief create a parse error exception
4403 @param[in] id_ the id of the exception
4404 @param[in] pos the position where the error occurred (or with
4405 chars_read_total=0 if the position cannot be
4406 determined)
4407 @param[in] what_arg the explanatory string
4408 @return parse_error object
4409 */
4410 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4411 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4412 {
4413 std::string w = concat(exception::name("parse_error", id_), "parse error",
4414 position_string(pos), ": ", exception::diagnostics(context), what_arg);
4415 return {id_, pos.chars_read_total, w.c_str()};
4416 }
4417
4418 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4419 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4420 {
4421 std::string w = concat(exception::name("parse_error", id_), "parse error",
4422 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4423 ": ", exception::diagnostics(context), what_arg);
4424 return {id_, byte_, w.c_str()};
4425 }
4426
4427 /*!
4428 @brief byte index of the parse error
4429
4430 The byte index of the last read character in the input file.
4431
4432 @note For an input with n bytes, 1 is the index of the first character and
4433 n+1 is the index of the terminating null byte or the end of file.
4434 This also holds true when reading a byte vector (CBOR or MessagePack).
4435 */
4436 const std::size_t byte;
4437
4438 private:
4439 parse_error(int id_, std::size_t byte_, const char* what_arg)
4440 : exception(id_, what_arg), byte(byte_) {}
4441
4442 static std::string position_string(const position_t& pos)
4443 {
4444 return concat(" at line ", std::to_string(pos.lines_read + 1),
4445 ", column ", std::to_string(pos.chars_read_current_line));
4446 }
4447};
4448
4449/// @brief exception indicating errors with iterators
4450/// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/
4451class invalid_iterator : public exception
4452{
4453 public:
4454 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4455 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4456 {
4457 std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4458 return {id_, w.c_str()};
4459 }
4460
4461 private:
4462 JSON_HEDLEY_NON_NULL(3)
4463 invalid_iterator(int id_, const char* what_arg)
4464 : exception(id_, what_arg) {}
4465};
4466
4467/// @brief exception indicating executing a member function with a wrong type
4468/// @sa https://json.nlohmann.me/api/basic_json/type_error/
4469class type_error : public exception
4470{
4471 public:
4472 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4473 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4474 {
4475 std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4476 return {id_, w.c_str()};
4477 }
4478
4479 private:
4480 JSON_HEDLEY_NON_NULL(3)
4481 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4482};
4483
4484/// @brief exception indicating access out of the defined range
4485/// @sa https://json.nlohmann.me/api/basic_json/out_of_range/
4486class out_of_range : public exception
4487{
4488 public:
4489 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4490 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4491 {
4492 std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4493 return {id_, w.c_str()};
4494 }
4495
4496 private:
4497 JSON_HEDLEY_NON_NULL(3)
4498 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4499};
4500
4501/// @brief exception indicating other library errors
4502/// @sa https://json.nlohmann.me/api/basic_json/other_error/
4503class other_error : public exception
4504{
4505 public:
4506 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4507 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4508 {
4509 std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4510 return {id_, w.c_str()};
4511 }
4512
4513 private:
4514 JSON_HEDLEY_NON_NULL(3)
4515 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4516};
4517
4518} // namespace detail
4519NLOHMANN_JSON_NAMESPACE_END
4520
4521// #include <nlohmann/detail/macro_scope.hpp>
4522
4523// #include <nlohmann/detail/meta/cpp_future.hpp>
4524
4525// #include <nlohmann/detail/meta/identity_tag.hpp>
4526// __ _____ _____ _____
4527// __| | __| | | | JSON for Modern C++
4528// | | |__ | | | | | | version 3.11.2
4529// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4530//
4531// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
4532// SPDX-License-Identifier: MIT
4533
4534
4535
4536// #include <nlohmann/detail/abi_macros.hpp>
4537
4538
4539NLOHMANN_JSON_NAMESPACE_BEGIN
4540namespace detail
4541{
4542
4543// dispatching helper struct
4544template <class T> struct identity_tag {};
4545
4546} // namespace detail
4547NLOHMANN_JSON_NAMESPACE_END
4548
4549// #include <nlohmann/detail/meta/std_fs.hpp>
4550// __ _____ _____ _____
4551// __| | __| | | | JSON for Modern C++
4552// | | |__ | | | | | | version 3.11.2
4553// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4554//
4555// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
4556// SPDX-License-Identifier: MIT
4557
4558
4559
4560// #include <nlohmann/detail/macro_scope.hpp>
4561
4562
4563#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4564#include <experimental/filesystem>
4565NLOHMANN_JSON_NAMESPACE_BEGIN
4566namespace detail
4567{
4568namespace std_fs = std::experimental::filesystem;
4569} // namespace detail
4570NLOHMANN_JSON_NAMESPACE_END
4571#elif JSON_HAS_FILESYSTEM
4572#include <filesystem>
4573NLOHMANN_JSON_NAMESPACE_BEGIN
4574namespace detail
4575{
4576namespace std_fs = std::filesystem;
4577} // namespace detail
4578NLOHMANN_JSON_NAMESPACE_END
4579#endif
4580
4581// #include <nlohmann/detail/meta/type_traits.hpp>
4582
4583// #include <nlohmann/detail/string_concat.hpp>
4584
4585// #include <nlohmann/detail/value_t.hpp>
4586
4587
4588NLOHMANN_JSON_NAMESPACE_BEGIN
4589namespace detail
4590{
4591
4592template<typename BasicJsonType>
4593inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4594{
4595 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4596 {
4597 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4598 }
4599 n = nullptr;
4600}
4601
4602// overloads for basic_json template parameters
4603template < typename BasicJsonType, typename ArithmeticType,
4604 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4605 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4606 int > = 0 >
4607void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4608{
4609 switch (static_cast<value_t>(j))
4610 {
4611 case value_t::number_unsigned:
4612 {
4613 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4614 break;
4615 }
4616 case value_t::number_integer:
4617 {
4618 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4619 break;
4620 }
4621 case value_t::number_float:
4622 {
4623 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4624 break;
4625 }
4626
4627 case value_t::null:
4628 case value_t::object:
4629 case value_t::array:
4630 case value_t::string:
4631 case value_t::boolean:
4632 case value_t::binary:
4633 case value_t::discarded:
4634 default:
4635 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4636 }
4637}
4638
4639template<typename BasicJsonType>
4640inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
4641{
4642 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4643 {
4644 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4645 }
4646 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4647}
4648
4649template<typename BasicJsonType>
4650inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
4651{
4652 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4653 {
4654 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4655 }
4656 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4657}
4658
4659template <
4660 typename BasicJsonType, typename StringType,
4661 enable_if_t <
4662 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4663 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
4664 && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4665 && !is_json_ref<StringType>::value, int > = 0 >
4666inline void from_json(const BasicJsonType& j, StringType& s)
4667{
4668 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4669 {
4670 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4671 }
4672
4673 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4674}
4675
4676template<typename BasicJsonType>
4677inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
4678{
4679 get_arithmetic_value(j, val);
4680}
4681
4682template<typename BasicJsonType>
4683inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
4684{
4685 get_arithmetic_value(j, val);
4686}
4687
4688template<typename BasicJsonType>
4689inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
4690{
4691 get_arithmetic_value(j, val);
4692}
4693
4694#if !JSON_DISABLE_ENUM_SERIALIZATION
4695template<typename BasicJsonType, typename EnumType,
4696 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4697inline void from_json(const BasicJsonType& j, EnumType& e)
4698{
4699 typename std::underlying_type<EnumType>::type val;
4700 get_arithmetic_value(j, val);
4701 e = static_cast<EnumType>(val);
4702}
4703#endif // JSON_DISABLE_ENUM_SERIALIZATION
4704
4705// forward_list doesn't have an insert method
4706template<typename BasicJsonType, typename T, typename Allocator,
4707 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4708inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
4709{
4710 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4711 {
4712 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4713 }
4714 l.clear();
4715 std::transform(j.rbegin(), j.rend(),
4716 std::front_inserter(l), [](const BasicJsonType & i)
4717 {
4718 return i.template get<T>();
4719 });
4720}
4721
4722// valarray doesn't have an insert method
4723template<typename BasicJsonType, typename T,
4724 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4725inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
4726{
4727 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4728 {
4729 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4730 }
4731 l.resize(j.size());
4732 std::transform(j.begin(), j.end(), std::begin(l),
4733 [](const BasicJsonType & elem)
4734 {
4735 return elem.template get<T>();
4736 });
4737}
4738
4739template<typename BasicJsonType, typename T, std::size_t N>
4740auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4741-> decltype(j.template get<T>(), void())
4742{
4743 for (std::size_t i = 0; i < N; ++i)
4744 {
4745 arr[i] = j.at(i).template get<T>();
4746 }
4747}
4748
4749template<typename BasicJsonType>
4750inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
4751{
4752 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
4753}
4754
4755template<typename BasicJsonType, typename T, std::size_t N>
4756auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
4757 priority_tag<2> /*unused*/)
4758-> decltype(j.template get<T>(), void())
4759{
4760 for (std::size_t i = 0; i < N; ++i)
4761 {
4762 arr[i] = j.at(i).template get<T>();
4763 }
4764}
4765
4766template<typename BasicJsonType, typename ConstructibleArrayType,
4767 enable_if_t<
4768 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4769 int> = 0>
4770auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
4771-> decltype(
4772 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
4773 j.template get<typename ConstructibleArrayType::value_type>(),
4774 void())
4775{
4776 using std::end;
4777
4778 ConstructibleArrayType ret;
4779 ret.reserve(j.size());
4780 std::transform(j.begin(), j.end(),
4781 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
4782 {
4783 // get<BasicJsonType>() returns *this, this won't call a from_json
4784 // method when value_type is BasicJsonType
4785 return i.template get<typename ConstructibleArrayType::value_type>();
4786 });
4787 arr = std::move(ret);
4788}
4789
4790template<typename BasicJsonType, typename ConstructibleArrayType,
4791 enable_if_t<
4792 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4793 int> = 0>
4794inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
4795 priority_tag<0> /*unused*/)
4796{
4797 using std::end;
4798
4799 ConstructibleArrayType ret;
4800 std::transform(
4801 j.begin(), j.end(), std::inserter(ret, end(ret)),
4802 [](const BasicJsonType & i)
4803 {
4804 // get<BasicJsonType>() returns *this, this won't call a from_json
4805 // method when value_type is BasicJsonType
4806 return i.template get<typename ConstructibleArrayType::value_type>();
4807 });
4808 arr = std::move(ret);
4809}
4810
4811template < typename BasicJsonType, typename ConstructibleArrayType,
4812 enable_if_t <
4813 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
4814 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
4815 !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
4816 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
4817 !is_basic_json<ConstructibleArrayType>::value,
4818 int > = 0 >
4819auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
4820-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
4821j.template get<typename ConstructibleArrayType::value_type>(),
4822void())
4823{
4824 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4825 {
4826 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4827 }
4828
4829 from_json_array_impl(j, arr, priority_tag<3> {});
4830}
4831
4832template < typename BasicJsonType, typename T, std::size_t... Idx >
4833std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
4834 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
4835{
4836 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
4837}
4838
4839template < typename BasicJsonType, typename T, std::size_t N >
4840auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
4841-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
4842{
4843 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4844 {
4845 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4846 }
4847
4848 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
4849}
4850
4851template<typename BasicJsonType>
4852inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
4853{
4854 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
4855 {
4856 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
4857 }
4858
4859 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
4860}
4861
4862template<typename BasicJsonType, typename ConstructibleObjectType,
4863 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
4864inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
4865{
4866 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
4867 {
4868 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
4869 }
4870
4871 ConstructibleObjectType ret;
4872 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
4873 using value_type = typename ConstructibleObjectType::value_type;
4874 std::transform(
4875 inner_object->begin(), inner_object->end(),
4876 std::inserter(ret, ret.begin()),
4877 [](typename BasicJsonType::object_t::value_type const & p)
4878 {
4879 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
4880 });
4881 obj = std::move(ret);
4882}
4883
4884// overload for arithmetic types, not chosen for basic_json template arguments
4885// (BooleanType, etc..); note: Is it really necessary to provide explicit
4886// overloads for boolean_t etc. in case of a custom BooleanType which is not
4887// an arithmetic type?
4888template < typename BasicJsonType, typename ArithmeticType,
4889 enable_if_t <
4890 std::is_arithmetic<ArithmeticType>::value&&
4891 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
4892 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
4893 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
4894 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4895 int > = 0 >
4896inline void from_json(const BasicJsonType& j, ArithmeticType& val)
4897{
4898 switch (static_cast<value_t>(j))
4899 {
4900 case value_t::number_unsigned:
4901 {
4902 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4903 break;
4904 }
4905 case value_t::number_integer:
4906 {
4907 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4908 break;
4909 }
4910 case value_t::number_float:
4911 {
4912 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4913 break;
4914 }
4915 case value_t::boolean:
4916 {
4917 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
4918 break;
4919 }
4920
4921 case value_t::null:
4922 case value_t::object:
4923 case value_t::array:
4924 case value_t::string:
4925 case value_t::binary:
4926 case value_t::discarded:
4927 default:
4928 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4929 }
4930}
4931
4932template<typename BasicJsonType, typename... Args, std::size_t... Idx>
4933std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
4934{
4935 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
4936}
4937
4938template < typename BasicJsonType, class A1, class A2 >
4939std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
4940{
4941 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
4942 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
4943}
4944
4945template<typename BasicJsonType, typename A1, typename A2>
4946inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
4947{
4948 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
4949}
4950
4951template<typename BasicJsonType, typename... Args>
4952std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
4953{
4954 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
4955}
4956
4957template<typename BasicJsonType, typename... Args>
4958inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
4959{
4960 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
4961}
4962
4963template<typename BasicJsonType, typename TupleRelated>
4964auto from_json(BasicJsonType&& j, TupleRelated&& t)
4965-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
4966{
4967 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4968 {
4969 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4970 }
4971
4972 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
4973}
4974
4975template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
4976 typename = enable_if_t < !std::is_constructible <
4977 typename BasicJsonType::string_t, Key >::value >>
4978inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
4979{
4980 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4981 {
4982 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4983 }
4984 m.clear();
4985 for (const auto& p : j)
4986 {
4987 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
4988 {
4989 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
4990 }
4991 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
4992 }
4993}
4994
4995template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
4996 typename = enable_if_t < !std::is_constructible <
4997 typename BasicJsonType::string_t, Key >::value >>
4998inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
4999{
5000 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5001 {
5002 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5003 }
5004 m.clear();
5005 for (const auto& p : j)
5006 {
5007 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5008 {
5009 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5010 }
5011 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5012 }
5013}
5014
5015#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5016template<typename BasicJsonType>
5017inline void from_json(const BasicJsonType& j, std_fs::path& p)
5018{
5019 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5020 {
5021 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5022 }
5023 p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5024}
5025#endif
5026
5027struct from_json_fn
5028{
5029 template<typename BasicJsonType, typename T>
5030 auto operator()(const BasicJsonType& j, T&& val) const
5031 noexcept(noexcept(from_json(j, std::forward<T>(val))))
5032 -> decltype(from_json(j, std::forward<T>(val)))
5033 {
5034 return from_json(j, std::forward<T>(val));
5035 }
5036};
5037
5038} // namespace detail
5039
5040#ifndef JSON_HAS_CPP_17
5041/// namespace to hold default `from_json` function
5042/// to see why this is required:
5043/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
5044namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5045{
5046#endif
5047JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5048 detail::static_const<detail::from_json_fn>::value;
5049#ifndef JSON_HAS_CPP_17
5050} // namespace
5051#endif
5052
5053NLOHMANN_JSON_NAMESPACE_END
5054
5055// #include <nlohmann/detail/conversions/to_json.hpp>
5056// __ _____ _____ _____
5057// __| | __| | | | JSON for Modern C++
5058// | | |__ | | | | | | version 3.11.2
5059// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5060//
5061// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
5062// SPDX-License-Identifier: MIT
5063
5064
5065
5066#include <algorithm> // copy
5067#include <iterator> // begin, end
5068#include <string> // string
5069#include <tuple> // tuple, get
5070#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5071#include <utility> // move, forward, declval, pair
5072#include <valarray> // valarray
5073#include <vector> // vector
5074
5075// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5076// __ _____ _____ _____
5077// __| | __| | | | JSON for Modern C++
5078// | | |__ | | | | | | version 3.11.2
5079// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5080//
5081// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
5082// SPDX-License-Identifier: MIT
5083
5084
5085
5086#include <cstddef> // size_t
5087#include <iterator> // input_iterator_tag
5088#include <string> // string, to_string
5089#include <tuple> // tuple_size, get, tuple_element
5090#include <utility> // move
5091
5092#if JSON_HAS_RANGES
5093 #include <ranges> // enable_borrowed_range
5094#endif
5095
5096// #include <nlohmann/detail/abi_macros.hpp>
5097
5098// #include <nlohmann/detail/meta/type_traits.hpp>
5099
5100// #include <nlohmann/detail/value_t.hpp>
5101
5102
5103NLOHMANN_JSON_NAMESPACE_BEGIN
5104namespace detail
5105{
5106
5107template<typename string_type>
5108void int_to_string( string_type& target, std::size_t value )
5109{
5110 // For ADL
5111 using std::to_string;
5112 target = to_string(value);
5113}
5114template<typename IteratorType> class iteration_proxy_value
5115{
5116 public:
5117 using difference_type = std::ptrdiff_t;
5118 using value_type = iteration_proxy_value;
5119 using pointer = value_type *;
5120 using reference = value_type &;
5121 using iterator_category = std::input_iterator_tag;
5122 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
5123
5124 private:
5125 /// the iterator
5126 IteratorType anchor{};
5127 /// an index for arrays (used to create key names)
5128 std::size_t array_index = 0;
5129 /// last stringified array index
5130 mutable std::size_t array_index_last = 0;
5131 /// a string representation of the array index
5132 mutable string_type array_index_str = "0";
5133 /// an empty string (to return a reference for primitive values)
5134 string_type empty_str{};
5135
5136 public:
5137 explicit iteration_proxy_value() = default;
5138 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
5139 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5140 && std::is_nothrow_default_constructible<string_type>::value)
5141 : anchor(std::move(it))
5142 , array_index(array_index_)
5143 {}
5144
5145 iteration_proxy_value(iteration_proxy_value const&) = default;
5146 iteration_proxy_value& operator=(iteration_proxy_value const&) = default;
5147 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
5148 iteration_proxy_value(iteration_proxy_value&&)
5149 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5150 && std::is_nothrow_move_constructible<string_type>::value) = default;
5151 iteration_proxy_value& operator=(iteration_proxy_value&&)
5152 noexcept(std::is_nothrow_move_assignable<IteratorType>::value
5153 && std::is_nothrow_move_assignable<string_type>::value) = default;
5154 ~iteration_proxy_value() = default;
5155
5156 /// dereference operator (needed for range-based for)
5157 const iteration_proxy_value& operator*() const
5158 {
5159 return *this;
5160 }
5161
5162 /// increment operator (needed for range-based for)
5163 iteration_proxy_value& operator++()
5164 {
5165 ++anchor;
5166 ++array_index;
5167
5168 return *this;
5169 }
5170
5171 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
5172 {
5173 auto tmp = iteration_proxy_value(anchor, array_index);
5174 ++anchor;
5175 ++array_index;
5176 return tmp;
5177 }
5178
5179 /// equality operator (needed for InputIterator)
5180 bool operator==(const iteration_proxy_value& o) const
5181 {
5182 return anchor == o.anchor;
5183 }
5184
5185 /// inequality operator (needed for range-based for)
5186 bool operator!=(const iteration_proxy_value& o) const
5187 {
5188 return anchor != o.anchor;
5189 }
5190
5191 /// return key of the iterator
5192 const string_type& key() const
5193 {
5194 JSON_ASSERT(anchor.m_object != nullptr);
5195
5196 switch (anchor.m_object->type())
5197 {
5198 // use integer array index as key
5199 case value_t::array:
5200 {
5201 if (array_index != array_index_last)
5202 {
5203 int_to_string( array_index_str, array_index );
5204 array_index_last = array_index;
5205 }
5206 return array_index_str;
5207 }
5208
5209 // use key from the object
5210 case value_t::object:
5211 return anchor.key();
5212
5213 // use an empty key for all primitive types
5214 case value_t::null:
5215 case value_t::string:
5216 case value_t::boolean:
5217 case value_t::number_integer:
5218 case value_t::number_unsigned:
5219 case value_t::number_float:
5220 case value_t::binary:
5221 case value_t::discarded:
5222 default:
5223 return empty_str;
5224 }
5225 }
5226
5227 /// return value of the iterator
5228 typename IteratorType::reference value() const
5229 {
5230 return anchor.value();
5231 }
5232};
5233
5234/// proxy class for the items() function
5235template<typename IteratorType> class iteration_proxy
5236{
5237 private:
5238 /// the container to iterate
5239 typename IteratorType::pointer container = nullptr;
5240
5241 public:
5242 explicit iteration_proxy() = default;
5243
5244 /// construct iteration proxy from a container
5245 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5246 : container(&cont) {}
5247
5248 iteration_proxy(iteration_proxy const&) = default;
5249 iteration_proxy& operator=(iteration_proxy const&) = default;
5250 iteration_proxy(iteration_proxy&&) noexcept = default;
5251 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5252 ~iteration_proxy() = default;
5253
5254 /// return iterator begin (needed for range-based for)
5255 iteration_proxy_value<IteratorType> begin() const noexcept
5256 {
5257 return iteration_proxy_value<IteratorType>(container->begin());
5258 }
5259
5260 /// return iterator end (needed for range-based for)
5261 iteration_proxy_value<IteratorType> end() const noexcept
5262 {
5263 return iteration_proxy_value<IteratorType>(container->end());
5264 }
5265};
5266
5267// Structured Bindings Support
5268// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5269// And see https://github.com/nlohmann/json/pull/1391
5270template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5271auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
5272{
5273 return i.key();
5274}
5275// Structured Bindings Support
5276// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5277// And see https://github.com/nlohmann/json/pull/1391
5278template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5279auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
5280{
5281 return i.value();
5282}
5283
5284} // namespace detail
5285NLOHMANN_JSON_NAMESPACE_END
5286
5287// The Addition to the STD Namespace is required to add
5288// Structured Bindings Support to the iteration_proxy_value class
5289// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5290// And see https://github.com/nlohmann/json/pull/1391
5291namespace std
5292{
5293
5294#if defined(__clang__)
5295 // Fix: https://github.com/nlohmann/json/issues/1401
5296 #pragma clang diagnostic push
5297 #pragma clang diagnostic ignored "-Wmismatched-tags"
5298#endif
5299template<typename IteratorType>
5300class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
5301 : public std::integral_constant<std::size_t, 2> {};
5302
5303template<std::size_t N, typename IteratorType>
5304class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
5305{
5306 public:
5307 using type = decltype(
5308 get<N>(std::declval <
5309 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5310};
5311#if defined(__clang__)
5312 #pragma clang diagnostic pop
5313#endif
5314
5315} // namespace std
5316
5317#if JSON_HAS_RANGES
5318 template <typename IteratorType>
5319 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5320#endif
5321
5322// #include <nlohmann/detail/macro_scope.hpp>
5323
5324// #include <nlohmann/detail/meta/cpp_future.hpp>
5325
5326// #include <nlohmann/detail/meta/std_fs.hpp>
5327
5328// #include <nlohmann/detail/meta/type_traits.hpp>
5329
5330// #include <nlohmann/detail/value_t.hpp>
5331
5332
5333NLOHMANN_JSON_NAMESPACE_BEGIN
5334namespace detail
5335{
5336
5337//////////////////
5338// constructors //
5339//////////////////
5340
5341/*
5342 * Note all external_constructor<>::construct functions need to call
5343 * j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an
5344 * allocated value (e.g., a string). See bug issue
5345 * https://github.com/nlohmann/json/issues/2865 for more information.
5346 */
5347
5348template<value_t> struct external_constructor;
5349
5350template<>
5351struct external_constructor<value_t::boolean>
5352{
5353 template<typename BasicJsonType>
5354 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5355 {
5356 j.m_value.destroy(j.m_type);
5357 j.m_type = value_t::boolean;
5358 j.m_value = b;
5359 j.assert_invariant();
5360 }
5361};
5362
5363template<>
5364struct external_constructor<value_t::string>
5365{
5366 template<typename BasicJsonType>
5367 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5368 {
5369 j.m_value.destroy(j.m_type);
5370 j.m_type = value_t::string;
5371 j.m_value = s;
5372 j.assert_invariant();
5373 }
5374
5375 template<typename BasicJsonType>
5376 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5377 {
5378 j.m_value.destroy(j.m_type);
5379 j.m_type = value_t::string;
5380 j.m_value = std::move(s);
5381 j.assert_invariant();
5382 }
5383
5384 template < typename BasicJsonType, typename CompatibleStringType,
5385 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5386 int > = 0 >
5387 static void construct(BasicJsonType& j, const CompatibleStringType& str)
5388 {
5389 j.m_value.destroy(j.m_type);
5390 j.m_type = value_t::string;
5391 j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5392 j.assert_invariant();
5393 }
5394};
5395
5396template<>
5397struct external_constructor<value_t::binary>
5398{
5399 template<typename BasicJsonType>
5400 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5401 {
5402 j.m_value.destroy(j.m_type);
5403 j.m_type = value_t::binary;
5404 j.m_value = typename BasicJsonType::binary_t(b);
5405 j.assert_invariant();
5406 }
5407
5408 template<typename BasicJsonType>
5409 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5410 {
5411 j.m_value.destroy(j.m_type);
5412 j.m_type = value_t::binary;
5413 j.m_value = typename BasicJsonType::binary_t(std::move(b));
5414 j.assert_invariant();
5415 }
5416};
5417
5418template<>
5419struct external_constructor<value_t::number_float>
5420{
5421 template<typename BasicJsonType>
5422 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5423 {
5424 j.m_value.destroy(j.m_type);
5425 j.m_type = value_t::number_float;
5426 j.m_value = val;
5427 j.assert_invariant();
5428 }
5429};
5430
5431template<>
5432struct external_constructor<value_t::number_unsigned>
5433{
5434 template<typename BasicJsonType>
5435 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5436 {
5437 j.m_value.destroy(j.m_type);
5438 j.m_type = value_t::number_unsigned;
5439 j.m_value = val;
5440 j.assert_invariant();
5441 }
5442};
5443
5444template<>
5445struct external_constructor<value_t::number_integer>
5446{
5447 template<typename BasicJsonType>
5448 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5449 {
5450 j.m_value.destroy(j.m_type);
5451 j.m_type = value_t::number_integer;
5452 j.m_value = val;
5453 j.assert_invariant();
5454 }
5455};
5456
5457template<>
5458struct external_constructor<value_t::array>
5459{
5460 template<typename BasicJsonType>
5461 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5462 {
5463 j.m_value.destroy(j.m_type);
5464 j.m_type = value_t::array;
5465 j.m_value = arr;
5466 j.set_parents();
5467 j.assert_invariant();
5468 }
5469
5470 template<typename BasicJsonType>
5471 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5472 {
5473 j.m_value.destroy(j.m_type);
5474 j.m_type = value_t::array;
5475 j.m_value = std::move(arr);
5476 j.set_parents();
5477 j.assert_invariant();
5478 }
5479
5480 template < typename BasicJsonType, typename CompatibleArrayType,
5481 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5482 int > = 0 >
5483 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5484 {
5485 using std::begin;
5486 using std::end;
5487
5488 j.m_value.destroy(j.m_type);
5489 j.m_type = value_t::array;
5490 j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5491 j.set_parents();
5492 j.assert_invariant();
5493 }
5494
5495 template<typename BasicJsonType>
5496 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
5497 {
5498 j.m_value.destroy(j.m_type);
5499 j.m_type = value_t::array;
5500 j.m_value = value_t::array;
5501 j.m_value.array->reserve(arr.size());
5502 for (const bool x : arr)
5503 {
5504 j.m_value.array->push_back(x);
5505 j.set_parent(j.m_value.array->back());
5506 }
5507 j.assert_invariant();
5508 }
5509
5510 template<typename BasicJsonType, typename T,
5511 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5512 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
5513 {
5514 j.m_value.destroy(j.m_type);
5515 j.m_type = value_t::array;
5516 j.m_value = value_t::array;
5517 j.m_value.array->resize(arr.size());
5518 if (arr.size() > 0)
5519 {
5520 std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
5521 }
5522 j.set_parents();
5523 j.assert_invariant();
5524 }
5525};
5526
5527template<>
5528struct external_constructor<value_t::object>
5529{
5530 template<typename BasicJsonType>
5531 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
5532 {
5533 j.m_value.destroy(j.m_type);
5534 j.m_type = value_t::object;
5535 j.m_value = obj;
5536 j.set_parents();
5537 j.assert_invariant();
5538 }
5539
5540 template<typename BasicJsonType>
5541 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5542 {
5543 j.m_value.destroy(j.m_type);
5544 j.m_type = value_t::object;
5545 j.m_value = std::move(obj);
5546 j.set_parents();
5547 j.assert_invariant();
5548 }
5549
5550 template < typename BasicJsonType, typename CompatibleObjectType,
5551 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
5552 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
5553 {
5554 using std::begin;
5555 using std::end;
5556
5557 j.m_value.destroy(j.m_type);
5558 j.m_type = value_t::object;
5559 j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5560 j.set_parents();
5561 j.assert_invariant();
5562 }
5563};
5564
5565/////////////
5566// to_json //
5567/////////////
5568
5569template<typename BasicJsonType, typename T,
5570 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
5571inline void to_json(BasicJsonType& j, T b) noexcept
5572{
5573 external_constructor<value_t::boolean>::construct(j, b);
5574}
5575
5576template < typename BasicJsonType, typename BoolRef,
5577 enable_if_t <
5578 ((std::is_same<std::vector<bool>::reference, BoolRef>::value
5579 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
5580 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
5581 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
5582 typename BasicJsonType::boolean_t >::value))
5583 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
5584inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
5585{
5586 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
5587}
5588
5589template<typename BasicJsonType, typename CompatibleString,
5590 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
5591inline void to_json(BasicJsonType& j, const CompatibleString& s)
5592{
5593 external_constructor<value_t::string>::construct(j, s);
5594}
5595
5596template<typename BasicJsonType>
5597inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5598{
5599 external_constructor<value_t::string>::construct(j, std::move(s));
5600}
5601
5602template<typename BasicJsonType, typename FloatType,
5603 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
5604inline void to_json(BasicJsonType& j, FloatType val) noexcept
5605{
5606 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
5607}
5608
5609template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
5610 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
5611inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
5612{
5613 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
5614}
5615
5616template<typename BasicJsonType, typename CompatibleNumberIntegerType,
5617 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
5618inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
5619{
5620 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
5621}
5622
5623#if !JSON_DISABLE_ENUM_SERIALIZATION
5624template<typename BasicJsonType, typename EnumType,
5625 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
5626inline void to_json(BasicJsonType& j, EnumType e) noexcept
5627{
5628 using underlying_type = typename std::underlying_type<EnumType>::type;
5629 external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
5630}
5631#endif // JSON_DISABLE_ENUM_SERIALIZATION
5632
5633template<typename BasicJsonType>
5634inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
5635{
5636 external_constructor<value_t::array>::construct(j, e);
5637}
5638
5639template < typename BasicJsonType, typename CompatibleArrayType,
5640 enable_if_t < is_compatible_array_type<BasicJsonType,
5641 CompatibleArrayType>::value&&
5642 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
5643 !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
5644 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
5645 !is_basic_json<CompatibleArrayType>::value,
5646 int > = 0 >
5647inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
5648{
5649 external_constructor<value_t::array>::construct(j, arr);
5650}
5651
5652template<typename BasicJsonType>
5653inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
5654{
5655 external_constructor<value_t::binary>::construct(j, bin);
5656}
5657
5658template<typename BasicJsonType, typename T,
5659 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5660inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
5661{
5662 external_constructor<value_t::array>::construct(j, std::move(arr));
5663}
5664
5665template<typename BasicJsonType>
5666inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5667{
5668 external_constructor<value_t::array>::construct(j, std::move(arr));
5669}
5670
5671template < typename BasicJsonType, typename CompatibleObjectType,
5672 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
5673inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
5674{
5675 external_constructor<value_t::object>::construct(j, obj);
5676}
5677
5678template<typename BasicJsonType>
5679inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5680{
5681 external_constructor<value_t::object>::construct(j, std::move(obj));
5682}
5683
5684template <
5685 typename BasicJsonType, typename T, std::size_t N,
5686 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
5687 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5688 int > = 0 >
5689inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5690{
5691 external_constructor<value_t::array>::construct(j, arr);
5692}
5693
5694template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
5695inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
5696{
5697 j = { p.first, p.second };
5698}
5699
5700// for https://github.com/nlohmann/json/pull/1134
5701template<typename BasicJsonType, typename T,
5702 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
5703inline void to_json(BasicJsonType& j, const T& b)
5704{
5705 j = { {b.key(), b.value()} };
5706}
5707
5708template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
5709inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
5710{
5711 j = { std::get<Idx>(t)... };
5712}
5713
5714template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
5715inline void to_json(BasicJsonType& j, const T& t)
5716{
5717 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
5718}
5719
5720#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5721template<typename BasicJsonType>
5722inline void to_json(BasicJsonType& j, const std_fs::path& p)
5723{
5724 j = p.string();
5725}
5726#endif
5727
5728struct to_json_fn
5729{
5730 template<typename BasicJsonType, typename T>
5731 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
5732 -> decltype(to_json(j, std::forward<T>(val)), void())
5733 {
5734 return to_json(j, std::forward<T>(val));
5735 }
5736};
5737} // namespace detail
5738
5739#ifndef JSON_HAS_CPP_17
5740/// namespace to hold default `to_json` function
5741/// to see why this is required:
5742/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
5743namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5744{
5745#endif
5746JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
5747 detail::static_const<detail::to_json_fn>::value;
5748#ifndef JSON_HAS_CPP_17
5749} // namespace
5750#endif
5751
5752NLOHMANN_JSON_NAMESPACE_END
5753
5754// #include <nlohmann/detail/meta/identity_tag.hpp>
5755
5756
5757NLOHMANN_JSON_NAMESPACE_BEGIN
5758
5759/// @sa https://json.nlohmann.me/api/adl_serializer/
5760template<typename ValueType, typename>
5761struct adl_serializer
5762{
5763 /// @brief convert a JSON value to any value type
5764 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
5765 template<typename BasicJsonType, typename TargetType = ValueType>
5766 static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
5767 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
5768 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
5769 {
5770 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
5771 }
5772
5773 /// @brief convert a JSON value to any value type
5774 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
5775 template<typename BasicJsonType, typename TargetType = ValueType>
5776 static auto from_json(BasicJsonType && j) noexcept(
5777 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
5778 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
5779 {
5780 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
5781 }
5782
5783 /// @brief convert any value type to a JSON value
5784 /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/
5785 template<typename BasicJsonType, typename TargetType = ValueType>
5786 static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
5787 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
5788 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
5789 {
5790 ::nlohmann::to_json(j, std::forward<TargetType>(val));
5791 }
5792};
5793
5794NLOHMANN_JSON_NAMESPACE_END
5795
5796// #include <nlohmann/byte_container_with_subtype.hpp>
5797// __ _____ _____ _____
5798// __| | __| | | | JSON for Modern C++
5799// | | |__ | | | | | | version 3.11.2
5800// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5801//
5802// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
5803// SPDX-License-Identifier: MIT
5804
5805
5806
5807#include <cstdint> // uint8_t, uint64_t
5808#include <tuple> // tie
5809#include <utility> // move
5810
5811// #include <nlohmann/detail/abi_macros.hpp>
5812
5813
5814NLOHMANN_JSON_NAMESPACE_BEGIN
5815
5816/// @brief an internal type for a backed binary type
5817/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/
5818template<typename BinaryType>
5819class byte_container_with_subtype : public BinaryType
5820{
5821 public:
5822 using container_type = BinaryType;
5823 using subtype_type = std::uint64_t;
5824
5825 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5826 byte_container_with_subtype() noexcept(noexcept(container_type()))
5827 : container_type()
5828 {}
5829
5830 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5831 byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
5832 : container_type(b)
5833 {}
5834
5835 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5836 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
5837 : container_type(std::move(b))
5838 {}
5839
5840 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5841 byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
5842 : container_type(b)
5843 , m_subtype(subtype_)
5844 , m_has_subtype(true)
5845 {}
5846
5847 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5848 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
5849 : container_type(std::move(b))
5850 , m_subtype(subtype_)
5851 , m_has_subtype(true)
5852 {}
5853
5854 bool operator==(const byte_container_with_subtype& rhs) const
5855 {
5856 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
5857 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
5858 }
5859
5860 bool operator!=(const byte_container_with_subtype& rhs) const
5861 {
5862 return !(rhs == *this);
5863 }
5864
5865 /// @brief sets the binary subtype
5866 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/
5867 void set_subtype(subtype_type subtype_) noexcept
5868 {
5869 m_subtype = subtype_;
5870 m_has_subtype = true;
5871 }
5872
5873 /// @brief return the binary subtype
5874 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/
5875 constexpr subtype_type subtype() const noexcept
5876 {
5877 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
5878 }
5879
5880 /// @brief return whether the value has a subtype
5881 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/
5882 constexpr bool has_subtype() const noexcept
5883 {
5884 return m_has_subtype;
5885 }
5886
5887 /// @brief clears the binary subtype
5888 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/
5889 void clear_subtype() noexcept
5890 {
5891 m_subtype = 0;
5892 m_has_subtype = false;
5893 }
5894
5895 private:
5896 subtype_type m_subtype = 0;
5897 bool m_has_subtype = false;
5898};
5899
5900NLOHMANN_JSON_NAMESPACE_END
5901
5902// #include <nlohmann/detail/conversions/from_json.hpp>
5903
5904// #include <nlohmann/detail/conversions/to_json.hpp>
5905
5906// #include <nlohmann/detail/exceptions.hpp>
5907
5908// #include <nlohmann/detail/hash.hpp>
5909// __ _____ _____ _____
5910// __| | __| | | | JSON for Modern C++
5911// | | |__ | | | | | | version 3.11.2
5912// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5913//
5914// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
5915// SPDX-License-Identifier: MIT
5916
5917
5918
5919#include <cstdint> // uint8_t
5920#include <cstddef> // size_t
5921#include <functional> // hash
5922
5923// #include <nlohmann/detail/abi_macros.hpp>
5924
5925// #include <nlohmann/detail/value_t.hpp>
5926
5927
5928NLOHMANN_JSON_NAMESPACE_BEGIN
5929namespace detail
5930{
5931
5932// boost::hash_combine
5933inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
5934{
5935 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
5936 return seed;
5937}
5938
5939/*!
5940@brief hash a JSON value
5941
5942The hash function tries to rely on std::hash where possible. Furthermore, the
5943type of the JSON value is taken into account to have different hash values for
5944null, 0, 0U, and false, etc.
5945
5946@tparam BasicJsonType basic_json specialization
5947@param j JSON value to hash
5948@return hash value of j
5949*/
5950template<typename BasicJsonType>
5951std::size_t hash(const BasicJsonType& j)
5952{
5953 using string_t = typename BasicJsonType::string_t;
5954 using number_integer_t = typename BasicJsonType::number_integer_t;
5955 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5956 using number_float_t = typename BasicJsonType::number_float_t;
5957
5958 const auto type = static_cast<std::size_t>(j.type());
5959 switch (j.type())
5960 {
5961 case BasicJsonType::value_t::null:
5962 case BasicJsonType::value_t::discarded:
5963 {
5964 return combine(type, 0);
5965 }
5966
5967 case BasicJsonType::value_t::object:
5968 {
5969 auto seed = combine(type, j.size());
5970 for (const auto& element : j.items())
5971 {
5972 const auto h = std::hash<string_t> {}(element.key());
5973 seed = combine(seed, h);
5974 seed = combine(seed, hash(element.value()));
5975 }
5976 return seed;
5977 }
5978
5979 case BasicJsonType::value_t::array:
5980 {
5981 auto seed = combine(type, j.size());
5982 for (const auto& element : j)
5983 {
5984 seed = combine(seed, hash(element));
5985 }
5986 return seed;
5987 }
5988
5989 case BasicJsonType::value_t::string:
5990 {
5991 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
5992 return combine(type, h);
5993 }
5994
5995 case BasicJsonType::value_t::boolean:
5996 {
5997 const auto h = std::hash<bool> {}(j.template get<bool>());
5998 return combine(type, h);
5999 }
6000
6001 case BasicJsonType::value_t::number_integer:
6002 {
6003 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
6004 return combine(type, h);
6005 }
6006
6007 case BasicJsonType::value_t::number_unsigned:
6008 {
6009 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
6010 return combine(type, h);
6011 }
6012
6013 case BasicJsonType::value_t::number_float:
6014 {
6015 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
6016 return combine(type, h);
6017 }
6018
6019 case BasicJsonType::value_t::binary:
6020 {
6021 auto seed = combine(type, j.get_binary().size());
6022 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
6023 seed = combine(seed, h);
6024 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
6025 for (const auto byte : j.get_binary())
6026 {
6027 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6028 }
6029 return seed;
6030 }
6031
6032 default: // LCOV_EXCL_LINE
6033 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
6034 return 0; // LCOV_EXCL_LINE
6035 }
6036}
6037
6038} // namespace detail
6039NLOHMANN_JSON_NAMESPACE_END
6040
6041// #include <nlohmann/detail/input/binary_reader.hpp>
6042// __ _____ _____ _____
6043// __| | __| | | | JSON for Modern C++
6044// | | |__ | | | | | | version 3.11.2
6045// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6046//
6047// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
6048// SPDX-License-Identifier: MIT
6049
6050
6051
6052#include <algorithm> // generate_n
6053#include <array> // array
6054#include <cmath> // ldexp
6055#include <cstddef> // size_t
6056#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6057#include <cstdio> // snprintf
6058#include <cstring> // memcpy
6059#include <iterator> // back_inserter
6060#include <limits> // numeric_limits
6061#include <string> // char_traits, string
6062#include <utility> // make_pair, move
6063#include <vector> // vector
6064
6065// #include <nlohmann/detail/exceptions.hpp>
6066
6067// #include <nlohmann/detail/input/input_adapters.hpp>
6068// __ _____ _____ _____
6069// __| | __| | | | JSON for Modern C++
6070// | | |__ | | | | | | version 3.11.2
6071// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6072//
6073// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
6074// SPDX-License-Identifier: MIT
6075
6076
6077
6078#include <array> // array
6079#include <cstddef> // size_t
6080#include <cstring> // strlen
6081#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
6082#include <memory> // shared_ptr, make_shared, addressof
6083#include <numeric> // accumulate
6084#include <string> // string, char_traits
6085#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6086#include <utility> // pair, declval
6087
6088#ifndef JSON_NO_IO
6089 #include <cstdio> // FILE *
6090 #include <istream> // istream
6091#endif // JSON_NO_IO
6092
6093// #include <nlohmann/detail/iterators/iterator_traits.hpp>
6094
6095// #include <nlohmann/detail/macro_scope.hpp>
6096
6097
6098NLOHMANN_JSON_NAMESPACE_BEGIN
6099namespace detail
6100{
6101
6102/// the supported input formats
6103enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
6104
6105////////////////////
6106// input adapters //
6107////////////////////
6108
6109#ifndef JSON_NO_IO
6110/*!
6111Input adapter for stdio file access. This adapter read only 1 byte and do not use any
6112 buffer. This adapter is a very low level adapter.
6113*/
6114class file_input_adapter
6115{
6116 public:
6117 using char_type = char;
6118
6119 JSON_HEDLEY_NON_NULL(2)
6120 explicit file_input_adapter(std::FILE* f) noexcept
6121 : m_file(f)
6122 {
6123 JSON_ASSERT(m_file != nullptr);
6124 }
6125
6126 // make class move-only
6127 file_input_adapter(const file_input_adapter&) = delete;
6128 file_input_adapter(file_input_adapter&&) noexcept = default;
6129 file_input_adapter& operator=(const file_input_adapter&) = delete;
6130 file_input_adapter& operator=(file_input_adapter&&) = delete;
6131 ~file_input_adapter() = default;
6132
6133 std::char_traits<char>::int_type get_character() noexcept
6134 {
6135 return std::fgetc(m_file);
6136 }
6137
6138 private:
6139 /// the file pointer to read from
6140 std::FILE* m_file;
6141};
6142
6143
6144/*!
6145Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
6146beginning of input. Does not support changing the underlying std::streambuf
6147in mid-input. Maintains underlying std::istream and std::streambuf to support
6148subsequent use of standard std::istream operations to process any input
6149characters following those used in parsing the JSON input. Clears the
6150std::istream flags; any input errors (e.g., EOF) will be detected by the first
6151subsequent call for input from the std::istream.
6152*/
6153class input_stream_adapter
6154{
6155 public:
6156 using char_type = char;
6157
6158 ~input_stream_adapter()
6159 {
6160 // clear stream flags; we use underlying streambuf I/O, do not
6161 // maintain ifstream flags, except eof
6162 if (is != nullptr)
6163 {
6164 is->clear(is->rdstate() & std::ios::eofbit);
6165 }
6166 }
6167
6168 explicit input_stream_adapter(std::istream& i)
6169 : is(&i), sb(i.rdbuf())
6170 {}
6171
6172 // delete because of pointer members
6173 input_stream_adapter(const input_stream_adapter&) = delete;
6174 input_stream_adapter& operator=(input_stream_adapter&) = delete;
6175 input_stream_adapter& operator=(input_stream_adapter&&) = delete;
6176
6177 input_stream_adapter(input_stream_adapter&& rhs) noexcept
6178 : is(rhs.is), sb(rhs.sb)
6179 {
6180 rhs.is = nullptr;
6181 rhs.sb = nullptr;
6182 }
6183
6184 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6185 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6186 // end up as the same value, e.g. 0xFFFFFFFF.
6187 std::char_traits<char>::int_type get_character()
6188 {
6189 auto res = sb->sbumpc();
6190 // set eof manually, as we don't use the istream interface.
6191 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6192 {
6193 is->clear(is->rdstate() | std::ios::eofbit);
6194 }
6195 return res;
6196 }
6197
6198 private:
6199 /// the associated input stream
6200 std::istream* is = nullptr;
6201 std::streambuf* sb = nullptr;
6202};
6203#endif // JSON_NO_IO
6204
6205// General-purpose iterator-based adapter. It might not be as fast as
6206// theoretically possible for some containers, but it is extremely versatile.
6207template<typename IteratorType>
6208class iterator_input_adapter
6209{
6210 public:
6211 using char_type = typename std::iterator_traits<IteratorType>::value_type;
6212
6213 iterator_input_adapter(IteratorType first, IteratorType last)
6214 : current(std::move(first)), end(std::move(last))
6215 {}
6216
6217 typename std::char_traits<char_type>::int_type get_character()
6218 {
6219 if (JSON_HEDLEY_LIKELY(current != end))
6220 {
6221 auto result = std::char_traits<char_type>::to_int_type(*current);
6222 std::advance(current, 1);
6223 return result;
6224 }
6225
6226 return std::char_traits<char_type>::eof();
6227 }
6228
6229 private:
6230 IteratorType current;
6231 IteratorType end;
6232
6233 template<typename BaseInputAdapter, size_t T>
6234 friend struct wide_string_input_helper;
6235
6236 bool empty() const
6237 {
6238 return current == end;
6239 }
6240};
6241
6242
6243template<typename BaseInputAdapter, size_t T>
6244struct wide_string_input_helper;
6245
6246template<typename BaseInputAdapter>
6247struct wide_string_input_helper<BaseInputAdapter, 4>
6248{
6249 // UTF-32
6250 static void fill_buffer(BaseInputAdapter& input,
6251 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6252 size_t& utf8_bytes_index,
6253 size_t& utf8_bytes_filled)
6254 {
6255 utf8_bytes_index = 0;
6256
6257 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6258 {
6259 utf8_bytes[0] = std::char_traits<char>::eof();
6260 utf8_bytes_filled = 1;
6261 }
6262 else
6263 {
6264 // get the current character
6265 const auto wc = input.get_character();
6266
6267 // UTF-32 to UTF-8 encoding
6268 if (wc < 0x80)
6269 {
6270 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6271 utf8_bytes_filled = 1;
6272 }
6273 else if (wc <= 0x7FF)
6274 {
6275 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6276 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6277 utf8_bytes_filled = 2;
6278 }
6279 else if (wc <= 0xFFFF)
6280 {
6281 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6282 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6283 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6284 utf8_bytes_filled = 3;
6285 }
6286 else if (wc <= 0x10FFFF)
6287 {
6288 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6289 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6290 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6291 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6292 utf8_bytes_filled = 4;
6293 }
6294 else
6295 {
6296 // unknown character
6297 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6298 utf8_bytes_filled = 1;
6299 }
6300 }
6301 }
6302};
6303
6304template<typename BaseInputAdapter>
6305struct wide_string_input_helper<BaseInputAdapter, 2>
6306{
6307 // UTF-16
6308 static void fill_buffer(BaseInputAdapter& input,
6309 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6310 size_t& utf8_bytes_index,
6311 size_t& utf8_bytes_filled)
6312 {
6313 utf8_bytes_index = 0;
6314
6315 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6316 {
6317 utf8_bytes[0] = std::char_traits<char>::eof();
6318 utf8_bytes_filled = 1;
6319 }
6320 else
6321 {
6322 // get the current character
6323 const auto wc = input.get_character();
6324
6325 // UTF-16 to UTF-8 encoding
6326 if (wc < 0x80)
6327 {
6328 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6329 utf8_bytes_filled = 1;
6330 }
6331 else if (wc <= 0x7FF)
6332 {
6333 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6334 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6335 utf8_bytes_filled = 2;
6336 }
6337 else if (0xD800 > wc || wc >= 0xE000)
6338 {
6339 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6340 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6341 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6342 utf8_bytes_filled = 3;
6343 }
6344 else
6345 {
6346 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6347 {
6348 const auto wc2 = static_cast<unsigned int>(input.get_character());
6349 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6350 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6351 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6352 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6353 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6354 utf8_bytes_filled = 4;
6355 }
6356 else
6357 {
6358 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6359 utf8_bytes_filled = 1;
6360 }
6361 }
6362 }
6363 }
6364};
6365
6366// Wraps another input apdater to convert wide character types into individual bytes.
6367template<typename BaseInputAdapter, typename WideCharType>
6368class wide_string_input_adapter
6369{
6370 public:
6371 using char_type = char;
6372
6373 wide_string_input_adapter(BaseInputAdapter base)
6374 : base_adapter(base) {}
6375
6376 typename std::char_traits<char>::int_type get_character() noexcept
6377 {
6378 // check if buffer needs to be filled
6379 if (utf8_bytes_index == utf8_bytes_filled)
6380 {
6381 fill_buffer<sizeof(WideCharType)>();
6382
6383 JSON_ASSERT(utf8_bytes_filled > 0);
6384 JSON_ASSERT(utf8_bytes_index == 0);
6385 }
6386
6387 // use buffer
6388 JSON_ASSERT(utf8_bytes_filled > 0);
6389 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
6390 return utf8_bytes[utf8_bytes_index++];
6391 }
6392
6393 private:
6394 BaseInputAdapter base_adapter;
6395
6396 template<size_t T>
6397 void fill_buffer()
6398 {
6399 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
6400 }
6401
6402 /// a buffer for UTF-8 bytes
6403 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6404
6405 /// index to the utf8_codes array for the next valid byte
6406 std::size_t utf8_bytes_index = 0;
6407 /// number of valid bytes in the utf8_codes array
6408 std::size_t utf8_bytes_filled = 0;
6409};
6410
6411
6412template<typename IteratorType, typename Enable = void>
6413struct iterator_input_adapter_factory
6414{
6415 using iterator_type = IteratorType;
6416 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6417 using adapter_type = iterator_input_adapter<iterator_type>;
6418
6419 static adapter_type create(IteratorType first, IteratorType last)
6420 {
6421 return adapter_type(std::move(first), std::move(last));
6422 }
6423};
6424
6425template<typename T>
6426struct is_iterator_of_multibyte
6427{
6428 using value_type = typename std::iterator_traits<T>::value_type;
6429 enum
6430 {
6431 value = sizeof(value_type) > 1
6432 };
6433};
6434
6435template<typename IteratorType>
6436struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
6437{
6438 using iterator_type = IteratorType;
6439 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6440 using base_adapter_type = iterator_input_adapter<iterator_type>;
6441 using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
6442
6443 static adapter_type create(IteratorType first, IteratorType last)
6444 {
6445 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6446 }
6447};
6448
6449// General purpose iterator-based input
6450template<typename IteratorType>
6451typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
6452{
6453 using factory_type = iterator_input_adapter_factory<IteratorType>;
6454 return factory_type::create(first, last);
6455}
6456
6457// Convenience shorthand from container to iterator
6458// Enables ADL on begin(container) and end(container)
6459// Encloses the using declarations in namespace for not to leak them to outside scope
6460
6461namespace container_input_adapter_factory_impl
6462{
6463
6464using std::begin;
6465using std::end;
6466
6467template<typename ContainerType, typename Enable = void>
6468struct container_input_adapter_factory {};
6469
6470template<typename ContainerType>
6471struct container_input_adapter_factory< ContainerType,
6472 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6473 {
6474 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6475
6476 static adapter_type create(const ContainerType& container)
6477{
6478 return input_adapter(begin(container), end(container));
6479}
6480 };
6481
6482} // namespace container_input_adapter_factory_impl
6483
6484template<typename ContainerType>
6485typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
6486{
6487 return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
6488}
6489
6490#ifndef JSON_NO_IO
6491// Special cases with fast paths
6492inline file_input_adapter input_adapter(std::FILE* file)
6493{
6494 return file_input_adapter(file);
6495}
6496
6497inline input_stream_adapter input_adapter(std::istream& stream)
6498{
6499 return input_stream_adapter(stream);
6500}
6501
6502inline input_stream_adapter input_adapter(std::istream&& stream)
6503{
6504 return input_stream_adapter(stream);
6505}
6506#endif // JSON_NO_IO
6507
6508using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6509
6510// Null-delimited strings, and the like.
6511template < typename CharT,
6512 typename std::enable_if <
6513 std::is_pointer<CharT>::value&&
6514 !std::is_array<CharT>::value&&
6515 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6516 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6517 int >::type = 0 >
6518contiguous_bytes_input_adapter input_adapter(CharT b)
6519{
6520 auto length = std::strlen(reinterpret_cast<const char*>(b));
6521 const auto* ptr = reinterpret_cast<const char*>(b);
6522 return input_adapter(ptr, ptr + length);
6523}
6524
6525template<typename T, std::size_t N>
6526auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6527{
6528 return input_adapter(array, array + N);
6529}
6530
6531// This class only handles inputs of input_buffer_adapter type.
6532// It's required so that expressions like {ptr, len} can be implicitly cast
6533// to the correct adapter.
6534class span_input_adapter
6535{
6536 public:
6537 template < typename CharT,
6538 typename std::enable_if <
6539 std::is_pointer<CharT>::value&&
6540 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6541 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6542 int >::type = 0 >
6543 span_input_adapter(CharT b, std::size_t l)
6544 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
6545
6546 template<class IteratorType,
6547 typename std::enable_if<
6548 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
6549 int>::type = 0>
6550 span_input_adapter(IteratorType first, IteratorType last)
6551 : ia(input_adapter(first, last)) {}
6552
6553 contiguous_bytes_input_adapter&& get()
6554 {
6555 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
6556 }
6557
6558 private:
6559 contiguous_bytes_input_adapter ia;
6560};
6561
6562} // namespace detail
6563NLOHMANN_JSON_NAMESPACE_END
6564
6565// #include <nlohmann/detail/input/json_sax.hpp>
6566// __ _____ _____ _____
6567// __| | __| | | | JSON for Modern C++
6568// | | |__ | | | | | | version 3.11.2
6569// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6570//
6571// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
6572// SPDX-License-Identifier: MIT
6573
6574
6575
6576#include <cstddef>
6577#include <string> // string
6578#include <utility> // move
6579#include <vector> // vector
6580
6581// #include <nlohmann/detail/exceptions.hpp>
6582
6583// #include <nlohmann/detail/macro_scope.hpp>
6584
6585// #include <nlohmann/detail/string_concat.hpp>
6586
6587
6588NLOHMANN_JSON_NAMESPACE_BEGIN
6589
6590/*!
6591@brief SAX interface
6592
6593This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
6594Each function is called in different situations while the input is parsed. The
6595boolean return value informs the parser whether to continue processing the
6596input.
6597*/
6598template<typename BasicJsonType>
6599struct json_sax
6600{
6601 using number_integer_t = typename BasicJsonType::number_integer_t;
6602 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6603 using number_float_t = typename BasicJsonType::number_float_t;
6604 using string_t = typename BasicJsonType::string_t;
6605 using binary_t = typename BasicJsonType::binary_t;
6606
6607 /*!
6608 @brief a null value was read
6609 @return whether parsing should proceed
6610 */
6611 virtual bool null() = 0;
6612
6613 /*!
6614 @brief a boolean value was read
6615 @param[in] val boolean value
6616 @return whether parsing should proceed
6617 */
6618 virtual bool boolean(bool val) = 0;
6619
6620 /*!
6621 @brief an integer number was read
6622 @param[in] val integer value
6623 @return whether parsing should proceed
6624 */
6625 virtual bool number_integer(number_integer_t val) = 0;
6626
6627 /*!
6628 @brief an unsigned integer number was read
6629 @param[in] val unsigned integer value
6630 @return whether parsing should proceed
6631 */
6632 virtual bool number_unsigned(number_unsigned_t val) = 0;
6633
6634 /*!
6635 @brief a floating-point number was read
6636 @param[in] val floating-point value
6637 @param[in] s raw token value
6638 @return whether parsing should proceed
6639 */
6640 virtual bool number_float(number_float_t val, const string_t& s) = 0;
6641
6642 /*!
6643 @brief a string value was read
6644 @param[in] val string value
6645 @return whether parsing should proceed
6646 @note It is safe to move the passed string value.
6647 */
6648 virtual bool string(string_t& val) = 0;
6649
6650 /*!
6651 @brief a binary value was read
6652 @param[in] val binary value
6653 @return whether parsing should proceed
6654 @note It is safe to move the passed binary value.
6655 */
6656 virtual bool binary(binary_t& val) = 0;
6657
6658 /*!
6659 @brief the beginning of an object was read
6660 @param[in] elements number of object elements or -1 if unknown
6661 @return whether parsing should proceed
6662 @note binary formats may report the number of elements
6663 */
6664 virtual bool start_object(std::size_t elements) = 0;
6665
6666 /*!
6667 @brief an object key was read
6668 @param[in] val object key
6669 @return whether parsing should proceed
6670 @note It is safe to move the passed string.
6671 */
6672 virtual bool key(string_t& val) = 0;
6673
6674 /*!
6675 @brief the end of an object was read
6676 @return whether parsing should proceed
6677 */
6678 virtual bool end_object() = 0;
6679
6680 /*!
6681 @brief the beginning of an array was read
6682 @param[in] elements number of array elements or -1 if unknown
6683 @return whether parsing should proceed
6684 @note binary formats may report the number of elements
6685 */
6686 virtual bool start_array(std::size_t elements) = 0;
6687
6688 /*!
6689 @brief the end of an array was read
6690 @return whether parsing should proceed
6691 */
6692 virtual bool end_array() = 0;
6693
6694 /*!
6695 @brief a parse error occurred
6696 @param[in] position the position in the input where the error occurs
6697 @param[in] last_token the last read token
6698 @param[in] ex an exception object describing the error
6699 @return whether parsing should proceed (must return false)
6700 */
6701 virtual bool parse_error(std::size_t position,
6702 const std::string& last_token,
6703 const detail::exception& ex) = 0;
6704
6705 json_sax() = default;
6706 json_sax(const json_sax&) = default;
6707 json_sax(json_sax&&) noexcept = default;
6708 json_sax& operator=(const json_sax&) = default;
6709 json_sax& operator=(json_sax&&) noexcept = default;
6710 virtual ~json_sax() = default;
6711};
6712
6713
6714namespace detail
6715{
6716/*!
6717@brief SAX implementation to create a JSON value from SAX events
6718
6719This class implements the @ref json_sax interface and processes the SAX events
6720to create a JSON value which makes it basically a DOM parser. The structure or
6721hierarchy of the JSON value is managed by the stack `ref_stack` which contains
6722a pointer to the respective array or object for each recursion depth.
6723
6724After successful parsing, the value that is passed by reference to the
6725constructor contains the parsed value.
6726
6727@tparam BasicJsonType the JSON type
6728*/
6729template<typename BasicJsonType>
6730class json_sax_dom_parser
6731{
6732 public:
6733 using number_integer_t = typename BasicJsonType::number_integer_t;
6734 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6735 using number_float_t = typename BasicJsonType::number_float_t;
6736 using string_t = typename BasicJsonType::string_t;
6737 using binary_t = typename BasicJsonType::binary_t;
6738
6739 /*!
6740 @param[in,out] r reference to a JSON value that is manipulated while
6741 parsing
6742 @param[in] allow_exceptions_ whether parse errors yield exceptions
6743 */
6744 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
6745 : root(r), allow_exceptions(allow_exceptions_)
6746 {}
6747
6748 // make class move-only
6749 json_sax_dom_parser(const json_sax_dom_parser&) = delete;
6750 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6751 json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
6752 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6753 ~json_sax_dom_parser() = default;
6754
6755 bool null()
6756 {
6757 handle_value(nullptr);
6758 return true;
6759 }
6760
6761 bool boolean(bool val)
6762 {
6763 handle_value(val);
6764 return true;
6765 }
6766
6767 bool number_integer(number_integer_t val)
6768 {
6769 handle_value(val);
6770 return true;
6771 }
6772
6773 bool number_unsigned(number_unsigned_t val)
6774 {
6775 handle_value(val);
6776 return true;
6777 }
6778
6779 bool number_float(number_float_t val, const string_t& /*unused*/)
6780 {
6781 handle_value(val);
6782 return true;
6783 }
6784
6785 bool string(string_t& val)
6786 {
6787 handle_value(val);
6788 return true;
6789 }
6790
6791 bool binary(binary_t& val)
6792 {
6793 handle_value(std::move(val));
6794 return true;
6795 }
6796
6797 bool start_object(std::size_t len)
6798 {
6799 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
6800
6801 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6802 {
6803 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
6804 }
6805
6806 return true;
6807 }
6808
6809 bool key(string_t& val)
6810 {
6811 JSON_ASSERT(!ref_stack.empty());
6812 JSON_ASSERT(ref_stack.back()->is_object());
6813
6814 // add null at given key and store the reference for later
6815 object_element = &(ref_stack.back()->m_value.object->operator[](val));
6816 return true;
6817 }
6818
6819 bool end_object()
6820 {
6821 JSON_ASSERT(!ref_stack.empty());
6822 JSON_ASSERT(ref_stack.back()->is_object());
6823
6824 ref_stack.back()->set_parents();
6825 ref_stack.pop_back();
6826 return true;
6827 }
6828
6829 bool start_array(std::size_t len)
6830 {
6831 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
6832
6833 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6834 {
6835 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
6836 }
6837
6838 return true;
6839 }
6840
6841 bool end_array()
6842 {
6843 JSON_ASSERT(!ref_stack.empty());
6844 JSON_ASSERT(ref_stack.back()->is_array());
6845
6846 ref_stack.back()->set_parents();
6847 ref_stack.pop_back();
6848 return true;
6849 }
6850
6851 template<class Exception>
6852 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
6853 const Exception& ex)
6854 {
6855 errored = true;
6856 static_cast<void>(ex);
6857 if (allow_exceptions)
6858 {
6859 JSON_THROW(ex);
6860 }
6861 return false;
6862 }
6863
6864 constexpr bool is_errored() const
6865 {
6866 return errored;
6867 }
6868
6869 private:
6870 /*!
6871 @invariant If the ref stack is empty, then the passed value will be the new
6872 root.
6873 @invariant If the ref stack contains a value, then it is an array or an
6874 object to which we can add elements
6875 */
6876 template<typename Value>
6877 JSON_HEDLEY_RETURNS_NON_NULL
6878 BasicJsonType* handle_value(Value&& v)
6879 {
6880 if (ref_stack.empty())
6881 {
6882 root = BasicJsonType(std::forward<Value>(v));
6883 return &root;
6884 }
6885
6886 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
6887
6888 if (ref_stack.back()->is_array())
6889 {
6890 ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
6891 return &(ref_stack.back()->m_value.array->back());
6892 }
6893
6894 JSON_ASSERT(ref_stack.back()->is_object());
6895 JSON_ASSERT(object_element);
6896 *object_element = BasicJsonType(std::forward<Value>(v));
6897 return object_element;
6898 }
6899
6900 /// the parsed JSON value
6901 BasicJsonType& root;
6902 /// stack to model hierarchy of values
6903 std::vector<BasicJsonType*> ref_stack {};
6904 /// helper to hold the reference for the next object element
6905 BasicJsonType* object_element = nullptr;
6906 /// whether a syntax error occurred
6907 bool errored = false;
6908 /// whether to throw exceptions in case of errors
6909 const bool allow_exceptions = true;
6910};
6911
6912template<typename BasicJsonType>
6913class json_sax_dom_callback_parser
6914{
6915 public:
6916 using number_integer_t = typename BasicJsonType::number_integer_t;
6917 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6918 using number_float_t = typename BasicJsonType::number_float_t;
6919 using string_t = typename BasicJsonType::string_t;
6920 using binary_t = typename BasicJsonType::binary_t;
6921 using parser_callback_t = typename BasicJsonType::parser_callback_t;
6922 using parse_event_t = typename BasicJsonType::parse_event_t;
6923
6924 json_sax_dom_callback_parser(BasicJsonType& r,
6925 const parser_callback_t cb,
6926 const bool allow_exceptions_ = true)
6927 : root(r), callback(cb), allow_exceptions(allow_exceptions_)
6928 {
6929 keep_stack.push_back(true);
6930 }
6931
6932 // make class move-only
6933 json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
6934 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6935 json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
6936 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6937 ~json_sax_dom_callback_parser() = default;
6938
6939 bool null()
6940 {
6941 handle_value(nullptr);
6942 return true;
6943 }
6944
6945 bool boolean(bool val)
6946 {
6947 handle_value(val);
6948 return true;
6949 }
6950
6951 bool number_integer(number_integer_t val)
6952 {
6953 handle_value(val);
6954 return true;
6955 }
6956
6957 bool number_unsigned(number_unsigned_t val)
6958 {
6959 handle_value(val);
6960 return true;
6961 }
6962
6963 bool number_float(number_float_t val, const string_t& /*unused*/)
6964 {
6965 handle_value(val);
6966 return true;
6967 }
6968
6969 bool string(string_t& val)
6970 {
6971 handle_value(val);
6972 return true;
6973 }
6974
6975 bool binary(binary_t& val)
6976 {
6977 handle_value(std::move(val));
6978 return true;
6979 }
6980
6981 bool start_object(std::size_t len)
6982 {
6983 // check callback for object start
6984 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
6985 keep_stack.push_back(keep);
6986
6987 auto val = handle_value(BasicJsonType::value_t::object, true);
6988 ref_stack.push_back(val.second);
6989
6990 // check object limit
6991 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6992 {
6993 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
6994 }
6995
6996 return true;
6997 }
6998
6999 bool key(string_t& val)
7000 {
7001 BasicJsonType k = BasicJsonType(val);
7002
7003 // check callback for key
7004 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
7005 key_keep_stack.push_back(keep);
7006
7007 // add discarded value at given key and store the reference for later
7008 if (keep && ref_stack.back())
7009 {
7010 object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
7011 }
7012
7013 return true;
7014 }
7015
7016 bool end_object()
7017 {
7018 if (ref_stack.back())
7019 {
7020 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
7021 {
7022 // discard object
7023 *ref_stack.back() = discarded;
7024 }
7025 else
7026 {
7027 ref_stack.back()->set_parents();
7028 }
7029 }
7030
7031 JSON_ASSERT(!ref_stack.empty());
7032 JSON_ASSERT(!keep_stack.empty());
7033 ref_stack.pop_back();
7034 keep_stack.pop_back();
7035
7036 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
7037 {
7038 // remove discarded value
7039 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
7040 {
7041 if (it->is_discarded())
7042 {
7043 ref_stack.back()->erase(it);
7044 break;
7045 }
7046 }
7047 }
7048
7049 return true;
7050 }
7051
7052 bool start_array(std::size_t len)
7053 {
7054 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
7055 keep_stack.push_back(keep);
7056
7057 auto val = handle_value(BasicJsonType::value_t::array, true);
7058 ref_stack.push_back(val.second);
7059
7060 // check array limit
7061 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7062 {
7063 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
7064 }
7065
7066 return true;
7067 }
7068
7069 bool end_array()
7070 {
7071 bool keep = true;
7072
7073 if (ref_stack.back())
7074 {
7075 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
7076 if (keep)
7077 {
7078 ref_stack.back()->set_parents();
7079 }
7080 else
7081 {
7082 // discard array
7083 *ref_stack.back() = discarded;
7084 }
7085 }
7086
7087 JSON_ASSERT(!ref_stack.empty());
7088 JSON_ASSERT(!keep_stack.empty());
7089 ref_stack.pop_back();
7090 keep_stack.pop_back();
7091
7092 // remove discarded value
7093 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
7094 {
7095 ref_stack.back()->m_value.array->pop_back();
7096 }
7097
7098 return true;
7099 }
7100
7101 template<class Exception>
7102 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
7103 const Exception& ex)
7104 {
7105 errored = true;
7106 static_cast<void>(ex);
7107 if (allow_exceptions)
7108 {
7109 JSON_THROW(ex);
7110 }
7111 return false;
7112 }
7113
7114 constexpr bool is_errored() const
7115 {
7116 return errored;
7117 }
7118
7119 private:
7120 /*!
7121 @param[in] v value to add to the JSON value we build during parsing
7122 @param[in] skip_callback whether we should skip calling the callback
7123 function; this is required after start_array() and
7124 start_object() SAX events, because otherwise we would call the
7125 callback function with an empty array or object, respectively.
7126
7127 @invariant If the ref stack is empty, then the passed value will be the new
7128 root.
7129 @invariant If the ref stack contains a value, then it is an array or an
7130 object to which we can add elements
7131
7132 @return pair of boolean (whether value should be kept) and pointer (to the
7133 passed value in the ref_stack hierarchy; nullptr if not kept)
7134 */
7135 template<typename Value>
7136 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
7137 {
7138 JSON_ASSERT(!keep_stack.empty());
7139
7140 // do not handle this value if we know it would be added to a discarded
7141 // container
7142 if (!keep_stack.back())
7143 {
7144 return {false, nullptr};
7145 }
7146
7147 // create value
7148 auto value = BasicJsonType(std::forward<Value>(v));
7149
7150 // check callback
7151 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
7152
7153 // do not handle this value if we just learnt it shall be discarded
7154 if (!keep)
7155 {
7156 return {false, nullptr};
7157 }
7158
7159 if (ref_stack.empty())
7160 {
7161 root = std::move(value);
7162 return {true, &root};
7163 }
7164
7165 // skip this value if we already decided to skip the parent
7166 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
7167 if (!ref_stack.back())
7168 {
7169 return {false, nullptr};
7170 }
7171
7172 // we now only expect arrays and objects
7173 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
7174
7175 // array
7176 if (ref_stack.back()->is_array())
7177 {
7178 ref_stack.back()->m_value.array->emplace_back(std::move(value));
7179 return {true, &(ref_stack.back()->m_value.array->back())};
7180 }
7181
7182 // object
7183 JSON_ASSERT(ref_stack.back()->is_object());
7184 // check if we should store an element for the current key
7185 JSON_ASSERT(!key_keep_stack.empty());
7186 const bool store_element = key_keep_stack.back();
7187 key_keep_stack.pop_back();
7188
7189 if (!store_element)
7190 {
7191 return {false, nullptr};
7192 }
7193
7194 JSON_ASSERT(object_element);
7195 *object_element = std::move(value);
7196 return {true, object_element};
7197 }
7198
7199 /// the parsed JSON value
7200 BasicJsonType& root;
7201 /// stack to model hierarchy of values
7202 std::vector<BasicJsonType*> ref_stack {};
7203 /// stack to manage which values to keep
7204 std::vector<bool> keep_stack {};
7205 /// stack to manage which object keys to keep
7206 std::vector<bool> key_keep_stack {};
7207 /// helper to hold the reference for the next object element
7208 BasicJsonType* object_element = nullptr;
7209 /// whether a syntax error occurred
7210 bool errored = false;
7211 /// callback function
7212 const parser_callback_t callback = nullptr;
7213 /// whether to throw exceptions in case of errors
7214 const bool allow_exceptions = true;
7215 /// a discarded value for the callback
7216 BasicJsonType discarded = BasicJsonType::value_t::discarded;
7217};
7218
7219template<typename BasicJsonType>
7220class json_sax_acceptor
7221{
7222 public:
7223 using number_integer_t = typename BasicJsonType::number_integer_t;
7224 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7225 using number_float_t = typename BasicJsonType::number_float_t;
7226 using string_t = typename BasicJsonType::string_t;
7227 using binary_t = typename BasicJsonType::binary_t;
7228
7229 bool null()
7230 {
7231 return true;
7232 }
7233
7234 bool boolean(bool /*unused*/)
7235 {
7236 return true;
7237 }
7238
7239 bool number_integer(number_integer_t /*unused*/)
7240 {
7241 return true;
7242 }
7243
7244 bool number_unsigned(number_unsigned_t /*unused*/)
7245 {
7246 return true;
7247 }
7248
7249 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
7250 {
7251 return true;
7252 }
7253
7254 bool string(string_t& /*unused*/)
7255 {
7256 return true;
7257 }
7258
7259 bool binary(binary_t& /*unused*/)
7260 {
7261 return true;
7262 }
7263
7264 bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7265 {
7266 return true;
7267 }
7268
7269 bool key(string_t& /*unused*/)
7270 {
7271 return true;
7272 }
7273
7274 bool end_object()
7275 {
7276 return true;
7277 }
7278
7279 bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7280 {
7281 return true;
7282 }
7283
7284 bool end_array()
7285 {
7286 return true;
7287 }
7288
7289 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
7290 {
7291 return false;
7292 }
7293};
7294
7295} // namespace detail
7296NLOHMANN_JSON_NAMESPACE_END
7297
7298// #include <nlohmann/detail/input/lexer.hpp>
7299// __ _____ _____ _____
7300// __| | __| | | | JSON for Modern C++
7301// | | |__ | | | | | | version 3.11.2
7302// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7303//
7304// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
7305// SPDX-License-Identifier: MIT
7306
7307
7308
7309#include <array> // array
7310#include <clocale> // localeconv
7311#include <cstddef> // size_t
7312#include <cstdio> // snprintf
7313#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7314#include <initializer_list> // initializer_list
7315#include <string> // char_traits, string
7316#include <utility> // move
7317#include <vector> // vector
7318
7319// #include <nlohmann/detail/input/input_adapters.hpp>
7320
7321// #include <nlohmann/detail/input/position_t.hpp>
7322
7323// #include <nlohmann/detail/macro_scope.hpp>
7324
7325
7326NLOHMANN_JSON_NAMESPACE_BEGIN
7327namespace detail
7328{
7329
7330///////////
7331// lexer //
7332///////////
7333
7334template<typename BasicJsonType>
7335class lexer_base
7336{
7337 public:
7338 /// token types for the parser
7339 enum class token_type
7340 {
7341 uninitialized, ///< indicating the scanner is uninitialized
7342 literal_true, ///< the `true` literal
7343 literal_false, ///< the `false` literal
7344 literal_null, ///< the `null` literal
7345 value_string, ///< a string -- use get_string() for actual value
7346 value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value
7347 value_integer, ///< a signed integer -- use get_number_integer() for actual value
7348 value_float, ///< an floating point number -- use get_number_float() for actual value
7349 begin_array, ///< the character for array begin `[`
7350 begin_object, ///< the character for object begin `{`
7351 end_array, ///< the character for array end `]`
7352 end_object, ///< the character for object end `}`
7353 name_separator, ///< the name separator `:`
7354 value_separator, ///< the value separator `,`
7355 parse_error, ///< indicating a parse error
7356 end_of_input, ///< indicating the end of the input buffer
7357 literal_or_value ///< a literal or the begin of a value (only for diagnostics)
7358 };
7359
7360 /// return name of values of type token_type (only used for errors)
7361 JSON_HEDLEY_RETURNS_NON_NULL
7362 JSON_HEDLEY_CONST
7363 static const char* token_type_name(const token_type t) noexcept
7364 {
7365 switch (t)
7366 {
7367 case token_type::uninitialized:
7368 return "<uninitialized>";
7369 case token_type::literal_true:
7370 return "true literal";
7371 case token_type::literal_false:
7372 return "false literal";
7373 case token_type::literal_null:
7374 return "null literal";
7375 case token_type::value_string:
7376 return "string literal";
7377 case token_type::value_unsigned:
7378 case token_type::value_integer:
7379 case token_type::value_float:
7380 return "number literal";
7381 case token_type::begin_array:
7382 return "'['";
7383 case token_type::begin_object:
7384 return "'{'";
7385 case token_type::end_array:
7386 return "']'";
7387 case token_type::end_object:
7388 return "'}'";
7389 case token_type::name_separator:
7390 return "':'";
7391 case token_type::value_separator:
7392 return "','";
7393 case token_type::parse_error:
7394 return "<parse error>";
7395 case token_type::end_of_input:
7396 return "end of input";
7397 case token_type::literal_or_value:
7398 return "'[', '{', or a literal";
7399 // LCOV_EXCL_START
7400 default: // catch non-enum values
7401 return "unknown token";
7402 // LCOV_EXCL_STOP
7403 }
7404 }
7405};
7406/*!
7407@brief lexical analysis
7408
7409This class organizes the lexical analysis during JSON deserialization.
7410*/
7411template<typename BasicJsonType, typename InputAdapterType>
7412class lexer : public lexer_base<BasicJsonType>
7413{
7414 using number_integer_t = typename BasicJsonType::number_integer_t;
7415 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7416 using number_float_t = typename BasicJsonType::number_float_t;
7417 using string_t = typename BasicJsonType::string_t;
7418 using char_type = typename InputAdapterType::char_type;
7419 using char_int_type = typename std::char_traits<char_type>::int_type;
7420
7421 public:
7422 using token_type = typename lexer_base<BasicJsonType>::token_type;
7423
7424 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7425 : ia(std::move(adapter))
7426 , ignore_comments(ignore_comments_)
7427 , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
7428 {}
7429
7430 // delete because of pointer members
7431 lexer(const lexer&) = delete;
7432 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7433 lexer& operator=(lexer&) = delete;
7434 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7435 ~lexer() = default;
7436
7437 private:
7438 /////////////////////
7439 // locales
7440 /////////////////////
7441
7442 /// return the locale-dependent decimal point
7443 JSON_HEDLEY_PURE
7444 static char get_decimal_point() noexcept
7445 {
7446 const auto* loc = localeconv();
7447 JSON_ASSERT(loc != nullptr);
7448 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7449 }
7450
7451 /////////////////////
7452 // scan functions
7453 /////////////////////
7454
7455 /*!
7456 @brief get codepoint from 4 hex characters following `\u`
7457
7458 For input "\u c1 c2 c3 c4" the codepoint is:
7459 (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
7460 = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
7461
7462 Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
7463 must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
7464 conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
7465 between the ASCII value of the character and the desired integer value.
7466
7467 @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
7468 non-hex character)
7469 */
7470 int get_codepoint()
7471 {
7472 // this function only makes sense after reading `\u`
7473 JSON_ASSERT(current == 'u');
7474 int codepoint = 0;
7475
7476 const auto factors = { 12u, 8u, 4u, 0u };
7477 for (const auto factor : factors)
7478 {
7479 get();
7480
7481 if (current >= '0' && current <= '9')
7482 {
7483 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7484 }
7485 else if (current >= 'A' && current <= 'F')
7486 {
7487 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7488 }
7489 else if (current >= 'a' && current <= 'f')
7490 {
7491 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7492 }
7493 else
7494 {
7495 return -1;
7496 }
7497 }
7498
7499 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7500 return codepoint;
7501 }
7502
7503 /*!
7504 @brief check if the next byte(s) are inside a given range
7505
7506 Adds the current byte and, for each passed range, reads a new byte and
7507 checks if it is inside the range. If a violation was detected, set up an
7508 error message and return false. Otherwise, return true.
7509
7510 @param[in] ranges list of integers; interpreted as list of pairs of
7511 inclusive lower and upper bound, respectively
7512
7513 @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
7514 1, 2, or 3 pairs. This precondition is enforced by an assertion.
7515
7516 @return true if and only if no range violation was detected
7517 */
7518 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7519 {
7520 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7521 add(current);
7522
7523 for (auto range = ranges.begin(); range != ranges.end(); ++range)
7524 {
7525 get();
7526 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range)))
7527 {
7528 add(current);
7529 }
7530 else
7531 {
7532 error_message = "invalid string: ill-formed UTF-8 byte";
7533 return false;
7534 }
7535 }
7536
7537 return true;
7538 }
7539
7540 /*!
7541 @brief scan a string literal
7542
7543 This function scans a string according to Sect. 7 of RFC 8259. While
7544 scanning, bytes are escaped and copied into buffer token_buffer. Then the
7545 function returns successfully, token_buffer is *not* null-terminated (as it
7546 may contain \0 bytes), and token_buffer.size() is the number of bytes in the
7547 string.
7548
7549 @return token_type::value_string if string could be successfully scanned,
7550 token_type::parse_error otherwise
7551
7552 @note In case of errors, variable error_message contains a textual
7553 description.
7554 */
7555 token_type scan_string()
7556 {
7557 // reset token_buffer (ignore opening quote)
7558 reset();
7559
7560 // we entered the function by reading an open quote
7561 JSON_ASSERT(current == '\"');
7562
7563 while (true)
7564 {
7565 // get next character
7566 switch (get())
7567 {
7568 // end of file while parsing string
7569 case std::char_traits<char_type>::eof():
7570 {
7571 error_message = "invalid string: missing closing quote";
7572 return token_type::parse_error;
7573 }
7574
7575 // closing quote
7576 case '\"':
7577 {
7578 return token_type::value_string;
7579 }
7580
7581 // escapes
7582 case '\\':
7583 {
7584 switch (get())
7585 {
7586 // quotation mark
7587 case '\"':
7588 add('\"');
7589 break;
7590 // reverse solidus
7591 case '\\':
7592 add('\\');
7593 break;
7594 // solidus
7595 case '/':
7596 add('/');
7597 break;
7598 // backspace
7599 case 'b':
7600 add('\b');
7601 break;
7602 // form feed
7603 case 'f':
7604 add('\f');
7605 break;
7606 // line feed
7607 case 'n':
7608 add('\n');
7609 break;
7610 // carriage return
7611 case 'r':
7612 add('\r');
7613 break;
7614 // tab
7615 case 't':
7616 add('\t');
7617 break;
7618
7619 // unicode escapes
7620 case 'u':
7621 {
7622 const int codepoint1 = get_codepoint();
7623 int codepoint = codepoint1; // start with codepoint1
7624
7625 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7626 {
7627 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7628 return token_type::parse_error;
7629 }
7630
7631 // check if code point is a high surrogate
7632 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7633 {
7634 // expect next \uxxxx entry
7635 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7636 {
7637 const int codepoint2 = get_codepoint();
7638
7639 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7640 {
7641 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7642 return token_type::parse_error;
7643 }
7644
7645 // check if codepoint2 is a low surrogate
7646 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7647 {
7648 // overwrite codepoint
7649 codepoint = static_cast<int>(
7650 // high surrogate occupies the most significant 22 bits
7651 (static_cast<unsigned int>(codepoint1) << 10u)
7652 // low surrogate occupies the least significant 15 bits
7653 + static_cast<unsigned int>(codepoint2)
7654 // there is still the 0xD800, 0xDC00 and 0x10000 noise
7655 // in the result, so we have to subtract with:
7656 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7657 - 0x35FDC00u);
7658 }
7659 else
7660 {
7661 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7662 return token_type::parse_error;
7663 }
7664 }
7665 else
7666 {
7667 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7668 return token_type::parse_error;
7669 }
7670 }
7671 else
7672 {
7673 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7674 {
7675 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7676 return token_type::parse_error;
7677 }
7678 }
7679
7680 // result of the above calculation yields a proper codepoint
7681 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7682
7683 // translate codepoint into bytes
7684 if (codepoint < 0x80)
7685 {
7686 // 1-byte characters: 0xxxxxxx (ASCII)
7687 add(static_cast<char_int_type>(codepoint));
7688 }
7689 else if (codepoint <= 0x7FF)
7690 {
7691 // 2-byte characters: 110xxxxx 10xxxxxx
7692 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7693 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7694 }
7695 else if (codepoint <= 0xFFFF)
7696 {
7697 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7698 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7699 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7700 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7701 }
7702 else
7703 {
7704 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7705 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7706 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7707 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7708 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7709 }
7710
7711 break;
7712 }
7713
7714 // other characters after escape
7715 default:
7716 error_message = "invalid string: forbidden character after backslash";
7717 return token_type::parse_error;
7718 }
7719
7720 break;
7721 }
7722
7723 // invalid control characters
7724 case 0x00:
7725 {
7726 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7727 return token_type::parse_error;
7728 }
7729
7730 case 0x01:
7731 {
7732 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7733 return token_type::parse_error;
7734 }
7735
7736 case 0x02:
7737 {
7738 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7739 return token_type::parse_error;
7740 }
7741
7742 case 0x03:
7743 {
7744 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7745 return token_type::parse_error;
7746 }
7747
7748 case 0x04:
7749 {
7750 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7751 return token_type::parse_error;
7752 }
7753
7754 case 0x05:
7755 {
7756 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7757 return token_type::parse_error;
7758 }
7759
7760 case 0x06:
7761 {
7762 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7763 return token_type::parse_error;
7764 }
7765
7766 case 0x07:
7767 {
7768 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7769 return token_type::parse_error;
7770 }
7771
7772 case 0x08:
7773 {
7774 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7775 return token_type::parse_error;
7776 }
7777
7778 case 0x09:
7779 {
7780 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7781 return token_type::parse_error;
7782 }
7783
7784 case 0x0A:
7785 {
7786 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7787 return token_type::parse_error;
7788 }
7789
7790 case 0x0B:
7791 {
7792 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7793 return token_type::parse_error;
7794 }
7795
7796 case 0x0C:
7797 {
7798 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7799 return token_type::parse_error;
7800 }
7801
7802 case 0x0D:
7803 {
7804 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7805 return token_type::parse_error;
7806 }
7807
7808 case 0x0E:
7809 {
7810 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7811 return token_type::parse_error;
7812 }
7813
7814 case 0x0F:
7815 {
7816 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7817 return token_type::parse_error;
7818 }
7819
7820 case 0x10:
7821 {
7822 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7823 return token_type::parse_error;
7824 }
7825
7826 case 0x11:
7827 {
7828 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7829 return token_type::parse_error;
7830 }
7831
7832 case 0x12:
7833 {
7834 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7835 return token_type::parse_error;
7836 }
7837
7838 case 0x13:
7839 {
7840 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7841 return token_type::parse_error;
7842 }
7843
7844 case 0x14:
7845 {
7846 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7847 return token_type::parse_error;
7848 }
7849
7850 case 0x15:
7851 {
7852 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7853 return token_type::parse_error;
7854 }
7855
7856 case 0x16:
7857 {
7858 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7859 return token_type::parse_error;
7860 }
7861
7862 case 0x17:
7863 {
7864 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7865 return token_type::parse_error;
7866 }
7867
7868 case 0x18:
7869 {
7870 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7871 return token_type::parse_error;
7872 }
7873
7874 case 0x19:
7875 {
7876 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7877 return token_type::parse_error;
7878 }
7879
7880 case 0x1A:
7881 {
7882 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7883 return token_type::parse_error;
7884 }
7885
7886 case 0x1B:
7887 {
7888 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7889 return token_type::parse_error;
7890 }
7891
7892 case 0x1C:
7893 {
7894 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7895 return token_type::parse_error;
7896 }
7897
7898 case 0x1D:
7899 {
7900 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7901 return token_type::parse_error;
7902 }
7903
7904 case 0x1E:
7905 {
7906 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7907 return token_type::parse_error;
7908 }
7909
7910 case 0x1F:
7911 {
7912 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7913 return token_type::parse_error;
7914 }
7915
7916 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7917 case 0x20:
7918 case 0x21:
7919 case 0x23:
7920 case 0x24:
7921 case 0x25:
7922 case 0x26:
7923 case 0x27:
7924 case 0x28:
7925 case 0x29:
7926 case 0x2A:
7927 case 0x2B:
7928 case 0x2C:
7929 case 0x2D:
7930 case 0x2E:
7931 case 0x2F:
7932 case 0x30:
7933 case 0x31:
7934 case 0x32:
7935 case 0x33:
7936 case 0x34:
7937 case 0x35:
7938 case 0x36:
7939 case 0x37:
7940 case 0x38:
7941 case 0x39:
7942 case 0x3A:
7943 case 0x3B:
7944 case 0x3C:
7945 case 0x3D:
7946 case 0x3E:
7947 case 0x3F:
7948 case 0x40:
7949 case 0x41:
7950 case 0x42:
7951 case 0x43:
7952 case 0x44:
7953 case 0x45:
7954 case 0x46:
7955 case 0x47:
7956 case 0x48:
7957 case 0x49:
7958 case 0x4A:
7959 case 0x4B:
7960 case 0x4C:
7961 case 0x4D:
7962 case 0x4E:
7963 case 0x4F:
7964 case 0x50:
7965 case 0x51:
7966 case 0x52:
7967 case 0x53:
7968 case 0x54:
7969 case 0x55:
7970 case 0x56:
7971 case 0x57:
7972 case 0x58:
7973 case 0x59:
7974 case 0x5A:
7975 case 0x5B:
7976 case 0x5D:
7977 case 0x5E:
7978 case 0x5F:
7979 case 0x60:
7980 case 0x61:
7981 case 0x62:
7982 case 0x63:
7983 case 0x64:
7984 case 0x65:
7985 case 0x66:
7986 case 0x67:
7987 case 0x68:
7988 case 0x69:
7989 case 0x6A:
7990 case 0x6B:
7991 case 0x6C:
7992 case 0x6D:
7993 case 0x6E:
7994 case 0x6F:
7995 case 0x70:
7996 case 0x71:
7997 case 0x72:
7998 case 0x73:
7999 case 0x74:
8000 case 0x75:
8001 case 0x76:
8002 case 0x77:
8003 case 0x78:
8004 case 0x79:
8005 case 0x7A:
8006 case 0x7B:
8007 case 0x7C:
8008 case 0x7D:
8009 case 0x7E:
8010 case 0x7F:
8011 {
8012 add(current);
8013 break;
8014 }
8015
8016 // U+0080..U+07FF: bytes C2..DF 80..BF
8017 case 0xC2:
8018 case 0xC3:
8019 case 0xC4:
8020 case 0xC5:
8021 case 0xC6:
8022 case 0xC7:
8023 case 0xC8:
8024 case 0xC9:
8025 case 0xCA:
8026 case 0xCB:
8027 case 0xCC:
8028 case 0xCD:
8029 case 0xCE:
8030 case 0xCF:
8031 case 0xD0:
8032 case 0xD1:
8033 case 0xD2:
8034 case 0xD3:
8035 case 0xD4:
8036 case 0xD5:
8037 case 0xD6:
8038 case 0xD7:
8039 case 0xD8:
8040 case 0xD9:
8041 case 0xDA:
8042 case 0xDB:
8043 case 0xDC:
8044 case 0xDD:
8045 case 0xDE:
8046 case 0xDF:
8047 {
8048 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
8049 {
8050 return token_type::parse_error;
8051 }
8052 break;
8053 }
8054
8055 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
8056 case 0xE0:
8057 {
8058 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
8059 {
8060 return token_type::parse_error;
8061 }
8062 break;
8063 }
8064
8065 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
8066 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
8067 case 0xE1:
8068 case 0xE2:
8069 case 0xE3:
8070 case 0xE4:
8071 case 0xE5:
8072 case 0xE6:
8073 case 0xE7:
8074 case 0xE8:
8075 case 0xE9:
8076 case 0xEA:
8077 case 0xEB:
8078 case 0xEC:
8079 case 0xEE:
8080 case 0xEF:
8081 {
8082 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
8083 {
8084 return token_type::parse_error;
8085 }
8086 break;
8087 }
8088
8089 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
8090 case 0xED:
8091 {
8092 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
8093 {
8094 return token_type::parse_error;
8095 }
8096 break;
8097 }
8098
8099 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
8100 case 0xF0:
8101 {
8102 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8103 {
8104 return token_type::parse_error;
8105 }
8106 break;
8107 }
8108
8109 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
8110 case 0xF1:
8111 case 0xF2:
8112 case 0xF3:
8113 {
8114 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8115 {
8116 return token_type::parse_error;
8117 }
8118 break;
8119 }
8120
8121 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
8122 case 0xF4:
8123 {
8124 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
8125 {
8126 return token_type::parse_error;
8127 }
8128 break;
8129 }
8130
8131 // remaining bytes (80..C1 and F5..FF) are ill-formed
8132 default:
8133 {
8134 error_message = "invalid string: ill-formed UTF-8 byte";
8135 return token_type::parse_error;
8136 }
8137 }
8138 }
8139 }
8140
8141 /*!
8142 * @brief scan a comment
8143 * @return whether comment could be scanned successfully
8144 */
8145 bool scan_comment()
8146 {
8147 switch (get())
8148 {
8149 // single-line comments skip input until a newline or EOF is read
8150 case '/':
8151 {
8152 while (true)
8153 {
8154 switch (get())
8155 {
8156 case '\n':
8157 case '\r':
8158 case std::char_traits<char_type>::eof():
8159 case '\0':
8160 return true;
8161
8162 default:
8163 break;
8164 }
8165 }
8166 }
8167
8168 // multi-line comments skip input until */ is read
8169 case '*':
8170 {
8171 while (true)
8172 {
8173 switch (get())
8174 {
8175 case std::char_traits<char_type>::eof():
8176 case '\0':
8177 {
8178 error_message = "invalid comment; missing closing '*/'";
8179 return false;
8180 }
8181
8182 case '*':
8183 {
8184 switch (get())
8185 {
8186 case '/':
8187 return true;
8188
8189 default:
8190 {
8191 unget();
8192 continue;
8193 }
8194 }
8195 }
8196
8197 default:
8198 continue;
8199 }
8200 }
8201 }
8202
8203 // unexpected character after reading '/'
8204 default:
8205 {
8206 error_message = "invalid comment; expecting '/' or '*' after '/'";
8207 return false;
8208 }
8209 }
8210 }
8211
8212 JSON_HEDLEY_NON_NULL(2)
8213 static void strtof(float& f, const char* str, char** endptr) noexcept
8214 {
8215 f = std::strtof(str, endptr);
8216 }
8217
8218 JSON_HEDLEY_NON_NULL(2)
8219 static void strtof(double& f, const char* str, char** endptr) noexcept
8220 {
8221 f = std::strtod(str, endptr);
8222 }
8223
8224 JSON_HEDLEY_NON_NULL(2)
8225 static void strtof(long double& f, const char* str, char** endptr) noexcept
8226 {
8227 f = std::strtold(str, endptr);
8228 }
8229
8230 /*!
8231 @brief scan a number literal
8232
8233 This function scans a string according to Sect. 6 of RFC 8259.
8234
8235 The function is realized with a deterministic finite state machine derived
8236 from the grammar described in RFC 8259. Starting in state "init", the
8237 input is read and used to determined the next state. Only state "done"
8238 accepts the number. State "error" is a trap state to model errors. In the
8239 table below, "anything" means any character but the ones listed before.
8240
8241 state | 0 | 1-9 | e E | + | - | . | anything
8242 ---------|----------|----------|----------|---------|---------|----------|-----------
8243 init | zero | any1 | [error] | [error] | minus | [error] | [error]
8244 minus | zero | any1 | [error] | [error] | [error] | [error] | [error]
8245 zero | done | done | exponent | done | done | decimal1 | done
8246 any1 | any1 | any1 | exponent | done | done | decimal1 | done
8247 decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error]
8248 decimal2 | decimal2 | decimal2 | exponent | done | done | done | done
8249 exponent | any2 | any2 | [error] | sign | sign | [error] | [error]
8250 sign | any2 | any2 | [error] | [error] | [error] | [error] | [error]
8251 any2 | any2 | any2 | done | done | done | done | done
8252
8253 The state machine is realized with one label per state (prefixed with
8254 "scan_number_") and `goto` statements between them. The state machine
8255 contains cycles, but any cycle can be left when EOF is read. Therefore,
8256 the function is guaranteed to terminate.
8257
8258 During scanning, the read bytes are stored in token_buffer. This string is
8259 then converted to a signed integer, an unsigned integer, or a
8260 floating-point number.
8261
8262 @return token_type::value_unsigned, token_type::value_integer, or
8263 token_type::value_float if number could be successfully scanned,
8264 token_type::parse_error otherwise
8265
8266 @note The scanner is independent of the current locale. Internally, the
8267 locale's decimal point is used instead of `.` to work with the
8268 locale-dependent converters.
8269 */
8270 token_type scan_number() // lgtm [cpp/use-of-goto]
8271 {
8272 // reset token_buffer to store the number's bytes
8273 reset();
8274
8275 // the type of the parsed number; initially set to unsigned; will be
8276 // changed if minus sign, decimal point or exponent is read
8277 token_type number_type = token_type::value_unsigned;
8278
8279 // state (init): we just found out we need to scan a number
8280 switch (current)
8281 {
8282 case '-':
8283 {
8284 add(current);
8285 goto scan_number_minus;
8286 }
8287
8288 case '0':
8289 {
8290 add(current);
8291 goto scan_number_zero;
8292 }
8293
8294 case '1':
8295 case '2':
8296 case '3':
8297 case '4':
8298 case '5':
8299 case '6':
8300 case '7':
8301 case '8':
8302 case '9':
8303 {
8304 add(current);
8305 goto scan_number_any1;
8306 }
8307
8308 // all other characters are rejected outside scan_number()
8309 default: // LCOV_EXCL_LINE
8310 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8311 }
8312
8313scan_number_minus:
8314 // state: we just parsed a leading minus sign
8315 number_type = token_type::value_integer;
8316 switch (get())
8317 {
8318 case '0':
8319 {
8320 add(current);
8321 goto scan_number_zero;
8322 }
8323
8324 case '1':
8325 case '2':
8326 case '3':
8327 case '4':
8328 case '5':
8329 case '6':
8330 case '7':
8331 case '8':
8332 case '9':
8333 {
8334 add(current);
8335 goto scan_number_any1;
8336 }
8337
8338 default:
8339 {
8340 error_message = "invalid number; expected digit after '-'";
8341 return token_type::parse_error;
8342 }
8343 }
8344
8345scan_number_zero:
8346 // state: we just parse a zero (maybe with a leading minus sign)
8347 switch (get())
8348 {
8349 case '.':
8350 {
8351 add(decimal_point_char);
8352 goto scan_number_decimal1;
8353 }
8354
8355 case 'e':
8356 case 'E':
8357 {
8358 add(current);
8359 goto scan_number_exponent;
8360 }
8361
8362 default:
8363 goto scan_number_done;
8364 }
8365
8366scan_number_any1:
8367 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8368 switch (get())
8369 {
8370 case '0':
8371 case '1':
8372 case '2':
8373 case '3':
8374 case '4':
8375 case '5':
8376 case '6':
8377 case '7':
8378 case '8':
8379 case '9':
8380 {
8381 add(current);
8382 goto scan_number_any1;
8383 }
8384
8385 case '.':
8386 {
8387 add(decimal_point_char);
8388 goto scan_number_decimal1;
8389 }
8390
8391 case 'e':
8392 case 'E':
8393 {
8394 add(current);
8395 goto scan_number_exponent;
8396 }
8397
8398 default:
8399 goto scan_number_done;
8400 }
8401
8402scan_number_decimal1:
8403 // state: we just parsed a decimal point
8404 number_type = token_type::value_float;
8405 switch (get())
8406 {
8407 case '0':
8408 case '1':
8409 case '2':
8410 case '3':
8411 case '4':
8412 case '5':
8413 case '6':
8414 case '7':
8415 case '8':
8416 case '9':
8417 {
8418 add(current);
8419 goto scan_number_decimal2;
8420 }
8421
8422 default:
8423 {
8424 error_message = "invalid number; expected digit after '.'";
8425 return token_type::parse_error;
8426 }
8427 }
8428
8429scan_number_decimal2:
8430 // we just parsed at least one number after a decimal point
8431 switch (get())
8432 {
8433 case '0':
8434 case '1':
8435 case '2':
8436 case '3':
8437 case '4':
8438 case '5':
8439 case '6':
8440 case '7':
8441 case '8':
8442 case '9':
8443 {
8444 add(current);
8445 goto scan_number_decimal2;
8446 }
8447
8448 case 'e':
8449 case 'E':
8450 {
8451 add(current);
8452 goto scan_number_exponent;
8453 }
8454
8455 default:
8456 goto scan_number_done;
8457 }
8458
8459scan_number_exponent:
8460 // we just parsed an exponent
8461 number_type = token_type::value_float;
8462 switch (get())
8463 {
8464 case '+':
8465 case '-':
8466 {
8467 add(current);
8468 goto scan_number_sign;
8469 }
8470
8471 case '0':
8472 case '1':
8473 case '2':
8474 case '3':
8475 case '4':
8476 case '5':
8477 case '6':
8478 case '7':
8479 case '8':
8480 case '9':
8481 {
8482 add(current);
8483 goto scan_number_any2;
8484 }
8485
8486 default:
8487 {
8488 error_message =
8489 "invalid number; expected '+', '-', or digit after exponent";
8490 return token_type::parse_error;
8491 }
8492 }
8493
8494scan_number_sign:
8495 // we just parsed an exponent sign
8496 switch (get())
8497 {
8498 case '0':
8499 case '1':
8500 case '2':
8501 case '3':
8502 case '4':
8503 case '5':
8504 case '6':
8505 case '7':
8506 case '8':
8507 case '9':
8508 {
8509 add(current);
8510 goto scan_number_any2;
8511 }
8512
8513 default:
8514 {
8515 error_message = "invalid number; expected digit after exponent sign";
8516 return token_type::parse_error;
8517 }
8518 }
8519
8520scan_number_any2:
8521 // we just parsed a number after the exponent or exponent sign
8522 switch (get())
8523 {
8524 case '0':
8525 case '1':
8526 case '2':
8527 case '3':
8528 case '4':
8529 case '5':
8530 case '6':
8531 case '7':
8532 case '8':
8533 case '9':
8534 {
8535 add(current);
8536 goto scan_number_any2;
8537 }
8538
8539 default:
8540 goto scan_number_done;
8541 }
8542
8543scan_number_done:
8544 // unget the character after the number (we only read it to know that
8545 // we are done scanning a number)
8546 unget();
8547
8548 char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8549 errno = 0;
8550
8551 // try to parse integers first and fall back to floats
8552 if (number_type == token_type::value_unsigned)
8553 {
8554 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8555
8556 // we checked the number format before
8557 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8558
8559 if (errno == 0)
8560 {
8561 value_unsigned = static_cast<number_unsigned_t>(x);
8562 if (value_unsigned == x)
8563 {
8564 return token_type::value_unsigned;
8565 }
8566 }
8567 }
8568 else if (number_type == token_type::value_integer)
8569 {
8570 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8571
8572 // we checked the number format before
8573 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8574
8575 if (errno == 0)
8576 {
8577 value_integer = static_cast<number_integer_t>(x);
8578 if (value_integer == x)
8579 {
8580 return token_type::value_integer;
8581 }
8582 }
8583 }
8584
8585 // this code is reached if we parse a floating-point number or if an
8586 // integer conversion above failed
8587 strtof(value_float, token_buffer.data(), &endptr);
8588
8589 // we checked the number format before
8590 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8591
8592 return token_type::value_float;
8593 }
8594
8595 /*!
8596 @param[in] literal_text the literal text to expect
8597 @param[in] length the length of the passed literal text
8598 @param[in] return_type the token type to return on success
8599 */
8600 JSON_HEDLEY_NON_NULL(2)
8601 token_type scan_literal(const char_type* literal_text, const std::size_t length,
8602 token_type return_type)
8603 {
8604 JSON_ASSERT(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
8605 for (std::size_t i = 1; i < length; ++i)
8606 {
8607 if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i]))
8608 {
8609 error_message = "invalid literal";
8610 return token_type::parse_error;
8611 }
8612 }
8613 return return_type;
8614 }
8615
8616 /////////////////////
8617 // input management
8618 /////////////////////
8619
8620 /// reset token_buffer; current character is beginning of token
8621 void reset() noexcept
8622 {
8623 token_buffer.clear();
8624 token_string.clear();
8625 token_string.push_back(std::char_traits<char_type>::to_char_type(current));
8626 }
8627
8628 /*
8629 @brief get next character from the input
8630
8631 This function provides the interface to the used input adapter. It does
8632 not throw in case the input reached EOF, but returns a
8633 `std::char_traits<char>::eof()` in that case. Stores the scanned characters
8634 for use in error messages.
8635
8636 @return character read from the input
8637 */
8638 char_int_type get()
8639 {
8640 ++position.chars_read_total;
8641 ++position.chars_read_current_line;
8642
8643 if (next_unget)
8644 {
8645 // just reset the next_unget variable and work with current
8646 next_unget = false;
8647 }
8648 else
8649 {
8650 current = ia.get_character();
8651 }
8652
8653 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
8654 {
8655 token_string.push_back(std::char_traits<char_type>::to_char_type(current));
8656 }
8657
8658 if (current == '\n')
8659 {
8660 ++position.lines_read;
8661 position.chars_read_current_line = 0;
8662 }
8663
8664 return current;
8665 }
8666
8667 /*!
8668 @brief unget current character (read it again on next get)
8669
8670 We implement unget by setting variable next_unget to true. The input is not
8671 changed - we just simulate ungetting by modifying chars_read_total,
8672 chars_read_current_line, and token_string. The next call to get() will
8673 behave as if the unget character is read again.
8674 */
8675 void unget()
8676 {
8677 next_unget = true;
8678
8679 --position.chars_read_total;
8680
8681 // in case we "unget" a newline, we have to also decrement the lines_read
8682 if (position.chars_read_current_line == 0)
8683 {
8684 if (position.lines_read > 0)
8685 {
8686 --position.lines_read;
8687 }
8688 }
8689 else
8690 {
8691 --position.chars_read_current_line;
8692 }
8693
8694 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
8695 {
8696 JSON_ASSERT(!token_string.empty());
8697 token_string.pop_back();
8698 }
8699 }
8700
8701 /// add a character to token_buffer
8702 void add(char_int_type c)
8703 {
8704 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8705 }
8706
8707 public:
8708 /////////////////////
8709 // value getters
8710 /////////////////////
8711
8712 /// return integer value
8713 constexpr number_integer_t get_number_integer() const noexcept
8714 {
8715 return value_integer;
8716 }
8717
8718 /// return unsigned integer value
8719 constexpr number_unsigned_t get_number_unsigned() const noexcept
8720 {
8721 return value_unsigned;
8722 }
8723
8724 /// return floating-point value
8725 constexpr number_float_t get_number_float() const noexcept
8726 {
8727 return value_float;
8728 }
8729
8730 /// return current string value (implicitly resets the token; useful only once)
8731 string_t& get_string()
8732 {
8733 return token_buffer;
8734 }
8735
8736 /////////////////////
8737 // diagnostics
8738 /////////////////////
8739
8740 /// return position of last read token
8741 constexpr position_t get_position() const noexcept
8742 {
8743 return position;
8744 }
8745
8746 /// return the last read token (for errors only). Will never contain EOF
8747 /// (an arbitrary value that is not a valid char value, often -1), because
8748 /// 255 may legitimately occur. May contain NUL, which should be escaped.
8749 std::string get_token_string() const
8750 {
8751 // escape control characters
8752 std::string result;
8753 for (const auto c : token_string)
8754 {
8755 if (static_cast<unsigned char>(c) <= '\x1F')
8756 {
8757 // escape control characters
8758 std::array<char, 9> cs{{}};
8759 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8760 result += cs.data();
8761 }
8762 else
8763 {
8764 // add character as is
8765 result.push_back(static_cast<std::string::value_type>(c));
8766 }
8767 }
8768
8769 return result;
8770 }
8771
8772 /// return syntax error message
8773 JSON_HEDLEY_RETURNS_NON_NULL
8774 constexpr const char* get_error_message() const noexcept
8775 {
8776 return error_message;
8777 }
8778
8779 /////////////////////
8780 // actual scanner
8781 /////////////////////
8782
8783 /*!
8784 @brief skip the UTF-8 byte order mark
8785 @return true iff there is no BOM or the correct BOM has been skipped
8786 */
8787 bool skip_bom()
8788 {
8789 if (get() == 0xEF)
8790 {
8791 // check if we completely parse the BOM
8792 return get() == 0xBB && get() == 0xBF;
8793 }
8794
8795 // the first character is not the beginning of the BOM; unget it to
8796 // process is later
8797 unget();
8798 return true;
8799 }
8800
8801 void skip_whitespace()
8802 {
8803 do
8804 {
8805 get();
8806 }
8807 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8808 }
8809
8810 token_type scan()
8811 {
8812 // initially, skip the BOM
8813 if (position.chars_read_total == 0 && !skip_bom())
8814 {
8815 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8816 return token_type::parse_error;
8817 }
8818
8819 // read next character and ignore whitespace
8820 skip_whitespace();
8821
8822 // ignore comments
8823 while (ignore_comments && current == '/')
8824 {
8825 if (!scan_comment())
8826 {
8827 return token_type::parse_error;
8828 }
8829
8830 // skip following whitespace
8831 skip_whitespace();
8832 }
8833
8834 switch (current)
8835 {
8836 // structural characters
8837 case '[':
8838 return token_type::begin_array;
8839 case ']':
8840 return token_type::end_array;
8841 case '{':
8842 return token_type::begin_object;
8843 case '}':
8844 return token_type::end_object;
8845 case ':':
8846 return token_type::name_separator;
8847 case ',':
8848 return token_type::value_separator;
8849
8850 // literals
8851 case 't':
8852 {
8853 std::array<char_type, 4> true_literal = {{static_cast<char_type>('t'), static_cast<char_type>('r'), static_cast<char_type>('u'), static_cast<char_type>('e')}};
8854 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
8855 }
8856 case 'f':
8857 {
8858 std::array<char_type, 5> false_literal = {{static_cast<char_type>('f'), static_cast<char_type>('a'), static_cast<char_type>('l'), static_cast<char_type>('s'), static_cast<char_type>('e')}};
8859 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
8860 }
8861 case 'n':
8862 {
8863 std::array<char_type, 4> null_literal = {{static_cast<char_type>('n'), static_cast<char_type>('u'), static_cast<char_type>('l'), static_cast<char_type>('l')}};
8864 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
8865 }
8866
8867 // string
8868 case '\"':
8869 return scan_string();
8870
8871 // number
8872 case '-':
8873 case '0':
8874 case '1':
8875 case '2':
8876 case '3':
8877 case '4':
8878 case '5':
8879 case '6':
8880 case '7':
8881 case '8':
8882 case '9':
8883 return scan_number();
8884
8885 // end of input (the null byte is needed when parsing from
8886 // string literals)
8887 case '\0':
8888 case std::char_traits<char_type>::eof():
8889 return token_type::end_of_input;
8890
8891 // error
8892 default:
8893 error_message = "invalid literal";
8894 return token_type::parse_error;
8895 }
8896 }
8897
8898 private:
8899 /// input adapter
8900 InputAdapterType ia;
8901
8902 /// whether comments should be ignored (true) or signaled as errors (false)
8903 const bool ignore_comments = false;
8904
8905 /// the current character
8906 char_int_type current = std::char_traits<char_type>::eof();
8907
8908 /// whether the next get() call should just return current
8909 bool next_unget = false;
8910
8911 /// the start position of the current token
8912 position_t position {};
8913
8914 /// raw input token string (for error messages)
8915 std::vector<char_type> token_string {};
8916
8917 /// buffer for variable-length tokens (numbers, strings)
8918 string_t token_buffer {};
8919
8920 /// a description of occurred lexer errors
8921 const char* error_message = "";
8922
8923 // number values
8924 number_integer_t value_integer = 0;
8925 number_unsigned_t value_unsigned = 0;
8926 number_float_t value_float = 0;
8927
8928 /// the decimal point
8929 const char_int_type decimal_point_char = '.';
8930};
8931
8932} // namespace detail
8933NLOHMANN_JSON_NAMESPACE_END
8934
8935// #include <nlohmann/detail/macro_scope.hpp>
8936
8937// #include <nlohmann/detail/meta/is_sax.hpp>
8938// __ _____ _____ _____
8939// __| | __| | | | JSON for Modern C++
8940// | | |__ | | | | | | version 3.11.2
8941// |_____|_____|_____|_|___| https://github.com/nlohmann/json
8942//
8943// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
8944// SPDX-License-Identifier: MIT
8945
8946
8947
8948#include <cstdint> // size_t
8949#include <utility> // declval
8950#include <string> // string
8951
8952// #include <nlohmann/detail/abi_macros.hpp>
8953
8954// #include <nlohmann/detail/meta/detected.hpp>
8955
8956// #include <nlohmann/detail/meta/type_traits.hpp>
8957
8958
8959NLOHMANN_JSON_NAMESPACE_BEGIN
8960namespace detail
8961{
8962
8963template<typename T>
8964using null_function_t = decltype(std::declval<T&>().null());
8965
8966template<typename T>
8967using boolean_function_t =
8968 decltype(std::declval<T&>().boolean(std::declval<bool>()));
8969
8970template<typename T, typename Integer>
8971using number_integer_function_t =
8972 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
8973
8974template<typename T, typename Unsigned>
8975using number_unsigned_function_t =
8976 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
8977
8978template<typename T, typename Float, typename String>
8979using number_float_function_t = decltype(std::declval<T&>().number_float(
8980 std::declval<Float>(), std::declval<const String&>()));
8981
8982template<typename T, typename String>
8983using string_function_t =
8984 decltype(std::declval<T&>().string(std::declval<String&>()));
8985
8986template<typename T, typename Binary>
8987using binary_function_t =
8988 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
8989
8990template<typename T>
8991using start_object_function_t =
8992 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
8993
8994template<typename T, typename String>
8995using key_function_t =
8996 decltype(std::declval<T&>().key(std::declval<String&>()));
8997
8998template<typename T>
8999using end_object_function_t = decltype(std::declval<T&>().end_object());
9000
9001template<typename T>
9002using start_array_function_t =
9003 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9004
9005template<typename T>
9006using end_array_function_t = decltype(std::declval<T&>().end_array());
9007
9008template<typename T, typename Exception>
9009using parse_error_function_t = decltype(std::declval<T&>().parse_error(
9010 std::declval<std::size_t>(), std::declval<const std::string&>(),
9011 std::declval<const Exception&>()));
9012
9013template<typename SAX, typename BasicJsonType>
9014struct is_sax
9015{
9016 private:
9017 static_assert(is_basic_json<BasicJsonType>::value,
9018 "BasicJsonType must be of type basic_json<...>");
9019
9020 using number_integer_t = typename BasicJsonType::number_integer_t;
9021 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9022 using number_float_t = typename BasicJsonType::number_float_t;
9023 using string_t = typename BasicJsonType::string_t;
9024 using binary_t = typename BasicJsonType::binary_t;
9025 using exception_t = typename BasicJsonType::exception;
9026
9027 public:
9028 static constexpr bool value =
9029 is_detected_exact<bool, null_function_t, SAX>::value &&
9030 is_detected_exact<bool, boolean_function_t, SAX>::value &&
9031 is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
9032 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
9033 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
9034 is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
9035 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
9036 is_detected_exact<bool, start_object_function_t, SAX>::value &&
9037 is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
9038 is_detected_exact<bool, end_object_function_t, SAX>::value &&
9039 is_detected_exact<bool, start_array_function_t, SAX>::value &&
9040 is_detected_exact<bool, end_array_function_t, SAX>::value &&
9041 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
9042};
9043
9044template<typename SAX, typename BasicJsonType>
9045struct is_sax_static_asserts
9046{
9047 private:
9048 static_assert(is_basic_json<BasicJsonType>::value,
9049 "BasicJsonType must be of type basic_json<...>");
9050
9051 using number_integer_t = typename BasicJsonType::number_integer_t;
9052 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9053 using number_float_t = typename BasicJsonType::number_float_t;
9054 using string_t = typename BasicJsonType::string_t;
9055 using binary_t = typename BasicJsonType::binary_t;
9056 using exception_t = typename BasicJsonType::exception;
9057
9058 public:
9059 static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
9060 "Missing/invalid function: bool null()");
9061 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9062 "Missing/invalid function: bool boolean(bool)");
9063 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9064 "Missing/invalid function: bool boolean(bool)");
9065 static_assert(
9066 is_detected_exact<bool, number_integer_function_t, SAX,
9067 number_integer_t>::value,
9068 "Missing/invalid function: bool number_integer(number_integer_t)");
9069 static_assert(
9070 is_detected_exact<bool, number_unsigned_function_t, SAX,
9071 number_unsigned_t>::value,
9072 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9073 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9074 number_float_t, string_t>::value,
9075 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9076 static_assert(
9077 is_detected_exact<bool, string_function_t, SAX, string_t>::value,
9078 "Missing/invalid function: bool string(string_t&)");
9079 static_assert(
9080 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
9081 "Missing/invalid function: bool binary(binary_t&)");
9082 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
9083 "Missing/invalid function: bool start_object(std::size_t)");
9084 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
9085 "Missing/invalid function: bool key(string_t&)");
9086 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
9087 "Missing/invalid function: bool end_object()");
9088 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
9089 "Missing/invalid function: bool start_array(std::size_t)");
9090 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
9091 "Missing/invalid function: bool end_array()");
9092 static_assert(
9093 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
9094 "Missing/invalid function: bool parse_error(std::size_t, const "
9095 "std::string&, const exception&)");
9096};
9097
9098} // namespace detail
9099NLOHMANN_JSON_NAMESPACE_END
9100
9101// #include <nlohmann/detail/meta/type_traits.hpp>
9102
9103// #include <nlohmann/detail/string_concat.hpp>
9104
9105// #include <nlohmann/detail/value_t.hpp>
9106
9107
9108NLOHMANN_JSON_NAMESPACE_BEGIN
9109namespace detail
9110{
9111
9112/// how to treat CBOR tags
9113enum class cbor_tag_handler_t
9114{
9115 error, ///< throw a parse_error exception in case of a tag
9116 ignore, ///< ignore tags
9117 store ///< store tags as binary type
9118};
9119
9120/*!
9121@brief determine system byte order
9122
9123@return true if and only if system's byte order is little endian
9124
9125@note from https://stackoverflow.com/a/1001328/266378
9126*/
9127static inline bool little_endianness(int num = 1) noexcept
9128{
9129 return *reinterpret_cast<char*>(&num) == 1;
9130}
9131
9132
9133///////////////////
9134// binary reader //
9135///////////////////
9136
9137/*!
9138@brief deserialization of CBOR, MessagePack, and UBJSON values
9139*/
9140template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
9141class binary_reader
9142{
9143 using number_integer_t = typename BasicJsonType::number_integer_t;
9144 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9145 using number_float_t = typename BasicJsonType::number_float_t;
9146 using string_t = typename BasicJsonType::string_t;
9147 using binary_t = typename BasicJsonType::binary_t;
9148 using json_sax_t = SAX;
9149 using char_type = typename InputAdapterType::char_type;
9150 using char_int_type = typename std::char_traits<char_type>::int_type;
9151
9152 public:
9153 /*!
9154 @brief create a binary reader
9155
9156 @param[in] adapter input adapter to read from
9157 */
9158 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
9159 {
9160 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
9161 }
9162
9163 // make class move-only
9164 binary_reader(const binary_reader&) = delete;
9165 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9166 binary_reader& operator=(const binary_reader&) = delete;
9167 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9168 ~binary_reader() = default;
9169
9170 /*!
9171 @param[in] format the binary format to parse
9172 @param[in] sax_ a SAX event processor
9173 @param[in] strict whether to expect the input to be consumed completed
9174 @param[in] tag_handler how to treat CBOR tags
9175
9176 @return whether parsing was successful
9177 */
9178 JSON_HEDLEY_NON_NULL(3)
9179 bool sax_parse(const input_format_t format,
9180 json_sax_t* sax_,
9181 const bool strict = true,
9182 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
9183 {
9184 sax = sax_;
9185 bool result = false;
9186
9187 switch (format)
9188 {
9189 case input_format_t::bson:
9190 result = parse_bson_internal();
9191 break;
9192
9193 case input_format_t::cbor:
9194 result = parse_cbor_internal(true, tag_handler);
9195 break;
9196
9197 case input_format_t::msgpack:
9198 result = parse_msgpack_internal();
9199 break;
9200
9201 case input_format_t::ubjson:
9202 case input_format_t::bjdata:
9203 result = parse_ubjson_internal();
9204 break;
9205
9206 case input_format_t::json: // LCOV_EXCL_LINE
9207 default: // LCOV_EXCL_LINE
9208 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9209 }
9210
9211 // strict mode: next byte must be EOF
9212 if (result && strict)
9213 {
9214 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
9215 {
9216 get_ignore_noop();
9217 }
9218 else
9219 {
9220 get();
9221 }
9222
9223 if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char_type>::eof()))
9224 {
9225 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9226 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
9227 }
9228 }
9229
9230 return result;
9231 }
9232
9233 private:
9234 //////////
9235 // BSON //
9236 //////////
9237
9238 /*!
9239 @brief Reads in a BSON-object and passes it to the SAX-parser.
9240 @return whether a valid BSON-value was passed to the SAX parser
9241 */
9242 bool parse_bson_internal()
9243 {
9244 std::int32_t document_size{};
9245 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9246
9247 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
9248 {
9249 return false;
9250 }
9251
9252 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
9253 {
9254 return false;
9255 }
9256
9257 return sax->end_object();
9258 }
9259
9260 /*!
9261 @brief Parses a C-style string from the BSON input.
9262 @param[in,out] result A reference to the string variable where the read
9263 string is to be stored.
9264 @return `true` if the \x00-byte indicating the end of the string was
9265 encountered before the EOF; false` indicates an unexpected EOF.
9266 */
9267 bool get_bson_cstr(string_t& result)
9268 {
9269 auto out = std::back_inserter(result);
9270 while (true)
9271 {
9272 get();
9273 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
9274 {
9275 return false;
9276 }
9277 if (current == 0x00)
9278 {
9279 return true;
9280 }
9281 *out++ = static_cast<typename string_t::value_type>(current);
9282 }
9283 }
9284
9285 /*!
9286 @brief Parses a zero-terminated string of length @a len from the BSON
9287 input.
9288 @param[in] len The length (including the zero-byte at the end) of the
9289 string to be read.
9290 @param[in,out] result A reference to the string variable where the read
9291 string is to be stored.
9292 @tparam NumberType The type of the length @a len
9293 @pre len >= 1
9294 @return `true` if the string was successfully parsed
9295 */
9296 template<typename NumberType>
9297 bool get_bson_string(const NumberType len, string_t& result)
9298 {
9299 if (JSON_HEDLEY_UNLIKELY(len < 1))
9300 {
9301 auto last_token = get_token_string();
9302 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9303 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
9304 }
9305
9306 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != std::char_traits<char_type>::eof();
9307 }
9308
9309 /*!
9310 @brief Parses a byte array input of length @a len from the BSON input.
9311 @param[in] len The length of the byte array to be read.
9312 @param[in,out] result A reference to the binary variable where the read
9313 array is to be stored.
9314 @tparam NumberType The type of the length @a len
9315 @pre len >= 0
9316 @return `true` if the byte array was successfully parsed
9317 */
9318 template<typename NumberType>
9319 bool get_bson_binary(const NumberType len, binary_t& result)
9320 {
9321 if (JSON_HEDLEY_UNLIKELY(len < 0))
9322 {
9323 auto last_token = get_token_string();
9324 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9325 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
9326 }
9327
9328 // All BSON binary values have a subtype
9329 std::uint8_t subtype{};
9330 get_number<std::uint8_t>(input_format_t::bson, subtype);
9331 result.set_subtype(subtype);
9332
9333 return get_binary(input_format_t::bson, len, result);
9334 }
9335
9336 /*!
9337 @brief Read a BSON document element of the given @a element_type.
9338 @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
9339 @param[in] element_type_parse_position The position in the input stream,
9340 where the `element_type` was read.
9341 @warning Not all BSON element types are supported yet. An unsupported
9342 @a element_type will give rise to a parse_error.114:
9343 Unsupported BSON record type 0x...
9344 @return whether a valid BSON-object/array was passed to the SAX parser
9345 */
9346 bool parse_bson_element_internal(const char_int_type element_type,
9347 const std::size_t element_type_parse_position)
9348 {
9349 switch (element_type)
9350 {
9351 case 0x01: // double
9352 {
9353 double number{};
9354 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
9355 }
9356
9357 case 0x02: // string
9358 {
9359 std::int32_t len{};
9360 string_t value;
9361 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
9362 }
9363
9364 case 0x03: // object
9365 {
9366 return parse_bson_internal();
9367 }
9368
9369 case 0x04: // array
9370 {
9371 return parse_bson_array();
9372 }
9373
9374 case 0x05: // binary
9375 {
9376 std::int32_t len{};
9377 binary_t value;
9378 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
9379 }
9380
9381 case 0x08: // boolean
9382 {
9383 return sax->boolean(get() != 0);
9384 }
9385
9386 case 0x0A: // null
9387 {
9388 return sax->null();
9389 }
9390
9391 case 0x10: // int32
9392 {
9393 std::int32_t value{};
9394 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9395 }
9396
9397 case 0x12: // int64
9398 {
9399 std::int64_t value{};
9400 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9401 }
9402
9403 default: // anything else not supported (yet)
9404 {
9405 std::array<char, 3> cr{{}};
9406 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
9407 std::string cr_str{cr.data()};
9408 return sax->parse_error(element_type_parse_position, cr_str,
9409 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
9410 }
9411 }
9412 }
9413
9414 /*!
9415 @brief Read a BSON element list (as specified in the BSON-spec)
9416
9417 The same binary layout is used for objects and arrays, hence it must be
9418 indicated with the argument @a is_array which one is expected
9419 (true --> array, false --> object).
9420
9421 @param[in] is_array Determines if the element list being read is to be
9422 treated as an object (@a is_array == false), or as an
9423 array (@a is_array == true).
9424 @return whether a valid BSON-object/array was passed to the SAX parser
9425 */
9426 bool parse_bson_element_list(const bool is_array)
9427 {
9428 string_t key;
9429
9430 while (auto element_type = get())
9431 {
9432 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
9433 {
9434 return false;
9435 }
9436
9437 const std::size_t element_type_parse_position = chars_read;
9438 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
9439 {
9440 return false;
9441 }
9442
9443 if (!is_array && !sax->key(key))
9444 {
9445 return false;
9446 }
9447
9448 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
9449 {
9450 return false;
9451 }
9452
9453 // get_bson_cstr only appends
9454 key.clear();
9455 }
9456
9457 return true;
9458 }
9459
9460 /*!
9461 @brief Reads an array from the BSON input and passes it to the SAX-parser.
9462 @return whether a valid BSON-array was passed to the SAX parser
9463 */
9464 bool parse_bson_array()
9465 {
9466 std::int32_t document_size{};
9467 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9468
9469 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
9470 {
9471 return false;
9472 }
9473
9474 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
9475 {
9476 return false;
9477 }
9478
9479 return sax->end_array();
9480 }
9481
9482 //////////
9483 // CBOR //
9484 //////////
9485
9486 /*!
9487 @param[in] get_char whether a new character should be retrieved from the
9488 input (true) or whether the last read character should
9489 be considered instead (false)
9490 @param[in] tag_handler how CBOR tags should be treated
9491
9492 @return whether a valid CBOR value was passed to the SAX parser
9493 */
9494 bool parse_cbor_internal(const bool get_char,
9495 const cbor_tag_handler_t tag_handler)
9496 {
9497 switch (get_char ? get() : current)
9498 {
9499 // EOF
9500 case std::char_traits<char_type>::eof():
9501 return unexpect_eof(input_format_t::cbor, "value");
9502
9503 // Integer 0x00..0x17 (0..23)
9504 case 0x00:
9505 case 0x01:
9506 case 0x02:
9507 case 0x03:
9508 case 0x04:
9509 case 0x05:
9510 case 0x06:
9511 case 0x07:
9512 case 0x08:
9513 case 0x09:
9514 case 0x0A:
9515 case 0x0B:
9516 case 0x0C:
9517 case 0x0D:
9518 case 0x0E:
9519 case 0x0F:
9520 case 0x10:
9521 case 0x11:
9522 case 0x12:
9523 case 0x13:
9524 case 0x14:
9525 case 0x15:
9526 case 0x16:
9527 case 0x17:
9528 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
9529
9530 case 0x18: // Unsigned integer (one-byte uint8_t follows)
9531 {
9532 std::uint8_t number{};
9533 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9534 }
9535
9536 case 0x19: // Unsigned integer (two-byte uint16_t follows)
9537 {
9538 std::uint16_t number{};
9539 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9540 }
9541
9542 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
9543 {
9544 std::uint32_t number{};
9545 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9546 }
9547
9548 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
9549 {
9550 std::uint64_t number{};
9551 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9552 }
9553
9554 // Negative integer -1-0x00..-1-0x17 (-1..-24)
9555 case 0x20:
9556 case 0x21:
9557 case 0x22:
9558 case 0x23:
9559 case 0x24:
9560 case 0x25:
9561 case 0x26:
9562 case 0x27:
9563 case 0x28:
9564 case 0x29:
9565 case 0x2A:
9566 case 0x2B:
9567 case 0x2C:
9568 case 0x2D:
9569 case 0x2E:
9570 case 0x2F:
9571 case 0x30:
9572 case 0x31:
9573 case 0x32:
9574 case 0x33:
9575 case 0x34:
9576 case 0x35:
9577 case 0x36:
9578 case 0x37:
9579 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
9580
9581 case 0x38: // Negative integer (one-byte uint8_t follows)
9582 {
9583 std::uint8_t number{};
9584 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9585 }
9586
9587 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
9588 {
9589 std::uint16_t number{};
9590 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9591 }
9592
9593 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
9594 {
9595 std::uint32_t number{};
9596 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9597 }
9598
9599 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
9600 {
9601 std::uint64_t number{};
9602 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
9603 - static_cast<number_integer_t>(number));
9604 }
9605
9606 // Binary data (0x00..0x17 bytes follow)
9607 case 0x40:
9608 case 0x41:
9609 case 0x42:
9610 case 0x43:
9611 case 0x44:
9612 case 0x45:
9613 case 0x46:
9614 case 0x47:
9615 case 0x48:
9616 case 0x49:
9617 case 0x4A:
9618 case 0x4B:
9619 case 0x4C:
9620 case 0x4D:
9621 case 0x4E:
9622 case 0x4F:
9623 case 0x50:
9624 case 0x51:
9625 case 0x52:
9626 case 0x53:
9627 case 0x54:
9628 case 0x55:
9629 case 0x56:
9630 case 0x57:
9631 case 0x58: // Binary data (one-byte uint8_t for n follows)
9632 case 0x59: // Binary data (two-byte uint16_t for n follow)
9633 case 0x5A: // Binary data (four-byte uint32_t for n follow)
9634 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9635 case 0x5F: // Binary data (indefinite length)
9636 {
9637 binary_t b;
9638 return get_cbor_binary(b) && sax->binary(b);
9639 }
9640
9641 // UTF-8 string (0x00..0x17 bytes follow)
9642 case 0x60:
9643 case 0x61:
9644 case 0x62:
9645 case 0x63:
9646 case 0x64:
9647 case 0x65:
9648 case 0x66:
9649 case 0x67:
9650 case 0x68:
9651 case 0x69:
9652 case 0x6A:
9653 case 0x6B:
9654 case 0x6C:
9655 case 0x6D:
9656 case 0x6E:
9657 case 0x6F:
9658 case 0x70:
9659 case 0x71:
9660 case 0x72:
9661 case 0x73:
9662 case 0x74:
9663 case 0x75:
9664 case 0x76:
9665 case 0x77:
9666 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9667 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9668 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9669 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9670 case 0x7F: // UTF-8 string (indefinite length)
9671 {
9672 string_t s;
9673 return get_cbor_string(s) && sax->string(s);
9674 }
9675
9676 // array (0x00..0x17 data items follow)
9677 case 0x80:
9678 case 0x81:
9679 case 0x82:
9680 case 0x83:
9681 case 0x84:
9682 case 0x85:
9683 case 0x86:
9684 case 0x87:
9685 case 0x88:
9686 case 0x89:
9687 case 0x8A:
9688 case 0x8B:
9689 case 0x8C:
9690 case 0x8D:
9691 case 0x8E:
9692 case 0x8F:
9693 case 0x90:
9694 case 0x91:
9695 case 0x92:
9696 case 0x93:
9697 case 0x94:
9698 case 0x95:
9699 case 0x96:
9700 case 0x97:
9701 return get_cbor_array(
9702 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9703
9704 case 0x98: // array (one-byte uint8_t for n follows)
9705 {
9706 std::uint8_t len{};
9707 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9708 }
9709
9710 case 0x99: // array (two-byte uint16_t for n follow)
9711 {
9712 std::uint16_t len{};
9713 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9714 }
9715
9716 case 0x9A: // array (four-byte uint32_t for n follow)
9717 {
9718 std::uint32_t len{};
9719 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9720 }
9721
9722 case 0x9B: // array (eight-byte uint64_t for n follow)
9723 {
9724 std::uint64_t len{};
9725 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9726 }
9727
9728 case 0x9F: // array (indefinite length)
9729 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
9730
9731 // map (0x00..0x17 pairs of data items follow)
9732 case 0xA0:
9733 case 0xA1:
9734 case 0xA2:
9735 case 0xA3:
9736 case 0xA4:
9737 case 0xA5:
9738 case 0xA6:
9739 case 0xA7:
9740 case 0xA8:
9741 case 0xA9:
9742 case 0xAA:
9743 case 0xAB:
9744 case 0xAC:
9745 case 0xAD:
9746 case 0xAE:
9747 case 0xAF:
9748 case 0xB0:
9749 case 0xB1:
9750 case 0xB2:
9751 case 0xB3:
9752 case 0xB4:
9753 case 0xB5:
9754 case 0xB6:
9755 case 0xB7:
9756 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9757
9758 case 0xB8: // map (one-byte uint8_t for n follows)
9759 {
9760 std::uint8_t len{};
9761 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9762 }
9763
9764 case 0xB9: // map (two-byte uint16_t for n follow)
9765 {
9766 std::uint16_t len{};
9767 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9768 }
9769
9770 case 0xBA: // map (four-byte uint32_t for n follow)
9771 {
9772 std::uint32_t len{};
9773 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9774 }
9775
9776 case 0xBB: // map (eight-byte uint64_t for n follow)
9777 {
9778 std::uint64_t len{};
9779 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9780 }
9781
9782 case 0xBF: // map (indefinite length)
9783 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
9784
9785 case 0xC6: // tagged item
9786 case 0xC7:
9787 case 0xC8:
9788 case 0xC9:
9789 case 0xCA:
9790 case 0xCB:
9791 case 0xCC:
9792 case 0xCD:
9793 case 0xCE:
9794 case 0xCF:
9795 case 0xD0:
9796 case 0xD1:
9797 case 0xD2:
9798 case 0xD3:
9799 case 0xD4:
9800 case 0xD8: // tagged item (1 bytes follow)
9801 case 0xD9: // tagged item (2 bytes follow)
9802 case 0xDA: // tagged item (4 bytes follow)
9803 case 0xDB: // tagged item (8 bytes follow)
9804 {
9805 switch (tag_handler)
9806 {
9807 case cbor_tag_handler_t::error:
9808 {
9809 auto last_token = get_token_string();
9810 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9811 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
9812 }
9813
9814 case cbor_tag_handler_t::ignore:
9815 {
9816 // ignore binary subtype
9817 switch (current)
9818 {
9819 case 0xD8:
9820 {
9821 std::uint8_t subtype_to_ignore{};
9822 get_number(input_format_t::cbor, subtype_to_ignore);
9823 break;
9824 }
9825 case 0xD9:
9826 {
9827 std::uint16_t subtype_to_ignore{};
9828 get_number(input_format_t::cbor, subtype_to_ignore);
9829 break;
9830 }
9831 case 0xDA:
9832 {
9833 std::uint32_t subtype_to_ignore{};
9834 get_number(input_format_t::cbor, subtype_to_ignore);
9835 break;
9836 }
9837 case 0xDB:
9838 {
9839 std::uint64_t subtype_to_ignore{};
9840 get_number(input_format_t::cbor, subtype_to_ignore);
9841 break;
9842 }
9843 default:
9844 break;
9845 }
9846 return parse_cbor_internal(true, tag_handler);
9847 }
9848
9849 case cbor_tag_handler_t::store:
9850 {
9851 binary_t b;
9852 // use binary subtype and store in binary container
9853 switch (current)
9854 {
9855 case 0xD8:
9856 {
9857 std::uint8_t subtype{};
9858 get_number(input_format_t::cbor, subtype);
9859 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9860 break;
9861 }
9862 case 0xD9:
9863 {
9864 std::uint16_t subtype{};
9865 get_number(input_format_t::cbor, subtype);
9866 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9867 break;
9868 }
9869 case 0xDA:
9870 {
9871 std::uint32_t subtype{};
9872 get_number(input_format_t::cbor, subtype);
9873 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9874 break;
9875 }
9876 case 0xDB:
9877 {
9878 std::uint64_t subtype{};
9879 get_number(input_format_t::cbor, subtype);
9880 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9881 break;
9882 }
9883 default:
9884 return parse_cbor_internal(true, tag_handler);
9885 }
9886 get();
9887 return get_cbor_binary(b) && sax->binary(b);
9888 }
9889
9890 default: // LCOV_EXCL_LINE
9891 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9892 return false; // LCOV_EXCL_LINE
9893 }
9894 }
9895
9896 case 0xF4: // false
9897 return sax->boolean(false);
9898
9899 case 0xF5: // true
9900 return sax->boolean(true);
9901
9902 case 0xF6: // null
9903 return sax->null();
9904
9905 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
9906 {
9907 const auto byte1_raw = get();
9908 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
9909 {
9910 return false;
9911 }
9912 const auto byte2_raw = get();
9913 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
9914 {
9915 return false;
9916 }
9917
9918 const auto byte1 = static_cast<unsigned char>(byte1_raw);
9919 const auto byte2 = static_cast<unsigned char>(byte2_raw);
9920
9921 // code from RFC 7049, Appendix D, Figure 3:
9922 // As half-precision floating-point numbers were only added
9923 // to IEEE 754 in 2008, today's programming platforms often
9924 // still only have limited support for them. It is very
9925 // easy to include at least decoding support for them even
9926 // without such support. An example of a small decoder for
9927 // half-precision floating-point numbers in the C language
9928 // is shown in Fig. 3.
9929 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
9930 const double val = [&half]
9931 {
9932 const int exp = (half >> 10u) & 0x1Fu;
9933 const unsigned int mant = half & 0x3FFu;
9934 JSON_ASSERT(0 <= exp&& exp <= 32);
9935 JSON_ASSERT(mant <= 1024);
9936 switch (exp)
9937 {
9938 case 0:
9939 return std::ldexp(mant, -24);
9940 case 31:
9941 return (mant == 0)
9942 ? std::numeric_limits<double>::infinity()
9943 : std::numeric_limits<double>::quiet_NaN();
9944 default:
9945 return std::ldexp(mant + 1024, exp - 25);
9946 }
9947 }();
9948 return sax->number_float((half & 0x8000u) != 0
9949 ? static_cast<number_float_t>(-val)
9950 : static_cast<number_float_t>(val), "");
9951 }
9952
9953 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
9954 {
9955 float number{};
9956 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
9957 }
9958
9959 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
9960 {
9961 double number{};
9962 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
9963 }
9964
9965 default: // anything else (0xFF is handled inside the other types)
9966 {
9967 auto last_token = get_token_string();
9968 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9969 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
9970 }
9971 }
9972 }
9973
9974 /*!
9975 @brief reads a CBOR string
9976
9977 This function first reads starting bytes to determine the expected
9978 string length and then copies this number of bytes into a string.
9979 Additionally, CBOR's strings with indefinite lengths are supported.
9980
9981 @param[out] result created string
9982
9983 @return whether string creation completed
9984 */
9985 bool get_cbor_string(string_t& result)
9986 {
9987 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
9988 {
9989 return false;
9990 }
9991
9992 switch (current)
9993 {
9994 // UTF-8 string (0x00..0x17 bytes follow)
9995 case 0x60:
9996 case 0x61:
9997 case 0x62:
9998 case 0x63:
9999 case 0x64:
10000 case 0x65:
10001 case 0x66:
10002 case 0x67:
10003 case 0x68:
10004 case 0x69:
10005 case 0x6A:
10006 case 0x6B:
10007 case 0x6C:
10008 case 0x6D:
10009 case 0x6E:
10010 case 0x6F:
10011 case 0x70:
10012 case 0x71:
10013 case 0x72:
10014 case 0x73:
10015 case 0x74:
10016 case 0x75:
10017 case 0x76:
10018 case 0x77:
10019 {
10020 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10021 }
10022
10023 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10024 {
10025 std::uint8_t len{};
10026 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10027 }
10028
10029 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10030 {
10031 std::uint16_t len{};
10032 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10033 }
10034
10035 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10036 {
10037 std::uint32_t len{};
10038 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10039 }
10040
10041 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10042 {
10043 std::uint64_t len{};
10044 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10045 }
10046
10047 case 0x7F: // UTF-8 string (indefinite length)
10048 {
10049 while (get() != 0xFF)
10050 {
10051 string_t chunk;
10052 if (!get_cbor_string(chunk))
10053 {
10054 return false;
10055 }
10056 result.append(chunk);
10057 }
10058 return true;
10059 }
10060
10061 default:
10062 {
10063 auto last_token = get_token_string();
10064 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10065 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10066 }
10067 }
10068 }
10069
10070 /*!
10071 @brief reads a CBOR byte array
10072
10073 This function first reads starting bytes to determine the expected
10074 byte array length and then copies this number of bytes into the byte array.
10075 Additionally, CBOR's byte arrays with indefinite lengths are supported.
10076
10077 @param[out] result created byte array
10078
10079 @return whether byte array creation completed
10080 */
10081 bool get_cbor_binary(binary_t& result)
10082 {
10083 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
10084 {
10085 return false;
10086 }
10087
10088 switch (current)
10089 {
10090 // Binary data (0x00..0x17 bytes follow)
10091 case 0x40:
10092 case 0x41:
10093 case 0x42:
10094 case 0x43:
10095 case 0x44:
10096 case 0x45:
10097 case 0x46:
10098 case 0x47:
10099 case 0x48:
10100 case 0x49:
10101 case 0x4A:
10102 case 0x4B:
10103 case 0x4C:
10104 case 0x4D:
10105 case 0x4E:
10106 case 0x4F:
10107 case 0x50:
10108 case 0x51:
10109 case 0x52:
10110 case 0x53:
10111 case 0x54:
10112 case 0x55:
10113 case 0x56:
10114 case 0x57:
10115 {
10116 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10117 }
10118
10119 case 0x58: // Binary data (one-byte uint8_t for n follows)
10120 {
10121 std::uint8_t len{};
10122 return get_number(input_format_t::cbor, len) &&
10123 get_binary(input_format_t::cbor, len, result);
10124 }
10125
10126 case 0x59: // Binary data (two-byte uint16_t for n follow)
10127 {
10128 std::uint16_t len{};
10129 return get_number(input_format_t::cbor, len) &&
10130 get_binary(input_format_t::cbor, len, result);
10131 }
10132
10133 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10134 {
10135 std::uint32_t len{};
10136 return get_number(input_format_t::cbor, len) &&
10137 get_binary(input_format_t::cbor, len, result);
10138 }
10139
10140 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10141 {
10142 std::uint64_t len{};
10143 return get_number(input_format_t::cbor, len) &&
10144 get_binary(input_format_t::cbor, len, result);
10145 }
10146
10147 case 0x5F: // Binary data (indefinite length)
10148 {
10149 while (get() != 0xFF)
10150 {
10151 binary_t chunk;
10152 if (!get_cbor_binary(chunk))
10153 {
10154 return false;
10155 }
10156 result.insert(result.end(), chunk.begin(), chunk.end());
10157 }
10158 return true;
10159 }
10160
10161 default:
10162 {
10163 auto last_token = get_token_string();
10164 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10165 exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr));
10166 }
10167 }
10168 }
10169
10170 /*!
10171 @param[in] len the length of the array or static_cast<std::size_t>(-1) for an
10172 array of indefinite size
10173 @param[in] tag_handler how CBOR tags should be treated
10174 @return whether array creation completed
10175 */
10176 bool get_cbor_array(const std::size_t len,
10177 const cbor_tag_handler_t tag_handler)
10178 {
10179 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10180 {
10181 return false;
10182 }
10183
10184 if (len != static_cast<std::size_t>(-1))
10185 {
10186 for (std::size_t i = 0; i < len; ++i)
10187 {
10188 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10189 {
10190 return false;
10191 }
10192 }
10193 }
10194 else
10195 {
10196 while (get() != 0xFF)
10197 {
10198 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
10199 {
10200 return false;
10201 }
10202 }
10203 }
10204
10205 return sax->end_array();
10206 }
10207
10208 /*!
10209 @param[in] len the length of the object or static_cast<std::size_t>(-1) for an
10210 object of indefinite size
10211 @param[in] tag_handler how CBOR tags should be treated
10212 @return whether object creation completed
10213 */
10214 bool get_cbor_object(const std::size_t len,
10215 const cbor_tag_handler_t tag_handler)
10216 {
10217 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10218 {
10219 return false;
10220 }
10221
10222 if (len != 0)
10223 {
10224 string_t key;
10225 if (len != static_cast<std::size_t>(-1))
10226 {
10227 for (std::size_t i = 0; i < len; ++i)
10228 {
10229 get();
10230 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10231 {
10232 return false;
10233 }
10234
10235 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10236 {
10237 return false;
10238 }
10239 key.clear();
10240 }
10241 }
10242 else
10243 {
10244 while (get() != 0xFF)
10245 {
10246 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10247 {
10248 return false;
10249 }
10250
10251 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10252 {
10253 return false;
10254 }
10255 key.clear();
10256 }
10257 }
10258 }
10259
10260 return sax->end_object();
10261 }
10262
10263 /////////////
10264 // MsgPack //
10265 /////////////
10266
10267 /*!
10268 @return whether a valid MessagePack value was passed to the SAX parser
10269 */
10270 bool parse_msgpack_internal()
10271 {
10272 switch (get())
10273 {
10274 // EOF
10275 case std::char_traits<char_type>::eof():
10276 return unexpect_eof(input_format_t::msgpack, "value");
10277
10278 // positive fixint
10279 case 0x00:
10280 case 0x01:
10281 case 0x02:
10282 case 0x03:
10283 case 0x04:
10284 case 0x05:
10285 case 0x06:
10286 case 0x07:
10287 case 0x08:
10288 case 0x09:
10289 case 0x0A:
10290 case 0x0B:
10291 case 0x0C:
10292 case 0x0D:
10293 case 0x0E:
10294 case 0x0F:
10295 case 0x10:
10296 case 0x11:
10297 case 0x12:
10298 case 0x13:
10299 case 0x14:
10300 case 0x15:
10301 case 0x16:
10302 case 0x17:
10303 case 0x18:
10304 case 0x19:
10305 case 0x1A:
10306 case 0x1B:
10307 case 0x1C:
10308 case 0x1D:
10309 case 0x1E:
10310 case 0x1F:
10311 case 0x20:
10312 case 0x21:
10313 case 0x22:
10314 case 0x23:
10315 case 0x24:
10316 case 0x25:
10317 case 0x26:
10318 case 0x27:
10319 case 0x28:
10320 case 0x29:
10321 case 0x2A:
10322 case 0x2B:
10323 case 0x2C:
10324 case 0x2D:
10325 case 0x2E:
10326 case 0x2F:
10327 case 0x30:
10328 case 0x31:
10329 case 0x32:
10330 case 0x33:
10331 case 0x34:
10332 case 0x35:
10333 case 0x36:
10334 case 0x37:
10335 case 0x38:
10336 case 0x39:
10337 case 0x3A:
10338 case 0x3B:
10339 case 0x3C:
10340 case 0x3D:
10341 case 0x3E:
10342 case 0x3F:
10343 case 0x40:
10344 case 0x41:
10345 case 0x42:
10346 case 0x43:
10347 case 0x44:
10348 case 0x45:
10349 case 0x46:
10350 case 0x47:
10351 case 0x48:
10352 case 0x49:
10353 case 0x4A:
10354 case 0x4B:
10355 case 0x4C:
10356 case 0x4D:
10357 case 0x4E:
10358 case 0x4F:
10359 case 0x50:
10360 case 0x51:
10361 case 0x52:
10362 case 0x53:
10363 case 0x54:
10364 case 0x55:
10365 case 0x56:
10366 case 0x57:
10367 case 0x58:
10368 case 0x59:
10369 case 0x5A:
10370 case 0x5B:
10371 case 0x5C:
10372 case 0x5D:
10373 case 0x5E:
10374 case 0x5F:
10375 case 0x60:
10376 case 0x61:
10377 case 0x62:
10378 case 0x63:
10379 case 0x64:
10380 case 0x65:
10381 case 0x66:
10382 case 0x67:
10383 case 0x68:
10384 case 0x69:
10385 case 0x6A:
10386 case 0x6B:
10387 case 0x6C:
10388 case 0x6D:
10389 case 0x6E:
10390 case 0x6F:
10391 case 0x70:
10392 case 0x71:
10393 case 0x72:
10394 case 0x73:
10395 case 0x74:
10396 case 0x75:
10397 case 0x76:
10398 case 0x77:
10399 case 0x78:
10400 case 0x79:
10401 case 0x7A:
10402 case 0x7B:
10403 case 0x7C:
10404 case 0x7D:
10405 case 0x7E:
10406 case 0x7F:
10407 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10408
10409 // fixmap
10410 case 0x80:
10411 case 0x81:
10412 case 0x82:
10413 case 0x83:
10414 case 0x84:
10415 case 0x85:
10416 case 0x86:
10417 case 0x87:
10418 case 0x88:
10419 case 0x89:
10420 case 0x8A:
10421 case 0x8B:
10422 case 0x8C:
10423 case 0x8D:
10424 case 0x8E:
10425 case 0x8F:
10426 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10427
10428 // fixarray
10429 case 0x90:
10430 case 0x91:
10431 case 0x92:
10432 case 0x93:
10433 case 0x94:
10434 case 0x95:
10435 case 0x96:
10436 case 0x97:
10437 case 0x98:
10438 case 0x99:
10439 case 0x9A:
10440 case 0x9B:
10441 case 0x9C:
10442 case 0x9D:
10443 case 0x9E:
10444 case 0x9F:
10445 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10446
10447 // fixstr
10448 case 0xA0:
10449 case 0xA1:
10450 case 0xA2:
10451 case 0xA3:
10452 case 0xA4:
10453 case 0xA5:
10454 case 0xA6:
10455 case 0xA7:
10456 case 0xA8:
10457 case 0xA9:
10458 case 0xAA:
10459 case 0xAB:
10460 case 0xAC:
10461 case 0xAD:
10462 case 0xAE:
10463 case 0xAF:
10464 case 0xB0:
10465 case 0xB1:
10466 case 0xB2:
10467 case 0xB3:
10468 case 0xB4:
10469 case 0xB5:
10470 case 0xB6:
10471 case 0xB7:
10472 case 0xB8:
10473 case 0xB9:
10474 case 0xBA:
10475 case 0xBB:
10476 case 0xBC:
10477 case 0xBD:
10478 case 0xBE:
10479 case 0xBF:
10480 case 0xD9: // str 8
10481 case 0xDA: // str 16
10482 case 0xDB: // str 32
10483 {
10484 string_t s;
10485 return get_msgpack_string(s) && sax->string(s);
10486 }
10487
10488 case 0xC0: // nil
10489 return sax->null();
10490
10491 case 0xC2: // false
10492 return sax->boolean(false);
10493
10494 case 0xC3: // true
10495 return sax->boolean(true);
10496
10497 case 0xC4: // bin 8
10498 case 0xC5: // bin 16
10499 case 0xC6: // bin 32
10500 case 0xC7: // ext 8
10501 case 0xC8: // ext 16
10502 case 0xC9: // ext 32
10503 case 0xD4: // fixext 1
10504 case 0xD5: // fixext 2
10505 case 0xD6: // fixext 4
10506 case 0xD7: // fixext 8
10507 case 0xD8: // fixext 16
10508 {
10509 binary_t b;
10510 return get_msgpack_binary(b) && sax->binary(b);
10511 }
10512
10513 case 0xCA: // float 32
10514 {
10515 float number{};
10516 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10517 }
10518
10519 case 0xCB: // float 64
10520 {
10521 double number{};
10522 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10523 }
10524
10525 case 0xCC: // uint 8
10526 {
10527 std::uint8_t number{};
10528 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10529 }
10530
10531 case 0xCD: // uint 16
10532 {
10533 std::uint16_t number{};
10534 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10535 }
10536
10537 case 0xCE: // uint 32
10538 {
10539 std::uint32_t number{};
10540 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10541 }
10542
10543 case 0xCF: // uint 64
10544 {
10545 std::uint64_t number{};
10546 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10547 }
10548
10549 case 0xD0: // int 8
10550 {
10551 std::int8_t number{};
10552 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10553 }
10554
10555 case 0xD1: // int 16
10556 {
10557 std::int16_t number{};
10558 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10559 }
10560
10561 case 0xD2: // int 32
10562 {
10563 std::int32_t number{};
10564 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10565 }
10566
10567 case 0xD3: // int 64
10568 {
10569 std::int64_t number{};
10570 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10571 }
10572
10573 case 0xDC: // array 16
10574 {
10575 std::uint16_t len{};
10576 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
10577 }
10578
10579 case 0xDD: // array 32
10580 {
10581 std::uint32_t len{};
10582 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
10583 }
10584
10585 case 0xDE: // map 16
10586 {
10587 std::uint16_t len{};
10588 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
10589 }
10590
10591 case 0xDF: // map 32
10592 {
10593 std::uint32_t len{};
10594 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
10595 }
10596
10597 // negative fixint
10598 case 0xE0:
10599 case 0xE1:
10600 case 0xE2:
10601 case 0xE3:
10602 case 0xE4:
10603 case 0xE5:
10604 case 0xE6:
10605 case 0xE7:
10606 case 0xE8:
10607 case 0xE9:
10608 case 0xEA:
10609 case 0xEB:
10610 case 0xEC:
10611 case 0xED:
10612 case 0xEE:
10613 case 0xEF:
10614 case 0xF0:
10615 case 0xF1:
10616 case 0xF2:
10617 case 0xF3:
10618 case 0xF4:
10619 case 0xF5:
10620 case 0xF6:
10621 case 0xF7:
10622 case 0xF8:
10623 case 0xF9:
10624 case 0xFA:
10625 case 0xFB:
10626 case 0xFC:
10627 case 0xFD:
10628 case 0xFE:
10629 case 0xFF:
10630 return sax->number_integer(static_cast<std::int8_t>(current));
10631
10632 default: // anything else
10633 {
10634 auto last_token = get_token_string();
10635 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10636 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
10637 }
10638 }
10639 }
10640
10641 /*!
10642 @brief reads a MessagePack string
10643
10644 This function first reads starting bytes to determine the expected
10645 string length and then copies this number of bytes into a string.
10646
10647 @param[out] result created string
10648
10649 @return whether string creation completed
10650 */
10651 bool get_msgpack_string(string_t& result)
10652 {
10653 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
10654 {
10655 return false;
10656 }
10657
10658 switch (current)
10659 {
10660 // fixstr
10661 case 0xA0:
10662 case 0xA1:
10663 case 0xA2:
10664 case 0xA3:
10665 case 0xA4:
10666 case 0xA5:
10667 case 0xA6:
10668 case 0xA7:
10669 case 0xA8:
10670 case 0xA9:
10671 case 0xAA:
10672 case 0xAB:
10673 case 0xAC:
10674 case 0xAD:
10675 case 0xAE:
10676 case 0xAF:
10677 case 0xB0:
10678 case 0xB1:
10679 case 0xB2:
10680 case 0xB3:
10681 case 0xB4:
10682 case 0xB5:
10683 case 0xB6:
10684 case 0xB7:
10685 case 0xB8:
10686 case 0xB9:
10687 case 0xBA:
10688 case 0xBB:
10689 case 0xBC:
10690 case 0xBD:
10691 case 0xBE:
10692 case 0xBF:
10693 {
10694 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
10695 }
10696
10697 case 0xD9: // str 8
10698 {
10699 std::uint8_t len{};
10700 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10701 }
10702
10703 case 0xDA: // str 16
10704 {
10705 std::uint16_t len{};
10706 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10707 }
10708
10709 case 0xDB: // str 32
10710 {
10711 std::uint32_t len{};
10712 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10713 }
10714
10715 default:
10716 {
10717 auto last_token = get_token_string();
10718 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10719 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
10720 }
10721 }
10722 }
10723
10724 /*!
10725 @brief reads a MessagePack byte array
10726
10727 This function first reads starting bytes to determine the expected
10728 byte array length and then copies this number of bytes into a byte array.
10729
10730 @param[out] result created byte array
10731
10732 @return whether byte array creation completed
10733 */
10734 bool get_msgpack_binary(binary_t& result)
10735 {
10736 // helper function to set the subtype
10737 auto assign_and_return_true = [&result](std::int8_t subtype)
10738 {
10739 result.set_subtype(static_cast<std::uint8_t>(subtype));
10740 return true;
10741 };
10742
10743 switch (current)
10744 {
10745 case 0xC4: // bin 8
10746 {
10747 std::uint8_t len{};
10748 return get_number(input_format_t::msgpack, len) &&
10749 get_binary(input_format_t::msgpack, len, result);
10750 }
10751
10752 case 0xC5: // bin 16
10753 {
10754 std::uint16_t len{};
10755 return get_number(input_format_t::msgpack, len) &&
10756 get_binary(input_format_t::msgpack, len, result);
10757 }
10758
10759 case 0xC6: // bin 32
10760 {
10761 std::uint32_t len{};
10762 return get_number(input_format_t::msgpack, len) &&
10763 get_binary(input_format_t::msgpack, len, result);
10764 }
10765
10766 case 0xC7: // ext 8
10767 {
10768 std::uint8_t len{};
10769 std::int8_t subtype{};
10770 return get_number(input_format_t::msgpack, len) &&
10771 get_number(input_format_t::msgpack, subtype) &&
10772 get_binary(input_format_t::msgpack, len, result) &&
10773 assign_and_return_true(subtype);
10774 }
10775
10776 case 0xC8: // ext 16
10777 {
10778 std::uint16_t len{};
10779 std::int8_t subtype{};
10780 return get_number(input_format_t::msgpack, len) &&
10781 get_number(input_format_t::msgpack, subtype) &&
10782 get_binary(input_format_t::msgpack, len, result) &&
10783 assign_and_return_true(subtype);
10784 }
10785
10786 case 0xC9: // ext 32
10787 {
10788 std::uint32_t len{};
10789 std::int8_t subtype{};
10790 return get_number(input_format_t::msgpack, len) &&
10791 get_number(input_format_t::msgpack, subtype) &&
10792 get_binary(input_format_t::msgpack, len, result) &&
10793 assign_and_return_true(subtype);
10794 }
10795
10796 case 0xD4: // fixext 1
10797 {
10798 std::int8_t subtype{};
10799 return get_number(input_format_t::msgpack, subtype) &&
10800 get_binary(input_format_t::msgpack, 1, result) &&
10801 assign_and_return_true(subtype);
10802 }
10803
10804 case 0xD5: // fixext 2
10805 {
10806 std::int8_t subtype{};
10807 return get_number(input_format_t::msgpack, subtype) &&
10808 get_binary(input_format_t::msgpack, 2, result) &&
10809 assign_and_return_true(subtype);
10810 }
10811
10812 case 0xD6: // fixext 4
10813 {
10814 std::int8_t subtype{};
10815 return get_number(input_format_t::msgpack, subtype) &&
10816 get_binary(input_format_t::msgpack, 4, result) &&
10817 assign_and_return_true(subtype);
10818 }
10819
10820 case 0xD7: // fixext 8
10821 {
10822 std::int8_t subtype{};
10823 return get_number(input_format_t::msgpack, subtype) &&
10824 get_binary(input_format_t::msgpack, 8, result) &&
10825 assign_and_return_true(subtype);
10826 }
10827
10828 case 0xD8: // fixext 16
10829 {
10830 std::int8_t subtype{};
10831 return get_number(input_format_t::msgpack, subtype) &&
10832 get_binary(input_format_t::msgpack, 16, result) &&
10833 assign_and_return_true(subtype);
10834 }
10835
10836 default: // LCOV_EXCL_LINE
10837 return false; // LCOV_EXCL_LINE
10838 }
10839 }
10840
10841 /*!
10842 @param[in] len the length of the array
10843 @return whether array creation completed
10844 */
10845 bool get_msgpack_array(const std::size_t len)
10846 {
10847 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10848 {
10849 return false;
10850 }
10851
10852 for (std::size_t i = 0; i < len; ++i)
10853 {
10854 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10855 {
10856 return false;
10857 }
10858 }
10859
10860 return sax->end_array();
10861 }
10862
10863 /*!
10864 @param[in] len the length of the object
10865 @return whether object creation completed
10866 */
10867 bool get_msgpack_object(const std::size_t len)
10868 {
10869 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10870 {
10871 return false;
10872 }
10873
10874 string_t key;
10875 for (std::size_t i = 0; i < len; ++i)
10876 {
10877 get();
10878 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
10879 {
10880 return false;
10881 }
10882
10883 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10884 {
10885 return false;
10886 }
10887 key.clear();
10888 }
10889
10890 return sax->end_object();
10891 }
10892
10893 ////////////
10894 // UBJSON //
10895 ////////////
10896
10897 /*!
10898 @param[in] get_char whether a new character should be retrieved from the
10899 input (true, default) or whether the last read
10900 character should be considered instead
10901
10902 @return whether a valid UBJSON value was passed to the SAX parser
10903 */
10904 bool parse_ubjson_internal(const bool get_char = true)
10905 {
10906 return get_ubjson_value(get_char ? get_ignore_noop() : current);
10907 }
10908
10909 /*!
10910 @brief reads a UBJSON string
10911
10912 This function is either called after reading the 'S' byte explicitly
10913 indicating a string, or in case of an object key where the 'S' byte can be
10914 left out.
10915
10916 @param[out] result created string
10917 @param[in] get_char whether a new character should be retrieved from the
10918 input (true, default) or whether the last read
10919 character should be considered instead
10920
10921 @return whether string creation completed
10922 */
10923 bool get_ubjson_string(string_t& result, const bool get_char = true)
10924 {
10925 if (get_char)
10926 {
10927 get(); // TODO(niels): may we ignore N here?
10928 }
10929
10930 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
10931 {
10932 return false;
10933 }
10934
10935 switch (current)
10936 {
10937 case 'U':
10938 {
10939 std::uint8_t len{};
10940 return get_number(input_format, len) && get_string(input_format, len, result);
10941 }
10942
10943 case 'i':
10944 {
10945 std::int8_t len{};
10946 return get_number(input_format, len) && get_string(input_format, len, result);
10947 }
10948
10949 case 'I':
10950 {
10951 std::int16_t len{};
10952 return get_number(input_format, len) && get_string(input_format, len, result);
10953 }
10954
10955 case 'l':
10956 {
10957 std::int32_t len{};
10958 return get_number(input_format, len) && get_string(input_format, len, result);
10959 }
10960
10961 case 'L':
10962 {
10963 std::int64_t len{};
10964 return get_number(input_format, len) && get_string(input_format, len, result);
10965 }
10966
10967 case 'u':
10968 {
10969 if (input_format != input_format_t::bjdata)
10970 {
10971 break;
10972 }
10973 std::uint16_t len{};
10974 return get_number(input_format, len) && get_string(input_format, len, result);
10975 }
10976
10977 case 'm':
10978 {
10979 if (input_format != input_format_t::bjdata)
10980 {
10981 break;
10982 }
10983 std::uint32_t len{};
10984 return get_number(input_format, len) && get_string(input_format, len, result);
10985 }
10986
10987 case 'M':
10988 {
10989 if (input_format != input_format_t::bjdata)
10990 {
10991 break;
10992 }
10993 std::uint64_t len{};
10994 return get_number(input_format, len) && get_string(input_format, len, result);
10995 }
10996
10997 default:
10998 break;
10999 }
11000 auto last_token = get_token_string();
11001 std::string message;
11002
11003 if (input_format != input_format_t::bjdata)
11004 {
11005 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11006 }
11007 else
11008 {
11009 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11010 }
11011 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11012 }
11013
11014 /*!
11015 @param[out] dim an integer vector storing the ND array dimensions
11016 @return whether reading ND array size vector is successful
11017 */
11018 bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
11019 {
11020 std::pair<std::size_t, char_int_type> size_and_type;
11021 size_t dimlen = 0;
11022 bool no_ndarray = true;
11023
11024 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11025 {
11026 return false;
11027 }
11028
11029 if (size_and_type.first != npos)
11030 {
11031 if (size_and_type.second != 0)
11032 {
11033 if (size_and_type.second != 'N')
11034 {
11035 for (std::size_t i = 0; i < size_and_type.first; ++i)
11036 {
11037 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11038 {
11039 return false;
11040 }
11041 dim.push_back(dimlen);
11042 }
11043 }
11044 }
11045 else
11046 {
11047 for (std::size_t i = 0; i < size_and_type.first; ++i)
11048 {
11049 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11050 {
11051 return false;
11052 }
11053 dim.push_back(dimlen);
11054 }
11055 }
11056 }
11057 else
11058 {
11059 while (current != ']')
11060 {
11061 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11062 {
11063 return false;
11064 }
11065 dim.push_back(dimlen);
11066 get_ignore_noop();
11067 }
11068 }
11069 return true;
11070 }
11071
11072 /*!
11073 @param[out] result determined size
11074 @param[in,out] is_ndarray for input, `true` means already inside an ndarray vector
11075 or ndarray dimension is not allowed; `false` means ndarray
11076 is allowed; for output, `true` means an ndarray is found;
11077 is_ndarray can only return `true` when its initial value
11078 is `false`
11079 @param[in] prefix type marker if already read, otherwise set to 0
11080
11081 @return whether size determination completed
11082 */
11083 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
11084 {
11085 if (prefix == 0)
11086 {
11087 prefix = get_ignore_noop();
11088 }
11089
11090 switch (prefix)
11091 {
11092 case 'U':
11093 {
11094 std::uint8_t number{};
11095 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11096 {
11097 return false;
11098 }
11099 result = static_cast<std::size_t>(number);
11100 return true;
11101 }
11102
11103 case 'i':
11104 {
11105 std::int8_t number{};
11106 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11107 {
11108 return false;
11109 }
11110 if (number < 0)
11111 {
11112 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11113 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11114 }
11115 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
11116 return true;
11117 }
11118
11119 case 'I':
11120 {
11121 std::int16_t number{};
11122 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11123 {
11124 return false;
11125 }
11126 if (number < 0)
11127 {
11128 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11129 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11130 }
11131 result = static_cast<std::size_t>(number);
11132 return true;
11133 }
11134
11135 case 'l':
11136 {
11137 std::int32_t number{};
11138 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11139 {
11140 return false;
11141 }
11142 if (number < 0)
11143 {
11144 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11145 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11146 }
11147 result = static_cast<std::size_t>(number);
11148 return true;
11149 }
11150
11151 case 'L':
11152 {
11153 std::int64_t number{};
11154 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11155 {
11156 return false;
11157 }
11158 if (number < 0)
11159 {
11160 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11161 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11162 }
11163 if (!value_in_range_of<std::size_t>(number))
11164 {
11165 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11166 exception_message(input_format, "integer value overflow", "size"), nullptr));
11167 }
11168 result = static_cast<std::size_t>(number);
11169 return true;
11170 }
11171
11172 case 'u':
11173 {
11174 if (input_format != input_format_t::bjdata)
11175 {
11176 break;
11177 }
11178 std::uint16_t number{};
11179 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11180 {
11181 return false;
11182 }
11183 result = static_cast<std::size_t>(number);
11184 return true;
11185 }
11186
11187 case 'm':
11188 {
11189 if (input_format != input_format_t::bjdata)
11190 {
11191 break;
11192 }
11193 std::uint32_t number{};
11194 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11195 {
11196 return false;
11197 }
11198 result = conditional_static_cast<std::size_t>(number);
11199 return true;
11200 }
11201
11202 case 'M':
11203 {
11204 if (input_format != input_format_t::bjdata)
11205 {
11206 break;
11207 }
11208 std::uint64_t number{};
11209 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11210 {
11211 return false;
11212 }
11213 if (!value_in_range_of<std::size_t>(number))
11214 {
11215 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11216 exception_message(input_format, "integer value overflow", "size"), nullptr));
11217 }
11218 result = detail::conditional_static_cast<std::size_t>(number);
11219 return true;
11220 }
11221
11222 case '[':
11223 {
11224 if (input_format != input_format_t::bjdata)
11225 {
11226 break;
11227 }
11228 if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array
11229 {
11230 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimentional vector is not allowed", "size"), nullptr));
11231 }
11232 std::vector<size_t> dim;
11233 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
11234 {
11235 return false;
11236 }
11237 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
11238 {
11239 result = dim.at(dim.size() - 1);
11240 return true;
11241 }
11242 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
11243 {
11244 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
11245 {
11246 if ( i == 0 )
11247 {
11248 result = 0;
11249 return true;
11250 }
11251 }
11252
11253 string_t key = "_ArraySize_";
11254 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
11255 {
11256 return false;
11257 }
11258 result = 1;
11259 for (auto i : dim)
11260 {
11261 result *= i;
11262 if (result == 0 || result == npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be npos as it is used to initialize size in get_ubjson_size_type()
11263 {
11264 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr));
11265 }
11266 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
11267 {
11268 return false;
11269 }
11270 }
11271 is_ndarray = true;
11272 return sax->end_array();
11273 }
11274 result = 0;
11275 return true;
11276 }
11277
11278 default:
11279 break;
11280 }
11281 auto last_token = get_token_string();
11282 std::string message;
11283
11284 if (input_format != input_format_t::bjdata)
11285 {
11286 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
11287 }
11288 else
11289 {
11290 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
11291 }
11292 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
11293 }
11294
11295 /*!
11296 @brief determine the type and size for a container
11297
11298 In the optimized UBJSON format, a type and a size can be provided to allow
11299 for a more compact representation.
11300
11301 @param[out] result pair of the size and the type
11302 @param[in] inside_ndarray whether the parser is parsing an ND array dimensional vector
11303
11304 @return whether pair creation completed
11305 */
11306 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
11307 {
11308 result.first = npos; // size
11309 result.second = 0; // type
11310 bool is_ndarray = false;
11311
11312 get_ignore_noop();
11313
11314 if (current == '$')
11315 {
11316 result.second = get(); // must not ignore 'N', because 'N' maybe the type
11317 if (input_format == input_format_t::bjdata
11318 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
11319 {
11320 auto last_token = get_token_string();
11321 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11322 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
11323 }
11324
11325 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
11326 {
11327 return false;
11328 }
11329
11330 get_ignore_noop();
11331 if (JSON_HEDLEY_UNLIKELY(current != '#'))
11332 {
11333 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11334 {
11335 return false;
11336 }
11337 auto last_token = get_token_string();
11338 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11339 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
11340 }
11341
11342 bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11343 if (input_format == input_format_t::bjdata && is_ndarray)
11344 {
11345 if (inside_ndarray)
11346 {
11347 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11348 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
11349 }
11350 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
11351 }
11352 return is_error;
11353 }
11354
11355 if (current == '#')
11356 {
11357 bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11358 if (input_format == input_format_t::bjdata && is_ndarray)
11359 {
11360 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11361 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
11362 }
11363 return is_error;
11364 }
11365
11366 return true;
11367 }
11368
11369 /*!
11370 @param prefix the previously read or set type prefix
11371 @return whether value creation completed
11372 */
11373 bool get_ubjson_value(const char_int_type prefix)
11374 {
11375 switch (prefix)
11376 {
11377 case std::char_traits<char_type>::eof(): // EOF
11378 return unexpect_eof(input_format, "value");
11379
11380 case 'T': // true
11381 return sax->boolean(true);
11382 case 'F': // false
11383 return sax->boolean(false);
11384
11385 case 'Z': // null
11386 return sax->null();
11387
11388 case 'U':
11389 {
11390 std::uint8_t number{};
11391 return get_number(input_format, number) && sax->number_unsigned(number);
11392 }
11393
11394 case 'i':
11395 {
11396 std::int8_t number{};
11397 return get_number(input_format, number) && sax->number_integer(number);
11398 }
11399
11400 case 'I':
11401 {
11402 std::int16_t number{};
11403 return get_number(input_format, number) && sax->number_integer(number);
11404 }
11405
11406 case 'l':
11407 {
11408 std::int32_t number{};
11409 return get_number(input_format, number) && sax->number_integer(number);
11410 }
11411
11412 case 'L':
11413 {
11414 std::int64_t number{};
11415 return get_number(input_format, number) && sax->number_integer(number);
11416 }
11417
11418 case 'u':
11419 {
11420 if (input_format != input_format_t::bjdata)
11421 {
11422 break;
11423 }
11424 std::uint16_t number{};
11425 return get_number(input_format, number) && sax->number_unsigned(number);
11426 }
11427
11428 case 'm':
11429 {
11430 if (input_format != input_format_t::bjdata)
11431 {
11432 break;
11433 }
11434 std::uint32_t number{};
11435 return get_number(input_format, number) && sax->number_unsigned(number);
11436 }
11437
11438 case 'M':
11439 {
11440 if (input_format != input_format_t::bjdata)
11441 {
11442 break;
11443 }
11444 std::uint64_t number{};
11445 return get_number(input_format, number) && sax->number_unsigned(number);
11446 }
11447
11448 case 'h':
11449 {
11450 if (input_format != input_format_t::bjdata)
11451 {
11452 break;
11453 }
11454 const auto byte1_raw = get();
11455 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11456 {
11457 return false;
11458 }
11459 const auto byte2_raw = get();
11460 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11461 {
11462 return false;
11463 }
11464
11465 const auto byte1 = static_cast<unsigned char>(byte1_raw);
11466 const auto byte2 = static_cast<unsigned char>(byte2_raw);
11467
11468 // code from RFC 7049, Appendix D, Figure 3:
11469 // As half-precision floating-point numbers were only added
11470 // to IEEE 754 in 2008, today's programming platforms often
11471 // still only have limited support for them. It is very
11472 // easy to include at least decoding support for them even
11473 // without such support. An example of a small decoder for
11474 // half-precision floating-point numbers in the C language
11475 // is shown in Fig. 3.
11476 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
11477 const double val = [&half]
11478 {
11479 const int exp = (half >> 10u) & 0x1Fu;
11480 const unsigned int mant = half & 0x3FFu;
11481 JSON_ASSERT(0 <= exp&& exp <= 32);
11482 JSON_ASSERT(mant <= 1024);
11483 switch (exp)
11484 {
11485 case 0:
11486 return std::ldexp(mant, -24);
11487 case 31:
11488 return (mant == 0)
11489 ? std::numeric_limits<double>::infinity()
11490 : std::numeric_limits<double>::quiet_NaN();
11491 default:
11492 return std::ldexp(mant + 1024, exp - 25);
11493 }
11494 }();
11495 return sax->number_float((half & 0x8000u) != 0
11496 ? static_cast<number_float_t>(-val)
11497 : static_cast<number_float_t>(val), "");
11498 }
11499
11500 case 'd':
11501 {
11502 float number{};
11503 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11504 }
11505
11506 case 'D':
11507 {
11508 double number{};
11509 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11510 }
11511
11512 case 'H':
11513 {
11514 return get_ubjson_high_precision_number();
11515 }
11516
11517 case 'C': // char
11518 {
11519 get();
11520 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
11521 {
11522 return false;
11523 }
11524 if (JSON_HEDLEY_UNLIKELY(current > 127))
11525 {
11526 auto last_token = get_token_string();
11527 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11528 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
11529 }
11530 string_t s(1, static_cast<typename string_t::value_type>(current));
11531 return sax->string(s);
11532 }
11533
11534 case 'S': // string
11535 {
11536 string_t s;
11537 return get_ubjson_string(s) && sax->string(s);
11538 }
11539
11540 case '[': // array
11541 return get_ubjson_array();
11542
11543 case '{': // object
11544 return get_ubjson_object();
11545
11546 default: // anything else
11547 break;
11548 }
11549 auto last_token = get_token_string();
11550 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr));
11551 }
11552
11553 /*!
11554 @return whether array creation completed
11555 */
11556 bool get_ubjson_array()
11557 {
11558 std::pair<std::size_t, char_int_type> size_and_type;
11559 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11560 {
11561 return false;
11562 }
11563
11564 // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata):
11565 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
11566
11567 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11568 {
11569 size_and_type.second &= ~(static_cast<char_int_type>(1) << 8); // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker
11570 auto it = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, [](const bjd_type & p, char_int_type t)
11571 {
11572 return p.first < t;
11573 });
11574 string_t key = "_ArrayType_";
11575 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
11576 {
11577 auto last_token = get_token_string();
11578 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11579 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
11580 }
11581
11582 string_t type = it->second; // sax->string() takes a reference
11583 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
11584 {
11585 return false;
11586 }
11587
11588 if (size_and_type.second == 'C')
11589 {
11590 size_and_type.second = 'U';
11591 }
11592
11593 key = "_ArrayData_";
11594 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
11595 {
11596 return false;
11597 }
11598
11599 for (std::size_t i = 0; i < size_and_type.first; ++i)
11600 {
11601 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11602 {
11603 return false;
11604 }
11605 }
11606
11607 return (sax->end_array() && sax->end_object());
11608 }
11609
11610 if (size_and_type.first != npos)
11611 {
11612 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
11613 {
11614 return false;
11615 }
11616
11617 if (size_and_type.second != 0)
11618 {
11619 if (size_and_type.second != 'N')
11620 {
11621 for (std::size_t i = 0; i < size_and_type.first; ++i)
11622 {
11623 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11624 {
11625 return false;
11626 }
11627 }
11628 }
11629 }
11630 else
11631 {
11632 for (std::size_t i = 0; i < size_and_type.first; ++i)
11633 {
11634 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11635 {
11636 return false;
11637 }
11638 }
11639 }
11640 }
11641 else
11642 {
11643 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
11644 {
11645 return false;
11646 }
11647
11648 while (current != ']')
11649 {
11650 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
11651 {
11652 return false;
11653 }
11654 get_ignore_noop();
11655 }
11656 }
11657
11658 return sax->end_array();
11659 }
11660
11661 /*!
11662 @return whether object creation completed
11663 */
11664 bool get_ubjson_object()
11665 {
11666 std::pair<std::size_t, char_int_type> size_and_type;
11667 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11668 {
11669 return false;
11670 }
11671
11672 // do not accept ND-array size in objects in BJData
11673 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11674 {
11675 auto last_token = get_token_string();
11676 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11677 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
11678 }
11679
11680 string_t key;
11681 if (size_and_type.first != npos)
11682 {
11683 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
11684 {
11685 return false;
11686 }
11687
11688 if (size_and_type.second != 0)
11689 {
11690 for (std::size_t i = 0; i < size_and_type.first; ++i)
11691 {
11692 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11693 {
11694 return false;
11695 }
11696 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11697 {
11698 return false;
11699 }
11700 key.clear();
11701 }
11702 }
11703 else
11704 {
11705 for (std::size_t i = 0; i < size_and_type.first; ++i)
11706 {
11707 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11708 {
11709 return false;
11710 }
11711 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11712 {
11713 return false;
11714 }
11715 key.clear();
11716 }
11717 }
11718 }
11719 else
11720 {
11721 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
11722 {
11723 return false;
11724 }
11725
11726 while (current != '}')
11727 {
11728 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
11729 {
11730 return false;
11731 }
11732 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11733 {
11734 return false;
11735 }
11736 get_ignore_noop();
11737 key.clear();
11738 }
11739 }
11740
11741 return sax->end_object();
11742 }
11743
11744 // Note, no reader for UBJSON binary types is implemented because they do
11745 // not exist
11746
11747 bool get_ubjson_high_precision_number()
11748 {
11749 // get size of following number string
11750 std::size_t size{};
11751 bool no_ndarray = true;
11752 auto res = get_ubjson_size_value(size, no_ndarray);
11753 if (JSON_HEDLEY_UNLIKELY(!res))
11754 {
11755 return res;
11756 }
11757
11758 // get number string
11759 std::vector<char> number_vector;
11760 for (std::size_t i = 0; i < size; ++i)
11761 {
11762 get();
11763 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11764 {
11765 return false;
11766 }
11767 number_vector.push_back(static_cast<char>(current));
11768 }
11769
11770 // parse number string
11771 using ia_type = decltype(detail::input_adapter(number_vector));
11772 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
11773 const auto result_number = number_lexer.scan();
11774 const auto number_string = number_lexer.get_token_string();
11775 const auto result_remainder = number_lexer.scan();
11776
11777 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
11778
11779 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
11780 {
11781 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11782 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11783 }
11784
11785 switch (result_number)
11786 {
11787 case token_type::value_integer:
11788 return sax->number_integer(number_lexer.get_number_integer());
11789 case token_type::value_unsigned:
11790 return sax->number_unsigned(number_lexer.get_number_unsigned());
11791 case token_type::value_float:
11792 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
11793 case token_type::uninitialized:
11794 case token_type::literal_true:
11795 case token_type::literal_false:
11796 case token_type::literal_null:
11797 case token_type::value_string:
11798 case token_type::begin_array:
11799 case token_type::begin_object:
11800 case token_type::end_array:
11801 case token_type::end_object:
11802 case token_type::name_separator:
11803 case token_type::value_separator:
11804 case token_type::parse_error:
11805 case token_type::end_of_input:
11806 case token_type::literal_or_value:
11807 default:
11808 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11809 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11810 }
11811 }
11812
11813 ///////////////////////
11814 // Utility functions //
11815 ///////////////////////
11816
11817 /*!
11818 @brief get next character from the input
11819
11820 This function provides the interface to the used input adapter. It does
11821 not throw in case the input reached EOF, but returns a -'ve valued
11822 `std::char_traits<char_type>::eof()` in that case.
11823
11824 @return character read from the input
11825 */
11826 char_int_type get()
11827 {
11828 ++chars_read;
11829 return current = ia.get_character();
11830 }
11831
11832 /*!
11833 @return character read from the input after ignoring all 'N' entries
11834 */
11835 char_int_type get_ignore_noop()
11836 {
11837 do
11838 {
11839 get();
11840 }
11841 while (current == 'N');
11842
11843 return current;
11844 }
11845
11846 /*
11847 @brief read a number from the input
11848
11849 @tparam NumberType the type of the number
11850 @param[in] format the current format (for diagnostics)
11851 @param[out] result number of type @a NumberType
11852
11853 @return whether conversion completed
11854
11855 @note This function needs to respect the system's endianness, because
11856 bytes in CBOR, MessagePack, and UBJSON are stored in network order
11857 (big endian) and therefore need reordering on little endian systems.
11858 On the other hand, BSON and BJData use little endian and should reorder
11859 on big endian systems.
11860 */
11861 template<typename NumberType, bool InputIsLittleEndian = false>
11862 bool get_number(const input_format_t format, NumberType& result)
11863 {
11864 // step 1: read input into array with system's byte order
11865 std::array<std::uint8_t, sizeof(NumberType)> vec{};
11866 for (std::size_t i = 0; i < sizeof(NumberType); ++i)
11867 {
11868 get();
11869 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
11870 {
11871 return false;
11872 }
11873
11874 // reverse byte order prior to conversion if necessary
11875 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
11876 {
11877 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
11878 }
11879 else
11880 {
11881 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
11882 }
11883 }
11884
11885 // step 2: convert array into number of type T and return
11886 std::memcpy(&result, vec.data(), sizeof(NumberType));
11887 return true;
11888 }
11889
11890 /*!
11891 @brief create a string by reading characters from the input
11892
11893 @tparam NumberType the type of the number
11894 @param[in] format the current format (for diagnostics)
11895 @param[in] len number of characters to read
11896 @param[out] result string created by reading @a len bytes
11897
11898 @return whether string creation completed
11899
11900 @note We can not reserve @a len bytes for the result, because @a len
11901 may be too large. Usually, @ref unexpect_eof() detects the end of
11902 the input before we run out of string memory.
11903 */
11904 template<typename NumberType>
11905 bool get_string(const input_format_t format,
11906 const NumberType len,
11907 string_t& result)
11908 {
11909 bool success = true;
11910 for (NumberType i = 0; i < len; i++)
11911 {
11912 get();
11913 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
11914 {
11915 success = false;
11916 break;
11917 }
11918 result.push_back(static_cast<typename string_t::value_type>(current));
11919 }
11920 return success;
11921 }
11922
11923 /*!
11924 @brief create a byte array by reading bytes from the input
11925
11926 @tparam NumberType the type of the number
11927 @param[in] format the current format (for diagnostics)
11928 @param[in] len number of bytes to read
11929 @param[out] result byte array created by reading @a len bytes
11930
11931 @return whether byte array creation completed
11932
11933 @note We can not reserve @a len bytes for the result, because @a len
11934 may be too large. Usually, @ref unexpect_eof() detects the end of
11935 the input before we run out of memory.
11936 */
11937 template<typename NumberType>
11938 bool get_binary(const input_format_t format,
11939 const NumberType len,
11940 binary_t& result)
11941 {
11942 bool success = true;
11943 for (NumberType i = 0; i < len; i++)
11944 {
11945 get();
11946 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
11947 {
11948 success = false;
11949 break;
11950 }
11951 result.push_back(static_cast<std::uint8_t>(current));
11952 }
11953 return success;
11954 }
11955
11956 /*!
11957 @param[in] format the current format (for diagnostics)
11958 @param[in] context further context information (for diagnostics)
11959 @return whether the last read character is not EOF
11960 */
11961 JSON_HEDLEY_NON_NULL(3)
11962 bool unexpect_eof(const input_format_t format, const char* context) const
11963 {
11964 if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char_type>::eof()))
11965 {
11966 return sax->parse_error(chars_read, "<end of file>",
11967 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
11968 }
11969 return true;
11970 }
11971
11972 /*!
11973 @return a string representation of the last read byte
11974 */
11975 std::string get_token_string() const
11976 {
11977 std::array<char, 3> cr{{}};
11978 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
11979 return std::string{cr.data()};
11980 }
11981
11982 /*!
11983 @param[in] format the current format
11984 @param[in] detail a detailed error message
11985 @param[in] context further context information
11986 @return a message string to use in the parse_error exceptions
11987 */
11988 std::string exception_message(const input_format_t format,
11989 const std::string& detail,
11990 const std::string& context) const
11991 {
11992 std::string error_msg = "syntax error while parsing ";
11993
11994 switch (format)
11995 {
11996 case input_format_t::cbor:
11997 error_msg += "CBOR";
11998 break;
11999
12000 case input_format_t::msgpack:
12001 error_msg += "MessagePack";
12002 break;
12003
12004 case input_format_t::ubjson:
12005 error_msg += "UBJSON";
12006 break;
12007
12008 case input_format_t::bson:
12009 error_msg += "BSON";
12010 break;
12011
12012 case input_format_t::bjdata:
12013 error_msg += "BJData";
12014 break;
12015
12016 case input_format_t::json: // LCOV_EXCL_LINE
12017 default: // LCOV_EXCL_LINE
12018 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12019 }
12020
12021 return concat(error_msg, ' ', context, ": ", detail);
12022 }
12023
12024 private:
12025 static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast<std::size_t>(-1);
12026
12027 /// input adapter
12028 InputAdapterType ia;
12029
12030 /// the current character
12031 char_int_type current = std::char_traits<char_type>::eof();
12032
12033 /// the number of characters read
12034 std::size_t chars_read = 0;
12035
12036 /// whether we can assume little endianness
12037 const bool is_little_endian = little_endianness();
12038
12039 /// input format
12040 const input_format_t input_format = input_format_t::json;
12041
12042 /// the SAX parser
12043 json_sax_t* sax = nullptr;
12044
12045 // excluded markers in bjdata optimized type
12046#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12047 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12048
12049#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12050 make_array<bjd_type>( \
12051 bjd_type{'C', "char"}, \
12052 bjd_type{'D', "double"}, \
12053 bjd_type{'I', "int16"}, \
12054 bjd_type{'L', "int64"}, \
12055 bjd_type{'M', "uint64"}, \
12056 bjd_type{'U', "uint8"}, \
12057 bjd_type{'d', "single"}, \
12058 bjd_type{'i', "int8"}, \
12059 bjd_type{'l', "int32"}, \
12060 bjd_type{'m', "uint32"}, \
12061 bjd_type{'u', "uint16"})
12062
12063 JSON_PRIVATE_UNLESS_TESTED:
12064 // lookup tables
12065 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12066 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12067 JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_;
12068
12069 using bjd_type = std::pair<char_int_type, string_t>;
12070 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12071 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12072 JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_;
12073
12074#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12075#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12076};
12077
12078#ifndef JSON_HAS_CPP_17
12079 template<typename BasicJsonType, typename InputAdapterType, typename SAX>
12080 constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
12081#endif
12082
12083} // namespace detail
12084NLOHMANN_JSON_NAMESPACE_END
12085
12086// #include <nlohmann/detail/input/input_adapters.hpp>
12087
12088// #include <nlohmann/detail/input/lexer.hpp>
12089
12090// #include <nlohmann/detail/input/parser.hpp>
12091// __ _____ _____ _____
12092// __| | __| | | | JSON for Modern C++
12093// | | |__ | | | | | | version 3.11.2
12094// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12095//
12096// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
12097// SPDX-License-Identifier: MIT
12098
12099
12100
12101#include <cmath> // isfinite
12102#include <cstdint> // uint8_t
12103#include <functional> // function
12104#include <string> // string
12105#include <utility> // move
12106#include <vector> // vector
12107
12108// #include <nlohmann/detail/exceptions.hpp>
12109
12110// #include <nlohmann/detail/input/input_adapters.hpp>
12111
12112// #include <nlohmann/detail/input/json_sax.hpp>
12113
12114// #include <nlohmann/detail/input/lexer.hpp>
12115
12116// #include <nlohmann/detail/macro_scope.hpp>
12117
12118// #include <nlohmann/detail/meta/is_sax.hpp>
12119
12120// #include <nlohmann/detail/string_concat.hpp>
12121
12122// #include <nlohmann/detail/value_t.hpp>
12123
12124
12125NLOHMANN_JSON_NAMESPACE_BEGIN
12126namespace detail
12127{
12128////////////
12129// parser //
12130////////////
12131
12132enum class parse_event_t : std::uint8_t
12133{
12134 /// the parser read `{` and started to process a JSON object
12135 object_start,
12136 /// the parser read `}` and finished processing a JSON object
12137 object_end,
12138 /// the parser read `[` and started to process a JSON array
12139 array_start,
12140 /// the parser read `]` and finished processing a JSON array
12141 array_end,
12142 /// the parser read a key of a value in an object
12143 key,
12144 /// the parser finished reading a JSON value
12145 value
12146};
12147
12148template<typename BasicJsonType>
12149using parser_callback_t =
12150 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
12151
12152/*!
12153@brief syntax analysis
12154
12155This class implements a recursive descent parser.
12156*/
12157template<typename BasicJsonType, typename InputAdapterType>
12158class parser
12159{
12160 using number_integer_t = typename BasicJsonType::number_integer_t;
12161 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12162 using number_float_t = typename BasicJsonType::number_float_t;
12163 using string_t = typename BasicJsonType::string_t;
12164 using lexer_t = lexer<BasicJsonType, InputAdapterType>;
12165 using token_type = typename lexer_t::token_type;
12166
12167 public:
12168 /// a parser reading from an input adapter
12169 explicit parser(InputAdapterType&& adapter,
12170 const parser_callback_t<BasicJsonType> cb = nullptr,
12171 const bool allow_exceptions_ = true,
12172 const bool skip_comments = false)
12173 : callback(cb)
12174 , m_lexer(std::move(adapter), skip_comments)
12175 , allow_exceptions(allow_exceptions_)
12176 {
12177 // read first token
12178 get_token();
12179 }
12180
12181 /*!
12182 @brief public parser interface
12183
12184 @param[in] strict whether to expect the last token to be EOF
12185 @param[in,out] result parsed JSON value
12186
12187 @throw parse_error.101 in case of an unexpected token
12188 @throw parse_error.102 if to_unicode fails or surrogate error
12189 @throw parse_error.103 if to_unicode fails
12190 */
12191 void parse(const bool strict, BasicJsonType& result)
12192 {
12193 if (callback)
12194 {
12195 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
12196 sax_parse_internal(&sdp);
12197
12198 // in strict mode, input must be completely read
12199 if (strict && (get_token() != token_type::end_of_input))
12200 {
12201 sdp.parse_error(m_lexer.get_position(),
12202 m_lexer.get_token_string(),
12203 parse_error::create(101, m_lexer.get_position(),
12204 exception_message(token_type::end_of_input, "value"), nullptr));
12205 }
12206
12207 // in case of an error, return discarded value
12208 if (sdp.is_errored())
12209 {
12210 result = value_t::discarded;
12211 return;
12212 }
12213
12214 // set top-level value to null if it was discarded by the callback
12215 // function
12216 if (result.is_discarded())
12217 {
12218 result = nullptr;
12219 }
12220 }
12221 else
12222 {
12223 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
12224 sax_parse_internal(&sdp);
12225
12226 // in strict mode, input must be completely read
12227 if (strict && (get_token() != token_type::end_of_input))
12228 {
12229 sdp.parse_error(m_lexer.get_position(),
12230 m_lexer.get_token_string(),
12231 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12232 }
12233
12234 // in case of an error, return discarded value
12235 if (sdp.is_errored())
12236 {
12237 result = value_t::discarded;
12238 return;
12239 }
12240 }
12241
12242 result.assert_invariant();
12243 }
12244
12245 /*!
12246 @brief public accept interface
12247
12248 @param[in] strict whether to expect the last token to be EOF
12249 @return whether the input is a proper JSON text
12250 */
12251 bool accept(const bool strict = true)
12252 {
12253 json_sax_acceptor<BasicJsonType> sax_acceptor;
12254 return sax_parse(&sax_acceptor, strict);
12255 }
12256
12257 template<typename SAX>
12258 JSON_HEDLEY_NON_NULL(2)
12259 bool sax_parse(SAX* sax, const bool strict = true)
12260 {
12261 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
12262 const bool result = sax_parse_internal(sax);
12263
12264 // strict mode: next byte must be EOF
12265 if (result && strict && (get_token() != token_type::end_of_input))
12266 {
12267 return sax->parse_error(m_lexer.get_position(),
12268 m_lexer.get_token_string(),
12269 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12270 }
12271
12272 return result;
12273 }
12274
12275 private:
12276 template<typename SAX>
12277 JSON_HEDLEY_NON_NULL(2)
12278 bool sax_parse_internal(SAX* sax)
12279 {
12280 // stack to remember the hierarchy of structured values we are parsing
12281 // true = array; false = object
12282 std::vector<bool> states;
12283 // value to avoid a goto (see comment where set to true)
12284 bool skip_to_state_evaluation = false;
12285
12286 while (true)
12287 {
12288 if (!skip_to_state_evaluation)
12289 {
12290 // invariant: get_token() was called before each iteration
12291 switch (last_token)
12292 {
12293 case token_type::begin_object:
12294 {
12295 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
12296 {
12297 return false;
12298 }
12299
12300 // closing } -> we are done
12301 if (get_token() == token_type::end_object)
12302 {
12303 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12304 {
12305 return false;
12306 }
12307 break;
12308 }
12309
12310 // parse key
12311 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
12312 {
12313 return sax->parse_error(m_lexer.get_position(),
12314 m_lexer.get_token_string(),
12315 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12316 }
12317 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12318 {
12319 return false;
12320 }
12321
12322 // parse separator (:)
12323 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12324 {
12325 return sax->parse_error(m_lexer.get_position(),
12326 m_lexer.get_token_string(),
12327 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12328 }
12329
12330 // remember we are now inside an object
12331 states.push_back(false);
12332
12333 // parse values
12334 get_token();
12335 continue;
12336 }
12337
12338 case token_type::begin_array:
12339 {
12340 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
12341 {
12342 return false;
12343 }
12344
12345 // closing ] -> we are done
12346 if (get_token() == token_type::end_array)
12347 {
12348 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12349 {
12350 return false;
12351 }
12352 break;
12353 }
12354
12355 // remember we are now inside an array
12356 states.push_back(true);
12357
12358 // parse values (no need to call get_token)
12359 continue;
12360 }
12361
12362 case token_type::value_float:
12363 {
12364 const auto res = m_lexer.get_number_float();
12365
12366 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
12367 {
12368 return sax->parse_error(m_lexer.get_position(),
12369 m_lexer.get_token_string(),
12370 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
12371 }
12372
12373 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
12374 {
12375 return false;
12376 }
12377
12378 break;
12379 }
12380
12381 case token_type::literal_false:
12382 {
12383 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
12384 {
12385 return false;
12386 }
12387 break;
12388 }
12389
12390 case token_type::literal_null:
12391 {
12392 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
12393 {
12394 return false;
12395 }
12396 break;
12397 }
12398
12399 case token_type::literal_true:
12400 {
12401 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
12402 {
12403 return false;
12404 }
12405 break;
12406 }
12407
12408 case token_type::value_integer:
12409 {
12410 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
12411 {
12412 return false;
12413 }
12414 break;
12415 }
12416
12417 case token_type::value_string:
12418 {
12419 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
12420 {
12421 return false;
12422 }
12423 break;
12424 }
12425
12426 case token_type::value_unsigned:
12427 {
12428 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
12429 {
12430 return false;
12431 }
12432 break;
12433 }
12434
12435 case token_type::parse_error:
12436 {
12437 // using "uninitialized" to avoid "expected" message
12438 return sax->parse_error(m_lexer.get_position(),
12439 m_lexer.get_token_string(),
12440 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
12441 }
12442
12443 case token_type::uninitialized:
12444 case token_type::end_array:
12445 case token_type::end_object:
12446 case token_type::name_separator:
12447 case token_type::value_separator:
12448 case token_type::end_of_input:
12449 case token_type::literal_or_value:
12450 default: // the last token was unexpected
12451 {
12452 return sax->parse_error(m_lexer.get_position(),
12453 m_lexer.get_token_string(),
12454 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12455 }
12456 }
12457 }
12458 else
12459 {
12460 skip_to_state_evaluation = false;
12461 }
12462
12463 // we reached this line after we successfully parsed a value
12464 if (states.empty())
12465 {
12466 // empty stack: we reached the end of the hierarchy: done
12467 return true;
12468 }
12469
12470 if (states.back()) // array
12471 {
12472 // comma -> next value
12473 if (get_token() == token_type::value_separator)
12474 {
12475 // parse a new value
12476 get_token();
12477 continue;
12478 }
12479
12480 // closing ]
12481 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
12482 {
12483 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12484 {
12485 return false;
12486 }
12487
12488 // We are done with this array. Before we can parse a
12489 // new value, we need to evaluate the new state first.
12490 // By setting skip_to_state_evaluation to false, we
12491 // are effectively jumping to the beginning of this if.
12492 JSON_ASSERT(!states.empty());
12493 states.pop_back();
12494 skip_to_state_evaluation = true;
12495 continue;
12496 }
12497
12498 return sax->parse_error(m_lexer.get_position(),
12499 m_lexer.get_token_string(),
12500 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
12501 }
12502
12503 // states.back() is false -> object
12504
12505 // comma -> next value
12506 if (get_token() == token_type::value_separator)
12507 {
12508 // parse key
12509 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
12510 {
12511 return sax->parse_error(m_lexer.get_position(),
12512 m_lexer.get_token_string(),
12513 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12514 }
12515
12516 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12517 {
12518 return false;
12519 }
12520
12521 // parse separator (:)
12522 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12523 {
12524 return sax->parse_error(m_lexer.get_position(),
12525 m_lexer.get_token_string(),
12526 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12527 }
12528
12529 // parse values
12530 get_token();
12531 continue;
12532 }
12533
12534 // closing }
12535 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
12536 {
12537 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12538 {
12539 return false;
12540 }
12541
12542 // We are done with this object. Before we can parse a
12543 // new value, we need to evaluate the new state first.
12544 // By setting skip_to_state_evaluation to false, we
12545 // are effectively jumping to the beginning of this if.
12546 JSON_ASSERT(!states.empty());
12547 states.pop_back();
12548 skip_to_state_evaluation = true;
12549 continue;
12550 }
12551
12552 return sax->parse_error(m_lexer.get_position(),
12553 m_lexer.get_token_string(),
12554 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
12555 }
12556 }
12557
12558 /// get next token from lexer
12559 token_type get_token()
12560 {
12561 return last_token = m_lexer.scan();
12562 }
12563
12564 std::string exception_message(const token_type expected, const std::string& context)
12565 {
12566 std::string error_msg = "syntax error ";
12567
12568 if (!context.empty())
12569 {
12570 error_msg += concat("while parsing ", context, ' ');
12571 }
12572
12573 error_msg += "- ";
12574
12575 if (last_token == token_type::parse_error)
12576 {
12577 error_msg += concat(m_lexer.get_error_message(), "; last read: '",
12578 m_lexer.get_token_string(), '\'');
12579 }
12580 else
12581 {
12582 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
12583 }
12584
12585 if (expected != token_type::uninitialized)
12586 {
12587 error_msg += concat("; expected ", lexer_t::token_type_name(expected));
12588 }
12589
12590 return error_msg;
12591 }
12592
12593 private:
12594 /// callback function
12595 const parser_callback_t<BasicJsonType> callback = nullptr;
12596 /// the type of the last read token
12597 token_type last_token = token_type::uninitialized;
12598 /// the lexer
12599 lexer_t m_lexer;
12600 /// whether to throw exceptions in case of errors
12601 const bool allow_exceptions = true;
12602};
12603
12604} // namespace detail
12605NLOHMANN_JSON_NAMESPACE_END
12606
12607// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12608// __ _____ _____ _____
12609// __| | __| | | | JSON for Modern C++
12610// | | |__ | | | | | | version 3.11.2
12611// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12612//
12613// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
12614// SPDX-License-Identifier: MIT
12615
12616
12617
12618// #include <nlohmann/detail/abi_macros.hpp>
12619
12620// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12621// __ _____ _____ _____
12622// __| | __| | | | JSON for Modern C++
12623// | | |__ | | | | | | version 3.11.2
12624// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12625//
12626// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
12627// SPDX-License-Identifier: MIT
12628
12629
12630
12631#include <cstddef> // ptrdiff_t
12632#include <limits> // numeric_limits
12633
12634// #include <nlohmann/detail/macro_scope.hpp>
12635
12636
12637NLOHMANN_JSON_NAMESPACE_BEGIN
12638namespace detail
12639{
12640
12641/*
12642@brief an iterator for primitive JSON types
12643
12644This class models an iterator for primitive JSON types (boolean, number,
12645string). It's only purpose is to allow the iterator/const_iterator classes
12646to "iterate" over primitive values. Internally, the iterator is modeled by
12647a `difference_type` variable. Value begin_value (`0`) models the begin,
12648end_value (`1`) models past the end.
12649*/
12650class primitive_iterator_t
12651{
12652 private:
12653 using difference_type = std::ptrdiff_t;
12654 static constexpr difference_type begin_value = 0;
12655 static constexpr difference_type end_value = begin_value + 1;
12656
12657 JSON_PRIVATE_UNLESS_TESTED:
12658 /// iterator as signed integer type
12659 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
12660
12661 public:
12662 constexpr difference_type get_value() const noexcept
12663 {
12664 return m_it;
12665 }
12666
12667 /// set iterator to a defined beginning
12668 void set_begin() noexcept
12669 {
12670 m_it = begin_value;
12671 }
12672
12673 /// set iterator to a defined past the end
12674 void set_end() noexcept
12675 {
12676 m_it = end_value;
12677 }
12678
12679 /// return whether the iterator can be dereferenced
12680 constexpr bool is_begin() const noexcept
12681 {
12682 return m_it == begin_value;
12683 }
12684
12685 /// return whether the iterator is at end
12686 constexpr bool is_end() const noexcept
12687 {
12688 return m_it == end_value;
12689 }
12690
12691 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12692 {
12693 return lhs.m_it == rhs.m_it;
12694 }
12695
12696 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12697 {
12698 return lhs.m_it < rhs.m_it;
12699 }
12700
12701 primitive_iterator_t operator+(difference_type n) noexcept
12702 {
12703 auto result = *this;
12704 result += n;
12705 return result;
12706 }
12707
12708 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12709 {
12710 return lhs.m_it - rhs.m_it;
12711 }
12712
12713 primitive_iterator_t& operator++() noexcept
12714 {
12715 ++m_it;
12716 return *this;
12717 }
12718
12719 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
12720 {
12721 auto result = *this;
12722 ++m_it;
12723 return result;
12724 }
12725
12726 primitive_iterator_t& operator--() noexcept
12727 {
12728 --m_it;
12729 return *this;
12730 }
12731
12732 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
12733 {
12734 auto result = *this;
12735 --m_it;
12736 return result;
12737 }
12738
12739 primitive_iterator_t& operator+=(difference_type n) noexcept
12740 {
12741 m_it += n;
12742 return *this;
12743 }
12744
12745 primitive_iterator_t& operator-=(difference_type n) noexcept
12746 {
12747 m_it -= n;
12748 return *this;
12749 }
12750};
12751
12752} // namespace detail
12753NLOHMANN_JSON_NAMESPACE_END
12754
12755
12756NLOHMANN_JSON_NAMESPACE_BEGIN
12757namespace detail
12758{
12759
12760/*!
12761@brief an iterator value
12762
12763@note This structure could easily be a union, but MSVC currently does not allow
12764unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
12765*/
12766template<typename BasicJsonType> struct internal_iterator
12767{
12768 /// iterator for JSON objects
12769 typename BasicJsonType::object_t::iterator object_iterator {};
12770 /// iterator for JSON arrays
12771 typename BasicJsonType::array_t::iterator array_iterator {};
12772 /// generic iterator for all other types
12773 primitive_iterator_t primitive_iterator {};
12774};
12775
12776} // namespace detail
12777NLOHMANN_JSON_NAMESPACE_END
12778
12779// #include <nlohmann/detail/iterators/iter_impl.hpp>
12780// __ _____ _____ _____
12781// __| | __| | | | JSON for Modern C++
12782// | | |__ | | | | | | version 3.11.2
12783// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12784//
12785// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
12786// SPDX-License-Identifier: MIT
12787
12788
12789
12790#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
12791#include <type_traits> // conditional, is_const, remove_const
12792
12793// #include <nlohmann/detail/exceptions.hpp>
12794
12795// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12796
12797// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12798
12799// #include <nlohmann/detail/macro_scope.hpp>
12800
12801// #include <nlohmann/detail/meta/cpp_future.hpp>
12802
12803// #include <nlohmann/detail/meta/type_traits.hpp>
12804
12805// #include <nlohmann/detail/value_t.hpp>
12806
12807
12808NLOHMANN_JSON_NAMESPACE_BEGIN
12809namespace detail
12810{
12811
12812// forward declare, to be able to friend it later on
12813template<typename IteratorType> class iteration_proxy;
12814template<typename IteratorType> class iteration_proxy_value;
12815
12816/*!
12817@brief a template for a bidirectional iterator for the @ref basic_json class
12818This class implements a both iterators (iterator and const_iterator) for the
12819@ref basic_json class.
12820@note An iterator is called *initialized* when a pointer to a JSON value has
12821 been set (e.g., by a constructor or a copy assignment). If the iterator is
12822 default-constructed, it is *uninitialized* and most methods are undefined.
12823 **The library uses assertions to detect calls on uninitialized iterators.**
12824@requirement The class satisfies the following concept requirements:
12825-
12826[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
12827 The iterator that can be moved can be moved in both directions (i.e.
12828 incremented and decremented).
12829@since version 1.0.0, simplified in version 2.0.9, change to bidirectional
12830 iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
12831*/
12832template<typename BasicJsonType>
12833class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
12834{
12835 /// the iterator with BasicJsonType of different const-ness
12836 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
12837 /// allow basic_json to access private members
12838 friend other_iter_impl;
12839 friend BasicJsonType;
12840 friend iteration_proxy<iter_impl>;
12841 friend iteration_proxy_value<iter_impl>;
12842
12843 using object_t = typename BasicJsonType::object_t;
12844 using array_t = typename BasicJsonType::array_t;
12845 // make sure BasicJsonType is basic_json or const basic_json
12846 static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
12847 "iter_impl only accepts (const) basic_json");
12848 // superficial check for the LegacyBidirectionalIterator named requirement
12849 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
12850 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
12851 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
12852
12853 public:
12854 /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
12855 /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
12856 /// A user-defined iterator should provide publicly accessible typedefs named
12857 /// iterator_category, value_type, difference_type, pointer, and reference.
12858 /// Note that value_type is required to be non-const, even for constant iterators.
12859 using iterator_category = std::bidirectional_iterator_tag;
12860
12861 /// the type of the values when the iterator is dereferenced
12862 using value_type = typename BasicJsonType::value_type;
12863 /// a type to represent differences between iterators
12864 using difference_type = typename BasicJsonType::difference_type;
12865 /// defines a pointer to the type iterated over (value_type)
12866 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
12867 typename BasicJsonType::const_pointer,
12868 typename BasicJsonType::pointer>::type;
12869 /// defines a reference to the type iterated over (value_type)
12870 using reference =
12871 typename std::conditional<std::is_const<BasicJsonType>::value,
12872 typename BasicJsonType::const_reference,
12873 typename BasicJsonType::reference>::type;
12874
12875 iter_impl() = default;
12876 ~iter_impl() = default;
12877 iter_impl(iter_impl&&) noexcept = default;
12878 iter_impl& operator=(iter_impl&&) noexcept = default;
12879
12880 /*!
12881 @brief constructor for a given JSON instance
12882 @param[in] object pointer to a JSON object for this iterator
12883 @pre object != nullptr
12884 @post The iterator is initialized; i.e. `m_object != nullptr`.
12885 */
12886 explicit iter_impl(pointer object) noexcept : m_object(object)
12887 {
12888 JSON_ASSERT(m_object != nullptr);
12889
12890 switch (m_object->m_type)
12891 {
12892 case value_t::object:
12893 {
12894 m_it.object_iterator = typename object_t::iterator();
12895 break;
12896 }
12897
12898 case value_t::array:
12899 {
12900 m_it.array_iterator = typename array_t::iterator();
12901 break;
12902 }
12903
12904 case value_t::null:
12905 case value_t::string:
12906 case value_t::boolean:
12907 case value_t::number_integer:
12908 case value_t::number_unsigned:
12909 case value_t::number_float:
12910 case value_t::binary:
12911 case value_t::discarded:
12912 default:
12913 {
12914 m_it.primitive_iterator = primitive_iterator_t();
12915 break;
12916 }
12917 }
12918 }
12919
12920 /*!
12921 @note The conventional copy constructor and copy assignment are implicitly
12922 defined. Combined with the following converting constructor and
12923 assignment, they support: (1) copy from iterator to iterator, (2)
12924 copy from const iterator to const iterator, and (3) conversion from
12925 iterator to const iterator. However conversion from const iterator
12926 to iterator is not defined.
12927 */
12928
12929 /*!
12930 @brief const copy constructor
12931 @param[in] other const iterator to copy from
12932 @note This copy constructor had to be defined explicitly to circumvent a bug
12933 occurring on msvc v19.0 compiler (VS 2015) debug build. For more
12934 information refer to: https://github.com/nlohmann/json/issues/1608
12935 */
12936 iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
12937 : m_object(other.m_object), m_it(other.m_it)
12938 {}
12939
12940 /*!
12941 @brief converting assignment
12942 @param[in] other const iterator to copy from
12943 @return const/non-const iterator
12944 @note It is not checked whether @a other is initialized.
12945 */
12946 iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
12947 {
12948 if (&other != this)
12949 {
12950 m_object = other.m_object;
12951 m_it = other.m_it;
12952 }
12953 return *this;
12954 }
12955
12956 /*!
12957 @brief converting constructor
12958 @param[in] other non-const iterator to copy from
12959 @note It is not checked whether @a other is initialized.
12960 */
12961 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
12962 : m_object(other.m_object), m_it(other.m_it)
12963 {}
12964
12965 /*!
12966 @brief converting assignment
12967 @param[in] other non-const iterator to copy from
12968 @return const/non-const iterator
12969 @note It is not checked whether @a other is initialized.
12970 */
12971 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
12972 {
12973 m_object = other.m_object;
12974 m_it = other.m_it;
12975 return *this;
12976 }
12977
12978 JSON_PRIVATE_UNLESS_TESTED:
12979 /*!
12980 @brief set the iterator to the first value
12981 @pre The iterator is initialized; i.e. `m_object != nullptr`.
12982 */
12983 void set_begin() noexcept
12984 {
12985 JSON_ASSERT(m_object != nullptr);
12986
12987 switch (m_object->m_type)
12988 {
12989 case value_t::object:
12990 {
12991 m_it.object_iterator = m_object->m_value.object->begin();
12992 break;
12993 }
12994
12995 case value_t::array:
12996 {
12997 m_it.array_iterator = m_object->m_value.array->begin();
12998 break;
12999 }
13000
13001 case value_t::null:
13002 {
13003 // set to end so begin()==end() is true: null is empty
13004 m_it.primitive_iterator.set_end();
13005 break;
13006 }
13007
13008 case value_t::string:
13009 case value_t::boolean:
13010 case value_t::number_integer:
13011 case value_t::number_unsigned:
13012 case value_t::number_float:
13013 case value_t::binary:
13014 case value_t::discarded:
13015 default:
13016 {
13017 m_it.primitive_iterator.set_begin();
13018 break;
13019 }
13020 }
13021 }
13022
13023 /*!
13024 @brief set the iterator past the last value
13025 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13026 */
13027 void set_end() noexcept
13028 {
13029 JSON_ASSERT(m_object != nullptr);
13030
13031 switch (m_object->m_type)
13032 {
13033 case value_t::object:
13034 {
13035 m_it.object_iterator = m_object->m_value.object->end();
13036 break;
13037 }
13038
13039 case value_t::array:
13040 {
13041 m_it.array_iterator = m_object->m_value.array->end();
13042 break;
13043 }
13044
13045 case value_t::null:
13046 case value_t::string:
13047 case value_t::boolean:
13048 case value_t::number_integer:
13049 case value_t::number_unsigned:
13050 case value_t::number_float:
13051 case value_t::binary:
13052 case value_t::discarded:
13053 default:
13054 {
13055 m_it.primitive_iterator.set_end();
13056 break;
13057 }
13058 }
13059 }
13060
13061 public:
13062 /*!
13063 @brief return a reference to the value pointed to by the iterator
13064 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13065 */
13066 reference operator*() const
13067 {
13068 JSON_ASSERT(m_object != nullptr);
13069
13070 switch (m_object->m_type)
13071 {
13072 case value_t::object:
13073 {
13074 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
13075 return m_it.object_iterator->second;
13076 }
13077
13078 case value_t::array:
13079 {
13080 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
13081 return *m_it.array_iterator;
13082 }
13083
13084 case value_t::null:
13085 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13086
13087 case value_t::string:
13088 case value_t::boolean:
13089 case value_t::number_integer:
13090 case value_t::number_unsigned:
13091 case value_t::number_float:
13092 case value_t::binary:
13093 case value_t::discarded:
13094 default:
13095 {
13096 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13097 {
13098 return *m_object;
13099 }
13100
13101 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13102 }
13103 }
13104 }
13105
13106 /*!
13107 @brief dereference the iterator
13108 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13109 */
13110 pointer operator->() const
13111 {
13112 JSON_ASSERT(m_object != nullptr);
13113
13114 switch (m_object->m_type)
13115 {
13116 case value_t::object:
13117 {
13118 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
13119 return &(m_it.object_iterator->second);
13120 }
13121
13122 case value_t::array:
13123 {
13124 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
13125 return &*m_it.array_iterator;
13126 }
13127
13128 case value_t::null:
13129 case value_t::string:
13130 case value_t::boolean:
13131 case value_t::number_integer:
13132 case value_t::number_unsigned:
13133 case value_t::number_float:
13134 case value_t::binary:
13135 case value_t::discarded:
13136 default:
13137 {
13138 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13139 {
13140 return m_object;
13141 }
13142
13143 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13144 }
13145 }
13146 }
13147
13148 /*!
13149 @brief post-increment (it++)
13150 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13151 */
13152 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
13153 {
13154 auto result = *this;
13155 ++(*this);
13156 return result;
13157 }
13158
13159 /*!
13160 @brief pre-increment (++it)
13161 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13162 */
13163 iter_impl& operator++()
13164 {
13165 JSON_ASSERT(m_object != nullptr);
13166
13167 switch (m_object->m_type)
13168 {
13169 case value_t::object:
13170 {
13171 std::advance(m_it.object_iterator, 1);
13172 break;
13173 }
13174
13175 case value_t::array:
13176 {
13177 std::advance(m_it.array_iterator, 1);
13178 break;
13179 }
13180
13181 case value_t::null:
13182 case value_t::string:
13183 case value_t::boolean:
13184 case value_t::number_integer:
13185 case value_t::number_unsigned:
13186 case value_t::number_float:
13187 case value_t::binary:
13188 case value_t::discarded:
13189 default:
13190 {
13191 ++m_it.primitive_iterator;
13192 break;
13193 }
13194 }
13195
13196 return *this;
13197 }
13198
13199 /*!
13200 @brief post-decrement (it--)
13201 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13202 */
13203 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
13204 {
13205 auto result = *this;
13206 --(*this);
13207 return result;
13208 }
13209
13210 /*!
13211 @brief pre-decrement (--it)
13212 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13213 */
13214 iter_impl& operator--()
13215 {
13216 JSON_ASSERT(m_object != nullptr);
13217
13218 switch (m_object->m_type)
13219 {
13220 case value_t::object:
13221 {
13222 std::advance(m_it.object_iterator, -1);
13223 break;
13224 }
13225
13226 case value_t::array:
13227 {
13228 std::advance(m_it.array_iterator, -1);
13229 break;
13230 }
13231
13232 case value_t::null:
13233 case value_t::string:
13234 case value_t::boolean:
13235 case value_t::number_integer:
13236 case value_t::number_unsigned:
13237 case value_t::number_float:
13238 case value_t::binary:
13239 case value_t::discarded:
13240 default:
13241 {
13242 --m_it.primitive_iterator;
13243 break;
13244 }
13245 }
13246
13247 return *this;
13248 }
13249
13250 /*!
13251 @brief comparison: equal
13252 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13253 */
13254 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
13255 bool operator==(const IterImpl& other) const
13256 {
13257 // if objects are not the same, the comparison is undefined
13258 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13259 {
13260 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13261 }
13262
13263 JSON_ASSERT(m_object != nullptr);
13264
13265 switch (m_object->m_type)
13266 {
13267 case value_t::object:
13268 return (m_it.object_iterator == other.m_it.object_iterator);
13269
13270 case value_t::array:
13271 return (m_it.array_iterator == other.m_it.array_iterator);
13272
13273 case value_t::null:
13274 case value_t::string:
13275 case value_t::boolean:
13276 case value_t::number_integer:
13277 case value_t::number_unsigned:
13278 case value_t::number_float:
13279 case value_t::binary:
13280 case value_t::discarded:
13281 default:
13282 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
13283 }
13284 }
13285
13286 /*!
13287 @brief comparison: not equal
13288 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13289 */
13290 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
13291 bool operator!=(const IterImpl& other) const
13292 {
13293 return !operator==(other);
13294 }
13295
13296 /*!
13297 @brief comparison: smaller
13298 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13299 */
13300 bool operator<(const iter_impl& other) const
13301 {
13302 // if objects are not the same, the comparison is undefined
13303 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13304 {
13305 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13306 }
13307
13308 JSON_ASSERT(m_object != nullptr);
13309
13310 switch (m_object->m_type)
13311 {
13312 case value_t::object:
13313 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
13314
13315 case value_t::array:
13316 return (m_it.array_iterator < other.m_it.array_iterator);
13317
13318 case value_t::null:
13319 case value_t::string:
13320 case value_t::boolean:
13321 case value_t::number_integer:
13322 case value_t::number_unsigned:
13323 case value_t::number_float:
13324 case value_t::binary:
13325 case value_t::discarded:
13326 default:
13327 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
13328 }
13329 }
13330
13331 /*!
13332 @brief comparison: less than or equal
13333 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13334 */
13335 bool operator<=(const iter_impl& other) const
13336 {
13337 return !other.operator < (*this);
13338 }
13339
13340 /*!
13341 @brief comparison: greater than
13342 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13343 */
13344 bool operator>(const iter_impl& other) const
13345 {
13346 return !operator<=(other);
13347 }
13348
13349 /*!
13350 @brief comparison: greater than or equal
13351 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13352 */
13353 bool operator>=(const iter_impl& other) const
13354 {
13355 return !operator<(other);
13356 }
13357
13358 /*!
13359 @brief add to iterator
13360 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13361 */
13362 iter_impl& operator+=(difference_type i)
13363 {
13364 JSON_ASSERT(m_object != nullptr);
13365
13366 switch (m_object->m_type)
13367 {
13368 case value_t::object:
13369 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13370
13371 case value_t::array:
13372 {
13373 std::advance(m_it.array_iterator, i);
13374 break;
13375 }
13376
13377 case value_t::null:
13378 case value_t::string:
13379 case value_t::boolean:
13380 case value_t::number_integer:
13381 case value_t::number_unsigned:
13382 case value_t::number_float:
13383 case value_t::binary:
13384 case value_t::discarded:
13385 default:
13386 {
13387 m_it.primitive_iterator += i;
13388 break;
13389 }
13390 }
13391
13392 return *this;
13393 }
13394
13395 /*!
13396 @brief subtract from iterator
13397 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13398 */
13399 iter_impl& operator-=(difference_type i)
13400 {
13401 return operator+=(-i);
13402 }
13403
13404 /*!
13405 @brief add to iterator
13406 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13407 */
13408 iter_impl operator+(difference_type i) const
13409 {
13410 auto result = *this;
13411 result += i;
13412 return result;
13413 }
13414
13415 /*!
13416 @brief addition of distance and iterator
13417 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13418 */
13419 friend iter_impl operator+(difference_type i, const iter_impl& it)
13420 {
13421 auto result = it;
13422 result += i;
13423 return result;
13424 }
13425
13426 /*!
13427 @brief subtract from iterator
13428 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13429 */
13430 iter_impl operator-(difference_type i) const
13431 {
13432 auto result = *this;
13433 result -= i;
13434 return result;
13435 }
13436
13437 /*!
13438 @brief return difference
13439 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13440 */
13441 difference_type operator-(const iter_impl& other) const
13442 {
13443 JSON_ASSERT(m_object != nullptr);
13444
13445 switch (m_object->m_type)
13446 {
13447 case value_t::object:
13448 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13449
13450 case value_t::array:
13451 return m_it.array_iterator - other.m_it.array_iterator;
13452
13453 case value_t::null:
13454 case value_t::string:
13455 case value_t::boolean:
13456 case value_t::number_integer:
13457 case value_t::number_unsigned:
13458 case value_t::number_float:
13459 case value_t::binary:
13460 case value_t::discarded:
13461 default:
13462 return m_it.primitive_iterator - other.m_it.primitive_iterator;
13463 }
13464 }
13465
13466 /*!
13467 @brief access to successor
13468 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13469 */
13470 reference operator[](difference_type n) const
13471 {
13472 JSON_ASSERT(m_object != nullptr);
13473
13474 switch (m_object->m_type)
13475 {
13476 case value_t::object:
13477 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
13478
13479 case value_t::array:
13480 return *std::next(m_it.array_iterator, n);
13481
13482 case value_t::null:
13483 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13484
13485 case value_t::string:
13486 case value_t::boolean:
13487 case value_t::number_integer:
13488 case value_t::number_unsigned:
13489 case value_t::number_float:
13490 case value_t::binary:
13491 case value_t::discarded:
13492 default:
13493 {
13494 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
13495 {
13496 return *m_object;
13497 }
13498
13499 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13500 }
13501 }
13502 }
13503
13504 /*!
13505 @brief return the key of an object iterator
13506 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13507 */
13508 const typename object_t::key_type& key() const
13509 {
13510 JSON_ASSERT(m_object != nullptr);
13511
13512 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
13513 {
13514 return m_it.object_iterator->first;
13515 }
13516
13517 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
13518 }
13519
13520 /*!
13521 @brief return the value of an iterator
13522 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13523 */
13524 reference value() const
13525 {
13526 return operator*();
13527 }
13528
13529 JSON_PRIVATE_UNLESS_TESTED:
13530 /// associated JSON instance
13531 pointer m_object = nullptr;
13532 /// the actual iterator of the associated instance
13533 internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
13534};
13535
13536} // namespace detail
13537NLOHMANN_JSON_NAMESPACE_END
13538
13539// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
13540
13541// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
13542// __ _____ _____ _____
13543// __| | __| | | | JSON for Modern C++
13544// | | |__ | | | | | | version 3.11.2
13545// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13546//
13547// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
13548// SPDX-License-Identifier: MIT
13549
13550
13551
13552#include <cstddef> // ptrdiff_t
13553#include <iterator> // reverse_iterator
13554#include <utility> // declval
13555
13556// #include <nlohmann/detail/abi_macros.hpp>
13557
13558
13559NLOHMANN_JSON_NAMESPACE_BEGIN
13560namespace detail
13561{
13562
13563//////////////////////
13564// reverse_iterator //
13565//////////////////////
13566
13567/*!
13568@brief a template for a reverse iterator class
13569
13570@tparam Base the base iterator type to reverse. Valid types are @ref
13571iterator (to create @ref reverse_iterator) and @ref const_iterator (to
13572create @ref const_reverse_iterator).
13573
13574@requirement The class satisfies the following concept requirements:
13575-
13576[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
13577 The iterator that can be moved can be moved in both directions (i.e.
13578 incremented and decremented).
13579- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
13580 It is possible to write to the pointed-to element (only if @a Base is
13581 @ref iterator).
13582
13583@since version 1.0.0
13584*/
13585template<typename Base>
13586class json_reverse_iterator : public std::reverse_iterator<Base>
13587{
13588 public:
13589 using difference_type = std::ptrdiff_t;
13590 /// shortcut to the reverse iterator adapter
13591 using base_iterator = std::reverse_iterator<Base>;
13592 /// the reference type for the pointed-to element
13593 using reference = typename Base::reference;
13594
13595 /// create reverse iterator from iterator
13596 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
13597 : base_iterator(it) {}
13598
13599 /// create reverse iterator from base class
13600 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
13601
13602 /// post-increment (it++)
13603 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
13604 {
13605 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
13606 }
13607
13608 /// pre-increment (++it)
13609 json_reverse_iterator& operator++()
13610 {
13611 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
13612 }
13613
13614 /// post-decrement (it--)
13615 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
13616 {
13617 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
13618 }
13619
13620 /// pre-decrement (--it)
13621 json_reverse_iterator& operator--()
13622 {
13623 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
13624 }
13625
13626 /// add to iterator
13627 json_reverse_iterator& operator+=(difference_type i)
13628 {
13629 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
13630 }
13631
13632 /// add to iterator
13633 json_reverse_iterator operator+(difference_type i) const
13634 {
13635 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
13636 }
13637
13638 /// subtract from iterator
13639 json_reverse_iterator operator-(difference_type i) const
13640 {
13641 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
13642 }
13643
13644 /// return difference
13645 difference_type operator-(const json_reverse_iterator& other) const
13646 {
13647 return base_iterator(*this) - base_iterator(other);
13648 }
13649
13650 /// access to successor
13651 reference operator[](difference_type n) const
13652 {
13653 return *(this->operator+(n));
13654 }
13655
13656 /// return the key of an object iterator
13657 auto key() const -> decltype(std::declval<Base>().key())
13658 {
13659 auto it = --this->base();
13660 return it.key();
13661 }
13662
13663 /// return the value of an iterator
13664 reference value() const
13665 {
13666 auto it = --this->base();
13667 return it.operator * ();
13668 }
13669};
13670
13671} // namespace detail
13672NLOHMANN_JSON_NAMESPACE_END
13673
13674// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13675
13676// #include <nlohmann/detail/json_pointer.hpp>
13677// __ _____ _____ _____
13678// __| | __| | | | JSON for Modern C++
13679// | | |__ | | | | | | version 3.11.2
13680// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13681//
13682// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
13683// SPDX-License-Identifier: MIT
13684
13685
13686
13687#include <algorithm> // all_of
13688#include <cctype> // isdigit
13689#include <cerrno> // errno, ERANGE
13690#include <cstdlib> // strtoull
13691#ifndef JSON_NO_IO
13692 #include <iosfwd> // ostream
13693#endif // JSON_NO_IO
13694#include <limits> // max
13695#include <numeric> // accumulate
13696#include <string> // string
13697#include <utility> // move
13698#include <vector> // vector
13699
13700// #include <nlohmann/detail/exceptions.hpp>
13701
13702// #include <nlohmann/detail/macro_scope.hpp>
13703
13704// #include <nlohmann/detail/string_concat.hpp>
13705
13706// #include <nlohmann/detail/string_escape.hpp>
13707
13708// #include <nlohmann/detail/value_t.hpp>
13709
13710
13711NLOHMANN_JSON_NAMESPACE_BEGIN
13712
13713/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
13714/// @sa https://json.nlohmann.me/api/json_pointer/
13715template<typename RefStringType>
13716class json_pointer
13717{
13718 // allow basic_json to access private members
13719 NLOHMANN_BASIC_JSON_TPL_DECLARATION
13720 friend class basic_json;
13721
13722 template<typename>
13723 friend class json_pointer;
13724
13725 template<typename T>
13726 struct string_t_helper
13727 {
13728 using type = T;
13729 };
13730
13731 NLOHMANN_BASIC_JSON_TPL_DECLARATION
13732 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
13733 {
13734 using type = StringType;
13735 };
13736
13737 public:
13738 // for backwards compatibility accept BasicJsonType
13739 using string_t = typename string_t_helper<RefStringType>::type;
13740
13741 /// @brief create JSON pointer
13742 /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
13743 explicit json_pointer(const string_t& s = "")
13744 : reference_tokens(split(s))
13745 {}
13746
13747 /// @brief return a string representation of the JSON pointer
13748 /// @sa https://json.nlohmann.me/api/json_pointer/to_string/
13749 string_t to_string() const
13750 {
13751 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
13752 string_t{},
13753 [](const string_t& a, const string_t& b)
13754 {
13755 return detail::concat(a, '/', detail::escape(b));
13756 });
13757 }
13758
13759 /// @brief return a string representation of the JSON pointer
13760 /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/
13761 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
13762 operator string_t() const
13763 {
13764 return to_string();
13765 }
13766
13767#ifndef JSON_NO_IO
13768 /// @brief write string representation of the JSON pointer to stream
13769 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
13770 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
13771 {
13772 o << ptr.to_string();
13773 return o;
13774 }
13775#endif
13776
13777 /// @brief append another JSON pointer at the end of this JSON pointer
13778 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
13779 json_pointer& operator/=(const json_pointer& ptr)
13780 {
13781 reference_tokens.insert(reference_tokens.end(),
13782 ptr.reference_tokens.begin(),
13783 ptr.reference_tokens.end());
13784 return *this;
13785 }
13786
13787 /// @brief append an unescaped reference token at the end of this JSON pointer
13788 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
13789 json_pointer& operator/=(string_t token)
13790 {
13791 push_back(std::move(token));
13792 return *this;
13793 }
13794
13795 /// @brief append an array index at the end of this JSON pointer
13796 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
13797 json_pointer& operator/=(std::size_t array_idx)
13798 {
13799 return *this /= std::to_string(array_idx);
13800 }
13801
13802 /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
13803 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
13804 friend json_pointer operator/(const json_pointer& lhs,
13805 const json_pointer& rhs)
13806 {
13807 return json_pointer(lhs) /= rhs;
13808 }
13809
13810 /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
13811 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
13812 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
13813 {
13814 return json_pointer(lhs) /= std::move(token);
13815 }
13816
13817 /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
13818 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
13819 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
13820 {
13821 return json_pointer(lhs) /= array_idx;
13822 }
13823
13824 /// @brief returns the parent of this JSON pointer
13825 /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/
13826 json_pointer parent_pointer() const
13827 {
13828 if (empty())
13829 {
13830 return *this;
13831 }
13832
13833 json_pointer res = *this;
13834 res.pop_back();
13835 return res;
13836 }
13837
13838 /// @brief remove last reference token
13839 /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/
13840 void pop_back()
13841 {
13842 if (JSON_HEDLEY_UNLIKELY(empty()))
13843 {
13844 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13845 }
13846
13847 reference_tokens.pop_back();
13848 }
13849
13850 /// @brief return last reference token
13851 /// @sa https://json.nlohmann.me/api/json_pointer/back/
13852 const string_t& back() const
13853 {
13854 if (JSON_HEDLEY_UNLIKELY(empty()))
13855 {
13856 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13857 }
13858
13859 return reference_tokens.back();
13860 }
13861
13862 /// @brief append an unescaped token at the end of the reference pointer
13863 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
13864 void push_back(const string_t& token)
13865 {
13866 reference_tokens.push_back(token);
13867 }
13868
13869 /// @brief append an unescaped token at the end of the reference pointer
13870 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
13871 void push_back(string_t&& token)
13872 {
13873 reference_tokens.push_back(std::move(token));
13874 }
13875
13876 /// @brief return whether pointer points to the root document
13877 /// @sa https://json.nlohmann.me/api/json_pointer/empty/
13878 bool empty() const noexcept
13879 {
13880 return reference_tokens.empty();
13881 }
13882
13883 private:
13884 /*!
13885 @param[in] s reference token to be converted into an array index
13886
13887 @return integer representation of @a s
13888
13889 @throw parse_error.106 if an array index begins with '0'
13890 @throw parse_error.109 if an array index begins not with a digit
13891 @throw out_of_range.404 if string @a s could not be converted to an integer
13892 @throw out_of_range.410 if an array index exceeds size_type
13893 */
13894 template<typename BasicJsonType>
13895 static typename BasicJsonType::size_type array_index(const string_t& s)
13896 {
13897 using size_type = typename BasicJsonType::size_type;
13898
13899 // error condition (cf. RFC 6901, Sect. 4)
13900 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
13901 {
13902 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
13903 }
13904
13905 // error condition (cf. RFC 6901, Sect. 4)
13906 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
13907 {
13908 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
13909 }
13910
13911 const char* p = s.c_str();
13912 char* p_end = nullptr;
13913 errno = 0; // strtoull doesn't reset errno
13914 unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
13915 if (p == p_end // invalid input or empty string
13916 || errno == ERANGE // out of range
13917 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
13918 {
13919 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
13920 }
13921
13922 // only triggered on special platforms (like 32bit), see also
13923 // https://github.com/nlohmann/json/pull/2203
13924 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
13925 {
13926 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
13927 }
13928
13929 return static_cast<size_type>(res);
13930 }
13931
13932 JSON_PRIVATE_UNLESS_TESTED:
13933 json_pointer top() const
13934 {
13935 if (JSON_HEDLEY_UNLIKELY(empty()))
13936 {
13937 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13938 }
13939
13940 json_pointer result = *this;
13941 result.reference_tokens = {reference_tokens[0]};
13942 return result;
13943 }
13944
13945 private:
13946 /*!
13947 @brief create and return a reference to the pointed to value
13948
13949 @complexity Linear in the number of reference tokens.
13950
13951 @throw parse_error.109 if array index is not a number
13952 @throw type_error.313 if value cannot be unflattened
13953 */
13954 template<typename BasicJsonType>
13955 BasicJsonType& get_and_create(BasicJsonType& j) const
13956 {
13957 auto* result = &j;
13958
13959 // in case no reference tokens exist, return a reference to the JSON value
13960 // j which will be overwritten by a primitive value
13961 for (const auto& reference_token : reference_tokens)
13962 {
13963 switch (result->type())
13964 {
13965 case detail::value_t::null:
13966 {
13967 if (reference_token == "0")
13968 {
13969 // start a new array if reference token is 0
13970 result = &result->operator[](0);
13971 }
13972 else
13973 {
13974 // start a new object otherwise
13975 result = &result->operator[](reference_token);
13976 }
13977 break;
13978 }
13979
13980 case detail::value_t::object:
13981 {
13982 // create an entry in the object
13983 result = &result->operator[](reference_token);
13984 break;
13985 }
13986
13987 case detail::value_t::array:
13988 {
13989 // create an entry in the array
13990 result = &result->operator[](array_index<BasicJsonType>(reference_token));
13991 break;
13992 }
13993
13994 /*
13995 The following code is only reached if there exists a reference
13996 token _and_ the current value is primitive. In this case, we have
13997 an error situation, because primitive values may only occur as
13998 single value; that is, with an empty list of reference tokens.
13999 */
14000 case detail::value_t::string:
14001 case detail::value_t::boolean:
14002 case detail::value_t::number_integer:
14003 case detail::value_t::number_unsigned:
14004 case detail::value_t::number_float:
14005 case detail::value_t::binary:
14006 case detail::value_t::discarded:
14007 default:
14008 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
14009 }
14010 }
14011
14012 return *result;
14013 }
14014
14015 /*!
14016 @brief return a reference to the pointed to value
14017
14018 @note This version does not throw if a value is not present, but tries to
14019 create nested values instead. For instance, calling this function
14020 with pointer `"/this/that"` on a null value is equivalent to calling
14021 `operator[]("this").operator[]("that")` on that value, effectively
14022 changing the null value to an object.
14023
14024 @param[in] ptr a JSON value
14025
14026 @return reference to the JSON value pointed to by the JSON pointer
14027
14028 @complexity Linear in the length of the JSON pointer.
14029
14030 @throw parse_error.106 if an array index begins with '0'
14031 @throw parse_error.109 if an array index was not a number
14032 @throw out_of_range.404 if the JSON pointer can not be resolved
14033 */
14034 template<typename BasicJsonType>
14035 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
14036 {
14037 for (const auto& reference_token : reference_tokens)
14038 {
14039 // convert null values to arrays or objects before continuing
14040 if (ptr->is_null())
14041 {
14042 // check if reference token is a number
14043 const bool nums =
14044 std::all_of(reference_token.begin(), reference_token.end(),
14045 [](const unsigned char x)
14046 {
14047 return std::isdigit(x);
14048 });
14049
14050 // change value to array for numbers or "-" or to object otherwise
14051 *ptr = (nums || reference_token == "-")
14052 ? detail::value_t::array
14053 : detail::value_t::object;
14054 }
14055
14056 switch (ptr->type())
14057 {
14058 case detail::value_t::object:
14059 {
14060 // use unchecked object access
14061 ptr = &ptr->operator[](reference_token);
14062 break;
14063 }
14064
14065 case detail::value_t::array:
14066 {
14067 if (reference_token == "-")
14068 {
14069 // explicitly treat "-" as index beyond the end
14070 ptr = &ptr->operator[](ptr->m_value.array->size());
14071 }
14072 else
14073 {
14074 // convert array index to number; unchecked access
14075 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14076 }
14077 break;
14078 }
14079
14080 case detail::value_t::null:
14081 case detail::value_t::string:
14082 case detail::value_t::boolean:
14083 case detail::value_t::number_integer:
14084 case detail::value_t::number_unsigned:
14085 case detail::value_t::number_float:
14086 case detail::value_t::binary:
14087 case detail::value_t::discarded:
14088 default:
14089 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14090 }
14091 }
14092
14093 return *ptr;
14094 }
14095
14096 /*!
14097 @throw parse_error.106 if an array index begins with '0'
14098 @throw parse_error.109 if an array index was not a number
14099 @throw out_of_range.402 if the array index '-' is used
14100 @throw out_of_range.404 if the JSON pointer can not be resolved
14101 */
14102 template<typename BasicJsonType>
14103 BasicJsonType& get_checked(BasicJsonType* ptr) const
14104 {
14105 for (const auto& reference_token : reference_tokens)
14106 {
14107 switch (ptr->type())
14108 {
14109 case detail::value_t::object:
14110 {
14111 // note: at performs range check
14112 ptr = &ptr->at(reference_token);
14113 break;
14114 }
14115
14116 case detail::value_t::array:
14117 {
14118 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14119 {
14120 // "-" always fails the range check
14121 JSON_THROW(detail::out_of_range::create(402, detail::concat(
14122 "array index '-' (", std::to_string(ptr->m_value.array->size()),
14123 ") is out of range"), ptr));
14124 }
14125
14126 // note: at performs range check
14127 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14128 break;
14129 }
14130
14131 case detail::value_t::null:
14132 case detail::value_t::string:
14133 case detail::value_t::boolean:
14134 case detail::value_t::number_integer:
14135 case detail::value_t::number_unsigned:
14136 case detail::value_t::number_float:
14137 case detail::value_t::binary:
14138 case detail::value_t::discarded:
14139 default:
14140 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14141 }
14142 }
14143
14144 return *ptr;
14145 }
14146
14147 /*!
14148 @brief return a const reference to the pointed to value
14149
14150 @param[in] ptr a JSON value
14151
14152 @return const reference to the JSON value pointed to by the JSON
14153 pointer
14154
14155 @throw parse_error.106 if an array index begins with '0'
14156 @throw parse_error.109 if an array index was not a number
14157 @throw out_of_range.402 if the array index '-' is used
14158 @throw out_of_range.404 if the JSON pointer can not be resolved
14159 */
14160 template<typename BasicJsonType>
14161 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
14162 {
14163 for (const auto& reference_token : reference_tokens)
14164 {
14165 switch (ptr->type())
14166 {
14167 case detail::value_t::object:
14168 {
14169 // use unchecked object access
14170 ptr = &ptr->operator[](reference_token);
14171 break;
14172 }
14173
14174 case detail::value_t::array:
14175 {
14176 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14177 {
14178 // "-" cannot be used for const access
14179 JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_value.array->size()), ") is out of range"), ptr));
14180 }
14181
14182 // use unchecked array access
14183 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14184 break;
14185 }
14186
14187 case detail::value_t::null:
14188 case detail::value_t::string:
14189 case detail::value_t::boolean:
14190 case detail::value_t::number_integer:
14191 case detail::value_t::number_unsigned:
14192 case detail::value_t::number_float:
14193 case detail::value_t::binary:
14194 case detail::value_t::discarded:
14195 default:
14196 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14197 }
14198 }
14199
14200 return *ptr;
14201 }
14202
14203 /*!
14204 @throw parse_error.106 if an array index begins with '0'
14205 @throw parse_error.109 if an array index was not a number
14206 @throw out_of_range.402 if the array index '-' is used
14207 @throw out_of_range.404 if the JSON pointer can not be resolved
14208 */
14209 template<typename BasicJsonType>
14210 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
14211 {
14212 for (const auto& reference_token : reference_tokens)
14213 {
14214 switch (ptr->type())
14215 {
14216 case detail::value_t::object:
14217 {
14218 // note: at performs range check
14219 ptr = &ptr->at(reference_token);
14220 break;
14221 }
14222
14223 case detail::value_t::array:
14224 {
14225 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14226 {
14227 // "-" always fails the range check
14228 JSON_THROW(detail::out_of_range::create(402, detail::concat(
14229 "array index '-' (", std::to_string(ptr->m_value.array->size()),
14230 ") is out of range"), ptr));
14231 }
14232
14233 // note: at performs range check
14234 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14235 break;
14236 }
14237
14238 case detail::value_t::null:
14239 case detail::value_t::string:
14240 case detail::value_t::boolean:
14241 case detail::value_t::number_integer:
14242 case detail::value_t::number_unsigned:
14243 case detail::value_t::number_float:
14244 case detail::value_t::binary:
14245 case detail::value_t::discarded:
14246 default:
14247 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14248 }
14249 }
14250
14251 return *ptr;
14252 }
14253
14254 /*!
14255 @throw parse_error.106 if an array index begins with '0'
14256 @throw parse_error.109 if an array index was not a number
14257 */
14258 template<typename BasicJsonType>
14259 bool contains(const BasicJsonType* ptr) const
14260 {
14261 for (const auto& reference_token : reference_tokens)
14262 {
14263 switch (ptr->type())
14264 {
14265 case detail::value_t::object:
14266 {
14267 if (!ptr->contains(reference_token))
14268 {
14269 // we did not find the key in the object
14270 return false;
14271 }
14272
14273 ptr = &ptr->operator[](reference_token);
14274 break;
14275 }
14276
14277 case detail::value_t::array:
14278 {
14279 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14280 {
14281 // "-" always fails the range check
14282 return false;
14283 }
14284 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
14285 {
14286 // invalid char
14287 return false;
14288 }
14289 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
14290 {
14291 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
14292 {
14293 // first char should be between '1' and '9'
14294 return false;
14295 }
14296 for (std::size_t i = 1; i < reference_token.size(); i++)
14297 {
14298 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
14299 {
14300 // other char should be between '0' and '9'
14301 return false;
14302 }
14303 }
14304 }
14305
14306 const auto idx = array_index<BasicJsonType>(reference_token);
14307 if (idx >= ptr->size())
14308 {
14309 // index out of range
14310 return false;
14311 }
14312
14313 ptr = &ptr->operator[](idx);
14314 break;
14315 }
14316
14317 case detail::value_t::null:
14318 case detail::value_t::string:
14319 case detail::value_t::boolean:
14320 case detail::value_t::number_integer:
14321 case detail::value_t::number_unsigned:
14322 case detail::value_t::number_float:
14323 case detail::value_t::binary:
14324 case detail::value_t::discarded:
14325 default:
14326 {
14327 // we do not expect primitive values if there is still a
14328 // reference token to process
14329 return false;
14330 }
14331 }
14332 }
14333
14334 // no reference token left means we found a primitive value
14335 return true;
14336 }
14337
14338 /*!
14339 @brief split the string input to reference tokens
14340
14341 @note This function is only called by the json_pointer constructor.
14342 All exceptions below are documented there.
14343
14344 @throw parse_error.107 if the pointer is not empty or begins with '/'
14345 @throw parse_error.108 if character '~' is not followed by '0' or '1'
14346 */
14347 static std::vector<string_t> split(const string_t& reference_string)
14348 {
14349 std::vector<string_t> result;
14350
14351 // special case: empty reference string -> no reference tokens
14352 if (reference_string.empty())
14353 {
14354 return result;
14355 }
14356
14357 // check if nonempty reference string begins with slash
14358 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
14359 {
14360 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
14361 }
14362
14363 // extract the reference tokens:
14364 // - slash: position of the last read slash (or end of string)
14365 // - start: position after the previous slash
14366 for (
14367 // search for the first slash after the first character
14368 std::size_t slash = reference_string.find_first_of('/', 1),
14369 // set the beginning of the first reference token
14370 start = 1;
14371 // we can stop if start == 0 (if slash == string_t::npos)
14372 start != 0;
14373 // set the beginning of the next reference token
14374 // (will eventually be 0 if slash == string_t::npos)
14375 start = (slash == string_t::npos) ? 0 : slash + 1,
14376 // find next slash
14377 slash = reference_string.find_first_of('/', start))
14378 {
14379 // use the text between the beginning of the reference token
14380 // (start) and the last slash (slash).
14381 auto reference_token = reference_string.substr(start, slash - start);
14382
14383 // check reference tokens are properly escaped
14384 for (std::size_t pos = reference_token.find_first_of('~');
14385 pos != string_t::npos;
14386 pos = reference_token.find_first_of('~', pos + 1))
14387 {
14388 JSON_ASSERT(reference_token[pos] == '~');
14389
14390 // ~ must be followed by 0 or 1
14391 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
14392 (reference_token[pos + 1] != '0' &&
14393 reference_token[pos + 1] != '1')))
14394 {
14395 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
14396 }
14397 }
14398
14399 // finally, store the reference token
14400 detail::unescape(reference_token);
14401 result.push_back(reference_token);
14402 }
14403
14404 return result;
14405 }
14406
14407 private:
14408 /*!
14409 @param[in] reference_string the reference string to the current value
14410 @param[in] value the value to consider
14411 @param[in,out] result the result object to insert values to
14412
14413 @note Empty objects or arrays are flattened to `null`.
14414 */
14415 template<typename BasicJsonType>
14416 static void flatten(const string_t& reference_string,
14417 const BasicJsonType& value,
14418 BasicJsonType& result)
14419 {
14420 switch (value.type())
14421 {
14422 case detail::value_t::array:
14423 {
14424 if (value.m_value.array->empty())
14425 {
14426 // flatten empty array as null
14427 result[reference_string] = nullptr;
14428 }
14429 else
14430 {
14431 // iterate array and use index as reference string
14432 for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
14433 {
14434 flatten(detail::concat(reference_string, '/', std::to_string(i)),
14435 value.m_value.array->operator[](i), result);
14436 }
14437 }
14438 break;
14439 }
14440
14441 case detail::value_t::object:
14442 {
14443 if (value.m_value.object->empty())
14444 {
14445 // flatten empty object as null
14446 result[reference_string] = nullptr;
14447 }
14448 else
14449 {
14450 // iterate object and use keys as reference string
14451 for (const auto& element : *value.m_value.object)
14452 {
14453 flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result);
14454 }
14455 }
14456 break;
14457 }
14458
14459 case detail::value_t::null:
14460 case detail::value_t::string:
14461 case detail::value_t::boolean:
14462 case detail::value_t::number_integer:
14463 case detail::value_t::number_unsigned:
14464 case detail::value_t::number_float:
14465 case detail::value_t::binary:
14466 case detail::value_t::discarded:
14467 default:
14468 {
14469 // add primitive value with its reference string
14470 result[reference_string] = value;
14471 break;
14472 }
14473 }
14474 }
14475
14476 /*!
14477 @param[in] value flattened JSON
14478
14479 @return unflattened JSON
14480
14481 @throw parse_error.109 if array index is not a number
14482 @throw type_error.314 if value is not an object
14483 @throw type_error.315 if object values are not primitive
14484 @throw type_error.313 if value cannot be unflattened
14485 */
14486 template<typename BasicJsonType>
14487 static BasicJsonType
14488 unflatten(const BasicJsonType& value)
14489 {
14490 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
14491 {
14492 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
14493 }
14494
14495 BasicJsonType result;
14496
14497 // iterate the JSON object values
14498 for (const auto& element : *value.m_value.object)
14499 {
14500 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
14501 {
14502 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
14503 }
14504
14505 // assign value to reference pointed to by JSON pointer; Note that if
14506 // the JSON pointer is "" (i.e., points to the whole value), function
14507 // get_and_create returns a reference to result itself. An assignment
14508 // will then create a primitive value.
14509 json_pointer(element.first).get_and_create(result) = element.second;
14510 }
14511
14512 return result;
14513 }
14514
14515 // can't use conversion operator because of ambiguity
14516 json_pointer<string_t> convert() const&
14517 {
14518 json_pointer<string_t> result;
14519 result.reference_tokens = reference_tokens;
14520 return result;
14521 }
14522
14523 json_pointer<string_t> convert()&&
14524 {
14525 json_pointer<string_t> result;
14526 result.reference_tokens = std::move(reference_tokens);
14527 return result;
14528 }
14529
14530 public:
14531#if JSON_HAS_THREE_WAY_COMPARISON
14532 /// @brief compares two JSON pointers for equality
14533 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
14534 template<typename RefStringTypeRhs>
14535 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
14536 {
14537 return reference_tokens == rhs.reference_tokens;
14538 }
14539
14540 /// @brief compares JSON pointer and string for equality
14541 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
14542 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
14543 bool operator==(const string_t& rhs) const
14544 {
14545 return *this == json_pointer(rhs);
14546 }
14547
14548 /// @brief 3-way compares two JSON pointers
14549 template<typename RefStringTypeRhs>
14550 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
14551 {
14552 return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
14553 }
14554#else
14555 /// @brief compares two JSON pointers for equality
14556 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
14557 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14558 // NOLINTNEXTLINE(readability-redundant-declaration)
14559 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14560 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14561
14562 /// @brief compares JSON pointer and string for equality
14563 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
14564 template<typename RefStringTypeLhs, typename StringType>
14565 // NOLINTNEXTLINE(readability-redundant-declaration)
14566 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14567 const StringType& rhs);
14568
14569 /// @brief compares string and JSON pointer for equality
14570 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
14571 template<typename RefStringTypeRhs, typename StringType>
14572 // NOLINTNEXTLINE(readability-redundant-declaration)
14573 friend bool operator==(const StringType& lhs,
14574 const json_pointer<RefStringTypeRhs>& rhs);
14575
14576 /// @brief compares two JSON pointers for inequality
14577 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
14578 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14579 // NOLINTNEXTLINE(readability-redundant-declaration)
14580 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14581 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14582
14583 /// @brief compares JSON pointer and string for inequality
14584 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
14585 template<typename RefStringTypeLhs, typename StringType>
14586 // NOLINTNEXTLINE(readability-redundant-declaration)
14587 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14588 const StringType& rhs);
14589
14590 /// @brief compares string and JSON pointer for inequality
14591 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
14592 template<typename RefStringTypeRhs, typename StringType>
14593 // NOLINTNEXTLINE(readability-redundant-declaration)
14594 friend bool operator!=(const StringType& lhs,
14595 const json_pointer<RefStringTypeRhs>& rhs);
14596
14597 /// @brief compares two JSON pointer for less-than
14598 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14599 // NOLINTNEXTLINE(readability-redundant-declaration)
14600 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
14601 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14602#endif
14603
14604 private:
14605 /// the reference tokens
14606 std::vector<string_t> reference_tokens;
14607};
14608
14609#if !JSON_HAS_THREE_WAY_COMPARISON
14610// functions cannot be defined inside class due to ODR violations
14611template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14612inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14613 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14614{
14615 return lhs.reference_tokens == rhs.reference_tokens;
14616}
14617
14618template<typename RefStringTypeLhs,
14619 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14620JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
14621inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14622 const StringType& rhs)
14623{
14624 return lhs == json_pointer<RefStringTypeLhs>(rhs);
14625}
14626
14627template<typename RefStringTypeRhs,
14628 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14629JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
14630inline bool operator==(const StringType& lhs,
14631 const json_pointer<RefStringTypeRhs>& rhs)
14632{
14633 return json_pointer<RefStringTypeRhs>(lhs) == rhs;
14634}
14635
14636template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14637inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14638 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14639{
14640 return !(lhs == rhs);
14641}
14642
14643template<typename RefStringTypeLhs,
14644 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14645JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
14646inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14647 const StringType& rhs)
14648{
14649 return !(lhs == rhs);
14650}
14651
14652template<typename RefStringTypeRhs,
14653 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14654JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
14655inline bool operator!=(const StringType& lhs,
14656 const json_pointer<RefStringTypeRhs>& rhs)
14657{
14658 return !(lhs == rhs);
14659}
14660
14661template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14662inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
14663 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14664{
14665 return lhs.reference_tokens < rhs.reference_tokens;
14666}
14667#endif
14668
14669NLOHMANN_JSON_NAMESPACE_END
14670
14671// #include <nlohmann/detail/json_ref.hpp>
14672// __ _____ _____ _____
14673// __| | __| | | | JSON for Modern C++
14674// | | |__ | | | | | | version 3.11.2
14675// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14676//
14677// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
14678// SPDX-License-Identifier: MIT
14679
14680
14681
14682#include <initializer_list>
14683#include <utility>
14684
14685// #include <nlohmann/detail/abi_macros.hpp>
14686
14687// #include <nlohmann/detail/meta/type_traits.hpp>
14688
14689
14690NLOHMANN_JSON_NAMESPACE_BEGIN
14691namespace detail
14692{
14693
14694template<typename BasicJsonType>
14695class json_ref
14696{
14697 public:
14698 using value_type = BasicJsonType;
14699
14700 json_ref(value_type&& value)
14701 : owned_value(std::move(value))
14702 {}
14703
14704 json_ref(const value_type& value)
14705 : value_ref(&value)
14706 {}
14707
14708 json_ref(std::initializer_list<json_ref> init)
14709 : owned_value(init)
14710 {}
14711
14712 template <
14713 class... Args,
14714 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
14715 json_ref(Args && ... args)
14716 : owned_value(std::forward<Args>(args)...)
14717 {}
14718
14719 // class should be movable only
14720 json_ref(json_ref&&) noexcept = default;
14721 json_ref(const json_ref&) = delete;
14722 json_ref& operator=(const json_ref&) = delete;
14723 json_ref& operator=(json_ref&&) = delete;
14724 ~json_ref() = default;
14725
14726 value_type moved_or_copied() const
14727 {
14728 if (value_ref == nullptr)
14729 {
14730 return std::move(owned_value);
14731 }
14732 return *value_ref;
14733 }
14734
14735 value_type const& operator*() const
14736 {
14737 return value_ref ? *value_ref : owned_value;
14738 }
14739
14740 value_type const* operator->() const
14741 {
14742 return &** this;
14743 }
14744
14745 private:
14746 mutable value_type owned_value = nullptr;
14747 value_type const* value_ref = nullptr;
14748};
14749
14750} // namespace detail
14751NLOHMANN_JSON_NAMESPACE_END
14752
14753// #include <nlohmann/detail/macro_scope.hpp>
14754
14755// #include <nlohmann/detail/string_concat.hpp>
14756
14757// #include <nlohmann/detail/string_escape.hpp>
14758
14759// #include <nlohmann/detail/meta/cpp_future.hpp>
14760
14761// #include <nlohmann/detail/meta/type_traits.hpp>
14762
14763// #include <nlohmann/detail/output/binary_writer.hpp>
14764// __ _____ _____ _____
14765// __| | __| | | | JSON for Modern C++
14766// | | |__ | | | | | | version 3.11.2
14767// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14768//
14769// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
14770// SPDX-License-Identifier: MIT
14771
14772
14773
14774#include <algorithm> // reverse
14775#include <array> // array
14776#include <map> // map
14777#include <cmath> // isnan, isinf
14778#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
14779#include <cstring> // memcpy
14780#include <limits> // numeric_limits
14781#include <string> // string
14782#include <utility> // move
14783#include <vector> // vector
14784
14785// #include <nlohmann/detail/input/binary_reader.hpp>
14786
14787// #include <nlohmann/detail/macro_scope.hpp>
14788
14789// #include <nlohmann/detail/output/output_adapters.hpp>
14790// __ _____ _____ _____
14791// __| | __| | | | JSON for Modern C++
14792// | | |__ | | | | | | version 3.11.2
14793// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14794//
14795// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
14796// SPDX-License-Identifier: MIT
14797
14798
14799
14800#include <algorithm> // copy
14801#include <cstddef> // size_t
14802#include <iterator> // back_inserter
14803#include <memory> // shared_ptr, make_shared
14804#include <string> // basic_string
14805#include <vector> // vector
14806
14807#ifndef JSON_NO_IO
14808 #include <ios> // streamsize
14809 #include <ostream> // basic_ostream
14810#endif // JSON_NO_IO
14811
14812// #include <nlohmann/detail/macro_scope.hpp>
14813
14814
14815NLOHMANN_JSON_NAMESPACE_BEGIN
14816namespace detail
14817{
14818
14819/// abstract output adapter interface
14820template<typename CharType> struct output_adapter_protocol
14821{
14822 virtual void write_character(CharType c) = 0;
14823 virtual void write_characters(const CharType* s, std::size_t length) = 0;
14824 virtual ~output_adapter_protocol() = default;
14825
14826 output_adapter_protocol() = default;
14827 output_adapter_protocol(const output_adapter_protocol&) = default;
14828 output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
14829 output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
14830 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
14831};
14832
14833/// a type to simplify interfaces
14834template<typename CharType>
14835using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
14836
14837/// output adapter for byte vectors
14838template<typename CharType, typename AllocatorType = std::allocator<CharType>>
14839class output_vector_adapter : public output_adapter_protocol<CharType>
14840{
14841 public:
14842 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
14843 : v(vec)
14844 {}
14845
14846 void write_character(CharType c) override
14847 {
14848 v.push_back(c);
14849 }
14850
14851 JSON_HEDLEY_NON_NULL(2)
14852 void write_characters(const CharType* s, std::size_t length) override
14853 {
14854 v.insert(v.end(), s, s + length);
14855 }
14856
14857 private:
14858 std::vector<CharType, AllocatorType>& v;
14859};
14860
14861#ifndef JSON_NO_IO
14862/// output adapter for output streams
14863template<typename CharType>
14864class output_stream_adapter : public output_adapter_protocol<CharType>
14865{
14866 public:
14867 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
14868 : stream(s)
14869 {}
14870
14871 void write_character(CharType c) override
14872 {
14873 stream.put(c);
14874 }
14875
14876 JSON_HEDLEY_NON_NULL(2)
14877 void write_characters(const CharType* s, std::size_t length) override
14878 {
14879 stream.write(s, static_cast<std::streamsize>(length));
14880 }
14881
14882 private:
14883 std::basic_ostream<CharType>& stream;
14884};
14885#endif // JSON_NO_IO
14886
14887/// output adapter for basic_string
14888template<typename CharType, typename StringType = std::basic_string<CharType>>
14889class output_string_adapter : public output_adapter_protocol<CharType>
14890{
14891 public:
14892 explicit output_string_adapter(StringType& s) noexcept
14893 : str(s)
14894 {}
14895
14896 void write_character(CharType c) override
14897 {
14898 str.push_back(c);
14899 }
14900
14901 JSON_HEDLEY_NON_NULL(2)
14902 void write_characters(const CharType* s, std::size_t length) override
14903 {
14904 str.append(s, length);
14905 }
14906
14907 private:
14908 StringType& str;
14909};
14910
14911template<typename CharType, typename StringType = std::basic_string<CharType>>
14912class output_adapter
14913{
14914 public:
14915 template<typename AllocatorType = std::allocator<CharType>>
14916 output_adapter(std::vector<CharType, AllocatorType>& vec)
14917 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
14918
14919#ifndef JSON_NO_IO
14920 output_adapter(std::basic_ostream<CharType>& s)
14921 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
14922#endif // JSON_NO_IO
14923
14924 output_adapter(StringType& s)
14925 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
14926
14927 operator output_adapter_t<CharType>()
14928 {
14929 return oa;
14930 }
14931
14932 private:
14933 output_adapter_t<CharType> oa = nullptr;
14934};
14935
14936} // namespace detail
14937NLOHMANN_JSON_NAMESPACE_END
14938
14939// #include <nlohmann/detail/string_concat.hpp>
14940
14941
14942NLOHMANN_JSON_NAMESPACE_BEGIN
14943namespace detail
14944{
14945
14946///////////////////
14947// binary writer //
14948///////////////////
14949
14950/*!
14951@brief serialization to CBOR and MessagePack values
14952*/
14953template<typename BasicJsonType, typename CharType>
14954class binary_writer
14955{
14956 using string_t = typename BasicJsonType::string_t;
14957 using binary_t = typename BasicJsonType::binary_t;
14958 using number_float_t = typename BasicJsonType::number_float_t;
14959
14960 public:
14961 /*!
14962 @brief create a binary writer
14963
14964 @param[in] adapter output adapter to write to
14965 */
14966 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
14967 {
14968 JSON_ASSERT(oa);
14969 }
14970
14971 /*!
14972 @param[in] j JSON value to serialize
14973 @pre j.type() == value_t::object
14974 */
14975 void write_bson(const BasicJsonType& j)
14976 {
14977 switch (j.type())
14978 {
14979 case value_t::object:
14980 {
14981 write_bson_object(*j.m_value.object);
14982 break;
14983 }
14984
14985 case value_t::null:
14986 case value_t::array:
14987 case value_t::string:
14988 case value_t::boolean:
14989 case value_t::number_integer:
14990 case value_t::number_unsigned:
14991 case value_t::number_float:
14992 case value_t::binary:
14993 case value_t::discarded:
14994 default:
14995 {
14996 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
14997 }
14998 }
14999 }
15000
15001 /*!
15002 @param[in] j JSON value to serialize
15003 */
15004 void write_cbor(const BasicJsonType& j)
15005 {
15006 switch (j.type())
15007 {
15008 case value_t::null:
15009 {
15010 oa->write_character(to_char_type(0xF6));
15011 break;
15012 }
15013
15014 case value_t::boolean:
15015 {
15016 oa->write_character(j.m_value.boolean
15017 ? to_char_type(0xF5)
15018 : to_char_type(0xF4));
15019 break;
15020 }
15021
15022 case value_t::number_integer:
15023 {
15024 if (j.m_value.number_integer >= 0)
15025 {
15026 // CBOR does not differentiate between positive signed
15027 // integers and unsigned integers. Therefore, we used the
15028 // code from the value_t::number_unsigned case here.
15029 if (j.m_value.number_integer <= 0x17)
15030 {
15031 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
15032 }
15033 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
15034 {
15035 oa->write_character(to_char_type(0x18));
15036 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
15037 }
15038 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
15039 {
15040 oa->write_character(to_char_type(0x19));
15041 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
15042 }
15043 else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
15044 {
15045 oa->write_character(to_char_type(0x1A));
15046 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
15047 }
15048 else
15049 {
15050 oa->write_character(to_char_type(0x1B));
15051 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
15052 }
15053 }
15054 else
15055 {
15056 // The conversions below encode the sign in the first
15057 // byte, and the value is converted to a positive number.
15058 const auto positive_number = -1 - j.m_value.number_integer;
15059 if (j.m_value.number_integer >= -24)
15060 {
15061 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
15062 }
15063 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
15064 {
15065 oa->write_character(to_char_type(0x38));
15066 write_number(static_cast<std::uint8_t>(positive_number));
15067 }
15068 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
15069 {
15070 oa->write_character(to_char_type(0x39));
15071 write_number(static_cast<std::uint16_t>(positive_number));
15072 }
15073 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
15074 {
15075 oa->write_character(to_char_type(0x3A));
15076 write_number(static_cast<std::uint32_t>(positive_number));
15077 }
15078 else
15079 {
15080 oa->write_character(to_char_type(0x3B));
15081 write_number(static_cast<std::uint64_t>(positive_number));
15082 }
15083 }
15084 break;
15085 }
15086
15087 case value_t::number_unsigned:
15088 {
15089 if (j.m_value.number_unsigned <= 0x17)
15090 {
15091 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
15092 }
15093 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15094 {
15095 oa->write_character(to_char_type(0x18));
15096 write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
15097 }
15098 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15099 {
15100 oa->write_character(to_char_type(0x19));
15101 write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
15102 }
15103 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15104 {
15105 oa->write_character(to_char_type(0x1A));
15106 write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
15107 }
15108 else
15109 {
15110 oa->write_character(to_char_type(0x1B));
15111 write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
15112 }
15113 break;
15114 }
15115
15116 case value_t::number_float:
15117 {
15118 if (std::isnan(j.m_value.number_float))
15119 {
15120 // NaN is 0xf97e00 in CBOR
15121 oa->write_character(to_char_type(0xF9));
15122 oa->write_character(to_char_type(0x7E));
15123 oa->write_character(to_char_type(0x00));
15124 }
15125 else if (std::isinf(j.m_value.number_float))
15126 {
15127 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
15128 oa->write_character(to_char_type(0xf9));
15129 oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
15130 oa->write_character(to_char_type(0x00));
15131 }
15132 else
15133 {
15134 write_compact_float(j.m_value.number_float, detail::input_format_t::cbor);
15135 }
15136 break;
15137 }
15138
15139 case value_t::string:
15140 {
15141 // step 1: write control byte and the string length
15142 const auto N = j.m_value.string->size();
15143 if (N <= 0x17)
15144 {
15145 write_number(static_cast<std::uint8_t>(0x60 + N));
15146 }
15147 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15148 {
15149 oa->write_character(to_char_type(0x78));
15150 write_number(static_cast<std::uint8_t>(N));
15151 }
15152 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15153 {
15154 oa->write_character(to_char_type(0x79));
15155 write_number(static_cast<std::uint16_t>(N));
15156 }
15157 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15158 {
15159 oa->write_character(to_char_type(0x7A));
15160 write_number(static_cast<std::uint32_t>(N));
15161 }
15162 // LCOV_EXCL_START
15163 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15164 {
15165 oa->write_character(to_char_type(0x7B));
15166 write_number(static_cast<std::uint64_t>(N));
15167 }
15168 // LCOV_EXCL_STOP
15169
15170 // step 2: write the string
15171 oa->write_characters(
15172 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
15173 j.m_value.string->size());
15174 break;
15175 }
15176
15177 case value_t::array:
15178 {
15179 // step 1: write control byte and the array size
15180 const auto N = j.m_value.array->size();
15181 if (N <= 0x17)
15182 {
15183 write_number(static_cast<std::uint8_t>(0x80 + N));
15184 }
15185 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15186 {
15187 oa->write_character(to_char_type(0x98));
15188 write_number(static_cast<std::uint8_t>(N));
15189 }
15190 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15191 {
15192 oa->write_character(to_char_type(0x99));
15193 write_number(static_cast<std::uint16_t>(N));
15194 }
15195 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15196 {
15197 oa->write_character(to_char_type(0x9A));
15198 write_number(static_cast<std::uint32_t>(N));
15199 }
15200 // LCOV_EXCL_START
15201 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15202 {
15203 oa->write_character(to_char_type(0x9B));
15204 write_number(static_cast<std::uint64_t>(N));
15205 }
15206 // LCOV_EXCL_STOP
15207
15208 // step 2: write each element
15209 for (const auto& el : *j.m_value.array)
15210 {
15211 write_cbor(el);
15212 }
15213 break;
15214 }
15215
15216 case value_t::binary:
15217 {
15218 if (j.m_value.binary->has_subtype())
15219 {
15220 if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
15221 {
15222 write_number(static_cast<std::uint8_t>(0xd8));
15223 write_number(static_cast<std::uint8_t>(j.m_value.binary->subtype()));
15224 }
15225 else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
15226 {
15227 write_number(static_cast<std::uint8_t>(0xd9));
15228 write_number(static_cast<std::uint16_t>(j.m_value.binary->subtype()));
15229 }
15230 else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
15231 {
15232 write_number(static_cast<std::uint8_t>(0xda));
15233 write_number(static_cast<std::uint32_t>(j.m_value.binary->subtype()));
15234 }
15235 else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
15236 {
15237 write_number(static_cast<std::uint8_t>(0xdb));
15238 write_number(static_cast<std::uint64_t>(j.m_value.binary->subtype()));
15239 }
15240 }
15241
15242 // step 1: write control byte and the binary array size
15243 const auto N = j.m_value.binary->size();
15244 if (N <= 0x17)
15245 {
15246 write_number(static_cast<std::uint8_t>(0x40 + N));
15247 }
15248 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15249 {
15250 oa->write_character(to_char_type(0x58));
15251 write_number(static_cast<std::uint8_t>(N));
15252 }
15253 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15254 {
15255 oa->write_character(to_char_type(0x59));
15256 write_number(static_cast<std::uint16_t>(N));
15257 }
15258 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15259 {
15260 oa->write_character(to_char_type(0x5A));
15261 write_number(static_cast<std::uint32_t>(N));
15262 }
15263 // LCOV_EXCL_START
15264 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15265 {
15266 oa->write_character(to_char_type(0x5B));
15267 write_number(static_cast<std::uint64_t>(N));
15268 }
15269 // LCOV_EXCL_STOP
15270
15271 // step 2: write each element
15272 oa->write_characters(
15273 reinterpret_cast<const CharType*>(j.m_value.binary->data()),
15274 N);
15275
15276 break;
15277 }
15278
15279 case value_t::object:
15280 {
15281 // step 1: write control byte and the object size
15282 const auto N = j.m_value.object->size();
15283 if (N <= 0x17)
15284 {
15285 write_number(static_cast<std::uint8_t>(0xA0 + N));
15286 }
15287 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15288 {
15289 oa->write_character(to_char_type(0xB8));
15290 write_number(static_cast<std::uint8_t>(N));
15291 }
15292 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15293 {
15294 oa->write_character(to_char_type(0xB9));
15295 write_number(static_cast<std::uint16_t>(N));
15296 }
15297 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15298 {
15299 oa->write_character(to_char_type(0xBA));
15300 write_number(static_cast<std::uint32_t>(N));
15301 }
15302 // LCOV_EXCL_START
15303 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15304 {
15305 oa->write_character(to_char_type(0xBB));
15306 write_number(static_cast<std::uint64_t>(N));
15307 }
15308 // LCOV_EXCL_STOP
15309
15310 // step 2: write each element
15311 for (const auto& el : *j.m_value.object)
15312 {
15313 write_cbor(el.first);
15314 write_cbor(el.second);
15315 }
15316 break;
15317 }
15318
15319 case value_t::discarded:
15320 default:
15321 break;
15322 }
15323 }
15324
15325 /*!
15326 @param[in] j JSON value to serialize
15327 */
15328 void write_msgpack(const BasicJsonType& j)
15329 {
15330 switch (j.type())
15331 {
15332 case value_t::null: // nil
15333 {
15334 oa->write_character(to_char_type(0xC0));
15335 break;
15336 }
15337
15338 case value_t::boolean: // true and false
15339 {
15340 oa->write_character(j.m_value.boolean
15341 ? to_char_type(0xC3)
15342 : to_char_type(0xC2));
15343 break;
15344 }
15345
15346 case value_t::number_integer:
15347 {
15348 if (j.m_value.number_integer >= 0)
15349 {
15350 // MessagePack does not differentiate between positive
15351 // signed integers and unsigned integers. Therefore, we used
15352 // the code from the value_t::number_unsigned case here.
15353 if (j.m_value.number_unsigned < 128)
15354 {
15355 // positive fixnum
15356 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
15357 }
15358 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15359 {
15360 // uint 8
15361 oa->write_character(to_char_type(0xCC));
15362 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
15363 }
15364 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15365 {
15366 // uint 16
15367 oa->write_character(to_char_type(0xCD));
15368 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
15369 }
15370 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15371 {
15372 // uint 32
15373 oa->write_character(to_char_type(0xCE));
15374 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
15375 }
15376 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15377 {
15378 // uint 64
15379 oa->write_character(to_char_type(0xCF));
15380 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
15381 }
15382 }
15383 else
15384 {
15385 if (j.m_value.number_integer >= -32)
15386 {
15387 // negative fixnum
15388 write_number(static_cast<std::int8_t>(j.m_value.number_integer));
15389 }
15390 else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
15391 j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
15392 {
15393 // int 8
15394 oa->write_character(to_char_type(0xD0));
15395 write_number(static_cast<std::int8_t>(j.m_value.number_integer));
15396 }
15397 else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
15398 j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
15399 {
15400 // int 16
15401 oa->write_character(to_char_type(0xD1));
15402 write_number(static_cast<std::int16_t>(j.m_value.number_integer));
15403 }
15404 else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
15405 j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
15406 {
15407 // int 32
15408 oa->write_character(to_char_type(0xD2));
15409 write_number(static_cast<std::int32_t>(j.m_value.number_integer));
15410 }
15411 else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
15412 j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
15413 {
15414 // int 64
15415 oa->write_character(to_char_type(0xD3));
15416 write_number(static_cast<std::int64_t>(j.m_value.number_integer));
15417 }
15418 }
15419 break;
15420 }
15421
15422 case value_t::number_unsigned:
15423 {
15424 if (j.m_value.number_unsigned < 128)
15425 {
15426 // positive fixnum
15427 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
15428 }
15429 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15430 {
15431 // uint 8
15432 oa->write_character(to_char_type(0xCC));
15433 write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
15434 }
15435 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15436 {
15437 // uint 16
15438 oa->write_character(to_char_type(0xCD));
15439 write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
15440 }
15441 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15442 {
15443 // uint 32
15444 oa->write_character(to_char_type(0xCE));
15445 write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
15446 }
15447 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15448 {
15449 // uint 64
15450 oa->write_character(to_char_type(0xCF));
15451 write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
15452 }
15453 break;
15454 }
15455
15456 case value_t::number_float:
15457 {
15458 write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack);
15459 break;
15460 }
15461
15462 case value_t::string:
15463 {
15464 // step 1: write control byte and the string length
15465 const auto N = j.m_value.string->size();
15466 if (N <= 31)
15467 {
15468 // fixstr
15469 write_number(static_cast<std::uint8_t>(0xA0 | N));
15470 }
15471 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15472 {
15473 // str 8
15474 oa->write_character(to_char_type(0xD9));
15475 write_number(static_cast<std::uint8_t>(N));
15476 }
15477 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15478 {
15479 // str 16
15480 oa->write_character(to_char_type(0xDA));
15481 write_number(static_cast<std::uint16_t>(N));
15482 }
15483 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15484 {
15485 // str 32
15486 oa->write_character(to_char_type(0xDB));
15487 write_number(static_cast<std::uint32_t>(N));
15488 }
15489
15490 // step 2: write the string
15491 oa->write_characters(
15492 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
15493 j.m_value.string->size());
15494 break;
15495 }
15496
15497 case value_t::array:
15498 {
15499 // step 1: write control byte and the array size
15500 const auto N = j.m_value.array->size();
15501 if (N <= 15)
15502 {
15503 // fixarray
15504 write_number(static_cast<std::uint8_t>(0x90 | N));
15505 }
15506 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15507 {
15508 // array 16
15509 oa->write_character(to_char_type(0xDC));
15510 write_number(static_cast<std::uint16_t>(N));
15511 }
15512 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15513 {
15514 // array 32
15515 oa->write_character(to_char_type(0xDD));
15516 write_number(static_cast<std::uint32_t>(N));
15517 }
15518
15519 // step 2: write each element
15520 for (const auto& el : *j.m_value.array)
15521 {
15522 write_msgpack(el);
15523 }
15524 break;
15525 }
15526
15527 case value_t::binary:
15528 {
15529 // step 0: determine if the binary type has a set subtype to
15530 // determine whether or not to use the ext or fixext types
15531 const bool use_ext = j.m_value.binary->has_subtype();
15532
15533 // step 1: write control byte and the byte string length
15534 const auto N = j.m_value.binary->size();
15535 if (N <= (std::numeric_limits<std::uint8_t>::max)())
15536 {
15537 std::uint8_t output_type{};
15538 bool fixed = true;
15539 if (use_ext)
15540 {
15541 switch (N)
15542 {
15543 case 1:
15544 output_type = 0xD4; // fixext 1
15545 break;
15546 case 2:
15547 output_type = 0xD5; // fixext 2
15548 break;
15549 case 4:
15550 output_type = 0xD6; // fixext 4
15551 break;
15552 case 8:
15553 output_type = 0xD7; // fixext 8
15554 break;
15555 case 16:
15556 output_type = 0xD8; // fixext 16
15557 break;
15558 default:
15559 output_type = 0xC7; // ext 8
15560 fixed = false;
15561 break;
15562 }
15563
15564 }
15565 else
15566 {
15567 output_type = 0xC4; // bin 8
15568 fixed = false;
15569 }
15570
15571 oa->write_character(to_char_type(output_type));
15572 if (!fixed)
15573 {
15574 write_number(static_cast<std::uint8_t>(N));
15575 }
15576 }
15577 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15578 {
15579 std::uint8_t output_type = use_ext
15580 ? 0xC8 // ext 16
15581 : 0xC5; // bin 16
15582
15583 oa->write_character(to_char_type(output_type));
15584 write_number(static_cast<std::uint16_t>(N));
15585 }
15586 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15587 {
15588 std::uint8_t output_type = use_ext
15589 ? 0xC9 // ext 32
15590 : 0xC6; // bin 32
15591
15592 oa->write_character(to_char_type(output_type));
15593 write_number(static_cast<std::uint32_t>(N));
15594 }
15595
15596 // step 1.5: if this is an ext type, write the subtype
15597 if (use_ext)
15598 {
15599 write_number(static_cast<std::int8_t>(j.m_value.binary->subtype()));
15600 }
15601
15602 // step 2: write the byte string
15603 oa->write_characters(
15604 reinterpret_cast<const CharType*>(j.m_value.binary->data()),
15605 N);
15606
15607 break;
15608 }
15609
15610 case value_t::object:
15611 {
15612 // step 1: write control byte and the object size
15613 const auto N = j.m_value.object->size();
15614 if (N <= 15)
15615 {
15616 // fixmap
15617 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
15618 }
15619 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15620 {
15621 // map 16
15622 oa->write_character(to_char_type(0xDE));
15623 write_number(static_cast<std::uint16_t>(N));
15624 }
15625 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15626 {
15627 // map 32
15628 oa->write_character(to_char_type(0xDF));
15629 write_number(static_cast<std::uint32_t>(N));
15630 }
15631
15632 // step 2: write each element
15633 for (const auto& el : *j.m_value.object)
15634 {
15635 write_msgpack(el.first);
15636 write_msgpack(el.second);
15637 }
15638 break;
15639 }
15640
15641 case value_t::discarded:
15642 default:
15643 break;
15644 }
15645 }
15646
15647 /*!
15648 @param[in] j JSON value to serialize
15649 @param[in] use_count whether to use '#' prefixes (optimized format)
15650 @param[in] use_type whether to use '$' prefixes (optimized format)
15651 @param[in] add_prefix whether prefixes need to be used for this value
15652 @param[in] use_bjdata whether write in BJData format, default is false
15653 */
15654 void write_ubjson(const BasicJsonType& j, const bool use_count,
15655 const bool use_type, const bool add_prefix = true,
15656 const bool use_bjdata = false)
15657 {
15658 switch (j.type())
15659 {
15660 case value_t::null:
15661 {
15662 if (add_prefix)
15663 {
15664 oa->write_character(to_char_type('Z'));
15665 }
15666 break;
15667 }
15668
15669 case value_t::boolean:
15670 {
15671 if (add_prefix)
15672 {
15673 oa->write_character(j.m_value.boolean
15674 ? to_char_type('T')
15675 : to_char_type('F'));
15676 }
15677 break;
15678 }
15679
15680 case value_t::number_integer:
15681 {
15682 write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix, use_bjdata);
15683 break;
15684 }
15685
15686 case value_t::number_unsigned:
15687 {
15688 write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix, use_bjdata);
15689 break;
15690 }
15691
15692 case value_t::number_float:
15693 {
15694 write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix, use_bjdata);
15695 break;
15696 }
15697
15698 case value_t::string:
15699 {
15700 if (add_prefix)
15701 {
15702 oa->write_character(to_char_type('S'));
15703 }
15704 write_number_with_ubjson_prefix(j.m_value.string->size(), true, use_bjdata);
15705 oa->write_characters(
15706 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
15707 j.m_value.string->size());
15708 break;
15709 }
15710
15711 case value_t::array:
15712 {
15713 if (add_prefix)
15714 {
15715 oa->write_character(to_char_type('['));
15716 }
15717
15718 bool prefix_required = true;
15719 if (use_type && !j.m_value.array->empty())
15720 {
15721 JSON_ASSERT(use_count);
15722 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15723 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
15724 [this, first_prefix, use_bjdata](const BasicJsonType & v)
15725 {
15726 return ubjson_prefix(v, use_bjdata) == first_prefix;
15727 });
15728
15729 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
15730
15731 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15732 {
15733 prefix_required = false;
15734 oa->write_character(to_char_type('$'));
15735 oa->write_character(first_prefix);
15736 }
15737 }
15738
15739 if (use_count)
15740 {
15741 oa->write_character(to_char_type('#'));
15742 write_number_with_ubjson_prefix(j.m_value.array->size(), true, use_bjdata);
15743 }
15744
15745 for (const auto& el : *j.m_value.array)
15746 {
15747 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata);
15748 }
15749
15750 if (!use_count)
15751 {
15752 oa->write_character(to_char_type(']'));
15753 }
15754
15755 break;
15756 }
15757
15758 case value_t::binary:
15759 {
15760 if (add_prefix)
15761 {
15762 oa->write_character(to_char_type('['));
15763 }
15764
15765 if (use_type && !j.m_value.binary->empty())
15766 {
15767 JSON_ASSERT(use_count);
15768 oa->write_character(to_char_type('$'));
15769 oa->write_character('U');
15770 }
15771
15772 if (use_count)
15773 {
15774 oa->write_character(to_char_type('#'));
15775 write_number_with_ubjson_prefix(j.m_value.binary->size(), true, use_bjdata);
15776 }
15777
15778 if (use_type)
15779 {
15780 oa->write_characters(
15781 reinterpret_cast<const CharType*>(j.m_value.binary->data()),
15782 j.m_value.binary->size());
15783 }
15784 else
15785 {
15786 for (size_t i = 0; i < j.m_value.binary->size(); ++i)
15787 {
15788 oa->write_character(to_char_type('U'));
15789 oa->write_character(j.m_value.binary->data()[i]);
15790 }
15791 }
15792
15793 if (!use_count)
15794 {
15795 oa->write_character(to_char_type(']'));
15796 }
15797
15798 break;
15799 }
15800
15801 case value_t::object:
15802 {
15803 if (use_bjdata && j.m_value.object->size() == 3 && j.m_value.object->find("_ArrayType_") != j.m_value.object->end() && j.m_value.object->find("_ArraySize_") != j.m_value.object->end() && j.m_value.object->find("_ArrayData_") != j.m_value.object->end())
15804 {
15805 if (!write_bjdata_ndarray(*j.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
15806 {
15807 break;
15808 }
15809 }
15810
15811 if (add_prefix)
15812 {
15813 oa->write_character(to_char_type('{'));
15814 }
15815
15816 bool prefix_required = true;
15817 if (use_type && !j.m_value.object->empty())
15818 {
15819 JSON_ASSERT(use_count);
15820 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15821 const bool same_prefix = std::all_of(j.begin(), j.end(),
15822 [this, first_prefix, use_bjdata](const BasicJsonType & v)
15823 {
15824 return ubjson_prefix(v, use_bjdata) == first_prefix;
15825 });
15826
15827 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
15828
15829 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15830 {
15831 prefix_required = false;
15832 oa->write_character(to_char_type('$'));
15833 oa->write_character(first_prefix);
15834 }
15835 }
15836
15837 if (use_count)
15838 {
15839 oa->write_character(to_char_type('#'));
15840 write_number_with_ubjson_prefix(j.m_value.object->size(), true, use_bjdata);
15841 }
15842
15843 for (const auto& el : *j.m_value.object)
15844 {
15845 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
15846 oa->write_characters(
15847 reinterpret_cast<const CharType*>(el.first.c_str()),
15848 el.first.size());
15849 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
15850 }
15851
15852 if (!use_count)
15853 {
15854 oa->write_character(to_char_type('}'));
15855 }
15856
15857 break;
15858 }
15859
15860 case value_t::discarded:
15861 default:
15862 break;
15863 }
15864 }
15865
15866 private:
15867 //////////
15868 // BSON //
15869 //////////
15870
15871 /*!
15872 @return The size of a BSON document entry header, including the id marker
15873 and the entry name size (and its null-terminator).
15874 */
15875 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
15876 {
15877 const auto it = name.find(static_cast<typename string_t::value_type>(0));
15878 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
15879 {
15880 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
15881 static_cast<void>(j);
15882 }
15883
15884 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
15885 }
15886
15887 /*!
15888 @brief Writes the given @a element_type and @a name to the output adapter
15889 */
15890 void write_bson_entry_header(const string_t& name,
15891 const std::uint8_t element_type)
15892 {
15893 oa->write_character(to_char_type(element_type)); // boolean
15894 oa->write_characters(
15895 reinterpret_cast<const CharType*>(name.c_str()),
15896 name.size() + 1u);
15897 }
15898
15899 /*!
15900 @brief Writes a BSON element with key @a name and boolean value @a value
15901 */
15902 void write_bson_boolean(const string_t& name,
15903 const bool value)
15904 {
15905 write_bson_entry_header(name, 0x08);
15906 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
15907 }
15908
15909 /*!
15910 @brief Writes a BSON element with key @a name and double value @a value
15911 */
15912 void write_bson_double(const string_t& name,
15913 const double value)
15914 {
15915 write_bson_entry_header(name, 0x01);
15916 write_number<double>(value, true);
15917 }
15918
15919 /*!
15920 @return The size of the BSON-encoded string in @a value
15921 */
15922 static std::size_t calc_bson_string_size(const string_t& value)
15923 {
15924 return sizeof(std::int32_t) + value.size() + 1ul;
15925 }
15926
15927 /*!
15928 @brief Writes a BSON element with key @a name and string value @a value
15929 */
15930 void write_bson_string(const string_t& name,
15931 const string_t& value)
15932 {
15933 write_bson_entry_header(name, 0x02);
15934
15935 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
15936 oa->write_characters(
15937 reinterpret_cast<const CharType*>(value.c_str()),
15938 value.size() + 1);
15939 }
15940
15941 /*!
15942 @brief Writes a BSON element with key @a name and null value
15943 */
15944 void write_bson_null(const string_t& name)
15945 {
15946 write_bson_entry_header(name, 0x0A);
15947 }
15948
15949 /*!
15950 @return The size of the BSON-encoded integer @a value
15951 */
15952 static std::size_t calc_bson_integer_size(const std::int64_t value)
15953 {
15954 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
15955 ? sizeof(std::int32_t)
15956 : sizeof(std::int64_t);
15957 }
15958
15959 /*!
15960 @brief Writes a BSON element with key @a name and integer @a value
15961 */
15962 void write_bson_integer(const string_t& name,
15963 const std::int64_t value)
15964 {
15965 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
15966 {
15967 write_bson_entry_header(name, 0x10); // int32
15968 write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
15969 }
15970 else
15971 {
15972 write_bson_entry_header(name, 0x12); // int64
15973 write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
15974 }
15975 }
15976
15977 /*!
15978 @return The size of the BSON-encoded unsigned integer in @a j
15979 */
15980 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
15981 {
15982 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
15983 ? sizeof(std::int32_t)
15984 : sizeof(std::int64_t);
15985 }
15986
15987 /*!
15988 @brief Writes a BSON element with key @a name and unsigned @a value
15989 */
15990 void write_bson_unsigned(const string_t& name,
15991 const BasicJsonType& j)
15992 {
15993 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
15994 {
15995 write_bson_entry_header(name, 0x10 /* int32 */);
15996 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_value.number_unsigned), true);
15997 }
15998 else if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
15999 {
16000 write_bson_entry_header(name, 0x12 /* int64 */);
16001 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_value.number_unsigned), true);
16002 }
16003 else
16004 {
16005 JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j));
16006 }
16007 }
16008
16009 /*!
16010 @brief Writes a BSON element with key @a name and object @a value
16011 */
16012 void write_bson_object_entry(const string_t& name,
16013 const typename BasicJsonType::object_t& value)
16014 {
16015 write_bson_entry_header(name, 0x03); // object
16016 write_bson_object(value);
16017 }
16018
16019 /*!
16020 @return The size of the BSON-encoded array @a value
16021 */
16022 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
16023 {
16024 std::size_t array_index = 0ul;
16025
16026 const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
16027 {
16028 return result + calc_bson_element_size(std::to_string(array_index++), el);
16029 });
16030
16031 return sizeof(std::int32_t) + embedded_document_size + 1ul;
16032 }
16033
16034 /*!
16035 @return The size of the BSON-encoded binary array @a value
16036 */
16037 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
16038 {
16039 return sizeof(std::int32_t) + value.size() + 1ul;
16040 }
16041
16042 /*!
16043 @brief Writes a BSON element with key @a name and array @a value
16044 */
16045 void write_bson_array(const string_t& name,
16046 const typename BasicJsonType::array_t& value)
16047 {
16048 write_bson_entry_header(name, 0x04); // array
16049 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
16050
16051 std::size_t array_index = 0ul;
16052
16053 for (const auto& el : value)
16054 {
16055 write_bson_element(std::to_string(array_index++), el);
16056 }
16057
16058 oa->write_character(to_char_type(0x00));
16059 }
16060
16061 /*!
16062 @brief Writes a BSON element with key @a name and binary value @a value
16063 */
16064 void write_bson_binary(const string_t& name,
16065 const binary_t& value)
16066 {
16067 write_bson_entry_header(name, 0x05);
16068
16069 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
16070 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
16071
16072 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
16073 }
16074
16075 /*!
16076 @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
16077 @return The calculated size for the BSON document entry for @a j with the given @a name.
16078 */
16079 static std::size_t calc_bson_element_size(const string_t& name,
16080 const BasicJsonType& j)
16081 {
16082 const auto header_size = calc_bson_entry_header_size(name, j);
16083 switch (j.type())
16084 {
16085 case value_t::object:
16086 return header_size + calc_bson_object_size(*j.m_value.object);
16087
16088 case value_t::array:
16089 return header_size + calc_bson_array_size(*j.m_value.array);
16090
16091 case value_t::binary:
16092 return header_size + calc_bson_binary_size(*j.m_value.binary);
16093
16094 case value_t::boolean:
16095 return header_size + 1ul;
16096
16097 case value_t::number_float:
16098 return header_size + 8ul;
16099
16100 case value_t::number_integer:
16101 return header_size + calc_bson_integer_size(j.m_value.number_integer);
16102
16103 case value_t::number_unsigned:
16104 return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
16105
16106 case value_t::string:
16107 return header_size + calc_bson_string_size(*j.m_value.string);
16108
16109 case value_t::null:
16110 return header_size + 0ul;
16111
16112 // LCOV_EXCL_START
16113 case value_t::discarded:
16114 default:
16115 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16116 return 0ul;
16117 // LCOV_EXCL_STOP
16118 }
16119 }
16120
16121 /*!
16122 @brief Serializes the JSON value @a j to BSON and associates it with the
16123 key @a name.
16124 @param name The name to associate with the JSON entity @a j within the
16125 current BSON document
16126 */
16127 void write_bson_element(const string_t& name,
16128 const BasicJsonType& j)
16129 {
16130 switch (j.type())
16131 {
16132 case value_t::object:
16133 return write_bson_object_entry(name, *j.m_value.object);
16134
16135 case value_t::array:
16136 return write_bson_array(name, *j.m_value.array);
16137
16138 case value_t::binary:
16139 return write_bson_binary(name, *j.m_value.binary);
16140
16141 case value_t::boolean:
16142 return write_bson_boolean(name, j.m_value.boolean);
16143
16144 case value_t::number_float:
16145 return write_bson_double(name, j.m_value.number_float);
16146
16147 case value_t::number_integer:
16148 return write_bson_integer(name, j.m_value.number_integer);
16149
16150 case value_t::number_unsigned:
16151 return write_bson_unsigned(name, j);
16152
16153 case value_t::string:
16154 return write_bson_string(name, *j.m_value.string);
16155
16156 case value_t::null:
16157 return write_bson_null(name);
16158
16159 // LCOV_EXCL_START
16160 case value_t::discarded:
16161 default:
16162 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16163 return;
16164 // LCOV_EXCL_STOP
16165 }
16166 }
16167
16168 /*!
16169 @brief Calculates the size of the BSON serialization of the given
16170 JSON-object @a j.
16171 @param[in] value JSON value to serialize
16172 @pre value.type() == value_t::object
16173 */
16174 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
16175 {
16176 std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
16177 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
16178 {
16179 return result += calc_bson_element_size(el.first, el.second);
16180 });
16181
16182 return sizeof(std::int32_t) + document_size + 1ul;
16183 }
16184
16185 /*!
16186 @param[in] value JSON value to serialize
16187 @pre value.type() == value_t::object
16188 */
16189 void write_bson_object(const typename BasicJsonType::object_t& value)
16190 {
16191 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
16192
16193 for (const auto& el : value)
16194 {
16195 write_bson_element(el.first, el.second);
16196 }
16197
16198 oa->write_character(to_char_type(0x00));
16199 }
16200
16201 //////////
16202 // CBOR //
16203 //////////
16204
16205 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
16206 {
16207 return to_char_type(0xFA); // Single-Precision Float
16208 }
16209
16210 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
16211 {
16212 return to_char_type(0xFB); // Double-Precision Float
16213 }
16214
16215 /////////////
16216 // MsgPack //
16217 /////////////
16218
16219 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
16220 {
16221 return to_char_type(0xCA); // float 32
16222 }
16223
16224 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
16225 {
16226 return to_char_type(0xCB); // float 64
16227 }
16228
16229 ////////////
16230 // UBJSON //
16231 ////////////
16232
16233 // UBJSON: write number (floating point)
16234 template<typename NumberType, typename std::enable_if<
16235 std::is_floating_point<NumberType>::value, int>::type = 0>
16236 void write_number_with_ubjson_prefix(const NumberType n,
16237 const bool add_prefix,
16238 const bool use_bjdata)
16239 {
16240 if (add_prefix)
16241 {
16242 oa->write_character(get_ubjson_float_prefix(n));
16243 }
16244 write_number(n, use_bjdata);
16245 }
16246
16247 // UBJSON: write number (unsigned integer)
16248 template<typename NumberType, typename std::enable_if<
16249 std::is_unsigned<NumberType>::value, int>::type = 0>
16250 void write_number_with_ubjson_prefix(const NumberType n,
16251 const bool add_prefix,
16252 const bool use_bjdata)
16253 {
16254 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16255 {
16256 if (add_prefix)
16257 {
16258 oa->write_character(to_char_type('i')); // int8
16259 }
16260 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16261 }
16262 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
16263 {
16264 if (add_prefix)
16265 {
16266 oa->write_character(to_char_type('U')); // uint8
16267 }
16268 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16269 }
16270 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16271 {
16272 if (add_prefix)
16273 {
16274 oa->write_character(to_char_type('I')); // int16
16275 }
16276 write_number(static_cast<std::int16_t>(n), use_bjdata);
16277 }
16278 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
16279 {
16280 if (add_prefix)
16281 {
16282 oa->write_character(to_char_type('u')); // uint16 - bjdata only
16283 }
16284 write_number(static_cast<std::uint16_t>(n), use_bjdata);
16285 }
16286 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16287 {
16288 if (add_prefix)
16289 {
16290 oa->write_character(to_char_type('l')); // int32
16291 }
16292 write_number(static_cast<std::int32_t>(n), use_bjdata);
16293 }
16294 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
16295 {
16296 if (add_prefix)
16297 {
16298 oa->write_character(to_char_type('m')); // uint32 - bjdata only
16299 }
16300 write_number(static_cast<std::uint32_t>(n), use_bjdata);
16301 }
16302 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16303 {
16304 if (add_prefix)
16305 {
16306 oa->write_character(to_char_type('L')); // int64
16307 }
16308 write_number(static_cast<std::int64_t>(n), use_bjdata);
16309 }
16310 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
16311 {
16312 if (add_prefix)
16313 {
16314 oa->write_character(to_char_type('M')); // uint64 - bjdata only
16315 }
16316 write_number(static_cast<std::uint64_t>(n), use_bjdata);
16317 }
16318 else
16319 {
16320 if (add_prefix)
16321 {
16322 oa->write_character(to_char_type('H')); // high-precision number
16323 }
16324
16325 const auto number = BasicJsonType(n).dump();
16326 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16327 for (std::size_t i = 0; i < number.size(); ++i)
16328 {
16329 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16330 }
16331 }
16332 }
16333
16334 // UBJSON: write number (signed integer)
16335 template < typename NumberType, typename std::enable_if <
16336 std::is_signed<NumberType>::value&&
16337 !std::is_floating_point<NumberType>::value, int >::type = 0 >
16338 void write_number_with_ubjson_prefix(const NumberType n,
16339 const bool add_prefix,
16340 const bool use_bjdata)
16341 {
16342 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
16343 {
16344 if (add_prefix)
16345 {
16346 oa->write_character(to_char_type('i')); // int8
16347 }
16348 write_number(static_cast<std::int8_t>(n), use_bjdata);
16349 }
16350 else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
16351 {
16352 if (add_prefix)
16353 {
16354 oa->write_character(to_char_type('U')); // uint8
16355 }
16356 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16357 }
16358 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
16359 {
16360 if (add_prefix)
16361 {
16362 oa->write_character(to_char_type('I')); // int16
16363 }
16364 write_number(static_cast<std::int16_t>(n), use_bjdata);
16365 }
16366 else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)())))
16367 {
16368 if (add_prefix)
16369 {
16370 oa->write_character(to_char_type('u')); // uint16 - bjdata only
16371 }
16372 write_number(static_cast<uint16_t>(n), use_bjdata);
16373 }
16374 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
16375 {
16376 if (add_prefix)
16377 {
16378 oa->write_character(to_char_type('l')); // int32
16379 }
16380 write_number(static_cast<std::int32_t>(n), use_bjdata);
16381 }
16382 else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)())))
16383 {
16384 if (add_prefix)
16385 {
16386 oa->write_character(to_char_type('m')); // uint32 - bjdata only
16387 }
16388 write_number(static_cast<uint32_t>(n), use_bjdata);
16389 }
16390 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
16391 {
16392 if (add_prefix)
16393 {
16394 oa->write_character(to_char_type('L')); // int64
16395 }
16396 write_number(static_cast<std::int64_t>(n), use_bjdata);
16397 }
16398 // LCOV_EXCL_START
16399 else
16400 {
16401 if (add_prefix)
16402 {
16403 oa->write_character(to_char_type('H')); // high-precision number
16404 }
16405
16406 const auto number = BasicJsonType(n).dump();
16407 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16408 for (std::size_t i = 0; i < number.size(); ++i)
16409 {
16410 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16411 }
16412 }
16413 // LCOV_EXCL_STOP
16414 }
16415
16416 /*!
16417 @brief determine the type prefix of container values
16418 */
16419 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
16420 {
16421 switch (j.type())
16422 {
16423 case value_t::null:
16424 return 'Z';
16425
16426 case value_t::boolean:
16427 return j.m_value.boolean ? 'T' : 'F';
16428
16429 case value_t::number_integer:
16430 {
16431 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
16432 {
16433 return 'i';
16434 }
16435 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
16436 {
16437 return 'U';
16438 }
16439 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
16440 {
16441 return 'I';
16442 }
16443 if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
16444 {
16445 return 'u';
16446 }
16447 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
16448 {
16449 return 'l';
16450 }
16451 if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
16452 {
16453 return 'm';
16454 }
16455 if ((std::numeric_limits<std::int64_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
16456 {
16457 return 'L';
16458 }
16459 // anything else is treated as high-precision number
16460 return 'H'; // LCOV_EXCL_LINE
16461 }
16462
16463 case value_t::number_unsigned:
16464 {
16465 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16466 {
16467 return 'i';
16468 }
16469 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
16470 {
16471 return 'U';
16472 }
16473 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16474 {
16475 return 'I';
16476 }
16477 if (use_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
16478 {
16479 return 'u';
16480 }
16481 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16482 {
16483 return 'l';
16484 }
16485 if (use_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
16486 {
16487 return 'm';
16488 }
16489 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16490 {
16491 return 'L';
16492 }
16493 if (use_bjdata && j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16494 {
16495 return 'M';
16496 }
16497 // anything else is treated as high-precision number
16498 return 'H'; // LCOV_EXCL_LINE
16499 }
16500
16501 case value_t::number_float:
16502 return get_ubjson_float_prefix(j.m_value.number_float);
16503
16504 case value_t::string:
16505 return 'S';
16506
16507 case value_t::array: // fallthrough
16508 case value_t::binary:
16509 return '[';
16510
16511 case value_t::object:
16512 return '{';
16513
16514 case value_t::discarded:
16515 default: // discarded values
16516 return 'N';
16517 }
16518 }
16519
16520 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
16521 {
16522 return 'd'; // float 32
16523 }
16524
16525 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
16526 {
16527 return 'D'; // float 64
16528 }
16529
16530 /*!
16531 @return false if the object is successfully converted to a bjdata ndarray, true if the type or size is invalid
16532 */
16533 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type)
16534 {
16535 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
16536 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'}
16537 };
16538
16539 string_t key = "_ArrayType_";
16540 auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
16541 if (it == bjdtype.end())
16542 {
16543 return true;
16544 }
16545 CharType dtype = it->second;
16546
16547 key = "_ArraySize_";
16548 std::size_t len = (value.at(key).empty() ? 0 : 1);
16549 for (const auto& el : value.at(key))
16550 {
16551 len *= static_cast<std::size_t>(el.m_value.number_unsigned);
16552 }
16553
16554 key = "_ArrayData_";
16555 if (value.at(key).size() != len)
16556 {
16557 return true;
16558 }
16559
16560 oa->write_character('[');
16561 oa->write_character('$');
16562 oa->write_character(dtype);
16563 oa->write_character('#');
16564
16565 key = "_ArraySize_";
16566 write_ubjson(value.at(key), use_count, use_type, true, true);
16567
16568 key = "_ArrayData_";
16569 if (dtype == 'U' || dtype == 'C')
16570 {
16571 for (const auto& el : value.at(key))
16572 {
16573 write_number(static_cast<std::uint8_t>(el.m_value.number_unsigned), true);
16574 }
16575 }
16576 else if (dtype == 'i')
16577 {
16578 for (const auto& el : value.at(key))
16579 {
16580 write_number(static_cast<std::int8_t>(el.m_value.number_integer), true);
16581 }
16582 }
16583 else if (dtype == 'u')
16584 {
16585 for (const auto& el : value.at(key))
16586 {
16587 write_number(static_cast<std::uint16_t>(el.m_value.number_unsigned), true);
16588 }
16589 }
16590 else if (dtype == 'I')
16591 {
16592 for (const auto& el : value.at(key))
16593 {
16594 write_number(static_cast<std::int16_t>(el.m_value.number_integer), true);
16595 }
16596 }
16597 else if (dtype == 'm')
16598 {
16599 for (const auto& el : value.at(key))
16600 {
16601 write_number(static_cast<std::uint32_t>(el.m_value.number_unsigned), true);
16602 }
16603 }
16604 else if (dtype == 'l')
16605 {
16606 for (const auto& el : value.at(key))
16607 {
16608 write_number(static_cast<std::int32_t>(el.m_value.number_integer), true);
16609 }
16610 }
16611 else if (dtype == 'M')
16612 {
16613 for (const auto& el : value.at(key))
16614 {
16615 write_number(static_cast<std::uint64_t>(el.m_value.number_unsigned), true);
16616 }
16617 }
16618 else if (dtype == 'L')
16619 {
16620 for (const auto& el : value.at(key))
16621 {
16622 write_number(static_cast<std::int64_t>(el.m_value.number_integer), true);
16623 }
16624 }
16625 else if (dtype == 'd')
16626 {
16627 for (const auto& el : value.at(key))
16628 {
16629 write_number(static_cast<float>(el.m_value.number_float), true);
16630 }
16631 }
16632 else if (dtype == 'D')
16633 {
16634 for (const auto& el : value.at(key))
16635 {
16636 write_number(static_cast<double>(el.m_value.number_float), true);
16637 }
16638 }
16639 return false;
16640 }
16641
16642 ///////////////////////
16643 // Utility functions //
16644 ///////////////////////
16645
16646 /*
16647 @brief write a number to output input
16648 @param[in] n number of type @a NumberType
16649 @param[in] OutputIsLittleEndian Set to true if output data is
16650 required to be little endian
16651 @tparam NumberType the type of the number
16652
16653 @note This function needs to respect the system's endianness, because bytes
16654 in CBOR, MessagePack, and UBJSON are stored in network order (big
16655 endian) and therefore need reordering on little endian systems.
16656 On the other hand, BSON and BJData use little endian and should reorder
16657 on big endian systems.
16658 */
16659 template<typename NumberType>
16660 void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
16661 {
16662 // step 1: write number to array of length NumberType
16663 std::array<CharType, sizeof(NumberType)> vec{};
16664 std::memcpy(vec.data(), &n, sizeof(NumberType));
16665
16666 // step 2: write array to output (with possible reordering)
16667 if (is_little_endian != OutputIsLittleEndian)
16668 {
16669 // reverse byte order prior to conversion if necessary
16670 std::reverse(vec.begin(), vec.end());
16671 }
16672
16673 oa->write_characters(vec.data(), sizeof(NumberType));
16674 }
16675
16676 void write_compact_float(const number_float_t n, detail::input_format_t format)
16677 {
16678#ifdef __GNUC__
16679#pragma GCC diagnostic push
16680#pragma GCC diagnostic ignored "-Wfloat-equal"
16681#endif
16682 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
16683 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
16684 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
16685 {
16686 oa->write_character(format == detail::input_format_t::cbor
16687 ? get_cbor_float_prefix(static_cast<float>(n))
16688 : get_msgpack_float_prefix(static_cast<float>(n)));
16689 write_number(static_cast<float>(n));
16690 }
16691 else
16692 {
16693 oa->write_character(format == detail::input_format_t::cbor
16694 ? get_cbor_float_prefix(n)
16695 : get_msgpack_float_prefix(n));
16696 write_number(n);
16697 }
16698#ifdef __GNUC__
16699#pragma GCC diagnostic pop
16700#endif
16701 }
16702
16703 public:
16704 // The following to_char_type functions are implement the conversion
16705 // between uint8_t and CharType. In case CharType is not unsigned,
16706 // such a conversion is required to allow values greater than 128.
16707 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
16708 template < typename C = CharType,
16709 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
16710 static constexpr CharType to_char_type(std::uint8_t x) noexcept
16711 {
16712 return *reinterpret_cast<char*>(&x);
16713 }
16714
16715 template < typename C = CharType,
16716 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
16717 static CharType to_char_type(std::uint8_t x) noexcept
16718 {
16719 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
16720 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
16721 CharType result;
16722 std::memcpy(&result, &x, sizeof(x));
16723 return result;
16724 }
16725
16726 template<typename C = CharType,
16727 enable_if_t<std::is_unsigned<C>::value>* = nullptr>
16728 static constexpr CharType to_char_type(std::uint8_t x) noexcept
16729 {
16730 return x;
16731 }
16732
16733 template < typename InputCharType, typename C = CharType,
16734 enable_if_t <
16735 std::is_signed<C>::value &&
16736 std::is_signed<char>::value &&
16737 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
16738 > * = nullptr >
16739 static constexpr CharType to_char_type(InputCharType x) noexcept
16740 {
16741 return x;
16742 }
16743
16744 private:
16745 /// whether we can assume little endianness
16746 const bool is_little_endian = little_endianness();
16747
16748 /// the output
16749 output_adapter_t<CharType> oa = nullptr;
16750};
16751
16752} // namespace detail
16753NLOHMANN_JSON_NAMESPACE_END
16754
16755// #include <nlohmann/detail/output/output_adapters.hpp>
16756
16757// #include <nlohmann/detail/output/serializer.hpp>
16758// __ _____ _____ _____
16759// __| | __| | | | JSON for Modern C++
16760// | | |__ | | | | | | version 3.11.2
16761// |_____|_____|_____|_|___| https://github.com/nlohmann/json
16762//
16763// SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <bjoern@hoehrmann.de>
16764// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
16765// SPDX-License-Identifier: MIT
16766
16767
16768
16769#include <algorithm> // reverse, remove, fill, find, none_of
16770#include <array> // array
16771#include <clocale> // localeconv, lconv
16772#include <cmath> // labs, isfinite, isnan, signbit
16773#include <cstddef> // size_t, ptrdiff_t
16774#include <cstdint> // uint8_t
16775#include <cstdio> // snprintf
16776#include <limits> // numeric_limits
16777#include <string> // string, char_traits
16778#include <iomanip> // setfill, setw
16779#include <type_traits> // is_same
16780#include <utility> // move
16781
16782// #include <nlohmann/detail/conversions/to_chars.hpp>
16783// __ _____ _____ _____
16784// __| | __| | | | JSON for Modern C++
16785// | | |__ | | | | | | version 3.11.2
16786// |_____|_____|_____|_|___| https://github.com/nlohmann/json
16787//
16788// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
16789// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
16790// SPDX-License-Identifier: MIT
16791
16792
16793
16794#include <array> // array
16795#include <cmath> // signbit, isfinite
16796#include <cstdint> // intN_t, uintN_t
16797#include <cstring> // memcpy, memmove
16798#include <limits> // numeric_limits
16799#include <type_traits> // conditional
16800
16801// #include <nlohmann/detail/macro_scope.hpp>
16802
16803
16804NLOHMANN_JSON_NAMESPACE_BEGIN
16805namespace detail
16806{
16807
16808/*!
16809@brief implements the Grisu2 algorithm for binary to decimal floating-point
16810conversion.
16811
16812This implementation is a slightly modified version of the reference
16813implementation which may be obtained from
16814http://florian.loitsch.com/publications (bench.tar.gz).
16815
16816The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
16817
16818For a detailed description of the algorithm see:
16819
16820[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
16821 Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
16822 Language Design and Implementation, PLDI 2010
16823[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
16824 Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
16825 Design and Implementation, PLDI 1996
16826*/
16827namespace dtoa_impl
16828{
16829
16830template<typename Target, typename Source>
16831Target reinterpret_bits(const Source source)
16832{
16833 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
16834
16835 Target target;
16836 std::memcpy(&target, &source, sizeof(Source));
16837 return target;
16838}
16839
16840struct diyfp // f * 2^e
16841{
16842 static constexpr int kPrecision = 64; // = q
16843
16844 std::uint64_t f = 0;
16845 int e = 0;
16846
16847 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
16848
16849 /*!
16850 @brief returns x - y
16851 @pre x.e == y.e and x.f >= y.f
16852 */
16853 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
16854 {
16855 JSON_ASSERT(x.e == y.e);
16856 JSON_ASSERT(x.f >= y.f);
16857
16858 return {x.f - y.f, x.e};
16859 }
16860
16861 /*!
16862 @brief returns x * y
16863 @note The result is rounded. (Only the upper q bits are returned.)
16864 */
16865 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
16866 {
16867 static_assert(kPrecision == 64, "internal error");
16868
16869 // Computes:
16870 // f = round((x.f * y.f) / 2^q)
16871 // e = x.e + y.e + q
16872
16873 // Emulate the 64-bit * 64-bit multiplication:
16874 //
16875 // p = u * v
16876 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
16877 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
16878 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
16879 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
16880 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
16881 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
16882 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
16883 //
16884 // (Since Q might be larger than 2^32 - 1)
16885 //
16886 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
16887 //
16888 // (Q_hi + H does not overflow a 64-bit int)
16889 //
16890 // = p_lo + 2^64 p_hi
16891
16892 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
16893 const std::uint64_t u_hi = x.f >> 32u;
16894 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
16895 const std::uint64_t v_hi = y.f >> 32u;
16896
16897 const std::uint64_t p0 = u_lo * v_lo;
16898 const std::uint64_t p1 = u_lo * v_hi;
16899 const std::uint64_t p2 = u_hi * v_lo;
16900 const std::uint64_t p3 = u_hi * v_hi;
16901
16902 const std::uint64_t p0_hi = p0 >> 32u;
16903 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
16904 const std::uint64_t p1_hi = p1 >> 32u;
16905 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
16906 const std::uint64_t p2_hi = p2 >> 32u;
16907
16908 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
16909
16910 // The full product might now be computed as
16911 //
16912 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
16913 // p_lo = p0_lo + (Q << 32)
16914 //
16915 // But in this particular case here, the full p_lo is not required.
16916 // Effectively we only need to add the highest bit in p_lo to p_hi (and
16917 // Q_hi + 1 does not overflow).
16918
16919 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
16920
16921 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
16922
16923 return {h, x.e + y.e + 64};
16924 }
16925
16926 /*!
16927 @brief normalize x such that the significand is >= 2^(q-1)
16928 @pre x.f != 0
16929 */
16930 static diyfp normalize(diyfp x) noexcept
16931 {
16932 JSON_ASSERT(x.f != 0);
16933
16934 while ((x.f >> 63u) == 0)
16935 {
16936 x.f <<= 1u;
16937 x.e--;
16938 }
16939
16940 return x;
16941 }
16942
16943 /*!
16944 @brief normalize x such that the result has the exponent E
16945 @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
16946 */
16947 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
16948 {
16949 const int delta = x.e - target_exponent;
16950
16951 JSON_ASSERT(delta >= 0);
16952 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
16953
16954 return {x.f << delta, target_exponent};
16955 }
16956};
16957
16958struct boundaries
16959{
16960 diyfp w;
16961 diyfp minus;
16962 diyfp plus;
16963};
16964
16965/*!
16966Compute the (normalized) diyfp representing the input number 'value' and its
16967boundaries.
16968
16969@pre value must be finite and positive
16970*/
16971template<typename FloatType>
16972boundaries compute_boundaries(FloatType value)
16973{
16974 JSON_ASSERT(std::isfinite(value));
16975 JSON_ASSERT(value > 0);
16976
16977 // Convert the IEEE representation into a diyfp.
16978 //
16979 // If v is denormal:
16980 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
16981 // If v is normalized:
16982 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
16983
16984 static_assert(std::numeric_limits<FloatType>::is_iec559,
16985 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
16986
16987 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
16988 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
16989 constexpr int kMinExp = 1 - kBias;
16990 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
16991
16992 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
16993
16994 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
16995 const std::uint64_t E = bits >> (kPrecision - 1);
16996 const std::uint64_t F = bits & (kHiddenBit - 1);
16997
16998 const bool is_denormal = E == 0;
16999 const diyfp v = is_denormal
17000 ? diyfp(F, kMinExp)
17001 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
17002
17003 // Compute the boundaries m- and m+ of the floating-point value
17004 // v = f * 2^e.
17005 //
17006 // Determine v- and v+, the floating-point predecessor and successor if v,
17007 // respectively.
17008 //
17009 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
17010 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
17011 //
17012 // v+ = v + 2^e
17013 //
17014 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
17015 // between m- and m+ round to v, regardless of how the input rounding
17016 // algorithm breaks ties.
17017 //
17018 // ---+-------------+-------------+-------------+-------------+--- (A)
17019 // v- m- v m+ v+
17020 //
17021 // -----------------+------+------+-------------+-------------+--- (B)
17022 // v- m- v m+ v+
17023
17024 const bool lower_boundary_is_closer = F == 0 && E > 1;
17025 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
17026 const diyfp m_minus = lower_boundary_is_closer
17027 ? diyfp(4 * v.f - 1, v.e - 2) // (B)
17028 : diyfp(2 * v.f - 1, v.e - 1); // (A)
17029
17030 // Determine the normalized w+ = m+.
17031 const diyfp w_plus = diyfp::normalize(m_plus);
17032
17033 // Determine w- = m- such that e_(w-) = e_(w+).
17034 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
17035
17036 return {diyfp::normalize(v), w_minus, w_plus};
17037}
17038
17039// Given normalized diyfp w, Grisu needs to find a (normalized) cached
17040// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
17041// within a certain range [alpha, gamma] (Definition 3.2 from [1])
17042//
17043// alpha <= e = e_c + e_w + q <= gamma
17044//
17045// or
17046//
17047// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
17048// <= f_c * f_w * 2^gamma
17049//
17050// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
17051//
17052// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
17053//
17054// or
17055//
17056// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
17057//
17058// The choice of (alpha,gamma) determines the size of the table and the form of
17059// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
17060// in practice:
17061//
17062// The idea is to cut the number c * w = f * 2^e into two parts, which can be
17063// processed independently: An integral part p1, and a fractional part p2:
17064//
17065// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
17066// = (f div 2^-e) + (f mod 2^-e) * 2^e
17067// = p1 + p2 * 2^e
17068//
17069// The conversion of p1 into decimal form requires a series of divisions and
17070// modulos by (a power of) 10. These operations are faster for 32-bit than for
17071// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
17072// achieved by choosing
17073//
17074// -e >= 32 or e <= -32 := gamma
17075//
17076// In order to convert the fractional part
17077//
17078// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
17079//
17080// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
17081// d[-i] are extracted in order:
17082//
17083// (10 * p2) div 2^-e = d[-1]
17084// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
17085//
17086// The multiplication by 10 must not overflow. It is sufficient to choose
17087//
17088// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
17089//
17090// Since p2 = f mod 2^-e < 2^-e,
17091//
17092// -e <= 60 or e >= -60 := alpha
17093
17094constexpr int kAlpha = -60;
17095constexpr int kGamma = -32;
17096
17097struct cached_power // c = f * 2^e ~= 10^k
17098{
17099 std::uint64_t f;
17100 int e;
17101 int k;
17102};
17103
17104/*!
17105For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
17106power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
17107satisfies (Definition 3.2 from [1])
17108
17109 alpha <= e_c + e + q <= gamma.
17110*/
17111inline cached_power get_cached_power_for_binary_exponent(int e)
17112{
17113 // Now
17114 //
17115 // alpha <= e_c + e + q <= gamma (1)
17116 // ==> f_c * 2^alpha <= c * 2^e * 2^q
17117 //
17118 // and since the c's are normalized, 2^(q-1) <= f_c,
17119 //
17120 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
17121 // ==> 2^(alpha - e - 1) <= c
17122 //
17123 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
17124 //
17125 // k = ceil( log_10( 2^(alpha - e - 1) ) )
17126 // = ceil( (alpha - e - 1) * log_10(2) )
17127 //
17128 // From the paper:
17129 // "In theory the result of the procedure could be wrong since c is rounded,
17130 // and the computation itself is approximated [...]. In practice, however,
17131 // this simple function is sufficient."
17132 //
17133 // For IEEE double precision floating-point numbers converted into
17134 // normalized diyfp's w = f * 2^e, with q = 64,
17135 //
17136 // e >= -1022 (min IEEE exponent)
17137 // -52 (p - 1)
17138 // -52 (p - 1, possibly normalize denormal IEEE numbers)
17139 // -11 (normalize the diyfp)
17140 // = -1137
17141 //
17142 // and
17143 //
17144 // e <= +1023 (max IEEE exponent)
17145 // -52 (p - 1)
17146 // -11 (normalize the diyfp)
17147 // = 960
17148 //
17149 // This binary exponent range [-1137,960] results in a decimal exponent
17150 // range [-307,324]. One does not need to store a cached power for each
17151 // k in this range. For each such k it suffices to find a cached power
17152 // such that the exponent of the product lies in [alpha,gamma].
17153 // This implies that the difference of the decimal exponents of adjacent
17154 // table entries must be less than or equal to
17155 //
17156 // floor( (gamma - alpha) * log_10(2) ) = 8.
17157 //
17158 // (A smaller distance gamma-alpha would require a larger table.)
17159
17160 // NB:
17161 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
17162
17163 constexpr int kCachedPowersMinDecExp = -300;
17164 constexpr int kCachedPowersDecStep = 8;
17165
17166 static constexpr std::array<cached_power, 79> kCachedPowers =
17167 {
17168 {
17169 { 0xAB70FE17C79AC6CA, -1060, -300 },
17170 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
17171 { 0xBE5691EF416BD60C, -1007, -284 },
17172 { 0x8DD01FAD907FFC3C, -980, -276 },
17173 { 0xD3515C2831559A83, -954, -268 },
17174 { 0x9D71AC8FADA6C9B5, -927, -260 },
17175 { 0xEA9C227723EE8BCB, -901, -252 },
17176 { 0xAECC49914078536D, -874, -244 },
17177 { 0x823C12795DB6CE57, -847, -236 },
17178 { 0xC21094364DFB5637, -821, -228 },
17179 { 0x9096EA6F3848984F, -794, -220 },
17180 { 0xD77485CB25823AC7, -768, -212 },
17181 { 0xA086CFCD97BF97F4, -741, -204 },
17182 { 0xEF340A98172AACE5, -715, -196 },
17183 { 0xB23867FB2A35B28E, -688, -188 },
17184 { 0x84C8D4DFD2C63F3B, -661, -180 },
17185 { 0xC5DD44271AD3CDBA, -635, -172 },
17186 { 0x936B9FCEBB25C996, -608, -164 },
17187 { 0xDBAC6C247D62A584, -582, -156 },
17188 { 0xA3AB66580D5FDAF6, -555, -148 },
17189 { 0xF3E2F893DEC3F126, -529, -140 },
17190 { 0xB5B5ADA8AAFF80B8, -502, -132 },
17191 { 0x87625F056C7C4A8B, -475, -124 },
17192 { 0xC9BCFF6034C13053, -449, -116 },
17193 { 0x964E858C91BA2655, -422, -108 },
17194 { 0xDFF9772470297EBD, -396, -100 },
17195 { 0xA6DFBD9FB8E5B88F, -369, -92 },
17196 { 0xF8A95FCF88747D94, -343, -84 },
17197 { 0xB94470938FA89BCF, -316, -76 },
17198 { 0x8A08F0F8BF0F156B, -289, -68 },
17199 { 0xCDB02555653131B6, -263, -60 },
17200 { 0x993FE2C6D07B7FAC, -236, -52 },
17201 { 0xE45C10C42A2B3B06, -210, -44 },
17202 { 0xAA242499697392D3, -183, -36 },
17203 { 0xFD87B5F28300CA0E, -157, -28 },
17204 { 0xBCE5086492111AEB, -130, -20 },
17205 { 0x8CBCCC096F5088CC, -103, -12 },
17206 { 0xD1B71758E219652C, -77, -4 },
17207 { 0x9C40000000000000, -50, 4 },
17208 { 0xE8D4A51000000000, -24, 12 },
17209 { 0xAD78EBC5AC620000, 3, 20 },
17210 { 0x813F3978F8940984, 30, 28 },
17211 { 0xC097CE7BC90715B3, 56, 36 },
17212 { 0x8F7E32CE7BEA5C70, 83, 44 },
17213 { 0xD5D238A4ABE98068, 109, 52 },
17214 { 0x9F4F2726179A2245, 136, 60 },
17215 { 0xED63A231D4C4FB27, 162, 68 },
17216 { 0xB0DE65388CC8ADA8, 189, 76 },
17217 { 0x83C7088E1AAB65DB, 216, 84 },
17218 { 0xC45D1DF942711D9A, 242, 92 },
17219 { 0x924D692CA61BE758, 269, 100 },
17220 { 0xDA01EE641A708DEA, 295, 108 },
17221 { 0xA26DA3999AEF774A, 322, 116 },
17222 { 0xF209787BB47D6B85, 348, 124 },
17223 { 0xB454E4A179DD1877, 375, 132 },
17224 { 0x865B86925B9BC5C2, 402, 140 },
17225 { 0xC83553C5C8965D3D, 428, 148 },
17226 { 0x952AB45CFA97A0B3, 455, 156 },
17227 { 0xDE469FBD99A05FE3, 481, 164 },
17228 { 0xA59BC234DB398C25, 508, 172 },
17229 { 0xF6C69A72A3989F5C, 534, 180 },
17230 { 0xB7DCBF5354E9BECE, 561, 188 },
17231 { 0x88FCF317F22241E2, 588, 196 },
17232 { 0xCC20CE9BD35C78A5, 614, 204 },
17233 { 0x98165AF37B2153DF, 641, 212 },
17234 { 0xE2A0B5DC971F303A, 667, 220 },
17235 { 0xA8D9D1535CE3B396, 694, 228 },
17236 { 0xFB9B7CD9A4A7443C, 720, 236 },
17237 { 0xBB764C4CA7A44410, 747, 244 },
17238 { 0x8BAB8EEFB6409C1A, 774, 252 },
17239 { 0xD01FEF10A657842C, 800, 260 },
17240 { 0x9B10A4E5E9913129, 827, 268 },
17241 { 0xE7109BFBA19C0C9D, 853, 276 },
17242 { 0xAC2820D9623BF429, 880, 284 },
17243 { 0x80444B5E7AA7CF85, 907, 292 },
17244 { 0xBF21E44003ACDD2D, 933, 300 },
17245 { 0x8E679C2F5E44FF8F, 960, 308 },
17246 { 0xD433179D9C8CB841, 986, 316 },
17247 { 0x9E19DB92B4E31BA9, 1013, 324 },
17248 }
17249 };
17250
17251 // This computation gives exactly the same results for k as
17252 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
17253 // for |e| <= 1500, but doesn't require floating-point operations.
17254 // NB: log_10(2) ~= 78913 / 2^18
17255 JSON_ASSERT(e >= -1500);
17256 JSON_ASSERT(e <= 1500);
17257 const int f = kAlpha - e - 1;
17258 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
17259
17260 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
17261 JSON_ASSERT(index >= 0);
17262 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
17263
17264 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
17265 JSON_ASSERT(kAlpha <= cached.e + e + 64);
17266 JSON_ASSERT(kGamma >= cached.e + e + 64);
17267
17268 return cached;
17269}
17270
17271/*!
17272For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
17273For n == 0, returns 1 and sets pow10 := 1.
17274*/
17275inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
17276{
17277 // LCOV_EXCL_START
17278 if (n >= 1000000000)
17279 {
17280 pow10 = 1000000000;
17281 return 10;
17282 }
17283 // LCOV_EXCL_STOP
17284 if (n >= 100000000)
17285 {
17286 pow10 = 100000000;
17287 return 9;
17288 }
17289 if (n >= 10000000)
17290 {
17291 pow10 = 10000000;
17292 return 8;
17293 }
17294 if (n >= 1000000)
17295 {
17296 pow10 = 1000000;
17297 return 7;
17298 }
17299 if (n >= 100000)
17300 {
17301 pow10 = 100000;
17302 return 6;
17303 }
17304 if (n >= 10000)
17305 {
17306 pow10 = 10000;
17307 return 5;
17308 }
17309 if (n >= 1000)
17310 {
17311 pow10 = 1000;
17312 return 4;
17313 }
17314 if (n >= 100)
17315 {
17316 pow10 = 100;
17317 return 3;
17318 }
17319 if (n >= 10)
17320 {
17321 pow10 = 10;
17322 return 2;
17323 }
17324
17325 pow10 = 1;
17326 return 1;
17327}
17328
17329inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
17330 std::uint64_t rest, std::uint64_t ten_k)
17331{
17332 JSON_ASSERT(len >= 1);
17333 JSON_ASSERT(dist <= delta);
17334 JSON_ASSERT(rest <= delta);
17335 JSON_ASSERT(ten_k > 0);
17336
17337 // <--------------------------- delta ---->
17338 // <---- dist --------->
17339 // --------------[------------------+-------------------]--------------
17340 // M- w M+
17341 //
17342 // ten_k
17343 // <------>
17344 // <---- rest ---->
17345 // --------------[------------------+----+--------------]--------------
17346 // w V
17347 // = buf * 10^k
17348 //
17349 // ten_k represents a unit-in-the-last-place in the decimal representation
17350 // stored in buf.
17351 // Decrement buf by ten_k while this takes buf closer to w.
17352
17353 // The tests are written in this order to avoid overflow in unsigned
17354 // integer arithmetic.
17355
17356 while (rest < dist
17357 && delta - rest >= ten_k
17358 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
17359 {
17360 JSON_ASSERT(buf[len - 1] != '0');
17361 buf[len - 1]--;
17362 rest += ten_k;
17363 }
17364}
17365
17366/*!
17367Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
17368M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
17369*/
17370inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
17371 diyfp M_minus, diyfp w, diyfp M_plus)
17372{
17373 static_assert(kAlpha >= -60, "internal error");
17374 static_assert(kGamma <= -32, "internal error");
17375
17376 // Generates the digits (and the exponent) of a decimal floating-point
17377 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
17378 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
17379 //
17380 // <--------------------------- delta ---->
17381 // <---- dist --------->
17382 // --------------[------------------+-------------------]--------------
17383 // M- w M+
17384 //
17385 // Grisu2 generates the digits of M+ from left to right and stops as soon as
17386 // V is in [M-,M+].
17387
17388 JSON_ASSERT(M_plus.e >= kAlpha);
17389 JSON_ASSERT(M_plus.e <= kGamma);
17390
17391 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
17392 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
17393
17394 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
17395 //
17396 // M+ = f * 2^e
17397 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
17398 // = ((p1 ) * 2^-e + (p2 )) * 2^e
17399 // = p1 + p2 * 2^e
17400
17401 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
17402
17403 auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
17404 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
17405
17406 // 1)
17407 //
17408 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
17409
17410 JSON_ASSERT(p1 > 0);
17411
17412 std::uint32_t pow10{};
17413 const int k = find_largest_pow10(p1, pow10);
17414
17415 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
17416 //
17417 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
17418 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
17419 //
17420 // M+ = p1 + p2 * 2^e
17421 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
17422 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
17423 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
17424 //
17425 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
17426 //
17427 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
17428 //
17429 // but stop as soon as
17430 //
17431 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
17432
17433 int n = k;
17434 while (n > 0)
17435 {
17436 // Invariants:
17437 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
17438 // pow10 = 10^(n-1) <= p1 < 10^n
17439 //
17440 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
17441 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
17442 //
17443 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
17444 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
17445 //
17446 JSON_ASSERT(d <= 9);
17447 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17448 //
17449 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
17450 //
17451 p1 = r;
17452 n--;
17453 //
17454 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
17455 // pow10 = 10^n
17456 //
17457
17458 // Now check if enough digits have been generated.
17459 // Compute
17460 //
17461 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
17462 //
17463 // Note:
17464 // Since rest and delta share the same exponent e, it suffices to
17465 // compare the significands.
17466 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
17467 if (rest <= delta)
17468 {
17469 // V = buffer * 10^n, with M- <= V <= M+.
17470
17471 decimal_exponent += n;
17472
17473 // We may now just stop. But instead look if the buffer could be
17474 // decremented to bring V closer to w.
17475 //
17476 // pow10 = 10^n is now 1 ulp in the decimal representation V.
17477 // The rounding procedure works with diyfp's with an implicit
17478 // exponent of e.
17479 //
17480 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
17481 //
17482 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
17483 grisu2_round(buffer, length, dist, delta, rest, ten_n);
17484
17485 return;
17486 }
17487
17488 pow10 /= 10;
17489 //
17490 // pow10 = 10^(n-1) <= p1 < 10^n
17491 // Invariants restored.
17492 }
17493
17494 // 2)
17495 //
17496 // The digits of the integral part have been generated:
17497 //
17498 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
17499 // = buffer + p2 * 2^e
17500 //
17501 // Now generate the digits of the fractional part p2 * 2^e.
17502 //
17503 // Note:
17504 // No decimal point is generated: the exponent is adjusted instead.
17505 //
17506 // p2 actually represents the fraction
17507 //
17508 // p2 * 2^e
17509 // = p2 / 2^-e
17510 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
17511 //
17512 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
17513 //
17514 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
17515 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
17516 //
17517 // using
17518 //
17519 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
17520 // = ( d) * 2^-e + ( r)
17521 //
17522 // or
17523 // 10^m * p2 * 2^e = d + r * 2^e
17524 //
17525 // i.e.
17526 //
17527 // M+ = buffer + p2 * 2^e
17528 // = buffer + 10^-m * (d + r * 2^e)
17529 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
17530 //
17531 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
17532
17533 JSON_ASSERT(p2 > delta);
17534
17535 int m = 0;
17536 for (;;)
17537 {
17538 // Invariant:
17539 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
17540 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
17541 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
17542 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
17543 //
17544 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
17545 p2 *= 10;
17546 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
17547 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
17548 //
17549 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
17550 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
17551 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
17552 //
17553 JSON_ASSERT(d <= 9);
17554 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17555 //
17556 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
17557 //
17558 p2 = r;
17559 m++;
17560 //
17561 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
17562 // Invariant restored.
17563
17564 // Check if enough digits have been generated.
17565 //
17566 // 10^-m * p2 * 2^e <= delta * 2^e
17567 // p2 * 2^e <= 10^m * delta * 2^e
17568 // p2 <= 10^m * delta
17569 delta *= 10;
17570 dist *= 10;
17571 if (p2 <= delta)
17572 {
17573 break;
17574 }
17575 }
17576
17577 // V = buffer * 10^-m, with M- <= V <= M+.
17578
17579 decimal_exponent -= m;
17580
17581 // 1 ulp in the decimal representation is now 10^-m.
17582 // Since delta and dist are now scaled by 10^m, we need to do the
17583 // same with ulp in order to keep the units in sync.
17584 //
17585 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
17586 //
17587 const std::uint64_t ten_m = one.f;
17588 grisu2_round(buffer, length, dist, delta, p2, ten_m);
17589
17590 // By construction this algorithm generates the shortest possible decimal
17591 // number (Loitsch, Theorem 6.2) which rounds back to w.
17592 // For an input number of precision p, at least
17593 //
17594 // N = 1 + ceil(p * log_10(2))
17595 //
17596 // decimal digits are sufficient to identify all binary floating-point
17597 // numbers (Matula, "In-and-Out conversions").
17598 // This implies that the algorithm does not produce more than N decimal
17599 // digits.
17600 //
17601 // N = 17 for p = 53 (IEEE double precision)
17602 // N = 9 for p = 24 (IEEE single precision)
17603}
17604
17605/*!
17606v = buf * 10^decimal_exponent
17607len is the length of the buffer (number of decimal digits)
17608The buffer must be large enough, i.e. >= max_digits10.
17609*/
17610JSON_HEDLEY_NON_NULL(1)
17611inline void grisu2(char* buf, int& len, int& decimal_exponent,
17612 diyfp m_minus, diyfp v, diyfp m_plus)
17613{
17614 JSON_ASSERT(m_plus.e == m_minus.e);
17615 JSON_ASSERT(m_plus.e == v.e);
17616
17617 // --------(-----------------------+-----------------------)-------- (A)
17618 // m- v m+
17619 //
17620 // --------------------(-----------+-----------------------)-------- (B)
17621 // m- v m+
17622 //
17623 // First scale v (and m- and m+) such that the exponent is in the range
17624 // [alpha, gamma].
17625
17626 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
17627
17628 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
17629
17630 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
17631 const diyfp w = diyfp::mul(v, c_minus_k);
17632 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
17633 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
17634
17635 // ----(---+---)---------------(---+---)---------------(---+---)----
17636 // w- w w+
17637 // = c*m- = c*v = c*m+
17638 //
17639 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
17640 // w+ are now off by a small amount.
17641 // In fact:
17642 //
17643 // w - v * 10^k < 1 ulp
17644 //
17645 // To account for this inaccuracy, add resp. subtract 1 ulp.
17646 //
17647 // --------+---[---------------(---+---)---------------]---+--------
17648 // w- M- w M+ w+
17649 //
17650 // Now any number in [M-, M+] (bounds included) will round to w when input,
17651 // regardless of how the input rounding algorithm breaks ties.
17652 //
17653 // And digit_gen generates the shortest possible such number in [M-, M+].
17654 // Note that this does not mean that Grisu2 always generates the shortest
17655 // possible number in the interval (m-, m+).
17656 const diyfp M_minus(w_minus.f + 1, w_minus.e);
17657 const diyfp M_plus (w_plus.f - 1, w_plus.e );
17658
17659 decimal_exponent = -cached.k; // = -(-k) = k
17660
17661 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
17662}
17663
17664/*!
17665v = buf * 10^decimal_exponent
17666len is the length of the buffer (number of decimal digits)
17667The buffer must be large enough, i.e. >= max_digits10.
17668*/
17669template<typename FloatType>
17670JSON_HEDLEY_NON_NULL(1)
17671void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
17672{
17673 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
17674 "internal error: not enough precision");
17675
17676 JSON_ASSERT(std::isfinite(value));
17677 JSON_ASSERT(value > 0);
17678
17679 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
17680 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
17681 // decimal representations are not exactly "short".
17682 //
17683 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
17684 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
17685 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
17686 // does.
17687 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
17688 // representation using the corresponding std::from_chars function recovers value exactly". That
17689 // indicates that single precision floating-point numbers should be recovered using
17690 // 'std::strtof'.
17691 //
17692 // NB: If the neighbors are computed for single-precision numbers, there is a single float
17693 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
17694 // value is off by 1 ulp.
17695#if 0
17696 const boundaries w = compute_boundaries(static_cast<double>(value));
17697#else
17698 const boundaries w = compute_boundaries(value);
17699#endif
17700
17701 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
17702}
17703
17704/*!
17705@brief appends a decimal representation of e to buf
17706@return a pointer to the element following the exponent.
17707@pre -1000 < e < 1000
17708*/
17709JSON_HEDLEY_NON_NULL(1)
17710JSON_HEDLEY_RETURNS_NON_NULL
17711inline char* append_exponent(char* buf, int e)
17712{
17713 JSON_ASSERT(e > -1000);
17714 JSON_ASSERT(e < 1000);
17715
17716 if (e < 0)
17717 {
17718 e = -e;
17719 *buf++ = '-';
17720 }
17721 else
17722 {
17723 *buf++ = '+';
17724 }
17725
17726 auto k = static_cast<std::uint32_t>(e);
17727 if (k < 10)
17728 {
17729 // Always print at least two digits in the exponent.
17730 // This is for compatibility with printf("%g").
17731 *buf++ = '0';
17732 *buf++ = static_cast<char>('0' + k);
17733 }
17734 else if (k < 100)
17735 {
17736 *buf++ = static_cast<char>('0' + k / 10);
17737 k %= 10;
17738 *buf++ = static_cast<char>('0' + k);
17739 }
17740 else
17741 {
17742 *buf++ = static_cast<char>('0' + k / 100);
17743 k %= 100;
17744 *buf++ = static_cast<char>('0' + k / 10);
17745 k %= 10;
17746 *buf++ = static_cast<char>('0' + k);
17747 }
17748
17749 return buf;
17750}
17751
17752/*!
17753@brief prettify v = buf * 10^decimal_exponent
17754
17755If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
17756notation. Otherwise it will be printed in exponential notation.
17757
17758@pre min_exp < 0
17759@pre max_exp > 0
17760*/
17761JSON_HEDLEY_NON_NULL(1)
17762JSON_HEDLEY_RETURNS_NON_NULL
17763inline char* format_buffer(char* buf, int len, int decimal_exponent,
17764 int min_exp, int max_exp)
17765{
17766 JSON_ASSERT(min_exp < 0);
17767 JSON_ASSERT(max_exp > 0);
17768
17769 const int k = len;
17770 const int n = len + decimal_exponent;
17771
17772 // v = buf * 10^(n-k)
17773 // k is the length of the buffer (number of decimal digits)
17774 // n is the position of the decimal point relative to the start of the buffer.
17775
17776 if (k <= n && n <= max_exp)
17777 {
17778 // digits[000]
17779 // len <= max_exp + 2
17780
17781 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
17782 // Make it look like a floating-point number (#362, #378)
17783 buf[n + 0] = '.';
17784 buf[n + 1] = '0';
17785 return buf + (static_cast<size_t>(n) + 2);
17786 }
17787
17788 if (0 < n && n <= max_exp)
17789 {
17790 // dig.its
17791 // len <= max_digits10 + 1
17792
17793 JSON_ASSERT(k > n);
17794
17795 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
17796 buf[n] = '.';
17797 return buf + (static_cast<size_t>(k) + 1U);
17798 }
17799
17800 if (min_exp < n && n <= 0)
17801 {
17802 // 0.[000]digits
17803 // len <= 2 + (-min_exp - 1) + max_digits10
17804
17805 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
17806 buf[0] = '0';
17807 buf[1] = '.';
17808 std::memset(buf + 2, '0', static_cast<size_t>(-n));
17809 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
17810 }
17811
17812 if (k == 1)
17813 {
17814 // dE+123
17815 // len <= 1 + 5
17816
17817 buf += 1;
17818 }
17819 else
17820 {
17821 // d.igitsE+123
17822 // len <= max_digits10 + 1 + 5
17823
17824 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
17825 buf[1] = '.';
17826 buf += 1 + static_cast<size_t>(k);
17827 }
17828
17829 *buf++ = 'e';
17830 return append_exponent(buf, n - 1);
17831}
17832
17833} // namespace dtoa_impl
17834
17835/*!
17836@brief generates a decimal representation of the floating-point number value in [first, last).
17837
17838The format of the resulting decimal representation is similar to printf's %g
17839format. Returns an iterator pointing past-the-end of the decimal representation.
17840
17841@note The input number must be finite, i.e. NaN's and Inf's are not supported.
17842@note The buffer must be large enough.
17843@note The result is NOT null-terminated.
17844*/
17845template<typename FloatType>
17846JSON_HEDLEY_NON_NULL(1, 2)
17847JSON_HEDLEY_RETURNS_NON_NULL
17848char* to_chars(char* first, const char* last, FloatType value)
17849{
17850 static_cast<void>(last); // maybe unused - fix warning
17851 JSON_ASSERT(std::isfinite(value));
17852
17853 // Use signbit(value) instead of (value < 0) since signbit works for -0.
17854 if (std::signbit(value))
17855 {
17856 value = -value;
17857 *first++ = '-';
17858 }
17859
17860#ifdef __GNUC__
17861#pragma GCC diagnostic push
17862#pragma GCC diagnostic ignored "-Wfloat-equal"
17863#endif
17864 if (value == 0) // +-0
17865 {
17866 *first++ = '0';
17867 // Make it look like a floating-point number (#362, #378)
17868 *first++ = '.';
17869 *first++ = '0';
17870 return first;
17871 }
17872#ifdef __GNUC__
17873#pragma GCC diagnostic pop
17874#endif
17875
17876 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
17877
17878 // Compute v = buffer * 10^decimal_exponent.
17879 // The decimal digits are stored in the buffer, which needs to be interpreted
17880 // as an unsigned decimal integer.
17881 // len is the length of the buffer, i.e. the number of decimal digits.
17882 int len = 0;
17883 int decimal_exponent = 0;
17884 dtoa_impl::grisu2(first, len, decimal_exponent, value);
17885
17886 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
17887
17888 // Format the buffer like printf("%.*g", prec, value)
17889 constexpr int kMinExp = -4;
17890 // Use digits10 here to increase compatibility with version 2.
17891 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
17892
17893 JSON_ASSERT(last - first >= kMaxExp + 2);
17894 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
17895 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
17896
17897 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
17898}
17899
17900} // namespace detail
17901NLOHMANN_JSON_NAMESPACE_END
17902
17903// #include <nlohmann/detail/exceptions.hpp>
17904
17905// #include <nlohmann/detail/macro_scope.hpp>
17906
17907// #include <nlohmann/detail/meta/cpp_future.hpp>
17908
17909// #include <nlohmann/detail/output/binary_writer.hpp>
17910
17911// #include <nlohmann/detail/output/output_adapters.hpp>
17912
17913// #include <nlohmann/detail/string_concat.hpp>
17914
17915// #include <nlohmann/detail/value_t.hpp>
17916
17917
17918NLOHMANN_JSON_NAMESPACE_BEGIN
17919namespace detail
17920{
17921
17922///////////////////
17923// serialization //
17924///////////////////
17925
17926/// how to treat decoding errors
17927enum class error_handler_t
17928{
17929 strict, ///< throw a type_error exception in case of invalid UTF-8
17930 replace, ///< replace invalid UTF-8 sequences with U+FFFD
17931 ignore ///< ignore invalid UTF-8 sequences
17932};
17933
17934template<typename BasicJsonType>
17935class serializer
17936{
17937 using string_t = typename BasicJsonType::string_t;
17938 using number_float_t = typename BasicJsonType::number_float_t;
17939 using number_integer_t = typename BasicJsonType::number_integer_t;
17940 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
17941 using binary_char_t = typename BasicJsonType::binary_t::value_type;
17942 static constexpr std::uint8_t UTF8_ACCEPT = 0;
17943 static constexpr std::uint8_t UTF8_REJECT = 1;
17944
17945 public:
17946 /*!
17947 @param[in] s output stream to serialize to
17948 @param[in] ichar indentation character to use
17949 @param[in] error_handler_ how to react on decoding errors
17950 */
17951 serializer(output_adapter_t<char> s, const char ichar,
17952 error_handler_t error_handler_ = error_handler_t::strict)
17953 : o(std::move(s))
17954 , loc(std::localeconv())
17955 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
17956 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
17957 , indent_char(ichar)
17958 , indent_string(512, indent_char)
17959 , error_handler(error_handler_)
17960 {}
17961
17962 // delete because of pointer members
17963 serializer(const serializer&) = delete;
17964 serializer& operator=(const serializer&) = delete;
17965 serializer(serializer&&) = delete;
17966 serializer& operator=(serializer&&) = delete;
17967 ~serializer() = default;
17968
17969 /*!
17970 @brief internal implementation of the serialization function
17971
17972 This function is called by the public member function dump and organizes
17973 the serialization internally. The indentation level is propagated as
17974 additional parameter. In case of arrays and objects, the function is
17975 called recursively.
17976
17977 - strings and object keys are escaped using `escape_string()`
17978 - integer numbers are converted implicitly via `operator<<`
17979 - floating-point numbers are converted to a string using `"%g"` format
17980 - binary values are serialized as objects containing the subtype and the
17981 byte array
17982
17983 @param[in] val value to serialize
17984 @param[in] pretty_print whether the output shall be pretty-printed
17985 @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
17986 in the output are escaped with `\uXXXX` sequences, and the result consists
17987 of ASCII characters only.
17988 @param[in] indent_step the indent level
17989 @param[in] current_indent the current indent level (only used internally)
17990 */
17991 void dump(const BasicJsonType& val,
17992 const bool pretty_print,
17993 const bool ensure_ascii,
17994 const unsigned int indent_step,
17995 const unsigned int current_indent = 0)
17996 {
17997 switch (val.m_type)
17998 {
17999 case value_t::object:
18000 {
18001 if (val.m_value.object->empty())
18002 {
18003 o->write_characters("{}", 2);
18004 return;
18005 }
18006
18007 if (pretty_print)
18008 {
18009 o->write_characters("{\n", 2);
18010
18011 // variable to hold indentation for recursive calls
18012 const auto new_indent = current_indent + indent_step;
18013 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18014 {
18015 indent_string.resize(indent_string.size() * 2, ' ');
18016 }
18017
18018 // first n-1 elements
18019 auto i = val.m_value.object->cbegin();
18020 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
18021 {
18022 o->write_characters(indent_string.c_str(), new_indent);
18023 o->write_character('\"');
18024 dump_escaped(i->first, ensure_ascii);
18025 o->write_characters("\": ", 3);
18026 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18027 o->write_characters(",\n", 2);
18028 }
18029
18030 // last element
18031 JSON_ASSERT(i != val.m_value.object->cend());
18032 JSON_ASSERT(std::next(i) == val.m_value.object->cend());
18033 o->write_characters(indent_string.c_str(), new_indent);
18034 o->write_character('\"');
18035 dump_escaped(i->first, ensure_ascii);
18036 o->write_characters("\": ", 3);
18037 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18038
18039 o->write_character('\n');
18040 o->write_characters(indent_string.c_str(), current_indent);
18041 o->write_character('}');
18042 }
18043 else
18044 {
18045 o->write_character('{');
18046
18047 // first n-1 elements
18048 auto i = val.m_value.object->cbegin();
18049 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
18050 {
18051 o->write_character('\"');
18052 dump_escaped(i->first, ensure_ascii);
18053 o->write_characters("\":", 2);
18054 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18055 o->write_character(',');
18056 }
18057
18058 // last element
18059 JSON_ASSERT(i != val.m_value.object->cend());
18060 JSON_ASSERT(std::next(i) == val.m_value.object->cend());
18061 o->write_character('\"');
18062 dump_escaped(i->first, ensure_ascii);
18063 o->write_characters("\":", 2);
18064 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18065
18066 o->write_character('}');
18067 }
18068
18069 return;
18070 }
18071
18072 case value_t::array:
18073 {
18074 if (val.m_value.array->empty())
18075 {
18076 o->write_characters("[]", 2);
18077 return;
18078 }
18079
18080 if (pretty_print)
18081 {
18082 o->write_characters("[\n", 2);
18083
18084 // variable to hold indentation for recursive calls
18085 const auto new_indent = current_indent + indent_step;
18086 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18087 {
18088 indent_string.resize(indent_string.size() * 2, ' ');
18089 }
18090
18091 // first n-1 elements
18092 for (auto i = val.m_value.array->cbegin();
18093 i != val.m_value.array->cend() - 1; ++i)
18094 {
18095 o->write_characters(indent_string.c_str(), new_indent);
18096 dump(*i, true, ensure_ascii, indent_step, new_indent);
18097 o->write_characters(",\n", 2);
18098 }
18099
18100 // last element
18101 JSON_ASSERT(!val.m_value.array->empty());
18102 o->write_characters(indent_string.c_str(), new_indent);
18103 dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
18104
18105 o->write_character('\n');
18106 o->write_characters(indent_string.c_str(), current_indent);
18107 o->write_character(']');
18108 }
18109 else
18110 {
18111 o->write_character('[');
18112
18113 // first n-1 elements
18114 for (auto i = val.m_value.array->cbegin();
18115 i != val.m_value.array->cend() - 1; ++i)
18116 {
18117 dump(*i, false, ensure_ascii, indent_step, current_indent);
18118 o->write_character(',');
18119 }
18120
18121 // last element
18122 JSON_ASSERT(!val.m_value.array->empty());
18123 dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
18124
18125 o->write_character(']');
18126 }
18127
18128 return;
18129 }
18130
18131 case value_t::string:
18132 {
18133 o->write_character('\"');
18134 dump_escaped(*val.m_value.string, ensure_ascii);
18135 o->write_character('\"');
18136 return;
18137 }
18138
18139 case value_t::binary:
18140 {
18141 if (pretty_print)
18142 {
18143 o->write_characters("{\n", 2);
18144
18145 // variable to hold indentation for recursive calls
18146 const auto new_indent = current_indent + indent_step;
18147 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18148 {
18149 indent_string.resize(indent_string.size() * 2, ' ');
18150 }
18151
18152 o->write_characters(indent_string.c_str(), new_indent);
18153
18154 o->write_characters("\"bytes\": [", 10);
18155
18156 if (!val.m_value.binary->empty())
18157 {
18158 for (auto i = val.m_value.binary->cbegin();
18159 i != val.m_value.binary->cend() - 1; ++i)
18160 {
18161 dump_integer(*i);
18162 o->write_characters(", ", 2);
18163 }
18164 dump_integer(val.m_value.binary->back());
18165 }
18166
18167 o->write_characters("],\n", 3);
18168 o->write_characters(indent_string.c_str(), new_indent);
18169
18170 o->write_characters("\"subtype\": ", 11);
18171 if (val.m_value.binary->has_subtype())
18172 {
18173 dump_integer(val.m_value.binary->subtype());
18174 }
18175 else
18176 {
18177 o->write_characters("null", 4);
18178 }
18179 o->write_character('\n');
18180 o->write_characters(indent_string.c_str(), current_indent);
18181 o->write_character('}');
18182 }
18183 else
18184 {
18185 o->write_characters("{\"bytes\":[", 10);
18186
18187 if (!val.m_value.binary->empty())
18188 {
18189 for (auto i = val.m_value.binary->cbegin();
18190 i != val.m_value.binary->cend() - 1; ++i)
18191 {
18192 dump_integer(*i);
18193 o->write_character(',');
18194 }
18195 dump_integer(val.m_value.binary->back());
18196 }
18197
18198 o->write_characters("],\"subtype\":", 12);
18199 if (val.m_value.binary->has_subtype())
18200 {
18201 dump_integer(val.m_value.binary->subtype());
18202 o->write_character('}');
18203 }
18204 else
18205 {
18206 o->write_characters("null}", 5);
18207 }
18208 }
18209 return;
18210 }
18211
18212 case value_t::boolean:
18213 {
18214 if (val.m_value.boolean)
18215 {
18216 o->write_characters("true", 4);
18217 }
18218 else
18219 {
18220 o->write_characters("false", 5);
18221 }
18222 return;
18223 }
18224
18225 case value_t::number_integer:
18226 {
18227 dump_integer(val.m_value.number_integer);
18228 return;
18229 }
18230
18231 case value_t::number_unsigned:
18232 {
18233 dump_integer(val.m_value.number_unsigned);
18234 return;
18235 }
18236
18237 case value_t::number_float:
18238 {
18239 dump_float(val.m_value.number_float);
18240 return;
18241 }
18242
18243 case value_t::discarded:
18244 {
18245 o->write_characters("<discarded>", 11);
18246 return;
18247 }
18248
18249 case value_t::null:
18250 {
18251 o->write_characters("null", 4);
18252 return;
18253 }
18254
18255 default: // LCOV_EXCL_LINE
18256 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18257 }
18258 }
18259
18260 JSON_PRIVATE_UNLESS_TESTED:
18261 /*!
18262 @brief dump escaped string
18263
18264 Escape a string by replacing certain special characters by a sequence of an
18265 escape character (backslash) and another character and other control
18266 characters by a sequence of "\u" followed by a four-digit hex
18267 representation. The escaped string is written to output stream @a o.
18268
18269 @param[in] s the string to escape
18270 @param[in] ensure_ascii whether to escape non-ASCII characters with
18271 \uXXXX sequences
18272
18273 @complexity Linear in the length of string @a s.
18274 */
18275 void dump_escaped(const string_t& s, const bool ensure_ascii)
18276 {
18277 std::uint32_t codepoint{};
18278 std::uint8_t state = UTF8_ACCEPT;
18279 std::size_t bytes = 0; // number of bytes written to string_buffer
18280
18281 // number of bytes written at the point of the last valid byte
18282 std::size_t bytes_after_last_accept = 0;
18283 std::size_t undumped_chars = 0;
18284
18285 for (std::size_t i = 0; i < s.size(); ++i)
18286 {
18287 const auto byte = static_cast<std::uint8_t>(s[i]);
18288
18289 switch (decode(state, codepoint, byte))
18290 {
18291 case UTF8_ACCEPT: // decode found a new code point
18292 {
18293 switch (codepoint)
18294 {
18295 case 0x08: // backspace
18296 {
18297 string_buffer[bytes++] = '\\';
18298 string_buffer[bytes++] = 'b';
18299 break;
18300 }
18301
18302 case 0x09: // horizontal tab
18303 {
18304 string_buffer[bytes++] = '\\';
18305 string_buffer[bytes++] = 't';
18306 break;
18307 }
18308
18309 case 0x0A: // newline
18310 {
18311 string_buffer[bytes++] = '\\';
18312 string_buffer[bytes++] = 'n';
18313 break;
18314 }
18315
18316 case 0x0C: // formfeed
18317 {
18318 string_buffer[bytes++] = '\\';
18319 string_buffer[bytes++] = 'f';
18320 break;
18321 }
18322
18323 case 0x0D: // carriage return
18324 {
18325 string_buffer[bytes++] = '\\';
18326 string_buffer[bytes++] = 'r';
18327 break;
18328 }
18329
18330 case 0x22: // quotation mark
18331 {
18332 string_buffer[bytes++] = '\\';
18333 string_buffer[bytes++] = '\"';
18334 break;
18335 }
18336
18337 case 0x5C: // reverse solidus
18338 {
18339 string_buffer[bytes++] = '\\';
18340 string_buffer[bytes++] = '\\';
18341 break;
18342 }
18343
18344 default:
18345 {
18346 // escape control characters (0x00..0x1F) or, if
18347 // ensure_ascii parameter is used, non-ASCII characters
18348 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
18349 {
18350 if (codepoint <= 0xFFFF)
18351 {
18352 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18353 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
18354 static_cast<std::uint16_t>(codepoint)));
18355 bytes += 6;
18356 }
18357 else
18358 {
18359 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18360 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
18361 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
18362 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
18363 bytes += 12;
18364 }
18365 }
18366 else
18367 {
18368 // copy byte to buffer (all previous bytes
18369 // been copied have in default case above)
18370 string_buffer[bytes++] = s[i];
18371 }
18372 break;
18373 }
18374 }
18375
18376 // write buffer and reset index; there must be 13 bytes
18377 // left, as this is the maximal number of bytes to be
18378 // written ("\uxxxx\uxxxx\0") for one code point
18379 if (string_buffer.size() - bytes < 13)
18380 {
18381 o->write_characters(string_buffer.data(), bytes);
18382 bytes = 0;
18383 }
18384
18385 // remember the byte position of this accept
18386 bytes_after_last_accept = bytes;
18387 undumped_chars = 0;
18388 break;
18389 }
18390
18391 case UTF8_REJECT: // decode found invalid UTF-8 byte
18392 {
18393 switch (error_handler)
18394 {
18395 case error_handler_t::strict:
18396 {
18397 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
18398 }
18399
18400 case error_handler_t::ignore:
18401 case error_handler_t::replace:
18402 {
18403 // in case we saw this character the first time, we
18404 // would like to read it again, because the byte
18405 // may be OK for itself, but just not OK for the
18406 // previous sequence
18407 if (undumped_chars > 0)
18408 {
18409 --i;
18410 }
18411
18412 // reset length buffer to the last accepted index;
18413 // thus removing/ignoring the invalid characters
18414 bytes = bytes_after_last_accept;
18415
18416 if (error_handler == error_handler_t::replace)
18417 {
18418 // add a replacement character
18419 if (ensure_ascii)
18420 {
18421 string_buffer[bytes++] = '\\';
18422 string_buffer[bytes++] = 'u';
18423 string_buffer[bytes++] = 'f';
18424 string_buffer[bytes++] = 'f';
18425 string_buffer[bytes++] = 'f';
18426 string_buffer[bytes++] = 'd';
18427 }
18428 else
18429 {
18430 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
18431 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
18432 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
18433 }
18434
18435 // write buffer and reset index; there must be 13 bytes
18436 // left, as this is the maximal number of bytes to be
18437 // written ("\uxxxx\uxxxx\0") for one code point
18438 if (string_buffer.size() - bytes < 13)
18439 {
18440 o->write_characters(string_buffer.data(), bytes);
18441 bytes = 0;
18442 }
18443
18444 bytes_after_last_accept = bytes;
18445 }
18446
18447 undumped_chars = 0;
18448
18449 // continue processing the string
18450 state = UTF8_ACCEPT;
18451 break;
18452 }
18453
18454 default: // LCOV_EXCL_LINE
18455 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18456 }
18457 break;
18458 }
18459
18460 default: // decode found yet incomplete multi-byte code point
18461 {
18462 if (!ensure_ascii)
18463 {
18464 // code point will not be escaped - copy byte to buffer
18465 string_buffer[bytes++] = s[i];
18466 }
18467 ++undumped_chars;
18468 break;
18469 }
18470 }
18471 }
18472
18473 // we finished processing the string
18474 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
18475 {
18476 // write buffer
18477 if (bytes > 0)
18478 {
18479 o->write_characters(string_buffer.data(), bytes);
18480 }
18481 }
18482 else
18483 {
18484 // we finish reading, but do not accept: string was incomplete
18485 switch (error_handler)
18486 {
18487 case error_handler_t::strict:
18488 {
18489 JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr));
18490 }
18491
18492 case error_handler_t::ignore:
18493 {
18494 // write all accepted bytes
18495 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18496 break;
18497 }
18498
18499 case error_handler_t::replace:
18500 {
18501 // write all accepted bytes
18502 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18503 // add a replacement character
18504 if (ensure_ascii)
18505 {
18506 o->write_characters("\\ufffd", 6);
18507 }
18508 else
18509 {
18510 o->write_characters("\xEF\xBF\xBD", 3);
18511 }
18512 break;
18513 }
18514
18515 default: // LCOV_EXCL_LINE
18516 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18517 }
18518 }
18519 }
18520
18521 private:
18522 /*!
18523 @brief count digits
18524
18525 Count the number of decimal (base 10) digits for an input unsigned integer.
18526
18527 @param[in] x unsigned integer number to count its digits
18528 @return number of decimal digits
18529 */
18530 inline unsigned int count_digits(number_unsigned_t x) noexcept
18531 {
18532 unsigned int n_digits = 1;
18533 for (;;)
18534 {
18535 if (x < 10)
18536 {
18537 return n_digits;
18538 }
18539 if (x < 100)
18540 {
18541 return n_digits + 1;
18542 }
18543 if (x < 1000)
18544 {
18545 return n_digits + 2;
18546 }
18547 if (x < 10000)
18548 {
18549 return n_digits + 3;
18550 }
18551 x = x / 10000u;
18552 n_digits += 4;
18553 }
18554 }
18555
18556 /*!
18557 * @brief convert a byte to a uppercase hex representation
18558 * @param[in] byte byte to represent
18559 * @return representation ("00".."FF")
18560 */
18561 static std::string hex_bytes(std::uint8_t byte)
18562 {
18563 std::string result = "FF";
18564 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
18565 result[0] = nibble_to_hex[byte / 16];
18566 result[1] = nibble_to_hex[byte % 16];
18567 return result;
18568 }
18569
18570 // templates to avoid warnings about useless casts
18571 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
18572 bool is_negative_number(NumberType x)
18573 {
18574 return x < 0;
18575 }
18576
18577 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
18578 bool is_negative_number(NumberType /*unused*/)
18579 {
18580 return false;
18581 }
18582
18583 /*!
18584 @brief dump an integer
18585
18586 Dump a given integer to output stream @a o. Works internally with
18587 @a number_buffer.
18588
18589 @param[in] x integer number (signed or unsigned) to dump
18590 @tparam NumberType either @a number_integer_t or @a number_unsigned_t
18591 */
18592 template < typename NumberType, detail::enable_if_t <
18593 std::is_integral<NumberType>::value ||
18594 std::is_same<NumberType, number_unsigned_t>::value ||
18595 std::is_same<NumberType, number_integer_t>::value ||
18596 std::is_same<NumberType, binary_char_t>::value,
18597 int > = 0 >
18598 void dump_integer(NumberType x)
18599 {
18600 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
18601 {
18602 {
18603 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
18604 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
18605 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
18606 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
18607 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
18608 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
18609 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
18610 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
18611 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
18612 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
18613 }
18614 };
18615
18616 // special case for "0"
18617 if (x == 0)
18618 {
18619 o->write_character('0');
18620 return;
18621 }
18622
18623 // use a pointer to fill the buffer
18624 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18625
18626 number_unsigned_t abs_value;
18627
18628 unsigned int n_chars{};
18629
18630 if (is_negative_number(x))
18631 {
18632 *buffer_ptr = '-';
18633 abs_value = remove_sign(static_cast<number_integer_t>(x));
18634
18635 // account one more byte for the minus sign
18636 n_chars = 1 + count_digits(abs_value);
18637 }
18638 else
18639 {
18640 abs_value = static_cast<number_unsigned_t>(x);
18641 n_chars = count_digits(abs_value);
18642 }
18643
18644 // spare 1 byte for '\0'
18645 JSON_ASSERT(n_chars < number_buffer.size() - 1);
18646
18647 // jump to the end to generate the string from backward,
18648 // so we later avoid reversing the result
18649 buffer_ptr += n_chars;
18650
18651 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
18652 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
18653 while (abs_value >= 100)
18654 {
18655 const auto digits_index = static_cast<unsigned>((abs_value % 100));
18656 abs_value /= 100;
18657 *(--buffer_ptr) = digits_to_99[digits_index][1];
18658 *(--buffer_ptr) = digits_to_99[digits_index][0];
18659 }
18660
18661 if (abs_value >= 10)
18662 {
18663 const auto digits_index = static_cast<unsigned>(abs_value);
18664 *(--buffer_ptr) = digits_to_99[digits_index][1];
18665 *(--buffer_ptr) = digits_to_99[digits_index][0];
18666 }
18667 else
18668 {
18669 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
18670 }
18671
18672 o->write_characters(number_buffer.data(), n_chars);
18673 }
18674
18675 /*!
18676 @brief dump a floating-point number
18677
18678 Dump a given floating-point number to output stream @a o. Works internally
18679 with @a number_buffer.
18680
18681 @param[in] x floating-point number to dump
18682 */
18683 void dump_float(number_float_t x)
18684 {
18685 // NaN / inf
18686 if (!std::isfinite(x))
18687 {
18688 o->write_characters("null", 4);
18689 return;
18690 }
18691
18692 // If number_float_t is an IEEE-754 single or double precision number,
18693 // use the Grisu2 algorithm to produce short numbers which are
18694 // guaranteed to round-trip, using strtof and strtod, resp.
18695 //
18696 // NB: The test below works if <long double> == <double>.
18697 static constexpr bool is_ieee_single_or_double
18698 = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
18699 (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
18700
18701 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
18702 }
18703
18704 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
18705 {
18706 auto* begin = number_buffer.data();
18707 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
18708
18709 o->write_characters(begin, static_cast<size_t>(end - begin));
18710 }
18711
18712 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
18713 {
18714 // get number of digits for a float -> text -> float round-trip
18715 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
18716
18717 // the actual conversion
18718 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18719 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
18720
18721 // negative value indicates an error
18722 JSON_ASSERT(len > 0);
18723 // check if buffer was large enough
18724 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
18725
18726 // erase thousands separator
18727 if (thousands_sep != '\0')
18728 {
18729 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
18730 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
18731 std::fill(end, number_buffer.end(), '\0');
18732 JSON_ASSERT((end - number_buffer.begin()) <= len);
18733 len = (end - number_buffer.begin());
18734 }
18735
18736 // convert decimal point to '.'
18737 if (decimal_point != '\0' && decimal_point != '.')
18738 {
18739 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
18740 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
18741 if (dec_pos != number_buffer.end())
18742 {
18743 *dec_pos = '.';
18744 }
18745 }
18746
18747 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
18748
18749 // determine if we need to append ".0"
18750 const bool value_is_int_like =
18751 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
18752 [](char c)
18753 {
18754 return c == '.' || c == 'e';
18755 });
18756
18757 if (value_is_int_like)
18758 {
18759 o->write_characters(".0", 2);
18760 }
18761 }
18762
18763 /*!
18764 @brief check whether a string is UTF-8 encoded
18765
18766 The function checks each byte of a string whether it is UTF-8 encoded. The
18767 result of the check is stored in the @a state parameter. The function must
18768 be called initially with state 0 (accept). State 1 means the string must
18769 be rejected, because the current byte is not allowed. If the string is
18770 completely processed, but the state is non-zero, the string ended
18771 prematurely; that is, the last byte indicated more bytes should have
18772 followed.
18773
18774 @param[in,out] state the state of the decoding
18775 @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT)
18776 @param[in] byte next byte to decode
18777 @return new state
18778
18779 @note The function has been edited: a std::array is used.
18780
18781 @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
18782 @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
18783 */
18784 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
18785 {
18786 static const std::array<std::uint8_t, 400> utf8d =
18787 {
18788 {
18789 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
18790 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
18791 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
18792 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
18793 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
18794 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
18795 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
18796 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
18797 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
18798 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
18799 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
18800 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
18801 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
18802 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
18803 }
18804 };
18805
18806 JSON_ASSERT(byte < utf8d.size());
18807 const std::uint8_t type = utf8d[byte];
18808
18809 codep = (state != UTF8_ACCEPT)
18810 ? (byte & 0x3fu) | (codep << 6u)
18811 : (0xFFu >> type) & (byte);
18812
18813 std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
18814 JSON_ASSERT(index < 400);
18815 state = utf8d[index];
18816 return state;
18817 }
18818
18819 /*
18820 * Overload to make the compiler happy while it is instantiating
18821 * dump_integer for number_unsigned_t.
18822 * Must never be called.
18823 */
18824 number_unsigned_t remove_sign(number_unsigned_t x)
18825 {
18826 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18827 return x; // LCOV_EXCL_LINE
18828 }
18829
18830 /*
18831 * Helper function for dump_integer
18832 *
18833 * This function takes a negative signed integer and returns its absolute
18834 * value as unsigned integer. The plus/minus shuffling is necessary as we can
18835 * not directly remove the sign of an arbitrary signed integer as the
18836 * absolute values of INT_MIN and INT_MAX are usually not the same. See
18837 * #1708 for details.
18838 */
18839 inline number_unsigned_t remove_sign(number_integer_t x) noexcept
18840 {
18841 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
18842 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
18843 }
18844
18845 private:
18846 /// the output of the serializer
18847 output_adapter_t<char> o = nullptr;
18848
18849 /// a (hopefully) large enough character buffer
18850 std::array<char, 64> number_buffer{{}};
18851
18852 /// the locale
18853 const std::lconv* loc = nullptr;
18854 /// the locale's thousand separator character
18855 const char thousands_sep = '\0';
18856 /// the locale's decimal point character
18857 const char decimal_point = '\0';
18858
18859 /// string buffer
18860 std::array<char, 512> string_buffer{{}};
18861
18862 /// the indentation character
18863 const char indent_char;
18864 /// the indentation string
18865 string_t indent_string;
18866
18867 /// error_handler how to react on decoding errors
18868 const error_handler_t error_handler;
18869};
18870
18871} // namespace detail
18872NLOHMANN_JSON_NAMESPACE_END
18873
18874// #include <nlohmann/detail/value_t.hpp>
18875
18876// #include <nlohmann/json_fwd.hpp>
18877
18878// #include <nlohmann/ordered_map.hpp>
18879// __ _____ _____ _____
18880// __| | __| | | | JSON for Modern C++
18881// | | |__ | | | | | | version 3.11.2
18882// |_____|_____|_____|_|___| https://github.com/nlohmann/json
18883//
18884// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
18885// SPDX-License-Identifier: MIT
18886
18887
18888
18889#include <functional> // equal_to, less
18890#include <initializer_list> // initializer_list
18891#include <iterator> // input_iterator_tag, iterator_traits
18892#include <memory> // allocator
18893#include <stdexcept> // for out_of_range
18894#include <type_traits> // enable_if, is_convertible
18895#include <utility> // pair
18896#include <vector> // vector
18897
18898// #include <nlohmann/detail/macro_scope.hpp>
18899
18900// #include <nlohmann/detail/meta/type_traits.hpp>
18901
18902
18903NLOHMANN_JSON_NAMESPACE_BEGIN
18904
18905/// ordered_map: a minimal map-like container that preserves insertion order
18906/// for use within nlohmann::basic_json<ordered_map>
18907template <class Key, class T, class IgnoredLess = std::less<Key>,
18908 class Allocator = std::allocator<std::pair<const Key, T>>>
18909 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
18910{
18911 using key_type = Key;
18912 using mapped_type = T;
18913 using Container = std::vector<std::pair<const Key, T>, Allocator>;
18914 using iterator = typename Container::iterator;
18915 using const_iterator = typename Container::const_iterator;
18916 using size_type = typename Container::size_type;
18917 using value_type = typename Container::value_type;
18918#ifdef JSON_HAS_CPP_14
18919 using key_compare = std::equal_to<>;
18920#else
18921 using key_compare = std::equal_to<Key>;
18922#endif
18923
18924 // Explicit constructors instead of `using Container::Container`
18925 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
18926 ordered_map() noexcept(noexcept(Container())) : Container{} {}
18927 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
18928 template <class It>
18929 ordered_map(It first, It last, const Allocator& alloc = Allocator())
18930 : Container{first, last, alloc} {}
18931 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
18932 : Container{init, alloc} {}
18933
18934 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
18935 {
18936 for (auto it = this->begin(); it != this->end(); ++it)
18937 {
18938 if (m_compare(it->first, key))
18939 {
18940 return {it, false};
18941 }
18942 }
18943 Container::emplace_back(key, std::forward<T>(t));
18944 return {std::prev(this->end()), true};
18945 }
18946
18947 template<class KeyType, detail::enable_if_t<
18948 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
18949 std::pair<iterator, bool> emplace(KeyType && key, T && t)
18950 {
18951 for (auto it = this->begin(); it != this->end(); ++it)
18952 {
18953 if (m_compare(it->first, key))
18954 {
18955 return {it, false};
18956 }
18957 }
18958 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
18959 return {std::prev(this->end()), true};
18960 }
18961
18962 T& operator[](const key_type& key)
18963 {
18964 return emplace(key, T{}).first->second;
18965 }
18966
18967 template<class KeyType, detail::enable_if_t<
18968 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
18969 T & operator[](KeyType && key)
18970 {
18971 return emplace(std::forward<KeyType>(key), T{}).first->second;
18972 }
18973
18974 const T& operator[](const key_type& key) const
18975 {
18976 return at(key);
18977 }
18978
18979 template<class KeyType, detail::enable_if_t<
18980 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
18981 const T & operator[](KeyType && key) const
18982 {
18983 return at(std::forward<KeyType>(key));
18984 }
18985
18986 T& at(const key_type& key)
18987 {
18988 for (auto it = this->begin(); it != this->end(); ++it)
18989 {
18990 if (m_compare(it->first, key))
18991 {
18992 return it->second;
18993 }
18994 }
18995
18996 JSON_THROW(std::out_of_range("key not found"));
18997 }
18998
18999 template<class KeyType, detail::enable_if_t<
19000 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19001 T & at(KeyType && key)
19002 {
19003 for (auto it = this->begin(); it != this->end(); ++it)
19004 {
19005 if (m_compare(it->first, key))
19006 {
19007 return it->second;
19008 }
19009 }
19010
19011 JSON_THROW(std::out_of_range("key not found"));
19012 }
19013
19014 const T& at(const key_type& key) const
19015 {
19016 for (auto it = this->begin(); it != this->end(); ++it)
19017 {
19018 if (m_compare(it->first, key))
19019 {
19020 return it->second;
19021 }
19022 }
19023
19024 JSON_THROW(std::out_of_range("key not found"));
19025 }
19026
19027 template<class KeyType, detail::enable_if_t<
19028 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19029 const T & at(KeyType && key) const
19030 {
19031 for (auto it = this->begin(); it != this->end(); ++it)
19032 {
19033 if (m_compare(it->first, key))
19034 {
19035 return it->second;
19036 }
19037 }
19038
19039 JSON_THROW(std::out_of_range("key not found"));
19040 }
19041
19042 size_type erase(const key_type& key)
19043 {
19044 for (auto it = this->begin(); it != this->end(); ++it)
19045 {
19046 if (m_compare(it->first, key))
19047 {
19048 // Since we cannot move const Keys, re-construct them in place
19049 for (auto next = it; ++next != this->end(); ++it)
19050 {
19051 it->~value_type(); // Destroy but keep allocation
19052 new (&*it) value_type{std::move(*next)};
19053 }
19054 Container::pop_back();
19055 return 1;
19056 }
19057 }
19058 return 0;
19059 }
19060
19061 template<class KeyType, detail::enable_if_t<
19062 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19063 size_type erase(KeyType && key)
19064 {
19065 for (auto it = this->begin(); it != this->end(); ++it)
19066 {
19067 if (m_compare(it->first, key))
19068 {
19069 // Since we cannot move const Keys, re-construct them in place
19070 for (auto next = it; ++next != this->end(); ++it)
19071 {
19072 it->~value_type(); // Destroy but keep allocation
19073 new (&*it) value_type{std::move(*next)};
19074 }
19075 Container::pop_back();
19076 return 1;
19077 }
19078 }
19079 return 0;
19080 }
19081
19082 iterator erase(iterator pos)
19083 {
19084 return erase(pos, std::next(pos));
19085 }
19086
19087 iterator erase(iterator first, iterator last)
19088 {
19089 if (first == last)
19090 {
19091 return first;
19092 }
19093
19094 const auto elements_affected = std::distance(first, last);
19095 const auto offset = std::distance(Container::begin(), first);
19096
19097 // This is the start situation. We need to delete elements_affected
19098 // elements (3 in this example: e, f, g), and need to return an
19099 // iterator past the last deleted element (h in this example).
19100 // Note that offset is the distance from the start of the vector
19101 // to first. We will need this later.
19102
19103 // [ a, b, c, d, e, f, g, h, i, j ]
19104 // ^ ^
19105 // first last
19106
19107 // Since we cannot move const Keys, we re-construct them in place.
19108 // We start at first and re-construct (viz. copy) the elements from
19109 // the back of the vector. Example for first iteration:
19110
19111 // ,--------.
19112 // v | destroy e and re-construct with h
19113 // [ a, b, c, d, e, f, g, h, i, j ]
19114 // ^ ^
19115 // it it + elements_affected
19116
19117 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
19118 {
19119 it->~value_type(); // destroy but keep allocation
19120 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
19121 }
19122
19123 // [ a, b, c, d, h, i, j, h, i, j ]
19124 // ^ ^
19125 // first last
19126
19127 // remove the unneeded elements at the end of the vector
19128 Container::resize(this->size() - static_cast<size_type>(elements_affected));
19129
19130 // [ a, b, c, d, h, i, j ]
19131 // ^ ^
19132 // first last
19133
19134 // first is now pointing past the last deleted element, but we cannot
19135 // use this iterator, because it may have been invalidated by the
19136 // resize call. Instead, we can return begin() + offset.
19137 return Container::begin() + offset;
19138 }
19139
19140 size_type count(const key_type& key) const
19141 {
19142 for (auto it = this->begin(); it != this->end(); ++it)
19143 {
19144 if (m_compare(it->first, key))
19145 {
19146 return 1;
19147 }
19148 }
19149 return 0;
19150 }
19151
19152 template<class KeyType, detail::enable_if_t<
19153 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19154 size_type count(KeyType && key) const
19155 {
19156 for (auto it = this->begin(); it != this->end(); ++it)
19157 {
19158 if (m_compare(it->first, key))
19159 {
19160 return 1;
19161 }
19162 }
19163 return 0;
19164 }
19165
19166 iterator find(const key_type& key)
19167 {
19168 for (auto it = this->begin(); it != this->end(); ++it)
19169 {
19170 if (m_compare(it->first, key))
19171 {
19172 return it;
19173 }
19174 }
19175 return Container::end();
19176 }
19177
19178 template<class KeyType, detail::enable_if_t<
19179 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19180 iterator find(KeyType && key)
19181 {
19182 for (auto it = this->begin(); it != this->end(); ++it)
19183 {
19184 if (m_compare(it->first, key))
19185 {
19186 return it;
19187 }
19188 }
19189 return Container::end();
19190 }
19191
19192 const_iterator find(const key_type& key) const
19193 {
19194 for (auto it = this->begin(); it != this->end(); ++it)
19195 {
19196 if (m_compare(it->first, key))
19197 {
19198 return it;
19199 }
19200 }
19201 return Container::end();
19202 }
19203
19204 std::pair<iterator, bool> insert( value_type&& value )
19205 {
19206 return emplace(value.first, std::move(value.second));
19207 }
19208
19209 std::pair<iterator, bool> insert( const value_type& value )
19210 {
19211 for (auto it = this->begin(); it != this->end(); ++it)
19212 {
19213 if (m_compare(it->first, value.first))
19214 {
19215 return {it, false};
19216 }
19217 }
19218 Container::push_back(value);
19219 return {--this->end(), true};
19220 }
19221
19222 template<typename InputIt>
19223 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
19224 std::input_iterator_tag>::value>::type;
19225
19226 template<typename InputIt, typename = require_input_iter<InputIt>>
19227 void insert(InputIt first, InputIt last)
19228 {
19229 for (auto it = first; it != last; ++it)
19230 {
19231 insert(*it);
19232 }
19233 }
19234
19235private:
19236 JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
19237};
19238
19239NLOHMANN_JSON_NAMESPACE_END
19240
19241
19242#if defined(JSON_HAS_CPP_17)
19243 #include <any>
19244 #include <string_view>
19245#endif
19246
19247/*!
19248@brief namespace for Niels Lohmann
19249@see https://github.com/nlohmann
19250@since version 1.0.0
19251*/
19252NLOHMANN_JSON_NAMESPACE_BEGIN
19253
19254/*!
19255@brief a class to store JSON values
19256
19257@internal
19258@invariant The member variables @a m_value and @a m_type have the following
19259relationship:
19260- If `m_type == value_t::object`, then `m_value.object != nullptr`.
19261- If `m_type == value_t::array`, then `m_value.array != nullptr`.
19262- If `m_type == value_t::string`, then `m_value.string != nullptr`.
19263The invariants are checked by member function assert_invariant().
19264
19265@note ObjectType trick from https://stackoverflow.com/a/9860911
19266@endinternal
19267
19268@since version 1.0.0
19269
19270@nosubgrouping
19271*/
19272NLOHMANN_BASIC_JSON_TPL_DECLARATION
19273class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
19274{
19275 private:
19276 template<detail::value_t> friend struct detail::external_constructor;
19277
19278 template<typename>
19279 friend class ::nlohmann::json_pointer;
19280 // can be restored when json_pointer backwards compatibility is removed
19281 // friend ::nlohmann::json_pointer<StringType>;
19282
19283 template<typename BasicJsonType, typename InputType>
19284 friend class ::nlohmann::detail::parser;
19285 friend ::nlohmann::detail::serializer<basic_json>;
19286 template<typename BasicJsonType>
19287 friend class ::nlohmann::detail::iter_impl;
19288 template<typename BasicJsonType, typename CharType>
19289 friend class ::nlohmann::detail::binary_writer;
19290 template<typename BasicJsonType, typename InputType, typename SAX>
19291 friend class ::nlohmann::detail::binary_reader;
19292 template<typename BasicJsonType>
19293 friend class ::nlohmann::detail::json_sax_dom_parser;
19294 template<typename BasicJsonType>
19295 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
19296 friend class ::nlohmann::detail::exception;
19297
19298 /// workaround type for MSVC
19299 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
19300
19301 JSON_PRIVATE_UNLESS_TESTED:
19302 // convenience aliases for types residing in namespace detail;
19303 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
19304
19305 template<typename InputAdapterType>
19306 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
19307 InputAdapterType adapter,
19308 detail::parser_callback_t<basic_json>cb = nullptr,
19309 const bool allow_exceptions = true,
19310 const bool ignore_comments = false
19311 )
19312 {
19313 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
19314 std::move(cb), allow_exceptions, ignore_comments);
19315 }
19316
19317 private:
19318 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
19319 template<typename BasicJsonType>
19320 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
19321 template<typename BasicJsonType>
19322 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
19323 template<typename Iterator>
19324 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
19325 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
19326
19327 template<typename CharType>
19328 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
19329
19330 template<typename InputType>
19331 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
19332 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
19333
19334 JSON_PRIVATE_UNLESS_TESTED:
19335 using serializer = ::nlohmann::detail::serializer<basic_json>;
19336
19337 public:
19338 using value_t = detail::value_t;
19339 /// JSON Pointer, see @ref nlohmann::json_pointer
19340 using json_pointer = ::nlohmann::json_pointer<StringType>;
19341 template<typename T, typename SFINAE>
19342 using json_serializer = JSONSerializer<T, SFINAE>;
19343 /// how to treat decoding errors
19344 using error_handler_t = detail::error_handler_t;
19345 /// how to treat CBOR tags
19346 using cbor_tag_handler_t = detail::cbor_tag_handler_t;
19347 /// helper type for initializer lists of basic_json values
19348 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
19349
19350 using input_format_t = detail::input_format_t;
19351 /// SAX interface type, see @ref nlohmann::json_sax
19352 using json_sax_t = json_sax<basic_json>;
19353
19354 ////////////////
19355 // exceptions //
19356 ////////////////
19357
19358 /// @name exceptions
19359 /// Classes to implement user-defined exceptions.
19360 /// @{
19361
19362 using exception = detail::exception;
19363 using parse_error = detail::parse_error;
19364 using invalid_iterator = detail::invalid_iterator;
19365 using type_error = detail::type_error;
19366 using out_of_range = detail::out_of_range;
19367 using other_error = detail::other_error;
19368
19369 /// @}
19370
19371
19372 /////////////////////
19373 // container types //
19374 /////////////////////
19375
19376 /// @name container types
19377 /// The canonic container types to use @ref basic_json like any other STL
19378 /// container.
19379 /// @{
19380
19381 /// the type of elements in a basic_json container
19382 using value_type = basic_json;
19383
19384 /// the type of an element reference
19385 using reference = value_type&;
19386 /// the type of an element const reference
19387 using const_reference = const value_type&;
19388
19389 /// a type to represent differences between iterators
19390 using difference_type = std::ptrdiff_t;
19391 /// a type to represent container sizes
19392 using size_type = std::size_t;
19393
19394 /// the allocator type
19395 using allocator_type = AllocatorType<basic_json>;
19396
19397 /// the type of an element pointer
19398 using pointer = typename std::allocator_traits<allocator_type>::pointer;
19399 /// the type of an element const pointer
19400 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
19401
19402 /// an iterator for a basic_json container
19403 using iterator = iter_impl<basic_json>;
19404 /// a const iterator for a basic_json container
19405 using const_iterator = iter_impl<const basic_json>;
19406 /// a reverse iterator for a basic_json container
19407 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
19408 /// a const reverse iterator for a basic_json container
19409 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
19410
19411 /// @}
19412
19413
19414 /// @brief returns the allocator associated with the container
19415 /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
19416 static allocator_type get_allocator()
19417 {
19418 return allocator_type();
19419 }
19420
19421 /// @brief returns version information on the library
19422 /// @sa https://json.nlohmann.me/api/basic_json/meta/
19423 JSON_HEDLEY_WARN_UNUSED_RESULT
19424 static basic_json meta()
19425 {
19426 basic_json result;
19427
19428 result["copyright"] = "(C) 2013-2022 Niels Lohmann";
19429 result["name"] = "JSON for Modern C++";
19430 result["url"] = "https://github.com/nlohmann/json";
19431 result["version"]["string"] =
19432 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
19433 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
19434 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
19435 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
19436 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
19437 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
19438
19439#ifdef _WIN32
19440 result["platform"] = "win32";
19441#elif defined __linux__
19442 result["platform"] = "linux";
19443#elif defined __APPLE__
19444 result["platform"] = "apple";
19445#elif defined __unix__
19446 result["platform"] = "unix";
19447#else
19448 result["platform"] = "unknown";
19449#endif
19450
19451#if defined(__ICC) || defined(__INTEL_COMPILER)
19452 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
19453#elif defined(__clang__)
19454 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
19455#elif defined(__GNUC__) || defined(__GNUG__)
19456 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
19457 std::to_string(__GNUC__), '.',
19458 std::to_string(__GNUC_MINOR__), '.',
19459 std::to_string(__GNUC_PATCHLEVEL__))
19460 }
19461 };
19462#elif defined(__HP_cc) || defined(__HP_aCC)
19463 result["compiler"] = "hp"
19464#elif defined(__IBMCPP__)
19465 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
19466#elif defined(_MSC_VER)
19467 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
19468#elif defined(__PGI)
19469 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
19470#elif defined(__SUNPRO_CC)
19471 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
19472#else
19473 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
19474#endif
19475
19476
19477#if defined(_MSVC_LANG)
19478 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
19479#elif defined(__cplusplus)
19480 result["compiler"]["c++"] = std::to_string(__cplusplus);
19481#else
19482 result["compiler"]["c++"] = "unknown";
19483#endif
19484 return result;
19485 }
19486
19487
19488 ///////////////////////////
19489 // JSON value data types //
19490 ///////////////////////////
19491
19492 /// @name JSON value data types
19493 /// The data types to store a JSON value. These types are derived from
19494 /// the template arguments passed to class @ref basic_json.
19495 /// @{
19496
19497 /// @brief default object key comparator type
19498 /// The actual object key comparator type (@ref object_comparator_t) may be
19499 /// different.
19500 /// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/
19501#if defined(JSON_HAS_CPP_14)
19502 // use of transparent comparator avoids unnecessary repeated construction of temporaries
19503 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
19504 using default_object_comparator_t = std::less<>;
19505#else
19506 using default_object_comparator_t = std::less<StringType>;
19507#endif
19508
19509 /// @brief a type for an object
19510 /// @sa https://json.nlohmann.me/api/basic_json/object_t/
19511 using object_t = ObjectType<StringType,
19512 basic_json,
19513 default_object_comparator_t,
19514 AllocatorType<std::pair<const StringType,
19515 basic_json>>>;
19516
19517 /// @brief a type for an array
19518 /// @sa https://json.nlohmann.me/api/basic_json/array_t/
19519 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
19520
19521 /// @brief a type for a string
19522 /// @sa https://json.nlohmann.me/api/basic_json/string_t/
19523 using string_t = StringType;
19524
19525 /// @brief a type for a boolean
19526 /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/
19527 using boolean_t = BooleanType;
19528
19529 /// @brief a type for a number (integer)
19530 /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/
19531 using number_integer_t = NumberIntegerType;
19532
19533 /// @brief a type for a number (unsigned)
19534 /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/
19535 using number_unsigned_t = NumberUnsignedType;
19536
19537 /// @brief a type for a number (floating-point)
19538 /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/
19539 using number_float_t = NumberFloatType;
19540
19541 /// @brief a type for a packed binary type
19542 /// @sa https://json.nlohmann.me/api/basic_json/binary_t/
19543 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
19544
19545 /// @brief object key comparator type
19546 /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
19547 using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
19548
19549 /// @}
19550
19551 private:
19552
19553 /// helper for exception-safe object creation
19554 template<typename T, typename... Args>
19555 JSON_HEDLEY_RETURNS_NON_NULL
19556 static T* create(Args&& ... args)
19557 {
19558 AllocatorType<T> alloc;
19559 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
19560
19561 auto deleter = [&](T * obj)
19562 {
19563 AllocatorTraits::deallocate(alloc, obj, 1);
19564 };
19565 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
19566 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
19567 JSON_ASSERT(obj != nullptr);
19568 return obj.release();
19569 }
19570
19571 ////////////////////////
19572 // JSON value storage //
19573 ////////////////////////
19574
19575 JSON_PRIVATE_UNLESS_TESTED:
19576 /*!
19577 @brief a JSON value
19578
19579 The actual storage for a JSON value of the @ref basic_json class. This
19580 union combines the different storage types for the JSON value types
19581 defined in @ref value_t.
19582
19583 JSON type | value_t type | used type
19584 --------- | --------------- | ------------------------
19585 object | object | pointer to @ref object_t
19586 array | array | pointer to @ref array_t
19587 string | string | pointer to @ref string_t
19588 boolean | boolean | @ref boolean_t
19589 number | number_integer | @ref number_integer_t
19590 number | number_unsigned | @ref number_unsigned_t
19591 number | number_float | @ref number_float_t
19592 binary | binary | pointer to @ref binary_t
19593 null | null | *no value is stored*
19594
19595 @note Variable-length types (objects, arrays, and strings) are stored as
19596 pointers. The size of the union should not exceed 64 bits if the default
19597 value types are used.
19598
19599 @since version 1.0.0
19600 */
19601 union json_value
19602 {
19603 /// object (stored with pointer to save storage)
19604 object_t* object;
19605 /// array (stored with pointer to save storage)
19606 array_t* array;
19607 /// string (stored with pointer to save storage)
19608 string_t* string;
19609 /// binary (stored with pointer to save storage)
19610 binary_t* binary;
19611 /// boolean
19612 boolean_t boolean;
19613 /// number (integer)
19614 number_integer_t number_integer;
19615 /// number (unsigned integer)
19616 number_unsigned_t number_unsigned;
19617 /// number (floating-point)
19618 number_float_t number_float;
19619
19620 /// default constructor (for null values)
19621 json_value() = default;
19622 /// constructor for booleans
19623 json_value(boolean_t v) noexcept : boolean(v) {}
19624 /// constructor for numbers (integer)
19625 json_value(number_integer_t v) noexcept : number_integer(v) {}
19626 /// constructor for numbers (unsigned)
19627 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
19628 /// constructor for numbers (floating-point)
19629 json_value(number_float_t v) noexcept : number_float(v) {}
19630 /// constructor for empty values of a given type
19631 json_value(value_t t)
19632 {
19633 switch (t)
19634 {
19635 case value_t::object:
19636 {
19637 object = create<object_t>();
19638 break;
19639 }
19640
19641 case value_t::array:
19642 {
19643 array = create<array_t>();
19644 break;
19645 }
19646
19647 case value_t::string:
19648 {
19649 string = create<string_t>("");
19650 break;
19651 }
19652
19653 case value_t::binary:
19654 {
19655 binary = create<binary_t>();
19656 break;
19657 }
19658
19659 case value_t::boolean:
19660 {
19661 boolean = static_cast<boolean_t>(false);
19662 break;
19663 }
19664
19665 case value_t::number_integer:
19666 {
19667 number_integer = static_cast<number_integer_t>(0);
19668 break;
19669 }
19670
19671 case value_t::number_unsigned:
19672 {
19673 number_unsigned = static_cast<number_unsigned_t>(0);
19674 break;
19675 }
19676
19677 case value_t::number_float:
19678 {
19679 number_float = static_cast<number_float_t>(0.0);
19680 break;
19681 }
19682
19683 case value_t::null:
19684 {
19685 object = nullptr; // silence warning, see #821
19686 break;
19687 }
19688
19689 case value_t::discarded:
19690 default:
19691 {
19692 object = nullptr; // silence warning, see #821
19693 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
19694 {
19695 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.2", nullptr)); // LCOV_EXCL_LINE
19696 }
19697 break;
19698 }
19699 }
19700 }
19701
19702 /// constructor for strings
19703 json_value(const string_t& value) : string(create<string_t>(value)) {}
19704
19705 /// constructor for rvalue strings
19706 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
19707
19708 /// constructor for objects
19709 json_value(const object_t& value) : object(create<object_t>(value)) {}
19710
19711 /// constructor for rvalue objects
19712 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
19713
19714 /// constructor for arrays
19715 json_value(const array_t& value) : array(create<array_t>(value)) {}
19716
19717 /// constructor for rvalue arrays
19718 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
19719
19720 /// constructor for binary arrays
19721 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
19722
19723 /// constructor for rvalue binary arrays
19724 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
19725
19726 /// constructor for binary arrays (internal type)
19727 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
19728
19729 /// constructor for rvalue binary arrays (internal type)
19730 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
19731
19732 void destroy(value_t t)
19733 {
19734 if (t == value_t::array || t == value_t::object)
19735 {
19736 // flatten the current json_value to a heap-allocated stack
19737 std::vector<basic_json> stack;
19738
19739 // move the top-level items to stack
19740 if (t == value_t::array)
19741 {
19742 stack.reserve(array->size());
19743 std::move(array->begin(), array->end(), std::back_inserter(stack));
19744 }
19745 else
19746 {
19747 stack.reserve(object->size());
19748 for (auto&& it : *object)
19749 {
19750 stack.push_back(std::move(it.second));
19751 }
19752 }
19753
19754 while (!stack.empty())
19755 {
19756 // move the last item to local variable to be processed
19757 basic_json current_item(std::move(stack.back()));
19758 stack.pop_back();
19759
19760 // if current_item is array/object, move
19761 // its children to the stack to be processed later
19762 if (current_item.is_array())
19763 {
19764 std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack));
19765
19766 current_item.m_value.array->clear();
19767 }
19768 else if (current_item.is_object())
19769 {
19770 for (auto&& it : *current_item.m_value.object)
19771 {
19772 stack.push_back(std::move(it.second));
19773 }
19774
19775 current_item.m_value.object->clear();
19776 }
19777
19778 // it's now safe that current_item get destructed
19779 // since it doesn't have any children
19780 }
19781 }
19782
19783 switch (t)
19784 {
19785 case value_t::object:
19786 {
19787 AllocatorType<object_t> alloc;
19788 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
19789 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
19790 break;
19791 }
19792
19793 case value_t::array:
19794 {
19795 AllocatorType<array_t> alloc;
19796 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
19797 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
19798 break;
19799 }
19800
19801 case value_t::string:
19802 {
19803 AllocatorType<string_t> alloc;
19804 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
19805 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
19806 break;
19807 }
19808
19809 case value_t::binary:
19810 {
19811 AllocatorType<binary_t> alloc;
19812 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
19813 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
19814 break;
19815 }
19816
19817 case value_t::null:
19818 case value_t::boolean:
19819 case value_t::number_integer:
19820 case value_t::number_unsigned:
19821 case value_t::number_float:
19822 case value_t::discarded:
19823 default:
19824 {
19825 break;
19826 }
19827 }
19828 }
19829 };
19830
19831 private:
19832 /*!
19833 @brief checks the class invariants
19834
19835 This function asserts the class invariants. It needs to be called at the
19836 end of every constructor to make sure that created objects respect the
19837 invariant. Furthermore, it has to be called each time the type of a JSON
19838 value is changed, because the invariant expresses a relationship between
19839 @a m_type and @a m_value.
19840
19841 Furthermore, the parent relation is checked for arrays and objects: If
19842 @a check_parents true and the value is an array or object, then the
19843 container's elements must have the current value as parent.
19844
19845 @param[in] check_parents whether the parent relation should be checked.
19846 The value is true by default and should only be set to false
19847 during destruction of objects when the invariant does not
19848 need to hold.
19849 */
19850 void assert_invariant(bool check_parents = true) const noexcept
19851 {
19852 JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr);
19853 JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr);
19854 JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr);
19855 JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr);
19856
19857#if JSON_DIAGNOSTICS
19858 JSON_TRY
19859 {
19860 // cppcheck-suppress assertWithSideEffect
19861 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
19862 {
19863 return j.m_parent == this;
19864 }));
19865 }
19866 JSON_CATCH(...) {} // LCOV_EXCL_LINE
19867#endif
19868 static_cast<void>(check_parents);
19869 }
19870
19871 void set_parents()
19872 {
19873#if JSON_DIAGNOSTICS
19874 switch (m_type)
19875 {
19876 case value_t::array:
19877 {
19878 for (auto& element : *m_value.array)
19879 {
19880 element.m_parent = this;
19881 }
19882 break;
19883 }
19884
19885 case value_t::object:
19886 {
19887 for (auto& element : *m_value.object)
19888 {
19889 element.second.m_parent = this;
19890 }
19891 break;
19892 }
19893
19894 case value_t::null:
19895 case value_t::string:
19896 case value_t::boolean:
19897 case value_t::number_integer:
19898 case value_t::number_unsigned:
19899 case value_t::number_float:
19900 case value_t::binary:
19901 case value_t::discarded:
19902 default:
19903 break;
19904 }
19905#endif
19906 }
19907
19908 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
19909 {
19910#if JSON_DIAGNOSTICS
19911 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
19912 {
19913 (it + i)->m_parent = this;
19914 }
19915#else
19916 static_cast<void>(count_set_parents);
19917#endif
19918 return it;
19919 }
19920
19921 reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
19922 {
19923#if JSON_DIAGNOSTICS
19924 if (old_capacity != static_cast<std::size_t>(-1))
19925 {
19926 // see https://github.com/nlohmann/json/issues/2838
19927 JSON_ASSERT(type() == value_t::array);
19928 if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
19929 {
19930 // capacity has changed: update all parents
19931 set_parents();
19932 return j;
19933 }
19934 }
19935
19936 // ordered_json uses a vector internally, so pointers could have
19937 // been invalidated; see https://github.com/nlohmann/json/issues/2962
19938#ifdef JSON_HEDLEY_MSVC_VERSION
19939#pragma warning(push )
19940#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
19941#endif
19942 if (detail::is_ordered_map<object_t>::value)
19943 {
19944 set_parents();
19945 return j;
19946 }
19947#ifdef JSON_HEDLEY_MSVC_VERSION
19948#pragma warning( pop )
19949#endif
19950
19951 j.m_parent = this;
19952#else
19953 static_cast<void>(j);
19954 static_cast<void>(old_capacity);
19955#endif
19956 return j;
19957 }
19958
19959 public:
19960 //////////////////////////
19961 // JSON parser callback //
19962 //////////////////////////
19963
19964 /// @brief parser event types
19965 /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
19966 using parse_event_t = detail::parse_event_t;
19967
19968 /// @brief per-element parser callback type
19969 /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
19970 using parser_callback_t = detail::parser_callback_t<basic_json>;
19971
19972 //////////////////
19973 // constructors //
19974 //////////////////
19975
19976 /// @name constructors and destructors
19977 /// Constructors of class @ref basic_json, copy/move constructor, copy
19978 /// assignment, static functions creating objects, and the destructor.
19979 /// @{
19980
19981 /// @brief create an empty value with a given type
19982 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
19983 basic_json(const value_t v)
19984 : m_type(v), m_value(v)
19985 {
19986 assert_invariant();
19987 }
19988
19989 /// @brief create a null object
19990 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
19991 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
19992 : basic_json(value_t::null)
19993 {
19994 assert_invariant();
19995 }
19996
19997 /// @brief create a JSON value from compatible types
19998 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
19999 template < typename CompatibleType,
20000 typename U = detail::uncvref_t<CompatibleType>,
20001 detail::enable_if_t <
20002 !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
20003 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
20004 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
20005 std::forward<CompatibleType>(val))))
20006 {
20007 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
20008 set_parents();
20009 assert_invariant();
20010 }
20011
20012 /// @brief create a JSON value from an existing one
20013 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20014 template < typename BasicJsonType,
20015 detail::enable_if_t <
20016 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
20017 basic_json(const BasicJsonType& val)
20018 {
20019 using other_boolean_t = typename BasicJsonType::boolean_t;
20020 using other_number_float_t = typename BasicJsonType::number_float_t;
20021 using other_number_integer_t = typename BasicJsonType::number_integer_t;
20022 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
20023 using other_string_t = typename BasicJsonType::string_t;
20024 using other_object_t = typename BasicJsonType::object_t;
20025 using other_array_t = typename BasicJsonType::array_t;
20026 using other_binary_t = typename BasicJsonType::binary_t;
20027
20028 switch (val.type())
20029 {
20030 case value_t::boolean:
20031 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
20032 break;
20033 case value_t::number_float:
20034 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
20035 break;
20036 case value_t::number_integer:
20037 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
20038 break;
20039 case value_t::number_unsigned:
20040 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
20041 break;
20042 case value_t::string:
20043 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
20044 break;
20045 case value_t::object:
20046 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
20047 break;
20048 case value_t::array:
20049 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
20050 break;
20051 case value_t::binary:
20052 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
20053 break;
20054 case value_t::null:
20055 *this = nullptr;
20056 break;
20057 case value_t::discarded:
20058 m_type = value_t::discarded;
20059 break;
20060 default: // LCOV_EXCL_LINE
20061 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
20062 }
20063 JSON_ASSERT(m_type == val.type());
20064 set_parents();
20065 assert_invariant();
20066 }
20067
20068 /// @brief create a container (array or object) from an initializer list
20069 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20070 basic_json(initializer_list_t init,
20071 bool type_deduction = true,
20072 value_t manual_type = value_t::array)
20073 {
20074 // check if each element is an array with two elements whose first
20075 // element is a string
20076 bool is_an_object = std::all_of(init.begin(), init.end(),
20077 [](const detail::json_ref<basic_json>& element_ref)
20078 {
20079 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string();
20080 });
20081
20082 // adjust type if type deduction is not wanted
20083 if (!type_deduction)
20084 {
20085 // if array is wanted, do not create an object though possible
20086 if (manual_type == value_t::array)
20087 {
20088 is_an_object = false;
20089 }
20090
20091 // if object is wanted but impossible, throw an exception
20092 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
20093 {
20094 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
20095 }
20096 }
20097
20098 if (is_an_object)
20099 {
20100 // the initializer list is a list of pairs -> create object
20101 m_type = value_t::object;
20102 m_value = value_t::object;
20103
20104 for (auto& element_ref : init)
20105 {
20106 auto element = element_ref.moved_or_copied();
20107 m_value.object->emplace(
20108 std::move(*((*element.m_value.array)[0].m_value.string)),
20109 std::move((*element.m_value.array)[1]));
20110 }
20111 }
20112 else
20113 {
20114 // the initializer list describes an array -> create array
20115 m_type = value_t::array;
20116 m_value.array = create<array_t>(init.begin(), init.end());
20117 }
20118
20119 set_parents();
20120 assert_invariant();
20121 }
20122
20123 /// @brief explicitly create a binary array (without subtype)
20124 /// @sa https://json.nlohmann.me/api/basic_json/binary/
20125 JSON_HEDLEY_WARN_UNUSED_RESULT
20126 static basic_json binary(const typename binary_t::container_type& init)
20127 {
20128 auto res = basic_json();
20129 res.m_type = value_t::binary;
20130 res.m_value = init;
20131 return res;
20132 }
20133
20134 /// @brief explicitly create a binary array (with subtype)
20135 /// @sa https://json.nlohmann.me/api/basic_json/binary/
20136 JSON_HEDLEY_WARN_UNUSED_RESULT
20137 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
20138 {
20139 auto res = basic_json();
20140 res.m_type = value_t::binary;
20141 res.m_value = binary_t(init, subtype);
20142 return res;
20143 }
20144
20145 /// @brief explicitly create a binary array
20146 /// @sa https://json.nlohmann.me/api/basic_json/binary/
20147 JSON_HEDLEY_WARN_UNUSED_RESULT
20148 static basic_json binary(typename binary_t::container_type&& init)
20149 {
20150 auto res = basic_json();
20151 res.m_type = value_t::binary;
20152 res.m_value = std::move(init);
20153 return res;
20154 }
20155
20156 /// @brief explicitly create a binary array (with subtype)
20157 /// @sa https://json.nlohmann.me/api/basic_json/binary/
20158 JSON_HEDLEY_WARN_UNUSED_RESULT
20159 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
20160 {
20161 auto res = basic_json();
20162 res.m_type = value_t::binary;
20163 res.m_value = binary_t(std::move(init), subtype);
20164 return res;
20165 }
20166
20167 /// @brief explicitly create an array from an initializer list
20168 /// @sa https://json.nlohmann.me/api/basic_json/array/
20169 JSON_HEDLEY_WARN_UNUSED_RESULT
20170 static basic_json array(initializer_list_t init = {})
20171 {
20172 return basic_json(init, false, value_t::array);
20173 }
20174
20175 /// @brief explicitly create an object from an initializer list
20176 /// @sa https://json.nlohmann.me/api/basic_json/object/
20177 JSON_HEDLEY_WARN_UNUSED_RESULT
20178 static basic_json object(initializer_list_t init = {})
20179 {
20180 return basic_json(init, false, value_t::object);
20181 }
20182
20183 /// @brief construct an array with count copies of given value
20184 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20185 basic_json(size_type cnt, const basic_json& val)
20186 : m_type(value_t::array)
20187 {
20188 m_value.array = create<array_t>(cnt, val);
20189 set_parents();
20190 assert_invariant();
20191 }
20192
20193 /// @brief construct a JSON container given an iterator range
20194 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20195 template < class InputIT, typename std::enable_if <
20196 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
20197 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
20198 basic_json(InputIT first, InputIT last)
20199 {
20200 JSON_ASSERT(first.m_object != nullptr);
20201 JSON_ASSERT(last.m_object != nullptr);
20202
20203 // make sure iterator fits the current value
20204 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20205 {
20206 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
20207 }
20208
20209 // copy type from first iterator
20210 m_type = first.m_object->m_type;
20211
20212 // check if iterator range is complete for primitive values
20213 switch (m_type)
20214 {
20215 case value_t::boolean:
20216 case value_t::number_float:
20217 case value_t::number_integer:
20218 case value_t::number_unsigned:
20219 case value_t::string:
20220 {
20221 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
20222 || !last.m_it.primitive_iterator.is_end()))
20223 {
20224 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
20225 }
20226 break;
20227 }
20228
20229 case value_t::null:
20230 case value_t::object:
20231 case value_t::array:
20232 case value_t::binary:
20233 case value_t::discarded:
20234 default:
20235 break;
20236 }
20237
20238 switch (m_type)
20239 {
20240 case value_t::number_integer:
20241 {
20242 m_value.number_integer = first.m_object->m_value.number_integer;
20243 break;
20244 }
20245
20246 case value_t::number_unsigned:
20247 {
20248 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
20249 break;
20250 }
20251
20252 case value_t::number_float:
20253 {
20254 m_value.number_float = first.m_object->m_value.number_float;
20255 break;
20256 }
20257
20258 case value_t::boolean:
20259 {
20260 m_value.boolean = first.m_object->m_value.boolean;
20261 break;
20262 }
20263
20264 case value_t::string:
20265 {
20266 m_value = *first.m_object->m_value.string;
20267 break;
20268 }
20269
20270 case value_t::object:
20271 {
20272 m_value.object = create<object_t>(first.m_it.object_iterator,
20273 last.m_it.object_iterator);
20274 break;
20275 }
20276
20277 case value_t::array:
20278 {
20279 m_value.array = create<array_t>(first.m_it.array_iterator,
20280 last.m_it.array_iterator);
20281 break;
20282 }
20283
20284 case value_t::binary:
20285 {
20286 m_value = *first.m_object->m_value.binary;
20287 break;
20288 }
20289
20290 case value_t::null:
20291 case value_t::discarded:
20292 default:
20293 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
20294 }
20295
20296 set_parents();
20297 assert_invariant();
20298 }
20299
20300
20301 ///////////////////////////////////////
20302 // other constructors and destructor //
20303 ///////////////////////////////////////
20304
20305 template<typename JsonRef,
20306 detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
20307 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
20308 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
20309
20310 /// @brief copy constructor
20311 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20312 basic_json(const basic_json& other)
20313 : m_type(other.m_type)
20314 {
20315 // check of passed value is valid
20316 other.assert_invariant();
20317
20318 switch (m_type)
20319 {
20320 case value_t::object:
20321 {
20322 m_value = *other.m_value.object;
20323 break;
20324 }
20325
20326 case value_t::array:
20327 {
20328 m_value = *other.m_value.array;
20329 break;
20330 }
20331
20332 case value_t::string:
20333 {
20334 m_value = *other.m_value.string;
20335 break;
20336 }
20337
20338 case value_t::boolean:
20339 {
20340 m_value = other.m_value.boolean;
20341 break;
20342 }
20343
20344 case value_t::number_integer:
20345 {
20346 m_value = other.m_value.number_integer;
20347 break;
20348 }
20349
20350 case value_t::number_unsigned:
20351 {
20352 m_value = other.m_value.number_unsigned;
20353 break;
20354 }
20355
20356 case value_t::number_float:
20357 {
20358 m_value = other.m_value.number_float;
20359 break;
20360 }
20361
20362 case value_t::binary:
20363 {
20364 m_value = *other.m_value.binary;
20365 break;
20366 }
20367
20368 case value_t::null:
20369 case value_t::discarded:
20370 default:
20371 break;
20372 }
20373
20374 set_parents();
20375 assert_invariant();
20376 }
20377
20378 /// @brief move constructor
20379 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20380 basic_json(basic_json&& other) noexcept
20381 : m_type(std::move(other.m_type)),
20382 m_value(std::move(other.m_value))
20383 {
20384 // check that passed value is valid
20385 other.assert_invariant(false);
20386
20387 // invalidate payload
20388 other.m_type = value_t::null;
20389 other.m_value = {};
20390
20391 set_parents();
20392 assert_invariant();
20393 }
20394
20395 /// @brief copy assignment
20396 /// @sa https://json.nlohmann.me/api/basic_json/operator=/
20397 basic_json& operator=(basic_json other) noexcept (
20398 std::is_nothrow_move_constructible<value_t>::value&&
20399 std::is_nothrow_move_assignable<value_t>::value&&
20400 std::is_nothrow_move_constructible<json_value>::value&&
20401 std::is_nothrow_move_assignable<json_value>::value
20402 )
20403 {
20404 // check that passed value is valid
20405 other.assert_invariant();
20406
20407 using std::swap;
20408 swap(m_type, other.m_type);
20409 swap(m_value, other.m_value);
20410
20411 set_parents();
20412 assert_invariant();
20413 return *this;
20414 }
20415
20416 /// @brief destructor
20417 /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/
20418 ~basic_json() noexcept
20419 {
20420 assert_invariant(false);
20421 m_value.destroy(m_type);
20422 }
20423
20424 /// @}
20425
20426 public:
20427 ///////////////////////
20428 // object inspection //
20429 ///////////////////////
20430
20431 /// @name object inspection
20432 /// Functions to inspect the type of a JSON value.
20433 /// @{
20434
20435 /// @brief serialization
20436 /// @sa https://json.nlohmann.me/api/basic_json/dump/
20437 string_t dump(const int indent = -1,
20438 const char indent_char = ' ',
20439 const bool ensure_ascii = false,
20440 const error_handler_t error_handler = error_handler_t::strict) const
20441 {
20442 string_t result;
20443 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
20444
20445 if (indent >= 0)
20446 {
20447 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
20448 }
20449 else
20450 {
20451 s.dump(*this, false, ensure_ascii, 0);
20452 }
20453
20454 return result;
20455 }
20456
20457 /// @brief return the type of the JSON value (explicit)
20458 /// @sa https://json.nlohmann.me/api/basic_json/type/
20459 constexpr value_t type() const noexcept
20460 {
20461 return m_type;
20462 }
20463
20464 /// @brief return whether type is primitive
20465 /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
20466 constexpr bool is_primitive() const noexcept
20467 {
20468 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
20469 }
20470
20471 /// @brief return whether type is structured
20472 /// @sa https://json.nlohmann.me/api/basic_json/is_structured/
20473 constexpr bool is_structured() const noexcept
20474 {
20475 return is_array() || is_object();
20476 }
20477
20478 /// @brief return whether value is null
20479 /// @sa https://json.nlohmann.me/api/basic_json/is_null/
20480 constexpr bool is_null() const noexcept
20481 {
20482 return m_type == value_t::null;
20483 }
20484
20485 /// @brief return whether value is a boolean
20486 /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
20487 constexpr bool is_boolean() const noexcept
20488 {
20489 return m_type == value_t::boolean;
20490 }
20491
20492 /// @brief return whether value is a number
20493 /// @sa https://json.nlohmann.me/api/basic_json/is_number/
20494 constexpr bool is_number() const noexcept
20495 {
20496 return is_number_integer() || is_number_float();
20497 }
20498
20499 /// @brief return whether value is an integer number
20500 /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
20501 constexpr bool is_number_integer() const noexcept
20502 {
20503 return m_type == value_t::number_integer || m_type == value_t::number_unsigned;
20504 }
20505
20506 /// @brief return whether value is an unsigned integer number
20507 /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
20508 constexpr bool is_number_unsigned() const noexcept
20509 {
20510 return m_type == value_t::number_unsigned;
20511 }
20512
20513 /// @brief return whether value is a floating-point number
20514 /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
20515 constexpr bool is_number_float() const noexcept
20516 {
20517 return m_type == value_t::number_float;
20518 }
20519
20520 /// @brief return whether value is an object
20521 /// @sa https://json.nlohmann.me/api/basic_json/is_object/
20522 constexpr bool is_object() const noexcept
20523 {
20524 return m_type == value_t::object;
20525 }
20526
20527 /// @brief return whether value is an array
20528 /// @sa https://json.nlohmann.me/api/basic_json/is_array/
20529 constexpr bool is_array() const noexcept
20530 {
20531 return m_type == value_t::array;
20532 }
20533
20534 /// @brief return whether value is a string
20535 /// @sa https://json.nlohmann.me/api/basic_json/is_string/
20536 constexpr bool is_string() const noexcept
20537 {
20538 return m_type == value_t::string;
20539 }
20540
20541 /// @brief return whether value is a binary array
20542 /// @sa https://json.nlohmann.me/api/basic_json/is_binary/
20543 constexpr bool is_binary() const noexcept
20544 {
20545 return m_type == value_t::binary;
20546 }
20547
20548 /// @brief return whether value is discarded
20549 /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
20550 constexpr bool is_discarded() const noexcept
20551 {
20552 return m_type == value_t::discarded;
20553 }
20554
20555 /// @brief return the type of the JSON value (implicit)
20556 /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/
20557 constexpr operator value_t() const noexcept
20558 {
20559 return m_type;
20560 }
20561
20562 /// @}
20563
20564 private:
20565 //////////////////
20566 // value access //
20567 //////////////////
20568
20569 /// get a boolean (explicit)
20570 boolean_t get_impl(boolean_t* /*unused*/) const
20571 {
20572 if (JSON_HEDLEY_LIKELY(is_boolean()))
20573 {
20574 return m_value.boolean;
20575 }
20576
20577 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
20578 }
20579
20580 /// get a pointer to the value (object)
20581 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
20582 {
20583 return is_object() ? m_value.object : nullptr;
20584 }
20585
20586 /// get a pointer to the value (object)
20587 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
20588 {
20589 return is_object() ? m_value.object : nullptr;
20590 }
20591
20592 /// get a pointer to the value (array)
20593 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
20594 {
20595 return is_array() ? m_value.array : nullptr;
20596 }
20597
20598 /// get a pointer to the value (array)
20599 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
20600 {
20601 return is_array() ? m_value.array : nullptr;
20602 }
20603
20604 /// get a pointer to the value (string)
20605 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
20606 {
20607 return is_string() ? m_value.string : nullptr;
20608 }
20609
20610 /// get a pointer to the value (string)
20611 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
20612 {
20613 return is_string() ? m_value.string : nullptr;
20614 }
20615
20616 /// get a pointer to the value (boolean)
20617 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
20618 {
20619 return is_boolean() ? &m_value.boolean : nullptr;
20620 }
20621
20622 /// get a pointer to the value (boolean)
20623 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
20624 {
20625 return is_boolean() ? &m_value.boolean : nullptr;
20626 }
20627
20628 /// get a pointer to the value (integer number)
20629 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
20630 {
20631 return is_number_integer() ? &m_value.number_integer : nullptr;
20632 }
20633
20634 /// get a pointer to the value (integer number)
20635 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
20636 {
20637 return is_number_integer() ? &m_value.number_integer : nullptr;
20638 }
20639
20640 /// get a pointer to the value (unsigned number)
20641 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
20642 {
20643 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
20644 }
20645
20646 /// get a pointer to the value (unsigned number)
20647 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
20648 {
20649 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
20650 }
20651
20652 /// get a pointer to the value (floating-point number)
20653 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
20654 {
20655 return is_number_float() ? &m_value.number_float : nullptr;
20656 }
20657
20658 /// get a pointer to the value (floating-point number)
20659 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
20660 {
20661 return is_number_float() ? &m_value.number_float : nullptr;
20662 }
20663
20664 /// get a pointer to the value (binary)
20665 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
20666 {
20667 return is_binary() ? m_value.binary : nullptr;
20668 }
20669
20670 /// get a pointer to the value (binary)
20671 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
20672 {
20673 return is_binary() ? m_value.binary : nullptr;
20674 }
20675
20676 /*!
20677 @brief helper function to implement get_ref()
20678
20679 This function helps to implement get_ref() without code duplication for
20680 const and non-const overloads
20681
20682 @tparam ThisType will be deduced as `basic_json` or `const basic_json`
20683
20684 @throw type_error.303 if ReferenceType does not match underlying value
20685 type of the current JSON
20686 */
20687 template<typename ReferenceType, typename ThisType>
20688 static ReferenceType get_ref_impl(ThisType& obj)
20689 {
20690 // delegate the call to get_ptr<>()
20691 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
20692
20693 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
20694 {
20695 return *ptr;
20696 }
20697
20698 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
20699 }
20700
20701 public:
20702 /// @name value access
20703 /// Direct access to the stored value of a JSON value.
20704 /// @{
20705
20706 /// @brief get a pointer value (implicit)
20707 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
20708 template<typename PointerType, typename std::enable_if<
20709 std::is_pointer<PointerType>::value, int>::type = 0>
20710 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20711 {
20712 // delegate the call to get_impl_ptr<>()
20713 return get_impl_ptr(static_cast<PointerType>(nullptr));
20714 }
20715
20716 /// @brief get a pointer value (implicit)
20717 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
20718 template < typename PointerType, typename std::enable_if <
20719 std::is_pointer<PointerType>::value&&
20720 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
20721 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20722 {
20723 // delegate the call to get_impl_ptr<>() const
20724 return get_impl_ptr(static_cast<PointerType>(nullptr));
20725 }
20726
20727 private:
20728 /*!
20729 @brief get a value (explicit)
20730
20731 Explicit type conversion between the JSON value and a compatible value
20732 which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
20733 and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
20734 The value is converted by calling the @ref json_serializer<ValueType>
20735 `from_json()` method.
20736
20737 The function is equivalent to executing
20738 @code {.cpp}
20739 ValueType ret;
20740 JSONSerializer<ValueType>::from_json(*this, ret);
20741 return ret;
20742 @endcode
20743
20744 This overloads is chosen if:
20745 - @a ValueType is not @ref basic_json,
20746 - @ref json_serializer<ValueType> has a `from_json()` method of the form
20747 `void from_json(const basic_json&, ValueType&)`, and
20748 - @ref json_serializer<ValueType> does not have a `from_json()` method of
20749 the form `ValueType from_json(const basic_json&)`
20750
20751 @tparam ValueType the returned value type
20752
20753 @return copy of the JSON value, converted to @a ValueType
20754
20755 @throw what @ref json_serializer<ValueType> `from_json()` method throws
20756
20757 @liveexample{The example below shows several conversions from JSON values
20758 to other types. There a few things to note: (1) Floating-point numbers can
20759 be converted to integers\, (2) A JSON array can be converted to a standard
20760 `std::vector<short>`\, (3) A JSON object can be converted to C++
20761 associative containers such as `std::unordered_map<std::string\,
20762 json>`.,get__ValueType_const}
20763
20764 @since version 2.1.0
20765 */
20766 template < typename ValueType,
20767 detail::enable_if_t <
20768 detail::is_default_constructible<ValueType>::value&&
20769 detail::has_from_json<basic_json_t, ValueType>::value,
20770 int > = 0 >
20771 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
20772 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
20773 {
20774 auto ret = ValueType();
20775 JSONSerializer<ValueType>::from_json(*this, ret);
20776 return ret;
20777 }
20778
20779 /*!
20780 @brief get a value (explicit); special case
20781
20782 Explicit type conversion between the JSON value and a compatible value
20783 which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
20784 and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
20785 The value is converted by calling the @ref json_serializer<ValueType>
20786 `from_json()` method.
20787
20788 The function is equivalent to executing
20789 @code {.cpp}
20790 return JSONSerializer<ValueType>::from_json(*this);
20791 @endcode
20792
20793 This overloads is chosen if:
20794 - @a ValueType is not @ref basic_json and
20795 - @ref json_serializer<ValueType> has a `from_json()` method of the form
20796 `ValueType from_json(const basic_json&)`
20797
20798 @note If @ref json_serializer<ValueType> has both overloads of
20799 `from_json()`, this one is chosen.
20800
20801 @tparam ValueType the returned value type
20802
20803 @return copy of the JSON value, converted to @a ValueType
20804
20805 @throw what @ref json_serializer<ValueType> `from_json()` method throws
20806
20807 @since version 2.1.0
20808 */
20809 template < typename ValueType,
20810 detail::enable_if_t <
20811 detail::has_non_default_from_json<basic_json_t, ValueType>::value,
20812 int > = 0 >
20813 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
20814 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
20815 {
20816 return JSONSerializer<ValueType>::from_json(*this);
20817 }
20818
20819 /*!
20820 @brief get special-case overload
20821
20822 This overloads converts the current @ref basic_json in a different
20823 @ref basic_json type
20824
20825 @tparam BasicJsonType == @ref basic_json
20826
20827 @return a copy of *this, converted into @a BasicJsonType
20828
20829 @complexity Depending on the implementation of the called `from_json()`
20830 method.
20831
20832 @since version 3.2.0
20833 */
20834 template < typename BasicJsonType,
20835 detail::enable_if_t <
20836 detail::is_basic_json<BasicJsonType>::value,
20837 int > = 0 >
20838 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
20839 {
20840 return *this;
20841 }
20842
20843 /*!
20844 @brief get special-case overload
20845
20846 This overloads avoids a lot of template boilerplate, it can be seen as the
20847 identity method
20848
20849 @tparam BasicJsonType == @ref basic_json
20850
20851 @return a copy of *this
20852
20853 @complexity Constant.
20854
20855 @since version 2.1.0
20856 */
20857 template<typename BasicJsonType,
20858 detail::enable_if_t<
20859 std::is_same<BasicJsonType, basic_json_t>::value,
20860 int> = 0>
20861 basic_json get_impl(detail::priority_tag<3> /*unused*/) const
20862 {
20863 return *this;
20864 }
20865
20866 /*!
20867 @brief get a pointer value (explicit)
20868 @copydoc get()
20869 */
20870 template<typename PointerType,
20871 detail::enable_if_t<
20872 std::is_pointer<PointerType>::value,
20873 int> = 0>
20874 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
20875 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
20876 {
20877 // delegate the call to get_ptr
20878 return get_ptr<PointerType>();
20879 }
20880
20881 public:
20882 /*!
20883 @brief get a (pointer) value (explicit)
20884
20885 Performs explicit type conversion between the JSON value and a compatible value if required.
20886
20887 - If the requested type is a pointer to the internally stored JSON value that pointer is returned.
20888 No copies are made.
20889
20890 - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
20891 from the current @ref basic_json.
20892
20893 - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
20894 method.
20895
20896 @tparam ValueTypeCV the provided value type
20897 @tparam ValueType the returned value type
20898
20899 @return copy of the JSON value, converted to @tparam ValueType if necessary
20900
20901 @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
20902
20903 @since version 2.1.0
20904 */
20905 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
20906#if defined(JSON_HAS_CPP_14)
20907 constexpr
20908#endif
20909 auto get() const noexcept(
20910 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
20911 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
20912 {
20913 // we cannot static_assert on ValueTypeCV being non-const, because
20914 // there is support for get<const basic_json_t>(), which is why we
20915 // still need the uncvref
20916 static_assert(!std::is_reference<ValueTypeCV>::value,
20917 "get() cannot be used with reference types, you might want to use get_ref()");
20918 return get_impl<ValueType>(detail::priority_tag<4> {});
20919 }
20920
20921 /*!
20922 @brief get a pointer value (explicit)
20923
20924 Explicit pointer access to the internally stored JSON value. No copies are
20925 made.
20926
20927 @warning The pointer becomes invalid if the underlying JSON object
20928 changes.
20929
20930 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
20931 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
20932 @ref number_unsigned_t, or @ref number_float_t.
20933
20934 @return pointer to the internally stored JSON value if the requested
20935 pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
20936
20937 @complexity Constant.
20938
20939 @liveexample{The example below shows how pointers to internal values of a
20940 JSON value can be requested. Note that no type conversions are made and a
20941 `nullptr` is returned if the value and the requested pointer type does not
20942 match.,get__PointerType}
20943
20944 @sa see @ref get_ptr() for explicit pointer-member access
20945
20946 @since version 1.0.0
20947 */
20948 template<typename PointerType, typename std::enable_if<
20949 std::is_pointer<PointerType>::value, int>::type = 0>
20950 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
20951 {
20952 // delegate the call to get_ptr
20953 return get_ptr<PointerType>();
20954 }
20955
20956 /// @brief get a value (explicit)
20957 /// @sa https://json.nlohmann.me/api/basic_json/get_to/
20958 template < typename ValueType,
20959 detail::enable_if_t <
20960 !detail::is_basic_json<ValueType>::value&&
20961 detail::has_from_json<basic_json_t, ValueType>::value,
20962 int > = 0 >
20963 ValueType & get_to(ValueType& v) const noexcept(noexcept(
20964 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
20965 {
20966 JSONSerializer<ValueType>::from_json(*this, v);
20967 return v;
20968 }
20969
20970 // specialization to allow calling get_to with a basic_json value
20971 // see https://github.com/nlohmann/json/issues/2175
20972 template<typename ValueType,
20973 detail::enable_if_t <
20974 detail::is_basic_json<ValueType>::value,
20975 int> = 0>
20976 ValueType & get_to(ValueType& v) const
20977 {
20978 v = *this;
20979 return v;
20980 }
20981
20982 template <
20983 typename T, std::size_t N,
20984 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
20985 detail::enable_if_t <
20986 detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
20987 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
20988 noexcept(noexcept(JSONSerializer<Array>::from_json(
20989 std::declval<const basic_json_t&>(), v)))
20990 {
20991 JSONSerializer<Array>::from_json(*this, v);
20992 return v;
20993 }
20994
20995 /// @brief get a reference value (implicit)
20996 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
20997 template<typename ReferenceType, typename std::enable_if<
20998 std::is_reference<ReferenceType>::value, int>::type = 0>
20999 ReferenceType get_ref()
21000 {
21001 // delegate call to get_ref_impl
21002 return get_ref_impl<ReferenceType>(*this);
21003 }
21004
21005 /// @brief get a reference value (implicit)
21006 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
21007 template < typename ReferenceType, typename std::enable_if <
21008 std::is_reference<ReferenceType>::value&&
21009 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
21010 ReferenceType get_ref() const
21011 {
21012 // delegate call to get_ref_impl
21013 return get_ref_impl<ReferenceType>(*this);
21014 }
21015
21016 /*!
21017 @brief get a value (implicit)
21018
21019 Implicit type conversion between the JSON value and a compatible value.
21020 The call is realized by calling @ref get() const.
21021
21022 @tparam ValueType non-pointer type compatible to the JSON value, for
21023 instance `int` for JSON integer numbers, `bool` for JSON booleans, or
21024 `std::vector` types for JSON arrays. The character type of @ref string_t
21025 as well as an initializer list of this type is excluded to avoid
21026 ambiguities as these types implicitly convert to `std::string`.
21027
21028 @return copy of the JSON value, converted to type @a ValueType
21029
21030 @throw type_error.302 in case passed type @a ValueType is incompatible
21031 to the JSON value type (e.g., the JSON value is of type boolean, but a
21032 string is requested); see example below
21033
21034 @complexity Linear in the size of the JSON value.
21035
21036 @liveexample{The example below shows several conversions from JSON values
21037 to other types. There a few things to note: (1) Floating-point numbers can
21038 be converted to integers\, (2) A JSON array can be converted to a standard
21039 `std::vector<short>`\, (3) A JSON object can be converted to C++
21040 associative containers such as `std::unordered_map<std::string\,
21041 json>`.,operator__ValueType}
21042
21043 @since version 1.0.0
21044 */
21045 template < typename ValueType, typename std::enable_if <
21046 detail::conjunction <
21047 detail::negation<std::is_pointer<ValueType>>,
21048 detail::negation<std::is_same<ValueType, std::nullptr_t>>,
21049 detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
21050 detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
21051 detail::negation<detail::is_basic_json<ValueType>>,
21052 detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
21053#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
21054 detail::negation<std::is_same<ValueType, std::string_view>>,
21055#endif
21056#if defined(JSON_HAS_CPP_17)
21057 detail::negation<std::is_same<ValueType, std::any>>,
21058#endif
21059 detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>
21060 >::value, int >::type = 0 >
21061 JSON_EXPLICIT operator ValueType() const
21062 {
21063 // delegate the call to get<>() const
21064 return get<ValueType>();
21065 }
21066
21067 /// @brief get a binary value
21068 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
21069 binary_t& get_binary()
21070 {
21071 if (!is_binary())
21072 {
21073 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21074 }
21075
21076 return *get_ptr<binary_t*>();
21077 }
21078
21079 /// @brief get a binary value
21080 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
21081 const binary_t& get_binary() const
21082 {
21083 if (!is_binary())
21084 {
21085 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21086 }
21087
21088 return *get_ptr<const binary_t*>();
21089 }
21090
21091 /// @}
21092
21093
21094 ////////////////////
21095 // element access //
21096 ////////////////////
21097
21098 /// @name element access
21099 /// Access to the JSON value.
21100 /// @{
21101
21102 /// @brief access specified array element with bounds checking
21103 /// @sa https://json.nlohmann.me/api/basic_json/at/
21104 reference at(size_type idx)
21105 {
21106 // at only works for arrays
21107 if (JSON_HEDLEY_LIKELY(is_array()))
21108 {
21109 JSON_TRY
21110 {
21111 return set_parent(m_value.array->at(idx));
21112 }
21113 JSON_CATCH (std::out_of_range&)
21114 {
21115 // create better exception explanation
21116 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21117 }
21118 }
21119 else
21120 {
21121 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21122 }
21123 }
21124
21125 /// @brief access specified array element with bounds checking
21126 /// @sa https://json.nlohmann.me/api/basic_json/at/
21127 const_reference at(size_type idx) const
21128 {
21129 // at only works for arrays
21130 if (JSON_HEDLEY_LIKELY(is_array()))
21131 {
21132 JSON_TRY
21133 {
21134 return m_value.array->at(idx);
21135 }
21136 JSON_CATCH (std::out_of_range&)
21137 {
21138 // create better exception explanation
21139 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21140 }
21141 }
21142 else
21143 {
21144 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21145 }
21146 }
21147
21148 /// @brief access specified object element with bounds checking
21149 /// @sa https://json.nlohmann.me/api/basic_json/at/
21150 reference at(const typename object_t::key_type& key)
21151 {
21152 // at only works for objects
21153 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21154 {
21155 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21156 }
21157
21158 auto it = m_value.object->find(key);
21159 if (it == m_value.object->end())
21160 {
21161 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21162 }
21163 return set_parent(it->second);
21164 }
21165
21166 /// @brief access specified object element with bounds checking
21167 /// @sa https://json.nlohmann.me/api/basic_json/at/
21168 template<class KeyType, detail::enable_if_t<
21169 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21170 reference at(KeyType && key)
21171 {
21172 // at only works for objects
21173 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21174 {
21175 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21176 }
21177
21178 auto it = m_value.object->find(std::forward<KeyType>(key));
21179 if (it == m_value.object->end())
21180 {
21181 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21182 }
21183 return set_parent(it->second);
21184 }
21185
21186 /// @brief access specified object element with bounds checking
21187 /// @sa https://json.nlohmann.me/api/basic_json/at/
21188 const_reference at(const typename object_t::key_type& key) const
21189 {
21190 // at only works for objects
21191 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21192 {
21193 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21194 }
21195
21196 auto it = m_value.object->find(key);
21197 if (it == m_value.object->end())
21198 {
21199 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21200 }
21201 return it->second;
21202 }
21203
21204 /// @brief access specified object element with bounds checking
21205 /// @sa https://json.nlohmann.me/api/basic_json/at/
21206 template<class KeyType, detail::enable_if_t<
21207 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21208 const_reference at(KeyType && key) const
21209 {
21210 // at only works for objects
21211 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21212 {
21213 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21214 }
21215
21216 auto it = m_value.object->find(std::forward<KeyType>(key));
21217 if (it == m_value.object->end())
21218 {
21219 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21220 }
21221 return it->second;
21222 }
21223
21224 /// @brief access specified array element
21225 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21226 reference operator[](size_type idx)
21227 {
21228 // implicitly convert null value to an empty array
21229 if (is_null())
21230 {
21231 m_type = value_t::array;
21232 m_value.array = create<array_t>();
21233 assert_invariant();
21234 }
21235
21236 // operator[] only works for arrays
21237 if (JSON_HEDLEY_LIKELY(is_array()))
21238 {
21239 // fill up array with null values if given idx is outside range
21240 if (idx >= m_value.array->size())
21241 {
21242#if JSON_DIAGNOSTICS
21243 // remember array size & capacity before resizing
21244 const auto old_size = m_value.array->size();
21245 const auto old_capacity = m_value.array->capacity();
21246#endif
21247 m_value.array->resize(idx + 1);
21248
21249#if JSON_DIAGNOSTICS
21250 if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
21251 {
21252 // capacity has changed: update all parents
21253 set_parents();
21254 }
21255 else
21256 {
21257 // set parent for values added above
21258 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
21259 }
21260#endif
21261 assert_invariant();
21262 }
21263
21264 return m_value.array->operator[](idx);
21265 }
21266
21267 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21268 }
21269
21270 /// @brief access specified array element
21271 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21272 const_reference operator[](size_type idx) const
21273 {
21274 // const operator[] only works for arrays
21275 if (JSON_HEDLEY_LIKELY(is_array()))
21276 {
21277 return m_value.array->operator[](idx);
21278 }
21279
21280 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21281 }
21282
21283 /// @brief access specified object element
21284 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21285 reference operator[](typename object_t::key_type key)
21286 {
21287 // implicitly convert null value to an empty object
21288 if (is_null())
21289 {
21290 m_type = value_t::object;
21291 m_value.object = create<object_t>();
21292 assert_invariant();
21293 }
21294
21295 // operator[] only works for objects
21296 if (JSON_HEDLEY_LIKELY(is_object()))
21297 {
21298 auto result = m_value.object->emplace(std::move(key), nullptr);
21299 return set_parent(result.first->second);
21300 }
21301
21302 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21303 }
21304
21305 /// @brief access specified object element
21306 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21307 const_reference operator[](const typename object_t::key_type& key) const
21308 {
21309 // const operator[] only works for objects
21310 if (JSON_HEDLEY_LIKELY(is_object()))
21311 {
21312 auto it = m_value.object->find(key);
21313 JSON_ASSERT(it != m_value.object->end());
21314 return it->second;
21315 }
21316
21317 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21318 }
21319
21320 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
21321 // (they seemingly cannot be constrained to resolve the ambiguity)
21322 template<typename T>
21323 reference operator[](T* key)
21324 {
21325 return operator[](typename object_t::key_type(key));
21326 }
21327
21328 template<typename T>
21329 const_reference operator[](T* key) const
21330 {
21331 return operator[](typename object_t::key_type(key));
21332 }
21333
21334 /// @brief access specified object element
21335 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21336 template<class KeyType, detail::enable_if_t<
21337 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
21338 reference operator[](KeyType && key)
21339 {
21340 // implicitly convert null value to an empty object
21341 if (is_null())
21342 {
21343 m_type = value_t::object;
21344 m_value.object = create<object_t>();
21345 assert_invariant();
21346 }
21347
21348 // operator[] only works for objects
21349 if (JSON_HEDLEY_LIKELY(is_object()))
21350 {
21351 auto result = m_value.object->emplace(std::forward<KeyType>(key), nullptr);
21352 return set_parent(result.first->second);
21353 }
21354
21355 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21356 }
21357
21358 /// @brief access specified object element
21359 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21360 template<class KeyType, detail::enable_if_t<
21361 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
21362 const_reference operator[](KeyType && key) const
21363 {
21364 // const operator[] only works for objects
21365 if (JSON_HEDLEY_LIKELY(is_object()))
21366 {
21367 auto it = m_value.object->find(std::forward<KeyType>(key));
21368 JSON_ASSERT(it != m_value.object->end());
21369 return it->second;
21370 }
21371
21372 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21373 }
21374
21375 private:
21376 template<typename KeyType>
21377 using is_comparable_with_object_key = detail::is_comparable <
21378 object_comparator_t, const typename object_t::key_type&, KeyType >;
21379
21380 template<typename ValueType>
21381 using value_return_type = std::conditional <
21382 detail::is_c_string_uncvref<ValueType>::value,
21383 string_t, typename std::decay<ValueType>::type >;
21384
21385 public:
21386 /// @brief access specified object element with default value
21387 /// @sa https://json.nlohmann.me/api/basic_json/value/
21388 template < class ValueType, detail::enable_if_t <
21389 !detail::is_transparent<object_comparator_t>::value
21390 && detail::is_getable<basic_json_t, ValueType>::value
21391 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21392 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
21393 {
21394 // value only works for objects
21395 if (JSON_HEDLEY_LIKELY(is_object()))
21396 {
21397 // if key is found, return value and given default value otherwise
21398 const auto it = find(key);
21399 if (it != end())
21400 {
21401 return it->template get<ValueType>();
21402 }
21403
21404 return default_value;
21405 }
21406
21407 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21408 }
21409
21410 /// @brief access specified object element with default value
21411 /// @sa https://json.nlohmann.me/api/basic_json/value/
21412 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21413 detail::enable_if_t <
21414 !detail::is_transparent<object_comparator_t>::value
21415 && detail::is_getable<basic_json_t, ReturnType>::value
21416 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21417 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
21418 {
21419 // value only works for objects
21420 if (JSON_HEDLEY_LIKELY(is_object()))
21421 {
21422 // if key is found, return value and given default value otherwise
21423 const auto it = find(key);
21424 if (it != end())
21425 {
21426 return it->template get<ReturnType>();
21427 }
21428
21429 return std::forward<ValueType>(default_value);
21430 }
21431
21432 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21433 }
21434
21435 /// @brief access specified object element with default value
21436 /// @sa https://json.nlohmann.me/api/basic_json/value/
21437 template < class ValueType, class KeyType, detail::enable_if_t <
21438 detail::is_transparent<object_comparator_t>::value
21439 && !detail::is_json_pointer<KeyType>::value
21440 && is_comparable_with_object_key<KeyType>::value
21441 && detail::is_getable<basic_json_t, ValueType>::value
21442 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21443 ValueType value(KeyType && key, const ValueType& default_value) const
21444 {
21445 // value only works for objects
21446 if (JSON_HEDLEY_LIKELY(is_object()))
21447 {
21448 // if key is found, return value and given default value otherwise
21449 const auto it = find(std::forward<KeyType>(key));
21450 if (it != end())
21451 {
21452 return it->template get<ValueType>();
21453 }
21454
21455 return default_value;
21456 }
21457
21458 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21459 }
21460
21461 /// @brief access specified object element via JSON Pointer with default value
21462 /// @sa https://json.nlohmann.me/api/basic_json/value/
21463 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
21464 detail::enable_if_t <
21465 detail::is_transparent<object_comparator_t>::value
21466 && !detail::is_json_pointer<KeyType>::value
21467 && is_comparable_with_object_key<KeyType>::value
21468 && detail::is_getable<basic_json_t, ReturnType>::value
21469 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21470 ReturnType value(KeyType && key, ValueType && default_value) const
21471 {
21472 // value only works for objects
21473 if (JSON_HEDLEY_LIKELY(is_object()))
21474 {
21475 // if key is found, return value and given default value otherwise
21476 const auto it = find(std::forward<KeyType>(key));
21477 if (it != end())
21478 {
21479 return it->template get<ReturnType>();
21480 }
21481
21482 return std::forward<ValueType>(default_value);
21483 }
21484
21485 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21486 }
21487
21488 /// @brief access specified object element via JSON Pointer with default value
21489 /// @sa https://json.nlohmann.me/api/basic_json/value/
21490 template < class ValueType, detail::enable_if_t <
21491 detail::is_getable<basic_json_t, ValueType>::value
21492 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21493 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
21494 {
21495 // value only works for objects
21496 if (JSON_HEDLEY_LIKELY(is_object()))
21497 {
21498 // if pointer resolves a value, return it or use default value
21499 JSON_TRY
21500 {
21501 return ptr.get_checked(this).template get<ValueType>();
21502 }
21503 JSON_INTERNAL_CATCH (out_of_range&)
21504 {
21505 return default_value;
21506 }
21507 }
21508
21509 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21510 }
21511
21512 /// @brief access specified object element via JSON Pointer with default value
21513 /// @sa https://json.nlohmann.me/api/basic_json/value/
21514 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21515 detail::enable_if_t <
21516 detail::is_getable<basic_json_t, ReturnType>::value
21517 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21518 ReturnType value(const json_pointer& ptr, ValueType && default_value) const
21519 {
21520 // value only works for objects
21521 if (JSON_HEDLEY_LIKELY(is_object()))
21522 {
21523 // if pointer resolves a value, return it or use default value
21524 JSON_TRY
21525 {
21526 return ptr.get_checked(this).template get<ReturnType>();
21527 }
21528 JSON_INTERNAL_CATCH (out_of_range&)
21529 {
21530 return std::forward<ValueType>(default_value);
21531 }
21532 }
21533
21534 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21535 }
21536
21537 template < class ValueType, class BasicJsonType, detail::enable_if_t <
21538 detail::is_basic_json<BasicJsonType>::value
21539 && detail::is_getable<basic_json_t, ValueType>::value
21540 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21541 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21542 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
21543 {
21544 return value(ptr.convert(), default_value);
21545 }
21546
21547 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
21548 detail::enable_if_t <
21549 detail::is_basic_json<BasicJsonType>::value
21550 && detail::is_getable<basic_json_t, ReturnType>::value
21551 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21552 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21553 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
21554 {
21555 return value(ptr.convert(), std::forward<ValueType>(default_value));
21556 }
21557
21558 /// @brief access the first element
21559 /// @sa https://json.nlohmann.me/api/basic_json/front/
21560 reference front()
21561 {
21562 return *begin();
21563 }
21564
21565 /// @brief access the first element
21566 /// @sa https://json.nlohmann.me/api/basic_json/front/
21567 const_reference front() const
21568 {
21569 return *cbegin();
21570 }
21571
21572 /// @brief access the last element
21573 /// @sa https://json.nlohmann.me/api/basic_json/back/
21574 reference back()
21575 {
21576 auto tmp = end();
21577 --tmp;
21578 return *tmp;
21579 }
21580
21581 /// @brief access the last element
21582 /// @sa https://json.nlohmann.me/api/basic_json/back/
21583 const_reference back() const
21584 {
21585 auto tmp = cend();
21586 --tmp;
21587 return *tmp;
21588 }
21589
21590 /// @brief remove element given an iterator
21591 /// @sa https://json.nlohmann.me/api/basic_json/erase/
21592 template < class IteratorType, detail::enable_if_t <
21593 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21594 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21595 IteratorType erase(IteratorType pos)
21596 {
21597 // make sure iterator fits the current value
21598 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
21599 {
21600 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21601 }
21602
21603 IteratorType result = end();
21604
21605 switch (m_type)
21606 {
21607 case value_t::boolean:
21608 case value_t::number_float:
21609 case value_t::number_integer:
21610 case value_t::number_unsigned:
21611 case value_t::string:
21612 case value_t::binary:
21613 {
21614 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
21615 {
21616 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
21617 }
21618
21619 if (is_string())
21620 {
21621 AllocatorType<string_t> alloc;
21622 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
21623 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
21624 m_value.string = nullptr;
21625 }
21626 else if (is_binary())
21627 {
21628 AllocatorType<binary_t> alloc;
21629 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
21630 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
21631 m_value.binary = nullptr;
21632 }
21633
21634 m_type = value_t::null;
21635 assert_invariant();
21636 break;
21637 }
21638
21639 case value_t::object:
21640 {
21641 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
21642 break;
21643 }
21644
21645 case value_t::array:
21646 {
21647 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
21648 break;
21649 }
21650
21651 case value_t::null:
21652 case value_t::discarded:
21653 default:
21654 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21655 }
21656
21657 return result;
21658 }
21659
21660 /// @brief remove elements given an iterator range
21661 /// @sa https://json.nlohmann.me/api/basic_json/erase/
21662 template < class IteratorType, detail::enable_if_t <
21663 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21664 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21665 IteratorType erase(IteratorType first, IteratorType last)
21666 {
21667 // make sure iterator fits the current value
21668 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
21669 {
21670 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
21671 }
21672
21673 IteratorType result = end();
21674
21675 switch (m_type)
21676 {
21677 case value_t::boolean:
21678 case value_t::number_float:
21679 case value_t::number_integer:
21680 case value_t::number_unsigned:
21681 case value_t::string:
21682 case value_t::binary:
21683 {
21684 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
21685 || !last.m_it.primitive_iterator.is_end()))
21686 {
21687 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
21688 }
21689
21690 if (is_string())
21691 {
21692 AllocatorType<string_t> alloc;
21693 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
21694 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
21695 m_value.string = nullptr;
21696 }
21697 else if (is_binary())
21698 {
21699 AllocatorType<binary_t> alloc;
21700 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
21701 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
21702 m_value.binary = nullptr;
21703 }
21704
21705 m_type = value_t::null;
21706 assert_invariant();
21707 break;
21708 }
21709
21710 case value_t::object:
21711 {
21712 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
21713 last.m_it.object_iterator);
21714 break;
21715 }
21716
21717 case value_t::array:
21718 {
21719 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
21720 last.m_it.array_iterator);
21721 break;
21722 }
21723
21724 case value_t::null:
21725 case value_t::discarded:
21726 default:
21727 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21728 }
21729
21730 return result;
21731 }
21732
21733 private:
21734 template < typename KeyType, detail::enable_if_t <
21735 detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
21736 size_type erase_internal(KeyType && key)
21737 {
21738 // this erase only works for objects
21739 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21740 {
21741 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21742 }
21743
21744 return m_value.object->erase(std::forward<KeyType>(key));
21745 }
21746
21747 template < typename KeyType, detail::enable_if_t <
21748 !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
21749 size_type erase_internal(KeyType && key)
21750 {
21751 // this erase only works for objects
21752 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21753 {
21754 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21755 }
21756
21757 const auto it = m_value.object->find(std::forward<KeyType>(key));
21758 if (it != m_value.object->end())
21759 {
21760 m_value.object->erase(it);
21761 return 1;
21762 }
21763 return 0;
21764 }
21765
21766 public:
21767
21768 /// @brief remove element from a JSON object given a key
21769 /// @sa https://json.nlohmann.me/api/basic_json/erase/
21770 size_type erase(const typename object_t::key_type& key)
21771 {
21772 // the indirection via erase_internal() is added to avoid making this
21773 // function a template and thus de-rank it during overload resolution
21774 return erase_internal(key);
21775 }
21776
21777 /// @brief remove element from a JSON object given a key
21778 /// @sa https://json.nlohmann.me/api/basic_json/erase/
21779 template<class KeyType, detail::enable_if_t<
21780 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21781 size_type erase(KeyType && key)
21782 {
21783 return erase_internal(std::forward<KeyType>(key));
21784 }
21785
21786 /// @brief remove element from a JSON array given an index
21787 /// @sa https://json.nlohmann.me/api/basic_json/erase/
21788 void erase(const size_type idx)
21789 {
21790 // this erase only works for arrays
21791 if (JSON_HEDLEY_LIKELY(is_array()))
21792 {
21793 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
21794 {
21795 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21796 }
21797
21798 m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
21799 }
21800 else
21801 {
21802 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21803 }
21804 }
21805
21806 /// @}
21807
21808
21809 ////////////
21810 // lookup //
21811 ////////////
21812
21813 /// @name lookup
21814 /// @{
21815
21816 /// @brief find an element in a JSON object
21817 /// @sa https://json.nlohmann.me/api/basic_json/find/
21818 iterator find(const typename object_t::key_type& key)
21819 {
21820 auto result = end();
21821
21822 if (is_object())
21823 {
21824 result.m_it.object_iterator = m_value.object->find(key);
21825 }
21826
21827 return result;
21828 }
21829
21830 /// @brief find an element in a JSON object
21831 /// @sa https://json.nlohmann.me/api/basic_json/find/
21832 const_iterator find(const typename object_t::key_type& key) const
21833 {
21834 auto result = cend();
21835
21836 if (is_object())
21837 {
21838 result.m_it.object_iterator = m_value.object->find(key);
21839 }
21840
21841 return result;
21842 }
21843
21844 /// @brief find an element in a JSON object
21845 /// @sa https://json.nlohmann.me/api/basic_json/find/
21846 template<class KeyType, detail::enable_if_t<
21847 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21848 iterator find(KeyType && key)
21849 {
21850 auto result = end();
21851
21852 if (is_object())
21853 {
21854 result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key));
21855 }
21856
21857 return result;
21858 }
21859
21860 /// @brief find an element in a JSON object
21861 /// @sa https://json.nlohmann.me/api/basic_json/find/
21862 template<class KeyType, detail::enable_if_t<
21863 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21864 const_iterator find(KeyType && key) const
21865 {
21866 auto result = cend();
21867
21868 if (is_object())
21869 {
21870 result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key));
21871 }
21872
21873 return result;
21874 }
21875
21876 /// @brief returns the number of occurrences of a key in a JSON object
21877 /// @sa https://json.nlohmann.me/api/basic_json/count/
21878 size_type count(const typename object_t::key_type& key) const
21879 {
21880 // return 0 for all nonobject types
21881 return is_object() ? m_value.object->count(key) : 0;
21882 }
21883
21884 /// @brief returns the number of occurrences of a key in a JSON object
21885 /// @sa https://json.nlohmann.me/api/basic_json/count/
21886 template<class KeyType, detail::enable_if_t<
21887 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21888 size_type count(KeyType && key) const
21889 {
21890 // return 0 for all nonobject types
21891 return is_object() ? m_value.object->count(std::forward<KeyType>(key)) : 0;
21892 }
21893
21894 /// @brief check the existence of an element in a JSON object
21895 /// @sa https://json.nlohmann.me/api/basic_json/contains/
21896 bool contains(const typename object_t::key_type& key) const
21897 {
21898 return is_object() && m_value.object->find(key) != m_value.object->end();
21899 }
21900
21901 /// @brief check the existence of an element in a JSON object
21902 /// @sa https://json.nlohmann.me/api/basic_json/contains/
21903 template<class KeyType, detail::enable_if_t<
21904 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21905 bool contains(KeyType && key) const
21906 {
21907 return is_object() && m_value.object->find(std::forward<KeyType>(key)) != m_value.object->end();
21908 }
21909
21910 /// @brief check the existence of an element in a JSON object given a JSON pointer
21911 /// @sa https://json.nlohmann.me/api/basic_json/contains/
21912 bool contains(const json_pointer& ptr) const
21913 {
21914 return ptr.contains(this);
21915 }
21916
21917 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
21918 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21919 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
21920 {
21921 return ptr.contains(this);
21922 }
21923
21924 /// @}
21925
21926
21927 ///////////////
21928 // iterators //
21929 ///////////////
21930
21931 /// @name iterators
21932 /// @{
21933
21934 /// @brief returns an iterator to the first element
21935 /// @sa https://json.nlohmann.me/api/basic_json/begin/
21936 iterator begin() noexcept
21937 {
21938 iterator result(this);
21939 result.set_begin();
21940 return result;
21941 }
21942
21943 /// @brief returns an iterator to the first element
21944 /// @sa https://json.nlohmann.me/api/basic_json/begin/
21945 const_iterator begin() const noexcept
21946 {
21947 return cbegin();
21948 }
21949
21950 /// @brief returns a const iterator to the first element
21951 /// @sa https://json.nlohmann.me/api/basic_json/cbegin/
21952 const_iterator cbegin() const noexcept
21953 {
21954 const_iterator result(this);
21955 result.set_begin();
21956 return result;
21957 }
21958
21959 /// @brief returns an iterator to one past the last element
21960 /// @sa https://json.nlohmann.me/api/basic_json/end/
21961 iterator end() noexcept
21962 {
21963 iterator result(this);
21964 result.set_end();
21965 return result;
21966 }
21967
21968 /// @brief returns an iterator to one past the last element
21969 /// @sa https://json.nlohmann.me/api/basic_json/end/
21970 const_iterator end() const noexcept
21971 {
21972 return cend();
21973 }
21974
21975 /// @brief returns an iterator to one past the last element
21976 /// @sa https://json.nlohmann.me/api/basic_json/cend/
21977 const_iterator cend() const noexcept
21978 {
21979 const_iterator result(this);
21980 result.set_end();
21981 return result;
21982 }
21983
21984 /// @brief returns an iterator to the reverse-beginning
21985 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
21986 reverse_iterator rbegin() noexcept
21987 {
21988 return reverse_iterator(end());
21989 }
21990
21991 /// @brief returns an iterator to the reverse-beginning
21992 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
21993 const_reverse_iterator rbegin() const noexcept
21994 {
21995 return crbegin();
21996 }
21997
21998 /// @brief returns an iterator to the reverse-end
21999 /// @sa https://json.nlohmann.me/api/basic_json/rend/
22000 reverse_iterator rend() noexcept
22001 {
22002 return reverse_iterator(begin());
22003 }
22004
22005 /// @brief returns an iterator to the reverse-end
22006 /// @sa https://json.nlohmann.me/api/basic_json/rend/
22007 const_reverse_iterator rend() const noexcept
22008 {
22009 return crend();
22010 }
22011
22012 /// @brief returns a const reverse iterator to the last element
22013 /// @sa https://json.nlohmann.me/api/basic_json/crbegin/
22014 const_reverse_iterator crbegin() const noexcept
22015 {
22016 return const_reverse_iterator(cend());
22017 }
22018
22019 /// @brief returns a const reverse iterator to one before the first
22020 /// @sa https://json.nlohmann.me/api/basic_json/crend/
22021 const_reverse_iterator crend() const noexcept
22022 {
22023 return const_reverse_iterator(cbegin());
22024 }
22025
22026 public:
22027 /// @brief wrapper to access iterator member functions in range-based for
22028 /// @sa https://json.nlohmann.me/api/basic_json/items/
22029 /// @deprecated This function is deprecated since 3.1.0 and will be removed in
22030 /// version 4.0.0 of the library. Please use @ref items() instead;
22031 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
22032 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22033 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
22034 {
22035 return ref.items();
22036 }
22037
22038 /// @brief wrapper to access iterator member functions in range-based for
22039 /// @sa https://json.nlohmann.me/api/basic_json/items/
22040 /// @deprecated This function is deprecated since 3.1.0 and will be removed in
22041 /// version 4.0.0 of the library. Please use @ref items() instead;
22042 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
22043 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22044 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
22045 {
22046 return ref.items();
22047 }
22048
22049 /// @brief helper to access iterator member functions in range-based for
22050 /// @sa https://json.nlohmann.me/api/basic_json/items/
22051 iteration_proxy<iterator> items() noexcept
22052 {
22053 return iteration_proxy<iterator>(*this);
22054 }
22055
22056 /// @brief helper to access iterator member functions in range-based for
22057 /// @sa https://json.nlohmann.me/api/basic_json/items/
22058 iteration_proxy<const_iterator> items() const noexcept
22059 {
22060 return iteration_proxy<const_iterator>(*this);
22061 }
22062
22063 /// @}
22064
22065
22066 //////////////
22067 // capacity //
22068 //////////////
22069
22070 /// @name capacity
22071 /// @{
22072
22073 /// @brief checks whether the container is empty.
22074 /// @sa https://json.nlohmann.me/api/basic_json/empty/
22075 bool empty() const noexcept
22076 {
22077 switch (m_type)
22078 {
22079 case value_t::null:
22080 {
22081 // null values are empty
22082 return true;
22083 }
22084
22085 case value_t::array:
22086 {
22087 // delegate call to array_t::empty()
22088 return m_value.array->empty();
22089 }
22090
22091 case value_t::object:
22092 {
22093 // delegate call to object_t::empty()
22094 return m_value.object->empty();
22095 }
22096
22097 case value_t::string:
22098 case value_t::boolean:
22099 case value_t::number_integer:
22100 case value_t::number_unsigned:
22101 case value_t::number_float:
22102 case value_t::binary:
22103 case value_t::discarded:
22104 default:
22105 {
22106 // all other types are nonempty
22107 return false;
22108 }
22109 }
22110 }
22111
22112 /// @brief returns the number of elements
22113 /// @sa https://json.nlohmann.me/api/basic_json/size/
22114 size_type size() const noexcept
22115 {
22116 switch (m_type)
22117 {
22118 case value_t::null:
22119 {
22120 // null values are empty
22121 return 0;
22122 }
22123
22124 case value_t::array:
22125 {
22126 // delegate call to array_t::size()
22127 return m_value.array->size();
22128 }
22129
22130 case value_t::object:
22131 {
22132 // delegate call to object_t::size()
22133 return m_value.object->size();
22134 }
22135
22136 case value_t::string:
22137 case value_t::boolean:
22138 case value_t::number_integer:
22139 case value_t::number_unsigned:
22140 case value_t::number_float:
22141 case value_t::binary:
22142 case value_t::discarded:
22143 default:
22144 {
22145 // all other types have size 1
22146 return 1;
22147 }
22148 }
22149 }
22150
22151 /// @brief returns the maximum possible number of elements
22152 /// @sa https://json.nlohmann.me/api/basic_json/max_size/
22153 size_type max_size() const noexcept
22154 {
22155 switch (m_type)
22156 {
22157 case value_t::array:
22158 {
22159 // delegate call to array_t::max_size()
22160 return m_value.array->max_size();
22161 }
22162
22163 case value_t::object:
22164 {
22165 // delegate call to object_t::max_size()
22166 return m_value.object->max_size();
22167 }
22168
22169 case value_t::null:
22170 case value_t::string:
22171 case value_t::boolean:
22172 case value_t::number_integer:
22173 case value_t::number_unsigned:
22174 case value_t::number_float:
22175 case value_t::binary:
22176 case value_t::discarded:
22177 default:
22178 {
22179 // all other types have max_size() == size()
22180 return size();
22181 }
22182 }
22183 }
22184
22185 /// @}
22186
22187
22188 ///////////////
22189 // modifiers //
22190 ///////////////
22191
22192 /// @name modifiers
22193 /// @{
22194
22195 /// @brief clears the contents
22196 /// @sa https://json.nlohmann.me/api/basic_json/clear/
22197 void clear() noexcept
22198 {
22199 switch (m_type)
22200 {
22201 case value_t::number_integer:
22202 {
22203 m_value.number_integer = 0;
22204 break;
22205 }
22206
22207 case value_t::number_unsigned:
22208 {
22209 m_value.number_unsigned = 0;
22210 break;
22211 }
22212
22213 case value_t::number_float:
22214 {
22215 m_value.number_float = 0.0;
22216 break;
22217 }
22218
22219 case value_t::boolean:
22220 {
22221 m_value.boolean = false;
22222 break;
22223 }
22224
22225 case value_t::string:
22226 {
22227 m_value.string->clear();
22228 break;
22229 }
22230
22231 case value_t::binary:
22232 {
22233 m_value.binary->clear();
22234 break;
22235 }
22236
22237 case value_t::array:
22238 {
22239 m_value.array->clear();
22240 break;
22241 }
22242
22243 case value_t::object:
22244 {
22245 m_value.object->clear();
22246 break;
22247 }
22248
22249 case value_t::null:
22250 case value_t::discarded:
22251 default:
22252 break;
22253 }
22254 }
22255
22256 /// @brief add an object to an array
22257 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
22258 void push_back(basic_json&& val)
22259 {
22260 // push_back only works for null objects or arrays
22261 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22262 {
22263 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22264 }
22265
22266 // transform null object into an array
22267 if (is_null())
22268 {
22269 m_type = value_t::array;
22270 m_value = value_t::array;
22271 assert_invariant();
22272 }
22273
22274 // add element to array (move semantics)
22275 const auto old_capacity = m_value.array->capacity();
22276 m_value.array->push_back(std::move(val));
22277 set_parent(m_value.array->back(), old_capacity);
22278 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
22279 }
22280
22281 /// @brief add an object to an array
22282 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
22283 reference operator+=(basic_json&& val)
22284 {
22285 push_back(std::move(val));
22286 return *this;
22287 }
22288
22289 /// @brief add an object to an array
22290 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
22291 void push_back(const basic_json& val)
22292 {
22293 // push_back only works for null objects or arrays
22294 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22295 {
22296 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22297 }
22298
22299 // transform null object into an array
22300 if (is_null())
22301 {
22302 m_type = value_t::array;
22303 m_value = value_t::array;
22304 assert_invariant();
22305 }
22306
22307 // add element to array
22308 const auto old_capacity = m_value.array->capacity();
22309 m_value.array->push_back(val);
22310 set_parent(m_value.array->back(), old_capacity);
22311 }
22312
22313 /// @brief add an object to an array
22314 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
22315 reference operator+=(const basic_json& val)
22316 {
22317 push_back(val);
22318 return *this;
22319 }
22320
22321 /// @brief add an object to an object
22322 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
22323 void push_back(const typename object_t::value_type& val)
22324 {
22325 // push_back only works for null objects or objects
22326 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22327 {
22328 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22329 }
22330
22331 // transform null object into an object
22332 if (is_null())
22333 {
22334 m_type = value_t::object;
22335 m_value = value_t::object;
22336 assert_invariant();
22337 }
22338
22339 // add element to object
22340 auto res = m_value.object->insert(val);
22341 set_parent(res.first->second);
22342 }
22343
22344 /// @brief add an object to an object
22345 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
22346 reference operator+=(const typename object_t::value_type& val)
22347 {
22348 push_back(val);
22349 return *this;
22350 }
22351
22352 /// @brief add an object to an object
22353 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
22354 void push_back(initializer_list_t init)
22355 {
22356 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
22357 {
22358 basic_json&& key = init.begin()->moved_or_copied();
22359 push_back(typename object_t::value_type(
22360 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
22361 }
22362 else
22363 {
22364 push_back(basic_json(init));
22365 }
22366 }
22367
22368 /// @brief add an object to an object
22369 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
22370 reference operator+=(initializer_list_t init)
22371 {
22372 push_back(init);
22373 return *this;
22374 }
22375
22376 /// @brief add an object to an array
22377 /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/
22378 template<class... Args>
22379 reference emplace_back(Args&& ... args)
22380 {
22381 // emplace_back only works for null objects or arrays
22382 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22383 {
22384 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
22385 }
22386
22387 // transform null object into an array
22388 if (is_null())
22389 {
22390 m_type = value_t::array;
22391 m_value = value_t::array;
22392 assert_invariant();
22393 }
22394
22395 // add element to array (perfect forwarding)
22396 const auto old_capacity = m_value.array->capacity();
22397 m_value.array->emplace_back(std::forward<Args>(args)...);
22398 return set_parent(m_value.array->back(), old_capacity);
22399 }
22400
22401 /// @brief add an object to an object if key does not exist
22402 /// @sa https://json.nlohmann.me/api/basic_json/emplace/
22403 template<class... Args>
22404 std::pair<iterator, bool> emplace(Args&& ... args)
22405 {
22406 // emplace only works for null objects or arrays
22407 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22408 {
22409 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
22410 }
22411
22412 // transform null object into an object
22413 if (is_null())
22414 {
22415 m_type = value_t::object;
22416 m_value = value_t::object;
22417 assert_invariant();
22418 }
22419
22420 // add element to array (perfect forwarding)
22421 auto res = m_value.object->emplace(std::forward<Args>(args)...);
22422 set_parent(res.first->second);
22423
22424 // create result iterator and set iterator to the result of emplace
22425 auto it = begin();
22426 it.m_it.object_iterator = res.first;
22427
22428 // return pair of iterator and boolean
22429 return {it, res.second};
22430 }
22431
22432 /// Helper for insertion of an iterator
22433 /// @note: This uses std::distance to support GCC 4.8,
22434 /// see https://github.com/nlohmann/json/pull/1257
22435 template<typename... Args>
22436 iterator insert_iterator(const_iterator pos, Args&& ... args)
22437 {
22438 iterator result(this);
22439 JSON_ASSERT(m_value.array != nullptr);
22440
22441 auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
22442 m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
22443 result.m_it.array_iterator = m_value.array->begin() + insert_pos;
22444
22445 // This could have been written as:
22446 // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
22447 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
22448
22449 set_parents();
22450 return result;
22451 }
22452
22453 /// @brief inserts element into array
22454 /// @sa https://json.nlohmann.me/api/basic_json/insert/
22455 iterator insert(const_iterator pos, const basic_json& val)
22456 {
22457 // insert only works for arrays
22458 if (JSON_HEDLEY_LIKELY(is_array()))
22459 {
22460 // check if iterator pos fits to this JSON value
22461 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22462 {
22463 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22464 }
22465
22466 // insert to array and return iterator
22467 return insert_iterator(pos, val);
22468 }
22469
22470 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22471 }
22472
22473 /// @brief inserts element into array
22474 /// @sa https://json.nlohmann.me/api/basic_json/insert/
22475 iterator insert(const_iterator pos, basic_json&& val)
22476 {
22477 return insert(pos, val);
22478 }
22479
22480 /// @brief inserts copies of element into array
22481 /// @sa https://json.nlohmann.me/api/basic_json/insert/
22482 iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
22483 {
22484 // insert only works for arrays
22485 if (JSON_HEDLEY_LIKELY(is_array()))
22486 {
22487 // check if iterator pos fits to this JSON value
22488 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22489 {
22490 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22491 }
22492
22493 // insert to array and return iterator
22494 return insert_iterator(pos, cnt, val);
22495 }
22496
22497 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22498 }
22499
22500 /// @brief inserts range of elements into array
22501 /// @sa https://json.nlohmann.me/api/basic_json/insert/
22502 iterator insert(const_iterator pos, const_iterator first, const_iterator last)
22503 {
22504 // insert only works for arrays
22505 if (JSON_HEDLEY_UNLIKELY(!is_array()))
22506 {
22507 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22508 }
22509
22510 // check if iterator pos fits to this JSON value
22511 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22512 {
22513 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22514 }
22515
22516 // check if range iterators belong to the same JSON object
22517 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22518 {
22519 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22520 }
22521
22522 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
22523 {
22524 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
22525 }
22526
22527 // insert to array and return iterator
22528 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
22529 }
22530
22531 /// @brief inserts elements from initializer list into array
22532 /// @sa https://json.nlohmann.me/api/basic_json/insert/
22533 iterator insert(const_iterator pos, initializer_list_t ilist)
22534 {
22535 // insert only works for arrays
22536 if (JSON_HEDLEY_UNLIKELY(!is_array()))
22537 {
22538 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22539 }
22540
22541 // check if iterator pos fits to this JSON value
22542 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22543 {
22544 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22545 }
22546
22547 // insert to array and return iterator
22548 return insert_iterator(pos, ilist.begin(), ilist.end());
22549 }
22550
22551 /// @brief inserts range of elements into object
22552 /// @sa https://json.nlohmann.me/api/basic_json/insert/
22553 void insert(const_iterator first, const_iterator last)
22554 {
22555 // insert only works for objects
22556 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22557 {
22558 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22559 }
22560
22561 // check if range iterators belong to the same JSON object
22562 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22563 {
22564 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22565 }
22566
22567 // passed iterators must belong to objects
22568 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22569 {
22570 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
22571 }
22572
22573 m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
22574 }
22575
22576 /// @brief updates a JSON object from another object, overwriting existing keys
22577 /// @sa https://json.nlohmann.me/api/basic_json/update/
22578 void update(const_reference j, bool merge_objects = false)
22579 {
22580 update(j.begin(), j.end(), merge_objects);
22581 }
22582
22583 /// @brief updates a JSON object from another object, overwriting existing keys
22584 /// @sa https://json.nlohmann.me/api/basic_json/update/
22585 void update(const_iterator first, const_iterator last, bool merge_objects = false)
22586 {
22587 // implicitly convert null value to an empty object
22588 if (is_null())
22589 {
22590 m_type = value_t::object;
22591 m_value.object = create<object_t>();
22592 assert_invariant();
22593 }
22594
22595 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22596 {
22597 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
22598 }
22599
22600 // check if range iterators belong to the same JSON object
22601 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22602 {
22603 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22604 }
22605
22606 // passed iterators must belong to objects
22607 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22608 {
22609 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
22610 }
22611
22612 for (auto it = first; it != last; ++it)
22613 {
22614 if (merge_objects && it.value().is_object())
22615 {
22616 auto it2 = m_value.object->find(it.key());
22617 if (it2 != m_value.object->end())
22618 {
22619 it2->second.update(it.value(), true);
22620 continue;
22621 }
22622 }
22623 m_value.object->operator[](it.key()) = it.value();
22624#if JSON_DIAGNOSTICS
22625 m_value.object->operator[](it.key()).m_parent = this;
22626#endif
22627 }
22628 }
22629
22630 /// @brief exchanges the values
22631 /// @sa https://json.nlohmann.me/api/basic_json/swap/
22632 void swap(reference other) noexcept (
22633 std::is_nothrow_move_constructible<value_t>::value&&
22634 std::is_nothrow_move_assignable<value_t>::value&&
22635 std::is_nothrow_move_constructible<json_value>::value&&
22636 std::is_nothrow_move_assignable<json_value>::value
22637 )
22638 {
22639 std::swap(m_type, other.m_type);
22640 std::swap(m_value, other.m_value);
22641
22642 set_parents();
22643 other.set_parents();
22644 assert_invariant();
22645 }
22646
22647 /// @brief exchanges the values
22648 /// @sa https://json.nlohmann.me/api/basic_json/swap/
22649 friend void swap(reference left, reference right) noexcept (
22650 std::is_nothrow_move_constructible<value_t>::value&&
22651 std::is_nothrow_move_assignable<value_t>::value&&
22652 std::is_nothrow_move_constructible<json_value>::value&&
22653 std::is_nothrow_move_assignable<json_value>::value
22654 )
22655 {
22656 left.swap(right);
22657 }
22658
22659 /// @brief exchanges the values
22660 /// @sa https://json.nlohmann.me/api/basic_json/swap/
22661 void swap(array_t& other) // NOLINT(bugprone-exception-escape)
22662 {
22663 // swap only works for arrays
22664 if (JSON_HEDLEY_LIKELY(is_array()))
22665 {
22666 using std::swap;
22667 swap(*(m_value.array), other);
22668 }
22669 else
22670 {
22671 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
22672 }
22673 }
22674
22675 /// @brief exchanges the values
22676 /// @sa https://json.nlohmann.me/api/basic_json/swap/
22677 void swap(object_t& other) // NOLINT(bugprone-exception-escape)
22678 {
22679 // swap only works for objects
22680 if (JSON_HEDLEY_LIKELY(is_object()))
22681 {
22682 using std::swap;
22683 swap(*(m_value.object), other);
22684 }
22685 else
22686 {
22687 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
22688 }
22689 }
22690
22691 /// @brief exchanges the values
22692 /// @sa https://json.nlohmann.me/api/basic_json/swap/
22693 void swap(string_t& other) // NOLINT(bugprone-exception-escape)
22694 {
22695 // swap only works for strings
22696 if (JSON_HEDLEY_LIKELY(is_string()))
22697 {
22698 using std::swap;
22699 swap(*(m_value.string), other);
22700 }
22701 else
22702 {
22703 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
22704 }
22705 }
22706
22707 /// @brief exchanges the values
22708 /// @sa https://json.nlohmann.me/api/basic_json/swap/
22709 void swap(binary_t& other) // NOLINT(bugprone-exception-escape)
22710 {
22711 // swap only works for strings
22712 if (JSON_HEDLEY_LIKELY(is_binary()))
22713 {
22714 using std::swap;
22715 swap(*(m_value.binary), other);
22716 }
22717 else
22718 {
22719 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
22720 }
22721 }
22722
22723 /// @brief exchanges the values
22724 /// @sa https://json.nlohmann.me/api/basic_json/swap/
22725 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
22726 {
22727 // swap only works for strings
22728 if (JSON_HEDLEY_LIKELY(is_binary()))
22729 {
22730 using std::swap;
22731 swap(*(m_value.binary), other);
22732 }
22733 else
22734 {
22735 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
22736 }
22737 }
22738
22739 /// @}
22740
22741 //////////////////////////////////////////
22742 // lexicographical comparison operators //
22743 //////////////////////////////////////////
22744
22745 /// @name lexicographical comparison operators
22746 /// @{
22747
22748 // note parentheses around operands are necessary; see
22749 // https://github.com/nlohmann/json/issues/1530
22750#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
22751 const auto lhs_type = lhs.type(); \
22752 const auto rhs_type = rhs.type(); \
22753 \
22754 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
22755 { \
22756 switch (lhs_type) \
22757 { \
22758 case value_t::array: \
22759 return (*lhs.m_value.array) op (*rhs.m_value.array); \
22760 \
22761 case value_t::object: \
22762 return (*lhs.m_value.object) op (*rhs.m_value.object); \
22763 \
22764 case value_t::null: \
22765 return (null_result); \
22766 \
22767 case value_t::string: \
22768 return (*lhs.m_value.string) op (*rhs.m_value.string); \
22769 \
22770 case value_t::boolean: \
22771 return (lhs.m_value.boolean) op (rhs.m_value.boolean); \
22772 \
22773 case value_t::number_integer: \
22774 return (lhs.m_value.number_integer) op (rhs.m_value.number_integer); \
22775 \
22776 case value_t::number_unsigned: \
22777 return (lhs.m_value.number_unsigned) op (rhs.m_value.number_unsigned); \
22778 \
22779 case value_t::number_float: \
22780 return (lhs.m_value.number_float) op (rhs.m_value.number_float); \
22781 \
22782 case value_t::binary: \
22783 return (*lhs.m_value.binary) op (*rhs.m_value.binary); \
22784 \
22785 case value_t::discarded: \
22786 default: \
22787 return (unordered_result); \
22788 } \
22789 } \
22790 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
22791 { \
22792 return static_cast<number_float_t>(lhs.m_value.number_integer) op rhs.m_value.number_float; \
22793 } \
22794 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
22795 { \
22796 return lhs.m_value.number_float op static_cast<number_float_t>(rhs.m_value.number_integer); \
22797 } \
22798 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
22799 { \
22800 return static_cast<number_float_t>(lhs.m_value.number_unsigned) op rhs.m_value.number_float; \
22801 } \
22802 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
22803 { \
22804 return lhs.m_value.number_float op static_cast<number_float_t>(rhs.m_value.number_unsigned); \
22805 } \
22806 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
22807 { \
22808 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) op rhs.m_value.number_integer; \
22809 } \
22810 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
22811 { \
22812 return lhs.m_value.number_integer op static_cast<number_integer_t>(rhs.m_value.number_unsigned); \
22813 } \
22814 else if(compares_unordered(lhs, rhs))\
22815 {\
22816 return (unordered_result);\
22817 }\
22818 \
22819 return (default_result);
22820
22821 JSON_PRIVATE_UNLESS_TESTED:
22822 // returns true if:
22823 // - any operand is NaN and the other operand is of number type
22824 // - any operand is discarded
22825 // in legacy mode, discarded values are considered ordered if
22826 // an operation is computed as an odd number of inverses of others
22827 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
22828 {
22829 if ((lhs.is_number_float() && std::isnan(lhs.m_value.number_float) && rhs.is_number())
22830 || (rhs.is_number_float() && std::isnan(rhs.m_value.number_float) && lhs.is_number()))
22831 {
22832 return true;
22833 }
22834#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
22835 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
22836#else
22837 static_cast<void>(inverse);
22838 return lhs.is_discarded() || rhs.is_discarded();
22839#endif
22840 }
22841
22842 private:
22843 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
22844 {
22845 return compares_unordered(*this, rhs, inverse);
22846 }
22847
22848 public:
22849#if JSON_HAS_THREE_WAY_COMPARISON
22850 /// @brief comparison: equal
22851 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
22852 bool operator==(const_reference rhs) const noexcept
22853 {
22854#ifdef __GNUC__
22855#pragma GCC diagnostic push
22856#pragma GCC diagnostic ignored "-Wfloat-equal"
22857#endif
22858 const_reference lhs = *this;
22859 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
22860#ifdef __GNUC__
22861#pragma GCC diagnostic pop
22862#endif
22863 }
22864
22865 /// @brief comparison: equal
22866 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
22867 template<typename ScalarType>
22868 requires std::is_scalar_v<ScalarType>
22869 bool operator==(ScalarType rhs) const noexcept
22870 {
22871 return *this == basic_json(rhs);
22872 }
22873
22874 /// @brief comparison: not equal
22875 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
22876 bool operator!=(const_reference rhs) const noexcept
22877 {
22878 if (compares_unordered(rhs, true))
22879 {
22880 return false;
22881 }
22882 return !operator==(rhs);
22883 }
22884
22885 /// @brief comparison: 3-way
22886 /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
22887 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
22888 {
22889 const_reference lhs = *this;
22890 // default_result is used if we cannot compare values. In that case,
22891 // we compare types.
22892 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
22893 std::partial_ordering::equivalent,
22894 std::partial_ordering::unordered,
22895 lhs_type <=> rhs_type) // *NOPAD*
22896 }
22897
22898 /// @brief comparison: 3-way
22899 /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
22900 template<typename ScalarType>
22901 requires std::is_scalar_v<ScalarType>
22902 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
22903 {
22904 return *this <=> basic_json(rhs); // *NOPAD*
22905 }
22906
22907#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
22908 // all operators that are computed as an odd number of inverses of others
22909 // need to be overloaded to emulate the legacy comparison behavior
22910
22911 /// @brief comparison: less than or equal
22912 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
22913 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
22914 bool operator<=(const_reference rhs) const noexcept
22915 {
22916 if (compares_unordered(rhs, true))
22917 {
22918 return false;
22919 }
22920 return !(rhs < *this);
22921 }
22922
22923 /// @brief comparison: less than or equal
22924 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
22925 template<typename ScalarType>
22926 requires std::is_scalar_v<ScalarType>
22927 bool operator<=(ScalarType rhs) const noexcept
22928 {
22929 return *this <= basic_json(rhs);
22930 }
22931
22932 /// @brief comparison: greater than or equal
22933 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
22934 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
22935 bool operator>=(const_reference rhs) const noexcept
22936 {
22937 if (compares_unordered(rhs, true))
22938 {
22939 return false;
22940 }
22941 return !(*this < rhs);
22942 }
22943
22944 /// @brief comparison: greater than or equal
22945 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
22946 template<typename ScalarType>
22947 requires std::is_scalar_v<ScalarType>
22948 bool operator>=(ScalarType rhs) const noexcept
22949 {
22950 return *this >= basic_json(rhs);
22951 }
22952#endif
22953#else
22954 /// @brief comparison: equal
22955 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
22956 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
22957 {
22958#ifdef __GNUC__
22959#pragma GCC diagnostic push
22960#pragma GCC diagnostic ignored "-Wfloat-equal"
22961#endif
22962 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
22963#ifdef __GNUC__
22964#pragma GCC diagnostic pop
22965#endif
22966 }
22967
22968 /// @brief comparison: equal
22969 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
22970 template<typename ScalarType, typename std::enable_if<
22971 std::is_scalar<ScalarType>::value, int>::type = 0>
22972 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
22973 {
22974 return lhs == basic_json(rhs);
22975 }
22976
22977 /// @brief comparison: equal
22978 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
22979 template<typename ScalarType, typename std::enable_if<
22980 std::is_scalar<ScalarType>::value, int>::type = 0>
22981 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
22982 {
22983 return basic_json(lhs) == rhs;
22984 }
22985
22986 /// @brief comparison: not equal
22987 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
22988 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
22989 {
22990 if (compares_unordered(lhs, rhs, true))
22991 {
22992 return false;
22993 }
22994 return !(lhs == rhs);
22995 }
22996
22997 /// @brief comparison: not equal
22998 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
22999 template<typename ScalarType, typename std::enable_if<
23000 std::is_scalar<ScalarType>::value, int>::type = 0>
23001 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
23002 {
23003 return lhs != basic_json(rhs);
23004 }
23005
23006 /// @brief comparison: not equal
23007 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23008 template<typename ScalarType, typename std::enable_if<
23009 std::is_scalar<ScalarType>::value, int>::type = 0>
23010 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
23011 {
23012 return basic_json(lhs) != rhs;
23013 }
23014
23015 /// @brief comparison: less than
23016 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
23017 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
23018 {
23019 // default_result is used if we cannot compare values. In that case,
23020 // we compare types. Note we have to call the operator explicitly,
23021 // because MSVC has problems otherwise.
23022 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
23023 }
23024
23025 /// @brief comparison: less than
23026 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
23027 template<typename ScalarType, typename std::enable_if<
23028 std::is_scalar<ScalarType>::value, int>::type = 0>
23029 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
23030 {
23031 return lhs < basic_json(rhs);
23032 }
23033
23034 /// @brief comparison: less than
23035 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
23036 template<typename ScalarType, typename std::enable_if<
23037 std::is_scalar<ScalarType>::value, int>::type = 0>
23038 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
23039 {
23040 return basic_json(lhs) < rhs;
23041 }
23042
23043 /// @brief comparison: less than or equal
23044 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23045 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
23046 {
23047 if (compares_unordered(lhs, rhs, true))
23048 {
23049 return false;
23050 }
23051 return !(rhs < lhs);
23052 }
23053
23054 /// @brief comparison: less than or equal
23055 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23056 template<typename ScalarType, typename std::enable_if<
23057 std::is_scalar<ScalarType>::value, int>::type = 0>
23058 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
23059 {
23060 return lhs <= basic_json(rhs);
23061 }
23062
23063 /// @brief comparison: less than or equal
23064 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23065 template<typename ScalarType, typename std::enable_if<
23066 std::is_scalar<ScalarType>::value, int>::type = 0>
23067 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
23068 {
23069 return basic_json(lhs) <= rhs;
23070 }
23071
23072 /// @brief comparison: greater than
23073 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
23074 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
23075 {
23076 // double inverse
23077 if (compares_unordered(lhs, rhs))
23078 {
23079 return false;
23080 }
23081 return !(lhs <= rhs);
23082 }
23083
23084 /// @brief comparison: greater than
23085 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
23086 template<typename ScalarType, typename std::enable_if<
23087 std::is_scalar<ScalarType>::value, int>::type = 0>
23088 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
23089 {
23090 return lhs > basic_json(rhs);
23091 }
23092
23093 /// @brief comparison: greater than
23094 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
23095 template<typename ScalarType, typename std::enable_if<
23096 std::is_scalar<ScalarType>::value, int>::type = 0>
23097 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
23098 {
23099 return basic_json(lhs) > rhs;
23100 }
23101
23102 /// @brief comparison: greater than or equal
23103 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23104 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
23105 {
23106 if (compares_unordered(lhs, rhs, true))
23107 {
23108 return false;
23109 }
23110 return !(lhs < rhs);
23111 }
23112
23113 /// @brief comparison: greater than or equal
23114 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23115 template<typename ScalarType, typename std::enable_if<
23116 std::is_scalar<ScalarType>::value, int>::type = 0>
23117 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
23118 {
23119 return lhs >= basic_json(rhs);
23120 }
23121
23122 /// @brief comparison: greater than or equal
23123 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23124 template<typename ScalarType, typename std::enable_if<
23125 std::is_scalar<ScalarType>::value, int>::type = 0>
23126 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
23127 {
23128 return basic_json(lhs) >= rhs;
23129 }
23130#endif
23131
23132#undef JSON_IMPLEMENT_OPERATOR
23133
23134 /// @}
23135
23136 ///////////////////
23137 // serialization //
23138 ///////////////////
23139
23140 /// @name serialization
23141 /// @{
23142#ifndef JSON_NO_IO
23143 /// @brief serialize to stream
23144 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
23145 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
23146 {
23147 // read width member and use it as indentation parameter if nonzero
23148 const bool pretty_print = o.width() > 0;
23149 const auto indentation = pretty_print ? o.width() : 0;
23150
23151 // reset width to 0 for subsequent calls to this stream
23152 o.width(0);
23153
23154 // do the actual serialization
23155 serializer s(detail::output_adapter<char>(o), o.fill());
23156 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
23157 return o;
23158 }
23159
23160 /// @brief serialize to stream
23161 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
23162 /// @deprecated This function is deprecated since 3.0.0 and will be removed in
23163 /// version 4.0.0 of the library. Please use
23164 /// operator<<(std::ostream&, const basic_json&) instead; that is,
23165 /// replace calls like `j >> o;` with `o << j;`.
23166 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
23167 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
23168 {
23169 return o << j;
23170 }
23171#endif // JSON_NO_IO
23172 /// @}
23173
23174
23175 /////////////////////
23176 // deserialization //
23177 /////////////////////
23178
23179 /// @name deserialization
23180 /// @{
23181
23182 /// @brief deserialize from a compatible input
23183 /// @sa https://json.nlohmann.me/api/basic_json/parse/
23184 template<typename InputType>
23185 JSON_HEDLEY_WARN_UNUSED_RESULT
23186 static basic_json parse(InputType&& i,
23187 const parser_callback_t cb = nullptr,
23188 const bool allow_exceptions = true,
23189 const bool ignore_comments = false)
23190 {
23191 basic_json result;
23192 parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
23193 return result;
23194 }
23195
23196 /// @brief deserialize from a pair of character iterators
23197 /// @sa https://json.nlohmann.me/api/basic_json/parse/
23198 template<typename IteratorType>
23199 JSON_HEDLEY_WARN_UNUSED_RESULT
23200 static basic_json parse(IteratorType first,
23201 IteratorType last,
23202 const parser_callback_t cb = nullptr,
23203 const bool allow_exceptions = true,
23204 const bool ignore_comments = false)
23205 {
23206 basic_json result;
23207 parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
23208 return result;
23209 }
23210
23211 JSON_HEDLEY_WARN_UNUSED_RESULT
23212 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
23213 static basic_json parse(detail::span_input_adapter&& i,
23214 const parser_callback_t cb = nullptr,
23215 const bool allow_exceptions = true,
23216 const bool ignore_comments = false)
23217 {
23218 basic_json result;
23219 parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
23220 return result;
23221 }
23222
23223 /// @brief check if the input is valid JSON
23224 /// @sa https://json.nlohmann.me/api/basic_json/accept/
23225 template<typename InputType>
23226 static bool accept(InputType&& i,
23227 const bool ignore_comments = false)
23228 {
23229 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
23230 }
23231
23232 /// @brief check if the input is valid JSON
23233 /// @sa https://json.nlohmann.me/api/basic_json/accept/
23234 template<typename IteratorType>
23235 static bool accept(IteratorType first, IteratorType last,
23236 const bool ignore_comments = false)
23237 {
23238 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
23239 }
23240
23241 JSON_HEDLEY_WARN_UNUSED_RESULT
23242 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
23243 static bool accept(detail::span_input_adapter&& i,
23244 const bool ignore_comments = false)
23245 {
23246 return parser(i.get(), nullptr, false, ignore_comments).accept(true);
23247 }
23248
23249 /// @brief generate SAX events
23250 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
23251 template <typename InputType, typename SAX>
23252 JSON_HEDLEY_NON_NULL(2)
23253 static bool sax_parse(InputType&& i, SAX* sax,
23254 input_format_t format = input_format_t::json,
23255 const bool strict = true,
23256 const bool ignore_comments = false)
23257 {
23258 auto ia = detail::input_adapter(std::forward<InputType>(i));
23259 return format == input_format_t::json
23260 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23261 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23262 }
23263
23264 /// @brief generate SAX events
23265 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
23266 template<class IteratorType, class SAX>
23267 JSON_HEDLEY_NON_NULL(3)
23268 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
23269 input_format_t format = input_format_t::json,
23270 const bool strict = true,
23271 const bool ignore_comments = false)
23272 {
23273 auto ia = detail::input_adapter(std::move(first), std::move(last));
23274 return format == input_format_t::json
23275 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23276 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23277 }
23278
23279 /// @brief generate SAX events
23280 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
23281 /// @deprecated This function is deprecated since 3.8.0 and will be removed in
23282 /// version 4.0.0 of the library. Please use
23283 /// sax_parse(ptr, ptr + len) instead.
23284 template <typename SAX>
23285 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
23286 JSON_HEDLEY_NON_NULL(2)
23287 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
23288 input_format_t format = input_format_t::json,
23289 const bool strict = true,
23290 const bool ignore_comments = false)
23291 {
23292 auto ia = i.get();
23293 return format == input_format_t::json
23294 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23295 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23296 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23297 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23298 }
23299#ifndef JSON_NO_IO
23300 /// @brief deserialize from stream
23301 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
23302 /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
23303 /// version 4.0.0 of the library. Please use
23304 /// operator>>(std::istream&, basic_json&) instead; that is,
23305 /// replace calls like `j << i;` with `i >> j;`.
23306 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
23307 friend std::istream& operator<<(basic_json& j, std::istream& i)
23308 {
23309 return operator>>(i, j);
23310 }
23311
23312 /// @brief deserialize from stream
23313 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
23314 friend std::istream& operator>>(std::istream& i, basic_json& j)
23315 {
23316 parser(detail::input_adapter(i)).parse(false, j);
23317 return i;
23318 }
23319#endif // JSON_NO_IO
23320 /// @}
23321
23322 ///////////////////////////
23323 // convenience functions //
23324 ///////////////////////////
23325
23326 /// @brief return the type as string
23327 /// @sa https://json.nlohmann.me/api/basic_json/type_name/
23328 JSON_HEDLEY_RETURNS_NON_NULL
23329 const char* type_name() const noexcept
23330 {
23331 switch (m_type)
23332 {
23333 case value_t::null:
23334 return "null";
23335 case value_t::object:
23336 return "object";
23337 case value_t::array:
23338 return "array";
23339 case value_t::string:
23340 return "string";
23341 case value_t::boolean:
23342 return "boolean";
23343 case value_t::binary:
23344 return "binary";
23345 case value_t::discarded:
23346 return "discarded";
23347 case value_t::number_integer:
23348 case value_t::number_unsigned:
23349 case value_t::number_float:
23350 default:
23351 return "number";
23352 }
23353 }
23354
23355
23356 JSON_PRIVATE_UNLESS_TESTED:
23357 //////////////////////
23358 // member variables //
23359 //////////////////////
23360
23361 /// the type of the current element
23362 value_t m_type = value_t::null;
23363
23364 /// the value of the current element
23365 json_value m_value = {};
23366
23367#if JSON_DIAGNOSTICS
23368 /// a pointer to a parent value (for debugging purposes)
23369 basic_json* m_parent = nullptr;
23370#endif
23371
23372 //////////////////////////////////////////
23373 // binary serialization/deserialization //
23374 //////////////////////////////////////////
23375
23376 /// @name binary serialization/deserialization support
23377 /// @{
23378
23379 public:
23380 /// @brief create a CBOR serialization of a given JSON value
23381 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
23382 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
23383 {
23384 std::vector<std::uint8_t> result;
23385 to_cbor(j, result);
23386 return result;
23387 }
23388
23389 /// @brief create a CBOR serialization of a given JSON value
23390 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
23391 static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
23392 {
23393 binary_writer<std::uint8_t>(o).write_cbor(j);
23394 }
23395
23396 /// @brief create a CBOR serialization of a given JSON value
23397 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
23398 static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
23399 {
23400 binary_writer<char>(o).write_cbor(j);
23401 }
23402
23403 /// @brief create a MessagePack serialization of a given JSON value
23404 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
23405 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
23406 {
23407 std::vector<std::uint8_t> result;
23408 to_msgpack(j, result);
23409 return result;
23410 }
23411
23412 /// @brief create a MessagePack serialization of a given JSON value
23413 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
23414 static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
23415 {
23416 binary_writer<std::uint8_t>(o).write_msgpack(j);
23417 }
23418
23419 /// @brief create a MessagePack serialization of a given JSON value
23420 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
23421 static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
23422 {
23423 binary_writer<char>(o).write_msgpack(j);
23424 }
23425
23426 /// @brief create a UBJSON serialization of a given JSON value
23427 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
23428 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
23429 const bool use_size = false,
23430 const bool use_type = false)
23431 {
23432 std::vector<std::uint8_t> result;
23433 to_ubjson(j, result, use_size, use_type);
23434 return result;
23435 }
23436
23437 /// @brief create a UBJSON serialization of a given JSON value
23438 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
23439 static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
23440 const bool use_size = false, const bool use_type = false)
23441 {
23442 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
23443 }
23444
23445 /// @brief create a UBJSON serialization of a given JSON value
23446 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
23447 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
23448 const bool use_size = false, const bool use_type = false)
23449 {
23450 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
23451 }
23452
23453 /// @brief create a BJData serialization of a given JSON value
23454 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
23455 static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
23456 const bool use_size = false,
23457 const bool use_type = false)
23458 {
23459 std::vector<std::uint8_t> result;
23460 to_bjdata(j, result, use_size, use_type);
23461 return result;
23462 }
23463
23464 /// @brief create a BJData serialization of a given JSON value
23465 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
23466 static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
23467 const bool use_size = false, const bool use_type = false)
23468 {
23469 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
23470 }
23471
23472 /// @brief create a BJData serialization of a given JSON value
23473 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
23474 static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
23475 const bool use_size = false, const bool use_type = false)
23476 {
23477 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
23478 }
23479
23480 /// @brief create a BSON serialization of a given JSON value
23481 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
23482 static std::vector<std::uint8_t> to_bson(const basic_json& j)
23483 {
23484 std::vector<std::uint8_t> result;
23485 to_bson(j, result);
23486 return result;
23487 }
23488
23489 /// @brief create a BSON serialization of a given JSON value
23490 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
23491 static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
23492 {
23493 binary_writer<std::uint8_t>(o).write_bson(j);
23494 }
23495
23496 /// @brief create a BSON serialization of a given JSON value
23497 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
23498 static void to_bson(const basic_json& j, detail::output_adapter<char> o)
23499 {
23500 binary_writer<char>(o).write_bson(j);
23501 }
23502
23503 /// @brief create a JSON value from an input in CBOR format
23504 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
23505 template<typename InputType>
23506 JSON_HEDLEY_WARN_UNUSED_RESULT
23507 static basic_json from_cbor(InputType&& i,
23508 const bool strict = true,
23509 const bool allow_exceptions = true,
23510 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23511 {
23512 basic_json result;
23513 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23514 auto ia = detail::input_adapter(std::forward<InputType>(i));
23515 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23516 return res ? result : basic_json(value_t::discarded);
23517 }
23518
23519 /// @brief create a JSON value from an input in CBOR format
23520 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
23521 template<typename IteratorType>
23522 JSON_HEDLEY_WARN_UNUSED_RESULT
23523 static basic_json from_cbor(IteratorType first, IteratorType last,
23524 const bool strict = true,
23525 const bool allow_exceptions = true,
23526 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23527 {
23528 basic_json result;
23529 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23530 auto ia = detail::input_adapter(std::move(first), std::move(last));
23531 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23532 return res ? result : basic_json(value_t::discarded);
23533 }
23534
23535 template<typename T>
23536 JSON_HEDLEY_WARN_UNUSED_RESULT
23537 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23538 static basic_json from_cbor(const T* ptr, std::size_t len,
23539 const bool strict = true,
23540 const bool allow_exceptions = true,
23541 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23542 {
23543 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
23544 }
23545
23546
23547 JSON_HEDLEY_WARN_UNUSED_RESULT
23548 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23549 static basic_json from_cbor(detail::span_input_adapter&& i,
23550 const bool strict = true,
23551 const bool allow_exceptions = true,
23552 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23553 {
23554 basic_json result;
23555 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23556 auto ia = i.get();
23557 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23558 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23559 return res ? result : basic_json(value_t::discarded);
23560 }
23561
23562 /// @brief create a JSON value from an input in MessagePack format
23563 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
23564 template<typename InputType>
23565 JSON_HEDLEY_WARN_UNUSED_RESULT
23566 static basic_json from_msgpack(InputType&& i,
23567 const bool strict = true,
23568 const bool allow_exceptions = true)
23569 {
23570 basic_json result;
23571 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23572 auto ia = detail::input_adapter(std::forward<InputType>(i));
23573 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23574 return res ? result : basic_json(value_t::discarded);
23575 }
23576
23577 /// @brief create a JSON value from an input in MessagePack format
23578 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
23579 template<typename IteratorType>
23580 JSON_HEDLEY_WARN_UNUSED_RESULT
23581 static basic_json from_msgpack(IteratorType first, IteratorType last,
23582 const bool strict = true,
23583 const bool allow_exceptions = true)
23584 {
23585 basic_json result;
23586 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23587 auto ia = detail::input_adapter(std::move(first), std::move(last));
23588 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23589 return res ? result : basic_json(value_t::discarded);
23590 }
23591
23592 template<typename T>
23593 JSON_HEDLEY_WARN_UNUSED_RESULT
23594 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23595 static basic_json from_msgpack(const T* ptr, std::size_t len,
23596 const bool strict = true,
23597 const bool allow_exceptions = true)
23598 {
23599 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
23600 }
23601
23602 JSON_HEDLEY_WARN_UNUSED_RESULT
23603 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23604 static basic_json from_msgpack(detail::span_input_adapter&& i,
23605 const bool strict = true,
23606 const bool allow_exceptions = true)
23607 {
23608 basic_json result;
23609 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23610 auto ia = i.get();
23611 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23612 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23613 return res ? result : basic_json(value_t::discarded);
23614 }
23615
23616 /// @brief create a JSON value from an input in UBJSON format
23617 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
23618 template<typename InputType>
23619 JSON_HEDLEY_WARN_UNUSED_RESULT
23620 static basic_json from_ubjson(InputType&& i,
23621 const bool strict = true,
23622 const bool allow_exceptions = true)
23623 {
23624 basic_json result;
23625 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23626 auto ia = detail::input_adapter(std::forward<InputType>(i));
23627 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23628 return res ? result : basic_json(value_t::discarded);
23629 }
23630
23631 /// @brief create a JSON value from an input in UBJSON format
23632 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
23633 template<typename IteratorType>
23634 JSON_HEDLEY_WARN_UNUSED_RESULT
23635 static basic_json from_ubjson(IteratorType first, IteratorType last,
23636 const bool strict = true,
23637 const bool allow_exceptions = true)
23638 {
23639 basic_json result;
23640 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23641 auto ia = detail::input_adapter(std::move(first), std::move(last));
23642 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23643 return res ? result : basic_json(value_t::discarded);
23644 }
23645
23646 template<typename T>
23647 JSON_HEDLEY_WARN_UNUSED_RESULT
23648 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23649 static basic_json from_ubjson(const T* ptr, std::size_t len,
23650 const bool strict = true,
23651 const bool allow_exceptions = true)
23652 {
23653 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
23654 }
23655
23656 JSON_HEDLEY_WARN_UNUSED_RESULT
23657 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23658 static basic_json from_ubjson(detail::span_input_adapter&& i,
23659 const bool strict = true,
23660 const bool allow_exceptions = true)
23661 {
23662 basic_json result;
23663 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23664 auto ia = i.get();
23665 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23666 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23667 return res ? result : basic_json(value_t::discarded);
23668 }
23669
23670
23671 /// @brief create a JSON value from an input in BJData format
23672 /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
23673 template<typename InputType>
23674 JSON_HEDLEY_WARN_UNUSED_RESULT
23675 static basic_json from_bjdata(InputType&& i,
23676 const bool strict = true,
23677 const bool allow_exceptions = true)
23678 {
23679 basic_json result;
23680 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23681 auto ia = detail::input_adapter(std::forward<InputType>(i));
23682 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23683 return res ? result : basic_json(value_t::discarded);
23684 }
23685
23686 /// @brief create a JSON value from an input in BJData format
23687 /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
23688 template<typename IteratorType>
23689 JSON_HEDLEY_WARN_UNUSED_RESULT
23690 static basic_json from_bjdata(IteratorType first, IteratorType last,
23691 const bool strict = true,
23692 const bool allow_exceptions = true)
23693 {
23694 basic_json result;
23695 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23696 auto ia = detail::input_adapter(std::move(first), std::move(last));
23697 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23698 return res ? result : basic_json(value_t::discarded);
23699 }
23700
23701 /// @brief create a JSON value from an input in BSON format
23702 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
23703 template<typename InputType>
23704 JSON_HEDLEY_WARN_UNUSED_RESULT
23705 static basic_json from_bson(InputType&& i,
23706 const bool strict = true,
23707 const bool allow_exceptions = true)
23708 {
23709 basic_json result;
23710 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23711 auto ia = detail::input_adapter(std::forward<InputType>(i));
23712 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23713 return res ? result : basic_json(value_t::discarded);
23714 }
23715
23716 /// @brief create a JSON value from an input in BSON format
23717 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
23718 template<typename IteratorType>
23719 JSON_HEDLEY_WARN_UNUSED_RESULT
23720 static basic_json from_bson(IteratorType first, IteratorType last,
23721 const bool strict = true,
23722 const bool allow_exceptions = true)
23723 {
23724 basic_json result;
23725 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23726 auto ia = detail::input_adapter(std::move(first), std::move(last));
23727 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23728 return res ? result : basic_json(value_t::discarded);
23729 }
23730
23731 template<typename T>
23732 JSON_HEDLEY_WARN_UNUSED_RESULT
23733 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23734 static basic_json from_bson(const T* ptr, std::size_t len,
23735 const bool strict = true,
23736 const bool allow_exceptions = true)
23737 {
23738 return from_bson(ptr, ptr + len, strict, allow_exceptions);
23739 }
23740
23741 JSON_HEDLEY_WARN_UNUSED_RESULT
23742 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23743 static basic_json from_bson(detail::span_input_adapter&& i,
23744 const bool strict = true,
23745 const bool allow_exceptions = true)
23746 {
23747 basic_json result;
23748 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23749 auto ia = i.get();
23750 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23751 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23752 return res ? result : basic_json(value_t::discarded);
23753 }
23754 /// @}
23755
23756 //////////////////////////
23757 // JSON Pointer support //
23758 //////////////////////////
23759
23760 /// @name JSON Pointer functions
23761 /// @{
23762
23763 /// @brief access specified element via JSON Pointer
23764 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
23765 reference operator[](const json_pointer& ptr)
23766 {
23767 return ptr.get_unchecked(this);
23768 }
23769
23770 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23771 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23772 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23773 {
23774 return ptr.get_unchecked(this);
23775 }
23776
23777 /// @brief access specified element via JSON Pointer
23778 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
23779 const_reference operator[](const json_pointer& ptr) const
23780 {
23781 return ptr.get_unchecked(this);
23782 }
23783
23784 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23785 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23786 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
23787 {
23788 return ptr.get_unchecked(this);
23789 }
23790
23791 /// @brief access specified element via JSON Pointer
23792 /// @sa https://json.nlohmann.me/api/basic_json/at/
23793 reference at(const json_pointer& ptr)
23794 {
23795 return ptr.get_checked(this);
23796 }
23797
23798 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23799 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23800 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23801 {
23802 return ptr.get_checked(this);
23803 }
23804
23805 /// @brief access specified element via JSON Pointer
23806 /// @sa https://json.nlohmann.me/api/basic_json/at/
23807 const_reference at(const json_pointer& ptr) const
23808 {
23809 return ptr.get_checked(this);
23810 }
23811
23812 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23813 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23814 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
23815 {
23816 return ptr.get_checked(this);
23817 }
23818
23819 /// @brief return flattened JSON value
23820 /// @sa https://json.nlohmann.me/api/basic_json/flatten/
23821 basic_json flatten() const
23822 {
23823 basic_json result(value_t::object);
23824 json_pointer::flatten("", *this, result);
23825 return result;
23826 }
23827
23828 /// @brief unflatten a previously flattened JSON value
23829 /// @sa https://json.nlohmann.me/api/basic_json/unflatten/
23830 basic_json unflatten() const
23831 {
23832 return json_pointer::unflatten(*this);
23833 }
23834
23835 /// @}
23836
23837 //////////////////////////
23838 // JSON Patch functions //
23839 //////////////////////////
23840
23841 /// @name JSON Patch functions
23842 /// @{
23843
23844 /// @brief applies a JSON patch in-place without copying the object
23845 /// @sa https://json.nlohmann.me/api/basic_json/patch/
23846 void patch_inplace(const basic_json& json_patch)
23847 {
23848 basic_json& result = *this;
23849 // the valid JSON Patch operations
23850 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
23851
23852 const auto get_op = [](const std::string & op)
23853 {
23854 if (op == "add")
23855 {
23856 return patch_operations::add;
23857 }
23858 if (op == "remove")
23859 {
23860 return patch_operations::remove;
23861 }
23862 if (op == "replace")
23863 {
23864 return patch_operations::replace;
23865 }
23866 if (op == "move")
23867 {
23868 return patch_operations::move;
23869 }
23870 if (op == "copy")
23871 {
23872 return patch_operations::copy;
23873 }
23874 if (op == "test")
23875 {
23876 return patch_operations::test;
23877 }
23878
23879 return patch_operations::invalid;
23880 };
23881
23882 // wrapper for "add" operation; add value at ptr
23883 const auto operation_add = [&result](json_pointer & ptr, basic_json val)
23884 {
23885 // adding to the root of the target document means replacing it
23886 if (ptr.empty())
23887 {
23888 result = val;
23889 return;
23890 }
23891
23892 // make sure the top element of the pointer exists
23893 json_pointer top_pointer = ptr.top();
23894 if (top_pointer != ptr)
23895 {
23896 result.at(top_pointer);
23897 }
23898
23899 // get reference to parent of JSON pointer ptr
23900 const auto last_path = ptr.back();
23901 ptr.pop_back();
23902 // parent must exist when performing patch add per RFC6902 specs
23903 basic_json& parent = result.at(ptr);
23904
23905 switch (parent.m_type)
23906 {
23907 case value_t::null:
23908 case value_t::object:
23909 {
23910 // use operator[] to add value
23911 parent[last_path] = val;
23912 break;
23913 }
23914
23915 case value_t::array:
23916 {
23917 if (last_path == "-")
23918 {
23919 // special case: append to back
23920 parent.push_back(val);
23921 }
23922 else
23923 {
23924 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
23925 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
23926 {
23927 // avoid undefined behavior
23928 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
23929 }
23930
23931 // default case: insert add offset
23932 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
23933 }
23934 break;
23935 }
23936
23937 // if there exists a parent it cannot be primitive
23938 case value_t::string: // LCOV_EXCL_LINE
23939 case value_t::boolean: // LCOV_EXCL_LINE
23940 case value_t::number_integer: // LCOV_EXCL_LINE
23941 case value_t::number_unsigned: // LCOV_EXCL_LINE
23942 case value_t::number_float: // LCOV_EXCL_LINE
23943 case value_t::binary: // LCOV_EXCL_LINE
23944 case value_t::discarded: // LCOV_EXCL_LINE
23945 default: // LCOV_EXCL_LINE
23946 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
23947 }
23948 };
23949
23950 // wrapper for "remove" operation; remove value at ptr
23951 const auto operation_remove = [this, &result](json_pointer & ptr)
23952 {
23953 // get reference to parent of JSON pointer ptr
23954 const auto last_path = ptr.back();
23955 ptr.pop_back();
23956 basic_json& parent = result.at(ptr);
23957
23958 // remove child
23959 if (parent.is_object())
23960 {
23961 // perform range check
23962 auto it = parent.find(last_path);
23963 if (JSON_HEDLEY_LIKELY(it != parent.end()))
23964 {
23965 parent.erase(it);
23966 }
23967 else
23968 {
23969 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
23970 }
23971 }
23972 else if (parent.is_array())
23973 {
23974 // note erase performs range check
23975 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
23976 }
23977 };
23978
23979 // type check: top level value must be an array
23980 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
23981 {
23982 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
23983 }
23984
23985 // iterate and apply the operations
23986 for (const auto& val : json_patch)
23987 {
23988 // wrapper to get a value for an operation
23989 const auto get_value = [&val](const std::string & op,
23990 const std::string & member,
23991 bool string_type) -> basic_json &
23992 {
23993 // find value
23994 auto it = val.m_value.object->find(member);
23995
23996 // context-sensitive error message
23997 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\'');
23998
23999 // check if desired value is present
24000 if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
24001 {
24002 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24003 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
24004 }
24005
24006 // check if result is of type string
24007 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
24008 {
24009 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24010 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
24011 }
24012
24013 // no error: return value
24014 return it->second;
24015 };
24016
24017 // type check: every element of the array must be an object
24018 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
24019 {
24020 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
24021 }
24022
24023 // collect mandatory members
24024 const auto op = get_value("op", "op", true).template get<std::string>();
24025 const auto path = get_value(op, "path", true).template get<std::string>();
24026 json_pointer ptr(path);
24027
24028 switch (get_op(op))
24029 {
24030 case patch_operations::add:
24031 {
24032 operation_add(ptr, get_value("add", "value", false));
24033 break;
24034 }
24035
24036 case patch_operations::remove:
24037 {
24038 operation_remove(ptr);
24039 break;
24040 }
24041
24042 case patch_operations::replace:
24043 {
24044 // the "path" location must exist - use at()
24045 result.at(ptr) = get_value("replace", "value", false);
24046 break;
24047 }
24048
24049 case patch_operations::move:
24050 {
24051 const auto from_path = get_value("move", "from", true).template get<std::string>();
24052 json_pointer from_ptr(from_path);
24053
24054 // the "from" location must exist - use at()
24055 basic_json v = result.at(from_ptr);
24056
24057 // The move operation is functionally identical to a
24058 // "remove" operation on the "from" location, followed
24059 // immediately by an "add" operation at the target
24060 // location with the value that was just removed.
24061 operation_remove(from_ptr);
24062 operation_add(ptr, v);
24063 break;
24064 }
24065
24066 case patch_operations::copy:
24067 {
24068 const auto from_path = get_value("copy", "from", true).template get<std::string>();
24069 const json_pointer from_ptr(from_path);
24070
24071 // the "from" location must exist - use at()
24072 basic_json v = result.at(from_ptr);
24073
24074 // The copy is functionally identical to an "add"
24075 // operation at the target location using the value
24076 // specified in the "from" member.
24077 operation_add(ptr, v);
24078 break;
24079 }
24080
24081 case patch_operations::test:
24082 {
24083 bool success = false;
24084 JSON_TRY
24085 {
24086 // check if "value" matches the one at "path"
24087 // the "path" location must exist - use at()
24088 success = (result.at(ptr) == get_value("test", "value", false));
24089 }
24090 JSON_INTERNAL_CATCH (out_of_range&)
24091 {
24092 // ignore out of range errors: success remains false
24093 }
24094
24095 // throw an exception if test fails
24096 if (JSON_HEDLEY_UNLIKELY(!success))
24097 {
24098 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
24099 }
24100
24101 break;
24102 }
24103
24104 case patch_operations::invalid:
24105 default:
24106 {
24107 // op must be "add", "remove", "replace", "move", "copy", or
24108 // "test"
24109 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
24110 }
24111 }
24112 }
24113 }
24114
24115 /// @brief applies a JSON patch to a copy of the current object
24116 /// @sa https://json.nlohmann.me/api/basic_json/patch/
24117 basic_json patch(const basic_json& json_patch) const
24118 {
24119 basic_json result = *this;
24120 result.patch_inplace(json_patch);
24121 return result;
24122 }
24123
24124 /// @brief creates a diff as a JSON patch
24125 /// @sa https://json.nlohmann.me/api/basic_json/diff/
24126 JSON_HEDLEY_WARN_UNUSED_RESULT
24127 static basic_json diff(const basic_json& source, const basic_json& target,
24128 const std::string& path = "")
24129 {
24130 // the patch
24131 basic_json result(value_t::array);
24132
24133 // if the values are the same, return empty patch
24134 if (source == target)
24135 {
24136 return result;
24137 }
24138
24139 if (source.type() != target.type())
24140 {
24141 // different types: replace value
24142 result.push_back(
24143 {
24144 {"op", "replace"}, {"path", path}, {"value", target}
24145 });
24146 return result;
24147 }
24148
24149 switch (source.type())
24150 {
24151 case value_t::array:
24152 {
24153 // first pass: traverse common elements
24154 std::size_t i = 0;
24155 while (i < source.size() && i < target.size())
24156 {
24157 // recursive call to compare array values at index i
24158 auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
24159 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24160 ++i;
24161 }
24162
24163 // We now reached the end of at least one array
24164 // in a second pass, traverse the remaining elements
24165
24166 // remove my remaining elements
24167 const auto end_index = static_cast<difference_type>(result.size());
24168 while (i < source.size())
24169 {
24170 // add operations in reverse order to avoid invalid
24171 // indices
24172 result.insert(result.begin() + end_index, object(
24173 {
24174 {"op", "remove"},
24175 {"path", detail::concat(path, '/', std::to_string(i))}
24176 }));
24177 ++i;
24178 }
24179
24180 // add other remaining elements
24181 while (i < target.size())
24182 {
24183 result.push_back(
24184 {
24185 {"op", "add"},
24186 {"path", detail::concat(path, "/-")},
24187 {"value", target[i]}
24188 });
24189 ++i;
24190 }
24191
24192 break;
24193 }
24194
24195 case value_t::object:
24196 {
24197 // first pass: traverse this object's elements
24198 for (auto it = source.cbegin(); it != source.cend(); ++it)
24199 {
24200 // escape the key name to be used in a JSON patch
24201 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24202
24203 if (target.find(it.key()) != target.end())
24204 {
24205 // recursive call to compare object values at key it
24206 auto temp_diff = diff(it.value(), target[it.key()], path_key);
24207 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24208 }
24209 else
24210 {
24211 // found a key that is not in o -> remove it
24212 result.push_back(object(
24213 {
24214 {"op", "remove"}, {"path", path_key}
24215 }));
24216 }
24217 }
24218
24219 // second pass: traverse other object's elements
24220 for (auto it = target.cbegin(); it != target.cend(); ++it)
24221 {
24222 if (source.find(it.key()) == source.end())
24223 {
24224 // found a key that is not in this -> add it
24225 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24226 result.push_back(
24227 {
24228 {"op", "add"}, {"path", path_key},
24229 {"value", it.value()}
24230 });
24231 }
24232 }
24233
24234 break;
24235 }
24236
24237 case value_t::null:
24238 case value_t::string:
24239 case value_t::boolean:
24240 case value_t::number_integer:
24241 case value_t::number_unsigned:
24242 case value_t::number_float:
24243 case value_t::binary:
24244 case value_t::discarded:
24245 default:
24246 {
24247 // both primitive type: replace value
24248 result.push_back(
24249 {
24250 {"op", "replace"}, {"path", path}, {"value", target}
24251 });
24252 break;
24253 }
24254 }
24255
24256 return result;
24257 }
24258 /// @}
24259
24260 ////////////////////////////////
24261 // JSON Merge Patch functions //
24262 ////////////////////////////////
24263
24264 /// @name JSON Merge Patch functions
24265 /// @{
24266
24267 /// @brief applies a JSON Merge Patch
24268 /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
24269 void merge_patch(const basic_json& apply_patch)
24270 {
24271 if (apply_patch.is_object())
24272 {
24273 if (!is_object())
24274 {
24275 *this = object();
24276 }
24277 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
24278 {
24279 if (it.value().is_null())
24280 {
24281 erase(it.key());
24282 }
24283 else
24284 {
24285 operator[](it.key()).merge_patch(it.value());
24286 }
24287 }
24288 }
24289 else
24290 {
24291 *this = apply_patch;
24292 }
24293 }
24294
24295 /// @}
24296};
24297
24298/// @brief user-defined to_string function for JSON values
24299/// @sa https://json.nlohmann.me/api/basic_json/to_string/
24300NLOHMANN_BASIC_JSON_TPL_DECLARATION
24301std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
24302{
24303 return j.dump();
24304}
24305
24306inline namespace literals
24307{
24308inline namespace json_literals
24309{
24310
24311/// @brief user-defined string literal for JSON values
24312/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
24313JSON_HEDLEY_NON_NULL(1)
24314inline nlohmann::json operator "" _json(const char* s, std::size_t n)
24315{
24316 return nlohmann::json::parse(s, s + n);
24317}
24318
24319/// @brief user-defined string literal for JSON pointer
24320/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
24321JSON_HEDLEY_NON_NULL(1)
24322inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
24323{
24324 return nlohmann::json::json_pointer(std::string(s, n));
24325}
24326
24327} // namespace json_literals
24328} // namespace literals
24329NLOHMANN_JSON_NAMESPACE_END
24330
24331///////////////////////
24332// nonmember support //
24333///////////////////////
24334
24335namespace std // NOLINT(cert-dcl58-cpp)
24336{
24337
24338/// @brief hash value for JSON objects
24339/// @sa https://json.nlohmann.me/api/basic_json/std_hash/
24340NLOHMANN_BASIC_JSON_TPL_DECLARATION
24341struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL>
24342{
24343 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
24344 {
24345 return nlohmann::detail::hash(j);
24346 }
24347};
24348
24349// specialization for std::less<value_t>
24350template<>
24351struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
24352{
24353 /*!
24354 @brief compare two value_t enum values
24355 @since version 3.0.0
24356 */
24357 bool operator()(::nlohmann::detail::value_t lhs,
24358 ::nlohmann::detail::value_t rhs) const noexcept
24359 {
24360#if JSON_HAS_THREE_WAY_COMPARISON
24361 return std::is_lt(lhs <=> rhs); // *NOPAD*
24362#else
24363 return ::nlohmann::detail::operator<(lhs, rhs);
24364#endif
24365 }
24366};
24367
24368// C++20 prohibit function specialization in the std namespace.
24369#ifndef JSON_HAS_CPP_20
24370
24371/// @brief exchanges the values of two JSON objects
24372/// @sa https://json.nlohmann.me/api/basic_json/std_swap/
24373NLOHMANN_BASIC_JSON_TPL_DECLARATION
24374inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name)
24375 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression)
24376 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
24377{
24378 j1.swap(j2);
24379}
24380
24381#endif
24382
24383} // namespace std
24384
24385#if JSON_USE_GLOBAL_UDLS
24386 using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24387 using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24388#endif
24389
24390// #include <nlohmann/detail/macro_unscope.hpp>
24391// __ _____ _____ _____
24392// __| | __| | | | JSON for Modern C++
24393// | | |__ | | | | | | version 3.11.2
24394// |_____|_____|_____|_|___| https://github.com/nlohmann/json
24395//
24396// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
24397// SPDX-License-Identifier: MIT
24398
24399
24400
24401// restore clang diagnostic settings
24402#if defined(__clang__)
24403 #pragma clang diagnostic pop
24404#endif
24405
24406// clean up
24407#undef JSON_ASSERT
24408#undef JSON_INTERNAL_CATCH
24409#undef JSON_THROW
24410#undef JSON_PRIVATE_UNLESS_TESTED
24411#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
24412#undef NLOHMANN_BASIC_JSON_TPL
24413#undef JSON_EXPLICIT
24414#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
24415#undef JSON_INLINE_VARIABLE
24416#undef JSON_NO_UNIQUE_ADDRESS
24417#undef JSON_DISABLE_ENUM_SERIALIZATION
24418#undef JSON_USE_GLOBAL_UDLS
24419
24420#ifndef JSON_TEST_KEEP_MACROS
24421 #undef JSON_CATCH
24422 #undef JSON_TRY
24423 #undef JSON_HAS_CPP_11
24424 #undef JSON_HAS_CPP_14
24425 #undef JSON_HAS_CPP_17
24426 #undef JSON_HAS_CPP_20
24427 #undef JSON_HAS_FILESYSTEM
24428 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
24429 #undef JSON_HAS_THREE_WAY_COMPARISON
24430 #undef JSON_HAS_RANGES
24431 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
24432#endif
24433
24434// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
24435// __ _____ _____ _____
24436// __| | __| | | | JSON for Modern C++
24437// | | |__ | | | | | | version 3.11.2
24438// |_____|_____|_____|_|___| https://github.com/nlohmann/json
24439//
24440// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
24441// SPDX-License-Identifier: MIT
24442
24443
24444
24445#undef JSON_HEDLEY_ALWAYS_INLINE
24446#undef JSON_HEDLEY_ARM_VERSION
24447#undef JSON_HEDLEY_ARM_VERSION_CHECK
24448#undef JSON_HEDLEY_ARRAY_PARAM
24449#undef JSON_HEDLEY_ASSUME
24450#undef JSON_HEDLEY_BEGIN_C_DECLS
24451#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
24452#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
24453#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
24454#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
24455#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
24456#undef JSON_HEDLEY_CLANG_HAS_FEATURE
24457#undef JSON_HEDLEY_CLANG_HAS_WARNING
24458#undef JSON_HEDLEY_COMPCERT_VERSION
24459#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
24460#undef JSON_HEDLEY_CONCAT
24461#undef JSON_HEDLEY_CONCAT3
24462#undef JSON_HEDLEY_CONCAT3_EX
24463#undef JSON_HEDLEY_CONCAT_EX
24464#undef JSON_HEDLEY_CONST
24465#undef JSON_HEDLEY_CONSTEXPR
24466#undef JSON_HEDLEY_CONST_CAST
24467#undef JSON_HEDLEY_CPP_CAST
24468#undef JSON_HEDLEY_CRAY_VERSION
24469#undef JSON_HEDLEY_CRAY_VERSION_CHECK
24470#undef JSON_HEDLEY_C_DECL
24471#undef JSON_HEDLEY_DEPRECATED
24472#undef JSON_HEDLEY_DEPRECATED_FOR
24473#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
24474#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
24475#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
24476#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
24477#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
24478#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
24479#undef JSON_HEDLEY_DIAGNOSTIC_POP
24480#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
24481#undef JSON_HEDLEY_DMC_VERSION
24482#undef JSON_HEDLEY_DMC_VERSION_CHECK
24483#undef JSON_HEDLEY_EMPTY_BASES
24484#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
24485#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
24486#undef JSON_HEDLEY_END_C_DECLS
24487#undef JSON_HEDLEY_FLAGS
24488#undef JSON_HEDLEY_FLAGS_CAST
24489#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
24490#undef JSON_HEDLEY_GCC_HAS_BUILTIN
24491#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
24492#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
24493#undef JSON_HEDLEY_GCC_HAS_EXTENSION
24494#undef JSON_HEDLEY_GCC_HAS_FEATURE
24495#undef JSON_HEDLEY_GCC_HAS_WARNING
24496#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
24497#undef JSON_HEDLEY_GCC_VERSION
24498#undef JSON_HEDLEY_GCC_VERSION_CHECK
24499#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
24500#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
24501#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
24502#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
24503#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
24504#undef JSON_HEDLEY_GNUC_HAS_FEATURE
24505#undef JSON_HEDLEY_GNUC_HAS_WARNING
24506#undef JSON_HEDLEY_GNUC_VERSION
24507#undef JSON_HEDLEY_GNUC_VERSION_CHECK
24508#undef JSON_HEDLEY_HAS_ATTRIBUTE
24509#undef JSON_HEDLEY_HAS_BUILTIN
24510#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
24511#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
24512#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
24513#undef JSON_HEDLEY_HAS_EXTENSION
24514#undef JSON_HEDLEY_HAS_FEATURE
24515#undef JSON_HEDLEY_HAS_WARNING
24516#undef JSON_HEDLEY_IAR_VERSION
24517#undef JSON_HEDLEY_IAR_VERSION_CHECK
24518#undef JSON_HEDLEY_IBM_VERSION
24519#undef JSON_HEDLEY_IBM_VERSION_CHECK
24520#undef JSON_HEDLEY_IMPORT
24521#undef JSON_HEDLEY_INLINE
24522#undef JSON_HEDLEY_INTEL_CL_VERSION
24523#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
24524#undef JSON_HEDLEY_INTEL_VERSION
24525#undef JSON_HEDLEY_INTEL_VERSION_CHECK
24526#undef JSON_HEDLEY_IS_CONSTANT
24527#undef JSON_HEDLEY_IS_CONSTEXPR_
24528#undef JSON_HEDLEY_LIKELY
24529#undef JSON_HEDLEY_MALLOC
24530#undef JSON_HEDLEY_MCST_LCC_VERSION
24531#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
24532#undef JSON_HEDLEY_MESSAGE
24533#undef JSON_HEDLEY_MSVC_VERSION
24534#undef JSON_HEDLEY_MSVC_VERSION_CHECK
24535#undef JSON_HEDLEY_NEVER_INLINE
24536#undef JSON_HEDLEY_NON_NULL
24537#undef JSON_HEDLEY_NO_ESCAPE
24538#undef JSON_HEDLEY_NO_RETURN
24539#undef JSON_HEDLEY_NO_THROW
24540#undef JSON_HEDLEY_NULL
24541#undef JSON_HEDLEY_PELLES_VERSION
24542#undef JSON_HEDLEY_PELLES_VERSION_CHECK
24543#undef JSON_HEDLEY_PGI_VERSION
24544#undef JSON_HEDLEY_PGI_VERSION_CHECK
24545#undef JSON_HEDLEY_PREDICT
24546#undef JSON_HEDLEY_PRINTF_FORMAT
24547#undef JSON_HEDLEY_PRIVATE
24548#undef JSON_HEDLEY_PUBLIC
24549#undef JSON_HEDLEY_PURE
24550#undef JSON_HEDLEY_REINTERPRET_CAST
24551#undef JSON_HEDLEY_REQUIRE
24552#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
24553#undef JSON_HEDLEY_REQUIRE_MSG
24554#undef JSON_HEDLEY_RESTRICT
24555#undef JSON_HEDLEY_RETURNS_NON_NULL
24556#undef JSON_HEDLEY_SENTINEL
24557#undef JSON_HEDLEY_STATIC_ASSERT
24558#undef JSON_HEDLEY_STATIC_CAST
24559#undef JSON_HEDLEY_STRINGIFY
24560#undef JSON_HEDLEY_STRINGIFY_EX
24561#undef JSON_HEDLEY_SUNPRO_VERSION
24562#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
24563#undef JSON_HEDLEY_TINYC_VERSION
24564#undef JSON_HEDLEY_TINYC_VERSION_CHECK
24565#undef JSON_HEDLEY_TI_ARMCL_VERSION
24566#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
24567#undef JSON_HEDLEY_TI_CL2000_VERSION
24568#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
24569#undef JSON_HEDLEY_TI_CL430_VERSION
24570#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
24571#undef JSON_HEDLEY_TI_CL6X_VERSION
24572#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
24573#undef JSON_HEDLEY_TI_CL7X_VERSION
24574#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
24575#undef JSON_HEDLEY_TI_CLPRU_VERSION
24576#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
24577#undef JSON_HEDLEY_TI_VERSION
24578#undef JSON_HEDLEY_TI_VERSION_CHECK
24579#undef JSON_HEDLEY_UNAVAILABLE
24580#undef JSON_HEDLEY_UNLIKELY
24581#undef JSON_HEDLEY_UNPREDICTABLE
24582#undef JSON_HEDLEY_UNREACHABLE
24583#undef JSON_HEDLEY_UNREACHABLE_RETURN
24584#undef JSON_HEDLEY_VERSION
24585#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
24586#undef JSON_HEDLEY_VERSION_DECODE_MINOR
24587#undef JSON_HEDLEY_VERSION_DECODE_REVISION
24588#undef JSON_HEDLEY_VERSION_ENCODE
24589#undef JSON_HEDLEY_WARNING
24590#undef JSON_HEDLEY_WARN_UNUSED_RESULT
24591#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
24592#undef JSON_HEDLEY_FALL_THROUGH
24593
24594
24595
24596#endif // INCLUDE_NLOHMANN_JSON_HPP_
diff --git a/vendor/libtwittercpp b/vendor/libtwittercpp deleted file mode 160000
Subproject 4963c3dd55b765a33a16a77af432f2bfa12b835