Merge lp:~thomas-voss/location-service/add-ichnaea-provider into lp:location-service/trunk
- add-ichnaea-provider
- Merge into trunk
Proposed by
Thomas Voß
Status: | Needs review |
---|---|
Proposed branch: | lp:~thomas-voss/location-service/add-ichnaea-provider |
Merge into: | lp:location-service/trunk |
Diff against target: |
10213 lines (+9973/-0) 39 files modified
3rd-party/ichnaea/CMakeLists.txt (+68/-0) 3rd-party/ichnaea/examples/client.cpp (+101/-0) 3rd-party/ichnaea/include/ichnaea/bluetooth_beacon.h (+33/-0) 3rd-party/ichnaea/include/ichnaea/client.h (+66/-0) 3rd-party/ichnaea/include/ichnaea/error.h (+56/-0) 3rd-party/ichnaea/include/ichnaea/geolocate/fallback.h (+49/-0) 3rd-party/ichnaea/include/ichnaea/geolocate/parameters.h (+48/-0) 3rd-party/ichnaea/include/ichnaea/geolocate/result.h (+45/-0) 3rd-party/ichnaea/include/ichnaea/geosubmit/parameters.h (+34/-0) 3rd-party/ichnaea/include/ichnaea/geosubmit/report.h (+67/-0) 3rd-party/ichnaea/include/ichnaea/geosubmit/result.h (+26/-0) 3rd-party/ichnaea/include/ichnaea/ichnaea.h (+37/-0) 3rd-party/ichnaea/include/ichnaea/radio_cell.h (+60/-0) 3rd-party/ichnaea/include/ichnaea/region/parameters.h (+28/-0) 3rd-party/ichnaea/include/ichnaea/region/result.h (+36/-0) 3rd-party/ichnaea/include/ichnaea/response.h (+86/-0) 3rd-party/ichnaea/include/ichnaea/wifi_access_point.h (+53/-0) 3rd-party/ichnaea/src/ichnaea/client.cpp (+120/-0) 3rd-party/ichnaea/src/ichnaea/codec.h (+371/-0) 3rd-party/ichnaea/src/ichnaea/error.cpp (+30/-0) 3rd-party/ichnaea/src/ichnaea/geolocate/fallback.cpp (+41/-0) 3rd-party/ichnaea/src/ichnaea/geosubmit/report.cpp (+29/-0) 3rd-party/ichnaea/src/ichnaea/radio_cell.cpp (+29/-0) 3rd-party/ichnaea/src/ichnaea/util/json.hpp (+7873/-0) 3rd-party/ichnaea/src/ichnaea/wifi_access_point.cpp (+37/-0) 3rd-party/ichnaea/tests/CMakeLists.txt (+19/-0) 3rd-party/ichnaea/tests/error_test.cpp (+25/-0) 3rd-party/ichnaea/tests/fallback_test.cpp (+38/-0) 3rd-party/ichnaea/tests/radio_cell_test.cpp (+26/-0) 3rd-party/ichnaea/tests/response_test.cpp (+34/-0) 3rd-party/ichnaea/tests/wifi_access_point_test.cpp (+26/-0) CMakeLists.txt (+3/-0) src/location_service/com/ubuntu/location/providers/CMakeLists.txt (+1/-0) src/location_service/com/ubuntu/location/providers/config.cpp (+7/-0) src/location_service/com/ubuntu/location/providers/mls/CMakeLists.txt (+15/-0) src/location_service/com/ubuntu/location/providers/mls/delayed_provider.cpp (+42/-0) src/location_service/com/ubuntu/location/providers/mls/delayed_provider.h (+62/-0) src/location_service/com/ubuntu/location/providers/mls/provider.cpp (+152/-0) src/location_service/com/ubuntu/location/providers/mls/provider.h (+100/-0) |
To merge this branch: | bzr merge lp:~thomas-voss/location-service/add-ichnaea-provider |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Simon Fels | Approve | ||
Scott Sweeny (community) | Approve | ||
Review via email: mp+302429@code.launchpad.net |
Commit message
Add a provider that talks to Mozilla's location services.
Description of the change
Add a provider that talks to Mozilla's location services.
To post a comment you must log in.
Unmerged revisions
- 265. By Thomas Voß
-
Add a provider that talks to Mozilla's location services.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added directory '3rd-party/ichnaea' | |||
2 | === added file '3rd-party/ichnaea/CMakeLists.txt' | |||
3 | --- 3rd-party/ichnaea/CMakeLists.txt 1970-01-01 00:00:00 +0000 | |||
4 | +++ 3rd-party/ichnaea/CMakeLists.txt 2016-08-09 15:10:52 +0000 | |||
5 | @@ -0,0 +1,68 @@ | |||
6 | 1 | cmake_minimum_required(VERSION 2.8) | ||
7 | 2 | |||
8 | 3 | project(ichnaea) | ||
9 | 4 | |||
10 | 5 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") | ||
11 | 6 | |||
12 | 7 | include(CTest) | ||
13 | 8 | |||
14 | 9 | find_package(PkgConfig) | ||
15 | 10 | find_package(Boost) | ||
16 | 11 | find_package(Threads) | ||
17 | 12 | |||
18 | 13 | pkg_check_modules(NET_CPP net-cpp REQUIRED) | ||
19 | 14 | pkg_check_modules(UBUNTU_LOCATION_SERVICE_CONNECTIVITY ubuntu-location-service-connectivity REQUIRED) | ||
20 | 15 | |||
21 | 16 | include_directories( | ||
22 | 17 | include | ||
23 | 18 | src | ||
24 | 19 | |||
25 | 20 | ${NET_CPP_INCLUDE_DIRS} | ||
26 | 21 | ${UBUNTU_LOCATION_SERVICE_CONNECTIVITY_INCLUDE_DIRS}) | ||
27 | 22 | |||
28 | 23 | add_library( | ||
29 | 24 | ichnaea | ||
30 | 25 | |||
31 | 26 | include/ichnaea/ichnaea.h | ||
32 | 27 | |||
33 | 28 | include/ichnaea/bluetooth_beacon.h | ||
34 | 29 | include/ichnaea/client.h | ||
35 | 30 | include/ichnaea/error.h | ||
36 | 31 | include/ichnaea/radio_cell.h | ||
37 | 32 | include/ichnaea/response.h | ||
38 | 33 | include/ichnaea/wifi_access_point.h | ||
39 | 34 | include/ichnaea/geolocate/fallback.h | ||
40 | 35 | include/ichnaea/geolocate/parameters.h | ||
41 | 36 | include/ichnaea/geolocate/result.h | ||
42 | 37 | include/ichnaea/geosubmit/parameters.h | ||
43 | 38 | include/ichnaea/geosubmit/report.h | ||
44 | 39 | include/ichnaea/region/parameters.h | ||
45 | 40 | include/ichnaea/region/result.h | ||
46 | 41 | |||
47 | 42 | src/ichnaea/geolocate/fallback.cpp | ||
48 | 43 | src/ichnaea/geosubmit/report.cpp | ||
49 | 44 | |||
50 | 45 | src/ichnaea/codec.h | ||
51 | 46 | src/ichnaea/client.cpp | ||
52 | 47 | src/ichnaea/error.cpp | ||
53 | 48 | src/ichnaea/radio_cell.cpp | ||
54 | 49 | src/ichnaea/wifi_access_point.cpp) | ||
55 | 50 | |||
56 | 51 | target_link_libraries( | ||
57 | 52 | ichnaea | ||
58 | 53 | |||
59 | 54 | ${CMAKE_THREAD_LIBS_INIT} | ||
60 | 55 | ${NET_CPP_LDFLAGS} | ||
61 | 56 | ${UBUNTU_LOCATION_SERVICE_CONNECTIVITY_LDFLAGS}) | ||
62 | 57 | |||
63 | 58 | add_executable( | ||
64 | 59 | ichnaea-client | ||
65 | 60 | |||
66 | 61 | examples/client.cpp) | ||
67 | 62 | |||
68 | 63 | target_link_libraries( | ||
69 | 64 | ichnaea-client | ||
70 | 65 | |||
71 | 66 | ichnaea) | ||
72 | 67 | |||
73 | 68 | add_subdirectory(tests) | ||
74 | 0 | 69 | ||
75 | === added directory '3rd-party/ichnaea/examples' | |||
76 | === added file '3rd-party/ichnaea/examples/client.cpp' | |||
77 | --- 3rd-party/ichnaea/examples/client.cpp 1970-01-01 00:00:00 +0000 | |||
78 | +++ 3rd-party/ichnaea/examples/client.cpp 2016-08-09 15:10:52 +0000 | |||
79 | @@ -0,0 +1,101 @@ | |||
80 | 1 | #include <ichnaea/client.h> | ||
81 | 2 | |||
82 | 3 | #include <com/ubuntu/location/connectivity/manager.h> | ||
83 | 4 | |||
84 | 5 | #include <core/dbus/macros.h> | ||
85 | 6 | #include <core/dbus/object.h> | ||
86 | 7 | #include <core/dbus/signal.h> | ||
87 | 8 | |||
88 | 9 | #include <core/net/http/client.h> | ||
89 | 10 | |||
90 | 11 | #include <thread> | ||
91 | 12 | #include <vector> | ||
92 | 13 | |||
93 | 14 | namespace connectivity = com::ubuntu::location::connectivity; | ||
94 | 15 | |||
95 | 16 | int main() | ||
96 | 17 | { | ||
97 | 18 | auto manager = connectivity::platform_default_manager(); | ||
98 | 19 | auto http_client = core::net::http::make_client(); | ||
99 | 20 | |||
100 | 21 | std::thread worker1{[http_client]() {http_client->run();}}; | ||
101 | 22 | |||
102 | 23 | auto client = std::make_shared<ichnaea::Client>("test", http_client); | ||
103 | 24 | |||
104 | 25 | manager->wireless_network_scan_finished().connect([manager, client] | ||
105 | 26 | { | ||
106 | 27 | std::cout << "Wireless network scan finished" << std::endl; | ||
107 | 28 | |||
108 | 29 | std::vector<connectivity::WirelessNetwork::Ptr> wifis; | ||
109 | 30 | |||
110 | 31 | manager->enumerate_visible_wireless_networks([&wifis](const connectivity::WirelessNetwork::Ptr& wifi) | ||
111 | 32 | { | ||
112 | 33 | wifis.push_back(wifi); | ||
113 | 34 | }); | ||
114 | 35 | |||
115 | 36 | ichnaea::geolocate::Parameters params; | ||
116 | 37 | params.consider_ip = true; | ||
117 | 38 | |||
118 | 39 | for (auto wifi : wifis) | ||
119 | 40 | { | ||
120 | 41 | ichnaea::WifiAccessPoint ap; | ||
121 | 42 | ap.bssid = wifi->bssid().get(); | ||
122 | 43 | ap.ssid = wifi->ssid().get(); | ||
123 | 44 | ap.frequency = wifi->frequency().get(); | ||
124 | 45 | ap.signal_strength = wifi->signal_strength().get(); | ||
125 | 46 | |||
126 | 47 | params.wifi_access_points.insert(ap); | ||
127 | 48 | } | ||
128 | 49 | |||
129 | 50 | try | ||
130 | 51 | { | ||
131 | 52 | client->geolocate(params, [client, params](const ichnaea::Response<ichnaea::geolocate::Result>& response) | ||
132 | 53 | { | ||
133 | 54 | if (not response.is_error()) | ||
134 | 55 | { | ||
135 | 56 | std::cout << "Submitting to the service again." << std::endl; | ||
136 | 57 | ichnaea::geosubmit::Parameters submission; | ||
137 | 58 | ichnaea::geosubmit::Report report; | ||
138 | 59 | report.timestamp = std::chrono::system_clock::now(); | ||
139 | 60 | report.position.latitude = response.result().location.lat; | ||
140 | 61 | report.position.longitude = response.result().location.lon; | ||
141 | 62 | report.position.accuracy = response.result().accuracy; | ||
142 | 63 | report.wifi_access_points = params.wifi_access_points; | ||
143 | 64 | submission.reports.push_back(report); | ||
144 | 65 | |||
145 | 66 | client->geosubmit(submission, [](const ichnaea::Response<ichnaea::geosubmit::Result>& response) | ||
146 | 67 | { | ||
147 | 68 | if (not response.is_error()) | ||
148 | 69 | std::cout << "Successfully submitted to service." << std::endl; | ||
149 | 70 | else | ||
150 | 71 | std::cout << "Error submitting to service: " << response.error() << std::endl; | ||
151 | 72 | }); | ||
152 | 73 | } | ||
153 | 74 | else | ||
154 | 75 | { | ||
155 | 76 | std::cout << "Error querying service for location: " << response.error() << std::endl; | ||
156 | 77 | } | ||
157 | 78 | }); | ||
158 | 79 | |||
159 | 80 | client->region(params, [](const ichnaea::Response<ichnaea::region::Result>& response) | ||
160 | 81 | { | ||
161 | 82 | if (not response.is_error()) | ||
162 | 83 | std::cout << response.result().country_code << ", " << response.result().country_name << std::endl; | ||
163 | 84 | else | ||
164 | 85 | std::cout << "Error querying service for region information: " << response.error() << std::endl; | ||
165 | 86 | }); | ||
166 | 87 | } | ||
167 | 88 | catch (const std::exception& e) | ||
168 | 89 | { | ||
169 | 90 | std::cout << e.what() << std::endl; | ||
170 | 91 | } | ||
171 | 92 | }); | ||
172 | 93 | |||
173 | 94 | while (true) | ||
174 | 95 | { | ||
175 | 96 | manager->request_scan_for_wireless_networks(); | ||
176 | 97 | std::this_thread::sleep_for(std::chrono::seconds{15}); | ||
177 | 98 | } | ||
178 | 99 | |||
179 | 100 | return 0; | ||
180 | 101 | } | ||
181 | 0 | 102 | ||
182 | === added directory '3rd-party/ichnaea/include' | |||
183 | === added directory '3rd-party/ichnaea/include/ichnaea' | |||
184 | === added file '3rd-party/ichnaea/include/ichnaea/bluetooth_beacon.h' | |||
185 | --- 3rd-party/ichnaea/include/ichnaea/bluetooth_beacon.h 1970-01-01 00:00:00 +0000 | |||
186 | +++ 3rd-party/ichnaea/include/ichnaea/bluetooth_beacon.h 2016-08-09 15:10:52 +0000 | |||
187 | @@ -0,0 +1,33 @@ | |||
188 | 1 | // Copyright (C) 2016 Canonical Ltd. | ||
189 | 2 | // | ||
190 | 3 | // This library is free software: you can redistribute it and/or modify | ||
191 | 4 | // it under the terms of the GNU Lesser General Public License as published | ||
192 | 5 | // by the Free Software Foundation, either version 3 of the License, or | ||
193 | 6 | // (at your option) any later version. | ||
194 | 7 | // | ||
195 | 8 | // This program is distributed in the hope that it will be useful, | ||
196 | 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
197 | 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
198 | 11 | // GNU General Public License for more details. | ||
199 | 12 | // | ||
200 | 13 | // You should have received a copy of the GNU Lesser General Public License | ||
201 | 14 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
202 | 15 | #ifndef ICHNAEA_BLUETOOTH_BEACON_H_ | ||
203 | 16 | #define ICHNAEA_BLUETOOTH_BEACON_H_ | ||
204 | 17 | |||
205 | 18 | #include <chrono> | ||
206 | 19 | #include <string> | ||
207 | 20 | |||
208 | 21 | namespace ichnaea | ||
209 | 22 | { | ||
210 | 23 | /// @brief BluetoothBeacon models a visible bluetooth le device. | ||
211 | 24 | struct BluetoothBeacon | ||
212 | 25 | { | ||
213 | 26 | std::string mac_address; ///< The address of the Bluetooth Low Energy (BLE) beacon. | ||
214 | 27 | std::string name; ///< The name of the BLE beacon. | ||
215 | 28 | std::chrono::milliseconds age; ///< The number of milliseconds since this BLE beacon was last seen. | ||
216 | 29 | double signal_strength; ///< The measured signal strength of the BLE beacon in dBm. | ||
217 | 30 | }; | ||
218 | 31 | } | ||
219 | 32 | |||
220 | 33 | #endif // ICHNAEA_BLUETOOTH_BEACON_H_ | ||
221 | 0 | 34 | ||
222 | === added file '3rd-party/ichnaea/include/ichnaea/client.h' | |||
223 | --- 3rd-party/ichnaea/include/ichnaea/client.h 1970-01-01 00:00:00 +0000 | |||
224 | +++ 3rd-party/ichnaea/include/ichnaea/client.h 2016-08-09 15:10:52 +0000 | |||
225 | @@ -0,0 +1,66 @@ | |||
226 | 1 | // Copyright (C) 2016 Canonical Ltd. | ||
227 | 2 | // | ||
228 | 3 | // This library is free software: you can redistribute it and/or modify | ||
229 | 4 | // it under the terms of the GNU Lesser General Public License as published | ||
230 | 5 | // by the Free Software Foundation, either version 3 of the License, or | ||
231 | 6 | // (at your option) any later version. | ||
232 | 7 | // | ||
233 | 8 | // This program is distributed in the hope that it will be useful, | ||
234 | 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
235 | 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
236 | 11 | // GNU General Public License for more details. | ||
237 | 12 | // | ||
238 | 13 | // You should have received a copy of the GNU Lesser General Public License | ||
239 | 14 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
240 | 15 | #ifndef ICHNAEA_CLIENT_H_ | ||
241 | 16 | #define ICHNAEA_CLIENT_H_ | ||
242 | 17 | |||
243 | 18 | #include <ichnaea/response.h> | ||
244 | 19 | |||
245 | 20 | #include <ichnaea/geolocate/parameters.h> | ||
246 | 21 | #include <ichnaea/geolocate/result.h> | ||
247 | 22 | |||
248 | 23 | #include <ichnaea/geosubmit/parameters.h> | ||
249 | 24 | #include <ichnaea/geosubmit/result.h> | ||
250 | 25 | |||
251 | 26 | #include <ichnaea/region/parameters.h> | ||
252 | 27 | #include <ichnaea/region/result.h> | ||
253 | 28 | |||
254 | 29 | #include <functional> | ||
255 | 30 | #include <memory> | ||
256 | 31 | #include <string> | ||
257 | 32 | |||
258 | 33 | namespace core { namespace net { namespace http { class Client; }}} | ||
259 | 34 | |||
260 | 35 | namespace ichnaea | ||
261 | 36 | { | ||
262 | 37 | /// @brief Client provides access to the ichnaea service offered by Mozilla. | ||
263 | 38 | class Client | ||
264 | 39 | { | ||
265 | 40 | public: | ||
266 | 41 | /// @brief The default host we talk to. | ||
267 | 42 | static constexpr const char* default_host{"https://location.services.mozilla.com"}; | ||
268 | 43 | |||
269 | 44 | /// @brief Client initializes a new instance with host, api_key and http_client. | ||
270 | 45 | Client(const std::string& host, const std::string& api_key, const std::shared_ptr<core::net::http::Client>& http_client); | ||
271 | 46 | |||
272 | 47 | /// @brief Client initializes a new instance with api_key and http_client. | ||
273 | 48 | Client(const std::string& api_key, const std::shared_ptr<core::net::http::Client>& http_client); | ||
274 | 49 | |||
275 | 50 | /// @brief geolocate queries the service instance for a position estimate for parameters, | ||
276 | 51 | /// reporting the response to cb. | ||
277 | 52 | void geolocate(const geolocate::Parameters& parameters, const std::function<void(const Response<geolocate::Result>&)>& cb); | ||
278 | 53 | |||
279 | 54 | /// @brief geosubmit feeds new location data to the service, reporting the status of the operation to cb. | ||
280 | 55 | void geosubmit(const geosubmit::Parameters& parameters, const std::function<void(const Response<geosubmit::Result>&)>& cb); | ||
281 | 56 | |||
282 | 57 | /// @brief region resolves the country for a given location, reporting the status of the operation to cb. | ||
283 | 58 | void region(const region::Parameters& parameters, const std::function<void(const Response<region::Result>&)>& cb); | ||
284 | 59 | private: | ||
285 | 60 | std::string host; | ||
286 | 61 | std::string api_key; | ||
287 | 62 | std::shared_ptr<core::net::http::Client> http_client; | ||
288 | 63 | }; | ||
289 | 64 | } | ||
290 | 65 | |||
291 | 66 | #endif // ICHNAEA_CLIENT_H_ | ||
292 | 0 | 67 | ||
293 | === added file '3rd-party/ichnaea/include/ichnaea/error.h' | |||
294 | --- 3rd-party/ichnaea/include/ichnaea/error.h 1970-01-01 00:00:00 +0000 | |||
295 | +++ 3rd-party/ichnaea/include/ichnaea/error.h 2016-08-09 15:10:52 +0000 | |||
296 | @@ -0,0 +1,56 @@ | |||
297 | 1 | // Copyright (C) 2016 Canonical Ltd. | ||
298 | 2 | // | ||
299 | 3 | // This library is free software: you can redistribute it and/or modify | ||
300 | 4 | // it under the terms of the GNU Lesser General Public License as published | ||
301 | 5 | // by the Free Software Foundation, either version 3 of the License, or | ||
302 | 6 | // (at your option) any later version. | ||
303 | 7 | // | ||
304 | 8 | // This program is distributed in the hope that it will be useful, | ||
305 | 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
306 | 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
307 | 11 | // GNU General Public License for more details. | ||
308 | 12 | // | ||
309 | 13 | // You should have received a copy of the GNU Lesser General Public License | ||
310 | 14 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
311 | 15 | #ifndef ICHNAEA_ERROR_H_ | ||
312 | 16 | #define ICHNAEA_ERROR_H_ | ||
313 | 17 | |||
314 | 18 | #include <core/net/http/status.h> | ||
315 | 19 | |||
316 | 20 | #include <iosfwd> | ||
317 | 21 | #include <stdexcept> | ||
318 | 22 | #include <string> | ||
319 | 23 | #include <vector> | ||
320 | 24 | |||
321 | 25 | namespace ichnaea | ||
322 | 26 | { | ||
323 | 27 | /// @brief Error models an error response. | ||
324 | 28 | struct Error : public std::runtime_error | ||
325 | 29 | { | ||
326 | 30 | /// @brief Detail provides further details describing | ||
327 | 31 | /// an error condition. | ||
328 | 32 | struct Detail | ||
329 | 33 | { | ||
330 | 34 | std::string domain; | ||
331 | 35 | std::string reason; | ||
332 | 36 | std::string message; | ||
333 | 37 | }; | ||
334 | 38 | |||
335 | 39 | /// @brief Initializes a new instance with code and message. | ||
336 | 40 | /// | ||
337 | 41 | /// A human-readable message is generated from code and message, | ||
338 | 42 | /// handing it to the std::runtime_error ctor such that what invocations | ||
339 | 43 | /// provide a meaningful summary of the exception. | ||
340 | 44 | Error(core::net::http::Status code, const std::string& message); | ||
341 | 45 | |||
342 | 46 | std::vector<Detail> errors; ///< errors provides further details about the error condition. | ||
343 | 47 | core::net::http::Status code; ///< code describes the top-level class of the error condition. | ||
344 | 48 | std::string message; ///< message provides a human-readable error message. | ||
345 | 49 | |||
346 | 50 | }; | ||
347 | 51 | |||
348 | 52 | /// @brief operator<< inserts error into out. | ||
349 | 53 | std::ostream& operator<<(std::ostream& out, const Error& error); | ||
350 | 54 | } | ||
351 | 55 | |||
352 | 56 | #endif // ICHNAEA_ERROR_H_ | ||
353 | 0 | 57 | ||
354 | === added directory '3rd-party/ichnaea/include/ichnaea/geolocate' | |||
355 | === added file '3rd-party/ichnaea/include/ichnaea/geolocate/fallback.h' | |||
356 | --- 3rd-party/ichnaea/include/ichnaea/geolocate/fallback.h 1970-01-01 00:00:00 +0000 | |||
357 | +++ 3rd-party/ichnaea/include/ichnaea/geolocate/fallback.h 2016-08-09 15:10:52 +0000 | |||
358 | @@ -0,0 +1,49 @@ | |||
359 | 1 | // Copyright (C) 2016 Canonical Ltd. | ||
360 | 2 | // | ||
361 | 3 | // This library is free software: you can redistribute it and/or modify | ||
362 | 4 | // it under the terms of the GNU Lesser General Public License as published | ||
363 | 5 | // by the Free Software Foundation, either version 3 of the License, or | ||
364 | 6 | // (at your option) any later version. | ||
365 | 7 | // | ||
366 | 8 | // This program is distributed in the hope that it will be useful, | ||
367 | 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
368 | 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
369 | 11 | // GNU General Public License for more details. | ||
370 | 12 | // | ||
371 | 13 | // You should have received a copy of the GNU Lesser General Public License | ||
372 | 14 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
373 | 15 | #ifndef ICHNAEA_GEOLOCATE_FALLBACK_H_ | ||
374 | 16 | #define ICHNAEA_GEOLOCATE_FALLBACK_H_ | ||
375 | 17 | |||
376 | 18 | #include <iosfwd> | ||
377 | 19 | |||
378 | 20 | namespace ichnaea | ||
379 | 21 | { | ||
380 | 22 | namespace geolocate | ||
381 | 23 | { | ||
382 | 24 | /// @brief Fallback enumerates all known fallback strategies | ||
383 | 25 | /// for obtaining a position estimate in the case of missing or | ||
384 | 26 | /// contradictory measurements. | ||
385 | 27 | enum class Fallback | ||
386 | 28 | { | ||
387 | 29 | none = 0, | ||
388 | 30 | /// If no exact cell match can be found, fall back from exact cell | ||
389 | 31 | /// position estimates to more coarse grained cell location area estimates, | ||
390 | 32 | /// rather than going directly to an even worse GeoIP based estimate. | ||
391 | 33 | lac = 1 << 0, | ||
392 | 34 | /// If no position can be estimated based on any of the provided data points, | ||
393 | 35 | /// fall back to an estimate based on a GeoIP database based on the senders IP | ||
394 | 36 | /// address at the time of the query. | ||
395 | 37 | ip = 1 << 1 | ||
396 | 38 | }; | ||
397 | 39 | |||
398 | 40 | /// @brief operator<< inserts fallback into out. | ||
399 | 41 | std::ostream& operator<<(std::ostream& out, Fallback fallback); | ||
400 | 42 | /// @brief operator| returns the bitwise or of lhs and rhs. | ||
401 | 43 | Fallback operator|(Fallback lhs, Fallback rhs); | ||
402 | 44 | /// @brief operator| returns the bitwise and of lhs and rhs. | ||
403 | 45 | Fallback operator&(Fallback lhs, Fallback rhs); | ||
404 | 46 | } | ||
405 | 47 | } | ||
406 | 48 | |||
407 | 49 | #endif // ICHNAEA_GEOLOCATE_FALLBACK_H_ | ||
408 | 0 | 50 | ||
409 | === added file '3rd-party/ichnaea/include/ichnaea/geolocate/parameters.h' | |||
410 | --- 3rd-party/ichnaea/include/ichnaea/geolocate/parameters.h 1970-01-01 00:00:00 +0000 | |||
411 | +++ 3rd-party/ichnaea/include/ichnaea/geolocate/parameters.h 2016-08-09 15:10:52 +0000 | |||
412 | @@ -0,0 +1,48 @@ | |||
413 | 1 | // Copyright (C) 2016 Canonical Ltd. | ||
414 | 2 | // | ||
415 | 3 | // This library is free software: you can redistribute it and/or modify | ||
416 | 4 | // it under the terms of the GNU Lesser General Public License as published | ||
417 | 5 | // by the Free Software Foundation, either version 3 of the License, or | ||
418 | 6 | // (at your option) any later version. | ||
419 | 7 | // | ||
420 | 8 | // This program is distributed in the hope that it will be useful, | ||
421 | 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
422 | 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
423 | 11 | // GNU General Public License for more details. | ||
424 | 12 | // | ||
425 | 13 | // You should have received a copy of the GNU Lesser General Public License | ||
426 | 14 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
427 | 15 | #ifndef ICHNAEA_GEOLOCATE_PARAMETERS_H_ | ||
428 | 16 | #define ICHNAEA_GEOLOCATE_PARAMETERS_H_ | ||
429 | 17 | |||
430 | 18 | #include <ichnaea/bluetooth_beacon.h> | ||
431 | 19 | #include <ichnaea/radio_cell.h> | ||
432 | 20 | #include <ichnaea/wifi_access_point.h> | ||
433 | 21 | |||
434 | 22 | #include <ichnaea/geolocate/fallback.h> | ||
435 | 23 | |||
436 | 24 | #include <boost/optional.hpp> | ||
437 | 25 | |||
438 | 26 | #include <set> | ||
439 | 27 | |||
440 | 28 | namespace ichnaea | ||
441 | 29 | { | ||
442 | 30 | namespace geolocate | ||
443 | 31 | { | ||
444 | 32 | /// @brief Parameters encapsulates all input parameters to a geolocate request. | ||
445 | 33 | struct Parameters | ||
446 | 34 | { | ||
447 | 35 | boost::optional<std::string> carrier; ///< The clear text name of the cell carrier / operator. | ||
448 | 36 | boost::optional<bool> consider_ip; ///< Should the clients IP address be used to locate it, defaults to true. | ||
449 | 37 | boost::optional<RadioCell::MCC> mcc; ///< The mobile country code stored on the SIM card. | ||
450 | 38 | boost::optional<RadioCell::MNC> mnc; ///< The mobile network code stored on the SIM card. | ||
451 | 39 | boost::optional<RadioCell::RadioType> radio_type; ///< Same as the radioType entry in each cell record. | ||
452 | 40 | std::set<BluetoothBeacon> bluetooth_beacons; ///< Visible bluetooth beacons. | ||
453 | 41 | std::set<WifiAccessPoint> wifi_access_points; ///< Visible access points. | ||
454 | 42 | std::set<RadioCell> radio_cells; ///< Visible radio cells. | ||
455 | 43 | boost::optional<Fallback> fallback; ///< Fallback setup. | ||
456 | 44 | }; | ||
457 | 45 | } | ||
458 | 46 | } | ||
459 | 47 | |||
460 | 48 | #endif // ICHNAEA_GEOLOCATE_PARAMETERS_H_ | ||
461 | 0 | 49 | ||
462 | === added file '3rd-party/ichnaea/include/ichnaea/geolocate/result.h' | |||
463 | --- 3rd-party/ichnaea/include/ichnaea/geolocate/result.h 1970-01-01 00:00:00 +0000 | |||
464 | +++ 3rd-party/ichnaea/include/ichnaea/geolocate/result.h 2016-08-09 15:10:52 +0000 | |||
465 | @@ -0,0 +1,45 @@ | |||
466 | 1 | // Copyright (C) 2016 Canonical Ltd. | ||
467 | 2 | // | ||
468 | 3 | // This library is free software: you can redistribute it and/or modify | ||
469 | 4 | // it under the terms of the GNU Lesser General Public License as published | ||
470 | 5 | // by the Free Software Foundation, either version 3 of the License, or | ||
471 | 6 | // (at your option) any later version. | ||
472 | 7 | // | ||
473 | 8 | // This program is distributed in the hope that it will be useful, | ||
474 | 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
475 | 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
476 | 11 | // GNU General Public License for more details. | ||
477 | 12 | // | ||
478 | 13 | // You should have received a copy of the GNU Lesser General Public License | ||
479 | 14 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
480 | 15 | #ifndef ICHNAEA_GEOLOCATE_RESULT_H_ | ||
481 | 16 | #define ICHNAEA_GEOLOCATE_RESULT_H_ | ||
482 | 17 | |||
483 | 18 | #include <ichnaea/geolocate/fallback.h> | ||
484 | 19 | |||
485 | 20 | #include <boost/optional.hpp> | ||
486 | 21 | |||
487 | 22 | namespace ichnaea | ||
488 | 23 | { | ||
489 | 24 | namespace geolocate | ||
490 | 25 | { | ||
491 | 26 | /// @brief Result bundles the successful respsone to a | ||
492 | 27 | /// geolocate request. | ||
493 | 28 | /// | ||
494 | 29 | /// Please note that we provide accessors for convenience and to | ||
495 | 30 | /// implement a named parameter pattern. | ||
496 | 31 | struct Result | ||
497 | 32 | { | ||
498 | 33 | struct Location | ||
499 | 34 | { | ||
500 | 35 | double lat; ///< lat is the latitude component of the position estimate. | ||
501 | 36 | double lon; ///< lon is the longitude component of the position estimate. | ||
502 | 37 | }; | ||
503 | 38 | Location location; ///< location is the position estimate determined by the service. | ||
504 | 39 | double accuracy; ///< accuracy describes the quality of the estimate in terms of a circle with radious accuracy. | ||
505 | 40 | boost::optional<Fallback> fallback; ///< fallback contains the fallback strategies that were used to obtain the position estimate. | ||
506 | 41 | }; | ||
507 | 42 | } | ||
508 | 43 | } | ||
509 | 44 | |||
510 | 45 | #endif // ICHNAEA_GEOLOCATE_RESULT_H_ | ||
511 | 0 | 46 | ||
512 | === added directory '3rd-party/ichnaea/include/ichnaea/geosubmit' | |||
513 | === added file '3rd-party/ichnaea/include/ichnaea/geosubmit/parameters.h' | |||
514 | --- 3rd-party/ichnaea/include/ichnaea/geosubmit/parameters.h 1970-01-01 00:00:00 +0000 | |||
515 | +++ 3rd-party/ichnaea/include/ichnaea/geosubmit/parameters.h 2016-08-09 15:10:52 +0000 | |||
516 | @@ -0,0 +1,34 @@ | |||
517 | 1 | // Copyright (C) 2016 Canonical Ltd. | ||
518 | 2 | // | ||
519 | 3 | // This library is free software: you can redistribute it and/or modify | ||
520 | 4 | // it under the terms of the GNU Lesser General Public License as published | ||
521 | 5 | // by the Free Software Foundation, either version 3 of the License, or | ||
522 | 6 | // (at your option) any later version. | ||
523 | 7 | // | ||
524 | 8 | // This program is distributed in the hope that it will be useful, | ||
525 | 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
526 | 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
527 | 11 | // GNU General Public License for more details. | ||
528 | 12 | // | ||
529 | 13 | // You should have received a copy of the GNU Lesser General Public License | ||
530 | 14 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
531 | 15 | #ifndef ICHNAEA_GEOSUBMIT_PARAMETERS_H_ | ||
532 | 16 | #define ICHNAEA_GEOSUBMIT_PARAMETERS_H_ | ||
533 | 17 | |||
534 | 18 | #include <ichnaea/geosubmit/report.h> | ||
535 | 19 | |||
536 | 20 | #include <vector> | ||
537 | 21 | |||
538 | 22 | namespace ichnaea | ||
539 | 23 | { | ||
540 | 24 | namespace geosubmit | ||
541 | 25 | { | ||
542 | 26 | /// @brief Parameters encapsulates all input parameters to a geosubmit request. | ||
543 | 27 | struct Parameters | ||
544 | 28 | { | ||
545 | 29 | std::vector<Report> reports; ///< Collection of samples to be submitted to the service. | ||
546 | 30 | }; | ||
547 | 31 | } | ||
548 | 32 | } | ||
549 | 33 | |||
550 | 34 | #endif // ICHNAEA_GEOSUBMIT_PARAMETERS_H_ | ||
551 | 0 | 35 | ||
552 | === added file '3rd-party/ichnaea/include/ichnaea/geosubmit/report.h' | |||
553 | --- 3rd-party/ichnaea/include/ichnaea/geosubmit/report.h 1970-01-01 00:00:00 +0000 | |||
554 | +++ 3rd-party/ichnaea/include/ichnaea/geosubmit/report.h 2016-08-09 15:10:52 +0000 | |||
555 | @@ -0,0 +1,67 @@ | |||
556 | 1 | // Copyright (C) 2016 Canonical Ltd. | ||
557 | 2 | // | ||
558 | 3 | // This library is free software: you can redistribute it and/or modify | ||
559 | 4 | // it under the terms of the GNU Lesser General Public License as published | ||
560 | 5 | // by the Free Software Foundation, either version 3 of the License, or | ||
561 | 6 | // (at your option) any later version. | ||
562 | 7 | // | ||
563 | 8 | // This program is distributed in the hope that it will be useful, | ||
564 | 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
565 | 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
566 | 11 | // GNU General Public License for more details. | ||
567 | 12 | // | ||
568 | 13 | // You should have received a copy of the GNU Lesser General Public License | ||
569 | 14 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
570 | 15 | #ifndef ICHNAEA_GEOSUBMIT_REPORT_H_ | ||
571 | 16 | #define ICHNAEA_GEOSUBMIT_REPORT_H_ | ||
572 | 17 | |||
573 | 18 | #include <ichnaea/bluetooth_beacon.h> | ||
574 | 19 | #include <ichnaea/radio_cell.h> | ||
575 | 20 | #include <ichnaea/wifi_access_point.h> | ||
576 | 21 | |||
577 | 22 | #include <boost/optional.hpp> | ||
578 | 23 | |||
579 | 24 | #include <chrono> | ||
580 | 25 | #include <set> | ||
581 | 26 | |||
582 | 27 | namespace ichnaea | ||
583 | 28 | { | ||
584 | 29 | namespace geosubmit | ||
585 | 30 | { | ||
586 | 31 | /// @brief Report encapsulates a set of wifi, cell and bt beacon measurements. | ||
587 | 32 | struct Report | ||
588 | 33 | { | ||
589 | 34 | struct Position | ||
590 | 35 | { | ||
591 | 36 | enum class Source | ||
592 | 37 | { | ||
593 | 38 | manual, | ||
594 | 39 | fusion, | ||
595 | 40 | gps | ||
596 | 41 | }; | ||
597 | 42 | |||
598 | 43 | double latitude; ///< The latitude of the observation (WGS 84). | ||
599 | 44 | double longitude; ///< The longitude of the observation (WGS 84). | ||
600 | 45 | boost::optional<double> accuracy; ///< The accuracy of the observed position in meters. | ||
601 | 46 | boost::optional<std::chrono::milliseconds> age; ///< The age of the position data (in milliseconds). | ||
602 | 47 | boost::optional<double> altitude; ///< The altitude at which the data was observed in meters above sea-level. | ||
603 | 48 | boost::optional<double> altitude_accuracy; ///< The accuracy of the altitude estimate in meters. | ||
604 | 49 | boost::optional<double> heading; ///< The heading field denotes the direction of travel of the device and is specified in degrees, where 0° ≤ heading < 360°, counting clockwise relative to the true north. | ||
605 | 50 | boost::optional<double> pressure; ///< The air pressure in hPa (millibar). | ||
606 | 51 | boost::optional<double> speed; ///< The speed field denotes the magnitude of the horizontal component of the device’s current velocity and is specified in meters per second. | ||
607 | 52 | boost::optional<Source> source; ///< The source of the position information. | ||
608 | 53 | }; | ||
609 | 54 | |||
610 | 55 | std::chrono::system_clock::time_point timestamp; ///< The time of observation of the data, measured in milliseconds since the UNIX epoch. | ||
611 | 56 | Position position; ///< The actual position measurement. | ||
612 | 57 | std::set<BluetoothBeacon> bluetooth_beacons; ///< Visible bluetooth beacons. | ||
613 | 58 | std::set<WifiAccessPoint> wifi_access_points; ///< Visible access points. | ||
614 | 59 | std::set<RadioCell> radio_cells; ///< Visible radio cells. | ||
615 | 60 | }; | ||
616 | 61 | |||
617 | 62 | /// @brief operator<< inserts source into out. | ||
618 | 63 | std::ostream& operator<<(std::ostream& out, Report::Position::Source source); | ||
619 | 64 | } | ||
620 | 65 | } | ||
621 | 66 | |||
622 | 67 | #endif // ICHNAEA_GEOSUBMIT_REPORT_H_ | ||
623 | 0 | 68 | ||
624 | === added file '3rd-party/ichnaea/include/ichnaea/geosubmit/result.h' | |||
625 | --- 3rd-party/ichnaea/include/ichnaea/geosubmit/result.h 1970-01-01 00:00:00 +0000 | |||
626 | +++ 3rd-party/ichnaea/include/ichnaea/geosubmit/result.h 2016-08-09 15:10:52 +0000 | |||
627 | @@ -0,0 +1,26 @@ | |||
628 | 1 | // Copyright (C) 2016 Canonical Ltd. | ||
629 | 2 | // | ||
630 | 3 | // This library is free software: you can redistribute it and/or modify | ||
631 | 4 | // it under the terms of the GNU Lesser General Public License as published | ||
632 | 5 | // by the Free Software Foundation, either version 3 of the License, or | ||
633 | 6 | // (at your option) any later version. | ||
634 | 7 | // | ||
635 | 8 | // This program is distributed in the hope that it will be useful, | ||
636 | 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
637 | 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
638 | 11 | // GNU General Public License for more details. | ||
639 | 12 | // | ||
640 | 13 | // You should have received a copy of the GNU Lesser General Public License | ||
641 | 14 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
642 | 15 | #ifndef ICHNAEA_GEOSUBMIT_RESULT_H_ | ||
643 | 16 | #define ICHNAEA_GEOSUBMIT_RESULT_H_ | ||
644 | 17 | |||
645 | 18 | namespace ichnaea | ||
646 | 19 | { | ||
647 | 20 | namespace geosubmit | ||
648 | 21 | { | ||
649 | 22 | struct Result {}; | ||
650 | 23 | } | ||
651 | 24 | } | ||
652 | 25 | |||
653 | 26 | #endif // ICHNAEA_GEOSUBMIT_RESULT_H_ | ||
654 | 0 | 27 | ||
655 | === added file '3rd-party/ichnaea/include/ichnaea/ichnaea.h' | |||
656 | --- 3rd-party/ichnaea/include/ichnaea/ichnaea.h 1970-01-01 00:00:00 +0000 | |||
657 | +++ 3rd-party/ichnaea/include/ichnaea/ichnaea.h 2016-08-09 15:10:52 +0000 | |||
658 | @@ -0,0 +1,37 @@ | |||
659 | 1 | // Copyright (C) 2016 Canonical Ltd. | ||
660 | 2 | // | ||
661 | 3 | // This library is free software: you can redistribute it and/or modify | ||
662 | 4 | // it under the terms of the GNU Lesser General Public License as published | ||
663 | 5 | // by the Free Software Foundation, either version 3 of the License, or | ||
664 | 6 | // (at your option) any later version. | ||
665 | 7 | // | ||
666 | 8 | // This program is distributed in the hope that it will be useful, | ||
667 | 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
668 | 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
669 | 11 | // GNU General Public License for more details. | ||
670 | 12 | // | ||
671 | 13 | // You should have received a copy of the GNU Lesser General Public License | ||
672 | 14 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
673 | 15 | #ifndef ICHNAEA_ICHNAEA_H_ | ||
674 | 16 | #define ICHNAEA_ICHNAEA_H_ | ||
675 | 17 | |||
676 | 18 | #include "ichnaea/response.h" | ||
677 | 19 | #include "ichnaea/radio_cell.h" | ||
678 | 20 | #include "ichnaea/client.h" | ||
679 | 21 | #include "ichnaea/error.h" | ||
680 | 22 | #include "ichnaea/geosubmit/parameters.h" | ||
681 | 23 | #include "ichnaea/geosubmit/result.h" | ||
682 | 24 | #include "ichnaea/geosubmit/report.h" | ||
683 | 25 | #include "ichnaea/bluetooth_beacon.h" | ||
684 | 26 | #include "ichnaea/geolocate/fallback.h" | ||
685 | 27 | #include "ichnaea/geolocate/parameters.h" | ||
686 | 28 | #include "ichnaea/geolocate/result.h" | ||
687 | 29 | #include "ichnaea/wifi_access_point.h" | ||
688 | 30 | |||
689 | 31 | /// @brief ichnaea contains types and functions for using Mozilla's location services: | ||
690 | 32 | /// | ||
691 | 33 | /// Please see https://mozilla.github.io/ichnaea/index.html for further details on the server-side | ||
692 | 34 | /// implementation. | ||
693 | 35 | namespace ichnaea{} | ||
694 | 36 | |||
695 | 37 | #endif // ICHNAEA_ICHNAEA_H_ | ||
696 | 0 | 38 | ||
697 | === added file '3rd-party/ichnaea/include/ichnaea/radio_cell.h' | |||
698 | --- 3rd-party/ichnaea/include/ichnaea/radio_cell.h 1970-01-01 00:00:00 +0000 | |||
699 | +++ 3rd-party/ichnaea/include/ichnaea/radio_cell.h 2016-08-09 15:10:52 +0000 | |||
700 | @@ -0,0 +1,60 @@ | |||
701 | 1 | // Copyright (C) 2016 Canonical Ltd. | ||
702 | 2 | // | ||
703 | 3 | // This library is free software: you can redistribute it and/or modify | ||
704 | 4 | // it under the terms of the GNU Lesser General Public License as published | ||
705 | 5 | // by the Free Software Foundation, either version 3 of the License, or | ||
706 | 6 | // (at your option) any later version. | ||
707 | 7 | // | ||
708 | 8 | // This program is distributed in the hope that it will be useful, | ||
709 | 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
710 | 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
711 | 11 | // GNU General Public License for more details. | ||
712 | 12 | // | ||
713 | 13 | // You should have received a copy of the GNU Lesser General Public License | ||
714 | 14 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
715 | 15 | #ifndef ICHNAEA_RADIO_CELL_H_ | ||
716 | 16 | #define ICHNAEA_RADIO_CELL_H_ | ||
717 | 17 | |||
718 | 18 | #include <boost/optional.hpp> | ||
719 | 19 | |||
720 | 20 | #include <chrono> | ||
721 | 21 | #include <iosfwd> | ||
722 | 22 | |||
723 | 23 | namespace ichnaea | ||
724 | 24 | { | ||
725 | 25 | /// @brief CellTower models an individual radio cell tower. | ||
726 | 26 | struct RadioCell | ||
727 | 27 | { | ||
728 | 28 | enum class RadioType | ||
729 | 29 | { | ||
730 | 30 | gsm, | ||
731 | 31 | wcdma, | ||
732 | 32 | lte | ||
733 | 33 | }; | ||
734 | 34 | |||
735 | 35 | /// @cond | ||
736 | 36 | typedef unsigned int MCC; | ||
737 | 37 | typedef unsigned int MNC; | ||
738 | 38 | typedef unsigned int LAC; | ||
739 | 39 | typedef unsigned int Id; | ||
740 | 40 | typedef unsigned int PSC; | ||
741 | 41 | /// @endcond | ||
742 | 42 | |||
743 | 43 | RadioType radio_type; ///< The type of radio network. | ||
744 | 44 | bool serving; ///< Whether this is the serving or a neighboring cell. | ||
745 | 45 | MCC mcc; ///< The mobile country code. | ||
746 | 46 | MNC mnc; ///< The mobile network code. | ||
747 | 47 | LAC lac; ///< The location area code for GSM and WCDMA networks. The tracking area code for LTE networks. | ||
748 | 48 | Id id; ///< The cell id or cell identity. | ||
749 | 49 | std::chrono::milliseconds age; ///< The number of milliseconds since this networks was last detected. | ||
750 | 50 | PSC psc; ///< The primary scrambling code for WCDMA and physical cell id for LTE. | ||
751 | 51 | boost::optional<double> asu; ///< The arbitrary strength unit indicating the signal strength if a direct signal strength reading is not available. | ||
752 | 52 | boost::optional<double> signal_strength; ///< The signal strength for this cell network, either the RSSI or RSCP. | ||
753 | 53 | double timing_advance; ///< The timing advance value for this cell network. | ||
754 | 54 | }; | ||
755 | 55 | |||
756 | 56 | /// @brief operator<< inserts radio_type into out. | ||
757 | 57 | std::ostream& operator<<(std::ostream& out, RadioCell::RadioType radio_type); | ||
758 | 58 | } | ||
759 | 59 | |||
760 | 60 | #endif // ICHNAEA_RADIO_CELL_H_ | ||
761 | 0 | 61 | ||
762 | === added directory '3rd-party/ichnaea/include/ichnaea/region' | |||
763 | === added file '3rd-party/ichnaea/include/ichnaea/region/parameters.h' | |||
764 | --- 3rd-party/ichnaea/include/ichnaea/region/parameters.h 1970-01-01 00:00:00 +0000 | |||
765 | +++ 3rd-party/ichnaea/include/ichnaea/region/parameters.h 2016-08-09 15:10:52 +0000 | |||
766 | @@ -0,0 +1,28 @@ | |||
767 | 1 | // Copyright (C) 2016 Canonical Ltd. | ||
768 | 2 | // | ||
769 | 3 | // This library is free software: you can redistribute it and/or modify | ||
770 | 4 | // it under the terms of the GNU Lesser General Public License as published | ||
771 | 5 | // by the Free Software Foundation, either version 3 of the License, or | ||
772 | 6 | // (at your option) any later version. | ||
773 | 7 | // | ||
774 | 8 | // This program is distributed in the hope that it will be useful, | ||
775 | 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
776 | 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
777 | 11 | // GNU General Public License for more details. | ||
778 | 12 | // | ||
779 | 13 | // You should have received a copy of the GNU Lesser General Public License | ||
780 | 14 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
781 | 15 | #ifndef ICHNAEA_RESULT_PARAMETERS_H_ | ||
782 | 16 | #define ICHNAEA_RESULT_PARAMETERS_H_ | ||
783 | 17 | |||
784 | 18 | #include <ichnaea/geolocate/parameters.h> | ||
785 | 19 | |||
786 | 20 | namespace ichnaea | ||
787 | 21 | { | ||
788 | 22 | namespace region | ||
789 | 23 | { | ||
790 | 24 | typedef ichnaea::geolocate::Parameters Parameters; | ||
791 | 25 | } | ||
792 | 26 | } | ||
793 | 27 | |||
794 | 28 | #endif // ICHNAEA_RESULT_PARAMETERS_H_ | ||
795 | 0 | 29 | ||
796 | === added file '3rd-party/ichnaea/include/ichnaea/region/result.h' | |||
797 | --- 3rd-party/ichnaea/include/ichnaea/region/result.h 1970-01-01 00:00:00 +0000 | |||
798 | +++ 3rd-party/ichnaea/include/ichnaea/region/result.h 2016-08-09 15:10:52 +0000 | |||
799 | @@ -0,0 +1,36 @@ | |||
800 | 1 | // Copyright (C) 2016 Canonical Ltd. | ||
801 | 2 | // | ||
802 | 3 | // This library is free software: you can redistribute it and/or modify | ||
803 | 4 | // it under the terms of the GNU Lesser General Public License as published | ||
804 | 5 | // by the Free Software Foundation, either version 3 of the License, or | ||
805 | 6 | // (at your option) any later version. | ||
806 | 7 | // | ||
807 | 8 | // This program is distributed in the hope that it will be useful, | ||
808 | 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
809 | 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
810 | 11 | // GNU General Public License for more details. | ||
811 | 12 | // | ||
812 | 13 | // You should have received a copy of the GNU Lesser General Public License | ||
813 | 14 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
814 | 15 | #ifndef ICHNAEA_REGION_RESULT_H_ | ||
815 | 16 | #define ICHNAEA_REGION_RESULT_H_ | ||
816 | 17 | |||
817 | 18 | #include <ichnaea/geolocate/fallback.h> | ||
818 | 19 | |||
819 | 20 | namespace ichnaea | ||
820 | 21 | { | ||
821 | 22 | namespace region | ||
822 | 23 | { | ||
823 | 24 | /// @brief Result bundles the result of a region query, reporting back | ||
824 | 25 | /// country code and name using region codes and names from the GENC dataset. | ||
825 | 26 | /// | ||
826 | 27 | /// See http://www.gwg.nga.mil/ccwg.php for further details. | ||
827 | 28 | struct Result | ||
828 | 29 | { | ||
829 | 30 | std::string country_code; | ||
830 | 31 | std::string country_name; | ||
831 | 32 | }; | ||
832 | 33 | } | ||
833 | 34 | } | ||
834 | 35 | |||
835 | 36 | #endif // ICHNAEA_REGION_RESULT_H_ | ||
836 | 0 | 37 | ||
837 | === added file '3rd-party/ichnaea/include/ichnaea/response.h' | |||
838 | --- 3rd-party/ichnaea/include/ichnaea/response.h 1970-01-01 00:00:00 +0000 | |||
839 | +++ 3rd-party/ichnaea/include/ichnaea/response.h 2016-08-09 15:10:52 +0000 | |||
840 | @@ -0,0 +1,86 @@ | |||
841 | 1 | // Copyright (C) 2016 Canonical Ltd. | ||
842 | 2 | // | ||
843 | 3 | // This library is free software: you can redistribute it and/or modify | ||
844 | 4 | // it under the terms of the GNU Lesser General Public License as published | ||
845 | 5 | // by the Free Software Foundation, either version 3 of the License, or | ||
846 | 6 | // (at your option) any later version. | ||
847 | 7 | // | ||
848 | 8 | // This program is distributed in the hope that it will be useful, | ||
849 | 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
850 | 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
851 | 11 | // GNU General Public License for more details. | ||
852 | 12 | // | ||
853 | 13 | // You should have received a copy of the GNU Lesser General Public License | ||
854 | 14 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
855 | 15 | #ifndef ICHNAEA_RESPONSE_H_ | ||
856 | 16 | #define ICHNAEA_RESPONSE_H_ | ||
857 | 17 | |||
858 | 18 | #include <ichnaea/error.h> | ||
859 | 19 | |||
860 | 20 | #include <boost/variant.hpp> | ||
861 | 21 | |||
862 | 22 | #include <type_traits> | ||
863 | 23 | |||
864 | 24 | namespace ichnaea | ||
865 | 25 | { | ||
866 | 26 | /// @brief Repsonse models a typed variant that either contains the Result of | ||
867 | 27 | /// an operation xor an error if the operation fails. | ||
868 | 28 | template<typename Result> | ||
869 | 29 | class Response | ||
870 | 30 | { | ||
871 | 31 | public: | ||
872 | 32 | /// @brief NotAnError is thrown if error() is invoked on a Response<T> | ||
873 | 33 | /// instance that contains a result. | ||
874 | 34 | struct NotAnError : public std::runtime_error | ||
875 | 35 | { | ||
876 | 36 | NotAnError() : std::runtime_error{"Not an error"} | ||
877 | 37 | { | ||
878 | 38 | } | ||
879 | 39 | }; | ||
880 | 40 | |||
881 | 41 | /// @brief Response initializes a new instance with result such | ||
882 | 42 | /// that subsequent invocations of is_error() return false. | ||
883 | 43 | explicit Response(const Result& result) | ||
884 | 44 | : result_or_error{result} | ||
885 | 45 | { | ||
886 | 46 | } | ||
887 | 47 | |||
888 | 48 | /// @brief Response initializes a new instance with error such | ||
889 | 49 | /// that subsequent invocations of is_error() return true. | ||
890 | 50 | explicit Response(const Error& error) | ||
891 | 51 | : result_or_error{error} | ||
892 | 52 | { | ||
893 | 53 | } | ||
894 | 54 | |||
895 | 55 | /// @brief is_error returns true if the instance contains an error. | ||
896 | 56 | bool is_error() const | ||
897 | 57 | { | ||
898 | 58 | return 1 == result_or_error.which(); | ||
899 | 59 | } | ||
900 | 60 | |||
901 | 61 | /// @brief error returns the error response or throws NotAnError | ||
902 | 62 | /// if no error is contained in the instance. | ||
903 | 63 | const Error& error() const | ||
904 | 64 | { | ||
905 | 65 | if (not is_error()) | ||
906 | 66 | throw NotAnError{}; | ||
907 | 67 | |||
908 | 68 | return boost::get<Error>(result_or_error); | ||
909 | 69 | } | ||
910 | 70 | |||
911 | 71 | /// @brief result returns the Result instance. Throws the contained | ||
912 | 72 | /// error if this is an error response. | ||
913 | 73 | const Result& result() const | ||
914 | 74 | { | ||
915 | 75 | if (is_error()) | ||
916 | 76 | throw error(); | ||
917 | 77 | |||
918 | 78 | return boost::get<Result>(result_or_error); | ||
919 | 79 | } | ||
920 | 80 | |||
921 | 81 | private: | ||
922 | 82 | boost::variant<Result, Error> result_or_error; | ||
923 | 83 | }; | ||
924 | 84 | } | ||
925 | 85 | |||
926 | 86 | #endif // ICHNAEA_RESPONSE_H_ | ||
927 | 0 | 87 | ||
928 | === added file '3rd-party/ichnaea/include/ichnaea/wifi_access_point.h' | |||
929 | --- 3rd-party/ichnaea/include/ichnaea/wifi_access_point.h 1970-01-01 00:00:00 +0000 | |||
930 | +++ 3rd-party/ichnaea/include/ichnaea/wifi_access_point.h 2016-08-09 15:10:52 +0000 | |||
931 | @@ -0,0 +1,53 @@ | |||
932 | 1 | // Copyright (C) 2016 Canonical Ltd. | ||
933 | 2 | // | ||
934 | 3 | // This library is free software: you can redistribute it and/or modify | ||
935 | 4 | // it under the terms of the GNU Lesser General Public License as published | ||
936 | 5 | // by the Free Software Foundation, either version 3 of the License, or | ||
937 | 6 | // (at your option) any later version. | ||
938 | 7 | // | ||
939 | 8 | // This program is distributed in the hope that it will be useful, | ||
940 | 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
941 | 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
942 | 11 | // GNU General Public License for more details. | ||
943 | 12 | // | ||
944 | 13 | // You should have received a copy of the GNU Lesser General Public License | ||
945 | 14 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
946 | 15 | #ifndef ICHNAEA_WIFI_ACCESS_POINT_H_ | ||
947 | 16 | #define ICHNAEA_WIFI_ACCESS_POINT_H_ | ||
948 | 17 | |||
949 | 18 | #include <boost/optional.hpp> | ||
950 | 19 | |||
951 | 20 | #include <chrono> | ||
952 | 21 | #include <string> | ||
953 | 22 | |||
954 | 23 | namespace ichnaea | ||
955 | 24 | { | ||
956 | 25 | struct WifiAccessPoint | ||
957 | 26 | { | ||
958 | 27 | enum class Type | ||
959 | 28 | { | ||
960 | 29 | _802_11_a, | ||
961 | 30 | _802_11_b, | ||
962 | 31 | _802_11_g, | ||
963 | 32 | _802_11_n, | ||
964 | 33 | _802_11_ac | ||
965 | 34 | }; | ||
966 | 35 | |||
967 | 36 | std::string bssid; ///< The BSSID of the WiFi network. | ||
968 | 37 | boost::optional<Type> type; ///< The Wifi radio type. | ||
969 | 38 | boost::optional<std::chrono::milliseconds> age; ///< The number of milliseconds since this network was last detected. | ||
970 | 39 | boost::optional<unsigned int> channel; ///< The WiFi channel, often 1 - 13 for networks in the 2.4GHz range. | ||
971 | 40 | boost::optional<double> frequency; ///< The frequency in MHz of the channel over which the client is communicating with the access point. | ||
972 | 41 | boost::optional<double> signal_strength; ///< The received signal strength (RSSI) in dBm. | ||
973 | 42 | boost::optional<double> signal_to_noise_ratio; ///< The current signal to noise ratio measured in dB. | ||
974 | 43 | boost::optional<std::string> ssid; ///< The SSID of the Wifi network. | ||
975 | 44 | }; | ||
976 | 45 | |||
977 | 46 | /// @brief operator< returns true if lhs is smaller than rhs. | ||
978 | 47 | bool operator<(const WifiAccessPoint& lhs, const WifiAccessPoint& rhs); | ||
979 | 48 | |||
980 | 49 | /// @brief operator<< inserts type into out. | ||
981 | 50 | std::ostream& operator<<(std::ostream& out, WifiAccessPoint::Type type); | ||
982 | 51 | } | ||
983 | 52 | |||
984 | 53 | #endif // ICHNAEA_WIFI_ACCESS_POINT_H_ | ||
985 | 0 | 54 | ||
986 | === added directory '3rd-party/ichnaea/src' | |||
987 | === added directory '3rd-party/ichnaea/src/ichnaea' | |||
988 | === added file '3rd-party/ichnaea/src/ichnaea/client.cpp' | |||
989 | --- 3rd-party/ichnaea/src/ichnaea/client.cpp 1970-01-01 00:00:00 +0000 | |||
990 | +++ 3rd-party/ichnaea/src/ichnaea/client.cpp 2016-08-09 15:10:52 +0000 | |||
991 | @@ -0,0 +1,120 @@ | |||
992 | 1 | // Copyright (C) 2016 Canonical Ltd. | ||
993 | 2 | // | ||
994 | 3 | // This library is free software: you can redistribute it and/or modify | ||
995 | 4 | // it under the terms of the GNU Lesser General Public License as published | ||
996 | 5 | // by the Free Software Foundation, either version 3 of the License, or | ||
997 | 6 | // (at your option) any later version. | ||
998 | 7 | // | ||
999 | 8 | // This program is distributed in the hope that it will be useful, | ||
1000 | 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1001 | 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1002 | 11 | // GNU General Public License for more details. | ||
1003 | 12 | // | ||
1004 | 13 | // You should have received a copy of the GNU Lesser General Public License | ||
1005 | 14 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1006 | 15 | #include <ichnaea/client.h> | ||
1007 | 16 | #include <ichnaea/codec.h> | ||
1008 | 17 | |||
1009 | 18 | #include <ichnaea/util/json.hpp> | ||
1010 | 19 | |||
1011 | 20 | #include <core/net/uri.h> | ||
1012 | 21 | #include <core/net/http/client.h> | ||
1013 | 22 | #include <core/net/http/request.h> | ||
1014 | 23 | #include <core/net/http/response.h> | ||
1015 | 24 | #include <core/net/http/status.h> | ||
1016 | 25 | |||
1017 | 26 | #include <boost/lexical_cast.hpp> | ||
1018 | 27 | |||
1019 | 28 | namespace http = core::net::http; | ||
1020 | 29 | namespace json = nlohmann; | ||
1021 | 30 | |||
1022 | 31 | ichnaea::Client::Client(const std::string& host, const std::string& api_key, const std::shared_ptr<http::Client>& http_client) | ||
1023 | 32 | : host{host}, api_key{api_key}, http_client{http_client} | ||
1024 | 33 | { | ||
1025 | 34 | } | ||
1026 | 35 | |||
1027 | 36 | ichnaea::Client::Client(const std::string& api_key, const std::shared_ptr<http::Client>& http_client) | ||
1028 | 37 | : Client{Client::default_host, api_key, http_client} | ||
1029 | 38 | { | ||
1030 | 39 | } | ||
1031 | 40 | |||
1032 | 41 | void ichnaea::Client::geolocate(const geolocate::Parameters& parameters, const std::function<void(const Response<geolocate::Result>&)>& cb) | ||
1033 | 42 | { | ||
1034 | 43 | json::json root; root & parameters; | ||
1035 | 44 | |||
1036 | 45 | http::Request::Configuration config; | ||
1037 | 46 | config.uri = http_client->uri_to_string(core::net::make_uri(host, {"v1", "geolocate"}, {{"key", api_key}})); | ||
1038 | 47 | http::Request::Handler handler; | ||
1039 | 48 | handler.on_response([cb](const http::Response& response) | ||
1040 | 49 | { | ||
1041 | 50 | auto root = json::json::parse(response.body); | ||
1042 | 51 | |||
1043 | 52 | if (response.status != http::Status::ok) | ||
1044 | 53 | { | ||
1045 | 54 | Error e{http::Status::bad_request, ""}; root & std::ref(e); | ||
1046 | 55 | cb(Response<geolocate::Result>{e}); | ||
1047 | 56 | } | ||
1048 | 57 | else | ||
1049 | 58 | { | ||
1050 | 59 | geolocate::Result r; root & std::ref(r); | ||
1051 | 60 | cb(Response<geolocate::Result>{r}); | ||
1052 | 61 | } | ||
1053 | 62 | }); | ||
1054 | 63 | |||
1055 | 64 | http_client->post(config, root.dump(), "application/json")->async_execute(handler); | ||
1056 | 65 | } | ||
1057 | 66 | |||
1058 | 67 | void ichnaea::Client::geosubmit(const geosubmit::Parameters& parameters, const std::function<void(const Response<geosubmit::Result>&)>& cb) | ||
1059 | 68 | { | ||
1060 | 69 | if (parameters.reports.empty()) | ||
1061 | 70 | return; | ||
1062 | 71 | |||
1063 | 72 | json::json root; root & parameters; | ||
1064 | 73 | |||
1065 | 74 | http::Request::Configuration config; | ||
1066 | 75 | config.uri = http_client->uri_to_string(core::net::make_uri(host, {"v2", "geosubmit"}, {})); | ||
1067 | 76 | http::Request::Handler handler; | ||
1068 | 77 | handler.on_response([cb](const http::Response& response) | ||
1069 | 78 | { | ||
1070 | 79 | auto root = json::json::parse(response.body); | ||
1071 | 80 | |||
1072 | 81 | if (response.status != http::Status::ok) | ||
1073 | 82 | { | ||
1074 | 83 | Error e{http::Status::bad_request, ""}; root & std::ref(e); | ||
1075 | 84 | cb(Response<geosubmit::Result>{e}); | ||
1076 | 85 | } | ||
1077 | 86 | else | ||
1078 | 87 | { | ||
1079 | 88 | geosubmit::Result r; root & std::ref(r); | ||
1080 | 89 | cb(Response<geosubmit::Result>{r}); | ||
1081 | 90 | } | ||
1082 | 91 | }); | ||
1083 | 92 | |||
1084 | 93 | http_client->post(config, root.dump(), "application/json")->async_execute(handler); | ||
1085 | 94 | } | ||
1086 | 95 | |||
1087 | 96 | void ichnaea::Client::region(const region::Parameters& parameters, const std::function<void(const Response<region::Result>&)>& cb) | ||
1088 | 97 | { | ||
1089 | 98 | json::json root; root & parameters; | ||
1090 | 99 | |||
1091 | 100 | http::Request::Configuration config; | ||
1092 | 101 | config.uri = http_client->uri_to_string(core::net::make_uri(host, {"v1", "country"}, {{"key", api_key}})); | ||
1093 | 102 | http::Request::Handler handler; | ||
1094 | 103 | handler.on_response([cb](const http::Response& response) | ||
1095 | 104 | { | ||
1096 | 105 | auto root = json::json::parse(response.body); | ||
1097 | 106 | |||
1098 | 107 | if (response.status != http::Status::ok) | ||
1099 | 108 | { | ||
1100 | 109 | Error e{http::Status::bad_request, ""}; root & std::ref(e); | ||
1101 | 110 | cb(Response<region::Result>{e}); | ||
1102 | 111 | } | ||
1103 | 112 | else | ||
1104 | 113 | { | ||
1105 | 114 | region::Result r; root & std::ref(r); | ||
1106 | 115 | cb(Response<region::Result>{r}); | ||
1107 | 116 | } | ||
1108 | 117 | }); | ||
1109 | 118 | |||
1110 | 119 | http_client->post(config, root.dump(), "application/json")->async_execute(handler); | ||
1111 | 120 | } | ||
1112 | 0 | 121 | ||
1113 | === added file '3rd-party/ichnaea/src/ichnaea/codec.h' | |||
1114 | --- 3rd-party/ichnaea/src/ichnaea/codec.h 1970-01-01 00:00:00 +0000 | |||
1115 | +++ 3rd-party/ichnaea/src/ichnaea/codec.h 2016-08-09 15:10:52 +0000 | |||
1116 | @@ -0,0 +1,371 @@ | |||
1117 | 1 | #ifndef ICHNAEA_CODEC_H_ | ||
1118 | 2 | #define ICHNAEA_CODEC_H_ | ||
1119 | 3 | |||
1120 | 4 | #include <ichnaea/error.h> | ||
1121 | 5 | |||
1122 | 6 | #include <ichnaea/bluetooth_beacon.h> | ||
1123 | 7 | #include <ichnaea/radio_cell.h> | ||
1124 | 8 | #include <ichnaea/wifi_access_point.h> | ||
1125 | 9 | |||
1126 | 10 | #include <ichnaea/geolocate/fallback.h> | ||
1127 | 11 | #include <ichnaea/geolocate/parameters.h> | ||
1128 | 12 | #include <ichnaea/geolocate/result.h> | ||
1129 | 13 | #include <ichnaea/geosubmit/parameters.h> | ||
1130 | 14 | #include <ichnaea/geosubmit/report.h> | ||
1131 | 15 | #include <ichnaea/geosubmit/result.h> | ||
1132 | 16 | #include <ichnaea/region/result.h> | ||
1133 | 17 | |||
1134 | 18 | #include <ichnaea/util/json.hpp> | ||
1135 | 19 | |||
1136 | 20 | #include <boost/lexical_cast.hpp> | ||
1137 | 21 | #include <boost/optional.hpp> | ||
1138 | 22 | |||
1139 | 23 | #include <chrono> | ||
1140 | 24 | #include <map> | ||
1141 | 25 | #include <set> | ||
1142 | 26 | #include <vector> | ||
1143 | 27 | |||
1144 | 28 | namespace json = nlohmann; | ||
1145 | 29 | |||
1146 | 30 | namespace ichnaea | ||
1147 | 31 | { | ||
1148 | 32 | |||
1149 | 33 | template<typename T> | ||
1150 | 34 | struct NVP | ||
1151 | 35 | { | ||
1152 | 36 | std::string name; | ||
1153 | 37 | T value; | ||
1154 | 38 | }; | ||
1155 | 39 | |||
1156 | 40 | template<typename T> | ||
1157 | 41 | inline NVP<T> make_nvp(const std::string& name, const T& value) | ||
1158 | 42 | { | ||
1159 | 43 | return NVP<T>{name, value}; | ||
1160 | 44 | } | ||
1161 | 45 | |||
1162 | 46 | template<typename T> | ||
1163 | 47 | struct Codec | ||
1164 | 48 | { | ||
1165 | 49 | static void encode(json::json& out, const T& in) | ||
1166 | 50 | { | ||
1167 | 51 | out = in; | ||
1168 | 52 | } | ||
1169 | 53 | |||
1170 | 54 | static void decode(json::json& in, T& out) | ||
1171 | 55 | { | ||
1172 | 56 | out = in; | ||
1173 | 57 | } | ||
1174 | 58 | }; | ||
1175 | 59 | |||
1176 | 60 | template<typename T> | ||
1177 | 61 | inline json::json& operator&(json::json& out, const T& in) | ||
1178 | 62 | { | ||
1179 | 63 | Codec<T>::encode(out, in); | ||
1180 | 64 | return out; | ||
1181 | 65 | } | ||
1182 | 66 | |||
1183 | 67 | template<typename T> | ||
1184 | 68 | inline json::json& operator&(json::json& out, const std::reference_wrapper<T>& in) | ||
1185 | 69 | { | ||
1186 | 70 | Codec<T>::decode(out, in.get()); | ||
1187 | 71 | return out; | ||
1188 | 72 | } | ||
1189 | 73 | |||
1190 | 74 | template<typename T> | ||
1191 | 75 | struct Codec<NVP<T>> | ||
1192 | 76 | { | ||
1193 | 77 | static void encode(json::json& out, const NVP<T>& in) | ||
1194 | 78 | { | ||
1195 | 79 | Codec<T>::encode(out[in.name], in.value); | ||
1196 | 80 | } | ||
1197 | 81 | |||
1198 | 82 | static void decode(json::json& in, NVP<T>& out) | ||
1199 | 83 | { | ||
1200 | 84 | Codec<T>::decode(in[out.name], out.value); | ||
1201 | 85 | } | ||
1202 | 86 | }; | ||
1203 | 87 | |||
1204 | 88 | template<typename T> | ||
1205 | 89 | struct Codec<NVP<boost::optional<T>>> | ||
1206 | 90 | { | ||
1207 | 91 | static void encode(json::json& out, const NVP<boost::optional<T>>& in) | ||
1208 | 92 | { | ||
1209 | 93 | if (in.value) out[in.name] & in.value; | ||
1210 | 94 | } | ||
1211 | 95 | |||
1212 | 96 | static void decode(json::json& in, NVP<boost::optional<T>>& out) | ||
1213 | 97 | { | ||
1214 | 98 | if (in) in[out.name] & out.value; | ||
1215 | 99 | } | ||
1216 | 100 | }; | ||
1217 | 101 | |||
1218 | 102 | template<typename T> | ||
1219 | 103 | struct Codec<NVP<std::set<T>>> | ||
1220 | 104 | { | ||
1221 | 105 | static void encode(json::json& out, const NVP<std::set<T>>& in) | ||
1222 | 106 | { | ||
1223 | 107 | if (not in.value.empty()) out[in.name] & in.value; | ||
1224 | 108 | } | ||
1225 | 109 | |||
1226 | 110 | static void decode(json::json& in, NVP<std::set<T>>& out) | ||
1227 | 111 | { | ||
1228 | 112 | if (in) in[out.name] & out.value; | ||
1229 | 113 | } | ||
1230 | 114 | }; | ||
1231 | 115 | |||
1232 | 116 | template<> | ||
1233 | 117 | struct Codec<std::chrono::milliseconds> | ||
1234 | 118 | { | ||
1235 | 119 | static void encode(json::json& out, const std::chrono::milliseconds in) | ||
1236 | 120 | { | ||
1237 | 121 | out & in.count(); | ||
1238 | 122 | } | ||
1239 | 123 | |||
1240 | 124 | static void decode(json::json& out, std::chrono::milliseconds& in); | ||
1241 | 125 | }; | ||
1242 | 126 | |||
1243 | 127 | template<typename T> | ||
1244 | 128 | struct Codec<boost::optional<T>> | ||
1245 | 129 | { | ||
1246 | 130 | static void encode(json::json& out, const boost::optional<T>& in) | ||
1247 | 131 | { | ||
1248 | 132 | if (in) Codec<T>::encode(out, *in); | ||
1249 | 133 | } | ||
1250 | 134 | |||
1251 | 135 | static void decode(json::json& out, boost::optional<T>& in) | ||
1252 | 136 | { | ||
1253 | 137 | if (out) Codec<T>::encode(out, *(in = T{})); | ||
1254 | 138 | } | ||
1255 | 139 | }; | ||
1256 | 140 | |||
1257 | 141 | template<typename T> | ||
1258 | 142 | struct Codec<std::set<T>> | ||
1259 | 143 | { | ||
1260 | 144 | static void encode(json::json& out, const std::set<T>& in) | ||
1261 | 145 | { | ||
1262 | 146 | if (in.empty()) return; | ||
1263 | 147 | for (const auto& element : in) | ||
1264 | 148 | { | ||
1265 | 149 | json::json j; Codec<T>::encode(j, element); out.push_back(j); | ||
1266 | 150 | } | ||
1267 | 151 | } | ||
1268 | 152 | |||
1269 | 153 | static void decode(json::json& out, std::set<T>& in) | ||
1270 | 154 | { | ||
1271 | 155 | for (const auto& element: in) | ||
1272 | 156 | { | ||
1273 | 157 | T t; Codec<T>::decode(element, t); in.insert(t); | ||
1274 | 158 | } | ||
1275 | 159 | } | ||
1276 | 160 | }; | ||
1277 | 161 | |||
1278 | 162 | template<typename T> | ||
1279 | 163 | struct Codec<std::vector<T>> | ||
1280 | 164 | { | ||
1281 | 165 | static void encode(json::json& out, const std::vector<T>& in) | ||
1282 | 166 | { | ||
1283 | 167 | if (in.empty()) return; | ||
1284 | 168 | for (const auto& element : in) | ||
1285 | 169 | { | ||
1286 | 170 | json::json j; Codec<T>::encode(j, element); out.push_back(j); | ||
1287 | 171 | } | ||
1288 | 172 | } | ||
1289 | 173 | |||
1290 | 174 | static void decode(json::json& out, std::vector<T>& in) | ||
1291 | 175 | { | ||
1292 | 176 | for (const auto& element: in) | ||
1293 | 177 | { | ||
1294 | 178 | T t; Codec<T>::decode(element, t); in.push_back(t); | ||
1295 | 179 | } | ||
1296 | 180 | } | ||
1297 | 181 | }; | ||
1298 | 182 | |||
1299 | 183 | template<> | ||
1300 | 184 | struct Codec<Error> | ||
1301 | 185 | { | ||
1302 | 186 | static void encode(json::json&, const Error&) | ||
1303 | 187 | { | ||
1304 | 188 | } | ||
1305 | 189 | |||
1306 | 190 | static void decode(json::json& in, Error& error) | ||
1307 | 191 | { | ||
1308 | 192 | Error e{static_cast<core::net::http::Status>(in["error"]["code"].get<unsigned int>()), in["error"]["message"]}; | ||
1309 | 193 | for (const auto& element : in["error"]["errors"]) | ||
1310 | 194 | e.errors.push_back({element["domain"], element["reason"], element["message"]}); | ||
1311 | 195 | error = e; | ||
1312 | 196 | } | ||
1313 | 197 | }; | ||
1314 | 198 | |||
1315 | 199 | template<> | ||
1316 | 200 | struct Codec<BluetoothBeacon> | ||
1317 | 201 | { | ||
1318 | 202 | static void encode(json::json& out, const BluetoothBeacon& in) | ||
1319 | 203 | { | ||
1320 | 204 | out & make_nvp("macAddress", in.mac_address) | ||
1321 | 205 | & make_nvp("name", in.name) | ||
1322 | 206 | & make_nvp("age", in.age.count()) | ||
1323 | 207 | & make_nvp("signalStrength", in.signal_strength); | ||
1324 | 208 | } | ||
1325 | 209 | |||
1326 | 210 | static void decode(json::json& out, BluetoothBeacon& in); | ||
1327 | 211 | }; | ||
1328 | 212 | |||
1329 | 213 | template<> | ||
1330 | 214 | struct Codec<WifiAccessPoint::Type> | ||
1331 | 215 | { | ||
1332 | 216 | static void encode(json::json& out, WifiAccessPoint::Type in) | ||
1333 | 217 | { | ||
1334 | 218 | out = boost::lexical_cast<std::string>(in); | ||
1335 | 219 | } | ||
1336 | 220 | }; | ||
1337 | 221 | |||
1338 | 222 | template<> | ||
1339 | 223 | struct Codec<WifiAccessPoint> | ||
1340 | 224 | { | ||
1341 | 225 | static void encode(json::json& out, const WifiAccessPoint& in) | ||
1342 | 226 | { | ||
1343 | 227 | out & make_nvp("macAddress", in.bssid) | ||
1344 | 228 | & make_nvp("age", in.age) | ||
1345 | 229 | & make_nvp("channel", in.channel) | ||
1346 | 230 | & make_nvp("frequency", in.frequency) | ||
1347 | 231 | & make_nvp("signalStrength", in.signal_strength) | ||
1348 | 232 | & make_nvp("signalToNoiseRatio", in.signal_to_noise_ratio) | ||
1349 | 233 | & make_nvp("ssid", in.ssid) | ||
1350 | 234 | & make_nvp("radioType", in.type); | ||
1351 | 235 | } | ||
1352 | 236 | |||
1353 | 237 | static void decode(json::json& out, BluetoothBeacon& in); | ||
1354 | 238 | }; | ||
1355 | 239 | |||
1356 | 240 | template<> | ||
1357 | 241 | struct Codec<RadioCell> | ||
1358 | 242 | { | ||
1359 | 243 | static void encode(json::json& out, const RadioCell& in) | ||
1360 | 244 | { | ||
1361 | 245 | out & make_nvp("radioType", boost::lexical_cast<std::string>(in.radio_type)) | ||
1362 | 246 | & make_nvp("mobileCountryCode", in.mcc) | ||
1363 | 247 | & make_nvp("mobileNetworkCode", in.mnc) | ||
1364 | 248 | & make_nvp("locationAreaCode", in.lac) | ||
1365 | 249 | & make_nvp("cellId", in.id) | ||
1366 | 250 | & make_nvp("age", in.age) | ||
1367 | 251 | & make_nvp("psc", in.psc) | ||
1368 | 252 | & make_nvp("asu", in.asu) | ||
1369 | 253 | & make_nvp("signalStrength", in.signal_strength) | ||
1370 | 254 | & make_nvp("timingAdvance", in.timing_advance); | ||
1371 | 255 | } | ||
1372 | 256 | |||
1373 | 257 | static void decode(json::json& out, RadioCell& in); | ||
1374 | 258 | }; | ||
1375 | 259 | |||
1376 | 260 | template<> | ||
1377 | 261 | struct Codec<geolocate::Parameters> | ||
1378 | 262 | { | ||
1379 | 263 | static void encode(json::json& out, const geolocate::Parameters& parameters) | ||
1380 | 264 | { | ||
1381 | 265 | out & make_nvp("carrier", parameters.carrier) | ||
1382 | 266 | & make_nvp("considerIp", parameters.consider_ip) | ||
1383 | 267 | & make_nvp("homeMobileCountryCode", parameters.mcc) | ||
1384 | 268 | & make_nvp("homeMobileNetworkCode", parameters.mnc) | ||
1385 | 269 | & make_nvp("bluetoothBeacons", parameters.bluetooth_beacons) | ||
1386 | 270 | & make_nvp("wifiAccessPoints", parameters.wifi_access_points) | ||
1387 | 271 | & make_nvp("cellTowers", parameters.radio_cells) | ||
1388 | 272 | & make_nvp("fallbacks", parameters.fallback); | ||
1389 | 273 | } | ||
1390 | 274 | }; | ||
1391 | 275 | |||
1392 | 276 | template<> | ||
1393 | 277 | struct Codec<geolocate::Fallback> | ||
1394 | 278 | { | ||
1395 | 279 | static void encode(json::json& out, geolocate::Fallback fb) | ||
1396 | 280 | { | ||
1397 | 281 | if ((fb & geolocate::Fallback::lac) == geolocate::Fallback::lac) | ||
1398 | 282 | out & make_nvp("lacf", true); | ||
1399 | 283 | if ((fb & geolocate::Fallback::ip) == geolocate::Fallback::ip) | ||
1400 | 284 | out & make_nvp("ip", true); | ||
1401 | 285 | } | ||
1402 | 286 | }; | ||
1403 | 287 | |||
1404 | 288 | template<> | ||
1405 | 289 | struct Codec<geolocate::Result> | ||
1406 | 290 | { | ||
1407 | 291 | static void decode(json::json& in, geolocate::Result& r) | ||
1408 | 292 | { | ||
1409 | 293 | r.location.lat = in["location"]["lat"]; | ||
1410 | 294 | r.location.lon = in["location"]["lng"]; | ||
1411 | 295 | r.accuracy = in["accuracy"]; | ||
1412 | 296 | |||
1413 | 297 | if (in["fallback"] == "ipf") | ||
1414 | 298 | r.fallback = geolocate::Fallback::ip; | ||
1415 | 299 | if (in["fallback"] == "lacf") | ||
1416 | 300 | r.fallback = geolocate::Fallback::lac; | ||
1417 | 301 | } | ||
1418 | 302 | }; | ||
1419 | 303 | |||
1420 | 304 | template<> | ||
1421 | 305 | struct Codec<geosubmit::Report::Position::Source> | ||
1422 | 306 | { | ||
1423 | 307 | static void encode(json::json& out, const geosubmit::Report::Position::Source& source) | ||
1424 | 308 | { | ||
1425 | 309 | out = boost::lexical_cast<std::string>(source); | ||
1426 | 310 | } | ||
1427 | 311 | |||
1428 | 312 | static void decode(json::json&, geosubmit::Report&); | ||
1429 | 313 | }; | ||
1430 | 314 | |||
1431 | 315 | template<> | ||
1432 | 316 | struct Codec<geosubmit::Report> | ||
1433 | 317 | { | ||
1434 | 318 | static void encode(json::json& out, const geosubmit::Report& report) | ||
1435 | 319 | { | ||
1436 | 320 | out & make_nvp("timestamp", std::chrono::system_clock::to_time_t(report.timestamp) * 1000); | ||
1437 | 321 | |||
1438 | 322 | out["position"] & make_nvp("latitude", report.position.latitude) | ||
1439 | 323 | & make_nvp("longitude", report.position.longitude) | ||
1440 | 324 | & make_nvp("accuracy", report.position.accuracy) | ||
1441 | 325 | & make_nvp("altitude", report.position.altitude) | ||
1442 | 326 | & make_nvp("altitudeAccuracy", report.position.altitude_accuracy) | ||
1443 | 327 | & make_nvp("age", report.position.age) | ||
1444 | 328 | & make_nvp("heading", report.position.heading) | ||
1445 | 329 | & make_nvp("pressure", report.position.pressure) | ||
1446 | 330 | & make_nvp("speed", report.position.speed) | ||
1447 | 331 | & make_nvp("source", report.position.source); | ||
1448 | 332 | out & make_nvp("bluetoothBeacons", report.bluetooth_beacons) | ||
1449 | 333 | & make_nvp("wifiAccessPoints", report.wifi_access_points) | ||
1450 | 334 | & make_nvp("radioCells", report.radio_cells); | ||
1451 | 335 | } | ||
1452 | 336 | |||
1453 | 337 | static void decode(json::json&, geosubmit::Report&); | ||
1454 | 338 | }; | ||
1455 | 339 | |||
1456 | 340 | template<> | ||
1457 | 341 | struct Codec<geosubmit::Parameters> | ||
1458 | 342 | { | ||
1459 | 343 | static void encode(json::json& out, const geosubmit::Parameters& params) | ||
1460 | 344 | { | ||
1461 | 345 | out & make_nvp("items", params.reports); | ||
1462 | 346 | } | ||
1463 | 347 | |||
1464 | 348 | static void decode(json::json&, geosubmit::Parameters&); | ||
1465 | 349 | }; | ||
1466 | 350 | |||
1467 | 351 | template<> | ||
1468 | 352 | struct Codec<geosubmit::Result> | ||
1469 | 353 | { | ||
1470 | 354 | static void decode(json::json&, geosubmit::Result&) | ||
1471 | 355 | { | ||
1472 | 356 | } | ||
1473 | 357 | }; | ||
1474 | 358 | |||
1475 | 359 | template<> | ||
1476 | 360 | struct Codec<region::Result> | ||
1477 | 361 | { | ||
1478 | 362 | static void decode(json::json& in, region::Result& result) | ||
1479 | 363 | { | ||
1480 | 364 | result.country_code = in["country_code"]; | ||
1481 | 365 | result.country_name = in["country_name"]; | ||
1482 | 366 | |||
1483 | 367 | } | ||
1484 | 368 | }; | ||
1485 | 369 | } | ||
1486 | 370 | |||
1487 | 371 | #endif // ICHNAEA_CODEC_H_ | ||
1488 | 0 | 372 | ||
1489 | === added file '3rd-party/ichnaea/src/ichnaea/error.cpp' | |||
1490 | --- 3rd-party/ichnaea/src/ichnaea/error.cpp 1970-01-01 00:00:00 +0000 | |||
1491 | +++ 3rd-party/ichnaea/src/ichnaea/error.cpp 2016-08-09 15:10:52 +0000 | |||
1492 | @@ -0,0 +1,30 @@ | |||
1493 | 1 | // Copyright (C) 2016 Canonical Ltd. | ||
1494 | 2 | // | ||
1495 | 3 | // This library is free software: you can redistribute it and/or modify | ||
1496 | 4 | // it under the terms of the GNU Lesser General Public License as published | ||
1497 | 5 | // by the Free Software Foundation, either version 3 of the License, or | ||
1498 | 6 | // (at your option) any later version. | ||
1499 | 7 | // | ||
1500 | 8 | // This program is distributed in the hope that it will be useful, | ||
1501 | 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1502 | 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1503 | 11 | // GNU General Public License for more details. | ||
1504 | 12 | // | ||
1505 | 13 | // You should have received a copy of the GNU Lesser General Public License | ||
1506 | 14 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1507 | 15 | #include <ichnaea/error.h> | ||
1508 | 16 | |||
1509 | 17 | #include <iostream> | ||
1510 | 18 | |||
1511 | 19 | ichnaea::Error::Error(core::net::http::Status code, const std::string& message) | ||
1512 | 20 | : std::runtime_error{message}, code{code}, message{message} | ||
1513 | 21 | { | ||
1514 | 22 | } | ||
1515 | 23 | |||
1516 | 24 | std::ostream& ichnaea::operator<<(std::ostream& out, const Error& error) | ||
1517 | 25 | { | ||
1518 | 26 | out << error.code << ", " << error.message << std::endl; | ||
1519 | 27 | for (const Error::Detail& detail : error.errors) | ||
1520 | 28 | out << " " << detail.domain << ", " << detail.message << ", " << detail.reason << std::endl; | ||
1521 | 29 | return out; | ||
1522 | 30 | } | ||
1523 | 0 | 31 | ||
1524 | === added directory '3rd-party/ichnaea/src/ichnaea/geolocate' | |||
1525 | === added file '3rd-party/ichnaea/src/ichnaea/geolocate/fallback.cpp' | |||
1526 | --- 3rd-party/ichnaea/src/ichnaea/geolocate/fallback.cpp 1970-01-01 00:00:00 +0000 | |||
1527 | +++ 3rd-party/ichnaea/src/ichnaea/geolocate/fallback.cpp 2016-08-09 15:10:52 +0000 | |||
1528 | @@ -0,0 +1,41 @@ | |||
1529 | 1 | // Copyright (C) 2016 Canonical Ltd. | ||
1530 | 2 | // | ||
1531 | 3 | // This library is free software: you can redistribute it and/or modify | ||
1532 | 4 | // it under the terms of the GNU Lesser General Public License as published | ||
1533 | 5 | // by the Free Software Foundation, either version 3 of the License, or | ||
1534 | 6 | // (at your option) any later version. | ||
1535 | 7 | // | ||
1536 | 8 | // This program is distributed in the hope that it will be useful, | ||
1537 | 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1538 | 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1539 | 11 | // GNU General Public License for more details. | ||
1540 | 12 | // | ||
1541 | 13 | // You should have received a copy of the GNU Lesser General Public License | ||
1542 | 14 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1543 | 15 | #include <ichnaea/geolocate/fallback.h> | ||
1544 | 16 | |||
1545 | 17 | #include <iostream> | ||
1546 | 18 | #include <type_traits> | ||
1547 | 19 | |||
1548 | 20 | std::ostream& ichnaea::geolocate::operator<<(std::ostream& out, Fallback fallback) | ||
1549 | 21 | { | ||
1550 | 22 | switch (fallback) | ||
1551 | 23 | { | ||
1552 | 24 | case Fallback::ip: return out << "ipf"; | ||
1553 | 25 | case Fallback::lac: return out << "lacf"; | ||
1554 | 26 | } | ||
1555 | 27 | |||
1556 | 28 | return out; | ||
1557 | 29 | } | ||
1558 | 30 | |||
1559 | 31 | ichnaea::geolocate::Fallback ichnaea::geolocate::operator|(ichnaea::geolocate::Fallback lhs, ichnaea::geolocate::Fallback rhs) | ||
1560 | 32 | { | ||
1561 | 33 | typedef typename std::underlying_type<Fallback>::type NT; | ||
1562 | 34 | return static_cast<Fallback>(static_cast<NT>(lhs) | static_cast<NT>(rhs)); | ||
1563 | 35 | } | ||
1564 | 36 | |||
1565 | 37 | ichnaea::geolocate::Fallback ichnaea::geolocate::operator&(ichnaea::geolocate::Fallback lhs, ichnaea::geolocate::Fallback rhs) | ||
1566 | 38 | { | ||
1567 | 39 | typedef typename std::underlying_type<Fallback>::type NT; | ||
1568 | 40 | return static_cast<Fallback>(static_cast<NT>(lhs) & static_cast<NT>(rhs)); | ||
1569 | 41 | } | ||
1570 | 0 | 42 | ||
1571 | === added directory '3rd-party/ichnaea/src/ichnaea/geosubmit' | |||
1572 | === added file '3rd-party/ichnaea/src/ichnaea/geosubmit/report.cpp' | |||
1573 | --- 3rd-party/ichnaea/src/ichnaea/geosubmit/report.cpp 1970-01-01 00:00:00 +0000 | |||
1574 | +++ 3rd-party/ichnaea/src/ichnaea/geosubmit/report.cpp 2016-08-09 15:10:52 +0000 | |||
1575 | @@ -0,0 +1,29 @@ | |||
1576 | 1 | // Copyright (C) 2016 Canonical Ltd. | ||
1577 | 2 | // | ||
1578 | 3 | // This library is free software: you can redistribute it and/or modify | ||
1579 | 4 | // it under the terms of the GNU Lesser General Public License as published | ||
1580 | 5 | // by the Free Software Foundation, either version 3 of the License, or | ||
1581 | 6 | // (at your option) any later version. | ||
1582 | 7 | // | ||
1583 | 8 | // This program is distributed in the hope that it will be useful, | ||
1584 | 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1585 | 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1586 | 11 | // GNU General Public License for more details. | ||
1587 | 12 | // | ||
1588 | 13 | // You should have received a copy of the GNU Lesser General Public License | ||
1589 | 14 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1590 | 15 | #include <ichnaea/geosubmit/report.h> | ||
1591 | 16 | |||
1592 | 17 | #include <iostream> | ||
1593 | 18 | |||
1594 | 19 | std::ostream& ichnaea::geosubmit::operator<<(std::ostream& out, Report::Position::Source source) | ||
1595 | 20 | { | ||
1596 | 21 | switch (source) | ||
1597 | 22 | { | ||
1598 | 23 | case Report::Position::Source::fusion: return out << "fusion"; | ||
1599 | 24 | case Report::Position::Source::gps: return out << "gps"; | ||
1600 | 25 | case Report::Position::Source::manual: return out << "manual"; | ||
1601 | 26 | } | ||
1602 | 27 | |||
1603 | 28 | return out; | ||
1604 | 29 | } | ||
1605 | 0 | 30 | ||
1606 | === added file '3rd-party/ichnaea/src/ichnaea/radio_cell.cpp' | |||
1607 | --- 3rd-party/ichnaea/src/ichnaea/radio_cell.cpp 1970-01-01 00:00:00 +0000 | |||
1608 | +++ 3rd-party/ichnaea/src/ichnaea/radio_cell.cpp 2016-08-09 15:10:52 +0000 | |||
1609 | @@ -0,0 +1,29 @@ | |||
1610 | 1 | // Copyright (C) 2016 Canonical Ltd. | ||
1611 | 2 | // | ||
1612 | 3 | // This library is free software: you can redistribute it and/or modify | ||
1613 | 4 | // it under the terms of the GNU Lesser General Public License as published | ||
1614 | 5 | // by the Free Software Foundation, either version 3 of the License, or | ||
1615 | 6 | // (at your option) any later version. | ||
1616 | 7 | // | ||
1617 | 8 | // This program is distributed in the hope that it will be useful, | ||
1618 | 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1619 | 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1620 | 11 | // GNU General Public License for more details. | ||
1621 | 12 | // | ||
1622 | 13 | // You should have received a copy of the GNU Lesser General Public License | ||
1623 | 14 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1624 | 15 | #include <ichnaea/radio_cell.h> | ||
1625 | 16 | |||
1626 | 17 | #include <iostream> | ||
1627 | 18 | |||
1628 | 19 | std::ostream& ichnaea::operator<<(std::ostream& out, ichnaea::RadioCell::RadioType radio_type) | ||
1629 | 20 | { | ||
1630 | 21 | switch (radio_type) | ||
1631 | 22 | { | ||
1632 | 23 | case ichnaea::RadioCell::RadioType::gsm: return out << "gsm"; | ||
1633 | 24 | case ichnaea::RadioCell::RadioType::lte: return out << "lte"; | ||
1634 | 25 | case ichnaea::RadioCell::RadioType::wcdma: return out << "wcdma"; | ||
1635 | 26 | } | ||
1636 | 27 | |||
1637 | 28 | return out; | ||
1638 | 29 | } | ||
1639 | 0 | 30 | ||
1640 | === added directory '3rd-party/ichnaea/src/ichnaea/util' | |||
1641 | === added file '3rd-party/ichnaea/src/ichnaea/util/json.hpp' | |||
1642 | --- 3rd-party/ichnaea/src/ichnaea/util/json.hpp 1970-01-01 00:00:00 +0000 | |||
1643 | +++ 3rd-party/ichnaea/src/ichnaea/util/json.hpp 2016-08-09 15:10:52 +0000 | |||
1644 | @@ -0,0 +1,7873 @@ | |||
1645 | 1 | /*! | ||
1646 | 2 | @mainpage | ||
1647 | 3 | |||
1648 | 4 | These pages contain the API documentation of JSON for Modern C++, a C++11 | ||
1649 | 5 | header-only JSON class. | ||
1650 | 6 | |||
1651 | 7 | Class @ref nlohmann::basic_json is a good entry point for the documentation. | ||
1652 | 8 | |||
1653 | 9 | @copyright The code is licensed under the [MIT | ||
1654 | 10 | License](http://opensource.org/licenses/MIT): | ||
1655 | 11 | <br> | ||
1656 | 12 | Copyright © 2013-2015 Niels Lohmann. | ||
1657 | 13 | <br> | ||
1658 | 14 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
1659 | 15 | of this software and associated documentation files (the "Software"), to deal | ||
1660 | 16 | in the Software without restriction, including without limitation the rights | ||
1661 | 17 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
1662 | 18 | copies of the Software, and to permit persons to whom the Software is | ||
1663 | 19 | furnished to do so, subject to the following conditions: | ||
1664 | 20 | <br> | ||
1665 | 21 | The above copyright notice and this permission notice shall be included in | ||
1666 | 22 | all copies or substantial portions of the Software. | ||
1667 | 23 | <br> | ||
1668 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
1669 | 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
1670 | 26 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
1671 | 27 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
1672 | 28 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
1673 | 29 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
1674 | 30 | SOFTWARE. | ||
1675 | 31 | |||
1676 | 32 | @author [Niels Lohmann](http://nlohmann.me) | ||
1677 | 33 | @see https://github.com/nlohmann/json to download the source code | ||
1678 | 34 | |||
1679 | 35 | @version 1.0.0 | ||
1680 | 36 | */ | ||
1681 | 37 | |||
1682 | 38 | #ifndef NLOHMANN_JSON_HPP | ||
1683 | 39 | #define NLOHMANN_JSON_HPP | ||
1684 | 40 | |||
1685 | 41 | #include <algorithm> | ||
1686 | 42 | #include <array> | ||
1687 | 43 | #include <ciso646> | ||
1688 | 44 | #include <cmath> | ||
1689 | 45 | #include <cstdio> | ||
1690 | 46 | #include <functional> | ||
1691 | 47 | #include <initializer_list> | ||
1692 | 48 | #include <iomanip> | ||
1693 | 49 | #include <iostream> | ||
1694 | 50 | #include <iterator> | ||
1695 | 51 | #include <limits> | ||
1696 | 52 | #include <map> | ||
1697 | 53 | #include <memory> | ||
1698 | 54 | #include <sstream> | ||
1699 | 55 | #include <string> | ||
1700 | 56 | #include <type_traits> | ||
1701 | 57 | #include <utility> | ||
1702 | 58 | #include <vector> | ||
1703 | 59 | |||
1704 | 60 | // enable ssize_t on MinGW | ||
1705 | 61 | #ifdef __GNUC__ | ||
1706 | 62 | #ifdef __MINGW32__ | ||
1707 | 63 | #include <sys/types.h> | ||
1708 | 64 | #endif | ||
1709 | 65 | #endif | ||
1710 | 66 | |||
1711 | 67 | // enable ssize_t for MSVC | ||
1712 | 68 | #ifdef _MSC_VER | ||
1713 | 69 | #include <basetsd.h> | ||
1714 | 70 | using ssize_t = SSIZE_T; | ||
1715 | 71 | #endif | ||
1716 | 72 | |||
1717 | 73 | /*! | ||
1718 | 74 | @brief namespace for Niels Lohmann | ||
1719 | 75 | @see https://github.com/nlohmann | ||
1720 | 76 | @since version 1.0.0 | ||
1721 | 77 | */ | ||
1722 | 78 | namespace nlohmann | ||
1723 | 79 | { | ||
1724 | 80 | |||
1725 | 81 | |||
1726 | 82 | /*! | ||
1727 | 83 | @brief unnamed namespace with internal helper functions | ||
1728 | 84 | @since version 1.0.0 | ||
1729 | 85 | */ | ||
1730 | 86 | namespace | ||
1731 | 87 | { | ||
1732 | 88 | /*! | ||
1733 | 89 | @brief Helper to determine whether there's a key_type for T. | ||
1734 | 90 | @sa http://stackoverflow.com/a/7728728/266378 | ||
1735 | 91 | */ | ||
1736 | 92 | template<typename T> | ||
1737 | 93 | struct has_mapped_type | ||
1738 | 94 | { | ||
1739 | 95 | private: | ||
1740 | 96 | template<typename C> static char test(typename C::mapped_type*); | ||
1741 | 97 | template<typename C> static int test(...); | ||
1742 | 98 | public: | ||
1743 | 99 | enum { value = sizeof(test<T>(0)) == sizeof(char) }; | ||
1744 | 100 | }; | ||
1745 | 101 | |||
1746 | 102 | /// "equality" comparison for floating point numbers | ||
1747 | 103 | template<typename T> | ||
1748 | 104 | static bool approx(const T a, const T b) | ||
1749 | 105 | { | ||
1750 | 106 | return not (a > b or a < b); | ||
1751 | 107 | } | ||
1752 | 108 | } | ||
1753 | 109 | |||
1754 | 110 | /*! | ||
1755 | 111 | @brief a class to store JSON values | ||
1756 | 112 | |||
1757 | 113 | @tparam ObjectType type for JSON objects (@c std::map by default; will be used | ||
1758 | 114 | in @ref object_t) | ||
1759 | 115 | @tparam ArrayType type for JSON arrays (@c std::vector by default; will be used | ||
1760 | 116 | in @ref array_t) | ||
1761 | 117 | @tparam StringType type for JSON strings and object keys (@c std::string by | ||
1762 | 118 | default; will be used in @ref string_t) | ||
1763 | 119 | @tparam BooleanType type for JSON booleans (@c `bool` by default; will be used | ||
1764 | 120 | in @ref boolean_t) | ||
1765 | 121 | @tparam NumberIntegerType type for JSON integer numbers (@c `int64_t` by | ||
1766 | 122 | default; will be used in @ref number_integer_t) | ||
1767 | 123 | @tparam NumberFloatType type for JSON floating-point numbers (@c `double` by | ||
1768 | 124 | default; will be used in @ref number_float_t) | ||
1769 | 125 | @tparam AllocatorType type of the allocator to use (@c `std::allocator` by | ||
1770 | 126 | default) | ||
1771 | 127 | |||
1772 | 128 | @requirement The class satisfies the following concept requirements: | ||
1773 | 129 | - Basic | ||
1774 | 130 | - [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible): | ||
1775 | 131 | JSON values can be default constructed. The result will be a JSON null value. | ||
1776 | 132 | - [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible): | ||
1777 | 133 | A JSON value can be constructed from an rvalue argument. | ||
1778 | 134 | - [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible): | ||
1779 | 135 | A JSON value can be copy-constrcuted from an lvalue expression. | ||
1780 | 136 | - [MoveAssignable](http://en.cppreference.com/w/cpp/concept/MoveAssignable): | ||
1781 | 137 | A JSON value van be assigned from an rvalue argument. | ||
1782 | 138 | - [CopyAssignable](http://en.cppreference.com/w/cpp/concept/CopyAssignable): | ||
1783 | 139 | A JSON value can be copy-assigned from an lvalue expression. | ||
1784 | 140 | - [Destructible](http://en.cppreference.com/w/cpp/concept/Destructible): | ||
1785 | 141 | JSON values can be destructed. | ||
1786 | 142 | - Layout | ||
1787 | 143 | - [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType): | ||
1788 | 144 | JSON values have | ||
1789 | 145 | [standard layout](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout): | ||
1790 | 146 | All non-static data members are private and standard layout types, the class | ||
1791 | 147 | has no virtual functions or (virtual) base classes. | ||
1792 | 148 | - Library-wide | ||
1793 | 149 | - [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable): | ||
1794 | 150 | JSON values can be compared with `==`, see @ref | ||
1795 | 151 | operator==(const_reference,const_reference). | ||
1796 | 152 | - [LessThanComparable](http://en.cppreference.com/w/cpp/concept/LessThanComparable): | ||
1797 | 153 | JSON values can be compared with `<`, see @ref | ||
1798 | 154 | operator<(const_reference,const_reference). | ||
1799 | 155 | - [Swappable](http://en.cppreference.com/w/cpp/concept/Swappable): | ||
1800 | 156 | Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of | ||
1801 | 157 | other compatible types, using unqualified function call @ref swap(). | ||
1802 | 158 | - [NullablePointer](http://en.cppreference.com/w/cpp/concept/NullablePointer): | ||
1803 | 159 | JSON values can be compared against `std::nullptr_t` objects which are used | ||
1804 | 160 | to model the `null` value. | ||
1805 | 161 | - Container | ||
1806 | 162 | - [Container](http://en.cppreference.com/w/cpp/concept/Container): | ||
1807 | 163 | JSON values can be used like STL containers and provide iterator access. | ||
1808 | 164 | - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer); | ||
1809 | 165 | JSON values can be used like STL containers and provide reverse iterator | ||
1810 | 166 | access. | ||
1811 | 167 | |||
1812 | 168 | @internal | ||
1813 | 169 | @note ObjectType trick from http://stackoverflow.com/a/9860911 | ||
1814 | 170 | @endinternal | ||
1815 | 171 | |||
1816 | 172 | @see RFC 7159 <http://rfc7159.net/rfc7159> | ||
1817 | 173 | |||
1818 | 174 | @since version 1.0.0 | ||
1819 | 175 | |||
1820 | 176 | @nosubgrouping | ||
1821 | 177 | */ | ||
1822 | 178 | template < | ||
1823 | 179 | template<typename U, typename V, typename... Args> class ObjectType = std::map, | ||
1824 | 180 | template<typename U, typename... Args> class ArrayType = std::vector, | ||
1825 | 181 | class StringType = std::string, | ||
1826 | 182 | class BooleanType = bool, | ||
1827 | 183 | class NumberIntegerType = int64_t, | ||
1828 | 184 | class NumberFloatType = double, | ||
1829 | 185 | template<typename U> class AllocatorType = std::allocator | ||
1830 | 186 | > | ||
1831 | 187 | class basic_json | ||
1832 | 188 | { | ||
1833 | 189 | private: | ||
1834 | 190 | /// workaround type for MSVC | ||
1835 | 191 | using basic_json_t = basic_json<ObjectType, | ||
1836 | 192 | ArrayType, | ||
1837 | 193 | StringType, | ||
1838 | 194 | BooleanType, | ||
1839 | 195 | NumberIntegerType, | ||
1840 | 196 | NumberFloatType, | ||
1841 | 197 | AllocatorType>; | ||
1842 | 198 | |||
1843 | 199 | public: | ||
1844 | 200 | |||
1845 | 201 | ///////////////////// | ||
1846 | 202 | // container types // | ||
1847 | 203 | ///////////////////// | ||
1848 | 204 | |||
1849 | 205 | /// @name container types | ||
1850 | 206 | /// @{ | ||
1851 | 207 | |||
1852 | 208 | /// the type of elements in a basic_json container | ||
1853 | 209 | using value_type = basic_json; | ||
1854 | 210 | |||
1855 | 211 | /// the type of an element reference | ||
1856 | 212 | using reference = value_type&; | ||
1857 | 213 | |||
1858 | 214 | /// the type of an element const reference | ||
1859 | 215 | using const_reference = const value_type&; | ||
1860 | 216 | |||
1861 | 217 | /// a type to represent differences between iterators | ||
1862 | 218 | using difference_type = std::ptrdiff_t; | ||
1863 | 219 | |||
1864 | 220 | /// a type to represent container sizes | ||
1865 | 221 | using size_type = std::size_t; | ||
1866 | 222 | |||
1867 | 223 | /// the allocator type | ||
1868 | 224 | using allocator_type = AllocatorType<basic_json>; | ||
1869 | 225 | |||
1870 | 226 | /// the type of an element pointer | ||
1871 | 227 | using pointer = typename std::allocator_traits<allocator_type>::pointer; | ||
1872 | 228 | /// the type of an element const pointer | ||
1873 | 229 | using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer; | ||
1874 | 230 | |||
1875 | 231 | // forward declaration | ||
1876 | 232 | template<typename Base> class json_reverse_iterator; | ||
1877 | 233 | |||
1878 | 234 | /// an iterator for a basic_json container | ||
1879 | 235 | class iterator; | ||
1880 | 236 | /// a const iterator for a basic_json container | ||
1881 | 237 | class const_iterator; | ||
1882 | 238 | /// a reverse iterator for a basic_json container | ||
1883 | 239 | using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>; | ||
1884 | 240 | /// a const reverse iterator for a basic_json container | ||
1885 | 241 | using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>; | ||
1886 | 242 | |||
1887 | 243 | /// @} | ||
1888 | 244 | |||
1889 | 245 | |||
1890 | 246 | /*! | ||
1891 | 247 | @brief returns the allocator associated with the container | ||
1892 | 248 | */ | ||
1893 | 249 | static allocator_type get_allocator() | ||
1894 | 250 | { | ||
1895 | 251 | return allocator_type(); | ||
1896 | 252 | } | ||
1897 | 253 | |||
1898 | 254 | |||
1899 | 255 | /////////////////////////// | ||
1900 | 256 | // JSON value data types // | ||
1901 | 257 | /////////////////////////// | ||
1902 | 258 | |||
1903 | 259 | /// @name JSON value data types | ||
1904 | 260 | /// @{ | ||
1905 | 261 | |||
1906 | 262 | /*! | ||
1907 | 263 | @brief a type for an object | ||
1908 | 264 | |||
1909 | 265 | [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows: | ||
1910 | 266 | > An object is an unordered collection of zero or more name/value pairs, | ||
1911 | 267 | > where a name is a string and a value is a string, number, boolean, null, | ||
1912 | 268 | > object, or array. | ||
1913 | 269 | |||
1914 | 270 | To store objects in C++, a type is defined by the template parameters | ||
1915 | 271 | described below. | ||
1916 | 272 | |||
1917 | 273 | @tparam ObjectType the container to store objects (e.g., `std::map` or | ||
1918 | 274 | `std::unordered_map`) | ||
1919 | 275 | @tparam StringType the type of the keys or names (e.g., `std::string`). The | ||
1920 | 276 | comparison function `std::less<StringType>` is used to order elements | ||
1921 | 277 | inside the container. | ||
1922 | 278 | @tparam AllocatorType the allocator to use for objects (e.g., | ||
1923 | 279 | `std::allocator`) | ||
1924 | 280 | |||
1925 | 281 | #### Default type | ||
1926 | 282 | |||
1927 | 283 | With the default values for @a ObjectType (`std::map`), @a StringType | ||
1928 | 284 | (`std::string`), and @a AllocatorType (`std::allocator`), the default value | ||
1929 | 285 | for @a object_t is: | ||
1930 | 286 | |||
1931 | 287 | @code {.cpp} | ||
1932 | 288 | std::map< | ||
1933 | 289 | std::string, // key_type | ||
1934 | 290 | basic_json, // value_type | ||
1935 | 291 | std::less<std::string>, // key_compare | ||
1936 | 292 | std::allocator<std::pair<const std::string, basic_json>> // allocator_type | ||
1937 | 293 | > | ||
1938 | 294 | @endcode | ||
1939 | 295 | |||
1940 | 296 | #### Behavior | ||
1941 | 297 | |||
1942 | 298 | The choice of @a object_t influences the behavior of the JSON class. With | ||
1943 | 299 | the default type, objects have the following behavior: | ||
1944 | 300 | |||
1945 | 301 | - When all names are unique, objects will be interoperable in the sense | ||
1946 | 302 | that all software implementations receiving that object will agree on the | ||
1947 | 303 | name-value mappings. | ||
1948 | 304 | - When the names within an object are not unique, later stored name/value | ||
1949 | 305 | pairs overwrite previously stored name/value pairs, leaving the used | ||
1950 | 306 | names unique. For instance, `{"key": 1}` and `{"key": 2, "key": 1}` will | ||
1951 | 307 | be treated as equal and both stored as `{"key": 1}`. | ||
1952 | 308 | - Internally, name/value pairs are stored in lexicographical order of the | ||
1953 | 309 | names. Objects will also be serialized (see @ref dump) in this order. For | ||
1954 | 310 | instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored and | ||
1955 | 311 | serialized as `{"a": 2, "b": 1}`. | ||
1956 | 312 | - When comparing objects, the order of the name/value pairs is irrelevant. | ||
1957 | 313 | This makes objects interoperable in the sense that they will not be | ||
1958 | 314 | affected by these differences. For instance, `{"b": 1, "a": 2}` and | ||
1959 | 315 | `{"a": 2, "b": 1}` will be treated as equal. | ||
1960 | 316 | |||
1961 | 317 | #### Limits | ||
1962 | 318 | |||
1963 | 319 | [RFC 7159](http://rfc7159.net/rfc7159) specifies: | ||
1964 | 320 | > An implementation may set limits on the maximum depth of nesting. | ||
1965 | 321 | |||
1966 | 322 | In this class, the object's limit of nesting is not constraint explicitly. | ||
1967 | 323 | However, a maximum depth of nesting may be introduced by the compiler or | ||
1968 | 324 | runtime environment. A theoretical limit can be queried by calling the @ref | ||
1969 | 325 | max_size function of a JSON object. | ||
1970 | 326 | |||
1971 | 327 | #### Storage | ||
1972 | 328 | |||
1973 | 329 | Objects are stored as pointers in a @ref basic_json type. That is, for any | ||
1974 | 330 | access to object values, a pointer of type `object_t*` must be dereferenced. | ||
1975 | 331 | |||
1976 | 332 | @sa @ref array_t -- type for an array value | ||
1977 | 333 | |||
1978 | 334 | @since version 1.0.0 | ||
1979 | 335 | */ | ||
1980 | 336 | using object_t = ObjectType<StringType, | ||
1981 | 337 | basic_json, | ||
1982 | 338 | std::less<StringType>, | ||
1983 | 339 | AllocatorType<std::pair<const StringType, | ||
1984 | 340 | basic_json>>>; | ||
1985 | 341 | |||
1986 | 342 | /*! | ||
1987 | 343 | @brief a type for an array | ||
1988 | 344 | |||
1989 | 345 | [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows: | ||
1990 | 346 | > An array is an ordered sequence of zero or more values. | ||
1991 | 347 | |||
1992 | 348 | To store objects in C++, a type is defined by the template parameters | ||
1993 | 349 | explained below. | ||
1994 | 350 | |||
1995 | 351 | @tparam ArrayType container type to store arrays (e.g., `std::vector` or | ||
1996 | 352 | `std::list`) | ||
1997 | 353 | @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`) | ||
1998 | 354 | |||
1999 | 355 | #### Default type | ||
2000 | 356 | |||
2001 | 357 | With the default values for @a ArrayType (`std::vector`) and @a | ||
2002 | 358 | AllocatorType (`std::allocator`), the default value for @a array_t is: | ||
2003 | 359 | |||
2004 | 360 | @code {.cpp} | ||
2005 | 361 | std::vector< | ||
2006 | 362 | basic_json, // value_type | ||
2007 | 363 | std::allocator<basic_json> // allocator_type | ||
2008 | 364 | > | ||
2009 | 365 | @endcode | ||
2010 | 366 | |||
2011 | 367 | #### Limits | ||
2012 | 368 | |||
2013 | 369 | [RFC 7159](http://rfc7159.net/rfc7159) specifies: | ||
2014 | 370 | > An implementation may set limits on the maximum depth of nesting. | ||
2015 | 371 | |||
2016 | 372 | In this class, the array's limit of nesting is not constraint explicitly. | ||
2017 | 373 | However, a maximum depth of nesting may be introduced by the compiler or | ||
2018 | 374 | runtime environment. A theoretical limit can be queried by calling the @ref | ||
2019 | 375 | max_size function of a JSON array. | ||
2020 | 376 | |||
2021 | 377 | #### Storage | ||
2022 | 378 | |||
2023 | 379 | Arrays are stored as pointers in a @ref basic_json type. That is, for any | ||
2024 | 380 | access to array values, a pointer of type `array_t*` must be dereferenced. | ||
2025 | 381 | |||
2026 | 382 | @sa @ref object_t -- type for an object value | ||
2027 | 383 | |||
2028 | 384 | @since version 1.0.0 | ||
2029 | 385 | */ | ||
2030 | 386 | using array_t = ArrayType<basic_json, AllocatorType<basic_json>>; | ||
2031 | 387 | |||
2032 | 388 | /*! | ||
2033 | 389 | @brief a type for a string | ||
2034 | 390 | |||
2035 | 391 | [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows: | ||
2036 | 392 | > A string is a sequence of zero or more Unicode characters. | ||
2037 | 393 | |||
2038 | 394 | To store objects in C++, a type is defined by the template parameter | ||
2039 | 395 | described below. Unicode values are split by the JSON class into byte-sized | ||
2040 | 396 | characters during deserialization. | ||
2041 | 397 | |||
2042 | 398 | @tparam StringType the container to store strings (e.g., `std::string`). | ||
2043 | 399 | Note this container is used for keys/names in objects, see @ref object_t. | ||
2044 | 400 | |||
2045 | 401 | #### Default type | ||
2046 | 402 | |||
2047 | 403 | With the default values for @a StringType (`std::string`), the default | ||
2048 | 404 | value for @a string_t is: | ||
2049 | 405 | |||
2050 | 406 | @code {.cpp} | ||
2051 | 407 | std::string | ||
2052 | 408 | @endcode | ||
2053 | 409 | |||
2054 | 410 | #### String comparison | ||
2055 | 411 | |||
2056 | 412 | [RFC 7159](http://rfc7159.net/rfc7159) states: | ||
2057 | 413 | > Software implementations are typically required to test names of object | ||
2058 | 414 | > members for equality. Implementations that transform the textual | ||
2059 | 415 | > representation into sequences of Unicode code units and then perform the | ||
2060 | 416 | > comparison numerically, code unit by code unit, are interoperable in the | ||
2061 | 417 | > sense that implementations will agree in all cases on equality or | ||
2062 | 418 | > inequality of two strings. For example, implementations that compare | ||
2063 | 419 | > strings with escaped characters unconverted may incorrectly find that | ||
2064 | 420 | > `"a\\b"` and `"a\u005Cb"` are not equal. | ||
2065 | 421 | |||
2066 | 422 | This implementation is interoperable as it does compare strings code unit | ||
2067 | 423 | by code unit. | ||
2068 | 424 | |||
2069 | 425 | #### Storage | ||
2070 | 426 | |||
2071 | 427 | String values are stored as pointers in a @ref basic_json type. That is, | ||
2072 | 428 | for any access to string values, a pointer of type `string_t*` must be | ||
2073 | 429 | dereferenced. | ||
2074 | 430 | |||
2075 | 431 | @since version 1.0.0 | ||
2076 | 432 | */ | ||
2077 | 433 | using string_t = StringType; | ||
2078 | 434 | |||
2079 | 435 | /*! | ||
2080 | 436 | @brief a type for a boolean | ||
2081 | 437 | |||
2082 | 438 | [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a | ||
2083 | 439 | type which differentiates the two literals `true` and `false`. | ||
2084 | 440 | |||
2085 | 441 | To store objects in C++, a type is defined by the template parameter @a | ||
2086 | 442 | BooleanType which chooses the type to use. | ||
2087 | 443 | |||
2088 | 444 | #### Default type | ||
2089 | 445 | |||
2090 | 446 | With the default values for @a BooleanType (`bool`), the default value for | ||
2091 | 447 | @a boolean_t is: | ||
2092 | 448 | |||
2093 | 449 | @code {.cpp} | ||
2094 | 450 | bool | ||
2095 | 451 | @endcode | ||
2096 | 452 | |||
2097 | 453 | #### Storage | ||
2098 | 454 | |||
2099 | 455 | Boolean values are stored directly inside a @ref basic_json type. | ||
2100 | 456 | |||
2101 | 457 | @since version 1.0.0 | ||
2102 | 458 | */ | ||
2103 | 459 | using boolean_t = BooleanType; | ||
2104 | 460 | |||
2105 | 461 | /*! | ||
2106 | 462 | @brief a type for a number (integer) | ||
2107 | 463 | |||
2108 | 464 | [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: | ||
2109 | 465 | > The representation of numbers is similar to that used in most programming | ||
2110 | 466 | > languages. A number is represented in base 10 using decimal digits. It | ||
2111 | 467 | > contains an integer component that may be prefixed with an optional minus | ||
2112 | 468 | > sign, which may be followed by a fraction part and/or an exponent part. | ||
2113 | 469 | > Leading zeros are not allowed. (...) Numeric values that cannot be | ||
2114 | 470 | > represented in the grammar below (such as Infinity and NaN) are not | ||
2115 | 471 | > permitted. | ||
2116 | 472 | |||
2117 | 473 | This description includes both integer and floating-point numbers. However, | ||
2118 | 474 | C++ allows more precise storage if it is known whether the number is an | ||
2119 | 475 | integer or a floating-point number. Therefore, two different types, @ref | ||
2120 | 476 | number_integer_t and @ref number_float_t are used. | ||
2121 | 477 | |||
2122 | 478 | To store integer numbers in C++, a type is defined by the template | ||
2123 | 479 | parameter @a NumberIntegerType which chooses the type to use. | ||
2124 | 480 | |||
2125 | 481 | #### Default type | ||
2126 | 482 | |||
2127 | 483 | With the default values for @a NumberIntegerType (`int64_t`), the default | ||
2128 | 484 | value for @a number_integer_t is: | ||
2129 | 485 | |||
2130 | 486 | @code {.cpp} | ||
2131 | 487 | int64_t | ||
2132 | 488 | @endcode | ||
2133 | 489 | |||
2134 | 490 | #### Default behavior | ||
2135 | 491 | |||
2136 | 492 | - The restrictions about leading zeros is not enforced in C++. Instead, | ||
2137 | 493 | leading zeros in integer literals lead to an interpretation as octal | ||
2138 | 494 | number. Internally, the value will be stored as decimal number. For | ||
2139 | 495 | instance, the C++ integer literal `010` will be serialized to `8`. During | ||
2140 | 496 | deserialization, leading zeros yield an error. | ||
2141 | 497 | - Not-a-number (NaN) values will be serialized to `null`. | ||
2142 | 498 | |||
2143 | 499 | #### Limits | ||
2144 | 500 | |||
2145 | 501 | [RFC 7159](http://rfc7159.net/rfc7159) specifies: | ||
2146 | 502 | > An implementation may set limits on the range and precision of numbers. | ||
2147 | 503 | |||
2148 | 504 | When the default type is used, the maximal integer number that can be | ||
2149 | 505 | stored is `9223372036854775807` (INT64_MAX) and the minimal integer number | ||
2150 | 506 | that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers | ||
2151 | 507 | that are out of range will yield over/underflow when used in a constructor. | ||
2152 | 508 | During deserialization, too large or small integer numbers will be | ||
2153 | 509 | automatically be stored as @ref number_float_t. | ||
2154 | 510 | |||
2155 | 511 | [RFC 7159](http://rfc7159.net/rfc7159) further states: | ||
2156 | 512 | > Note that when such software is used, numbers that are integers and are | ||
2157 | 513 | > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense | ||
2158 | 514 | > that implementations will agree exactly on their numeric values. | ||
2159 | 515 | |||
2160 | 516 | As this range is a subrange of the exactly supported range [INT64_MIN, | ||
2161 | 517 | INT64_MAX], this class's integer type is interoperable. | ||
2162 | 518 | |||
2163 | 519 | #### Storage | ||
2164 | 520 | |||
2165 | 521 | Integer number values are stored directly inside a @ref basic_json type. | ||
2166 | 522 | |||
2167 | 523 | @sa @ref number_float_t -- type for number values (floating-point) | ||
2168 | 524 | |||
2169 | 525 | @since version 1.0.0 | ||
2170 | 526 | */ | ||
2171 | 527 | using number_integer_t = NumberIntegerType; | ||
2172 | 528 | |||
2173 | 529 | /*! | ||
2174 | 530 | @brief a type for a number (floating-point) | ||
2175 | 531 | |||
2176 | 532 | [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: | ||
2177 | 533 | > The representation of numbers is similar to that used in most programming | ||
2178 | 534 | > languages. A number is represented in base 10 using decimal digits. It | ||
2179 | 535 | > contains an integer component that may be prefixed with an optional minus | ||
2180 | 536 | > sign, which may be followed by a fraction part and/or an exponent part. | ||
2181 | 537 | > Leading zeros are not allowed. (...) Numeric values that cannot be | ||
2182 | 538 | > represented in the grammar below (such as Infinity and NaN) are not | ||
2183 | 539 | > permitted. | ||
2184 | 540 | |||
2185 | 541 | This description includes both integer and floating-point numbers. However, | ||
2186 | 542 | C++ allows more precise storage if it is known whether the number is an | ||
2187 | 543 | integer or a floating-point number. Therefore, two different types, @ref | ||
2188 | 544 | number_integer_t and @ref number_float_t are used. | ||
2189 | 545 | |||
2190 | 546 | To store floating-point numbers in C++, a type is defined by the template | ||
2191 | 547 | parameter @a NumberFloatType which chooses the type to use. | ||
2192 | 548 | |||
2193 | 549 | #### Default type | ||
2194 | 550 | |||
2195 | 551 | With the default values for @a NumberFloatType (`double`), the default | ||
2196 | 552 | value for @a number_float_t is: | ||
2197 | 553 | |||
2198 | 554 | @code {.cpp} | ||
2199 | 555 | double | ||
2200 | 556 | @endcode | ||
2201 | 557 | |||
2202 | 558 | #### Default behavior | ||
2203 | 559 | |||
2204 | 560 | - The restrictions about leading zeros is not enforced in C++. Instead, | ||
2205 | 561 | leading zeros in floating-point literals will be ignored. Internally, the | ||
2206 | 562 | value will be stored as decimal number. For instance, the C++ | ||
2207 | 563 | floating-point literal `01.2` will be serialized to `1.2`. During | ||
2208 | 564 | deserialization, leading zeros yield an error. | ||
2209 | 565 | - Not-a-number (NaN) values will be serialized to `null`. | ||
2210 | 566 | |||
2211 | 567 | #### Limits | ||
2212 | 568 | |||
2213 | 569 | [RFC 7159](http://rfc7159.net/rfc7159) states: | ||
2214 | 570 | > This specification allows implementations to set limits on the range and | ||
2215 | 571 | > precision of numbers accepted. Since software that implements IEEE | ||
2216 | 572 | > 754-2008 binary64 (double precision) numbers is generally available and | ||
2217 | 573 | > widely used, good interoperability can be achieved by implementations that | ||
2218 | 574 | > expect no more precision or range than these provide, in the sense that | ||
2219 | 575 | > implementations will approximate JSON numbers within the expected | ||
2220 | 576 | > precision. | ||
2221 | 577 | |||
2222 | 578 | This implementation does exactly follow this approach, as it uses double | ||
2223 | 579 | precision floating-point numbers. Note values smaller than | ||
2224 | 580 | `-1.79769313486232e+308` and values greather than `1.79769313486232e+308` | ||
2225 | 581 | will be stored as NaN internally and be serialized to `null`. | ||
2226 | 582 | |||
2227 | 583 | #### Storage | ||
2228 | 584 | |||
2229 | 585 | Floating-point number values are stored directly inside a @ref basic_json | ||
2230 | 586 | type. | ||
2231 | 587 | |||
2232 | 588 | @sa @ref number_integer_t -- type for number values (integer) | ||
2233 | 589 | |||
2234 | 590 | @since version 1.0.0 | ||
2235 | 591 | */ | ||
2236 | 592 | using number_float_t = NumberFloatType; | ||
2237 | 593 | |||
2238 | 594 | /// @} | ||
2239 | 595 | |||
2240 | 596 | |||
2241 | 597 | /////////////////////////// | ||
2242 | 598 | // JSON type enumeration // | ||
2243 | 599 | /////////////////////////// | ||
2244 | 600 | |||
2245 | 601 | /*! | ||
2246 | 602 | @brief the JSON type enumeration | ||
2247 | 603 | |||
2248 | 604 | This enumeration collects the different JSON types. It is internally used | ||
2249 | 605 | to distinguish the stored values, and the functions @ref is_null(), @ref | ||
2250 | 606 | is_object(), @ref is_array(), @ref is_string(), @ref is_boolean(), @ref | ||
2251 | 607 | is_number(), and @ref is_discarded() rely on it. | ||
2252 | 608 | |||
2253 | 609 | @since version 1.0.0 | ||
2254 | 610 | */ | ||
2255 | 611 | enum class value_t : uint8_t | ||
2256 | 612 | { | ||
2257 | 613 | null, ///< null value | ||
2258 | 614 | object, ///< object (unordered set of name/value pairs) | ||
2259 | 615 | array, ///< array (ordered collection of values) | ||
2260 | 616 | string, ///< string value | ||
2261 | 617 | boolean, ///< boolean value | ||
2262 | 618 | number_integer, ///< number value (integer) | ||
2263 | 619 | number_float, ///< number value (floating-point) | ||
2264 | 620 | discarded ///< discarded by the the parser callback function | ||
2265 | 621 | }; | ||
2266 | 622 | |||
2267 | 623 | |||
2268 | 624 | private: | ||
2269 | 625 | /// helper for exception-safe object creation | ||
2270 | 626 | template<typename T, typename... Args> | ||
2271 | 627 | static T* create(Args&& ... args) | ||
2272 | 628 | { | ||
2273 | 629 | AllocatorType<T> alloc; | ||
2274 | 630 | auto deleter = [&](T * object) | ||
2275 | 631 | { | ||
2276 | 632 | alloc.deallocate(object, 1); | ||
2277 | 633 | }; | ||
2278 | 634 | std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter); | ||
2279 | 635 | alloc.construct(object.get(), std::forward<Args>(args)...); | ||
2280 | 636 | return object.release(); | ||
2281 | 637 | } | ||
2282 | 638 | |||
2283 | 639 | //////////////////////// | ||
2284 | 640 | // JSON value storage // | ||
2285 | 641 | //////////////////////// | ||
2286 | 642 | |||
2287 | 643 | /*! | ||
2288 | 644 | @brief a JSON value | ||
2289 | 645 | |||
2290 | 646 | The actual storage for a JSON value of the @ref basic_json class. | ||
2291 | 647 | |||
2292 | 648 | @since version 1.0.0 | ||
2293 | 649 | */ | ||
2294 | 650 | union json_value | ||
2295 | 651 | { | ||
2296 | 652 | /// object (stored with pointer to save storage) | ||
2297 | 653 | object_t* object; | ||
2298 | 654 | /// array (stored with pointer to save storage) | ||
2299 | 655 | array_t* array; | ||
2300 | 656 | /// string (stored with pointer to save storage) | ||
2301 | 657 | string_t* string; | ||
2302 | 658 | /// boolean | ||
2303 | 659 | boolean_t boolean; | ||
2304 | 660 | /// number (integer) | ||
2305 | 661 | number_integer_t number_integer; | ||
2306 | 662 | /// number (floating-point) | ||
2307 | 663 | number_float_t number_float; | ||
2308 | 664 | |||
2309 | 665 | /// default constructor (for null values) | ||
2310 | 666 | json_value() noexcept = default; | ||
2311 | 667 | /// constructor for booleans | ||
2312 | 668 | json_value(boolean_t v) noexcept : boolean(v) {} | ||
2313 | 669 | /// constructor for numbers (integer) | ||
2314 | 670 | json_value(number_integer_t v) noexcept : number_integer(v) {} | ||
2315 | 671 | /// constructor for numbers (floating-point) | ||
2316 | 672 | json_value(number_float_t v) noexcept : number_float(v) {} | ||
2317 | 673 | /// constructor for empty values of a given type | ||
2318 | 674 | json_value(value_t t) | ||
2319 | 675 | { | ||
2320 | 676 | switch (t) | ||
2321 | 677 | { | ||
2322 | 678 | case value_t::object: | ||
2323 | 679 | { | ||
2324 | 680 | object = create<object_t>(); | ||
2325 | 681 | break; | ||
2326 | 682 | } | ||
2327 | 683 | |||
2328 | 684 | case value_t::array: | ||
2329 | 685 | { | ||
2330 | 686 | array = create<array_t>(); | ||
2331 | 687 | break; | ||
2332 | 688 | } | ||
2333 | 689 | |||
2334 | 690 | case value_t::string: | ||
2335 | 691 | { | ||
2336 | 692 | string = create<string_t>(""); | ||
2337 | 693 | break; | ||
2338 | 694 | } | ||
2339 | 695 | |||
2340 | 696 | case value_t::boolean: | ||
2341 | 697 | { | ||
2342 | 698 | boolean = boolean_t(false); | ||
2343 | 699 | break; | ||
2344 | 700 | } | ||
2345 | 701 | |||
2346 | 702 | case value_t::number_integer: | ||
2347 | 703 | { | ||
2348 | 704 | number_integer = number_integer_t(0); | ||
2349 | 705 | break; | ||
2350 | 706 | } | ||
2351 | 707 | |||
2352 | 708 | case value_t::number_float: | ||
2353 | 709 | { | ||
2354 | 710 | number_float = number_float_t(0.0); | ||
2355 | 711 | break; | ||
2356 | 712 | } | ||
2357 | 713 | |||
2358 | 714 | default: | ||
2359 | 715 | { | ||
2360 | 716 | break; | ||
2361 | 717 | } | ||
2362 | 718 | } | ||
2363 | 719 | } | ||
2364 | 720 | |||
2365 | 721 | /// constructor for strings | ||
2366 | 722 | json_value(const string_t& value) | ||
2367 | 723 | { | ||
2368 | 724 | string = create<string_t>(value); | ||
2369 | 725 | } | ||
2370 | 726 | |||
2371 | 727 | /// constructor for objects | ||
2372 | 728 | json_value(const object_t& value) | ||
2373 | 729 | { | ||
2374 | 730 | object = create<object_t>(value); | ||
2375 | 731 | } | ||
2376 | 732 | |||
2377 | 733 | /// constructor for arrays | ||
2378 | 734 | json_value(const array_t& value) | ||
2379 | 735 | { | ||
2380 | 736 | array = create<array_t>(value); | ||
2381 | 737 | } | ||
2382 | 738 | }; | ||
2383 | 739 | |||
2384 | 740 | |||
2385 | 741 | public: | ||
2386 | 742 | ////////////////////////// | ||
2387 | 743 | // JSON parser callback // | ||
2388 | 744 | ////////////////////////// | ||
2389 | 745 | |||
2390 | 746 | /*! | ||
2391 | 747 | @brief JSON callback events | ||
2392 | 748 | |||
2393 | 749 | This enumeration lists the parser events that can trigger calling a | ||
2394 | 750 | callback function of type @ref parser_callback_t during parsing. | ||
2395 | 751 | |||
2396 | 752 | @since version 1.0.0 | ||
2397 | 753 | */ | ||
2398 | 754 | enum class parse_event_t : uint8_t | ||
2399 | 755 | { | ||
2400 | 756 | /// the parser read `{` and started to process a JSON object | ||
2401 | 757 | object_start, | ||
2402 | 758 | /// the parser read `}` and finished processing a JSON object | ||
2403 | 759 | object_end, | ||
2404 | 760 | /// the parser read `[` and started to process a JSON array | ||
2405 | 761 | array_start, | ||
2406 | 762 | /// the parser read `]` and finished processing a JSON array | ||
2407 | 763 | array_end, | ||
2408 | 764 | /// the parser read a key of a value in an object | ||
2409 | 765 | key, | ||
2410 | 766 | /// the parser finished reading a JSON value | ||
2411 | 767 | value | ||
2412 | 768 | }; | ||
2413 | 769 | |||
2414 | 770 | /*! | ||
2415 | 771 | @brief per-element parser callback type | ||
2416 | 772 | |||
2417 | 773 | With a parser callback function, the result of parsing a JSON text can be | ||
2418 | 774 | influenced. When passed to @ref parse(std::istream&, parser_callback_t) or | ||
2419 | 775 | @ref parse(const string_t&, parser_callback_t), it is called on certain | ||
2420 | 776 | events (passed as @ref parse_event_t via parameter @a event) with a set | ||
2421 | 777 | recursion depth @a depth and context JSON value @a parsed. The return value | ||
2422 | 778 | of the callback function is a boolean indicating whether the element that | ||
2423 | 779 | emitted the callback shall be kept or not. | ||
2424 | 780 | |||
2425 | 781 | We distinguish six scenarios (determined by the event type) in which the | ||
2426 | 782 | callback function can be called. The following table describes the values | ||
2427 | 783 | of the parameters @a depth, @a event, and @a parsed. | ||
2428 | 784 | |||
2429 | 785 | parameter @a event | description | parameter @a depth | parameter @a parsed | ||
2430 | 786 | ------------------ | ----------- | ------------------ | ------------------- | ||
2431 | 787 | parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded | ||
2432 | 788 | parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key | ||
2433 | 789 | parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object | ||
2434 | 790 | parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded | ||
2435 | 791 | parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array | ||
2436 | 792 | parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value | ||
2437 | 793 | |||
2438 | 794 | Discarding a value (i.e., returning `false`) has different effects | ||
2439 | 795 | depending on the context in which function was called: | ||
2440 | 796 | |||
2441 | 797 | - Discarded values in structured types are skipped. That is, the parser | ||
2442 | 798 | will behave as if the discarded value was never read. | ||
2443 | 799 | - In case a value outside a structured type is skipped, it is replaced with | ||
2444 | 800 | `null`. This case happens if the top-level element is skipped. | ||
2445 | 801 | |||
2446 | 802 | @param[in] depth the depth of the recursion during parsing | ||
2447 | 803 | |||
2448 | 804 | @param[in] event an event of type parse_event_t indicating the context in | ||
2449 | 805 | the callback function has been called | ||
2450 | 806 | |||
2451 | 807 | @param[in,out] parsed the current intermediate parse result; note that | ||
2452 | 808 | writing to this value has no effect for parse_event_t::key events | ||
2453 | 809 | |||
2454 | 810 | @return Whether the JSON value which called the function during parsing | ||
2455 | 811 | should be kept (`true`) or not (`false`). In the latter case, it is either | ||
2456 | 812 | skipped completely or replaced by an empty discarded object. | ||
2457 | 813 | |||
2458 | 814 | @sa @ref parse(std::istream&, parser_callback_t) or | ||
2459 | 815 | @ref parse(const string_t&, parser_callback_t) for examples | ||
2460 | 816 | |||
2461 | 817 | @since version 1.0.0 | ||
2462 | 818 | */ | ||
2463 | 819 | using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>; | ||
2464 | 820 | |||
2465 | 821 | |||
2466 | 822 | ////////////////// | ||
2467 | 823 | // constructors // | ||
2468 | 824 | ////////////////// | ||
2469 | 825 | |||
2470 | 826 | /// @name constructors and destructors | ||
2471 | 827 | /// @{ | ||
2472 | 828 | |||
2473 | 829 | /*! | ||
2474 | 830 | @brief create an empty value with a given type | ||
2475 | 831 | |||
2476 | 832 | Create an empty JSON value with a given type. The value will be default | ||
2477 | 833 | initialized with an empty value which depends on the type: | ||
2478 | 834 | |||
2479 | 835 | Value type | initial value | ||
2480 | 836 | ----------- | ------------- | ||
2481 | 837 | null | `null` | ||
2482 | 838 | boolean | `false` | ||
2483 | 839 | string | `""` | ||
2484 | 840 | number | `0` | ||
2485 | 841 | object | `{}` | ||
2486 | 842 | array | `[]` | ||
2487 | 843 | |||
2488 | 844 | @param[in] value_type the type of the value to create | ||
2489 | 845 | |||
2490 | 846 | @complexity Constant. | ||
2491 | 847 | |||
2492 | 848 | @throw std::bad_alloc if allocation for object, array, or string value | ||
2493 | 849 | fails | ||
2494 | 850 | |||
2495 | 851 | @liveexample{The following code shows the constructor for different @ref | ||
2496 | 852 | value_t values,basic_json__value_t} | ||
2497 | 853 | |||
2498 | 854 | @sa @ref basic_json(std::nullptr_t) -- create a `null` value | ||
2499 | 855 | @sa @ref basic_json(boolean_t value) -- create a boolean value | ||
2500 | 856 | @sa @ref basic_json(const string_t&) -- create a string value | ||
2501 | 857 | @sa @ref basic_json(const object_t&) -- create a object value | ||
2502 | 858 | @sa @ref basic_json(const array_t&) -- create a array value | ||
2503 | 859 | @sa @ref basic_json(const number_float_t) -- create a number | ||
2504 | 860 | (floating-point) value | ||
2505 | 861 | @sa @ref basic_json(const number_integer_t) -- create a number (integer) | ||
2506 | 862 | value | ||
2507 | 863 | |||
2508 | 864 | @since version 1.0.0 | ||
2509 | 865 | */ | ||
2510 | 866 | basic_json(const value_t value_type) | ||
2511 | 867 | : m_type(value_type), m_value(value_type) | ||
2512 | 868 | {} | ||
2513 | 869 | |||
2514 | 870 | /*! | ||
2515 | 871 | @brief create a null object (implicitly) | ||
2516 | 872 | |||
2517 | 873 | Create a `null` JSON value. This is the implicit version of the `null` | ||
2518 | 874 | value constructor as it takes no parameters. | ||
2519 | 875 | |||
2520 | 876 | @complexity Constant. | ||
2521 | 877 | |||
2522 | 878 | @requirement This function satisfies the Container requirements: | ||
2523 | 879 | - The complexity is constant. | ||
2524 | 880 | - As postcondition, it holds: `basic_json().empty() == true`. | ||
2525 | 881 | |||
2526 | 882 | @liveexample{The following code shows the constructor for a `null` JSON | ||
2527 | 883 | value.,basic_json} | ||
2528 | 884 | |||
2529 | 885 | @sa @ref basic_json(std::nullptr_t) -- create a `null` value | ||
2530 | 886 | |||
2531 | 887 | @since version 1.0.0 | ||
2532 | 888 | */ | ||
2533 | 889 | basic_json() noexcept = default; | ||
2534 | 890 | |||
2535 | 891 | /*! | ||
2536 | 892 | @brief create a null object (explicitly) | ||
2537 | 893 | |||
2538 | 894 | Create a `null` JSON value. This is the explicitly version of the `null` | ||
2539 | 895 | value constructor as it takes a null pointer as parameter. It allows to | ||
2540 | 896 | create `null` values by explicitly assigning a @c nullptr to a JSON value. | ||
2541 | 897 | The passed null pointer itself is not read -- it is only used to choose the | ||
2542 | 898 | right constructor. | ||
2543 | 899 | |||
2544 | 900 | @complexity Constant. | ||
2545 | 901 | |||
2546 | 902 | @liveexample{The following code shows the constructor with null pointer | ||
2547 | 903 | parameter.,basic_json__nullptr_t} | ||
2548 | 904 | |||
2549 | 905 | @sa @ref basic_json() -- default constructor (implicitly creating a `null` | ||
2550 | 906 | value) | ||
2551 | 907 | |||
2552 | 908 | @since version 1.0.0 | ||
2553 | 909 | */ | ||
2554 | 910 | basic_json(std::nullptr_t) noexcept | ||
2555 | 911 | : basic_json(value_t::null) | ||
2556 | 912 | {} | ||
2557 | 913 | |||
2558 | 914 | /*! | ||
2559 | 915 | @brief create an object (explicit) | ||
2560 | 916 | |||
2561 | 917 | Create an object JSON value with a given content. | ||
2562 | 918 | |||
2563 | 919 | @param[in] val a value for the object | ||
2564 | 920 | |||
2565 | 921 | @complexity Linear in the size of the passed @a val. | ||
2566 | 922 | |||
2567 | 923 | @throw std::bad_alloc if allocation for object value fails | ||
2568 | 924 | |||
2569 | 925 | @liveexample{The following code shows the constructor with an @ref object_t | ||
2570 | 926 | parameter.,basic_json__object_t} | ||
2571 | 927 | |||
2572 | 928 | @sa @ref basic_json(const CompatibleObjectType&) -- create an object value | ||
2573 | 929 | from a compatible STL container | ||
2574 | 930 | |||
2575 | 931 | @since version 1.0.0 | ||
2576 | 932 | */ | ||
2577 | 933 | basic_json(const object_t& val) | ||
2578 | 934 | : m_type(value_t::object), m_value(val) | ||
2579 | 935 | {} | ||
2580 | 936 | |||
2581 | 937 | /*! | ||
2582 | 938 | @brief create an object (implicit) | ||
2583 | 939 | |||
2584 | 940 | Create an object JSON value with a given content. This constructor allows | ||
2585 | 941 | any type that can be used to construct values of type @ref object_t. | ||
2586 | 942 | Examples include the types `std::map` and `std::unordered_map`. | ||
2587 | 943 | |||
2588 | 944 | @tparam CompatibleObjectType an object type whose `key_type` and | ||
2589 | 945 | `value_type` is compatible to @ref object_t | ||
2590 | 946 | |||
2591 | 947 | @param[in] val a value for the object | ||
2592 | 948 | |||
2593 | 949 | @complexity Linear in the size of the passed @a val. | ||
2594 | 950 | |||
2595 | 951 | @throw std::bad_alloc if allocation for object value fails | ||
2596 | 952 | |||
2597 | 953 | @liveexample{The following code shows the constructor with several | ||
2598 | 954 | compatible object type parameters.,basic_json__CompatibleObjectType} | ||
2599 | 955 | |||
2600 | 956 | @sa @ref basic_json(const object_t&) -- create an object value | ||
2601 | 957 | |||
2602 | 958 | @since version 1.0.0 | ||
2603 | 959 | */ | ||
2604 | 960 | template <class CompatibleObjectType, typename | ||
2605 | 961 | std::enable_if< | ||
2606 | 962 | std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and | ||
2607 | 963 | std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type | ||
2608 | 964 | = 0> | ||
2609 | 965 | basic_json(const CompatibleObjectType& val) | ||
2610 | 966 | : m_type(value_t::object) | ||
2611 | 967 | { | ||
2612 | 968 | using std::begin; | ||
2613 | 969 | using std::end; | ||
2614 | 970 | m_value.object = create<object_t>(begin(val), end(val)); | ||
2615 | 971 | } | ||
2616 | 972 | |||
2617 | 973 | /*! | ||
2618 | 974 | @brief create an array (explicit) | ||
2619 | 975 | |||
2620 | 976 | Create an array JSON value with a given content. | ||
2621 | 977 | |||
2622 | 978 | @param[in] val a value for the array | ||
2623 | 979 | |||
2624 | 980 | @complexity Linear in the size of the passed @a val. | ||
2625 | 981 | |||
2626 | 982 | @throw std::bad_alloc if allocation for array value fails | ||
2627 | 983 | |||
2628 | 984 | @liveexample{The following code shows the constructor with an @ref array_t | ||
2629 | 985 | parameter.,basic_json__array_t} | ||
2630 | 986 | |||
2631 | 987 | @sa @ref basic_json(const CompatibleArrayType&) -- create an array value | ||
2632 | 988 | from a compatible STL containers | ||
2633 | 989 | |||
2634 | 990 | @since version 1.0.0 | ||
2635 | 991 | */ | ||
2636 | 992 | basic_json(const array_t& val) | ||
2637 | 993 | : m_type(value_t::array), m_value(val) | ||
2638 | 994 | {} | ||
2639 | 995 | |||
2640 | 996 | /*! | ||
2641 | 997 | @brief create an array (implicit) | ||
2642 | 998 | |||
2643 | 999 | Create an array JSON value with a given content. This constructor allows | ||
2644 | 1000 | any type that can be used to construct values of type @ref array_t. | ||
2645 | 1001 | Examples include the types `std::vector`, `std::list`, and `std::set`. | ||
2646 | 1002 | |||
2647 | 1003 | @tparam CompatibleArrayType an object type whose `value_type` is compatible | ||
2648 | 1004 | to @ref array_t | ||
2649 | 1005 | |||
2650 | 1006 | @param[in] val a value for the array | ||
2651 | 1007 | |||
2652 | 1008 | @complexity Linear in the size of the passed @a val. | ||
2653 | 1009 | |||
2654 | 1010 | @throw std::bad_alloc if allocation for array value fails | ||
2655 | 1011 | |||
2656 | 1012 | @liveexample{The following code shows the constructor with several | ||
2657 | 1013 | compatible array type parameters.,basic_json__CompatibleArrayType} | ||
2658 | 1014 | |||
2659 | 1015 | @sa @ref basic_json(const array_t&) -- create an array value | ||
2660 | 1016 | |||
2661 | 1017 | @since version 1.0.0 | ||
2662 | 1018 | */ | ||
2663 | 1019 | template <class CompatibleArrayType, typename | ||
2664 | 1020 | std::enable_if< | ||
2665 | 1021 | not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and | ||
2666 | 1022 | not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and | ||
2667 | 1023 | not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and | ||
2668 | 1024 | not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and | ||
2669 | 1025 | not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and | ||
2670 | 1026 | not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and | ||
2671 | 1027 | std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type | ||
2672 | 1028 | = 0> | ||
2673 | 1029 | basic_json(const CompatibleArrayType& val) | ||
2674 | 1030 | : m_type(value_t::array) | ||
2675 | 1031 | { | ||
2676 | 1032 | using std::begin; | ||
2677 | 1033 | using std::end; | ||
2678 | 1034 | m_value.array = create<array_t>(begin(val), end(val)); | ||
2679 | 1035 | } | ||
2680 | 1036 | |||
2681 | 1037 | /*! | ||
2682 | 1038 | @brief create a string (explicit) | ||
2683 | 1039 | |||
2684 | 1040 | Create an string JSON value with a given content. | ||
2685 | 1041 | |||
2686 | 1042 | @param[in] val a value for the string | ||
2687 | 1043 | |||
2688 | 1044 | @complexity Linear in the size of the passed @a val. | ||
2689 | 1045 | |||
2690 | 1046 | @throw std::bad_alloc if allocation for string value fails | ||
2691 | 1047 | |||
2692 | 1048 | @liveexample{The following code shows the constructor with an @ref string_t | ||
2693 | 1049 | parameter.,basic_json__string_t} | ||
2694 | 1050 | |||
2695 | 1051 | @sa @ref basic_json(const typename string_t::value_type*) -- create a | ||
2696 | 1052 | string value from a character pointer | ||
2697 | 1053 | @sa @ref basic_json(const CompatibleStringType&) -- create a string value | ||
2698 | 1054 | from a compatible string container | ||
2699 | 1055 | |||
2700 | 1056 | @since version 1.0.0 | ||
2701 | 1057 | */ | ||
2702 | 1058 | basic_json(const string_t& val) | ||
2703 | 1059 | : m_type(value_t::string), m_value(val) | ||
2704 | 1060 | {} | ||
2705 | 1061 | |||
2706 | 1062 | /*! | ||
2707 | 1063 | @brief create a string (explicit) | ||
2708 | 1064 | |||
2709 | 1065 | Create a string JSON value with a given content. | ||
2710 | 1066 | |||
2711 | 1067 | @param[in] val a literal value for the string | ||
2712 | 1068 | |||
2713 | 1069 | @complexity Linear in the size of the passed @a val. | ||
2714 | 1070 | |||
2715 | 1071 | @throw std::bad_alloc if allocation for string value fails | ||
2716 | 1072 | |||
2717 | 1073 | @liveexample{The following code shows the constructor with string literal | ||
2718 | 1074 | parameter.,basic_json__string_t_value_type} | ||
2719 | 1075 | |||
2720 | 1076 | @sa @ref basic_json(const string_t&) -- create a string value | ||
2721 | 1077 | @sa @ref basic_json(const CompatibleStringType&) -- create a string value | ||
2722 | 1078 | from a compatible string container | ||
2723 | 1079 | |||
2724 | 1080 | @since version 1.0.0 | ||
2725 | 1081 | */ | ||
2726 | 1082 | basic_json(const typename string_t::value_type* val) | ||
2727 | 1083 | : basic_json(string_t(val)) | ||
2728 | 1084 | {} | ||
2729 | 1085 | |||
2730 | 1086 | /*! | ||
2731 | 1087 | @brief create a string (implicit) | ||
2732 | 1088 | |||
2733 | 1089 | Create a string JSON value with a given content. | ||
2734 | 1090 | |||
2735 | 1091 | @param[in] val a value for the string | ||
2736 | 1092 | |||
2737 | 1093 | @tparam CompatibleStringType an string type which is compatible to @ref | ||
2738 | 1094 | string_t | ||
2739 | 1095 | |||
2740 | 1096 | @complexity Linear in the size of the passed @a val. | ||
2741 | 1097 | |||
2742 | 1098 | @throw std::bad_alloc if allocation for string value fails | ||
2743 | 1099 | |||
2744 | 1100 | @liveexample{The following code shows the construction of a string value | ||
2745 | 1101 | from a compatible type.,basic_json__CompatibleStringType} | ||
2746 | 1102 | |||
2747 | 1103 | @sa @ref basic_json(const string_t&) -- create a string value | ||
2748 | 1104 | @sa @ref basic_json(const typename string_t::value_type*) -- create a | ||
2749 | 1105 | string value from a character pointer | ||
2750 | 1106 | |||
2751 | 1107 | @since version 1.0.0 | ||
2752 | 1108 | */ | ||
2753 | 1109 | template <class CompatibleStringType, typename | ||
2754 | 1110 | std::enable_if< | ||
2755 | 1111 | std::is_constructible<string_t, CompatibleStringType>::value, int>::type | ||
2756 | 1112 | = 0> | ||
2757 | 1113 | basic_json(const CompatibleStringType& val) | ||
2758 | 1114 | : basic_json(string_t(val)) | ||
2759 | 1115 | {} | ||
2760 | 1116 | |||
2761 | 1117 | /*! | ||
2762 | 1118 | @brief create a boolean (explicit) | ||
2763 | 1119 | |||
2764 | 1120 | Creates a JSON boolean type from a given value. | ||
2765 | 1121 | |||
2766 | 1122 | @param[in] val a boolean value to store | ||
2767 | 1123 | |||
2768 | 1124 | @complexity Constant. | ||
2769 | 1125 | |||
2770 | 1126 | @liveexample{The example below demonstrates boolean | ||
2771 | 1127 | values.,basic_json__boolean_t} | ||
2772 | 1128 | |||
2773 | 1129 | @since version 1.0.0 | ||
2774 | 1130 | */ | ||
2775 | 1131 | basic_json(boolean_t val) | ||
2776 | 1132 | : m_type(value_t::boolean), m_value(val) | ||
2777 | 1133 | {} | ||
2778 | 1134 | |||
2779 | 1135 | /*! | ||
2780 | 1136 | @brief create an integer number (explicit) | ||
2781 | 1137 | |||
2782 | 1138 | Create an interger number JSON value with a given content. | ||
2783 | 1139 | |||
2784 | 1140 | @tparam T helper type to compare number_integer_t and int (not visible in) | ||
2785 | 1141 | the interface. | ||
2786 | 1142 | |||
2787 | 1143 | @param[in] val an integer to create a JSON number from | ||
2788 | 1144 | |||
2789 | 1145 | @note This constructor would have the same signature as @ref | ||
2790 | 1146 | basic_json(const int value), so we need to switch this one off in case | ||
2791 | 1147 | number_integer_t is the same as int. This is done via the helper type @a T. | ||
2792 | 1148 | |||
2793 | 1149 | @complexity Constant. | ||
2794 | 1150 | |||
2795 | 1151 | @liveexample{The example below shows the construction of a JSON integer | ||
2796 | 1152 | number value.,basic_json__number_integer_t} | ||
2797 | 1153 | |||
2798 | 1154 | @sa @ref basic_json(const int) -- create a number value (integer) | ||
2799 | 1155 | @sa @ref basic_json(const CompatibleNumberIntegerType) -- create a number | ||
2800 | 1156 | value (integer) from a compatible number type | ||
2801 | 1157 | |||
2802 | 1158 | @since version 1.0.0 | ||
2803 | 1159 | */ | ||
2804 | 1160 | template<typename T, | ||
2805 | 1161 | typename std::enable_if< | ||
2806 | 1162 | not (std::is_same<T, int>::value) | ||
2807 | 1163 | and std::is_same<T, number_integer_t>::value | ||
2808 | 1164 | , int>::type = 0> | ||
2809 | 1165 | basic_json(const number_integer_t val) | ||
2810 | 1166 | : m_type(value_t::number_integer), m_value(val) | ||
2811 | 1167 | {} | ||
2812 | 1168 | |||
2813 | 1169 | /*! | ||
2814 | 1170 | @brief create an integer number from an enum type (explicit) | ||
2815 | 1171 | |||
2816 | 1172 | Create an integer number JSON value with a given content. | ||
2817 | 1173 | |||
2818 | 1174 | @param[in] val an integer to create a JSON number from | ||
2819 | 1175 | |||
2820 | 1176 | @note This constructor allows to pass enums directly to a constructor. As | ||
2821 | 1177 | C++ has no way of specifying the type of an anonymous enum explicitly, we | ||
2822 | 1178 | can only rely on the fact that such values implicitly convert to int. As | ||
2823 | 1179 | int may already be the same type of number_integer_t, we may need to switch | ||
2824 | 1180 | off the constructor @ref basic_json(const number_integer_t). | ||
2825 | 1181 | |||
2826 | 1182 | @complexity Constant. | ||
2827 | 1183 | |||
2828 | 1184 | @liveexample{The example below shows the construction of a JSON integer | ||
2829 | 1185 | number value from an anonymous enum.,basic_json__const_int} | ||
2830 | 1186 | |||
2831 | 1187 | @sa @ref basic_json(const number_integer_t) -- create a number value | ||
2832 | 1188 | (integer) | ||
2833 | 1189 | @sa @ref basic_json(const CompatibleNumberIntegerType) -- create a number | ||
2834 | 1190 | value (integer) from a compatible number type | ||
2835 | 1191 | |||
2836 | 1192 | @since version 1.0.0 | ||
2837 | 1193 | */ | ||
2838 | 1194 | basic_json(const int val) | ||
2839 | 1195 | : m_type(value_t::number_integer), | ||
2840 | 1196 | m_value(static_cast<number_integer_t>(val)) | ||
2841 | 1197 | {} | ||
2842 | 1198 | |||
2843 | 1199 | /*! | ||
2844 | 1200 | @brief create an integer number (implicit) | ||
2845 | 1201 | |||
2846 | 1202 | Create an integer number JSON value with a given content. This constructor | ||
2847 | 1203 | allows any type that can be used to construct values of type @ref | ||
2848 | 1204 | number_integer_t. Examples may include the types `int`, `int32_t`, or | ||
2849 | 1205 | `short`. | ||
2850 | 1206 | |||
2851 | 1207 | @tparam CompatibleNumberIntegerType an integer type which is compatible to | ||
2852 | 1208 | @ref number_integer_t. | ||
2853 | 1209 | |||
2854 | 1210 | @param[in] val an integer to create a JSON number from | ||
2855 | 1211 | |||
2856 | 1212 | @complexity Constant. | ||
2857 | 1213 | |||
2858 | 1214 | @liveexample{The example below shows the construction of several JSON | ||
2859 | 1215 | integer number values from compatible | ||
2860 | 1216 | types.,basic_json__CompatibleIntegerNumberType} | ||
2861 | 1217 | |||
2862 | 1218 | @sa @ref basic_json(const number_integer_t) -- create a number value | ||
2863 | 1219 | (integer) | ||
2864 | 1220 | @sa @ref basic_json(const int) -- create a number value (integer) | ||
2865 | 1221 | |||
2866 | 1222 | @since version 1.0.0 | ||
2867 | 1223 | */ | ||
2868 | 1224 | template<typename CompatibleNumberIntegerType, typename | ||
2869 | 1225 | std::enable_if< | ||
2870 | 1226 | std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and | ||
2871 | 1227 | std::numeric_limits<CompatibleNumberIntegerType>::is_integer, CompatibleNumberIntegerType>::type | ||
2872 | 1228 | = 0> | ||
2873 | 1229 | basic_json(const CompatibleNumberIntegerType val) noexcept | ||
2874 | 1230 | : m_type(value_t::number_integer), | ||
2875 | 1231 | m_value(static_cast<number_integer_t>(val)) | ||
2876 | 1232 | {} | ||
2877 | 1233 | |||
2878 | 1234 | /*! | ||
2879 | 1235 | @brief create a floating-point number (explicit) | ||
2880 | 1236 | |||
2881 | 1237 | Create a floating-point number JSON value with a given content. | ||
2882 | 1238 | |||
2883 | 1239 | @param[in] val a floating-point value to create a JSON number from | ||
2884 | 1240 | |||
2885 | 1241 | @note RFC 7159 <http://www.rfc-editor.org/rfc/rfc7159.txt>, section 6 | ||
2886 | 1242 | disallows NaN values: | ||
2887 | 1243 | > Numeric values that cannot be represented in the grammar below (such | ||
2888 | 1244 | > as Infinity and NaN) are not permitted. | ||
2889 | 1245 | In case the parameter @a val is not a number, a JSON null value is | ||
2890 | 1246 | created instead. | ||
2891 | 1247 | |||
2892 | 1248 | @complexity Constant. | ||
2893 | 1249 | |||
2894 | 1250 | @liveexample{The following example creates several floating-point | ||
2895 | 1251 | values.,basic_json__number_float_t} | ||
2896 | 1252 | |||
2897 | 1253 | @sa @ref basic_json(const CompatibleNumberFloatType) -- create a number | ||
2898 | 1254 | value (floating-point) from a compatible number type | ||
2899 | 1255 | |||
2900 | 1256 | @since version 1.0.0 | ||
2901 | 1257 | */ | ||
2902 | 1258 | basic_json(const number_float_t val) | ||
2903 | 1259 | : m_type(value_t::number_float), m_value(val) | ||
2904 | 1260 | { | ||
2905 | 1261 | // replace infinity and NAN by null | ||
2906 | 1262 | if (not std::isfinite(val)) | ||
2907 | 1263 | { | ||
2908 | 1264 | m_type = value_t::null; | ||
2909 | 1265 | m_value = json_value(); | ||
2910 | 1266 | } | ||
2911 | 1267 | } | ||
2912 | 1268 | |||
2913 | 1269 | /*! | ||
2914 | 1270 | @brief create an floating-point number (implicit) | ||
2915 | 1271 | |||
2916 | 1272 | Create an floating-point number JSON value with a given content. This | ||
2917 | 1273 | constructor allows any type that can be used to construct values of type | ||
2918 | 1274 | @ref number_float_t. Examples may include the types `float`. | ||
2919 | 1275 | |||
2920 | 1276 | @tparam CompatibleNumberFloatType a floating-point type which is compatible | ||
2921 | 1277 | to @ref number_float_t. | ||
2922 | 1278 | |||
2923 | 1279 | @param[in] val a floating-point to create a JSON number from | ||
2924 | 1280 | |||
2925 | 1281 | @note RFC 7159 <http://www.rfc-editor.org/rfc/rfc7159.txt>, section 6 | ||
2926 | 1282 | disallows NaN values: | ||
2927 | 1283 | > Numeric values that cannot be represented in the grammar below (such | ||
2928 | 1284 | > as Infinity and NaN) are not permitted. | ||
2929 | 1285 | In case the parameter @a val is not a number, a JSON null value is | ||
2930 | 1286 | created instead. | ||
2931 | 1287 | |||
2932 | 1288 | @complexity Constant. | ||
2933 | 1289 | |||
2934 | 1290 | @liveexample{The example below shows the construction of several JSON | ||
2935 | 1291 | floating-point number values from compatible | ||
2936 | 1292 | types.,basic_json__CompatibleNumberFloatType} | ||
2937 | 1293 | |||
2938 | 1294 | @sa @ref basic_json(const number_float_t) -- create a number value | ||
2939 | 1295 | (floating-point) | ||
2940 | 1296 | |||
2941 | 1297 | @since version 1.0.0 | ||
2942 | 1298 | */ | ||
2943 | 1299 | template<typename CompatibleNumberFloatType, typename = typename | ||
2944 | 1300 | std::enable_if< | ||
2945 | 1301 | std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and | ||
2946 | 1302 | std::is_floating_point<CompatibleNumberFloatType>::value>::type | ||
2947 | 1303 | > | ||
2948 | 1304 | basic_json(const CompatibleNumberFloatType val) noexcept | ||
2949 | 1305 | : basic_json(number_float_t(val)) | ||
2950 | 1306 | {} | ||
2951 | 1307 | |||
2952 | 1308 | /*! | ||
2953 | 1309 | @brief create a container (array or object) from an initializer list | ||
2954 | 1310 | |||
2955 | 1311 | Creates a JSON value of type array or object from the passed initializer | ||
2956 | 1312 | list @a init. In case @a type_deduction is `true` (default), the type of | ||
2957 | 1313 | the JSON value to be created is deducted from the initializer list @a init | ||
2958 | 1314 | according to the following rules: | ||
2959 | 1315 | |||
2960 | 1316 | 1. If the list is empty, an empty JSON object value `{}` is created. | ||
2961 | 1317 | 2. If the list consists of pairs whose first element is a string, a JSON | ||
2962 | 1318 | object value is created where the first elements of the pairs are treated | ||
2963 | 1319 | as keys and the second elements are as values. | ||
2964 | 1320 | 3. In all other cases, an array is created. | ||
2965 | 1321 | |||
2966 | 1322 | The rules aim to create the best fit between a C++ initializer list and | ||
2967 | 1323 | JSON values. The ratioinale is as follows: | ||
2968 | 1324 | |||
2969 | 1325 | 1. The empty initializer list is written as `{}` which is exactly an empty | ||
2970 | 1326 | JSON object. | ||
2971 | 1327 | 2. C++ has now way of describing mapped types other than to list a list of | ||
2972 | 1328 | pairs. As JSON requires that keys must be of type string, rule 2 is the | ||
2973 | 1329 | weakest constraint one can pose on initializer lists to interpret them as | ||
2974 | 1330 | an object. | ||
2975 | 1331 | 3. In all other cases, the initializer list could not be interpreted as | ||
2976 | 1332 | JSON object type, so interpreting it as JSON array type is safe. | ||
2977 | 1333 | |||
2978 | 1334 | With the rules described above, the following JSON values cannot be | ||
2979 | 1335 | expressed by an initializer list: | ||
2980 | 1336 | |||
2981 | 1337 | - the empty array (`[]`): use @ref array(std::initializer_list<basic_json>) | ||
2982 | 1338 | with an empty initializer list in this case | ||
2983 | 1339 | - arrays whose elements satisfy rule 2: use @ref | ||
2984 | 1340 | array(std::initializer_list<basic_json>) with the same initializer list | ||
2985 | 1341 | in this case | ||
2986 | 1342 | |||
2987 | 1343 | @note When used without parentheses around an empty initializer list, @ref | ||
2988 | 1344 | basic_json() is called instead of this function, yielding the JSON null | ||
2989 | 1345 | value. | ||
2990 | 1346 | |||
2991 | 1347 | @param[in] init initializer list with JSON values | ||
2992 | 1348 | |||
2993 | 1349 | @param[in] type_deduction internal parameter; when set to `true`, the type | ||
2994 | 1350 | of the JSON value is deducted from the initializer list @a init; when set | ||
2995 | 1351 | to `false`, the type provided via @a manual_type is forced. This mode is | ||
2996 | 1352 | used by the functions @ref array(std::initializer_list<basic_json>) and | ||
2997 | 1353 | @ref object(std::initializer_list<basic_json>). | ||
2998 | 1354 | |||
2999 | 1355 | @param[in] manual_type internal parameter; when @a type_deduction is set to | ||
3000 | 1356 | `false`, the created JSON value will use the provided type (only @ref | ||
3001 | 1357 | value_t::array and @ref value_t::object are valid); when @a type_deduction | ||
3002 | 1358 | is set to `true`, this parameter has no effect | ||
3003 | 1359 | |||
3004 | 1360 | @throw std::domain_error if @a type_deduction is `false`, @a manual_type is | ||
3005 | 1361 | `value_t::object`, but @a init contains an element which is not a pair | ||
3006 | 1362 | whose first element is a string; example: `"cannot create object from | ||
3007 | 1363 | initializer list"` | ||
3008 | 1364 | |||
3009 | 1365 | @complexity Linear in the size of the initializer list @a init. | ||
3010 | 1366 | |||
3011 | 1367 | @liveexample{The example below shows how JSON values are created from | ||
3012 | 1368 | initializer lists,basic_json__list_init_t} | ||
3013 | 1369 | |||
3014 | 1370 | @sa @ref array(std::initializer_list<basic_json>) -- create a JSON array | ||
3015 | 1371 | value from an initializer list | ||
3016 | 1372 | @sa @ref object(std::initializer_list<basic_json>) -- create a JSON object | ||
3017 | 1373 | value from an initializer list | ||
3018 | 1374 | |||
3019 | 1375 | @since version 1.0.0 | ||
3020 | 1376 | */ | ||
3021 | 1377 | basic_json(std::initializer_list<basic_json> init, | ||
3022 | 1378 | bool type_deduction = true, | ||
3023 | 1379 | value_t manual_type = value_t::array) | ||
3024 | 1380 | { | ||
3025 | 1381 | // the initializer list could describe an object | ||
3026 | 1382 | bool is_an_object = true; | ||
3027 | 1383 | |||
3028 | 1384 | // check if each element is an array with two elements whose first | ||
3029 | 1385 | // element is a string | ||
3030 | 1386 | for (const auto& element : init) | ||
3031 | 1387 | { | ||
3032 | 1388 | if (not element.is_array() or element.size() != 2 | ||
3033 | 1389 | or not element[0].is_string()) | ||
3034 | 1390 | { | ||
3035 | 1391 | // we found an element that makes it impossible to use the | ||
3036 | 1392 | // initializer list as object | ||
3037 | 1393 | is_an_object = false; | ||
3038 | 1394 | break; | ||
3039 | 1395 | } | ||
3040 | 1396 | } | ||
3041 | 1397 | |||
3042 | 1398 | // adjust type if type deduction is not wanted | ||
3043 | 1399 | if (not type_deduction) | ||
3044 | 1400 | { | ||
3045 | 1401 | // if array is wanted, do not create an object though possible | ||
3046 | 1402 | if (manual_type == value_t::array) | ||
3047 | 1403 | { | ||
3048 | 1404 | is_an_object = false; | ||
3049 | 1405 | } | ||
3050 | 1406 | |||
3051 | 1407 | // if object is wanted but impossible, throw an exception | ||
3052 | 1408 | if (manual_type == value_t::object and not is_an_object) | ||
3053 | 1409 | { | ||
3054 | 1410 | throw std::domain_error("cannot create object from initializer list"); | ||
3055 | 1411 | } | ||
3056 | 1412 | } | ||
3057 | 1413 | |||
3058 | 1414 | if (is_an_object) | ||
3059 | 1415 | { | ||
3060 | 1416 | // the initializer list is a list of pairs -> create object | ||
3061 | 1417 | m_type = value_t::object; | ||
3062 | 1418 | m_value = value_t::object; | ||
3063 | 1419 | |||
3064 | 1420 | for (auto& element : init) | ||
3065 | 1421 | { | ||
3066 | 1422 | m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1])); | ||
3067 | 1423 | } | ||
3068 | 1424 | } | ||
3069 | 1425 | else | ||
3070 | 1426 | { | ||
3071 | 1427 | // the initializer list describes an array -> create array | ||
3072 | 1428 | m_type = value_t::array; | ||
3073 | 1429 | m_value.array = create<array_t>(std::move(init)); | ||
3074 | 1430 | } | ||
3075 | 1431 | } | ||
3076 | 1432 | |||
3077 | 1433 | /*! | ||
3078 | 1434 | @brief explicitly create an array from an initializer list | ||
3079 | 1435 | |||
3080 | 1436 | Creates a JSON array value from a given initializer list. That is, given a | ||
3081 | 1437 | list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the | ||
3082 | 1438 | initializer list is empty, the empty array `[]` is created. | ||
3083 | 1439 | |||
3084 | 1440 | @note This function is only needed to express two edge cases that cannot be | ||
3085 | 1441 | realized with the initializer list constructor (@ref | ||
3086 | 1442 | basic_json(std::initializer_list<basic_json>, bool, value_t)). These cases | ||
3087 | 1443 | are: | ||
3088 | 1444 | 1. creating an array whose elements are all pairs whose first element is a | ||
3089 | 1445 | string -- in this case, the initializer list constructor would create an | ||
3090 | 1446 | object, taking the first elements as keys | ||
3091 | 1447 | 2. creating an empty array -- passing the empty initializer list to the | ||
3092 | 1448 | initializer list constructor yields an empty object | ||
3093 | 1449 | |||
3094 | 1450 | @param[in] init initializer list with JSON values to create an array from | ||
3095 | 1451 | (optional) | ||
3096 | 1452 | |||
3097 | 1453 | @return JSON array value | ||
3098 | 1454 | |||
3099 | 1455 | @complexity Linear in the size of @a init. | ||
3100 | 1456 | |||
3101 | 1457 | @liveexample{The following code shows an example for the @ref array | ||
3102 | 1458 | function.,array} | ||
3103 | 1459 | |||
3104 | 1460 | @sa @ref basic_json(std::initializer_list<basic_json>, bool, value_t) -- | ||
3105 | 1461 | create a JSON value from an initializer list | ||
3106 | 1462 | @sa @ref object(std::initializer_list<basic_json>) -- create a JSON object | ||
3107 | 1463 | value from an initializer list | ||
3108 | 1464 | |||
3109 | 1465 | @since version 1.0.0 | ||
3110 | 1466 | */ | ||
3111 | 1467 | static basic_json array(std::initializer_list<basic_json> init = | ||
3112 | 1468 | std::initializer_list<basic_json>()) | ||
3113 | 1469 | { | ||
3114 | 1470 | return basic_json(init, false, value_t::array); | ||
3115 | 1471 | } | ||
3116 | 1472 | |||
3117 | 1473 | /*! | ||
3118 | 1474 | @brief explicitly create an object from an initializer list | ||
3119 | 1475 | |||
3120 | 1476 | Creates a JSON object value from a given initializer list. The initializer | ||
3121 | 1477 | lists elements must be pairs, and their first elments must be strings. If | ||
3122 | 1478 | the initializer list is empty, the empty object `{}` is created. | ||
3123 | 1479 | |||
3124 | 1480 | @note This function is only added for symmetry reasons. In contrast to the | ||
3125 | 1481 | related function @ref array(std::initializer_list<basic_json>), there are | ||
3126 | 1482 | no cases which can only be expressed by this function. That is, any | ||
3127 | 1483 | initializer list @a init can also be passed to the initializer list | ||
3128 | 1484 | constructor | ||
3129 | 1485 | @ref basic_json(std::initializer_list<basic_json>, bool, value_t). | ||
3130 | 1486 | |||
3131 | 1487 | @param[in] init initializer list to create an object from (optional) | ||
3132 | 1488 | |||
3133 | 1489 | @return JSON object value | ||
3134 | 1490 | |||
3135 | 1491 | @throw std::domain_error if @a init is not a pair whose first elements are | ||
3136 | 1492 | strings; thrown by | ||
3137 | 1493 | @ref basic_json(std::initializer_list<basic_json>, bool, value_t) | ||
3138 | 1494 | |||
3139 | 1495 | @complexity Linear in the size of @a init. | ||
3140 | 1496 | |||
3141 | 1497 | @liveexample{The following code shows an example for the @ref object | ||
3142 | 1498 | function.,object} | ||
3143 | 1499 | |||
3144 | 1500 | @sa @ref basic_json(std::initializer_list<basic_json>, bool, value_t) -- | ||
3145 | 1501 | create a JSON value from an initializer list | ||
3146 | 1502 | @sa @ref array(std::initializer_list<basic_json>) -- create a JSON array | ||
3147 | 1503 | value from an initializer list | ||
3148 | 1504 | |||
3149 | 1505 | @since version 1.0.0 | ||
3150 | 1506 | */ | ||
3151 | 1507 | static basic_json object(std::initializer_list<basic_json> init = | ||
3152 | 1508 | std::initializer_list<basic_json>()) | ||
3153 | 1509 | { | ||
3154 | 1510 | return basic_json(init, false, value_t::object); | ||
3155 | 1511 | } | ||
3156 | 1512 | |||
3157 | 1513 | /*! | ||
3158 | 1514 | @brief construct an array with count copies of given value | ||
3159 | 1515 | |||
3160 | 1516 | Constructs a JSON array value by creating @a cnt copies of a passed | ||
3161 | 1517 | value. In case @a cnt is `0`, an empty array is created. As postcondition, | ||
3162 | 1518 | `std::distance(begin(),end()) == cnt` holds. | ||
3163 | 1519 | |||
3164 | 1520 | @param[in] cnt the number of JSON copies of @a val to create | ||
3165 | 1521 | @param[in] val the JSON value to copy | ||
3166 | 1522 | |||
3167 | 1523 | @complexity Linear in @a cnt. | ||
3168 | 1524 | |||
3169 | 1525 | @liveexample{The following code shows examples for the @ref | ||
3170 | 1526 | basic_json(size_type\, const basic_json&) | ||
3171 | 1527 | constructor.,basic_json__size_type_basic_json} | ||
3172 | 1528 | |||
3173 | 1529 | @since version 1.0.0 | ||
3174 | 1530 | */ | ||
3175 | 1531 | basic_json(size_type cnt, const basic_json& val) | ||
3176 | 1532 | : m_type(value_t::array) | ||
3177 | 1533 | { | ||
3178 | 1534 | m_value.array = create<array_t>(cnt, val); | ||
3179 | 1535 | } | ||
3180 | 1536 | |||
3181 | 1537 | /*! | ||
3182 | 1538 | @brief construct a JSON container given an iterator range | ||
3183 | 1539 | |||
3184 | 1540 | Constructs the JSON value with the contents of the range `[first, last)`. | ||
3185 | 1541 | The semantics depends on the different types a JSON value can have: | ||
3186 | 1542 | - In case of primitive types (number, boolean, or string), @a first must | ||
3187 | 1543 | be `begin()` and @a last must be `end()`. In this case, the value is | ||
3188 | 1544 | copied. Otherwise, std::out_of_range is thrown. | ||
3189 | 1545 | - In case of structured types (array, object), the constructor behaves | ||
3190 | 1546 | as similar versions for `std::vector`. | ||
3191 | 1547 | - In case of a null type, std::domain_error is thrown. | ||
3192 | 1548 | |||
3193 | 1549 | @tparam InputIT an input iterator type (@ref iterator or @ref | ||
3194 | 1550 | const_iterator) | ||
3195 | 1551 | |||
3196 | 1552 | @param[in] first begin of the range to copy from (included) | ||
3197 | 1553 | @param[in] last end of the range to copy from (excluded) | ||
3198 | 1554 | |||
3199 | 1555 | @throw std::domain_error if iterators are not compatible; that is, do not | ||
3200 | 1556 | belong to the same JSON value; example: `"iterators are not compatible"` | ||
3201 | 1557 | @throw std::out_of_range if iterators are for a primitive type (number, | ||
3202 | 1558 | boolean, or string) where an out of range error can be detected easily; | ||
3203 | 1559 | example: `"iterators out of range"` | ||
3204 | 1560 | @throw std::bad_alloc if allocation for object, array, or string fails | ||
3205 | 1561 | @throw std::domain_error if called with a null value; example: `"cannot use | ||
3206 | 1562 | construct with iterators from null"` | ||
3207 | 1563 | |||
3208 | 1564 | @complexity Linear in distance between @a first and @a last. | ||
3209 | 1565 | |||
3210 | 1566 | @liveexample{The example below shows several ways to create JSON values by | ||
3211 | 1567 | specifying a subrange with iterators.,basic_json__InputIt_InputIt} | ||
3212 | 1568 | |||
3213 | 1569 | @since version 1.0.0 | ||
3214 | 1570 | */ | ||
3215 | 1571 | template <class InputIT, typename | ||
3216 | 1572 | std::enable_if< | ||
3217 | 1573 | std::is_same<InputIT, typename basic_json_t::iterator>::value or | ||
3218 | 1574 | std::is_same<InputIT, typename basic_json_t::const_iterator>::value | ||
3219 | 1575 | , int>::type | ||
3220 | 1576 | = 0> | ||
3221 | 1577 | basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type) | ||
3222 | 1578 | { | ||
3223 | 1579 | // make sure iterator fits the current value | ||
3224 | 1580 | if (first.m_object != last.m_object) | ||
3225 | 1581 | { | ||
3226 | 1582 | throw std::domain_error("iterators are not compatible"); | ||
3227 | 1583 | } | ||
3228 | 1584 | |||
3229 | 1585 | // check if iterator range is complete for primitive values | ||
3230 | 1586 | switch (m_type) | ||
3231 | 1587 | { | ||
3232 | 1588 | case value_t::boolean: | ||
3233 | 1589 | case value_t::number_float: | ||
3234 | 1590 | case value_t::number_integer: | ||
3235 | 1591 | case value_t::string: | ||
3236 | 1592 | { | ||
3237 | 1593 | if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end()) | ||
3238 | 1594 | { | ||
3239 | 1595 | throw std::out_of_range("iterators out of range"); | ||
3240 | 1596 | } | ||
3241 | 1597 | break; | ||
3242 | 1598 | } | ||
3243 | 1599 | |||
3244 | 1600 | default: | ||
3245 | 1601 | { | ||
3246 | 1602 | break; | ||
3247 | 1603 | } | ||
3248 | 1604 | } | ||
3249 | 1605 | |||
3250 | 1606 | switch (m_type) | ||
3251 | 1607 | { | ||
3252 | 1608 | case value_t::number_integer: | ||
3253 | 1609 | { | ||
3254 | 1610 | m_value.number_integer = first.m_object->m_value.number_integer; | ||
3255 | 1611 | break; | ||
3256 | 1612 | } | ||
3257 | 1613 | |||
3258 | 1614 | case value_t::number_float: | ||
3259 | 1615 | { | ||
3260 | 1616 | m_value.number_float = first.m_object->m_value.number_float; | ||
3261 | 1617 | break; | ||
3262 | 1618 | } | ||
3263 | 1619 | |||
3264 | 1620 | case value_t::boolean: | ||
3265 | 1621 | { | ||
3266 | 1622 | m_value.boolean = first.m_object->m_value.boolean; | ||
3267 | 1623 | break; | ||
3268 | 1624 | } | ||
3269 | 1625 | |||
3270 | 1626 | case value_t::string: | ||
3271 | 1627 | { | ||
3272 | 1628 | m_value = *first.m_object->m_value.string; | ||
3273 | 1629 | break; | ||
3274 | 1630 | } | ||
3275 | 1631 | |||
3276 | 1632 | case value_t::object: | ||
3277 | 1633 | { | ||
3278 | 1634 | m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator); | ||
3279 | 1635 | break; | ||
3280 | 1636 | } | ||
3281 | 1637 | |||
3282 | 1638 | case value_t::array: | ||
3283 | 1639 | { | ||
3284 | 1640 | m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator); | ||
3285 | 1641 | break; | ||
3286 | 1642 | } | ||
3287 | 1643 | |||
3288 | 1644 | default: | ||
3289 | 1645 | { | ||
3290 | 1646 | throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name()); | ||
3291 | 1647 | } | ||
3292 | 1648 | } | ||
3293 | 1649 | } | ||
3294 | 1650 | |||
3295 | 1651 | /////////////////////////////////////// | ||
3296 | 1652 | // other constructors and destructor // | ||
3297 | 1653 | /////////////////////////////////////// | ||
3298 | 1654 | |||
3299 | 1655 | /*! | ||
3300 | 1656 | @brief copy constructor | ||
3301 | 1657 | |||
3302 | 1658 | Creates a copy of a given JSON value. | ||
3303 | 1659 | |||
3304 | 1660 | @param[in] other the JSON value to copy | ||
3305 | 1661 | |||
3306 | 1662 | @complexity Linear in the size of @a other. | ||
3307 | 1663 | |||
3308 | 1664 | @requirement This function satisfies the Container requirements: | ||
3309 | 1665 | - The complexity is linear. | ||
3310 | 1666 | - As postcondition, it holds: `other == basic_json(other)`. | ||
3311 | 1667 | |||
3312 | 1668 | @throw std::bad_alloc if allocation for object, array, or string fails. | ||
3313 | 1669 | |||
3314 | 1670 | @liveexample{The following code shows an example for the copy | ||
3315 | 1671 | constructor.,basic_json__basic_json} | ||
3316 | 1672 | |||
3317 | 1673 | @since version 1.0.0 | ||
3318 | 1674 | */ | ||
3319 | 1675 | basic_json(const basic_json& other) | ||
3320 | 1676 | : m_type(other.m_type) | ||
3321 | 1677 | { | ||
3322 | 1678 | switch (m_type) | ||
3323 | 1679 | { | ||
3324 | 1680 | case value_t::object: | ||
3325 | 1681 | { | ||
3326 | 1682 | m_value = *other.m_value.object; | ||
3327 | 1683 | break; | ||
3328 | 1684 | } | ||
3329 | 1685 | |||
3330 | 1686 | case value_t::array: | ||
3331 | 1687 | { | ||
3332 | 1688 | m_value = *other.m_value.array; | ||
3333 | 1689 | break; | ||
3334 | 1690 | } | ||
3335 | 1691 | |||
3336 | 1692 | case value_t::string: | ||
3337 | 1693 | { | ||
3338 | 1694 | m_value = *other.m_value.string; | ||
3339 | 1695 | break; | ||
3340 | 1696 | } | ||
3341 | 1697 | |||
3342 | 1698 | case value_t::boolean: | ||
3343 | 1699 | { | ||
3344 | 1700 | m_value = other.m_value.boolean; | ||
3345 | 1701 | break; | ||
3346 | 1702 | } | ||
3347 | 1703 | |||
3348 | 1704 | case value_t::number_integer: | ||
3349 | 1705 | { | ||
3350 | 1706 | m_value = other.m_value.number_integer; | ||
3351 | 1707 | break; | ||
3352 | 1708 | } | ||
3353 | 1709 | |||
3354 | 1710 | case value_t::number_float: | ||
3355 | 1711 | { | ||
3356 | 1712 | m_value = other.m_value.number_float; | ||
3357 | 1713 | break; | ||
3358 | 1714 | } | ||
3359 | 1715 | |||
3360 | 1716 | default: | ||
3361 | 1717 | { | ||
3362 | 1718 | break; | ||
3363 | 1719 | } | ||
3364 | 1720 | } | ||
3365 | 1721 | } | ||
3366 | 1722 | |||
3367 | 1723 | /*! | ||
3368 | 1724 | @brief move constructor | ||
3369 | 1725 | |||
3370 | 1726 | Move constructor. Constructs a JSON value with the contents of the given | ||
3371 | 1727 | value @a other using move semantics. It "steals" the resources from @a | ||
3372 | 1728 | other and leaves it as JSON null value. | ||
3373 | 1729 | |||
3374 | 1730 | @param[in,out] other value to move to this object | ||
3375 | 1731 | |||
3376 | 1732 | @post @a other is a JSON null value | ||
3377 | 1733 | |||
3378 | 1734 | @complexity Constant. | ||
3379 | 1735 | |||
3380 | 1736 | @liveexample{The code below shows the move constructor explicitly called | ||
3381 | 1737 | via std::move.,basic_json__moveconstructor} | ||
3382 | 1738 | |||
3383 | 1739 | @since version 1.0.0 | ||
3384 | 1740 | */ | ||
3385 | 1741 | basic_json(basic_json&& other) noexcept | ||
3386 | 1742 | : m_type(std::move(other.m_type)), | ||
3387 | 1743 | m_value(std::move(other.m_value)) | ||
3388 | 1744 | { | ||
3389 | 1745 | // invalidate payload | ||
3390 | 1746 | other.m_type = value_t::null; | ||
3391 | 1747 | other.m_value = {}; | ||
3392 | 1748 | } | ||
3393 | 1749 | |||
3394 | 1750 | /*! | ||
3395 | 1751 | @brief copy assignment | ||
3396 | 1752 | |||
3397 | 1753 | Copy assignment operator. Copies a JSON value via the "copy and swap" | ||
3398 | 1754 | strategy: It is expressed in terms of the copy constructor, destructor, and | ||
3399 | 1755 | the swap() member function. | ||
3400 | 1756 | |||
3401 | 1757 | @param[in] other value to copy from | ||
3402 | 1758 | |||
3403 | 1759 | @complexity Linear. | ||
3404 | 1760 | |||
3405 | 1761 | @requirement This function satisfies the Container requirements: | ||
3406 | 1762 | - The complexity is linear. | ||
3407 | 1763 | |||
3408 | 1764 | @liveexample{The code below shows and example for the copy assignment. It | ||
3409 | 1765 | creates a copy of value `a` which is then swapped with `b`. Finally\, the | ||
3410 | 1766 | copy of `a` (which is the null value after the swap) is | ||
3411 | 1767 | destroyed.,basic_json__copyassignment} | ||
3412 | 1768 | |||
3413 | 1769 | @since version 1.0.0 | ||
3414 | 1770 | */ | ||
3415 | 1771 | reference& operator=(basic_json other) noexcept ( | ||
3416 | 1772 | std::is_nothrow_move_constructible<value_t>::value and | ||
3417 | 1773 | std::is_nothrow_move_assignable<value_t>::value and | ||
3418 | 1774 | std::is_nothrow_move_constructible<json_value>::value and | ||
3419 | 1775 | std::is_nothrow_move_assignable<json_value>::value | ||
3420 | 1776 | ) | ||
3421 | 1777 | { | ||
3422 | 1778 | using std::swap; | ||
3423 | 1779 | swap(m_type, other.m_type); | ||
3424 | 1780 | swap(m_value, other.m_value); | ||
3425 | 1781 | return *this; | ||
3426 | 1782 | } | ||
3427 | 1783 | |||
3428 | 1784 | /*! | ||
3429 | 1785 | @brief destructor | ||
3430 | 1786 | |||
3431 | 1787 | Destroys the JSON value and frees all allocated memory. | ||
3432 | 1788 | |||
3433 | 1789 | @complexity Linear. | ||
3434 | 1790 | |||
3435 | 1791 | @requirement This function satisfies the Container requirements: | ||
3436 | 1792 | - The complexity is linear. | ||
3437 | 1793 | - All stored elements are destroyed and all memory is freed. | ||
3438 | 1794 | |||
3439 | 1795 | @since version 1.0.0 | ||
3440 | 1796 | */ | ||
3441 | 1797 | ~basic_json() | ||
3442 | 1798 | { | ||
3443 | 1799 | switch (m_type) | ||
3444 | 1800 | { | ||
3445 | 1801 | case value_t::object: | ||
3446 | 1802 | { | ||
3447 | 1803 | AllocatorType<object_t> alloc; | ||
3448 | 1804 | alloc.destroy(m_value.object); | ||
3449 | 1805 | alloc.deallocate(m_value.object, 1); | ||
3450 | 1806 | break; | ||
3451 | 1807 | } | ||
3452 | 1808 | |||
3453 | 1809 | case value_t::array: | ||
3454 | 1810 | { | ||
3455 | 1811 | AllocatorType<array_t> alloc; | ||
3456 | 1812 | alloc.destroy(m_value.array); | ||
3457 | 1813 | alloc.deallocate(m_value.array, 1); | ||
3458 | 1814 | break; | ||
3459 | 1815 | } | ||
3460 | 1816 | |||
3461 | 1817 | case value_t::string: | ||
3462 | 1818 | { | ||
3463 | 1819 | AllocatorType<string_t> alloc; | ||
3464 | 1820 | alloc.destroy(m_value.string); | ||
3465 | 1821 | alloc.deallocate(m_value.string, 1); | ||
3466 | 1822 | break; | ||
3467 | 1823 | } | ||
3468 | 1824 | |||
3469 | 1825 | default: | ||
3470 | 1826 | { | ||
3471 | 1827 | // all other types need no specific destructor | ||
3472 | 1828 | break; | ||
3473 | 1829 | } | ||
3474 | 1830 | } | ||
3475 | 1831 | } | ||
3476 | 1832 | |||
3477 | 1833 | /// @} | ||
3478 | 1834 | |||
3479 | 1835 | public: | ||
3480 | 1836 | /////////////////////// | ||
3481 | 1837 | // object inspection // | ||
3482 | 1838 | /////////////////////// | ||
3483 | 1839 | |||
3484 | 1840 | /// @name object inspection | ||
3485 | 1841 | /// @{ | ||
3486 | 1842 | |||
3487 | 1843 | /*! | ||
3488 | 1844 | @brief serialization | ||
3489 | 1845 | |||
3490 | 1846 | Serialization function for JSON values. The function tries to mimick | ||
3491 | 1847 | Python's @p json.dumps() function, and currently supports its @p indent | ||
3492 | 1848 | parameter. | ||
3493 | 1849 | |||
3494 | 1850 | @param[in] indent if indent is nonnegative, then array elements and object | ||
3495 | 1851 | members will be pretty-printed with that indent level. An indent level of 0 | ||
3496 | 1852 | will only insert newlines. -1 (the default) selects the most compact | ||
3497 | 1853 | representation | ||
3498 | 1854 | |||
3499 | 1855 | @return string containing the serialization of the JSON value | ||
3500 | 1856 | |||
3501 | 1857 | @complexity Linear. | ||
3502 | 1858 | |||
3503 | 1859 | @liveexample{The following example shows the effect of different @a indent | ||
3504 | 1860 | parameters to the result of the serializaion.,dump} | ||
3505 | 1861 | |||
3506 | 1862 | @see https://docs.python.org/2/library/json.html#json.dump | ||
3507 | 1863 | |||
3508 | 1864 | @since version 1.0.0 | ||
3509 | 1865 | */ | ||
3510 | 1866 | string_t dump(const int indent = -1) const | ||
3511 | 1867 | { | ||
3512 | 1868 | std::stringstream ss; | ||
3513 | 1869 | |||
3514 | 1870 | if (indent >= 0) | ||
3515 | 1871 | { | ||
3516 | 1872 | dump(ss, true, static_cast<unsigned int>(indent)); | ||
3517 | 1873 | } | ||
3518 | 1874 | else | ||
3519 | 1875 | { | ||
3520 | 1876 | dump(ss, false, 0); | ||
3521 | 1877 | } | ||
3522 | 1878 | |||
3523 | 1879 | return ss.str(); | ||
3524 | 1880 | } | ||
3525 | 1881 | |||
3526 | 1882 | /*! | ||
3527 | 1883 | @brief return the type of the JSON value (explicit) | ||
3528 | 1884 | |||
3529 | 1885 | Return the type of the JSON value as a value from the @ref value_t | ||
3530 | 1886 | enumeration. | ||
3531 | 1887 | |||
3532 | 1888 | @return the type of the JSON value | ||
3533 | 1889 | |||
3534 | 1890 | @complexity Constant. | ||
3535 | 1891 | |||
3536 | 1892 | @liveexample{The following code exemplifies @ref type() for all JSON | ||
3537 | 1893 | types.,type} | ||
3538 | 1894 | |||
3539 | 1895 | @since version 1.0.0 | ||
3540 | 1896 | */ | ||
3541 | 1897 | value_t type() const noexcept | ||
3542 | 1898 | { | ||
3543 | 1899 | return m_type; | ||
3544 | 1900 | } | ||
3545 | 1901 | |||
3546 | 1902 | /*! | ||
3547 | 1903 | @brief return whether type is primitive | ||
3548 | 1904 | |||
3549 | 1905 | This function returns true iff the JSON type is primitive (string, number, | ||
3550 | 1906 | boolean, or null). | ||
3551 | 1907 | |||
3552 | 1908 | @return `true` if type is primitive (string, number, boolean, or null), | ||
3553 | 1909 | `false` otherwise. | ||
3554 | 1910 | |||
3555 | 1911 | @complexity Constant. | ||
3556 | 1912 | |||
3557 | 1913 | @liveexample{The following code exemplifies @ref is_primitive for all JSON | ||
3558 | 1914 | types.,is_primitive} | ||
3559 | 1915 | |||
3560 | 1916 | @since version 1.0.0 | ||
3561 | 1917 | */ | ||
3562 | 1918 | bool is_primitive() const noexcept | ||
3563 | 1919 | { | ||
3564 | 1920 | return is_null() or is_string() or is_boolean() or is_number(); | ||
3565 | 1921 | } | ||
3566 | 1922 | |||
3567 | 1923 | /*! | ||
3568 | 1924 | @brief return whether type is structured | ||
3569 | 1925 | |||
3570 | 1926 | This function returns true iff the JSON type is structured (array or | ||
3571 | 1927 | object). | ||
3572 | 1928 | |||
3573 | 1929 | @return `true` if type is structured (array or object), `false` otherwise. | ||
3574 | 1930 | |||
3575 | 1931 | @complexity Constant. | ||
3576 | 1932 | |||
3577 | 1933 | @liveexample{The following code exemplifies @ref is_structured for all JSON | ||
3578 | 1934 | types.,is_structured} | ||
3579 | 1935 | |||
3580 | 1936 | @since version 1.0.0 | ||
3581 | 1937 | */ | ||
3582 | 1938 | bool is_structured() const noexcept | ||
3583 | 1939 | { | ||
3584 | 1940 | return is_array() or is_object(); | ||
3585 | 1941 | } | ||
3586 | 1942 | |||
3587 | 1943 | /*! | ||
3588 | 1944 | @brief return whether value is null | ||
3589 | 1945 | |||
3590 | 1946 | This function returns true iff the JSON value is null. | ||
3591 | 1947 | |||
3592 | 1948 | @return `true` if type is null, `false` otherwise. | ||
3593 | 1949 | |||
3594 | 1950 | @complexity Constant. | ||
3595 | 1951 | |||
3596 | 1952 | @liveexample{The following code exemplifies @ref is_null for all JSON | ||
3597 | 1953 | types.,is_null} | ||
3598 | 1954 | |||
3599 | 1955 | @since version 1.0.0 | ||
3600 | 1956 | */ | ||
3601 | 1957 | bool is_null() const noexcept | ||
3602 | 1958 | { | ||
3603 | 1959 | return m_type == value_t::null; | ||
3604 | 1960 | } | ||
3605 | 1961 | |||
3606 | 1962 | /*! | ||
3607 | 1963 | @brief return whether value is a boolean | ||
3608 | 1964 | |||
3609 | 1965 | This function returns true iff the JSON value is a boolean. | ||
3610 | 1966 | |||
3611 | 1967 | @return `true` if type is boolean, `false` otherwise. | ||
3612 | 1968 | |||
3613 | 1969 | @complexity Constant. | ||
3614 | 1970 | |||
3615 | 1971 | @liveexample{The following code exemplifies @ref is_boolean for all JSON | ||
3616 | 1972 | types.,is_boolean} | ||
3617 | 1973 | |||
3618 | 1974 | @since version 1.0.0 | ||
3619 | 1975 | */ | ||
3620 | 1976 | bool is_boolean() const noexcept | ||
3621 | 1977 | { | ||
3622 | 1978 | return m_type == value_t::boolean; | ||
3623 | 1979 | } | ||
3624 | 1980 | |||
3625 | 1981 | /*! | ||
3626 | 1982 | @brief return whether value is a number | ||
3627 | 1983 | |||
3628 | 1984 | This function returns true iff the JSON value is a number. This includes | ||
3629 | 1985 | both integer and floating-point values. | ||
3630 | 1986 | |||
3631 | 1987 | @return `true` if type is number (regardless whether integer or | ||
3632 | 1988 | floating-type), `false` otherwise. | ||
3633 | 1989 | |||
3634 | 1990 | @complexity Constant. | ||
3635 | 1991 | |||
3636 | 1992 | @liveexample{The following code exemplifies @ref is_number for all JSON | ||
3637 | 1993 | types.,is_number} | ||
3638 | 1994 | |||
3639 | 1995 | @sa @ref is_number_integer() -- check if value is an integer number | ||
3640 | 1996 | @sa @ref is_number_float() -- check if value is a floating-point number | ||
3641 | 1997 | |||
3642 | 1998 | @since version 1.0.0 | ||
3643 | 1999 | */ | ||
3644 | 2000 | bool is_number() const noexcept | ||
3645 | 2001 | { | ||
3646 | 2002 | return is_number_integer() or is_number_float(); | ||
3647 | 2003 | } | ||
3648 | 2004 | |||
3649 | 2005 | /*! | ||
3650 | 2006 | @brief return whether value is an integer number | ||
3651 | 2007 | |||
3652 | 2008 | This function returns true iff the JSON value is an integer number. This | ||
3653 | 2009 | excludes floating-point values. | ||
3654 | 2010 | |||
3655 | 2011 | @return `true` if type is an integer number, `false` otherwise. | ||
3656 | 2012 | |||
3657 | 2013 | @complexity Constant. | ||
3658 | 2014 | |||
3659 | 2015 | @liveexample{The following code exemplifies @ref is_number_integer for all | ||
3660 | 2016 | JSON types.,is_number_integer} | ||
3661 | 2017 | |||
3662 | 2018 | @sa @ref is_number() -- check if value is a number | ||
3663 | 2019 | @sa @ref is_number_float() -- check if value is a floating-point number | ||
3664 | 2020 | |||
3665 | 2021 | @since version 1.0.0 | ||
3666 | 2022 | */ | ||
3667 | 2023 | bool is_number_integer() const noexcept | ||
3668 | 2024 | { | ||
3669 | 2025 | return m_type == value_t::number_integer; | ||
3670 | 2026 | } | ||
3671 | 2027 | |||
3672 | 2028 | /*! | ||
3673 | 2029 | @brief return whether value is a floating-point number | ||
3674 | 2030 | |||
3675 | 2031 | This function returns true iff the JSON value is a floating-point number. | ||
3676 | 2032 | This excludes integer values. | ||
3677 | 2033 | |||
3678 | 2034 | @return `true` if type is a floating-point number, `false` otherwise. | ||
3679 | 2035 | |||
3680 | 2036 | @complexity Constant. | ||
3681 | 2037 | |||
3682 | 2038 | @liveexample{The following code exemplifies @ref is_number_float for all | ||
3683 | 2039 | JSON types.,is_number_float} | ||
3684 | 2040 | |||
3685 | 2041 | @sa @ref is_number() -- check if value is number | ||
3686 | 2042 | @sa @ref is_number_integer() -- check if value is an integer number | ||
3687 | 2043 | |||
3688 | 2044 | @since version 1.0.0 | ||
3689 | 2045 | */ | ||
3690 | 2046 | bool is_number_float() const noexcept | ||
3691 | 2047 | { | ||
3692 | 2048 | return m_type == value_t::number_float; | ||
3693 | 2049 | } | ||
3694 | 2050 | |||
3695 | 2051 | /*! | ||
3696 | 2052 | @brief return whether value is an object | ||
3697 | 2053 | |||
3698 | 2054 | This function returns true iff the JSON value is an object. | ||
3699 | 2055 | |||
3700 | 2056 | @return `true` if type is object, `false` otherwise. | ||
3701 | 2057 | |||
3702 | 2058 | @complexity Constant. | ||
3703 | 2059 | |||
3704 | 2060 | @liveexample{The following code exemplifies @ref is_object for all JSON | ||
3705 | 2061 | types.,is_object} | ||
3706 | 2062 | |||
3707 | 2063 | @since version 1.0.0 | ||
3708 | 2064 | */ | ||
3709 | 2065 | bool is_object() const noexcept | ||
3710 | 2066 | { | ||
3711 | 2067 | return m_type == value_t::object; | ||
3712 | 2068 | } | ||
3713 | 2069 | |||
3714 | 2070 | /*! | ||
3715 | 2071 | @brief return whether value is an array | ||
3716 | 2072 | |||
3717 | 2073 | This function returns true iff the JSON value is an array. | ||
3718 | 2074 | |||
3719 | 2075 | @return `true` if type is array, `false` otherwise. | ||
3720 | 2076 | |||
3721 | 2077 | @complexity Constant. | ||
3722 | 2078 | |||
3723 | 2079 | @liveexample{The following code exemplifies @ref is_array for all JSON | ||
3724 | 2080 | types.,is_array} | ||
3725 | 2081 | |||
3726 | 2082 | @since version 1.0.0 | ||
3727 | 2083 | */ | ||
3728 | 2084 | bool is_array() const noexcept | ||
3729 | 2085 | { | ||
3730 | 2086 | return m_type == value_t::array; | ||
3731 | 2087 | } | ||
3732 | 2088 | |||
3733 | 2089 | /*! | ||
3734 | 2090 | @brief return whether value is a string | ||
3735 | 2091 | |||
3736 | 2092 | This function returns true iff the JSON value is a string. | ||
3737 | 2093 | |||
3738 | 2094 | @return `true` if type is string, `false` otherwise. | ||
3739 | 2095 | |||
3740 | 2096 | @complexity Constant. | ||
3741 | 2097 | |||
3742 | 2098 | @liveexample{The following code exemplifies @ref is_string for all JSON | ||
3743 | 2099 | types.,is_string} | ||
3744 | 2100 | |||
3745 | 2101 | @since version 1.0.0 | ||
3746 | 2102 | */ | ||
3747 | 2103 | bool is_string() const noexcept | ||
3748 | 2104 | { | ||
3749 | 2105 | return m_type == value_t::string; | ||
3750 | 2106 | } | ||
3751 | 2107 | |||
3752 | 2108 | /*! | ||
3753 | 2109 | @brief return whether value is discarded | ||
3754 | 2110 | |||
3755 | 2111 | This function returns true iff the JSON value was discarded during parsing | ||
3756 | 2112 | with a callback function (see @ref parser_callback_t). | ||
3757 | 2113 | |||
3758 | 2114 | @note This function will always be `false` for JSON values after parsing. | ||
3759 | 2115 | That is, discarded values can only occur during parsing, but will be | ||
3760 | 2116 | removed when inside a structured value or replaced by null in other cases. | ||
3761 | 2117 | |||
3762 | 2118 | @return `true` if type is discarded, `false` otherwise. | ||
3763 | 2119 | |||
3764 | 2120 | @complexity Constant. | ||
3765 | 2121 | |||
3766 | 2122 | @liveexample{The following code exemplifies @ref is_discarded for all JSON | ||
3767 | 2123 | types.,is_discarded} | ||
3768 | 2124 | |||
3769 | 2125 | @since version 1.0.0 | ||
3770 | 2126 | */ | ||
3771 | 2127 | bool is_discarded() const noexcept | ||
3772 | 2128 | { | ||
3773 | 2129 | return m_type == value_t::discarded; | ||
3774 | 2130 | } | ||
3775 | 2131 | |||
3776 | 2132 | /*! | ||
3777 | 2133 | @brief return the type of the JSON value (implicit) | ||
3778 | 2134 | |||
3779 | 2135 | Implicitly return the type of the JSON value as a value from the @ref | ||
3780 | 2136 | value_t enumeration. | ||
3781 | 2137 | |||
3782 | 2138 | @return the type of the JSON value | ||
3783 | 2139 | |||
3784 | 2140 | @complexity Constant. | ||
3785 | 2141 | |||
3786 | 2142 | @liveexample{The following code exemplifies the value_t operator for all | ||
3787 | 2143 | JSON types.,operator__value_t} | ||
3788 | 2144 | |||
3789 | 2145 | @since version 1.0.0 | ||
3790 | 2146 | */ | ||
3791 | 2147 | operator value_t() const noexcept | ||
3792 | 2148 | { | ||
3793 | 2149 | return m_type; | ||
3794 | 2150 | } | ||
3795 | 2151 | |||
3796 | 2152 | /// @} | ||
3797 | 2153 | |||
3798 | 2154 | private: | ||
3799 | 2155 | ////////////////// | ||
3800 | 2156 | // value access // | ||
3801 | 2157 | ////////////////// | ||
3802 | 2158 | |||
3803 | 2159 | /// get an object (explicit) | ||
3804 | 2160 | template <class T, typename | ||
3805 | 2161 | std::enable_if< | ||
3806 | 2162 | std::is_convertible<typename object_t::key_type, typename T::key_type>::value and | ||
3807 | 2163 | std::is_convertible<basic_json_t, typename T::mapped_type>::value | ||
3808 | 2164 | , int>::type = 0> | ||
3809 | 2165 | T get_impl(T*) const | ||
3810 | 2166 | { | ||
3811 | 2167 | if (is_object()) | ||
3812 | 2168 | { | ||
3813 | 2169 | return T(m_value.object->begin(), m_value.object->end()); | ||
3814 | 2170 | } | ||
3815 | 2171 | else | ||
3816 | 2172 | { | ||
3817 | 2173 | throw std::domain_error("type must be object, but is " + type_name()); | ||
3818 | 2174 | } | ||
3819 | 2175 | } | ||
3820 | 2176 | |||
3821 | 2177 | /// get an object (explicit) | ||
3822 | 2178 | object_t get_impl(object_t*) const | ||
3823 | 2179 | { | ||
3824 | 2180 | if (is_object()) | ||
3825 | 2181 | { | ||
3826 | 2182 | return *(m_value.object); | ||
3827 | 2183 | } | ||
3828 | 2184 | else | ||
3829 | 2185 | { | ||
3830 | 2186 | throw std::domain_error("type must be object, but is " + type_name()); | ||
3831 | 2187 | } | ||
3832 | 2188 | } | ||
3833 | 2189 | |||
3834 | 2190 | /// get an array (explicit) | ||
3835 | 2191 | template <class T, typename | ||
3836 | 2192 | std::enable_if< | ||
3837 | 2193 | std::is_convertible<basic_json_t, typename T::value_type>::value and | ||
3838 | 2194 | not std::is_same<basic_json_t, typename T::value_type>::value and | ||
3839 | 2195 | not std::is_arithmetic<T>::value and | ||
3840 | 2196 | not std::is_convertible<std::string, T>::value and | ||
3841 | 2197 | not has_mapped_type<T>::value | ||
3842 | 2198 | , int>::type = 0> | ||
3843 | 2199 | T get_impl(T*) const | ||
3844 | 2200 | { | ||
3845 | 2201 | if (is_array()) | ||
3846 | 2202 | { | ||
3847 | 2203 | T to_vector; | ||
3848 | 2204 | std::transform(m_value.array->begin(), m_value.array->end(), | ||
3849 | 2205 | std::inserter(to_vector, to_vector.end()), [](basic_json i) | ||
3850 | 2206 | { | ||
3851 | 2207 | return i.get<typename T::value_type>(); | ||
3852 | 2208 | }); | ||
3853 | 2209 | return to_vector; | ||
3854 | 2210 | } | ||
3855 | 2211 | else | ||
3856 | 2212 | { | ||
3857 | 2213 | throw std::domain_error("type must be array, but is " + type_name()); | ||
3858 | 2214 | } | ||
3859 | 2215 | } | ||
3860 | 2216 | |||
3861 | 2217 | /// get an array (explicit) | ||
3862 | 2218 | template <class T, typename | ||
3863 | 2219 | std::enable_if< | ||
3864 | 2220 | std::is_convertible<basic_json_t, T>::value and | ||
3865 | 2221 | not std::is_same<basic_json_t, T>::value | ||
3866 | 2222 | , int>::type = 0> | ||
3867 | 2223 | std::vector<T> get_impl(std::vector<T>*) const | ||
3868 | 2224 | { | ||
3869 | 2225 | if (is_array()) | ||
3870 | 2226 | { | ||
3871 | 2227 | std::vector<T> to_vector; | ||
3872 | 2228 | to_vector.reserve(m_value.array->size()); | ||
3873 | 2229 | std::transform(m_value.array->begin(), m_value.array->end(), | ||
3874 | 2230 | std::inserter(to_vector, to_vector.end()), [](basic_json i) | ||
3875 | 2231 | { | ||
3876 | 2232 | return i.get<T>(); | ||
3877 | 2233 | }); | ||
3878 | 2234 | return to_vector; | ||
3879 | 2235 | } | ||
3880 | 2236 | else | ||
3881 | 2237 | { | ||
3882 | 2238 | throw std::domain_error("type must be array, but is " + type_name()); | ||
3883 | 2239 | } | ||
3884 | 2240 | } | ||
3885 | 2241 | |||
3886 | 2242 | /// get an array (explicit) | ||
3887 | 2243 | template <class T, typename | ||
3888 | 2244 | std::enable_if< | ||
3889 | 2245 | std::is_same<basic_json, typename T::value_type>::value and | ||
3890 | 2246 | not has_mapped_type<T>::value | ||
3891 | 2247 | , int>::type = 0> | ||
3892 | 2248 | T get_impl(T*) const | ||
3893 | 2249 | { | ||
3894 | 2250 | if (is_array()) | ||
3895 | 2251 | { | ||
3896 | 2252 | return T(m_value.array->begin(), m_value.array->end()); | ||
3897 | 2253 | } | ||
3898 | 2254 | else | ||
3899 | 2255 | { | ||
3900 | 2256 | throw std::domain_error("type must be array, but is " + type_name()); | ||
3901 | 2257 | } | ||
3902 | 2258 | } | ||
3903 | 2259 | |||
3904 | 2260 | /// get an array (explicit) | ||
3905 | 2261 | array_t get_impl(array_t*) const | ||
3906 | 2262 | { | ||
3907 | 2263 | if (is_array()) | ||
3908 | 2264 | { | ||
3909 | 2265 | return *(m_value.array); | ||
3910 | 2266 | } | ||
3911 | 2267 | else | ||
3912 | 2268 | { | ||
3913 | 2269 | throw std::domain_error("type must be array, but is " + type_name()); | ||
3914 | 2270 | } | ||
3915 | 2271 | } | ||
3916 | 2272 | |||
3917 | 2273 | /// get a string (explicit) | ||
3918 | 2274 | template <typename T, typename | ||
3919 | 2275 | std::enable_if< | ||
3920 | 2276 | std::is_convertible<string_t, T>::value | ||
3921 | 2277 | , int>::type = 0> | ||
3922 | 2278 | T get_impl(T*) const | ||
3923 | 2279 | { | ||
3924 | 2280 | if (is_string()) | ||
3925 | 2281 | { | ||
3926 | 2282 | return *m_value.string; | ||
3927 | 2283 | } | ||
3928 | 2284 | else | ||
3929 | 2285 | { | ||
3930 | 2286 | throw std::domain_error("type must be string, but is " + type_name()); | ||
3931 | 2287 | } | ||
3932 | 2288 | } | ||
3933 | 2289 | |||
3934 | 2290 | /// get a number (explicit) | ||
3935 | 2291 | template<typename T, typename | ||
3936 | 2292 | std::enable_if< | ||
3937 | 2293 | std::is_arithmetic<T>::value | ||
3938 | 2294 | , int>::type = 0> | ||
3939 | 2295 | T get_impl(T*) const | ||
3940 | 2296 | { | ||
3941 | 2297 | switch (m_type) | ||
3942 | 2298 | { | ||
3943 | 2299 | case value_t::number_integer: | ||
3944 | 2300 | { | ||
3945 | 2301 | return static_cast<T>(m_value.number_integer); | ||
3946 | 2302 | } | ||
3947 | 2303 | |||
3948 | 2304 | case value_t::number_float: | ||
3949 | 2305 | { | ||
3950 | 2306 | return static_cast<T>(m_value.number_float); | ||
3951 | 2307 | } | ||
3952 | 2308 | |||
3953 | 2309 | default: | ||
3954 | 2310 | { | ||
3955 | 2311 | throw std::domain_error("type must be number, but is " + type_name()); | ||
3956 | 2312 | } | ||
3957 | 2313 | } | ||
3958 | 2314 | } | ||
3959 | 2315 | |||
3960 | 2316 | /// get a boolean (explicit) | ||
3961 | 2317 | boolean_t get_impl(boolean_t*) const | ||
3962 | 2318 | { | ||
3963 | 2319 | if (is_boolean()) | ||
3964 | 2320 | { | ||
3965 | 2321 | return m_value.boolean; | ||
3966 | 2322 | } | ||
3967 | 2323 | else | ||
3968 | 2324 | { | ||
3969 | 2325 | throw std::domain_error("type must be boolean, but is " + type_name()); | ||
3970 | 2326 | } | ||
3971 | 2327 | } | ||
3972 | 2328 | |||
3973 | 2329 | /// get a pointer to the value (object) | ||
3974 | 2330 | object_t* get_impl_ptr(object_t*) noexcept | ||
3975 | 2331 | { | ||
3976 | 2332 | return is_object() ? m_value.object : nullptr; | ||
3977 | 2333 | } | ||
3978 | 2334 | |||
3979 | 2335 | /// get a pointer to the value (object) | ||
3980 | 2336 | const object_t* get_impl_ptr(const object_t*) const noexcept | ||
3981 | 2337 | { | ||
3982 | 2338 | return is_object() ? m_value.object : nullptr; | ||
3983 | 2339 | } | ||
3984 | 2340 | |||
3985 | 2341 | /// get a pointer to the value (array) | ||
3986 | 2342 | array_t* get_impl_ptr(array_t*) noexcept | ||
3987 | 2343 | { | ||
3988 | 2344 | return is_array() ? m_value.array : nullptr; | ||
3989 | 2345 | } | ||
3990 | 2346 | |||
3991 | 2347 | /// get a pointer to the value (array) | ||
3992 | 2348 | const array_t* get_impl_ptr(const array_t*) const noexcept | ||
3993 | 2349 | { | ||
3994 | 2350 | return is_array() ? m_value.array : nullptr; | ||
3995 | 2351 | } | ||
3996 | 2352 | |||
3997 | 2353 | /// get a pointer to the value (string) | ||
3998 | 2354 | string_t* get_impl_ptr(string_t*) noexcept | ||
3999 | 2355 | { | ||
4000 | 2356 | return is_string() ? m_value.string : nullptr; | ||
4001 | 2357 | } | ||
4002 | 2358 | |||
4003 | 2359 | /// get a pointer to the value (string) | ||
4004 | 2360 | const string_t* get_impl_ptr(const string_t*) const noexcept | ||
4005 | 2361 | { | ||
4006 | 2362 | return is_string() ? m_value.string : nullptr; | ||
4007 | 2363 | } | ||
4008 | 2364 | |||
4009 | 2365 | /// get a pointer to the value (boolean) | ||
4010 | 2366 | boolean_t* get_impl_ptr(boolean_t*) noexcept | ||
4011 | 2367 | { | ||
4012 | 2368 | return is_boolean() ? &m_value.boolean : nullptr; | ||
4013 | 2369 | } | ||
4014 | 2370 | |||
4015 | 2371 | /// get a pointer to the value (boolean) | ||
4016 | 2372 | const boolean_t* get_impl_ptr(const boolean_t*) const noexcept | ||
4017 | 2373 | { | ||
4018 | 2374 | return is_boolean() ? &m_value.boolean : nullptr; | ||
4019 | 2375 | } | ||
4020 | 2376 | |||
4021 | 2377 | /// get a pointer to the value (integer number) | ||
4022 | 2378 | number_integer_t* get_impl_ptr(number_integer_t*) noexcept | ||
4023 | 2379 | { | ||
4024 | 2380 | return is_number_integer() ? &m_value.number_integer : nullptr; | ||
4025 | 2381 | } | ||
4026 | 2382 | |||
4027 | 2383 | /// get a pointer to the value (integer number) | ||
4028 | 2384 | const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept | ||
4029 | 2385 | { | ||
4030 | 2386 | return is_number_integer() ? &m_value.number_integer : nullptr; | ||
4031 | 2387 | } | ||
4032 | 2388 | |||
4033 | 2389 | /// get a pointer to the value (floating-point number) | ||
4034 | 2390 | number_float_t* get_impl_ptr(number_float_t*) noexcept | ||
4035 | 2391 | { | ||
4036 | 2392 | return is_number_float() ? &m_value.number_float : nullptr; | ||
4037 | 2393 | } | ||
4038 | 2394 | |||
4039 | 2395 | /// get a pointer to the value (floating-point number) | ||
4040 | 2396 | const number_float_t* get_impl_ptr(const number_float_t*) const noexcept | ||
4041 | 2397 | { | ||
4042 | 2398 | return is_number_float() ? &m_value.number_float : nullptr; | ||
4043 | 2399 | } | ||
4044 | 2400 | |||
4045 | 2401 | public: | ||
4046 | 2402 | |||
4047 | 2403 | /// @name value access | ||
4048 | 2404 | /// @{ | ||
4049 | 2405 | |||
4050 | 2406 | /*! | ||
4051 | 2407 | @brief get a value (explicit) | ||
4052 | 2408 | |||
4053 | 2409 | Explicit type conversion between the JSON value and a compatible value. | ||
4054 | 2410 | |||
4055 | 2411 | @tparam ValueType non-pointer type compatible to the JSON value, for | ||
4056 | 2412 | instance `int` for JSON integer numbers, `bool` for JSON booleans, or | ||
4057 | 2413 | `std::vector` types for JSON arrays | ||
4058 | 2414 | |||
4059 | 2415 | @return copy of the JSON value, converted to type @a ValueType | ||
4060 | 2416 | |||
4061 | 2417 | @throw std::domain_error in case passed type @a ValueType is incompatible | ||
4062 | 2418 | to JSON; example: `"type must be object, but is null"` | ||
4063 | 2419 | |||
4064 | 2420 | @complexity Linear in the size of the JSON value. | ||
4065 | 2421 | |||
4066 | 2422 | @liveexample{The example below shows serveral conversions from JSON values | ||
4067 | 2423 | to other types. There a few things to note: (1) Floating-point numbers can | ||
4068 | 2424 | be converted to integers\, (2) A JSON array can be converted to a standard | ||
4069 | 2425 | `std::vector<short>`\, (3) A JSON object can be converted to C++ | ||
4070 | 2426 | assiciative containers such as `std::unordered_map<std::string\, | ||
4071 | 2427 | json>`.,get__ValueType_const} | ||
4072 | 2428 | |||
4073 | 2429 | @internal | ||
4074 | 2430 | The idea of using a casted null pointer to choose the correct | ||
4075 | 2431 | implementation is from <http://stackoverflow.com/a/8315197/266378>. | ||
4076 | 2432 | @endinternal | ||
4077 | 2433 | |||
4078 | 2434 | @sa @ref operator ValueType() const for implicit conversion | ||
4079 | 2435 | @sa @ref get() for pointer-member access | ||
4080 | 2436 | |||
4081 | 2437 | @since version 1.0.0 | ||
4082 | 2438 | */ | ||
4083 | 2439 | template<typename ValueType, typename | ||
4084 | 2440 | std::enable_if< | ||
4085 | 2441 | not std::is_pointer<ValueType>::value | ||
4086 | 2442 | , int>::type = 0> | ||
4087 | 2443 | ValueType get() const | ||
4088 | 2444 | { | ||
4089 | 2445 | return get_impl(static_cast<ValueType*>(nullptr)); | ||
4090 | 2446 | } | ||
4091 | 2447 | |||
4092 | 2448 | /*! | ||
4093 | 2449 | @brief get a pointer value (explicit) | ||
4094 | 2450 | |||
4095 | 2451 | Explicit pointer access to the internally stored JSON value. No copies are | ||
4096 | 2452 | made. | ||
4097 | 2453 | |||
4098 | 2454 | @warning The pointer becomes invalid if the underlying JSON object changes. | ||
4099 | 2455 | |||
4100 | 2456 | @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref | ||
4101 | 2457 | object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref | ||
4102 | 2458 | number_float_t. | ||
4103 | 2459 | |||
4104 | 2460 | @return pointer to the internally stored JSON value if the requested | ||
4105 | 2461 | pointer type @a PointerType fits to the JSON value; `nullptr` otherwise | ||
4106 | 2462 | |||
4107 | 2463 | @complexity Constant. | ||
4108 | 2464 | |||
4109 | 2465 | @liveexample{The example below shows how pointers to internal values of a | ||
4110 | 2466 | JSON value can be requested. Note that no type conversions are made and a | ||
4111 | 2467 | `nullptr` is returned if the value and the requested pointer type does not | ||
4112 | 2468 | match.,get__PointerType} | ||
4113 | 2469 | |||
4114 | 2470 | @sa @ref get_ptr() for explicit pointer-member access | ||
4115 | 2471 | |||
4116 | 2472 | @since version 1.0.0 | ||
4117 | 2473 | */ | ||
4118 | 2474 | template<typename PointerType, typename | ||
4119 | 2475 | std::enable_if< | ||
4120 | 2476 | std::is_pointer<PointerType>::value | ||
4121 | 2477 | , int>::type = 0> | ||
4122 | 2478 | PointerType get() noexcept | ||
4123 | 2479 | { | ||
4124 | 2480 | // delegate the call to get_ptr | ||
4125 | 2481 | return get_ptr<PointerType>(); | ||
4126 | 2482 | } | ||
4127 | 2483 | |||
4128 | 2484 | /*! | ||
4129 | 2485 | @brief get a pointer value (explicit) | ||
4130 | 2486 | @copydoc get() | ||
4131 | 2487 | */ | ||
4132 | 2488 | template<typename PointerType, typename | ||
4133 | 2489 | std::enable_if< | ||
4134 | 2490 | std::is_pointer<PointerType>::value | ||
4135 | 2491 | , int>::type = 0> | ||
4136 | 2492 | const PointerType get() const noexcept | ||
4137 | 2493 | { | ||
4138 | 2494 | // delegate the call to get_ptr | ||
4139 | 2495 | return get_ptr<PointerType>(); | ||
4140 | 2496 | } | ||
4141 | 2497 | |||
4142 | 2498 | /*! | ||
4143 | 2499 | @brief get a pointer value (implicit) | ||
4144 | 2500 | |||
4145 | 2501 | Implict pointer access to the internally stored JSON value. No copies are | ||
4146 | 2502 | made. | ||
4147 | 2503 | |||
4148 | 2504 | @warning Writing data to the pointee of the result yields an undefined | ||
4149 | 2505 | state. | ||
4150 | 2506 | |||
4151 | 2507 | @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref | ||
4152 | 2508 | object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref | ||
4153 | 2509 | number_float_t. | ||
4154 | 2510 | |||
4155 | 2511 | @return pointer to the internally stored JSON value if the requested | ||
4156 | 2512 | pointer type @a PointerType fits to the JSON value; `nullptr` otherwise | ||
4157 | 2513 | |||
4158 | 2514 | @complexity Constant. | ||
4159 | 2515 | |||
4160 | 2516 | @liveexample{The example below shows how pointers to internal values of a | ||
4161 | 2517 | JSON value can be requested. Note that no type conversions are made and a | ||
4162 | 2518 | `nullptr` is returned if the value and the requested pointer type does not | ||
4163 | 2519 | match.,get_ptr} | ||
4164 | 2520 | |||
4165 | 2521 | @since version 1.0.0 | ||
4166 | 2522 | */ | ||
4167 | 2523 | template<typename PointerType, typename | ||
4168 | 2524 | std::enable_if< | ||
4169 | 2525 | std::is_pointer<PointerType>::value | ||
4170 | 2526 | , int>::type = 0> | ||
4171 | 2527 | PointerType get_ptr() noexcept | ||
4172 | 2528 | { | ||
4173 | 2529 | // delegate the call to get_impl_ptr<>() | ||
4174 | 2530 | return get_impl_ptr(static_cast<PointerType>(nullptr)); | ||
4175 | 2531 | } | ||
4176 | 2532 | |||
4177 | 2533 | /*! | ||
4178 | 2534 | @brief get a pointer value (implicit) | ||
4179 | 2535 | @copydoc get_ptr() | ||
4180 | 2536 | */ | ||
4181 | 2537 | template<typename PointerType, typename | ||
4182 | 2538 | std::enable_if< | ||
4183 | 2539 | std::is_pointer<PointerType>::value | ||
4184 | 2540 | and std::is_const<typename std::remove_pointer<PointerType>::type>::value | ||
4185 | 2541 | , int>::type = 0> | ||
4186 | 2542 | const PointerType get_ptr() const noexcept | ||
4187 | 2543 | { | ||
4188 | 2544 | // delegate the call to get_impl_ptr<>() const | ||
4189 | 2545 | return get_impl_ptr(static_cast<const PointerType>(nullptr)); | ||
4190 | 2546 | } | ||
4191 | 2547 | |||
4192 | 2548 | /*! | ||
4193 | 2549 | @brief get a value (implicit) | ||
4194 | 2550 | |||
4195 | 2551 | Implict type conversion between the JSON value and a compatible value. The | ||
4196 | 2552 | call is realized by calling @ref get() const. | ||
4197 | 2553 | |||
4198 | 2554 | @tparam ValueType non-pointer type compatible to the JSON value, for | ||
4199 | 2555 | instance `int` for JSON integer numbers, `bool` for JSON booleans, or | ||
4200 | 2556 | `std::vector` types for JSON arrays. The character type of @ref string_t | ||
4201 | 2557 | as well as an initializer list of this type is excluded to avoid | ||
4202 | 2558 | ambiguities as these types implicitly convert to `std::string`. | ||
4203 | 2559 | |||
4204 | 2560 | @return copy of the JSON value, converted to type @a ValueType | ||
4205 | 2561 | |||
4206 | 2562 | @throw std::domain_error in case passed type @a ValueType is incompatible | ||
4207 | 2563 | to JSON, thrown by @ref get() const | ||
4208 | 2564 | |||
4209 | 2565 | @complexity Linear in the size of the JSON value. | ||
4210 | 2566 | |||
4211 | 2567 | @liveexample{The example below shows serveral conversions from JSON values | ||
4212 | 2568 | to other types. There a few things to note: (1) Floating-point numbers can | ||
4213 | 2569 | be converted to integers\, (2) A JSON array can be converted to a standard | ||
4214 | 2570 | `std::vector<short>`\, (3) A JSON object can be converted to C++ | ||
4215 | 2571 | assiciative containers such as `std::unordered_map<std::string\, | ||
4216 | 2572 | json>`.,operator__ValueType} | ||
4217 | 2573 | |||
4218 | 2574 | @since version 1.0.0 | ||
4219 | 2575 | */ | ||
4220 | 2576 | template<typename ValueType, typename | ||
4221 | 2577 | std::enable_if< | ||
4222 | 2578 | not std::is_pointer<ValueType>::value | ||
4223 | 2579 | and not std::is_same<ValueType, typename string_t::value_type>::value | ||
4224 | 2580 | and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value | ||
4225 | 2581 | , int>::type = 0> | ||
4226 | 2582 | operator ValueType() const | ||
4227 | 2583 | { | ||
4228 | 2584 | // delegate the call to get<>() const | ||
4229 | 2585 | return get<ValueType>(); | ||
4230 | 2586 | } | ||
4231 | 2587 | |||
4232 | 2588 | /// @} | ||
4233 | 2589 | |||
4234 | 2590 | |||
4235 | 2591 | //////////////////// | ||
4236 | 2592 | // element access // | ||
4237 | 2593 | //////////////////// | ||
4238 | 2594 | |||
4239 | 2595 | /// @name element access | ||
4240 | 2596 | /// @{ | ||
4241 | 2597 | |||
4242 | 2598 | /*! | ||
4243 | 2599 | @brief access specified array element with bounds checking | ||
4244 | 2600 | |||
4245 | 2601 | Returns a reference to the element at specified location @a idx, with | ||
4246 | 2602 | bounds checking. | ||
4247 | 2603 | |||
4248 | 2604 | @param[in] idx index of the element to access | ||
4249 | 2605 | |||
4250 | 2606 | @return reference to the element at index @a idx | ||
4251 | 2607 | |||
4252 | 2608 | @throw std::domain_error if the JSON value is not an array; example: | ||
4253 | 2609 | `"cannot use at() with string"` | ||
4254 | 2610 | @throw std::out_of_range if the index @a idx is out of range of the array; | ||
4255 | 2611 | that is, `idx >= size()`; example: `"array index 7 is out of range"` | ||
4256 | 2612 | |||
4257 | 2613 | @complexity Constant. | ||
4258 | 2614 | |||
4259 | 2615 | @liveexample{The example below shows how array elements can be read and | ||
4260 | 2616 | written using at.,at__size_type} | ||
4261 | 2617 | |||
4262 | 2618 | @since version 1.0.0 | ||
4263 | 2619 | */ | ||
4264 | 2620 | reference at(size_type idx) | ||
4265 | 2621 | { | ||
4266 | 2622 | // at only works for arrays | ||
4267 | 2623 | if (is_array()) | ||
4268 | 2624 | { | ||
4269 | 2625 | try | ||
4270 | 2626 | { | ||
4271 | 2627 | return m_value.array->at(idx); | ||
4272 | 2628 | } | ||
4273 | 2629 | catch (std::out_of_range& e) | ||
4274 | 2630 | { | ||
4275 | 2631 | // create better exception explanation | ||
4276 | 2632 | throw std::out_of_range("array index " + std::to_string(idx) + " is out of range"); | ||
4277 | 2633 | } | ||
4278 | 2634 | } | ||
4279 | 2635 | else | ||
4280 | 2636 | { | ||
4281 | 2637 | throw std::domain_error("cannot use at() with " + type_name()); | ||
4282 | 2638 | } | ||
4283 | 2639 | } | ||
4284 | 2640 | |||
4285 | 2641 | /*! | ||
4286 | 2642 | @brief access specified array element with bounds checking | ||
4287 | 2643 | |||
4288 | 2644 | Returns a const reference to the element at specified location @a idx, with | ||
4289 | 2645 | bounds checking. | ||
4290 | 2646 | |||
4291 | 2647 | @param[in] idx index of the element to access | ||
4292 | 2648 | |||
4293 | 2649 | @return const reference to the element at index @a idx | ||
4294 | 2650 | |||
4295 | 2651 | @throw std::domain_error if the JSON value is not an array; example: | ||
4296 | 2652 | `"cannot use at() with string"` | ||
4297 | 2653 | @throw std::out_of_range if the index @a idx is out of range of the array; | ||
4298 | 2654 | that is, `idx >= size()`; example: `"array index 7 is out of range"` | ||
4299 | 2655 | |||
4300 | 2656 | @complexity Constant. | ||
4301 | 2657 | |||
4302 | 2658 | @liveexample{The example below shows how array elements can be read using | ||
4303 | 2659 | at.,at__size_type_const} | ||
4304 | 2660 | |||
4305 | 2661 | @since version 1.0.0 | ||
4306 | 2662 | */ | ||
4307 | 2663 | const_reference at(size_type idx) const | ||
4308 | 2664 | { | ||
4309 | 2665 | // at only works for arrays | ||
4310 | 2666 | if (is_array()) | ||
4311 | 2667 | { | ||
4312 | 2668 | try | ||
4313 | 2669 | { | ||
4314 | 2670 | return m_value.array->at(idx); | ||
4315 | 2671 | } | ||
4316 | 2672 | catch (std::out_of_range& e) | ||
4317 | 2673 | { | ||
4318 | 2674 | // create better exception explanation | ||
4319 | 2675 | throw std::out_of_range("array index " + std::to_string(idx) + " is out of range"); | ||
4320 | 2676 | } | ||
4321 | 2677 | } | ||
4322 | 2678 | else | ||
4323 | 2679 | { | ||
4324 | 2680 | throw std::domain_error("cannot use at() with " + type_name()); | ||
4325 | 2681 | } | ||
4326 | 2682 | } | ||
4327 | 2683 | |||
4328 | 2684 | /*! | ||
4329 | 2685 | @brief access specified object element with bounds checking | ||
4330 | 2686 | |||
4331 | 2687 | Returns a reference to the element at with specified key @a key, with | ||
4332 | 2688 | bounds checking. | ||
4333 | 2689 | |||
4334 | 2690 | @param[in] key key of the element to access | ||
4335 | 2691 | |||
4336 | 2692 | @return reference to the element at key @a key | ||
4337 | 2693 | |||
4338 | 2694 | @throw std::domain_error if the JSON value is not an object; example: | ||
4339 | 2695 | `"cannot use at() with boolean"` | ||
4340 | 2696 | @throw std::out_of_range if the key @a key is is not stored in the object; | ||
4341 | 2697 | that is, `find(key) == end()`; example: `"key "the fast" not found"` | ||
4342 | 2698 | |||
4343 | 2699 | @complexity Logarithmic in the size of the container. | ||
4344 | 2700 | |||
4345 | 2701 | @liveexample{The example below shows how object elements can be read and | ||
4346 | 2702 | written using at.,at__object_t_key_type} | ||
4347 | 2703 | |||
4348 | 2704 | @sa @ref operator[](const typename object_t::key_type&) for unchecked | ||
4349 | 2705 | access by reference | ||
4350 | 2706 | @sa @ref value() for access by value with a default value | ||
4351 | 2707 | |||
4352 | 2708 | @since version 1.0.0 | ||
4353 | 2709 | */ | ||
4354 | 2710 | reference at(const typename object_t::key_type& key) | ||
4355 | 2711 | { | ||
4356 | 2712 | // at only works for objects | ||
4357 | 2713 | if (is_object()) | ||
4358 | 2714 | { | ||
4359 | 2715 | try | ||
4360 | 2716 | { | ||
4361 | 2717 | return m_value.object->at(key); | ||
4362 | 2718 | } | ||
4363 | 2719 | catch (std::out_of_range& e) | ||
4364 | 2720 | { | ||
4365 | 2721 | // create better exception explanation | ||
4366 | 2722 | throw std::out_of_range("key '" + key + "' not found"); | ||
4367 | 2723 | } | ||
4368 | 2724 | } | ||
4369 | 2725 | else | ||
4370 | 2726 | { | ||
4371 | 2727 | throw std::domain_error("cannot use at() with " + type_name()); | ||
4372 | 2728 | } | ||
4373 | 2729 | } | ||
4374 | 2730 | |||
4375 | 2731 | /*! | ||
4376 | 2732 | @brief access specified object element with bounds checking | ||
4377 | 2733 | |||
4378 | 2734 | Returns a const reference to the element at with specified key @a key, with | ||
4379 | 2735 | bounds checking. | ||
4380 | 2736 | |||
4381 | 2737 | @param[in] key key of the element to access | ||
4382 | 2738 | |||
4383 | 2739 | @return const reference to the element at key @a key | ||
4384 | 2740 | |||
4385 | 2741 | @throw std::domain_error if the JSON value is not an object; example: | ||
4386 | 2742 | `"cannot use at() with boolean"` | ||
4387 | 2743 | @throw std::out_of_range if the key @a key is is not stored in the object; | ||
4388 | 2744 | that is, `find(key) == end()`; example: `"key "the fast" not found"` | ||
4389 | 2745 | |||
4390 | 2746 | @complexity Logarithmic in the size of the container. | ||
4391 | 2747 | |||
4392 | 2748 | @liveexample{The example below shows how object elements can be read using | ||
4393 | 2749 | at.,at__object_t_key_type_const} | ||
4394 | 2750 | |||
4395 | 2751 | @sa @ref operator[](const typename object_t::key_type&) for unchecked | ||
4396 | 2752 | access by reference | ||
4397 | 2753 | @sa @ref value() for access by value with a default value | ||
4398 | 2754 | |||
4399 | 2755 | @since version 1.0.0 | ||
4400 | 2756 | */ | ||
4401 | 2757 | const_reference at(const typename object_t::key_type& key) const | ||
4402 | 2758 | { | ||
4403 | 2759 | // at only works for objects | ||
4404 | 2760 | if (is_object()) | ||
4405 | 2761 | { | ||
4406 | 2762 | try | ||
4407 | 2763 | { | ||
4408 | 2764 | return m_value.object->at(key); | ||
4409 | 2765 | } | ||
4410 | 2766 | catch (std::out_of_range& e) | ||
4411 | 2767 | { | ||
4412 | 2768 | // create better exception explanation | ||
4413 | 2769 | throw std::out_of_range("key '" + key + "' not found"); | ||
4414 | 2770 | } | ||
4415 | 2771 | } | ||
4416 | 2772 | else | ||
4417 | 2773 | { | ||
4418 | 2774 | throw std::domain_error("cannot use at() with " + type_name()); | ||
4419 | 2775 | } | ||
4420 | 2776 | } | ||
4421 | 2777 | |||
4422 | 2778 | /*! | ||
4423 | 2779 | @brief access specified array element | ||
4424 | 2780 | |||
4425 | 2781 | Returns a reference to the element at specified location @a idx. | ||
4426 | 2782 | |||
4427 | 2783 | @note If @a idx is beyond the range of the array (i.e., `idx >= size()`), | ||
4428 | 2784 | then the array is silently filled up with `null` values to make `idx` a | ||
4429 | 2785 | valid reference to the last stored element. | ||
4430 | 2786 | |||
4431 | 2787 | @param[in] idx index of the element to access | ||
4432 | 2788 | |||
4433 | 2789 | @return reference to the element at index @a idx | ||
4434 | 2790 | |||
4435 | 2791 | @throw std::domain_error if JSON is not an array or null; example: `"cannot | ||
4436 | 2792 | use operator[] with null"` | ||
4437 | 2793 | |||
4438 | 2794 | @complexity Constant if @a idx is in the range of the array. Otherwise | ||
4439 | 2795 | linear in `idx - size()`. | ||
4440 | 2796 | |||
4441 | 2797 | @liveexample{The example below shows how array elements can be read and | ||
4442 | 2798 | written using [] operator. Note the addition of `null` | ||
4443 | 2799 | values.,operatorarray__size_type} | ||
4444 | 2800 | |||
4445 | 2801 | @since version 1.0.0 | ||
4446 | 2802 | */ | ||
4447 | 2803 | reference operator[](size_type idx) | ||
4448 | 2804 | { | ||
4449 | 2805 | // implicitly convert null to object | ||
4450 | 2806 | if (is_null()) | ||
4451 | 2807 | { | ||
4452 | 2808 | m_type = value_t::array; | ||
4453 | 2809 | m_value.array = create<array_t>(); | ||
4454 | 2810 | } | ||
4455 | 2811 | |||
4456 | 2812 | // [] only works for arrays | ||
4457 | 2813 | if (is_array()) | ||
4458 | 2814 | { | ||
4459 | 2815 | for (size_t i = m_value.array->size(); i <= idx; ++i) | ||
4460 | 2816 | { | ||
4461 | 2817 | m_value.array->push_back(basic_json()); | ||
4462 | 2818 | } | ||
4463 | 2819 | |||
4464 | 2820 | return m_value.array->operator[](idx); | ||
4465 | 2821 | } | ||
4466 | 2822 | else | ||
4467 | 2823 | { | ||
4468 | 2824 | throw std::domain_error("cannot use operator[] with " + type_name()); | ||
4469 | 2825 | } | ||
4470 | 2826 | } | ||
4471 | 2827 | |||
4472 | 2828 | /*! | ||
4473 | 2829 | @brief access specified array element | ||
4474 | 2830 | |||
4475 | 2831 | Returns a const reference to the element at specified location @a idx. | ||
4476 | 2832 | |||
4477 | 2833 | @param[in] idx index of the element to access | ||
4478 | 2834 | |||
4479 | 2835 | @return const reference to the element at index @a idx | ||
4480 | 2836 | |||
4481 | 2837 | @throw std::domain_error if JSON is not an array; example: `"cannot use | ||
4482 | 2838 | operator[] with null"` | ||
4483 | 2839 | |||
4484 | 2840 | @complexity Constant. | ||
4485 | 2841 | |||
4486 | 2842 | @liveexample{The example below shows how array elements can be read using | ||
4487 | 2843 | the [] operator.,operatorarray__size_type_const} | ||
4488 | 2844 | |||
4489 | 2845 | @since version 1.0.0 | ||
4490 | 2846 | */ | ||
4491 | 2847 | const_reference operator[](size_type idx) const | ||
4492 | 2848 | { | ||
4493 | 2849 | // at only works for arrays | ||
4494 | 2850 | if (is_array()) | ||
4495 | 2851 | { | ||
4496 | 2852 | return m_value.array->operator[](idx); | ||
4497 | 2853 | } | ||
4498 | 2854 | else | ||
4499 | 2855 | { | ||
4500 | 2856 | throw std::domain_error("cannot use operator[] with " + type_name()); | ||
4501 | 2857 | } | ||
4502 | 2858 | } | ||
4503 | 2859 | |||
4504 | 2860 | /*! | ||
4505 | 2861 | @brief access specified object element | ||
4506 | 2862 | |||
4507 | 2863 | Returns a reference to the element at with specified key @a key. | ||
4508 | 2864 | |||
4509 | 2865 | @note If @a key is not found in the object, then it is silently added to | ||
4510 | 2866 | the object and filled with a `null` value to make `key` a valid reference. | ||
4511 | 2867 | In case the value was `null` before, it is converted to an object. | ||
4512 | 2868 | |||
4513 | 2869 | @param[in] key key of the element to access | ||
4514 | 2870 | |||
4515 | 2871 | @return reference to the element at key @a key | ||
4516 | 2872 | |||
4517 | 2873 | @throw std::domain_error if JSON is not an object or null; example: | ||
4518 | 2874 | `"cannot use operator[] with null"` | ||
4519 | 2875 | |||
4520 | 2876 | @complexity Logarithmic in the size of the container. | ||
4521 | 2877 | |||
4522 | 2878 | @liveexample{The example below shows how object elements can be read and | ||
4523 | 2879 | written using the [] operator.,operatorarray__key_type} | ||
4524 | 2880 | |||
4525 | 2881 | @sa @ref at(const typename object_t::key_type&) for access by reference | ||
4526 | 2882 | with range checking | ||
4527 | 2883 | @sa @ref value() for access by value with a default value | ||
4528 | 2884 | |||
4529 | 2885 | @since version 1.0.0 | ||
4530 | 2886 | */ | ||
4531 | 2887 | reference operator[](const typename object_t::key_type& key) | ||
4532 | 2888 | { | ||
4533 | 2889 | // implicitly convert null to object | ||
4534 | 2890 | if (is_null()) | ||
4535 | 2891 | { | ||
4536 | 2892 | m_type = value_t::object; | ||
4537 | 2893 | m_value.object = create<object_t>(); | ||
4538 | 2894 | } | ||
4539 | 2895 | |||
4540 | 2896 | // [] only works for objects | ||
4541 | 2897 | if (is_object()) | ||
4542 | 2898 | { | ||
4543 | 2899 | return m_value.object->operator[](key); | ||
4544 | 2900 | } | ||
4545 | 2901 | else | ||
4546 | 2902 | { | ||
4547 | 2903 | throw std::domain_error("cannot use operator[] with " + type_name()); | ||
4548 | 2904 | } | ||
4549 | 2905 | } | ||
4550 | 2906 | |||
4551 | 2907 | /*! | ||
4552 | 2908 | @brief read-only access specified object element | ||
4553 | 2909 | |||
4554 | 2910 | Returns a const reference to the element at with specified key @a key. No | ||
4555 | 2911 | bounds checking is performed. | ||
4556 | 2912 | |||
4557 | 2913 | @warning If the element with key @a key does not exist, the behavior is | ||
4558 | 2914 | undefined. | ||
4559 | 2915 | |||
4560 | 2916 | @param[in] key key of the element to access | ||
4561 | 2917 | |||
4562 | 2918 | @return const reference to the element at key @a key | ||
4563 | 2919 | |||
4564 | 2920 | @throw std::domain_error if JSON is not an object; example: `"cannot use | ||
4565 | 2921 | operator[] with null"` | ||
4566 | 2922 | |||
4567 | 2923 | @complexity Logarithmic in the size of the container. | ||
4568 | 2924 | |||
4569 | 2925 | @liveexample{The example below shows how object elements can be read using | ||
4570 | 2926 | the [] operator.,operatorarray__key_type_const} | ||
4571 | 2927 | |||
4572 | 2928 | @sa @ref at(const typename object_t::key_type&) for access by reference | ||
4573 | 2929 | with range checking | ||
4574 | 2930 | @sa @ref value() for access by value with a default value | ||
4575 | 2931 | |||
4576 | 2932 | @since version 1.0.0 | ||
4577 | 2933 | */ | ||
4578 | 2934 | const_reference operator[](const typename object_t::key_type& key) const | ||
4579 | 2935 | { | ||
4580 | 2936 | // [] only works for objects | ||
4581 | 2937 | if (is_object()) | ||
4582 | 2938 | { | ||
4583 | 2939 | return m_value.object->find(key)->second; | ||
4584 | 2940 | } | ||
4585 | 2941 | else | ||
4586 | 2942 | { | ||
4587 | 2943 | throw std::domain_error("cannot use operator[] with " + type_name()); | ||
4588 | 2944 | } | ||
4589 | 2945 | } | ||
4590 | 2946 | |||
4591 | 2947 | /*! | ||
4592 | 2948 | @brief access specified object element | ||
4593 | 2949 | |||
4594 | 2950 | Returns a reference to the element at with specified key @a key. | ||
4595 | 2951 | |||
4596 | 2952 | @note If @a key is not found in the object, then it is silently added to | ||
4597 | 2953 | the object and filled with a `null` value to make `key` a valid reference. | ||
4598 | 2954 | In case the value was `null` before, it is converted to an object. | ||
4599 | 2955 | |||
4600 | 2956 | @note This function is required for compatibility reasons with Clang. | ||
4601 | 2957 | |||
4602 | 2958 | @param[in] key key of the element to access | ||
4603 | 2959 | |||
4604 | 2960 | @return reference to the element at key @a key | ||
4605 | 2961 | |||
4606 | 2962 | @throw std::domain_error if JSON is not an object or null; example: | ||
4607 | 2963 | `"cannot use operator[] with null"` | ||
4608 | 2964 | |||
4609 | 2965 | @complexity Logarithmic in the size of the container. | ||
4610 | 2966 | |||
4611 | 2967 | @liveexample{The example below shows how object elements can be read and | ||
4612 | 2968 | written using the [] operator.,operatorarray__key_type} | ||
4613 | 2969 | |||
4614 | 2970 | @sa @ref at(const typename object_t::key_type&) for access by reference | ||
4615 | 2971 | with range checking | ||
4616 | 2972 | @sa @ref value() for access by value with a default value | ||
4617 | 2973 | |||
4618 | 2974 | @since version 1.0.0 | ||
4619 | 2975 | */ | ||
4620 | 2976 | template<typename T, std::size_t n> | ||
4621 | 2977 | reference operator[](const T (&key)[n]) | ||
4622 | 2978 | { | ||
4623 | 2979 | // implicitly convert null to object | ||
4624 | 2980 | if (is_null()) | ||
4625 | 2981 | { | ||
4626 | 2982 | m_type = value_t::object; | ||
4627 | 2983 | m_value = value_t::object; | ||
4628 | 2984 | } | ||
4629 | 2985 | |||
4630 | 2986 | // at only works for objects | ||
4631 | 2987 | if (is_object()) | ||
4632 | 2988 | { | ||
4633 | 2989 | return m_value.object->operator[](key); | ||
4634 | 2990 | } | ||
4635 | 2991 | else | ||
4636 | 2992 | { | ||
4637 | 2993 | throw std::domain_error("cannot use operator[] with " + type_name()); | ||
4638 | 2994 | } | ||
4639 | 2995 | } | ||
4640 | 2996 | |||
4641 | 2997 | /*! | ||
4642 | 2998 | @brief read-only access specified object element | ||
4643 | 2999 | |||
4644 | 3000 | Returns a const reference to the element at with specified key @a key. No | ||
4645 | 3001 | bounds checking is performed. | ||
4646 | 3002 | |||
4647 | 3003 | @warning If the element with key @a key does not exist, the behavior is | ||
4648 | 3004 | undefined. | ||
4649 | 3005 | |||
4650 | 3006 | @note This function is required for compatibility reasons with Clang. | ||
4651 | 3007 | |||
4652 | 3008 | @param[in] key key of the element to access | ||
4653 | 3009 | |||
4654 | 3010 | @return const reference to the element at key @a key | ||
4655 | 3011 | |||
4656 | 3012 | @throw std::domain_error if JSON is not an object; example: `"cannot use | ||
4657 | 3013 | operator[] with null"` | ||
4658 | 3014 | |||
4659 | 3015 | @complexity Logarithmic in the size of the container. | ||
4660 | 3016 | |||
4661 | 3017 | @liveexample{The example below shows how object elements can be read using | ||
4662 | 3018 | the [] operator.,operatorarray__key_type_const} | ||
4663 | 3019 | |||
4664 | 3020 | @sa @ref at(const typename object_t::key_type&) for access by reference | ||
4665 | 3021 | with range checking | ||
4666 | 3022 | @sa @ref value() for access by value with a default value | ||
4667 | 3023 | |||
4668 | 3024 | @since version 1.0.0 | ||
4669 | 3025 | */ | ||
4670 | 3026 | template<typename T, std::size_t n> | ||
4671 | 3027 | const_reference operator[](const T (&key)[n]) const | ||
4672 | 3028 | { | ||
4673 | 3029 | // at only works for objects | ||
4674 | 3030 | if (is_object()) | ||
4675 | 3031 | { | ||
4676 | 3032 | return m_value.object->find(key)->second; | ||
4677 | 3033 | } | ||
4678 | 3034 | else | ||
4679 | 3035 | { | ||
4680 | 3036 | throw std::domain_error("cannot use operator[] with " + type_name()); | ||
4681 | 3037 | } | ||
4682 | 3038 | } | ||
4683 | 3039 | |||
4684 | 3040 | /*! | ||
4685 | 3041 | @brief access specified object element with default value | ||
4686 | 3042 | |||
4687 | 3043 | Returns either a copy of an object's element at the specified key @a key or | ||
4688 | 3044 | a given default value if no element with key @a key exists. | ||
4689 | 3045 | |||
4690 | 3046 | The function is basically equivalent to executing | ||
4691 | 3047 | @code {.cpp} | ||
4692 | 3048 | try { | ||
4693 | 3049 | return at(key); | ||
4694 | 3050 | } catch(std::out_of_range) { | ||
4695 | 3051 | return default_value; | ||
4696 | 3052 | } | ||
4697 | 3053 | @endcode | ||
4698 | 3054 | |||
4699 | 3055 | @note Unlike @ref at(const typename object_t::key_type&), this function | ||
4700 | 3056 | does not throw if the given key @a key was not found. | ||
4701 | 3057 | |||
4702 | 3058 | @note Unlike @ref operator[](const typename object_t::key_type& key), this | ||
4703 | 3059 | function does not implicitly add an element to the position defined by @a | ||
4704 | 3060 | key. This function is furthermore also applicable to const objects. | ||
4705 | 3061 | |||
4706 | 3062 | @param[in] key key of the element to access | ||
4707 | 3063 | @param[in] default_value the value to return if @a key is not found | ||
4708 | 3064 | |||
4709 | 3065 | @tparam ValueType type compatible to JSON values, for instance `int` for | ||
4710 | 3066 | JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for | ||
4711 | 3067 | JSON arrays. Note the type of the expected value at @a key and the default | ||
4712 | 3068 | value @a default_value must be compatible. | ||
4713 | 3069 | |||
4714 | 3070 | @return copy of the element at key @a key or @a default_value if @a key | ||
4715 | 3071 | is not found | ||
4716 | 3072 | |||
4717 | 3073 | @throw std::domain_error if JSON is not an object; example: `"cannot use | ||
4718 | 3074 | value() with null"` | ||
4719 | 3075 | |||
4720 | 3076 | @complexity Logarithmic in the size of the container. | ||
4721 | 3077 | |||
4722 | 3078 | @liveexample{The example below shows how object elements can be queried | ||
4723 | 3079 | with a default value.,basic_json__value} | ||
4724 | 3080 | |||
4725 | 3081 | @sa @ref at(const typename object_t::key_type&) for access by reference | ||
4726 | 3082 | with range checking | ||
4727 | 3083 | @sa @ref operator[](const typename object_t::key_type&) for unchecked | ||
4728 | 3084 | access by reference | ||
4729 | 3085 | |||
4730 | 3086 | @since version 1.0.0 | ||
4731 | 3087 | */ | ||
4732 | 3088 | template <class ValueType, typename | ||
4733 | 3089 | std::enable_if< | ||
4734 | 3090 | std::is_convertible<basic_json_t, ValueType>::value | ||
4735 | 3091 | , int>::type = 0> | ||
4736 | 3092 | ValueType value(const typename object_t::key_type& key, ValueType default_value) const | ||
4737 | 3093 | { | ||
4738 | 3094 | // at only works for objects | ||
4739 | 3095 | if (is_object()) | ||
4740 | 3096 | { | ||
4741 | 3097 | // if key is found, return value and given default value otherwise | ||
4742 | 3098 | const auto it = find(key); | ||
4743 | 3099 | if (it != end()) | ||
4744 | 3100 | { | ||
4745 | 3101 | return *it; | ||
4746 | 3102 | } | ||
4747 | 3103 | else | ||
4748 | 3104 | { | ||
4749 | 3105 | return default_value; | ||
4750 | 3106 | } | ||
4751 | 3107 | } | ||
4752 | 3108 | else | ||
4753 | 3109 | { | ||
4754 | 3110 | throw std::domain_error("cannot use value() with " + type_name()); | ||
4755 | 3111 | } | ||
4756 | 3112 | } | ||
4757 | 3113 | |||
4758 | 3114 | /*! | ||
4759 | 3115 | @brief overload for a default value of type const char* | ||
4760 | 3116 | @copydoc basic_json::value() | ||
4761 | 3117 | */ | ||
4762 | 3118 | string_t value(const typename object_t::key_type& key, const char* default_value) const | ||
4763 | 3119 | { | ||
4764 | 3120 | return value(key, string_t(default_value)); | ||
4765 | 3121 | } | ||
4766 | 3122 | |||
4767 | 3123 | /*! | ||
4768 | 3124 | @brief access the first element | ||
4769 | 3125 | |||
4770 | 3126 | Returns a reference to the first element in the container. For a JSON | ||
4771 | 3127 | container `c`, the expression `c.front()` is equivalent to `*c.begin()`. | ||
4772 | 3128 | |||
4773 | 3129 | @return In case of a structured type (array or object), a reference to the | ||
4774 | 3130 | first element is returned. In cast of number, string, or boolean values, a | ||
4775 | 3131 | reference to the value is returned. | ||
4776 | 3132 | |||
4777 | 3133 | @complexity Constant. | ||
4778 | 3134 | |||
4779 | 3135 | @note Calling `front` on an empty container is undefined. | ||
4780 | 3136 | |||
4781 | 3137 | @throw std::out_of_range when called on null value | ||
4782 | 3138 | |||
4783 | 3139 | @liveexample{The following code shows an example for @ref front.,front} | ||
4784 | 3140 | |||
4785 | 3141 | @since version 1.0.0 | ||
4786 | 3142 | */ | ||
4787 | 3143 | reference front() | ||
4788 | 3144 | { | ||
4789 | 3145 | return *begin(); | ||
4790 | 3146 | } | ||
4791 | 3147 | |||
4792 | 3148 | /*! | ||
4793 | 3149 | @copydoc basic_json::front() | ||
4794 | 3150 | */ | ||
4795 | 3151 | const_reference front() const | ||
4796 | 3152 | { | ||
4797 | 3153 | return *cbegin(); | ||
4798 | 3154 | } | ||
4799 | 3155 | |||
4800 | 3156 | /*! | ||
4801 | 3157 | @brief access the last element | ||
4802 | 3158 | |||
4803 | 3159 | Returns a reference to the last element in the container. For a JSON | ||
4804 | 3160 | container `c`, the expression `c.back()` is equivalent to `{ auto tmp = | ||
4805 | 3161 | c.end(); --tmp; return *tmp; }`. | ||
4806 | 3162 | |||
4807 | 3163 | @return In case of a structured type (array or object), a reference to the | ||
4808 | 3164 | last element is returned. In cast of number, string, or boolean values, a | ||
4809 | 3165 | reference to the value is returned. | ||
4810 | 3166 | |||
4811 | 3167 | @complexity Constant. | ||
4812 | 3168 | |||
4813 | 3169 | @note Calling `back` on an empty container is undefined. | ||
4814 | 3170 | |||
4815 | 3171 | @throw std::out_of_range when called on null value. | ||
4816 | 3172 | |||
4817 | 3173 | @liveexample{The following code shows an example for @ref back.,back} | ||
4818 | 3174 | |||
4819 | 3175 | @since version 1.0.0 | ||
4820 | 3176 | */ | ||
4821 | 3177 | reference back() | ||
4822 | 3178 | { | ||
4823 | 3179 | auto tmp = end(); | ||
4824 | 3180 | --tmp; | ||
4825 | 3181 | return *tmp; | ||
4826 | 3182 | } | ||
4827 | 3183 | |||
4828 | 3184 | /*! | ||
4829 | 3185 | @copydoc basic_json::back() | ||
4830 | 3186 | */ | ||
4831 | 3187 | const_reference back() const | ||
4832 | 3188 | { | ||
4833 | 3189 | auto tmp = cend(); | ||
4834 | 3190 | --tmp; | ||
4835 | 3191 | return *tmp; | ||
4836 | 3192 | } | ||
4837 | 3193 | |||
4838 | 3194 | /*! | ||
4839 | 3195 | @brief remove element given an iterator | ||
4840 | 3196 | |||
4841 | 3197 | Removes the element specified by iterator @a pos. Invalidates iterators and | ||
4842 | 3198 | references at or after the point of the erase, including the end() | ||
4843 | 3199 | iterator. The iterator @a pos must be valid and dereferenceable. Thus the | ||
4844 | 3200 | end() iterator (which is valid, but is not dereferencable) cannot be used | ||
4845 | 3201 | as a value for @a pos. | ||
4846 | 3202 | |||
4847 | 3203 | If called on a primitive type other than null, the resulting JSON value | ||
4848 | 3204 | will be `null`. | ||
4849 | 3205 | |||
4850 | 3206 | @param[in] pos iterator to the element to remove | ||
4851 | 3207 | @return Iterator following the last removed element. If the iterator @a pos | ||
4852 | 3208 | refers to the last element, the end() iterator is returned. | ||
4853 | 3209 | |||
4854 | 3210 | @tparam InteratorType an @ref iterator or @ref const_iterator | ||
4855 | 3211 | |||
4856 | 3212 | @throw std::domain_error if called on a `null` value; example: `"cannot use | ||
4857 | 3213 | erase() with null"` | ||
4858 | 3214 | @throw std::domain_error if called on an iterator which does not belong to | ||
4859 | 3215 | the current JSON value; example: `"iterator does not fit current value"` | ||
4860 | 3216 | @throw std::out_of_range if called on a primitive type with invalid | ||
4861 | 3217 | iterator (i.e., any iterator which is not end()); example: `"iterator out | ||
4862 | 3218 | of range"` | ||
4863 | 3219 | |||
4864 | 3220 | @complexity The complexity depends on the type: | ||
4865 | 3221 | - objects: amortized constant | ||
4866 | 3222 | - arrays: linear in distance between pos and the end of the container | ||
4867 | 3223 | - strings: linear in the length of the string | ||
4868 | 3224 | - other types: constant | ||
4869 | 3225 | |||
4870 | 3226 | @liveexample{The example shows the result of erase for different JSON | ||
4871 | 3227 | types.,erase__IteratorType} | ||
4872 | 3228 | |||
4873 | 3229 | @sa @ref erase(InteratorType, InteratorType) -- removes the elements in the | ||
4874 | 3230 | given range | ||
4875 | 3231 | @sa @ref erase(const typename object_t::key_type&) -- remvoes the element | ||
4876 | 3232 | from an object at the given key | ||
4877 | 3233 | @sa @ref erase(const size_type) -- removes the element from an array at the | ||
4878 | 3234 | given index | ||
4879 | 3235 | |||
4880 | 3236 | @since version 1.0.0 | ||
4881 | 3237 | */ | ||
4882 | 3238 | template <class InteratorType, typename | ||
4883 | 3239 | std::enable_if< | ||
4884 | 3240 | std::is_same<InteratorType, typename basic_json_t::iterator>::value or | ||
4885 | 3241 | std::is_same<InteratorType, typename basic_json_t::const_iterator>::value | ||
4886 | 3242 | , int>::type | ||
4887 | 3243 | = 0> | ||
4888 | 3244 | InteratorType erase(InteratorType pos) | ||
4889 | 3245 | { | ||
4890 | 3246 | // make sure iterator fits the current value | ||
4891 | 3247 | if (this != pos.m_object) | ||
4892 | 3248 | { | ||
4893 | 3249 | throw std::domain_error("iterator does not fit current value"); | ||
4894 | 3250 | } | ||
4895 | 3251 | |||
4896 | 3252 | InteratorType result = end(); | ||
4897 | 3253 | |||
4898 | 3254 | switch (m_type) | ||
4899 | 3255 | { | ||
4900 | 3256 | case value_t::boolean: | ||
4901 | 3257 | case value_t::number_float: | ||
4902 | 3258 | case value_t::number_integer: | ||
4903 | 3259 | case value_t::string: | ||
4904 | 3260 | { | ||
4905 | 3261 | if (not pos.m_it.primitive_iterator.is_begin()) | ||
4906 | 3262 | { | ||
4907 | 3263 | throw std::out_of_range("iterator out of range"); | ||
4908 | 3264 | } | ||
4909 | 3265 | |||
4910 | 3266 | if (is_string()) | ||
4911 | 3267 | { | ||
4912 | 3268 | delete m_value.string; | ||
4913 | 3269 | m_value.string = nullptr; | ||
4914 | 3270 | } | ||
4915 | 3271 | |||
4916 | 3272 | m_type = value_t::null; | ||
4917 | 3273 | break; | ||
4918 | 3274 | } | ||
4919 | 3275 | |||
4920 | 3276 | case value_t::object: | ||
4921 | 3277 | { | ||
4922 | 3278 | result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); | ||
4923 | 3279 | break; | ||
4924 | 3280 | } | ||
4925 | 3281 | |||
4926 | 3282 | case value_t::array: | ||
4927 | 3283 | { | ||
4928 | 3284 | result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); | ||
4929 | 3285 | break; | ||
4930 | 3286 | } | ||
4931 | 3287 | |||
4932 | 3288 | default: | ||
4933 | 3289 | { | ||
4934 | 3290 | throw std::domain_error("cannot use erase() with " + type_name()); | ||
4935 | 3291 | } | ||
4936 | 3292 | } | ||
4937 | 3293 | |||
4938 | 3294 | return result; | ||
4939 | 3295 | } | ||
4940 | 3296 | |||
4941 | 3297 | /*! | ||
4942 | 3298 | @brief remove elements given an iterator range | ||
4943 | 3299 | |||
4944 | 3300 | Removes the element specified by the range `[first; last)`. Invalidates | ||
4945 | 3301 | iterators and references at or after the point of the erase, including the | ||
4946 | 3302 | end() iterator. The iterator @a first does not need to be dereferenceable | ||
4947 | 3303 | if `first == last`: erasing an empty range is a no-op. | ||
4948 | 3304 | |||
4949 | 3305 | If called on a primitive type other than null, the resulting JSON value | ||
4950 | 3306 | will be `null`. | ||
4951 | 3307 | |||
4952 | 3308 | @param[in] first iterator to the beginning of the range to remove | ||
4953 | 3309 | @param[in] last iterator past the end of the range to remove | ||
4954 | 3310 | @return Iterator following the last removed element. If the iterator @a | ||
4955 | 3311 | second refers to the last element, the end() iterator is returned. | ||
4956 | 3312 | |||
4957 | 3313 | @tparam InteratorType an @ref iterator or @ref const_iterator | ||
4958 | 3314 | |||
4959 | 3315 | @throw std::domain_error if called on a `null` value; example: `"cannot use | ||
4960 | 3316 | erase() with null"` | ||
4961 | 3317 | @throw std::domain_error if called on iterators which does not belong to | ||
4962 | 3318 | the current JSON value; example: `"iterators do not fit current value"` | ||
4963 | 3319 | @throw std::out_of_range if called on a primitive type with invalid | ||
4964 | 3320 | iterators (i.e., if `first != begin()` and `last != end()`); example: | ||
4965 | 3321 | `"iterators out of range"` | ||
4966 | 3322 | |||
4967 | 3323 | @complexity The complexity depends on the type: | ||
4968 | 3324 | - objects: `log(size()) + std::distance(first, last)` | ||
4969 | 3325 | - arrays: linear in the distance between @a first and @a last, plus linear | ||
4970 | 3326 | in the distance between @a last and end of the container | ||
4971 | 3327 | - strings: linear in the length of the string | ||
4972 | 3328 | - other types: constant | ||
4973 | 3329 | |||
4974 | 3330 | @liveexample{The example shows the result of erase for different JSON | ||
4975 | 3331 | types.,erase__IteratorType_IteratorType} | ||
4976 | 3332 | |||
4977 | 3333 | @sa @ref erase(InteratorType) -- removes the element at a given position | ||
4978 | 3334 | @sa @ref erase(const typename object_t::key_type&) -- remvoes the element | ||
4979 | 3335 | from an object at the given key | ||
4980 | 3336 | @sa @ref erase(const size_type) -- removes the element from an array at the | ||
4981 | 3337 | given index | ||
4982 | 3338 | |||
4983 | 3339 | @since version 1.0.0 | ||
4984 | 3340 | */ | ||
4985 | 3341 | template <class InteratorType, typename | ||
4986 | 3342 | std::enable_if< | ||
4987 | 3343 | std::is_same<InteratorType, typename basic_json_t::iterator>::value or | ||
4988 | 3344 | std::is_same<InteratorType, typename basic_json_t::const_iterator>::value | ||
4989 | 3345 | , int>::type | ||
4990 | 3346 | = 0> | ||
4991 | 3347 | InteratorType erase(InteratorType first, InteratorType last) | ||
4992 | 3348 | { | ||
4993 | 3349 | // make sure iterator fits the current value | ||
4994 | 3350 | if (this != first.m_object or this != last.m_object) | ||
4995 | 3351 | { | ||
4996 | 3352 | throw std::domain_error("iterators do not fit current value"); | ||
4997 | 3353 | } | ||
4998 | 3354 | |||
4999 | 3355 | InteratorType result = end(); | ||
5000 | 3356 |
The diff has been truncated for viewing.
LGTM