Merge lp:~thomas-voss/location-service/add-ichnaea-provider into lp:location-service/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
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.
Revision history for this message
Scott Sweeny (ssweeny) wrote :

LGTM

review: Approve
Revision history for this message
Simon Fels (morphis) wrote :

LGTM

review: Approve

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

Subscribers

People subscribed via source and target branches