Compare commits

..

286 Commits

Author SHA1 Message Date
Niels Lohmann
aafad2be1f Merge branch 'release/3.3.0' 2018-10-05 12:59:28 +02:00
Niels Lohmann
cdfe6ceda6 🔖 set version to 3.3.0 2018-10-05 11:20:10 +02:00
Niels Lohmann
b968faa882 🔖 set version to 3.3.0 2018-10-05 10:59:33 +02:00
Niels Lohmann
cd518fbbab 📝 small update to pass test suite 2018-10-05 08:58:38 +02:00
Niels Lohmann
b911654857 📝 updated contributor list 2018-10-04 22:30:18 +02:00
Niels Lohmann
bb55885215 💄 cleaned code 2018-10-04 20:42:19 +02:00
Niels Lohmann
5c7d27c338 Merge pull request #1272 from antonioborondo/fix_warning
Fix warning C4127: conditional expression is constant
2018-10-04 20:33:26 +02:00
Antonio Borondo
b6fdad9acd Remove anonymous namespace 2018-10-03 13:51:49 +01:00
Antonio Borondo
7c385a4844 Fix error: 'wide_string_input_helper' was not declared in this scope 2018-10-03 12:41:34 +01:00
Antonio Borondo
9ba3f79667 Fix error: explicit specialization in non-namespace scope 2018-10-03 12:26:24 +01:00
Antonio Borondo
8d1585f065 Change implementation to use templates 2018-10-03 11:44:02 +01:00
Antonio Borondo
ad3c216bb5 Generate header 2018-10-03 11:27:53 +01:00
Antonio Borondo
0231059290 Fix warning 2018-10-03 11:27:53 +01:00
Niels Lohmann
9f18e17063 Merge pull request #1270 from chuckatkins/add-more-cmake-docs
docs: Add additional CMake documentation
2018-10-03 10:11:27 +02:00
Niels Lohmann
53ec0a16f3 Merge pull request #1271 from chuckatkins/cleanup-deprecated-warnings
Turn off additional deprecation warnings for GCC.
2018-10-02 22:07:18 +02:00
Chuck Atkins
4c617611e2 docs: Add additional CMake documentation 2018-10-02 14:28:20 -04:00
Chuck Atkins
829571ab5c Turn off additional deprecation warnings for GCC.
In follow up from the conversation in #1269, this adds the
`-Wno-deprecate-declarations` flag to unit tests to allow them to
test deprecated APIs without all the noisy compiler warnings.
This also refactors the setting of build properties for test targets
to use `target_<...>` commands instead of `set_target_properties()`.
2018-10-02 13:01:19 -04:00
Niels Lohmann
c8231eff75 Merge pull request #1260 from chuckatkins/fix-cmake-target-alias
Fix broken cmake imported target alias
2018-10-01 17:44:50 +02:00
Chuck Atkins
02e653bdf7 docs: add a note in the readme about using the CMake imported target 2018-09-30 22:52:54 -04:00
Chuck Atkins
564506a885 cmake: add import config tests 2018-09-30 22:52:47 -04:00
Chuck Atkins
1729db85c1 cmake: fix package config to deal with versioning and namespaces 2018-09-30 09:56:33 -04:00
Niels Lohmann
910a895027 Merge pull request #1238 from theodelrieu/fix/1237
Fix issue #1237
2018-09-29 14:50:54 +02:00
Niels Lohmann
1fae82b7a7 Merge branch 'develop' into fix/1237 2018-09-29 14:50:36 +02:00
Niels Lohmann
22e55349a6 📝 added Wandbox link #1227 2018-09-29 14:33:39 +02:00
Niels Lohmann
70e587c3da 📝 added Wandbox link #1227 2018-09-29 14:33:21 +02:00
Niels Lohmann
d26f39466e Merge pull request #1231 from theodelrieu/feature/get_with_parameter
Add a get overload taking a parameter.
2018-09-29 14:30:04 +02:00
Niels Lohmann
c61a9071ae 🚨 fixed a compilation issue with ICPC #755
Closes #1222
2018-09-29 11:50:14 +02:00
Niels Lohmann
b59a58406e Merge branch 'develop' of https://github.com/nlohmann/json into develop 2018-09-29 11:48:52 +02:00
Niels Lohmann
4e54c9a13d 🚨 fixed a compilation issue with ICPC #755
Closes #1222
2018-09-29 11:48:49 +02:00
Niels Lohmann
95432c34f9 Merge pull request #1262 from knilch0r/patch-1
unit-testsuites.cpp: fix hangup if file not found
2018-09-29 10:58:10 +02:00
knilch
8c1387cfb3 unit-testsuites.cpp: fix hangup if file not found
If run from the wrong directory, std::ifstream f("test/data/big-list-of-naughty-strings/blns.json"); will not find the file and thus f.eof() will never return true.
Use canonical C++ file reading loop from https://gehrcke.de/2011/06/reading-files-in-c-using-ifstream-dealing-correctly-with-badbit-failbit-eofbit-and-perror/ instead.
2018-09-28 11:33:23 +02:00
Théo DELRIEU
521fe49fec Add basic_json::get_to function.
Takes an lvalue reference, and returns the same reference.

This allows non-default constructible types to be converted without
specializing adl_serializer.
This overload does not require CopyConstructible either.

Implements #1227
2018-09-28 11:25:23 +02:00
Niels Lohmann
680a4ab672 Merge pull request #1257 from henryiii/gcc48
GCC 48
2018-09-28 10:05:17 +02:00
Henry Fredrick Schreiner
7a37ba0c02 Adding 4.8 test to travis 2018-09-27 22:31:39 +02:00
Chris Harris
99b7c7c8ef Patch nlohmann/json for GCC 4.8
See https://github.com/nlohmann/json/pull/212 for details
2018-09-25 18:10:20 +02:00
Niels Lohmann
e184b6ecf2 Merge pull request #1252 from koponomarenko/fix-meson-build
Add version and license to meson.build
2018-09-22 14:49:03 +02:00
Niels Lohmann
88b055c2df Merge pull request #1249 from LEgregius/clang-3.4.2-crash-workaround
#1179 Reordered the code. It seems to stop clang 3.4.2 in RHEL 7 from crash…
2018-09-22 14:14:56 +02:00
Kostiantyn Ponomarenko
8799759b85 Add version and license to meson.build 2018-09-20 21:54:10 +03:00
Théo DELRIEU
4e52277b70 Fix issue #1237
* Make the conversion operator SFINAE correct.
* Workaround a GCC bug with some traits in type_traits.hpp

The first bullet-point implies that every `get`/`get_ptr` be SFINAE
correct as well.
2018-09-20 10:33:14 +02:00
Niels Lohmann
e4bc98d036 Merge pull request #1245 from chuckatkins/fix-target-namespace-backward-compatibility
Use a version check to provide backwards comatible CMake imported target names
2018-09-19 20:46:51 +02:00
David Guthrie
4d780b091b Reordered the code. It seems to stop clang 3.4.2 in RHEL 7 from crashing intermittently. 2018-09-18 16:38:59 -04:00
Chuck Atkins
3b1a5cafad Use a version check to provide backwards comatible imported target names. 2018-09-18 13:59:19 -04:00
Niels Lohmann
99939d6340 📝 added lgtm.com badge
See https://lgtm.com/projects/g/nlohmann/json
2018-09-18 19:27:52 +02:00
Niels Lohmann
4e2f35d4c2 👷 adding Xcode 10 worker
See https://blog.travis-ci.com/2018-09-13-xcode-10-is-now-available?utm_source=twitter&utm_medium=web&utm_campaign=xcode10_gm
2018-09-18 19:22:30 +02:00
Niels Lohmann
7fa3b8865c Merge pull request #1221 from rivertam/better-error-305
Better error 305
2018-09-18 12:49:07 +02:00
Ben Berman
8f07ab6392 Replace "key-style argument" with "string argument" 2018-09-17 15:36:38 -04:00
Niels Lohmann
186c747a19 Merge pull request #1230 from mandreyel/lambda-unevaluated-context-fix
Move lambda out of unevaluated context
2018-09-10 20:52:11 +02:00
mandreyel
6b5334c167 Move lambda out of unevaluated context 2018-09-10 13:34:59 +02:00
Niels Lohmann
ebb3c03293 🎨 cleanup after #1228 2018-09-09 18:19:33 +02:00
Niels Lohmann
d3428b35c5 Merge pull request #1228 from theodelrieu/remove_static_asserts
Remove static asserts
2018-09-09 18:12:43 +02:00
Théo DELRIEU
aea648bb7a remove now-useless traits. check for is_basic_json where needed 2018-09-07 14:10:39 +02:00
Théo DELRIEU
4b4bbceebf make from_json SFINAE-correct 2018-09-07 14:10:37 +02:00
Théo DELRIEU
f7971f04a5 make to_json SFINAE-correct 2018-09-07 12:18:04 +02:00
Théo DELRIEU
f7c8a2145a refactor from/to_json(CompatibleArrayType) 2018-09-07 12:18:04 +02:00
Théo DELRIEU
628f76729e do not check for compatible_object_type in compatible_array_type 2018-09-07 12:18:03 +02:00
Théo DELRIEU
29f72966c3 refactor is_compatible_type, remove conjunction & co 2018-09-07 12:18:03 +02:00
Théo DELRIEU
77967e6548 refactor is_compatible_integer_type 2018-09-07 12:18:03 +02:00
Théo DELRIEU
13760857ff refactor is_compatible_array_type 2018-09-07 12:18:02 +02:00
Théo DELRIEU
924e95c6e8 refactor is_compatible_string_type 2018-09-07 12:18:02 +02:00
Théo DELRIEU
e84195ab7b refactor is_compatible_object_type 2018-09-07 12:18:02 +02:00
Théo DELRIEU
b59c3367c9 use detected instead of has_* traits 2018-09-07 12:17:59 +02:00
Théo DELRIEU
1ea8cd128c fix void_t for older compilers 2018-09-07 12:17:33 +02:00
Niels Lohmann
eb30ff0615 🚨 fixed a compiler warning #1224 2018-09-06 07:25:19 +02:00
Ben Berman
ad053ef09c Fix tests for improved error 305(hopefully) 2018-08-30 13:21:55 -04:00
Ben Berman
bbdfe7dea6 Improve error messages for error 305
Addresses #1220
2018-08-30 12:35:51 -04:00
Niels Lohmann
d713727f22 Merge pull request #1202 from dennisfischer/develop
Export package to allow builds without installing
2018-08-25 10:56:30 +02:00
Niels Lohmann
04597c3a66 Merge pull request #1214 from devsisters/fix-1213
Fix #1213
2018-08-24 17:54:28 +02:00
Hyeon Kim
aada309f61 Fix #1213 2018-08-24 21:55:13 +09:00
Niels Lohmann
359f98d140 Merge branch 'release/3.2.0' into develop 2018-08-20 19:36:25 +02:00
Niels Lohmann
8c20571136 Merge branch 'release/3.2.0' 2018-08-20 19:36:10 +02:00
Dennis Fischer
dfe607c6ff Export package to allow builds without installing 2018-08-20 09:23:12 +02:00
Niels Lohmann
9f3857ef6f 🔖 set version to 3.2.0 2018-08-18 18:46:15 +02:00
Niels Lohmann
7608a64e1e 🔨 fixed amalgamation 2018-08-18 18:14:12 +02:00
Niels Lohmann
a7b02bdce0 🔖 preparing 3.2.0 release 2018-08-18 17:48:49 +02:00
Niels Lohmann
c6a482b16c 📝 added example for sax_parse 2018-08-18 15:42:18 +02:00
Niels Lohmann
5ad52f4167 ⬆️ Catch 1.12.0 2018-08-18 12:02:12 +02:00
Niels Lohmann
3811daa8a3 📝 release preparation 2018-08-18 12:00:14 +02:00
Niels Lohmann
6899fa304c Merge branch 'develop' of https://github.com/nlohmann/json into develop 2018-08-18 08:15:06 +02:00
Niels Lohmann
57faaf42ca 🚨 fixed a compiler warning 2018-08-18 08:15:03 +02:00
Niels Lohmann
f78ac4fbd3 Merge pull request #1200 from thyu/develop
Fix -Wno-sometimes-uninitialized by initializing "result" in parse_sax
2018-08-18 08:14:04 +02:00
Tsz-Ho Yu
3004a73951 Fix -Wno-sometimes-uninitialized by initializing "result" in parse_sax
The function parse_sax() returns sometimes-uninitialized warnings in
some compilers. This commit fixes that.
2018-08-18 01:12:19 +01:00
Niels Lohmann
e33b31e6aa 🐛 fixed callback-related issue (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) 2018-08-17 23:09:45 +02:00
Niels Lohmann
b5c54b41fd 📝 overworked documentation 2018-08-16 21:53:47 +02:00
Niels Lohmann
07494e06d7 🚨 fixed some compiler warnings 2018-08-16 18:20:30 +02:00
Niels Lohmann
d5b21b051c Merge pull request #1153 from theodelrieu/refactor/no_virtual_sax
Refactor/no virtual sax
2018-08-16 17:47:55 +02:00
Théo DELRIEU
0cc3db4f15 add static_asserts on SAX interface 2018-08-16 11:59:57 +02:00
Théo DELRIEU
38f8a51a8f use abstract sax class in parser tests 2018-08-16 11:59:49 +02:00
Théo DELRIEU
9bbb133094 remove no_limit constant and default values 2018-08-16 11:59:05 +02:00
Théo DELRIEU
442886d040 use templates in the sax interface instead of virtuals 2018-08-16 11:58:52 +02:00
Théo DELRIEU
f6febbe359 split meta.hpp, add detected_t (used to define concepts) 2018-08-16 11:58:42 +02:00
Niels Lohmann
3ac2d81a95 🔨 fixed a MinGW error #1193 2018-08-14 22:13:56 +02:00
Niels Lohmann
be2065dce9 🚨 fixing a MinGW warning #1192 2018-08-14 22:11:47 +02:00
Niels Lohmann
fed70f6bff 🎨 reindented code 2018-08-14 22:11:08 +02:00
Niels Lohmann
0e748f2f8c Merge pull request #1187 from devsisters/json-internal-catch
[RFC] Introduce a new macro function: JSON_INTERNAL_CATCH
2018-08-14 21:56:29 +02:00
Niels Lohmann
861ee400cc Merge pull request #1176 from grembo/develop
Fix unit tests that were silently skipped or crashed (depending on the compiler)
2018-08-14 21:48:49 +02:00
Niels Lohmann
3ce4325350 📝 updated documentation of used compilers 2018-08-01 22:31:51 +02:00
Niels Lohmann
ba4a19d4af 👷 added more CI workers 2018-08-01 20:59:58 +02:00
Niels Lohmann
043eff5ba8 👷 added more CI workers 2018-07-31 21:18:33 +02:00
Michael Gmelin
05b27e83b7 Exclude bytewise comparison in certain tests.
These tests never worked - they weren't run before
d5aaeb4.

Note that these tests would fail because of this library
ordering dictionary keys (which is legal). So changing the
input files (or modifying stored cbor/msgpack/ubjson files)
would make the tests work and they could get removed from
"exclude_packaged".

Also move parsing of files in these unit tests to within
the inner sections, so that they're only parsed
number_of_files * number_of_sections instead of
number_of_files * number_of_files * number_of_sections
(so, instead of close to 100k parses about 700).
2018-07-29 14:52:52 +02:00
Michael Gmelin
d5aaeb4cce Make section names unique in loops, as catch doesn't support duplicate
sections, see also https://github.com/catchorg/Catch2/issues/816#issuecomment-278268122

As a result, when built with gcc, loop iterations were skipped. When
built with clang, the test aborted with an assertion in catch.hpp
line 6222.

This also addresses the issues discussed here:
https://github.com/nlohmann/json/issues/1032#issuecomment-378707696

and here:
https://github.com/catchorg/Catch2/issues/1241

Please note that this introduces new problems, as some of
the unit tests fail now - the library stores keys in
lexographical order, while the cbor/msgpack/ubjson examples
store them in original order.
2018-07-29 10:44:36 +02:00
Niels Lohmann
3760a38b7e 🏁 implicit conversion is not allowed with MSVC 2018-07-21 11:47:05 +02:00
Niels Lohmann
5b14411669 🏁 trying to fix C2440 error
Error in AppVeyor:

unit-conversions.cpp(441): error C2440: 'initializing': cannot convert from 'nlohmann::json' to 'std::nullptr_t'

(https://ci.appveyor.com/project/nlohmann/json/build/2838/job/wo7im01sq6tvhe9m)
2018-07-21 10:59:00 +02:00
Niels Lohmann
347e77bdc1 🚑 fix for #1169 2018-07-21 10:31:55 +02:00
Niels Lohmann
04372a8c56 🏁 fix for #1168 2018-07-19 17:31:50 +02:00
Hyeon Kim
d0e60de433 Add new JSON_INTERNAL_CATCH macro function 2018-07-19 15:43:41 +09:00
Niels Lohmann
7bfc406ded 📝 added note about CocoaPods #1148 2018-07-05 21:18:46 +02:00
Niels Lohmann
d456a2d777 Merge pull request #1151 from sonulohani/bigObjFix
Fixed compiler error in VS 2015 for debug mode
2018-06-29 09:03:43 +02:00
Sonu Lohani
b8ad3388ec Fixed compiler error in VS 2015 for debug mode
https://github.com/nlohmann/json/issues/1114
2018-06-29 09:34:41 +05:30
Niels Lohmann
39dd775e38 🔨 cleanup after #1134 2018-06-28 21:32:32 +02:00
Niels Lohmann
86a96b059d Merge pull request #1134 from Daniel599/feature/items_iterator
fixed compile error for #1045
2018-06-28 21:21:17 +02:00
Niels Lohmann
396a914f9e 🔨 added macro to disable compiler check #1128 2018-06-26 22:47:40 +02:00
Niels Lohmann
bab5826504 Merge pull request #1144 from jrakow/cppreference-link-fix
Fix links to cppreference named requirements (formerly concepts)
2018-06-26 07:58:45 +02:00
Niels Lohmann
515cfc2d89 Merge pull request #1142 from jrakow/develop
meson: fix include directory
2018-06-24 23:33:30 +02:00
Julius Rakow
963d06a13c 📝 fix links to cppreference named requirements
"Concepts" have been renamed to "named requirements".
This is because P0898R3 Standard Library Concepts has been merged into
C++20.
Cppreference have moved their links accordingly.
2018-06-24 22:36:19 +02:00
Julius Rakow
9f00db48d9 📝 link to cppreference via HTTPS 2018-06-24 22:34:47 +02:00
Julius Rakow
ec2ebd5ec9 meson: add multiple headers target 2018-06-24 18:07:30 +02:00
Julius Rakow
0bb36bb140 meson: fix include directory 2018-06-24 18:07:30 +02:00
Niels Lohmann
62457729e8 📝 mentioned MinGW in README 2018-06-24 18:03:59 +02:00
Niels Lohmann
09c0df4a21 👷 choosing correct image 2018-06-24 17:40:16 +02:00
Niels Lohmann
1bbc4a0859 👷 using Ninja to speed up build 2018-06-24 17:10:13 +02:00
Niels Lohmann
d8fe13fc83 🔨 fixed escaping for MinGW 2018-06-24 16:57:53 +02:00
Niels Lohmann
e59b930927 👷 trying a more recent compiler 2018-06-24 16:40:47 +02:00
Niels Lohmann
937d68e2e5 👷 forgot old PATH 2018-06-24 16:37:02 +02:00
Niels Lohmann
989ad9b759 👷 using help from https://stackoverflow.com/a/48509334/266378 2018-06-24 16:35:16 +02:00
Niels Lohmann
067e288289 👷 set build type 2018-06-24 16:29:03 +02:00
Niels Lohmann
7bbc06b487 👷 forgot quotes 2018-06-24 16:18:44 +02:00
Niels Lohmann
441e5d87e6 👷 experimenting with AppVeyor and MinGW 2018-06-24 16:17:06 +02:00
Niels Lohmann
7fa4ddf93e 💄 fixed indentation 2018-06-23 17:27:40 +02:00
Niels Lohmann
bf348ca8a4 Merge pull request #1028 from gracicot/develop
Added support for string_view in C++17
2018-06-23 17:10:04 +02:00
Niels Lohmann
ed6a0686df 🔨 small refactoring to improve branch coverage
The branch coverage reported by lcov is weird. The code before and after has the same Godbolt assembler, but the code with the lambda has a better branch coverage.
2018-06-23 17:05:04 +02:00
Niels Lohmann
c8bfdfd961 👷 tryping different platforms for AppVeyor 2018-06-23 11:12:32 +02:00
Niels Lohmann
c02de445bf 🚨 fixed more compiler warnings 2018-06-23 11:00:42 +02:00
Niels Lohmann
66dd1a846d 🚨 fixed more compiler warnings 2018-06-23 10:47:55 +02:00
Niels Lohmann
850922269d 🚨 removed compiler warnings 2018-06-23 10:28:04 +02:00
Niels Lohmann
0460b90977 📝 fix for #1052 #1139 2018-06-22 22:35:48 +02:00
Niels Lohmann
85f35a1d59 📝 documentation fix 2018-06-22 22:34:42 +02:00
Niels Lohmann
e7c1638d11 💄 cleanup 2018-06-18 22:03:46 +02:00
Niels Lohmann
1c81e9f5ae Merge pull request #1130 from agrianius/develop
test (non)equality for alt_string implementation
2018-06-18 22:01:53 +02:00
Niels Lohmann
d505ed7b31 Merge pull request #1138 from theodelrieu/feature/unordered_map_conversion
Feature/unordered map conversion
2018-06-18 21:59:46 +02:00
Théo DELRIEU
2c920a1032 run make amalgamate 2018-06-18 15:14:10 +02:00
Théo DELRIEU
2b37d7ed86 from_json: add overload for std::unordered_map
Fixes #1133
2018-06-18 15:14:10 +02:00
Théo DELRIEU
299469cfd5 from_json: add missing template arguments for std::map 2018-06-18 10:52:11 +02:00
Danielc
1566ad4053 fixed compile error for #1045; to_json for iternation_proxy_internal was needed 2018-06-16 12:01:49 +03:00
Vitaliy
f574d7e084 simplify templates for operators, add more checks 2018-06-14 15:07:06 +03:00
Vitaliy
cd28d872e7 forward declarations to make new compilers happy 2018-06-11 20:50:39 +03:00
Vitaliy
3d3055909c define global operator< for const char* and alt_string 2018-06-11 19:09:57 +03:00
Vitaliy
4feb8211ca test (non)equality for alt_string implementation 2018-06-11 18:03:46 +03:00
Guillaume Racicot
14e6278c2f Merge branch 'develop' of github.com:gracicot/json into develop 2018-06-04 11:18:25 -04:00
Guillaume Racicot
7acd90b651 Fixed check for compatible string type 2018-06-04 11:18:19 -04:00
Guillaume Racicot
5676a2a076 Aligned template declaration 2018-06-03 23:51:07 -04:00
Guillaume Racicot
e0e7fa39e7 Re-added external_constructor with string compatible types 2018-06-03 23:49:13 -04:00
Guillaume Racicot
4778c02ab5 Set MSVC version from 1514 and older 2018-06-01 14:42:25 -04:00
Guillaume Racicot
714c592680 Disabled implicit conversion to string_view on MSVC 15.13 and older 2018-06-01 14:22:57 -04:00
Niels Lohmann
e830bc502f Merge pull request #1117 from TinyTinni/develop
remove stringstream dependency
2018-06-01 08:05:45 +02:00
Matthias Möller
ecadcdb593 added char cast
should fix the GCC unittest
2018-05-31 16:36:16 +02:00
Matthias Möller
48656a49f5 typo 2018-05-31 15:32:21 +02:00
Matthias Möller
64acb42aa7 remove stringstream dependency 2018-05-31 13:45:58 +02:00
Niels Lohmann
8efbf8d7bb 📝 documentation to avoid future issues like #1108 2018-05-28 18:14:44 +02:00
Niels Lohmann
e5a67fc3f8 Merge branch 'develop' of https://github.com/nlohmann/json into develop 2018-05-28 17:57:46 +02:00
Niels Lohmann
a49644ab74 🚑 adjusted Fuzzer to new parser
out_of_range exceptions where unexpected before - the parser used to crash in these situations...
2018-05-28 17:57:22 +02:00
Niels Lohmann
0efaf891e5 Merge pull request #1089 from theodelrieu/feature/map_conversion
Provide a from_json overload for std::map
2018-05-28 14:53:23 +02:00
Théo DELRIEU
c5e63fd684 Provide a from_json overload for std::map
This overload is chosen only when BasicJsonType::string_t
is not constructible from std::map::key_type.

Currently, converting a map to json treats it as an array of pairs.

fixes #1079
2018-05-28 11:06:24 +02:00
Niels Lohmann
db03d09312 Merge branch 'feature/key_ref' into develop (fixes #1098) 2018-05-27 22:26:00 +02:00
Niels Lohmann
cf9299d222 Merge branch 'feature/sax2' into develop #971 2018-05-27 18:12:59 +02:00
Niels Lohmann
3cdc4d784b 📝 added documentation 2018-05-27 18:07:53 +02:00
Niels Lohmann
adf09726b0 Merge branch 'develop' into feature/sax2 2018-05-27 14:26:13 +02:00
Niels Lohmann
481ace65c4 🔨 only calculate array index string when needed #1098 2018-05-27 12:04:22 +02:00
Niels Lohmann
1c6b332dcd 👌 mitigating cppcheck bug #1101 2018-05-26 14:10:13 +02:00
Niels Lohmann
90eb0a91e0 keys are now returned as const reference #1098 2018-05-26 13:26:40 +02:00
Niels Lohmann
1f84cc2c88 adjusted test cases 2018-05-17 16:50:37 +02:00
Niels Lohmann
717301d1bc Merge branch 'testsuite' into feature/sax2 2018-05-17 16:36:43 +02:00
Niels Lohmann
4639bb2c8f added more tests from recent nst's JSONTestSuite 2018-05-17 10:10:01 +02:00
Niels Lohmann
e94862a649 🚑 fixed error in callback logic 2018-05-06 19:00:49 +02:00
Niels Lohmann
ae213721b1 🔨 removed unget function for wstring parsers 2018-05-06 14:05:29 +02:00
Niels Lohmann
5ff2abb90d Merge branch 'develop' into feature/sax2 2018-05-06 13:29:23 +02:00
Niels Lohmann
567fe9b7a0 Merge pull request #1078 from martin-mfg/patch-1
fix typo in README
2018-05-04 17:04:35 +02:00
martin-mfg
377e956655 fix typo in readme
The README says:
> "The library itself contains of a single header file ..."

I guess "consists of a" is the wording that was intended here. Alternatively, "contains a" might also be what was intended. Either way, I think both versions work equally well and thus choose the one that I believe was intended.
2018-05-03 22:42:52 +02:00
Niels Lohmann
5da596385b Update issue templates 2018-05-03 18:35:56 +02:00
Niels Lohmann
7bbe7bb98f 🔥 removed old issue template 2018-05-03 18:35:21 +02:00
Niels Lohmann
14f01e1981 🔧 update issue templates 2018-05-03 18:32:53 +02:00
Niels Lohmann
86b0732a10 📝 added public key used for commits and releases 2018-05-03 18:11:42 +02:00
Niels Lohmann
ed69e50ad2 📄 added SPDX-License-Identifier 2018-05-03 17:41:45 +02:00
Niels Lohmann
5bc4ff9da3 Merge branch 'feature/wstring' into develop 2018-04-29 17:29:57 +02:00
Niels Lohmann
fa3e42f826 Merge branch 'develop' into feature/wstring 2018-04-29 13:16:12 +02:00
Niels Lohmann
b5d1755dfb 🔥 removed commented-out test cases #1060 2018-04-22 15:41:42 +02:00
Niels Lohmann
0ab8fab338 Merge pull request #1058 from dns13/patch-1
Fix typo
2018-04-17 23:26:00 +05:30
Jan Schöppach
65b4d8251b Fix typo in single_include, too 2018-04-17 13:02:36 +02:00
Jan Schöppach
53fb230098 Fix typo 2018-04-17 12:08:44 +02:00
Niels Lohmann
46ec2fddf8 📝 updated THANKS list 2018-04-10 18:13:37 +02:00
Niels Lohmann
b8bfd1140d Merge pull request #1048 from chuckatkins/misc-cmake-packaging-enhancements
Misc cmake packaging enhancements
2018-04-10 17:57:21 +02:00
Chuck Atkins
33a2154f8d Enable target namespaces and build dir project config
CMake convention is to use a project namespace, i.e. Foo::, for imported
targets.  When multiple targets are imported from a project, this looks
like Foo::Bar1 Foo::Bar2, etc.  This adds the nlohmann_json:: namespace to
the exported target names.

This also allows the generated project config files to be used from the
build directory instead of just the install directory.
2018-04-10 09:08:38 -04:00
Niels Lohmann
29362c6ace Merge pull request #1047 from jammehcow/patch-1
Fixed incorrect LLVM version number in README
2018-04-10 08:39:58 +02:00
Niels Lohmann
c02a3155d4 👷 added Xcode 9.3 builder
See https://blog.travis-ci.com/2018-04-09-say-bonjour-to-xcode-93-and-macos-high-sierra.
2018-04-10 08:39:28 +02:00
Niels Lohmann
8d8f890771 💩 first try on #1045 2018-04-10 08:29:07 +02:00
James Upjohn
7f20e9ddc7 Fixed incorrect version number in README
clang-900.0.39.2 is from LLVM 9.0.0, not 8.1.0
2018-04-10 17:16:44 +12:00
Chuck Atkins
031b88d315 Make the CMake install dir user-configurable 2018-04-09 11:31:25 -04:00
Guillaume Racicot
aaee18ce90 Added test for string conversion with string_view 2018-04-09 11:15:33 -04:00
Niels Lohmann
7c503c64b7 Merge pull request #1043 from coryan/patch-1
Fix trivial typo in comment.
2018-04-09 08:19:56 +02:00
Carlos O'Ryan
4286b16b71 Fix trivial typo in comment.
Not really important, but since I saw it.
2018-04-08 15:46:25 -04:00
Niels Lohmann
cf91b4f2bb Merge branch 'develop' into feature/wstring 2018-04-08 11:36:58 +02:00
Niels Lohmann
f924df1835 Merge branch 'develop' into feature/sax2 2018-04-08 11:36:44 +02:00
Niels Lohmann
acf10d9af7 Merge pull request #1041 from ax3l/topic-spack
Package Manager: Spack
2018-04-08 11:32:35 +02:00
Niels Lohmann
e1ea8369ad Merge branch 'develop' into feature/sax2 2018-04-08 09:31:59 +02:00
Niels Lohmann
40f279c59d Merge branch 'feature/issue1021' into develop 2018-04-08 09:28:37 +02:00
Niels Lohmann
18a0271a95 Merge branch 'develop' into feature/issue1021 2018-04-08 09:21:43 +02:00
Axel Huebl
1ae9896387 Package Manager: Spack
I contributed a package to the Spack package manager.

Spack is a flexible package manager that supports multiple versions,
configurations, platforms, and compilers. It is popular in
high-performance computing.
2018-04-08 01:12:49 +02:00
Niels Lohmann
83b143382e Merge pull request #1040 from ax3l/topic-debugViewMSVCcmakeMin
CMake: 3.8+ is Sufficient
2018-04-07 15:14:59 +02:00
Axel Huebl
e439a1a9a7 CMake: 3.8+ is Sufficient
The current CMake scripts depend on CMake 3.8+.
This allows us to remove previous work-arounds.
2018-04-07 13:15:44 +02:00
Niels Lohmann
495436a5d5 Merge pull request #1026 from ktonon/develop
Added public target_compile_features for auto and constexpr
2018-04-03 17:34:42 +02:00
Kevin Tonon
a35d414c39 Update CMake to latest on Travis 2018-04-03 08:28:07 -04:00
Niels Lohmann
08a7233d1b 🚑 fixed commit 1e08654 2018-04-02 22:38:44 +02:00
Niels Lohmann
1e08654f99 🔨 cleanup 2018-04-02 22:25:17 +02:00
Niels Lohmann
aa89c5e048 🔨 removing unget_character() function from input adapters #834 2018-04-02 21:10:48 +02:00
Niels Lohmann
6678eb2b4a improved test coverage #1031 2018-04-02 15:38:49 +02:00
Niels Lohmann
16c5bfeaad 👌 fixed compiler warnings #1031 2018-04-02 13:01:56 +02:00
Niels Lohmann
727dd4664b 🔨 trying to make tests run with MSVC #1031 2018-04-02 12:27:07 +02:00
Niels Lohmann
ab89ae4e50 🔨 trying to make tests run with MSVC #1031 2018-04-02 11:34:36 +02:00
Niels Lohmann
eb06d0531a 🚧 added input adapter for wide strings #1031 2018-04-01 19:12:36 +02:00
Niels Lohmann
ba6edd5634 🔨 cleanup 2018-03-30 00:38:18 +02:00
Niels Lohmann
850671b9f1 🔨 using a vector<bool> for the parser hierarchy 2018-03-29 18:45:43 +02:00
Niels Lohmann
4efa8cdb4c 💚 fixed Valgrind options #1030 2018-03-29 17:19:21 +02:00
Niels Lohmann
830c93fd09 📝 fixed example for operator> #1029 2018-03-29 17:07:55 +02:00
Guillaume Racicot
c78dbc366c Added test for conversion to string_view 2018-03-29 01:03:57 -04:00
Guillaume Racicot
53d8d57921 Amalgamate single include 2018-03-29 01:03:36 -04:00
Niels Lohmann
5f723bbec6 🔨 realized callback parser wirh SAX interface #971 2018-03-28 23:39:39 +02:00
Niels Lohmann
896a9db461 🔨 improved code #1021 2018-03-28 19:37:21 +02:00
Kevin Tonon
73cc5089e3 Using target_compile_features to specify C++ 11 standard 2018-03-28 13:11:49 -04:00
Niels Lohmann
a9baab76c2 🚑 fix for #1021 2018-03-28 18:20:55 +02:00
Niels Lohmann
4f6b2b6429 🔨 changed SAX interface 2018-03-21 20:12:06 +01:00
Niels Lohmann
2537677e4c improved test coverage 2018-03-20 23:40:01 +01:00
Niels Lohmann
9e1abb4842 improved coverage 2018-03-20 22:39:08 +01:00
Niels Lohmann
1e38ffc014 more tests 2018-03-20 20:04:11 +01:00
Niels Lohmann
25f56ff207 📝 updated documentation 2018-03-20 19:22:18 +01:00
Niels Lohmann
99ecca55c4 improved test coverage 2018-03-20 18:49:10 +01:00
Niels Lohmann
9e07e9b4ec implemented non-throwing binary reader 2018-03-19 22:48:13 +01:00
Niels Lohmann
a271ee5f16 ♻️ proper use of SAX parser for binary formats 2018-03-18 23:00:45 +01:00
Niels Lohmann
943d641054 🔨 some refactoring 2018-03-18 16:07:21 +01:00
Niels Lohmann
22929fe189 🚧 started a SAX/DOM/callback parser 2018-03-18 15:13:53 +01:00
Niels Lohmann
375b05a17d 🔨 cleanup 2018-03-17 23:31:18 +01:00
Niels Lohmann
606a25195f improved test coverage 2018-03-17 19:15:59 +01:00
Niels Lohmann
c87ffad45c ♻️ implemented a non-recursive parser 2018-03-17 14:46:50 +01:00
Guillaume Racicot
2a5506ed98 Amalgamated headers 2018-03-16 13:16:10 -04:00
Guillaume Racicot
8165707990 basic_json now supports getting many type of strings 2018-03-15 15:35:00 -04:00
Niels Lohmann
27cf05af8d Merge branch 'develop' into feature/sax2 2018-03-14 22:02:19 +01:00
Niels Lohmann
183390c10b Merge branch 'release/3.1.2' 2018-03-14 21:47:50 +01:00
Niels Lohmann
a52e8355b8 oops 2018-03-14 17:32:48 +01:00
Niels Lohmann
21410d50af 🏁 moved /Wall to CMake 2018-03-14 17:21:31 +01:00
Niels Lohmann
829ed74d66 🏁 experimenting with /Wall 2018-03-14 07:38:22 +01:00
Niels Lohmann
1262d474eb 🏁 fixed an MSVC warning 2018-03-14 07:32:28 +01:00
Niels Lohmann
282bafae4f 🔨 fixed compilation error 2018-03-14 07:18:42 +01:00
Niels Lohmann
abac6a0e84 Merge branch 'develop' into feature/sax2 2018-03-13 23:58:17 +01:00
Niels Lohmann
3d4f6a2940 🔨 cleaner exception interface 2018-03-11 22:47:25 +01:00
Niels Lohmann
ad47b0fbde ♻️ refactored binary readers to use a SAX parser 2018-03-11 18:47:38 +01:00
Niels Lohmann
149d2fd09c 💚 improved test coverage 2018-03-10 11:24:00 +01:00
Niels Lohmann
6399cd3039 Merge branch 'develop' into feature/sax2 2018-03-10 11:07:36 +01:00
Niels Lohmann
35e43df625 Merge branch 'develop' into feature/sax2 2018-03-09 21:56:30 +01:00
Niels Lohmann
7c1a788893 Merge branch 'develop' into feature/sax2 2018-03-08 07:39:37 +01:00
Niels Lohmann
8b379948d0 🔥 replaced acceptor with SAX parser 2018-03-07 22:40:48 +01:00
Niels Lohmann
303a0c5843 Merge branch 'develop' into feature/sax2 2018-03-07 22:26:01 +01:00
Niels Lohmann
5beab80553 🔨 using the SAX-DOM parser 2018-03-06 18:17:07 +01:00
Niels Lohmann
faf2546a15 🔨 simplified SAX-DOM parser 2018-03-06 07:19:05 +01:00
Niels Lohmann
5b9d03cfdb 🔨 added SAX-DOM-Parser 2018-03-05 21:06:00 +01:00
Niels Lohmann
9d27429527 🔨 added error messages to SAX interface 2018-03-05 16:46:35 +01:00
Niels Lohmann
86991d5204 Merge branch 'develop' into feature/sax2 2018-03-05 16:16:43 +01:00
Niels Lohmann
3ff9455332 🔨 added a SAX-DOM-Parser 2018-02-26 23:39:23 +01:00
Niels Lohmann
21352c4d8e ♻️ refactored SAX parser 2018-02-26 20:08:12 +01:00
Niels Lohmann
981e226ca2 Merge branch 'develop' into feature/sax2 2018-02-26 20:07:52 +01:00
Niels Lohmann
8d6b3d44d6 👌 fixed some compiler warnings 2018-02-25 18:35:16 +01:00
Niels Lohmann
8c7f46f7d0 🔨 removed a logic error and improved coverage 2018-02-25 17:10:30 +01:00
Niels Lohmann
922f7a3d0e added more tests for SAX parsing 2018-02-25 14:21:30 +01:00
Niels Lohmann
ac230e8b4b 🔨 fixed test cases to be more robust 2018-02-25 10:44:47 +01:00
Niels Lohmann
374ebacc51 added a SAX parser #971 2018-02-24 18:04:07 +01:00
Niels Lohmann
c8ea63a31b Merge branch 'release/3.1.1' 2018-02-13 19:36:20 +01:00
Niels Lohmann
15acf260ca Merge branch 'release/3.1.0' 2018-02-02 00:05:55 +01:00
Niels Lohmann
a43347e1f9 Merge branch 'develop' 2017-12-29 20:35:02 +01:00
Niels Lohmann
5681e55da8 Merge branch 'release/3.0.1' 2017-12-29 20:24:20 +01:00
Niels Lohmann
9f81beb5e2 Merge branch 'release/3.0.0' 2017-12-17 11:04:04 +01:00
Niels Lohmann
c0d511ea50 🔀 merge branch 'release/2.1.1' 2017-02-25 16:36:46 +01:00
Niels Lohmann
1e99a0273f 🔀 merge branch 'release/2.1.0' 2017-01-28 18:42:27 +01:00
Niels Lohmann
528bc96d7e Merge branch 'develop' 2017-01-02 16:41:33 +01:00
Niels Lohmann
1c98ce869c 🔀 merge branch 'release/2.0.10' 2017-01-02 16:37:52 +01:00
Niels Lohmann
6df60b0448 🔀 Merge branch 'release/2.0.9' 2016-12-16 21:34:54 +01:00
Niels Lohmann
272ebdc900 🔖 Merge branch 'release/2.0.8' 2016-12-02 20:07:14 +01:00
Niels
79a9d00e15 Merge branch 'develop' 2016-11-03 18:54:59 +01:00
Niels
a4d13c92ba Merge branch 'release/2.0.7' 2016-11-02 20:52:24 +01:00
Niels
60bba02cc6 Merge branch 'release/2.0.6' 2016-10-15 16:47:56 +02:00
475 changed files with 10639 additions and 3925 deletions

View File

@@ -54,7 +54,7 @@ To make changes, you need to edit the following files:
## Please don't
- The C++11 support varies between different **compilers** and versions. Please note the [list of supported compilers](https://github.com/nlohmann/json/blob/master/README.md#supported-compilers). Some compilers like GCC 4.8 (and earlier), Clang 3.3 (and earlier), or Microsoft Visual Studio 13.0 and earlier are known not to work due to missing or incomplete C++11 support. Please refrain from proposing changes that work around these compiler's limitations with `#ifdef`s or other means.
- The C++11 support varies between different **compilers** and versions. Please note the [list of supported compilers](https://github.com/nlohmann/json/blob/master/README.md#supported-compilers). Some compilers like GCC 4.7 (and earlier), Clang 3.3 (and earlier), or Microsoft Visual Studio 13.0 and earlier are known not to work due to missing or incomplete C++11 support. Please refrain from proposing changes that work around these compiler's limitations with `#ifdef`s or other means.
- Specifically, I am aware of compilation problems with **Microsoft Visual Studio** (there even is an [issue label](https://github.com/nlohmann/json/issues?utf8=✓&q=label%3A%22visual+studio%22+) for these kind of bugs). I understand that even in 2016, complete C++11 support isn't there yet. But please also understand that I do not want to drop features or uglify the code just to make Microsoft's sub-standard compiler happy. The past has shown that there are ways to express the functionality such that the code compiles with the most recent MSVC - unfortunately, this is not the main objective of the project.
- Please refrain from proposing changes that would **break [JSON](http://json.org) conformance**. If you propose a conformant extension of JSON to be supported by the library, please motivate this extension.
- We shall not extend the library to **support comments**. There is quite some [controversy](https://www.reddit.com/r/programming/comments/4v6chu/why_json_doesnt_support_comments_douglas_crockford/) around this topic, and there were quite some [issues](https://github.com/nlohmann/json/issues/376) on this. We believe that JSON is fine without comments.

View File

@@ -1,22 +1,19 @@
**Bug Report**
- What is the issue you have?
- Please describe the steps to reproduce the issue. Can you provide a small but working code example?
- What is the expected behavior?
- And what is the actual behavior instead?
- Which compiler and operating system are you using? Is it a [supported compiler](https://github.com/nlohmann/json#supported-compilers)?
- Did you use a released version of the library or the version from the `develop` branch?
- If you experience a compilation error: can you [compile and run the unit tests](https://github.com/nlohmann/json#execute-unit-tests)?
**Feature Request**
- Describe the feature in as much detail as possible.
- Include sample usage where appropriate.
---
name: Bug report
about: Create a report to help us improve
---
- What is the issue you have?
- Please describe the steps to reproduce the issue. Can you provide a small but working code example?
- What is the expected behavior?
- And what is the actual behavior instead?
- Which compiler and operating system are you using? Is it a [supported compiler](https://github.com/nlohmann/json#supported-compilers)?
- Did you use a released version of the library or the version from the `develop` branch?
- If you experience a compilation error: can you [compile and run the unit tests](https://github.com/nlohmann/json#execute-unit-tests)?

View File

@@ -0,0 +1,9 @@
---
name: Feature request
about: Suggest an idea for this project
---
- Describe the feature in as much detail as possible.
- Include sample usage where appropriate.

View File

@@ -13,7 +13,7 @@ Read the [Contribution Guidelines](https://github.com/nlohmann/json/blob/develop
## Please don't
- The C++11 support varies between different **compilers** and versions. Please note the [list of supported compilers](https://github.com/nlohmann/json/blob/master/README.md#supported-compilers). Some compilers like GCC 4.8 (and earlier), Clang 3.3 (and earlier), or Microsoft Visual Studio 13.0 and earlier are known not to work due to missing or incomplete C++11 support. Please refrain from proposing changes that work around these compiler's limitations with `#ifdef`s or other means.
- The C++11 support varies between different **compilers** and versions. Please note the [list of supported compilers](https://github.com/nlohmann/json/blob/master/README.md#supported-compilers). Some compilers like GCC 4.7 (and earlier), Clang 3.3 (and earlier), or Microsoft Visual Studio 13.0 and earlier are known not to work due to missing or incomplete C++11 support. Please refrain from proposing changes that work around these compiler's limitations with `#ifdef`s or other means.
- Specifically, I am aware of compilation problems with **Microsoft Visual Studio** (there even is an [issue label](https://github.com/nlohmann/json/issues?utf8=✓&q=label%3A%22visual+studio%22+) for these kind of bugs). I understand that even in 2016, complete C++11 support isn't there yet. But please also understand that I do not want to drop features or uglify the code just to make Microsoft's sub-standard compiler happy. The past has shown that there are ways to express the functionality such that the code compiles with the most recent MSVC - unfortunately, this is not the main objective of the project.
- Please refrain from proposing changes that would **break [JSON](http://json.org) conformance**. If you propose a conformant extension of JSON to be supported by the library, please motivate this extension.
- Please do not open pull requests that address **multiple issues**.

View File

@@ -155,11 +155,28 @@ matrix:
- os: osx
osx_image: xcode9.2
- os: osx
osx_image: xcode9.3
- os: osx
osx_image: xcode9.4
- os: osx
osx_image: xcode10
# Linux / GCC
- os: linux
compiler: gcc
env: COMPILER=g++-4.9
env: compiler=g++-4.8
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.8', 'ninja-build']
- os: linux
compiler: gcc
env: compiler=g++-4.9
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
@@ -189,15 +206,23 @@ matrix:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-7', 'ninja-build']
- os: linux
compiler: gcc
env: COMPILER=g++-8
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-8', 'ninja-build']
- os: linux
compiler: gcc
env:
- COMPILER=g++-7
- COMPILER=g++-8
- CXXFLAGS=-std=c++17
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-7', 'ninja-build']
packages: ['g++-8', 'ninja-build']
# Linux / Clang
@@ -257,15 +282,23 @@ matrix:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-5.0']
packages: ['g++-6', 'clang-5.0', 'ninja-build']
- os: linux
compiler: clang
env: COMPILER=clang++-6.0
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-6.0']
packages: ['g++-6', 'clang-6.0', 'ninja-build']
- os: linux
compiler: clang
env:
- COMPILER=clang++-5.0
- COMPILER=clang++-6.0
- CXXFLAGS=-std=c++1z
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-5.0']
packages: ['g++-6', 'clang-5.0', 'ninja-build']
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-6.0']
packages: ['g++-6', 'clang-6.0', 'ninja-build']
################
# build script #
@@ -277,6 +310,7 @@ script:
if [[ (-x $(which brew)) ]]; then
brew update
brew install cmake ninja
brew upgrade cmake
cmake --version
fi

View File

@@ -1,10 +1,10 @@
cmake_minimum_required(VERSION 3.0.0)
cmake_minimum_required(VERSION 3.8)
##
## PROJECT
## name and version
##
project(nlohmann_json VERSION 3.1.2 LANGUAGES CXX)
project(nlohmann_json VERSION 3.3.0 LANGUAGES CXX)
##
## INCLUDE
@@ -22,13 +22,15 @@ option(JSON_MultipleHeaders "Use non-amalgamated version of the library." OFF)
## CONFIGURATION
##
set(NLOHMANN_JSON_TARGET_NAME ${PROJECT_NAME})
set(NLOHMANN_JSON_CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}")
set(NLOHMANN_JSON_CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}"
CACHE INTERNAL "")
set(NLOHMANN_JSON_INCLUDE_INSTALL_DIR "include")
set(NLOHMANN_JSON_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
set(NLOHMANN_JSON_CMAKE_CONFIG_TEMPLATE "cmake/config.cmake.in")
set(NLOHMANN_JSON_CMAKE_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}/cmake_config")
set(NLOHMANN_JSON_CMAKE_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}")
set(NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
set(NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Config.cmake")
set(NLOHMANN_JSON_CMAKE_PROJECT_TARGETS_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Targets.cmake")
if (JSON_MultipleHeaders)
set(NLOHMANN_JSON_INCLUDE_BUILD_DIR "${PROJECT_SOURCE_DIR}/include/")
@@ -43,6 +45,8 @@ endif()
## create target and add include path
##
add_library(${NLOHMANN_JSON_TARGET_NAME} INTERFACE)
add_library(${PROJECT_NAME}::${NLOHMANN_JSON_TARGET_NAME} ALIAS ${NLOHMANN_JSON_TARGET_NAME})
target_compile_features(${NLOHMANN_JSON_TARGET_NAME} INTERFACE cxx_std_11)
target_include_directories(
${NLOHMANN_JSON_TARGET_NAME}
@@ -51,8 +55,8 @@ target_include_directories(
$<INSTALL_INTERFACE:include>
)
## add debug view defintion file for msvc (natvis) [cmake <= 3.2.2 does not support export of source files]
if (MSVC AND CMAKE_VERSION VERSION_GREATER "3.2.2")
## add debug view definition file for msvc (natvis)
if (MSVC)
set(NLOHMANN_ADD_NATVIS TRUE)
set(NLOHMANN_NATVIS_FILE "nlohmann_json.natvis")
target_sources(
@@ -62,7 +66,7 @@ if (MSVC AND CMAKE_VERSION VERSION_GREATER "3.2.2")
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${NLOHMANN_NATVIS_FILE}>
)
endif()
##
## TESTS
## create and configure the unit test target
@@ -82,10 +86,10 @@ include(CMakePackageConfigHelpers)
write_basic_package_version_file(
${NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE} COMPATIBILITY SameMajorVersion
)
configure_package_config_file(
configure_file(
${NLOHMANN_JSON_CMAKE_CONFIG_TEMPLATE}
${NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE}
INSTALL_DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
@ONLY
)
install(
@@ -102,6 +106,11 @@ if (NLOHMANN_ADD_NATVIS)
DESTINATION .
)
endif()
export(
TARGETS ${NLOHMANN_JSON_TARGET_NAME}
NAMESPACE ${PROJECT_NAME}::
FILE ${NLOHMANN_JSON_CMAKE_PROJECT_TARGETS_FILE}
)
install(
TARGETS ${NLOHMANN_JSON_TARGET_NAME}
EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME}
@@ -109,5 +118,6 @@ install(
)
install(
EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME}
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
)

View File

@@ -1,6 +1,254 @@
# Change Log
All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/).
## [v3.3.0](https://github.com/nlohmann/json/releases/tag/v3.3.0) (2018-10-05)
[Full Changelog](https://github.com/nlohmann/json/compare/v3.2.0...v3.3.0)
- When key is not found print the key name into error too [\#1273](https://github.com/nlohmann/json/issues/1273)
- Visual Studio 2017 15.8.5 "conditional expression is constant" warning on Line 1851 in json.hpp [\#1268](https://github.com/nlohmann/json/issues/1268)
- how can we get this working on WSL? [\#1264](https://github.com/nlohmann/json/issues/1264)
- Help needed [\#1259](https://github.com/nlohmann/json/issues/1259)
- A way to get to a JSON values "key" [\#1258](https://github.com/nlohmann/json/issues/1258)
- Two blackslashes on json output file [\#1253](https://github.com/nlohmann/json/issues/1253)
- Including nlohmann the badwrong way. [\#1250](https://github.com/nlohmann/json/issues/1250)
- how to build with clang? [\#1247](https://github.com/nlohmann/json/issues/1247)
- Cmake target\_link\_libraries unable to find nlohmann\_json since version 3.2.0 [\#1243](https://github.com/nlohmann/json/issues/1243)
- \[Question\] Access to end\(\) iterator reference [\#1242](https://github.com/nlohmann/json/issues/1242)
- Parsing different json format [\#1241](https://github.com/nlohmann/json/issues/1241)
- Parsing Multiple JSON Files [\#1240](https://github.com/nlohmann/json/issues/1240)
- Doesn't compile under C++17 [\#1239](https://github.com/nlohmann/json/issues/1239)
- Conversion operator for nlohmann::json is not SFINAE friendly [\#1237](https://github.com/nlohmann/json/issues/1237)
- Custom deserialization of number\_float\_t [\#1236](https://github.com/nlohmann/json/issues/1236)
- Move tests to a separate repo [\#1235](https://github.com/nlohmann/json/issues/1235)
- deprecated-declarations warnings when compiling tests with GCC 8.2.1. [\#1233](https://github.com/nlohmann/json/issues/1233)
- Incomplete type with json\_fwd.hpp [\#1232](https://github.com/nlohmann/json/issues/1232)
- Parse Error [\#1229](https://github.com/nlohmann/json/issues/1229)
- json::get function with argument [\#1227](https://github.com/nlohmann/json/issues/1227)
- questions regarding from\_json [\#1226](https://github.com/nlohmann/json/issues/1226)
- Lambda in unevaluated context [\#1225](https://github.com/nlohmann/json/issues/1225)
- NLohmann doesn't compile when enabling strict warning policies [\#1224](https://github.com/nlohmann/json/issues/1224)
- Creating array of objects [\#1223](https://github.com/nlohmann/json/issues/1223)
- Somewhat unhelpful error message "cannot use operator\[\] with object" [\#1220](https://github.com/nlohmann/json/issues/1220)
- single\_include json.hpp [\#1218](https://github.com/nlohmann/json/issues/1218)
- Maps with enum class keys which are convertible to JSON strings should be converted to JSON dictionaries [\#1217](https://github.com/nlohmann/json/issues/1217)
- Adding JSON Array to the Array [\#1216](https://github.com/nlohmann/json/issues/1216)
- Best way to output a vector of a given type to json [\#1215](https://github.com/nlohmann/json/issues/1215)
- compiler warning: double definition of macro JSON\_INTERNAL\_CATCH [\#1213](https://github.com/nlohmann/json/issues/1213)
- Compilation error when using MOCK\_METHOD1 from GMock and nlohmann::json [\#1212](https://github.com/nlohmann/json/issues/1212)
- Issues parsing a previously encoded binary \(non-UTF8\) string. [\#1211](https://github.com/nlohmann/json/issues/1211)
- Yet another ordering question: char \* and parse\(\) [\#1209](https://github.com/nlohmann/json/issues/1209)
- Error using gcc 8.1.0 on Ubuntu 14.04 [\#1207](https://github.com/nlohmann/json/issues/1207)
- "type must be string, but is " std::string\(j.type\_name\(\) [\#1206](https://github.com/nlohmann/json/issues/1206)
- Returning empty json object from a function of type const json& ? [\#1205](https://github.com/nlohmann/json/issues/1205)
- VS2017 compiler suggests using constexpr if [\#1204](https://github.com/nlohmann/json/issues/1204)
- Template instatiation error on compiling [\#1203](https://github.com/nlohmann/json/issues/1203)
- Soften the landing when dumping non-UTF8 strings \(type\_error.316 exception\) [\#1198](https://github.com/nlohmann/json/issues/1198)
- BUG - json dump field with unicode -\> array of ints \(instead of string\) [\#1197](https://github.com/nlohmann/json/issues/1197)
- Compile error using Code::Blocks // mingw-w64 GCC 8.1.0 - "Incomplete Type" [\#1193](https://github.com/nlohmann/json/issues/1193)
- SEGFAULT on arm target [\#1190](https://github.com/nlohmann/json/issues/1190)
- Compiler crash with old Clang [\#1179](https://github.com/nlohmann/json/issues/1179)
- Custom Precision on floating point numbers [\#1170](https://github.com/nlohmann/json/issues/1170)
- Can we have a json\_view class like std::string\_view? [\#1158](https://github.com/nlohmann/json/issues/1158)
- improve error handling [\#1152](https://github.com/nlohmann/json/issues/1152)
- We should remove static\_asserts [\#960](https://github.com/nlohmann/json/issues/960)
- Fix warning C4127: conditional expression is constant [\#1272](https://github.com/nlohmann/json/pull/1272) ([antonioborondo](https://github.com/antonioborondo))
- Turn off additional deprecation warnings for GCC. [\#1271](https://github.com/nlohmann/json/pull/1271) ([chuckatkins](https://github.com/chuckatkins))
- docs: Add additional CMake documentation [\#1270](https://github.com/nlohmann/json/pull/1270) ([chuckatkins](https://github.com/chuckatkins))
- unit-testsuites.cpp: fix hangup if file not found [\#1262](https://github.com/nlohmann/json/pull/1262) ([knilch0r](https://github.com/knilch0r))
- Fix broken cmake imported target alias [\#1260](https://github.com/nlohmann/json/pull/1260) ([chuckatkins](https://github.com/chuckatkins))
- GCC 48 [\#1257](https://github.com/nlohmann/json/pull/1257) ([henryiii](https://github.com/henryiii))
- Add version and license to meson.build [\#1252](https://github.com/nlohmann/json/pull/1252) ([koponomarenko](https://github.com/koponomarenko))
- \#1179 Reordered the code. It seems to stop clang 3.4.2 in RHEL 7 from crash… [\#1249](https://github.com/nlohmann/json/pull/1249) ([LEgregius](https://github.com/LEgregius))
- Use a version check to provide backwards comatible CMake imported target names [\#1245](https://github.com/nlohmann/json/pull/1245) ([chuckatkins](https://github.com/chuckatkins))
- Fix issue \#1237 [\#1238](https://github.com/nlohmann/json/pull/1238) ([theodelrieu](https://github.com/theodelrieu))
- Add a get overload taking a parameter. [\#1231](https://github.com/nlohmann/json/pull/1231) ([theodelrieu](https://github.com/theodelrieu))
- Move lambda out of unevaluated context [\#1230](https://github.com/nlohmann/json/pull/1230) ([mandreyel](https://github.com/mandreyel))
- Remove static asserts [\#1228](https://github.com/nlohmann/json/pull/1228) ([theodelrieu](https://github.com/theodelrieu))
- Better error 305 [\#1221](https://github.com/nlohmann/json/pull/1221) ([rivertam](https://github.com/rivertam))
- Fix \#1213 [\#1214](https://github.com/nlohmann/json/pull/1214) ([simnalamburt](https://github.com/simnalamburt))
- Export package to allow builds without installing [\#1202](https://github.com/nlohmann/json/pull/1202) ([dennisfischer](https://github.com/dennisfischer))
## [v3.2.0](https://github.com/nlohmann/json/releases/tag/v3.2.0) (2018-08-20)
[Full Changelog](https://github.com/nlohmann/json/compare/v3.1.2...v3.2.0)
- Am I doing this wrong? Getting an empty string [\#1199](https://github.com/nlohmann/json/issues/1199)
- Incompatible Pointer Type [\#1196](https://github.com/nlohmann/json/issues/1196)
- json.exception.type\_error.316 [\#1195](https://github.com/nlohmann/json/issues/1195)
- Strange warnings in Code::Blocks 17.12, GNU GCC [\#1192](https://github.com/nlohmann/json/issues/1192)
- \[Question\] Current place in code to change floating point resolution [\#1191](https://github.com/nlohmann/json/issues/1191)
- Add key name when throwing type error [\#1189](https://github.com/nlohmann/json/issues/1189)
- Not able to include in visual studio code? [\#1188](https://github.com/nlohmann/json/issues/1188)
- Get an Index or row number of an element [\#1186](https://github.com/nlohmann/json/issues/1186)
- reduce repos size [\#1185](https://github.com/nlohmann/json/issues/1185)
- Difference between `merge\_patch` and `update` [\#1183](https://github.com/nlohmann/json/issues/1183)
- Is there a way to get an element from a JSON without throwing an exception on failure? [\#1182](https://github.com/nlohmann/json/issues/1182)
- to\_string? [\#1181](https://github.com/nlohmann/json/issues/1181)
- How to cache a json object's pointer into a map? [\#1180](https://github.com/nlohmann/json/issues/1180)
- Can this library work within a Qt project for Android using Qt Creator? [\#1178](https://github.com/nlohmann/json/issues/1178)
- How to get all keys of one object? [\#1177](https://github.com/nlohmann/json/issues/1177)
- How can I only parse the first level and get the value as string? [\#1175](https://github.com/nlohmann/json/issues/1175)
- I have a query regarding nlohmann::basic\_json::basic\_json [\#1174](https://github.com/nlohmann/json/issues/1174)
- unordered\_map with vectors won't convert to json? [\#1173](https://github.com/nlohmann/json/issues/1173)
- return json objects from functions [\#1172](https://github.com/nlohmann/json/issues/1172)
- Problem when exporting to CBOR [\#1171](https://github.com/nlohmann/json/issues/1171)
- Roundtripping null to nullptr does not work [\#1169](https://github.com/nlohmann/json/issues/1169)
- MSVC fails to compile std::swap specialization for nlohmann::json [\#1168](https://github.com/nlohmann/json/issues/1168)
- Unexpected behaviour of is\_null - Part II [\#1167](https://github.com/nlohmann/json/issues/1167)
- Floating point imprecision [\#1166](https://github.com/nlohmann/json/issues/1166)
- Combine json objects into one? [\#1165](https://github.com/nlohmann/json/issues/1165)
- Is there any way to know if the object has changed? [\#1164](https://github.com/nlohmann/json/issues/1164)
- Value throws on null string [\#1163](https://github.com/nlohmann/json/issues/1163)
- Weird template issue in large project [\#1162](https://github.com/nlohmann/json/issues/1162)
- \_json returns a different result vs ::parse [\#1161](https://github.com/nlohmann/json/issues/1161)
- Showing difference between two json objects [\#1160](https://github.com/nlohmann/json/issues/1160)
- no instance of overloaded function "std::swap" matches the specified type [\#1159](https://github.com/nlohmann/json/issues/1159)
- resize\(...\)? [\#1157](https://github.com/nlohmann/json/issues/1157)
- Issue with struct nested in class' to\_json [\#1155](https://github.com/nlohmann/json/issues/1155)
- Deserialize std::map with std::nan [\#1154](https://github.com/nlohmann/json/issues/1154)
- Parse throwing errors [\#1149](https://github.com/nlohmann/json/issues/1149)
- cocoapod integration [\#1148](https://github.com/nlohmann/json/issues/1148)
- wstring parsing [\#1147](https://github.com/nlohmann/json/issues/1147)
- Is it possible to dump a two-dimensional array to "\[\[null\],\[1,2,3\]\]"? [\#1146](https://github.com/nlohmann/json/issues/1146)
- Want to write a class member variable and a struct variable \( this structure is inside the class\) to the json file [\#1145](https://github.com/nlohmann/json/issues/1145)
- Does json support converting an instance of a struct into json string? [\#1143](https://github.com/nlohmann/json/issues/1143)
- \#Most efficient way to search for child parameters \(recursive find?\) [\#1141](https://github.com/nlohmann/json/issues/1141)
- could not find to\_json\(\) method in T's namespace [\#1140](https://github.com/nlohmann/json/issues/1140)
- chars get treated as JSON numbers not JSON strings [\#1139](https://github.com/nlohmann/json/issues/1139)
- How do I count number of objects in array? [\#1137](https://github.com/nlohmann/json/issues/1137)
- Serializing a vector of classes? [\#1136](https://github.com/nlohmann/json/issues/1136)
- Compile error. Unable convert form nullptr to nullptr&& [\#1135](https://github.com/nlohmann/json/issues/1135)
- std::unordered\_map in struct, serialization [\#1133](https://github.com/nlohmann/json/issues/1133)
- dump\(\) can't handle umlauts [\#1131](https://github.com/nlohmann/json/issues/1131)
- Add a way to get a key reference from the iterator [\#1127](https://github.com/nlohmann/json/issues/1127)
- can't not parse "\\“ string [\#1123](https://github.com/nlohmann/json/issues/1123)
- if json file contain Internationalization chars , get exception [\#1122](https://github.com/nlohmann/json/issues/1122)
- How to use a json::iterator dereferenced value in code? [\#1120](https://github.com/nlohmann/json/issues/1120)
- clang compiler: error : unknown type name 'not' [\#1119](https://github.com/nlohmann/json/issues/1119)
- Disable implicit conversions from json to std::initializer\_list\<T\> for any T [\#1118](https://github.com/nlohmann/json/issues/1118)
- Implicit conversions to complex types can lead to surprising and confusing errors [\#1116](https://github.com/nlohmann/json/issues/1116)
- How can I write from\_json for a complex datatype that is not default constructible? [\#1115](https://github.com/nlohmann/json/issues/1115)
- Compile error in VS2015 when compiling unit-conversions.cpp [\#1114](https://github.com/nlohmann/json/issues/1114)
- ADL Serializer for std::any / boost::any [\#1113](https://github.com/nlohmann/json/issues/1113)
- Unexpected behaviour of is\_null [\#1112](https://github.com/nlohmann/json/issues/1112)
- How to resolve " undefined reference to `std::\_\_throw\_bad\_cast\(\)'" [\#1111](https://github.com/nlohmann/json/issues/1111)
- cannot compile on ubuntu 18.04 and 16.04 [\#1110](https://github.com/nlohmann/json/issues/1110)
- JSON representation for floating point values has too many digits [\#1109](https://github.com/nlohmann/json/issues/1109)
- Not working for classes containing "\_declspec\(dllimport\)" in their declaration [\#1108](https://github.com/nlohmann/json/issues/1108)
- Get keys from json object [\#1107](https://github.com/nlohmann/json/issues/1107)
- dump\(\) without alphabetical order [\#1106](https://github.com/nlohmann/json/issues/1106)
- Cannot deserialize types using std::ratio [\#1105](https://github.com/nlohmann/json/issues/1105)
- i want to learn json [\#1104](https://github.com/nlohmann/json/issues/1104)
- Type checking during compile [\#1103](https://github.com/nlohmann/json/issues/1103)
- Iterate through sub items [\#1102](https://github.com/nlohmann/json/issues/1102)
- cppcheck failing for version 3.1.2 [\#1101](https://github.com/nlohmann/json/issues/1101)
- Deserializing std::map [\#1100](https://github.com/nlohmann/json/issues/1100)
- accessing key by reference [\#1098](https://github.com/nlohmann/json/issues/1098)
- clang 3.8.0 croaks while trying to compile with debug symbols [\#1097](https://github.com/nlohmann/json/issues/1097)
- Serialize a list of class objects with json [\#1096](https://github.com/nlohmann/json/issues/1096)
- Null bytes in files are treated like EOF [\#1095](https://github.com/nlohmann/json/issues/1095)
- Small question [\#1094](https://github.com/nlohmann/json/issues/1094)
- Upgrading to 3.x: to\_/from\_json with enum class [\#1093](https://github.com/nlohmann/json/issues/1093)
- Q: few questions about json construction [\#1092](https://github.com/nlohmann/json/issues/1092)
- general crayCC compilation failure [\#1091](https://github.com/nlohmann/json/issues/1091)
- Merge Patch clears original data [\#1090](https://github.com/nlohmann/json/issues/1090)
- \[Question\] how to use nlohmann/json in c++? [\#1088](https://github.com/nlohmann/json/issues/1088)
- C++17 decomposition declaration support [\#1087](https://github.com/nlohmann/json/issues/1087)
- \[Question\] Access multi-level json objects [\#1086](https://github.com/nlohmann/json/issues/1086)
- Serializing vector [\#1085](https://github.com/nlohmann/json/issues/1085)
- update nested value in multi hierarchy json object [\#1084](https://github.com/nlohmann/json/issues/1084)
- Overriding default values? [\#1083](https://github.com/nlohmann/json/issues/1083)
- detail namespace collision with Cereal? [\#1082](https://github.com/nlohmann/json/issues/1082)
- Error using json.dump\(\); [\#1081](https://github.com/nlohmann/json/issues/1081)
- Consuming TCP Stream [\#1080](https://github.com/nlohmann/json/issues/1080)
- Compilation error with strong typed enums in map in combination with namespaces [\#1079](https://github.com/nlohmann/json/issues/1079)
- cassert error [\#1076](https://github.com/nlohmann/json/issues/1076)
- Valid json data not being parsed [\#1075](https://github.com/nlohmann/json/issues/1075)
- Feature request :: Better testing for key existance without try/catch [\#1074](https://github.com/nlohmann/json/issues/1074)
- Hi, I have input like a.b.c and want to convert it to \"a\"{\"b\": \"c\"} form. Any suggestions how do I do this? Thanks. [\#1073](https://github.com/nlohmann/json/issues/1073)
- ADL deserializer not picked up for non default-constructible type [\#1072](https://github.com/nlohmann/json/issues/1072)
- Deserializing std::array doesn't compiler \(no insert\(\)\) [\#1071](https://github.com/nlohmann/json/issues/1071)
- Serializing OpenCV Mat problem [\#1070](https://github.com/nlohmann/json/issues/1070)
- Compilation error with ICPC compiler [\#1068](https://github.com/nlohmann/json/issues/1068)
- Minimal branch? [\#1066](https://github.com/nlohmann/json/issues/1066)
- Not existing value, crash [\#1065](https://github.com/nlohmann/json/issues/1065)
- cyryllic symbols [\#1064](https://github.com/nlohmann/json/issues/1064)
- newbie usage question [\#1063](https://github.com/nlohmann/json/issues/1063)
- Trying j\["strTest"\] = "%A" produces "strTest": "-0X1.CCCCCCCCCCCCCP+205" [\#1062](https://github.com/nlohmann/json/issues/1062)
- convert json value to std::string??? [\#1061](https://github.com/nlohmann/json/issues/1061)
- Commented out test cases, should they be removed? [\#1060](https://github.com/nlohmann/json/issues/1060)
- different behaviour between clang and gcc with braced initialization [\#1059](https://github.com/nlohmann/json/issues/1059)
- json array: initialize with prescribed size and `resize` method. [\#1057](https://github.com/nlohmann/json/issues/1057)
- Is it possible to use exceptions istead of assertions? [\#1056](https://github.com/nlohmann/json/issues/1056)
- when using assign operator in with json object a static assertion fails.. [\#1055](https://github.com/nlohmann/json/issues/1055)
- Iterate over leafs of a JSON data structure: enrich the JSON pointer API [\#1054](https://github.com/nlohmann/json/issues/1054)
- \[Feature request\] Access by path [\#1053](https://github.com/nlohmann/json/issues/1053)
- document that implicit js -\> primitive conversion does not work for std::string::value\_type and why [\#1052](https://github.com/nlohmann/json/issues/1052)
- error: BasicJsonType in namespace :: does not name a type [\#1051](https://github.com/nlohmann/json/issues/1051)
- Destructor is called when filling object through assignement [\#1050](https://github.com/nlohmann/json/issues/1050)
- Is this thing thread safe for reads? [\#1049](https://github.com/nlohmann/json/issues/1049)
- clang-tidy: Call to virtual function during construction [\#1046](https://github.com/nlohmann/json/issues/1046)
- Using STL algorithms with JSON containers with expected results? [\#1045](https://github.com/nlohmann/json/issues/1045)
- Usage with gtest/gmock not working as expected [\#1044](https://github.com/nlohmann/json/issues/1044)
- Consequences of from\_json / to\_json being in namespace of data struct. [\#1042](https://github.com/nlohmann/json/issues/1042)
- const\_reference operator\[\]\(const typename object\_t::key\_type& key\) const throw instead of assert [\#1039](https://github.com/nlohmann/json/issues/1039)
- Trying to retrieve data from nested objects [\#1038](https://github.com/nlohmann/json/issues/1038)
- Direct download link for json\_fwd.hpp? [\#1037](https://github.com/nlohmann/json/issues/1037)
- I know the library supports UTF-8, but failed to dump the value [\#1036](https://github.com/nlohmann/json/issues/1036)
- Putting a Vec3-like vector into a json object [\#1035](https://github.com/nlohmann/json/issues/1035)
- Ternary operator crash [\#1034](https://github.com/nlohmann/json/issues/1034)
- Issued with Clion Inspection Resolution since 2018.1 [\#1033](https://github.com/nlohmann/json/issues/1033)
- Some testcases fail and one never finishes [\#1032](https://github.com/nlohmann/json/issues/1032)
- Can this class work with wchar\_t / std::wstring? [\#1031](https://github.com/nlohmann/json/issues/1031)
- Makefile: Valgrind flags have no effect [\#1030](https://github.com/nlohmann/json/issues/1030)
- 「==」 Should be 「\>」 [\#1029](https://github.com/nlohmann/json/issues/1029)
- HOCON reader? [\#1027](https://github.com/nlohmann/json/issues/1027)
- add json string in previous string?? [\#1025](https://github.com/nlohmann/json/issues/1025)
- RFC: fluent parsing interface [\#1023](https://github.com/nlohmann/json/issues/1023)
- Does it support chinese character? [\#1022](https://github.com/nlohmann/json/issues/1022)
- to/from\_msgpack only works with standard typization [\#1021](https://github.com/nlohmann/json/issues/1021)
- Build failure using latest clang and GCC compilers [\#1020](https://github.com/nlohmann/json/issues/1020)
- can two json objects be concatenated? [\#1019](https://github.com/nlohmann/json/issues/1019)
- Erase by integer index [\#1018](https://github.com/nlohmann/json/issues/1018)
- Function find overload taking a json\_pointer [\#1017](https://github.com/nlohmann/json/issues/1017)
- I think should implement an parser function [\#1016](https://github.com/nlohmann/json/issues/1016)
- Readme gif [\#1015](https://github.com/nlohmann/json/issues/1015)
- Python bindings [\#1014](https://github.com/nlohmann/json/issues/1014)
- how to add two json string in single object?? [\#1012](https://github.com/nlohmann/json/issues/1012)
- how to serialize class Object \(convert data in object into json\)?? [\#1011](https://github.com/nlohmann/json/issues/1011)
- Enable forward declaration of json by making json a class instead of a using declaration [\#997](https://github.com/nlohmann/json/issues/997)
- compilation error while using intel c++ compiler 2018 [\#994](https://github.com/nlohmann/json/issues/994)
- How to create a json variable? [\#990](https://github.com/nlohmann/json/issues/990)
- istream \>\> json --- 1st character skipped in stream [\#976](https://github.com/nlohmann/json/issues/976)
- Add a SAX parser [\#971](https://github.com/nlohmann/json/issues/971)
- Add Key name to Exception [\#932](https://github.com/nlohmann/json/issues/932)
- How to solve large json file? [\#927](https://github.com/nlohmann/json/issues/927)
- json\_pointer public push\_back, pop\_back [\#837](https://github.com/nlohmann/json/issues/837)
- Using input\_adapter in a slightly unexpected way [\#834](https://github.com/nlohmann/json/issues/834)
- Stack-overflow \(OSS-Fuzz 4234\) [\#832](https://github.com/nlohmann/json/issues/832)
- Fix -Wno-sometimes-uninitialized by initializing "result" in parse\_sax [\#1200](https://github.com/nlohmann/json/pull/1200) ([thyu](https://github.com/thyu))
- \[RFC\] Introduce a new macro function: JSON\_INTERNAL\_CATCH [\#1187](https://github.com/nlohmann/json/pull/1187) ([simnalamburt](https://github.com/simnalamburt))
- Fix unit tests that were silently skipped or crashed \(depending on the compiler\) [\#1176](https://github.com/nlohmann/json/pull/1176) ([grembo](https://github.com/grembo))
- Refactor/no virtual sax [\#1153](https://github.com/nlohmann/json/pull/1153) ([theodelrieu](https://github.com/theodelrieu))
- Fixed compiler error in VS 2015 for debug mode [\#1151](https://github.com/nlohmann/json/pull/1151) ([sonulohani](https://github.com/sonulohani))
- Fix links to cppreference named requirements \(formerly concepts\) [\#1144](https://github.com/nlohmann/json/pull/1144) ([jrakow](https://github.com/jrakow))
- meson: fix include directory [\#1142](https://github.com/nlohmann/json/pull/1142) ([jrakow](https://github.com/jrakow))
- Feature/unordered map conversion [\#1138](https://github.com/nlohmann/json/pull/1138) ([theodelrieu](https://github.com/theodelrieu))
- fixed compile error for \#1045 [\#1134](https://github.com/nlohmann/json/pull/1134) ([Daniel599](https://github.com/Daniel599))
- test \(non\)equality for alt\_string implementation [\#1130](https://github.com/nlohmann/json/pull/1130) ([agrianius](https://github.com/agrianius))
- remove stringstream dependency [\#1117](https://github.com/nlohmann/json/pull/1117) ([TinyTinni](https://github.com/TinyTinni))
- Provide a from\_json overload for std::map [\#1089](https://github.com/nlohmann/json/pull/1089) ([theodelrieu](https://github.com/theodelrieu))
- fix typo in README [\#1078](https://github.com/nlohmann/json/pull/1078) ([martin-mfg](https://github.com/martin-mfg))
- Fix typo [\#1058](https://github.com/nlohmann/json/pull/1058) ([dns13](https://github.com/dns13))
- Misc cmake packaging enhancements [\#1048](https://github.com/nlohmann/json/pull/1048) ([chuckatkins](https://github.com/chuckatkins))
- Fixed incorrect LLVM version number in README [\#1047](https://github.com/nlohmann/json/pull/1047) ([jammehcow](https://github.com/jammehcow))
- Fix trivial typo in comment. [\#1043](https://github.com/nlohmann/json/pull/1043) ([coryan](https://github.com/coryan))
- Package Manager: Spack [\#1041](https://github.com/nlohmann/json/pull/1041) ([ax3l](https://github.com/ax3l))
- CMake: 3.8+ is Sufficient [\#1040](https://github.com/nlohmann/json/pull/1040) ([ax3l](https://github.com/ax3l))
- Added support for string\_view in C++17 [\#1028](https://github.com/nlohmann/json/pull/1028) ([gracicot](https://github.com/gracicot))
- Added public target\_compile\_features for auto and constexpr [\#1026](https://github.com/nlohmann/json/pull/1026) ([ktonon](https://github.com/ktonon))
## [v3.1.2](https://github.com/nlohmann/json/releases/tag/v3.1.2) (2018-03-14)
[Full Changelog](https://github.com/nlohmann/json/compare/v3.1.1...v3.1.2)
@@ -16,7 +264,6 @@ All notable changes to this project will be documented in this file. This projec
- get\<T\> for types that are not default constructible [\#996](https://github.com/nlohmann/json/issues/996)
- Prevent Null values to appear in .dump\(\) [\#995](https://github.com/nlohmann/json/issues/995)
- number parsing [\#993](https://github.com/nlohmann/json/issues/993)
- How to create a json variable? [\#990](https://github.com/nlohmann/json/issues/990)
- C2664 \(C++/CLR\) cannot convert 'nullptr' to 'nullptr &&' [\#987](https://github.com/nlohmann/json/issues/987)
- Uniform initialization from another json object differs between gcc and clang. [\#985](https://github.com/nlohmann/json/issues/985)
- Problem with adding the lib as a submodule [\#983](https://github.com/nlohmann/json/issues/983)
@@ -785,7 +1032,6 @@ All notable changes to this project will be documented in this file. This projec
- json::diff generates incorrect patch when removing multiple array elements. [\#269](https://github.com/nlohmann/json/issues/269)
- Docs - What does Json\[key\] return? [\#267](https://github.com/nlohmann/json/issues/267)
- Compiler Errors With JSON.hpp [\#265](https://github.com/nlohmann/json/issues/265)
- Throw exception instead of crashing my app [\#264](https://github.com/nlohmann/json/issues/264)
- Ambiguous push\_back and operator+= overloads [\#263](https://github.com/nlohmann/json/issues/263)
- Preseving order of items in json [\#262](https://github.com/nlohmann/json/issues/262)
- '\' char problem in strings [\#261](https://github.com/nlohmann/json/issues/261)

View File

@@ -9,6 +9,7 @@ SRCS = include/nlohmann/json.hpp \
include/nlohmann/detail/exceptions.hpp \
include/nlohmann/detail/input/binary_reader.hpp \
include/nlohmann/detail/input/input_adapters.hpp \
include/nlohmann/detail/input/json_sax.hpp \
include/nlohmann/detail/input/lexer.hpp \
include/nlohmann/detail/input/parser.hpp \
include/nlohmann/detail/iterators/internal_iterator.hpp \
@@ -20,7 +21,10 @@ SRCS = include/nlohmann/json.hpp \
include/nlohmann/detail/json_ref.hpp \
include/nlohmann/detail/macro_scope.hpp \
include/nlohmann/detail/macro_unscope.hpp \
include/nlohmann/detail/meta.hpp \
include/nlohmann/detail/meta/cpp_future.hpp \
include/nlohmann/detail/meta/detected.hpp \
include/nlohmann/detail/meta/type_traits.hpp \
include/nlohmann/detail/meta/void_t.hpp \
include/nlohmann/detail/output/binary_writer.hpp \
include/nlohmann/detail/output/output_adapters.hpp \
include/nlohmann/detail/output/serializer.hpp \
@@ -82,9 +86,9 @@ clean:
coverage:
mkdir build_coverage
cd build_coverage ; CXX=g++-5 cmake .. -GNinja -DJSON_Coverage=ON -DJSON_MultipleHeaders=ON
cd build_coverage ; CXX=g++-7 cmake .. -GNinja -DJSON_Coverage=ON -DJSON_MultipleHeaders=ON
cd build_coverage ; ninja
cd build_coverage ; ctest -j10
cd build_coverage ; ctest -E '.*_default' -j10
cd build_coverage ; ninja lcov_html
open build_coverage/test/html/index.html
@@ -187,7 +191,10 @@ pedantic_gcc:
-Wunused-macros \
-Wunused-parameter \
-Wuseless-cast \
-Wvariadic-macros"
-Wvariadic-macros \
-Wctor-dtor-privacy \
-Winit-self \
-Wstrict-null-sentinel"
##########################################################################
# benchmarks

242
README.md
View File

@@ -5,6 +5,7 @@
[![Coverage Status](https://img.shields.io/coveralls/nlohmann/json.svg)](https://coveralls.io/r/nlohmann/json)
[![Coverity Scan Build Status](https://scan.coverity.com/projects/5550/badge.svg)](https://scan.coverity.com/projects/nlohmann-json)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/f3732b3327e34358a0e9d1fe9f661f08)](https://www.codacy.com/app/nlohmann/json?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=nlohmann/json&amp;utm_campaign=Badge_Grade)
[![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/nlohmann/json.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/nlohmann/json/context:cpp)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/TarF5pPn9NtHQjhf)
[![Documentation](https://img.shields.io/badge/docs-doxygen-blue.svg)](http://nlohmann.github.io/json)
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT)
@@ -15,6 +16,8 @@
- [Design goals](#design-goals)
- [Integration](#integration)
- [CMake](#cmake)
- [Package Managers](#package-managers)
- [Examples](#examples)
- [JSON as first-class data type](#json-as-first-class-data-type)
- [Serialization / Deserialization](#serialization--deserialization)
@@ -68,6 +71,71 @@ to the files you want to process JSON and set the necessary switches to enable C
You can further use file [`include/nlohmann/json_fwd.hpp`](https://github.com/nlohmann/json/blob/develop/include/nlohmann/json_fwd.hpp) for forward-declarations. The installation of json_fwd.hpp (as part of cmake's install step), can be achieved by setting `-DJSON_MultipleHeaders=ON`.
### CMake
You can also use the `nlohmann_json::nlohmann_json` interface target in CMake. This target populates the appropriate usage requirements for `INTERFACE_INCLUDE_DIRECTORIES` to point to the appropriate include directories and `INTERFACE_COMPILE_FEATURES` for the necessary C++11 flags.
#### External
To use this library from a CMake project, you can locate it directly with `find_package()` and use the namespaced imported target from the generated package configuration:
```cmake
# CMakeLists.txt
find_package(nlohmann_json 3.2.0 REQUIRED)
...
add_library(foo ...)
...
target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)
```
The package configuration file, `nlohmann_jsonConfig.cmake`, can be used either from an install tree or directly out of the build tree.
#### Embedded
To embed the library directly into an existing CMake project, place the entire source tree in a subdirectory and call `add_subdirectory()` in your `CMakeLists.txt` file:
```cmake
# Typically you don't care so much for a third party library's tests to be
# run from your own project's code.
set(JSON_BuildTests OFF CACHE INTERNAL "")
# Don't use include(nlohmann_json/CMakeLists.txt) since that carries with it
# inintended consequences that will break the build. It's generally
# discouraged (although not necessarily well documented as such) to use
# include(...) for pulling in other CMake projects anyways.
add_subdirectory(nlohmann_json)
...
add_library(foo ...)
...
target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)
```
#### Supporting Both
To allow your project to support either an externally supplied or an embedded JSON library, you can use a pattern akin to the following:
``` cmake
# Top level CMakeLists.txt
project(FOO)
...
option(FOO_USE_EXTERNAL_JSON "Use an external JSON library" OFF)
...
add_subdirectory(thirdparty)
...
add_library(foo ...)
...
# Note that the namespaced target will always be available regardless of the
# import method
target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)
```
```cmake
# thirdparty/CMakeLists.txt
...
if(FOO_USE_EXTERNAL_JSON)
find_package(nlohmann_json 3.2.0 REQUIRED)
else()
set(JSON_BuildTests OFF CACHE INTERNAL "")
add_subdirectory(nlohmann_json)
endif()
...
```
`thirdparty/nlohmann_json` is then a complete copy of this source tree.
### Package Managers
:beer: If you are using OS X and [Homebrew](http://brew.sh), just type `brew tap nlohmann/json` and `brew install nlohmann_json` and you're set. If you want the bleeding edge rather than the latest release, use `brew install nlohmann_json --HEAD`.
@@ -76,6 +144,8 @@ If you are using the [Meson Build System](http://mesonbuild.com), then you can w
If you are using [Conan](https://www.conan.io/) to manage your dependencies, merely add `jsonformoderncpp/x.y.z@vthiery/stable` to your `conanfile.py`'s requires, where `x.y.z` is the release version you want to use. Please file issues [here](https://github.com/vthiery/conan-jsonformoderncpp/issues) if you experience problems with the packages.
If you are using [Spack](https://www.spack.io/) to manage your dependencies, you can use the `nlohmann_json` package. Please see the [spack project](https://github.com/spack/spack) for any issues regarding the packaging.
If you are using [hunter](https://github.com/ruslo/hunter/) on your project for external dependencies, then you can use the [nlohmann_json package](https://docs.hunter.sh/en/latest/packages/pkg/nlohmann_json.html). Please see the hunter project for any issues regarding the packaging.
If you are using [Buckaroo](https://buckaroo.pm), you can install this library's module with `buckaroo install nlohmann/json`. Please file issues [here](https://github.com/LoopPerfect/buckaroo-recipes/issues/new?title=nlohmann/nlohmann/json).
@@ -84,6 +154,8 @@ If you are using [vcpkg](https://github.com/Microsoft/vcpkg/) on your project fo
If you are using [cget](http://cget.readthedocs.io/en/latest/), you can install the latest development version with `cget install nlohmann/json`. A specific version can be installed with `cget install nlohmann/json@v3.1.0`. Also, the multiple header version can be installed by adding the `-DJSON_MultipleHeaders=ON` flag (i.e., `cget install nlohmann/json -DJSON_MultipleHeaders=ON`).
If you are using [CocoaPods](https://cocoapods.org), you can use the library by adding pod `"nlohmann_json", '~>3.1.2'` to your podfile (see [an example](https://bitbucket.org/benman/nlohmann_json-cocoapod/src/master/)). Please file issues [here](https://bitbucket.org/benman/nlohmann_json-cocoapod/issues?status=new&status=open).
## Examples
Beside the examples below, you may want to check the [documentation](https://nlohmann.github.io/json/) where each function contains a separate code example (e.g., check out [`emplace()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a5338e282d1d02bed389d852dd670d98d.html#a5338e282d1d02bed389d852dd670d98d)). All [example files](https://github.com/nlohmann/json/tree/develop/doc/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/doc/examples/emplace.cpp)).
@@ -169,7 +241,6 @@ json empty_object_explicit = json::object();
json array_not_object = json::array({ {"currency", "USD"}, {"value", 42.99} });
```
### Serialization / Deserialization
#### To/from strings
@@ -223,18 +294,22 @@ json j_string = "this is a string";
std::string cpp_string = j_string;
// retrieve the string value (explicit JSON to std::string conversion)
auto cpp_string2 = j_string.get<std::string>();
// retrieve the string value (alternative explicit JSON to std::string conversion)
std::string cpp_string3;
j_string.get_to(cpp_string3);
// retrieve the serialized value (explicit JSON serialization)
std::string serialized_string = j_string.dump();
// output of original string
std::cout << cpp_string << " == " << cpp_string2 << " == " << j_string.get<std::string>() << '\n';
std::cout << cpp_string << " == " << cpp_string2 << " == " << cpp_string3 << " == " << j_string.get<std::string>() << '\n';
// output of serialized value
std::cout << j_string << " == " << serialized_string << std::endl;
```
[`.dump()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a5adea76fedba9898d404fef8598aa663.html#a5adea76fedba9898d404fef8598aa663) always returns the serialized value, and [`.get<std::string>()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a16f9445f7629f634221a42b967cdcd43.html#a16f9445f7629f634221a42b967cdcd43) returns the originally stored string value.
Note the library only supports UTF-8. When you store strings with different encodings in the library, calling [`dump()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a5adea76fedba9898d404fef8598aa663.html#a5adea76fedba9898d404fef8598aa663) may throw an exception.
#### To/from streams (e.g. files, string streams)
@@ -283,10 +358,53 @@ std::vector<std::uint8_t> v = {'t', 'r', 'u', 'e'};
json j = json::parse(v);
```
#### SAX interface
The library uses a SAX-like interface with the following functions:
```cpp
// called when null is parsed
bool null();
// called when a boolean is parsed; value is passed
bool boolean(bool val);
// called when a signed or unsigned integer number is parsed; value is passed
bool number_integer(number_integer_t val);
bool number_unsigned(number_unsigned_t val);
// called when a floating-point number is parsed; value and original string is passed
bool number_float(number_float_t val, const string_t& s);
// called when a string is parsed; value is passed and can be safely moved away
bool string(string_t& val);
// called when an object or array begins or ends, resp. The number of elements is passed (or -1 if not known)
bool start_object(std::size_t elements);
bool end_object();
bool start_array(std::size_t elements);
bool end_array();
// called when an object key is parsed; value is passed and can be safely moved away
bool key(string_t& val);
// called when a parse error occurs; byte position, the last token, and an exception is passed
bool parse_error(std::size_t position, const std::string& last_token, const detail::exception& ex);
```
The return value of each function determines whether parsing should proceed.
To implement your own SAX handler, proceed as follows:
1. Implement the SAX interface in a class. You can use class `nlohmann::json_sax<json>` as base class, but you can also use any class where the functions described above are implemented and public.
2. Create an object of your SAX interface class, e.g. `my_sax`.
3. Call `bool json::sax_parse(input, &my_sax)`; where the first parameter can be any input like a string or an input stream and the second parameter is a pointer to your SAX interface.
Note the `sax_parse` function only returns a `bool` indicating the result of the last executed SAX event. It does not return a `json` value - it is up to you to decide what to do with the SAX events. Furthermore, no exceptions are thrown in case of a parse error - it is up to you what to do with the exception object passed to your `parse_error` implementation. Internally, the SAX interface is used for the DOM parser (class `json_sax_dom_parser`) as well as the acceptor (`json_sax_acceptor`), see file [`json_sax.hpp`](https://github.com/nlohmann/json/blob/develop/include/nlohmann/detail/input/json_sax.hpp).
### STL-like access
We designed the JSON class to behave just like an STL container. In fact, it satisfies the [**ReversibleContainer**](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) requirement.
We designed the JSON class to behave just like an STL container. In fact, it satisfies the [**ReversibleContainer**](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) requirement.
```cpp
// create an array using push_back
@@ -523,6 +641,14 @@ int vi = jn.get<int>();
// etc.
```
Note that `char` types are not automatically converted to JSON strings, but to integer numbers. A conversion to a string must be specified explicitly:
```cpp
char ch = 'A'; // ASCII value 65
json j_default = ch; // stores integer number 65
json j_string = std::string(1, ch); // stores string "A"
```
### Arbitrary types conversions
Every type can be serialized in JSON, not just STL containers and scalar types. Usually, you would do something along those lines:
@@ -587,24 +713,24 @@ namespace ns {
}
void from_json(const json& j, person& p) {
p.name = j.at("name").get<std::string>();
p.address = j.at("address").get<std::string>();
p.age = j.at("age").get<int>();
j.at("name").get_to(p.name);
j.at("address").get_to(p.address);
j.at("age").get_to(p.age);
}
} // namespace ns
```
That's all! When calling the `json` constructor with your type, your custom `to_json` method will be automatically called.
Likewise, when calling `get<your_type>()`, the `from_json` method will be called.
Likewise, when calling `get<your_type>()` or `get_to(your_type&)`, the `from_json` method will be called.
Some important things:
* Those methods **MUST** be in your type's namespace (which can be the global namespace), or the library will not be able to locate them (in this example, they are in namespace `ns`, where `person` is defined).
* When using `get<your_type>()`, `your_type` **MUST** be [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). (There is a way to bypass this requirement described later.)
* Those methods **MUST** be available (e.g., properly headers must be included) everywhere you use the implicit conversions. Look at [issue 1108](https://github.com/nlohmann/json/issues/1108) for errors that may occur otherwise.
* When using `get<your_type>()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.)
* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a93403e803947b86f4da2d1fb3345cf2c.html#a93403e803947b86f4da2d1fb3345cf2c) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior.
* In case your type contains several `operator=` definitions, code like `your_variable = your_json;` [may not compile](https://github.com/nlohmann/json/issues/667). You need to write `your_variable = your_json.get<decltype your_variable>();` instead.
* In case your type contains several `operator=` definitions, code like `your_variable = your_json;` [may not compile](https://github.com/nlohmann/json/issues/667). You need to write `your_variable = your_json.get<decltype(your_variable)>();` or `your_json.get_to(your_variable);` instead.
* You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these.
* Be careful with the definition order of the `from_json`/`to_json` functions: If a type `B` has a member of type `A`, you **MUST** define `to_json(A)` before `to_json(B)`. Look at [issue 561](https://github.com/nlohmann/json/issues/561) for more details.
#### How do I convert third-party types?
@@ -612,7 +738,7 @@ Some important things:
This requires a bit more advanced technique. But first, let's see how this conversion mechanism works:
The library uses **JSON Serializers** to convert types to json.
The default serializer for `nlohmann::json` is `nlohmann::adl_serializer` (ADL means [Argument-Dependent Lookup](http://en.cppreference.com/w/cpp/language/adl)).
The default serializer for `nlohmann::json` is `nlohmann::adl_serializer` (ADL means [Argument-Dependent Lookup](https://en.cppreference.com/w/cpp/language/adl)).
It is implemented like this (simplified):
@@ -661,7 +787,7 @@ namespace nlohmann {
#### How can I use `get()` for non-default constructible/non-copyable types?
There is a way, if your type is [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible). You will need to specialize the `adl_serializer` as well, but with a special `from_json` overload:
There is a way, if your type is [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible). You will need to specialize the `adl_serializer` as well, but with a special `from_json` overload:
```cpp
struct move_only_type {
@@ -786,8 +912,8 @@ json j_from_ubjson = json::from_ubjson(v_ubjson);
Though it's 2018 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work:
- GCC 4.9 - 7.2 (and possibly later)
- Clang 3.4 - 5.0 (and possibly later)
- GCC 4.8 - 8.2 (and possibly later)
- Clang 3.4 - 6.1 (and possibly later)
- Intel C++ Compiler 17.0.2 (and possibly later)
- Microsoft Visual C++ 2015 / Build Tools 14.0.25123.0 (and possibly later)
- Microsoft Visual C++ 2017 / Build Tools 15.5.180.51428 (and possibly later)
@@ -796,7 +922,7 @@ I would be happy to learn about other compilers/versions.
Please note:
- GCC 4.8 does not work because of two bugs ([55817](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55817) and [57824](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57824)) in the C++11 support. Note there is a [pull request](https://github.com/nlohmann/json/pull/212) to fix some of the issues.
- GCC 4.8 has a bug [57824](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57824)): multiline raw strings cannot be the arguments to macros. Don't use multiline raw strings directly in macros with this compiler.
- Android defaults to using very old compilers and C++ libraries. To fix this, add the following to your `Application.mk`. This will switch to the LLVM C++ library, the Clang compiler, and enable C++11 and other features disabled by default.
```
@@ -809,32 +935,40 @@ Please note:
- For GCC running on MinGW or Android SDK, the error `'to_string' is not a member of 'std'` (or similarly, for `strtod`) may occur. Note this is not an issue with the code, but rather with the compiler itself. On Android, see above to build with a newer environment. For MinGW, please refer to [this site](http://tehsausage.com/mingw-to-string) and [this discussion](https://github.com/nlohmann/json/issues/136) for information on how to fix this bug. For Android NDK using `APP_STL := gnustl_static`, please refer to [this discussion](https://github.com/nlohmann/json/issues/219).
- Unsupported versions of GCC and Clang are rejected by `#error` directives. This can be switched off by defining `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK`. Note that you can expect no support in this case.
The following compilers are currently used in continuous integration at [Travis](https://travis-ci.org/nlohmann/json) and [AppVeyor](https://ci.appveyor.com/project/nlohmann/json):
| Compiler | Operating System | Version String |
|-----------------|------------------------------|----------------|
| GCC 4.9.4 | Ubuntu 14.04.5 LTS | g++-4.9 (Ubuntu 4.9.4-2ubuntu1~14.04.1) 4.9.4 |
| GCC 5.4.1 | Ubuntu 14.04.5 LTS | g++-5 (Ubuntu 5.4.1-2ubuntu1~14.04) 5.4.1 20160904 |
| GCC 6.3.0 | Ubuntu 14.04.5 LTS | g++-6 (Ubuntu/Linaro 6.3.0-18ubuntu2~14.04) 6.3.0 20170519 |
| GCC 7.1.0 | Ubuntu 14.04.5 LTS | g++-7 (Ubuntu 7.1.0-5ubuntu2~14.04) 7.1.0
| Clang 3.5.0 | Ubuntu 14.04.5 LTS | clang version 3.5.0-4ubuntu2~trusty2 (tags/RELEASE_350/final) |
| Clang 3.6.2 | Ubuntu 14.04.5 LTS | clang version 3.6.2-svn240577-1~exp1 (branches/release_36) |
| Clang 3.7.1 | Ubuntu 14.04.5 LTS | clang version 3.7.1-svn253571-1~exp1 (branches/release_37) |
| Clang 3.8.0 | Ubuntu 14.04.5 LTS | clang version 3.8.0-2ubuntu3~trusty5 (tags/RELEASE_380/final) |
| Clang 3.9.1 | Ubuntu 14.04.5 LTS | clang version 3.9.1-4ubuntu3~14.04.2 (tags/RELEASE_391/rc2) |
| Clang 4.0.1 | Ubuntu 14.04.5 LTS | clang version 4.0.1-svn305264-1~exp1 (branches/release_40) |
| Clang 5.0.0 | Ubuntu 14.04.5 LTS | clang version 5.0.0-svn310902-1~exp1 (branches/release_50) |
| Clang Xcode 6.4 | Darwin Kernel Version 14.3.0 (OSX 10.10.3) | Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) |
| Clang Xcode 7.3 | Darwin Kernel Version 15.0.0 (OSX 10.10.5) | Apple LLVM version 7.3.0 (clang-703.0.29) |
| Clang Xcode 8.0 | Darwin Kernel Version 15.6.0 | Apple LLVM version 8.0.0 (clang-800.0.38) |
| Clang Xcode 8.1 | Darwin Kernel Version 16.1.0 (macOS 10.12.1) | Apple LLVM version 8.0.0 (clang-800.0.42.1) |
| Clang Xcode 8.2 | Darwin Kernel Version 16.1.0 (macOS 10.12.1) | Apple LLVM version 8.0.0 (clang-800.0.42.1) |
| Clang Xcode 8.3 | Darwin Kernel Version 16.5.0 (macOS 10.12.4) | Apple LLVM version 8.1.0 (clang-802.0.38) |
| Clang Xcode 9.0 | Darwin Kernel Version 16.7.0 (macOS 10.12.6) | Apple LLVM version 9.0.0 (clang-900.0.37) |
| Clang Xcode 9.1 | Darwin Kernel Version 16.7.0 (macOS 10.12.6) | Apple LLVM version 9.0.0 (clang-900.0.38) |
| Clang Xcode 9.2 | Darwin Kernel Version 16.7.0 (macOS 10.12.6) | Apple LLVM version 8.1.0 (clang-900.0.39.2) |
| GCC 4.8.5 | Ubuntu 14.04.5 LTS | g++-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.2) 4.8.5 |
| GCC 4.9.4 | Ubuntu 14.04.1 LTS | g++-4.9 (Ubuntu 4.9.4-2ubuntu1~14.04.1) 4.9.4 |
| GCC 5.5.0 | Ubuntu 14.04.1 LTS | g++-5 (Ubuntu 5.5.0-12ubuntu1~14.04) 5.5.0 20171010 |
| GCC 6.4.0 | Ubuntu 14.04.1 LTS | g++-6 (Ubuntu 6.4.0-17ubuntu1~14.04) 6.4.0 20180424 |
| GCC 7.3.0 | Ubuntu 14.04.1 LTS | g++-7 (Ubuntu 7.3.0-21ubuntu1~14.04) 7.3.0 |
| GCC 7.3.0 | Windows Server 2012 R2 (x64) | g++ (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 7.3.0 |
| GCC 8.1.0 | Ubuntu 14.04.1 LTS | g++-8 (Ubuntu 8.1.0-5ubuntu1~14.04) 8.1.0 |
| Clang 3.5.0 | Ubuntu 14.04.1 LTS | clang version 3.5.0-4ubuntu2~trusty2 (tags/RELEASE_350/final) (based on LLVM 3.5.0) |
| Clang 3.6.2 | Ubuntu 14.04.1 LTS | clang version 3.6.2-svn240577-1~exp1 (branches/release_36) (based on LLVM 3.6.2) |
| Clang 3.7.1 | Ubuntu 14.04.1 LTS | clang version 3.7.1-svn253571-1~exp1 (branches/release_37) (based on LLVM 3.7.1) |
| Clang 3.8.0 | Ubuntu 14.04.1 LTS | clang version 3.8.0-2ubuntu3~trusty5 (tags/RELEASE_380/final) |
| Clang 3.9.1 | Ubuntu 14.04.1 LTS | clang version 3.9.1-4ubuntu3~14.04.3 (tags/RELEASE_391/rc2) |
| Clang 4.0.1 | Ubuntu 14.04.1 LTS | clang version 4.0.1-svn305264-1~exp1 (branches/release_40) |
| Clang 5.0.2 | Ubuntu 14.04.1 LTS | clang version 5.0.2-svn328729-1~exp1~20180509123505.100 (branches/release_50) |
| Clang 6.0.1 | Ubuntu 14.04.1 LTS | clang version 6.0.1-svn334776-1~exp1~20180726133705.85 (branches/release_60) |
| Clang Xcode 6.4 | OSX 10.10.5 | Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) |
| Clang Xcode 7.3 | OSX 10.11.6 | Apple LLVM version 7.3.0 (clang-703.0.31) |
| Clang Xcode 8.0 | OSX 10.11.6 | Apple LLVM version 8.0.0 (clang-800.0.38) |
| Clang Xcode 8.1 | OSX 10.12.6 | Apple LLVM version 8.0.0 (clang-800.0.42.1) |
| Clang Xcode 8.2 | OSX 10.12.6 | Apple LLVM version 8.0.0 (clang-800.0.42.1) |
| Clang Xcode 8.3 | OSX 10.11.6 | Apple LLVM version 8.1.0 (clang-802.0.38) |
| Clang Xcode 9.0 | OSX 10.12.6 | Apple LLVM version 9.0.0 (clang-900.0.37) |
| Clang Xcode 9.1 | OSX 10.12.6 | Apple LLVM version 9.0.0 (clang-900.0.38) |
| Clang Xcode 9.2 | OSX 10.13.3 | Apple LLVM version 9.1.0 (clang-902.0.39.1) |
| Clang Xcode 9.3 | OSX 10.13.3 | Apple LLVM version 9.1.0 (clang-902.0.39.2) |
| Clang Xcode 10.0 | OSX 10.13.3 | Apple LLVM version 10.0.0 (clang-1000.11.45.2) |
| Visual Studio 14 2015 | Windows Server 2012 R2 (x64) | Microsoft (R) Build Engine version 14.0.25420.1, MSVC 19.0.24215.1 |
| Visual Studio 2017 | Windows Server 2016 | Microsoft (R) Build Engine version 15.5.180.51428, MSVC 19.12.25830.2 |
| Visual Studio 2017 | Windows Server 2016 | Microsoft (R) Build Engine version 15.7.180.61344, MSVC 19.14.26433.0 |
## License
@@ -862,6 +996,9 @@ If you have questions regarding the library, I would like to invite you to [open
Only if your request would contain confidential information, please [send me an email](mailto:mail@nlohmann.me). For encrypted messages, please use [this key](https://keybase.io/nlohmann/pgp_keys.asc).
## Security
[Commits by Niels Lohmann](https://github.com/nlohmann/json/commits) and [releases](https://github.com/nlohmann/json/releases) are signed with this [PGP Key](https://keybase.io/nlohmann/pgp_keys.asc?fingerprint=797167ae41c0a6d9232e48457f3cea63ae251b69).
## Thanks
@@ -916,7 +1053,7 @@ I deeply appreciate the help of the following people.
- [Vladimir Petrigo](https://github.com/vpetrigo) made a SFINAE hack more readable and added Visual Studio 17 to the build matrix.
- [Denis Andrejew](https://github.com/seeekr) fixed a grammar issue in the README file.
- [Pierre-Antoine Lacaze](https://github.com/palacaze) found a subtle bug in the `dump()` function.
- [TurpentineDistillery](https://github.com/TurpentineDistillery) pointed to [`std::locale::classic()`](http://en.cppreference.com/w/cpp/locale/locale/classic) to avoid too much locale joggling, found some nice performance improvements in the parser, improved the benchmarking code, and realized locale-independent number parsing and printing.
- [TurpentineDistillery](https://github.com/TurpentineDistillery) pointed to [`std::locale::classic()`](https://en.cppreference.com/w/cpp/locale/locale/classic) to avoid too much locale joggling, found some nice performance improvements in the parser, improved the benchmarking code, and realized locale-independent number parsing and printing.
- [cgzones](https://github.com/cgzones) had an idea how to fix the Coverity scan.
- [Jared Grubb](https://github.com/jaredgrubb) silenced a nasty documentation warning.
- [Yixin Zhang](https://github.com/qwename) fixed an integer overflow check.
@@ -975,14 +1112,39 @@ I deeply appreciate the help of the following people.
- [Paul Fultz II](https://github.com/pfultz2) added a note on the cget package manager.
- [Wilson Lin](https://github.com/wla80) made the integration section of the README more concise.
- [RalfBielig](https://github.com/ralfbielig) detected and fixed a memory leak in the parser callback.
- [agrianius](https://github.com/agrianius) allowed to dump JSON to an alternative string type
- [agrianius](https://github.com/agrianius) allowed to dump JSON to an alternative string type.
- [Kevin Tonon](https://github.com/ktonon) overworked the C++11 compiler checks in CMake.
- [Axel Huebl](https://github.com/ax3l) simplified a CMake check and added support for the [Spack package manager](https://spack.io).
- [Carlos O'Ryan](https://github.com/coryan) fixed a typo.
- [James Upjohn](https://github.com/jammehcow) fixed a version number in the compilers section.
- [Chuck Atkins](https://github.com/chuckatkins) adjusted the CMake files to the CMake packaging guidelines and provided documentation for the CMake integration.
- [Jan Schöppach](https://github.com/dns13) fixed a typo.
- [martin-mfg](https://github.com/martin-mfg) fixed a typo.
- [Matthias Möller](https://github.com/TinyTinni) removed the dependency from `std::stringstream`.
- [agrianius](https://github.com/agrianius) added code to use alternative string implementations.
- [Daniel599](https://github.com/Daniel599) allowed to use more algorithms with the `items()` function.
- [Julius Rakow](https://github.com/jrakow) fixed the Meson include directory and fixed the links to [cppreference.com](cppreference.com).
- [Sonu Lohani](https://github.com/sonulohani) fixed the compilation with MSVC 2015 in debug mode.
- [grembo](https://github.com/grembo) fixed the test suite and re-enabled several test cases.
- [Hyeon Kim](https://github.com/simnalamburt) introduced the macro `JSON_INTERNAL_CATCH` to control the exception handling inside the library.
- [thyu](https://github.com/thyu) fixed a compiler warning.
- [David Guthrie](https://github.com/LEgregius) fixed a subtle compilation error with Clang 3.4.2.
- [Dennis Fischer](https://github.com/dennisfischer) allowed to call `find_package` without installing the library.
- [Hyeon Kim](https://github.com/simnalamburt) fixed an issue with a double macro definition.
- [Ben Berman](https://github.com/rivertam) made some error messages more understandable.
- [zakalibit](https://github.com/zakalibit) fixed a compilation problem with the Intel C++ compiler.
- [mandreyel](https://github.com/mandreyel) fixed a compilation problem.
- [Kostiantyn Ponomarenko](https://github.com/koponomarenko) added version and license information to the Meson build file.
- [Henry Schreiner](https://github.com/henryiii) added support for GCC 4.8.
- [knilch](https://github.com/knilch0r) made sure the test suite does not stall when run in the wrong directory.
- [Antonio Borondo](https://github.com/antonioborondo) fixed an MSVC 2017 warning.
Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone.
## Used third-party tools
The library itself contains of a single header file licensed under the MIT license. However, it is built, tested, documented, and whatnot using a lot of third-party tools and services. Thanks a lot!
The library itself consists of a single header file licensed under the MIT license. However, it is built, tested, documented, and whatnot using a lot of third-party tools and services. Thanks a lot!
- [**amalgamate.py - Amalgamate C source and header files**](https://github.com/edlund/amalgamate) to create a single header file
- [**American fuzzy lop**](http://lcamtuf.coredump.cx/afl/) for fuzz testing
@@ -1015,7 +1177,7 @@ The library is currently used in Apple macOS Sierra and iOS 10. I am not sure wh
## Notes
- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](http://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a2e26bd0b0168abb61f67ad5bcd5b9fa1.html#a2e26bd0b0168abb61f67ad5bcd5b9fa1) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a674de1ee73e6bf4843fc5dc1351fb726.html#a674de1ee73e6bf4843fc5dc1351fb726).
- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](https://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a2e26bd0b0168abb61f67ad5bcd5b9fa1.html#a2e26bd0b0168abb61f67ad5bcd5b9fa1) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a674de1ee73e6bf4843fc5dc1351fb726.html#a674de1ee73e6bf4843fc5dc1351fb726).
- As the exact type of a number is not defined in the [JSON specification](http://rfc7159.net/rfc7159), this library tries to choose the best fitting C++ number type automatically. As a result, the type `double` may be used to store numbers which may yield [**floating-point exceptions**](https://github.com/nlohmann/json/issues/181) in certain rare situations if floating-point exceptions have been unmasked in the calling code. These exceptions are not caused by the library and need to be fixed in the calling code, such as by re-masking the exceptions prior to calling library functions.
- The library supports **Unicode input** as follows:
- Only **UTF-8** encoded input is supported which is the default encoding for JSON according to [RFC 7159](http://rfc7159.net/rfc7159#rfc.section.8.1).

View File

@@ -1,26 +1,58 @@
version: '{build}'
os:
- Visual Studio 2015
- Visual Studio 2017
environment:
matrix:
- additional_flags: ""
- additional_flags: "/permissive- /std:c++latest /utf-8"
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
COMPILER: mingw
platform: x86
FLAGS: ""
GENERATOR: Ninja
matrix:
exclude:
- additional_flags: "/permissive- /std:c++latest /utf-8"
os: Visual Studio 2015
init: []
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
platform: x86
FLAGS: ""
GENERATOR: Visual Studio 14 2015
install: []
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
platform: x86
FLAGS: ""
GENERATOR: Visual Studio 15 2017
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
platform: x86
FLAGS: "/permissive- /std:c++latest /utf-8"
GENERATOR: Visual Studio 15 2017
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
platform: x64
FLAGS: ""
GENERATOR: Visual Studio 14 2015
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
platform: x64
FLAGS: ""
GENERATOR: Visual Studio 15 2017
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
platform: x64
FLAGS: "/permissive- /std:c++latest /utf-8"
GENERATOR: Visual Studio 15 2017
init:
- cmake --version
- msbuild /version
install:
- if "%COMPILER%"=="mingw" appveyor DownloadFile https://github.com/ninja-build/ninja/releases/download/v1.6.0/ninja-win.zip -FileName ninja.zip
- if "%COMPILER%"=="mingw" 7z x ninja.zip -oC:\projects\deps\ninja > nul
- if "%COMPILER%"=="mingw" set PATH=C:\projects\deps\ninja;%PATH%
- if "%COMPILER%"=="mingw" set PATH=C:\mingw-w64\x86_64-7.3.0-posix-seh-rt_v5-rev0\mingw64\bin;%PATH%
- if "%COMPILER%"=="mingw" g++ --version
before_build:
- cmake . -G "%GENERATOR%" -DCMAKE_CXX_FLAGS="%FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin"
build_script:
- IF "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2015" ( SET GEN="Visual Studio 14 2015") ELSE (SET GEN="Visual Studio 15 2017")
- cmake . -G%GEN% -DCMAKE_CXX_FLAGS="%additional_flags%"
- cmake --build . --config Release
test_script:

View File

@@ -1,9 +1,9 @@
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.8)
project(JSON_Benchmarks LANGUAGES CXX)
# set compiler flags
if((CMAKE_CXX_COMPILER_ID MATCHES GNU) OR (CMAKE_CXX_COMPILER_ID MATCHES Clang))
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -flto -DNDEBUG -O3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto -DNDEBUG -O3")
endif()
# configure Google Benchmarks
@@ -23,4 +23,5 @@ file(COPY ${CMAKE_SOURCE_DIR}/../test/data/regression/floats.json
# benchmark binary
add_executable(json_benchmarks src/benchmarks.cpp)
target_compile_features(json_benchmarks PRIVATE cxx_std_11)
target_link_libraries(json_benchmarks benchmark ${CMAKE_THREAD_LIBS_INIT})

View File

@@ -1,3 +1,15 @@
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/@NLOHMANN_JSON_TARGETS_EXPORT_NAME@.cmake")
check_required_components("@PROJECT_NAME@")
include(FindPackageHandleStandardArgs)
set(${CMAKE_FIND_PACKAGE_NAME}_CONFIG ${CMAKE_CURRENT_LIST_FILE})
find_package_handle_standard_args(@PROJECT_NAME@ CONFIG_MODE)
if(NOT TARGET @PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@)
include("${CMAKE_CURRENT_LIST_DIR}/@NLOHMANN_JSON_TARGETS_EXPORT_NAME@.cmake")
if((NOT TARGET @NLOHMANN_JSON_TARGET_NAME@) AND
(NOT @PROJECT_NAME@_FIND_VERSION OR
@PROJECT_NAME@_FIND_VERSION VERSION_LESS 3.2.0))
add_library(@NLOHMANN_JSON_TARGET_NAME@ INTERFACE IMPORTED)
set_target_properties(@NLOHMANN_JSON_TARGET_NAME@ PROPERTIES
INTERFACE_LINK_LIBRARIES @PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@
)
endif()
endif()

View File

@@ -5,7 +5,7 @@
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "JSON for Modern C++"
PROJECT_NUMBER = 3.1.2
PROJECT_NUMBER = 3.3.0
PROJECT_BRIEF =
PROJECT_LOGO =
OUTPUT_DIRECTORY = .

Binary file not shown.

Before

Width:  |  Height:  |  Size: 568 KiB

After

Width:  |  Height:  |  Size: 726 KiB

View File

@@ -1,4 +1,5 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/TarF5pPn9NtHQjhf"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/RWX63GizBsDZ5EnQ"><b>online</b></a>

View File

@@ -1,4 +1,5 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/tfI8DuCuZs3VB9VF"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/3OPLSVPyweUyEHaX"><b>online</b></a>

View File

@@ -1,4 +1,5 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/E1HQedkl1zo48WW5"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/4bn447WQbTERfBaL"><b>online</b></a>

View File

@@ -1,4 +1,5 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/mya8dUDcDDVoUlBZ"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/AHKW5EMQN4YQ68TY"><b>online</b></a>

View File

@@ -1,4 +1,5 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/sMmEKxW5MGOgLC7z"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/J0KoQF8sOpdMg4kN"><b>online</b></a>

View File

@@ -1,4 +1,5 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/qq29jfETq7nZRrh5"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/uuQK0DAjhbSd96K6"><b>online</b></a>

60
doc/examples/get_to.cpp Normal file
View File

@@ -0,0 +1,60 @@
#include <iostream>
#include <unordered_map>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create a JSON value with different types
json json_types =
{
{"boolean", true},
{
"number", {
{"integer", 42},
{"floating-point", 17.23}
}
},
{"string", "Hello, world!"},
{"array", {1, 2, 3, 4, 5}},
{"null", nullptr}
};
bool v1;
int v2;
short v3;
float v4;
int v5;
std::string v6;
std::vector<short> v7;
std::unordered_map<std::string, json> v8;
// use explicit conversions
json_types["boolean"].get_to(v1);
json_types["number"]["integer"].get_to(v2);
json_types["number"]["integer"].get_to(v3);
json_types["number"]["floating-point"].get_to(v4);
json_types["number"]["floating-point"].get_to(v5);
json_types["string"].get_to(v6);
json_types["array"].get_to(v7);
json_types.get_to(v8);
// print the conversion results
std::cout << v1 << '\n';
std::cout << v2 << ' ' << v3 << '\n';
std::cout << v4 << ' ' << v5 << '\n';
std::cout << v6 << '\n';
for (auto i : v7)
{
std::cout << i << ' ';
}
std::cout << "\n\n";
for (auto i : v8)
{
std::cout << i.first << ": " << i.second << '\n';
}
}

1
doc/examples/get_to.link Normal file
View File

@@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/QxtxaO6JZAMJPutC"><b>online</b></a>

View File

@@ -0,0 +1,11 @@
1
42 42
17.23 17
Hello, world!
1 2 3 4 5
string: "Hello, world!"
number: {"floating-point":17.23,"integer":42}
null: null
boolean: true
array: [1,2,3,4,5]

View File

@@ -1,4 +1,5 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/0zdmfNQCe4TMw0iI"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/eFzRNyod3g4aVkvl"><b>online</b></a>

View File

@@ -2,7 +2,7 @@
"compiler": {
"c++": "201103",
"family": "clang",
"version": "9.0.0 (clang-900.0.39.2)"
"version": "10.0.0 (clang-1000.10.43.1)"
},
"copyright": "(C) 2013-2017 Niels Lohmann",
"name": "JSON for Modern C++",
@@ -10,8 +10,8 @@
"url": "https://github.com/nlohmann/json",
"version": {
"major": 3,
"minor": 1,
"patch": 2,
"string": "3.1.2"
"minor": 3,
"patch": 0,
"string": "3.3.0"
}
}

View File

@@ -17,8 +17,8 @@ int main()
// output values and comparisons
std::cout << std::boolalpha;
std::cout << array_1 << " == " << array_2 << " " << (array_1 > array_2) << '\n';
std::cout << object_1 << " == " << object_2 << " " << (object_1 > object_2) << '\n';
std::cout << number_1 << " == " << number_2 << " " << (number_1 > number_2) << '\n';
std::cout << string_1 << " == " << string_2 << " " << (string_1 > string_2) << '\n';
std::cout << array_1 << " > " << array_2 << " " << (array_1 > array_2) << '\n';
std::cout << object_1 << " > " << object_2 << " " << (object_1 > object_2) << '\n';
std::cout << number_1 << " > " << number_2 << " " << (number_1 > number_2) << '\n';
std::cout << string_1 << " > " << string_2 << " " << (string_1 > string_2) << '\n';
}

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/yiz7oCHVpFHSALB1"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/ntF7DMzC85gbQKHu"><b>online</b></a>

View File

@@ -1,4 +1,4 @@
[1,2,3] == [1,2,4] false
{"A":"a","B":"b"} == {"A":"a","B":"b"} false
17 == 17.0000000000001 false
"foo" == "bar" true
[1,2,3] > [1,2,4] false
{"A":"a","B":"b"} > {"A":"a","B":"b"} false
17 > 17.0000000000001 false
"foo" > "bar" true

View File

@@ -1,4 +1,6 @@
#include <iostream>
#include <iomanip>
#include <sstream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/YrUqrUFMD7JHwSQR"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/IvgowYGaX0SgOFIG"><b>online</b></a>

View File

@@ -1,4 +1,5 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/wXcm4ObnoaXw7CRt"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/ckGZIBookDffV00n"><b>online</b></a>

View File

@@ -1,4 +1,5 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/vxt8d8qvYorXS2yq"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/oKnfnFrLHG8H1OAl"><b>online</b></a>

View File

@@ -1,4 +1,5 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/TSNxHmegVwLW2pXf"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/i3BBhl7Ub5y9b0yp"><b>online</b></a>

View File

@@ -1,4 +1,5 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/l3zNo3YKC2X8yAw9"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/sGdJMOaJnFNJBtH7"><b>online</b></a>

View File

@@ -1,4 +1,6 @@
#include <iostream>
#include <iomanip>
#include <sstream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/Mf7A6JtvqT1Na7Pk"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/UZgRBIeqdZhm6M8F"><b>online</b></a>

View File

@@ -1,4 +1,5 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/oa6BVkBXjG8DNkzX"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/VThe0hdMSUdNSOLK"><b>online</b></a>

View File

@@ -1,4 +1,5 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/QXdl4yzts3qPeZ0U"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/QZgjsR0PiAw2Lqpk"><b>online</b></a>

View File

@@ -1,4 +1,5 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/8ObNa6ejw4BXQ5qG"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/hFd1W46W2Hb81sHN"><b>online</b></a>

124
doc/examples/sax_parse.cpp Normal file
View File

@@ -0,0 +1,124 @@
#include <iostream>
#include <iomanip>
#include <sstream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
// a simple event consumer that collects string representations of the passed
// values; not inheriting from json::json_sax_t is not required, but can
// help not to forget a required function
class sax_event_consumer : public json::json_sax_t
{
public:
std::vector<std::string> events;
bool null() override
{
events.push_back("value: null");
return true;
}
bool boolean(bool val) override
{
events.push_back("value: " + std::string(val ? "true" : "false"));
return true;
}
bool number_integer(number_integer_t val) override
{
events.push_back("value: " + std::to_string(val));
return true;
}
bool number_unsigned(number_unsigned_t val) override
{
events.push_back("value: " + std::to_string(val));
return true;
}
bool number_float(number_float_t val, const string_t& s) override
{
events.push_back("value: " + s);
return true;
}
bool string(string_t& val) override
{
events.push_back("value: " + val);
return true;
}
bool start_object(std::size_t elements) override
{
events.push_back("start: object");
return true;
}
bool end_object() override
{
events.push_back("end: object");
return true;
}
bool start_array(std::size_t elements) override
{
events.push_back("start: array");
return true;
}
bool end_array() override
{
events.push_back("end: array");
return true;
}
bool key(string_t& val) override
{
events.push_back("key: " + val);
return true;
}
bool parse_error(std::size_t position, const std::string& last_token, const json::exception& ex) override
{
events.push_back("error: " + std::string(ex.what()));
return false;
}
};
int main()
{
// a JSON text
auto text = R"(
{
"Image": {
"Width": 800,
"Height": 600,
"Title": "View from 15th Floor",
"Thumbnail": {
"Url": "http://www.example.com/image/481989943",
"Height": 125,
"Width": 100
},
"Animated" : false,
"IDs": [116, 943, 234, 38793],
"Distance": 12.723374634
}
}
)";
// create a SAX event consumer object
sax_event_consumer sec;
// parse and serialize JSON
bool result = json::sax_parse(text, &sec);
// output the recorded events
for (auto& event : sec.events)
{
std::cout << "(" << event << ") ";
}
// output the result of sax_parse
std::cout << "\nresult: " << std::boolalpha << result << std::endl;
}

View File

@@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/fGkQLWbQn7enKkIG"><b>online</b></a>

View File

@@ -0,0 +1,2 @@
(start: object) (key: Image) (start: object) (key: Width) (value: 800) (key: Height) (value: 600) (key: Title) (value: View from 15th Floor) (key: Thumbnail) (start: object) (key: Url) (value: http://www.example.com/image/481989943) (key: Height) (value: 125) (key: Width) (value: 100) (end: object) (key: Animated) (value: false) (key: IDs) (start: array) (value: 116) (value: 943) (value: 234) (value: 38793) (end: array) (key: Distance) (value: 12.723374634) (end: object) (end: object)
result: true

View File

@@ -1,4 +1,5 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/4bQSclXeqjVFYVL3"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/LRM37xarSuPJmv92"><b>online</b></a>

View File

@@ -1,4 +1,5 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/WvT2Q0r9vlJYyMM8"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/CaRFhkrefL4miesE"><b>online</b></a>

View File

@@ -1,4 +1,5 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/j3HE6cOkCmKbxxAt"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/2luqHy9iADx4UNm7"><b>online</b></a>

View File

@@ -1,4 +1,5 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/U45AGi5nsDtoDf3u"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/knK4jnD2hIVxQoyk"><b>online</b></a>

View File

@@ -1,4 +1,5 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/TGvdYyJtstacZxWq"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/kjcoWACW7FMqKRBG"><b>online</b></a>

View File

@@ -1,4 +1,5 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

View File

@@ -1 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/BMlas6312rkE4cxz"><b>online</b></a>
<a target="_blank" href="https://wandbox.org/permlink/0LBIsEa18IrerWwy"><b>online</b></a>

View File

@@ -39,9 +39,11 @@ These pages contain the API documentation of JSON for Modern C++, a C++11 header
- @link nlohmann::basic_json::dump dump @endlink serialize to string
- @link nlohmann::basic_json::operator<<(std::ostream&, const basic_json &) operator<< @endlink serialize to stream
- deserialization / parsing
- @link nlohmann::basic_json::parse parse @endlink parse from string
- @link nlohmann::basic_json::parse parse @endlink parse from input (string, file, etc.) and return JSON value
- @link nlohmann::basic_json::sax_parse sax_parse @endlink parse from input (string, file, etc.) and generate SAX events
- @link nlohmann::basic_json::operator>>(std::istream&, basic_json&) operator>> @endlink parse from stream
- @link nlohmann::basic_json::accept accept @endlink check for syntax errors without parsing
- @link nlohmann::json_sax SAX interface @endlink define a user-defined SAX event consumer
- [binary formats](binary_formats.md):
- CBOR: @link nlohmann::basic_json::from_cbor from_cbor @endlink / @link nlohmann::basic_json::to_cbor to_cbor @endlink
- MessagePack: @link nlohmann::basic_json::from_msgpack from_msgpack @endlink / @link nlohmann::basic_json::to_msgpack to_msgpack @endlink
@@ -304,4 +306,4 @@ Note that this table only lists those exceptions thrown due to the type. For ins
@author [Niels Lohmann](http://nlohmann.me)
@see https://github.com/nlohmann/json to download the source code
@version 3.1.2
@version 3.3.0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

@@ -20,8 +20,10 @@ struct adl_serializer
@param[in,out] val value to write to
*/
template<typename BasicJsonType, typename ValueType>
static void from_json(BasicJsonType&& j, ValueType& val) noexcept(
noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
static auto from_json(BasicJsonType&& j, ValueType& val) noexcept(
noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val))) -> decltype(
::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void()
)
{
::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
}
@@ -35,9 +37,11 @@ struct adl_serializer
@param[in,out] j JSON value to write to
@param[in] val value to read from
*/
template<typename BasicJsonType, typename ValueType>
static void to_json(BasicJsonType& j, ValueType&& val) noexcept(
template <typename BasicJsonType, typename ValueType>
static auto to_json(BasicJsonType& j, ValueType&& val) noexcept(
noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
-> decltype(::nlohmann::to_json(j, std::forward<ValueType>(val)),
void())
{
::nlohmann::to_json(j, std::forward<ValueType>(val));
}

View File

@@ -5,21 +5,34 @@
#include <ciso646> // and, not
#include <forward_list> // forward_list
#include <iterator> // inserter, front_inserter, end
#include <map> // map
#include <string> // string
#include <tuple> // tuple, make_tuple
#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
#include <unordered_map> // unordered_map
#include <utility> // pair, declval
#include <valarray> // valarray
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/value_t.hpp>
namespace nlohmann
{
namespace detail
{
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
{
if (JSON_UNLIKELY(not j.is_null()))
{
JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
}
n = nullptr;
}
// overloads for basic_json template parameters
template<typename BasicJsonType, typename ArithmeticType,
enable_if_t<std::is_arithmetic<ArithmeticType>::value and
@@ -70,6 +83,23 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
}
template <
typename BasicJsonType, typename CompatibleStringType,
enable_if_t <
is_compatible_string_type<BasicJsonType, CompatibleStringType>::value and
not std::is_same<typename BasicJsonType::string_t,
CompatibleStringType>::value,
int > = 0 >
void from_json(const BasicJsonType& j, CompatibleStringType& s)
{
if (JSON_UNLIKELY(not j.is_string()))
{
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
}
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
}
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
{
@@ -97,16 +127,6 @@ void from_json(const BasicJsonType& j, EnumType& e)
e = static_cast<EnumType>(val);
}
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
{
if (JSON_UNLIKELY(not j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
}
arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
}
// forward_list doesn't have an insert method
template<typename BasicJsonType, typename T, typename Allocator,
enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
@@ -136,24 +156,28 @@ void from_json(const BasicJsonType& j, std::valarray<T>& l)
std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l));
}
template<typename BasicJsonType, typename CompatibleArrayType>
void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0> /*unused*/)
template<typename BasicJsonType>
void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
{
using std::end;
arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
}
std::transform(j.begin(), j.end(),
std::inserter(arr, end(arr)), [](const BasicJsonType & i)
template <typename BasicJsonType, typename T, std::size_t N>
auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
priority_tag<2> /*unused*/)
-> decltype(j.template get<T>(), void())
{
for (std::size_t i = 0; i < N; ++i)
{
// get<BasicJsonType>() returns *this, this won't call a from_json
// method when value_type is BasicJsonType
return i.template get<typename CompatibleArrayType::value_type>();
});
arr[i] = j.at(i).template get<T>();
}
}
template<typename BasicJsonType, typename CompatibleArrayType>
auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1> /*unused*/)
-> decltype(
arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
j.template get<typename CompatibleArrayType::value_type>(),
void())
{
using std::end;
@@ -168,25 +192,34 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, prio
});
}
template<typename BasicJsonType, typename T, std::size_t N>
void from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, priority_tag<2> /*unused*/)
template <typename BasicJsonType, typename CompatibleArrayType>
void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr,
priority_tag<0> /*unused*/)
{
for (std::size_t i = 0; i < N; ++i)
using std::end;
std::transform(
j.begin(), j.end(), std::inserter(arr, end(arr)),
[](const BasicJsonType & i)
{
arr[i] = j.at(i).template get<T>();
}
// get<BasicJsonType>() returns *this, this won't call a from_json
// method when value_type is BasicJsonType
return i.template get<typename CompatibleArrayType::value_type>();
});
}
template <
typename BasicJsonType, typename CompatibleArrayType,
enable_if_t <
is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
not std::is_same<typename BasicJsonType::array_t,
CompatibleArrayType>::value and
std::is_constructible <
BasicJsonType, typename CompatibleArrayType::value_type >::value,
int > = 0 >
void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
template <typename BasicJsonType, typename CompatibleArrayType,
enable_if_t <
is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
not is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value and
not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and
not is_basic_json<CompatibleArrayType>::value,
int > = 0 >
auto from_json(const BasicJsonType& j, CompatibleArrayType& arr)
-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
j.template get<typename CompatibleArrayType::value_type>(),
void())
{
if (JSON_UNLIKELY(not j.is_array()))
{
@@ -194,7 +227,7 @@ void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
std::string(j.type_name())));
}
from_json_array_impl(j, arr, priority_tag<2> {});
from_json_array_impl(j, arr, priority_tag<3> {});
}
template<typename BasicJsonType, typename CompatibleObjectType,
@@ -277,37 +310,53 @@ void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
}
template <typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
typename = enable_if_t<not std::is_constructible<
typename BasicJsonType::string_t, Key>::value>>
void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
{
if (JSON_UNLIKELY(not j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
}
for (const auto& p : j)
{
if (JSON_UNLIKELY(not p.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
}
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
}
}
template <typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
typename = enable_if_t<not std::is_constructible<
typename BasicJsonType::string_t, Key>::value>>
void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
{
if (JSON_UNLIKELY(not j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
}
for (const auto& p : j)
{
if (JSON_UNLIKELY(not p.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
}
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
}
}
struct from_json_fn
{
private:
template<typename BasicJsonType, typename T>
auto call(const BasicJsonType& j, T& val, priority_tag<1> /*unused*/) const
auto operator()(const BasicJsonType& j, T& val) const
noexcept(noexcept(from_json(j, val)))
-> decltype(from_json(j, val), void())
{
return from_json(j, val);
}
template<typename BasicJsonType, typename T>
void call(const BasicJsonType& /*unused*/, T& /*unused*/, priority_tag<0> /*unused*/) const noexcept
{
static_assert(sizeof(BasicJsonType) == 0,
"could not find from_json() method in T's namespace");
#ifdef _MSC_VER
// MSVC does not show a stacktrace for the above assert
using decayed = uncvref_t<T>;
static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0,
"forcing MSVC stacktrace to show which T we're talking about.");
#endif
}
public:
template<typename BasicJsonType, typename T>
void operator()(const BasicJsonType& j, T& val) const
noexcept(noexcept(std::declval<from_json_fn>().call(j, val, priority_tag<1> {})))
{
return call(j, val, priority_tag<1> {});
}
};
}

View File

@@ -887,7 +887,7 @@ void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
// numbers, all float's can be recovered using strtod (and strtof). However, the resulting
// decimal representations are not exactly "short".
//
// The documentation for 'std::to_chars' (http://en.cppreference.com/w/cpp/utility/to_chars)
// The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
// says "value is converted to a string as if by std::sprintf in the default ("C") locale"
// and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars'
// does.

View File

@@ -8,8 +8,10 @@
#include <valarray> // valarray
#include <vector> // vector
#include <nlohmann/detail/meta.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/value_t.hpp>
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
namespace nlohmann
{
@@ -51,6 +53,16 @@ struct external_constructor<value_t::string>
j.m_value = std::move(s);
j.assert_invariant();
}
template<typename BasicJsonType, typename CompatibleStringType,
enable_if_t<not std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
int> = 0>
static void construct(BasicJsonType& j, const CompatibleStringType& str)
{
j.m_type = value_t::string;
j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
j.assert_invariant();
}
};
template<>
@@ -236,10 +248,14 @@ void to_json(BasicJsonType& j, const std::vector<bool>& e)
external_constructor<value_t::array>::construct(j, e);
}
template<typename BasicJsonType, typename CompatibleArrayType,
enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value or
std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value,
int> = 0>
template <typename BasicJsonType, typename CompatibleArrayType,
enable_if_t<is_compatible_array_type<BasicJsonType,
CompatibleArrayType>::value and
not is_compatible_object_type<
BasicJsonType, CompatibleArrayType>::value and
not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and
not is_basic_json<CompatibleArrayType>::value,
int> = 0>
void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
{
external_constructor<value_t::array>::construct(j, arr);
@@ -247,7 +263,7 @@ void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
template<typename BasicJsonType, typename T,
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
void to_json(BasicJsonType& j, std::valarray<T> arr)
void to_json(BasicJsonType& j, const std::valarray<T>& arr)
{
external_constructor<value_t::array>::construct(j, std::move(arr));
}
@@ -259,7 +275,7 @@ void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
}
template<typename BasicJsonType, typename CompatibleObjectType,
enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0>
enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value and not is_basic_json<CompatibleObjectType>::value, int> = 0>
void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
{
external_constructor<value_t::object>::construct(j, obj);
@@ -271,9 +287,12 @@ void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
external_constructor<value_t::object>::construct(j, std::move(obj));
}
template<typename BasicJsonType, typename T, std::size_t N,
enable_if_t<not std::is_constructible<typename BasicJsonType::string_t, T (&)[N]>::value, int> = 0>
void to_json(BasicJsonType& j, T (&arr)[N])
template <
typename BasicJsonType, typename T, std::size_t N,
enable_if_t<not std::is_constructible<typename BasicJsonType::string_t,
const T (&)[N]>::value,
int> = 0 >
void to_json(BasicJsonType& j, const T (&arr)[N])
{
external_constructor<value_t::array>::construct(j, arr);
}
@@ -284,6 +303,14 @@ void to_json(BasicJsonType& j, const std::pair<Args...>& p)
j = {p.first, p.second};
}
// for https://github.com/nlohmann/json/pull/1134
template<typename BasicJsonType, typename T,
enable_if_t<std::is_same<T, typename iteration_proxy<typename BasicJsonType::iterator>::iteration_proxy_internal>::value, int> = 0>
void to_json(BasicJsonType& j, T b) noexcept
{
j = {{b.key(), b.value()}};
}
template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...>)
{
@@ -298,35 +325,12 @@ void to_json(BasicJsonType& j, const std::tuple<Args...>& t)
struct to_json_fn
{
private:
template<typename BasicJsonType, typename T>
auto call(BasicJsonType& j, T&& val, priority_tag<1> /*unused*/) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
-> decltype(to_json(j, std::forward<T>(val)), void())
{
return to_json(j, std::forward<T>(val));
}
template<typename BasicJsonType, typename T>
void call(BasicJsonType& /*unused*/, T&& /*unused*/, priority_tag<0> /*unused*/) const noexcept
{
static_assert(sizeof(BasicJsonType) == 0,
"could not find to_json() method in T's namespace");
#ifdef _MSC_VER
// MSVC does not show a stacktrace for the above assert
using decayed = uncvref_t<T>;
static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0,
"forcing MSVC stacktrace to show which T we're talking about.");
#endif
}
public:
template<typename BasicJsonType, typename T>
void operator()(BasicJsonType& j, T&& val) const
noexcept(noexcept(std::declval<to_json_fn>().call(j, std::forward<T>(val), priority_tag<1> {})))
{
return call(j, std::forward<T>(val), priority_tag<1> {});
}
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,8 @@
#pragma once
#include <algorithm> // min
#include <array> // array
#include <cassert> // assert
#include <cstddef> // size_t
#include <cstring> // strlen
#include <ios> // streamsize, streamoff, streampos
#include <istream> // istream
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
#include <memory> // shared_ptr, make_shared, addressof
@@ -20,6 +17,9 @@ namespace nlohmann
{
namespace detail
{
/// the supported input formats
enum class input_format_t { json, cbor, msgpack, ubjson };
////////////////////
// input adapters //
////////////////////
@@ -28,19 +28,17 @@ namespace detail
@brief abstract input adapter interface
Produces a stream of std::char_traits<char>::int_type characters from a
std::istream, a buffer, or some other input type. Accepts the return of exactly
one non-EOF character for future input. The int_type characters returned
consist of all valid char values as positive values (typically unsigned char),
plus an EOF value outside that range, specified by the value of the function
std::char_traits<char>::eof(). This value is typically -1, but could be any
arbitrary value which is not a valid char value.
std::istream, a buffer, or some other input type. Accepts the return of
exactly one non-EOF character for future input. The int_type characters
returned consist of all valid char values as positive values (typically
unsigned char), plus an EOF value outside that range, specified by the value
of the function std::char_traits<char>::eof(). This value is typically -1, but
could be any arbitrary value which is not a valid char value.
*/
struct input_adapter_protocol
{
/// get a character [0,255] or std::char_traits<char>::eof().
virtual std::char_traits<char>::int_type get_character() = 0;
/// restore the last non-eof() character to input
virtual void unget_character() = 0;
virtual ~input_adapter_protocol() = default;
};
@@ -68,34 +66,7 @@ class input_stream_adapter : public input_adapter_protocol
explicit input_stream_adapter(std::istream& i)
: is(i), sb(*i.rdbuf())
{
// skip byte order mark
std::char_traits<char>::int_type c;
if ((c = get_character()) == 0xEF)
{
if ((c = get_character()) == 0xBB)
{
if ((c = get_character()) == 0xBF)
{
return; // Ignore BOM
}
else if (c != std::char_traits<char>::eof())
{
is.unget();
}
is.putback('\xBB');
}
else if (c != std::char_traits<char>::eof())
{
is.unget();
}
is.putback('\xEF');
}
else if (c != std::char_traits<char>::eof())
{
is.unget(); // no byte order mark; process as usual
}
}
{}
// delete because of pointer members
input_stream_adapter(const input_stream_adapter&) = delete;
@@ -109,11 +80,6 @@ class input_stream_adapter : public input_adapter_protocol
return sb.sbumpc();
}
void unget_character() override
{
sb.sungetc(); // is.unget() avoided for performance
}
private:
/// the associated input stream
std::istream& is;
@@ -125,14 +91,8 @@ class input_buffer_adapter : public input_adapter_protocol
{
public:
input_buffer_adapter(const char* b, const std::size_t l)
: cursor(b), limit(b + l), start(b)
{
// skip byte order mark
if (l >= 3 and b[0] == '\xEF' and b[1] == '\xBB' and b[2] == '\xBF')
{
cursor += 3;
}
}
: cursor(b), limit(b + l)
{}
// delete because of pointer members
input_buffer_adapter(const input_buffer_adapter&) = delete;
@@ -148,21 +108,172 @@ class input_buffer_adapter : public input_adapter_protocol
return std::char_traits<char>::eof();
}
void unget_character() noexcept override
{
if (JSON_LIKELY(cursor > start))
{
--cursor;
}
}
private:
/// pointer to the current character
const char* cursor;
/// pointer past the last character
const char* limit;
/// pointer to the first character
const char* start;
const char* const limit;
};
template<typename WideStringType, size_t T>
struct wide_string_input_helper
{
// UTF-32
static void fill_buffer(const WideStringType& str, size_t& current_wchar, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled)
{
utf8_bytes_index = 0;
if (current_wchar == str.size())
{
utf8_bytes[0] = std::char_traits<char>::eof();
utf8_bytes_filled = 1;
}
else
{
// get the current character
const int wc = static_cast<int>(str[current_wchar++]);
// UTF-32 to UTF-8 encoding
if (wc < 0x80)
{
utf8_bytes[0] = wc;
utf8_bytes_filled = 1;
}
else if (wc <= 0x7FF)
{
utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F);
utf8_bytes[1] = 0x80 | (wc & 0x3F);
utf8_bytes_filled = 2;
}
else if (wc <= 0xFFFF)
{
utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F);
utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
utf8_bytes[2] = 0x80 | (wc & 0x3F);
utf8_bytes_filled = 3;
}
else if (wc <= 0x10FFFF)
{
utf8_bytes[0] = 0xF0 | ((wc >> 18) & 0x07);
utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F);
utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F);
utf8_bytes[3] = 0x80 | (wc & 0x3F);
utf8_bytes_filled = 4;
}
else
{
// unknown character
utf8_bytes[0] = wc;
utf8_bytes_filled = 1;
}
}
}
};
template<typename WideStringType>
struct wide_string_input_helper<WideStringType, 2>
{
// UTF-16
static void fill_buffer(const WideStringType& str, size_t& current_wchar, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled)
{
utf8_bytes_index = 0;
if (current_wchar == str.size())
{
utf8_bytes[0] = std::char_traits<char>::eof();
utf8_bytes_filled = 1;
}
else
{
// get the current character
const int wc = static_cast<int>(str[current_wchar++]);
// UTF-16 to UTF-8 encoding
if (wc < 0x80)
{
utf8_bytes[0] = wc;
utf8_bytes_filled = 1;
}
else if (wc <= 0x7FF)
{
utf8_bytes[0] = 0xC0 | ((wc >> 6));
utf8_bytes[1] = 0x80 | (wc & 0x3F);
utf8_bytes_filled = 2;
}
else if (0xD800 > wc or wc >= 0xE000)
{
utf8_bytes[0] = 0xE0 | ((wc >> 12));
utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
utf8_bytes[2] = 0x80 | (wc & 0x3F);
utf8_bytes_filled = 3;
}
else
{
if (current_wchar < str.size())
{
const int wc2 = static_cast<int>(str[current_wchar++]);
const int charcode = 0x10000 + (((wc & 0x3FF) << 10) | (wc2 & 0x3FF));
utf8_bytes[0] = 0xf0 | (charcode >> 18);
utf8_bytes[1] = 0x80 | ((charcode >> 12) & 0x3F);
utf8_bytes[2] = 0x80 | ((charcode >> 6) & 0x3F);
utf8_bytes[3] = 0x80 | (charcode & 0x3F);
utf8_bytes_filled = 4;
}
else
{
// unknown character
++current_wchar;
utf8_bytes[0] = wc;
utf8_bytes_filled = 1;
}
}
}
}
};
template<typename WideStringType>
class wide_string_input_adapter : public input_adapter_protocol
{
public:
explicit wide_string_input_adapter(const WideStringType& w) : str(w) {}
std::char_traits<char>::int_type get_character() noexcept override
{
// check if buffer needs to be filled
if (utf8_bytes_index == utf8_bytes_filled)
{
fill_buffer<sizeof(typename WideStringType::value_type)>();
assert(utf8_bytes_filled > 0);
assert(utf8_bytes_index == 0);
}
// use buffer
assert(utf8_bytes_filled > 0);
assert(utf8_bytes_index < utf8_bytes_filled);
return utf8_bytes[utf8_bytes_index++];
}
private:
template<size_t T>
void fill_buffer()
{
wide_string_input_helper<WideStringType, T>::fill_buffer(str, current_wchar, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
}
/// the wstring to process
const WideStringType& str;
/// index of the current wchar in str
std::size_t current_wchar = 0;
/// a buffer for UTF-8 bytes
std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
/// index to the utf8_codes array for the next valid byte
std::size_t utf8_bytes_index = 0;
/// number of valid bytes in the utf8_codes array
std::size_t utf8_bytes_filled = 0;
};
class input_adapter
@@ -178,6 +289,15 @@ class input_adapter
input_adapter(std::istream&& i)
: ia(std::make_shared<input_stream_adapter>(i)) {}
input_adapter(const std::wstring& ws)
: ia(std::make_shared<wide_string_input_adapter<std::wstring>>(ws)) {}
input_adapter(const std::u16string& ws)
: ia(std::make_shared<wide_string_input_adapter<std::u16string>>(ws)) {}
input_adapter(const std::u32string& ws)
: ia(std::make_shared<wide_string_input_adapter<std::u32string>>(ws)) {}
/// input adapter for buffer
template<typename CharT,
typename std::enable_if<
@@ -208,15 +328,18 @@ class input_adapter
int>::type = 0>
input_adapter(IteratorType first, IteratorType last)
{
#ifndef NDEBUG
// assertion to check that the iterator range is indeed contiguous,
// see http://stackoverflow.com/a/35008842/266378 for more discussion
assert(std::accumulate(
first, last, std::pair<bool, int>(true, 0),
[&first](std::pair<bool, int> res, decltype(*first) val)
const auto is_contiguous = std::accumulate(
first, last, std::pair<bool, int>(true, 0),
[&first](std::pair<bool, int> res, decltype(*first) val)
{
res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
return res;
}).first);
}).first;
assert(is_contiguous);
#endif
// assertion to check that each element is 1 byte long
static_assert(

View File

@@ -0,0 +1,702 @@
#pragma once
#include <cstddef>
#include <string>
#include <vector>
#include <nlohmann/detail/input/parser.hpp>
#include <nlohmann/detail/exceptions.hpp>
namespace nlohmann
{
/*!
@brief SAX interface
This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
Each function is called in different situations while the input is parsed. The
boolean return value informs the parser whether to continue processing the
input.
*/
template<typename BasicJsonType>
struct json_sax
{
/// type for (signed) integers
using number_integer_t = typename BasicJsonType::number_integer_t;
/// type for unsigned integers
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
/// type for floating-point numbers
using number_float_t = typename BasicJsonType::number_float_t;
/// type for strings
using string_t = typename BasicJsonType::string_t;
/*!
@brief a null value was read
@return whether parsing should proceed
*/
virtual bool null() = 0;
/*!
@brief a boolean value was read
@param[in] val boolean value
@return whether parsing should proceed
*/
virtual bool boolean(bool val) = 0;
/*!
@brief an integer number was read
@param[in] val integer value
@return whether parsing should proceed
*/
virtual bool number_integer(number_integer_t val) = 0;
/*!
@brief an unsigned integer number was read
@param[in] val unsigned integer value
@return whether parsing should proceed
*/
virtual bool number_unsigned(number_unsigned_t val) = 0;
/*!
@brief an floating-point number was read
@param[in] val floating-point value
@param[in] s raw token value
@return whether parsing should proceed
*/
virtual bool number_float(number_float_t val, const string_t& s) = 0;
/*!
@brief a string was read
@param[in] val string value
@return whether parsing should proceed
@note It is safe to move the passed string.
*/
virtual bool string(string_t& val) = 0;
/*!
@brief the beginning of an object was read
@param[in] elements number of object elements or -1 if unknown
@return whether parsing should proceed
@note binary formats may report the number of elements
*/
virtual bool start_object(std::size_t elements) = 0;
/*!
@brief an object key was read
@param[in] val object key
@return whether parsing should proceed
@note It is safe to move the passed string.
*/
virtual bool key(string_t& val) = 0;
/*!
@brief the end of an object was read
@return whether parsing should proceed
*/
virtual bool end_object() = 0;
/*!
@brief the beginning of an array was read
@param[in] elements number of array elements or -1 if unknown
@return whether parsing should proceed
@note binary formats may report the number of elements
*/
virtual bool start_array(std::size_t elements) = 0;
/*!
@brief the end of an array was read
@return whether parsing should proceed
*/
virtual bool end_array() = 0;
/*!
@brief a parse error occurred
@param[in] position the position in the input where the error occurs
@param[in] last_token the last read token
@param[in] error_msg a detailed error message
@return whether parsing should proceed (must return false)
*/
virtual bool parse_error(std::size_t position,
const std::string& last_token,
const detail::exception& ex) = 0;
virtual ~json_sax() = default;
};
namespace detail
{
/*!
@brief SAX implementation to create a JSON value from SAX events
This class implements the @ref json_sax interface and processes the SAX events
to create a JSON value which makes it basically a DOM parser. The structure or
hierarchy of the JSON value is managed by the stack `ref_stack` which contains
a pointer to the respective array or object for each recursion depth.
After successful parsing, the value that is passed by reference to the
constructor contains the parsed value.
@tparam BasicJsonType the JSON type
*/
template<typename BasicJsonType>
class json_sax_dom_parser
{
public:
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
/*!
@param[in, out] r reference to a JSON value that is manipulated while
parsing
@param[in] allow_exceptions_ whether parse errors yield exceptions
*/
explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
: root(r), allow_exceptions(allow_exceptions_)
{}
bool null()
{
handle_value(nullptr);
return true;
}
bool boolean(bool val)
{
handle_value(val);
return true;
}
bool number_integer(number_integer_t val)
{
handle_value(val);
return true;
}
bool number_unsigned(number_unsigned_t val)
{
handle_value(val);
return true;
}
bool number_float(number_float_t val, const string_t&)
{
handle_value(val);
return true;
}
bool string(string_t& val)
{
handle_value(val);
return true;
}
bool start_object(std::size_t len)
{
ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive object size: " + std::to_string(len)));
}
return true;
}
bool key(string_t& val)
{
// add null at given key and store the reference for later
object_element = &(ref_stack.back()->m_value.object->operator[](val));
return true;
}
bool end_object()
{
ref_stack.pop_back();
return true;
}
bool start_array(std::size_t len)
{
ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive array size: " + std::to_string(len)));
}
return true;
}
bool end_array()
{
ref_stack.pop_back();
return true;
}
bool parse_error(std::size_t, const std::string&,
const detail::exception& ex)
{
errored = true;
if (allow_exceptions)
{
// determine the proper exception type from the id
switch ((ex.id / 100) % 100)
{
case 1:
JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
case 4:
JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
// LCOV_EXCL_START
case 2:
JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
case 3:
JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
case 5:
JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
default:
assert(false);
// LCOV_EXCL_STOP
}
}
return false;
}
constexpr bool is_errored() const
{
return errored;
}
private:
/*!
@invariant If the ref stack is empty, then the passed value will be the new
root.
@invariant If the ref stack contains a value, then it is an array or an
object to which we can add elements
*/
template<typename Value>
BasicJsonType* handle_value(Value&& v)
{
if (ref_stack.empty())
{
root = BasicJsonType(std::forward<Value>(v));
return &root;
}
else
{
assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
if (ref_stack.back()->is_array())
{
ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
return &(ref_stack.back()->m_value.array->back());
}
else
{
assert(object_element);
*object_element = BasicJsonType(std::forward<Value>(v));
return object_element;
}
}
}
/// the parsed JSON value
BasicJsonType& root;
/// stack to model hierarchy of values
std::vector<BasicJsonType*> ref_stack;
/// helper to hold the reference for the next object element
BasicJsonType* object_element = nullptr;
/// whether a syntax error occurred
bool errored = false;
/// whether to throw exceptions in case of errors
const bool allow_exceptions = true;
};
template<typename BasicJsonType>
class json_sax_dom_callback_parser
{
public:
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
using parser_callback_t = typename BasicJsonType::parser_callback_t;
using parse_event_t = typename BasicJsonType::parse_event_t;
json_sax_dom_callback_parser(BasicJsonType& r,
const parser_callback_t cb,
const bool allow_exceptions_ = true)
: root(r), callback(cb), allow_exceptions(allow_exceptions_)
{
keep_stack.push_back(true);
}
bool null()
{
handle_value(nullptr);
return true;
}
bool boolean(bool val)
{
handle_value(val);
return true;
}
bool number_integer(number_integer_t val)
{
handle_value(val);
return true;
}
bool number_unsigned(number_unsigned_t val)
{
handle_value(val);
return true;
}
bool number_float(number_float_t val, const string_t&)
{
handle_value(val);
return true;
}
bool string(string_t& val)
{
handle_value(val);
return true;
}
bool start_object(std::size_t len)
{
// check callback for object start
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
keep_stack.push_back(keep);
auto val = handle_value(BasicJsonType::value_t::object, true);
ref_stack.push_back(val.second);
// check object limit
if (ref_stack.back())
{
if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive object size: " + std::to_string(len)));
}
}
return true;
}
bool key(string_t& val)
{
BasicJsonType k = BasicJsonType(val);
// check callback for key
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
key_keep_stack.push_back(keep);
// add discarded value at given key and store the reference for later
if (keep and ref_stack.back())
{
object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
}
return true;
}
bool end_object()
{
if (ref_stack.back())
{
if (not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
{
// discard object
*ref_stack.back() = discarded;
}
}
assert(not ref_stack.empty());
assert(not keep_stack.empty());
ref_stack.pop_back();
keep_stack.pop_back();
if (not ref_stack.empty() and ref_stack.back())
{
// remove discarded value
if (ref_stack.back()->is_object())
{
for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
{
if (it->is_discarded())
{
ref_stack.back()->erase(it);
break;
}
}
}
}
return true;
}
bool start_array(std::size_t len)
{
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
keep_stack.push_back(keep);
auto val = handle_value(BasicJsonType::value_t::array, true);
ref_stack.push_back(val.second);
// check array limit
if (ref_stack.back())
{
if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive array size: " + std::to_string(len)));
}
}
return true;
}
bool end_array()
{
bool keep = true;
if (ref_stack.back())
{
keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
if (not keep)
{
// discard array
*ref_stack.back() = discarded;
}
}
assert(not ref_stack.empty());
assert(not keep_stack.empty());
ref_stack.pop_back();
keep_stack.pop_back();
// remove discarded value
if (not keep and not ref_stack.empty())
{
if (ref_stack.back()->is_array())
{
ref_stack.back()->m_value.array->pop_back();
}
}
return true;
}
bool parse_error(std::size_t, const std::string&,
const detail::exception& ex)
{
errored = true;
if (allow_exceptions)
{
// determine the proper exception type from the id
switch ((ex.id / 100) % 100)
{
case 1:
JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
case 4:
JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
// LCOV_EXCL_START
case 2:
JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
case 3:
JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
case 5:
JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
default:
assert(false);
// LCOV_EXCL_STOP
}
}
return false;
}
constexpr bool is_errored() const
{
return errored;
}
private:
/*!
@param[in] v value to add to the JSON value we build during parsing
@param[in] skip_callback whether we should skip calling the callback
function; this is required after start_array() and
start_object() SAX events, because otherwise we would call the
callback function with an empty array or object, respectively.
@invariant If the ref stack is empty, then the passed value will be the new
root.
@invariant If the ref stack contains a value, then it is an array or an
object to which we can add elements
@return pair of boolean (whether value should be kept) and pointer (to the
passed value in the ref_stack hierarchy; nullptr if not kept)
*/
template<typename Value>
std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
{
assert(not keep_stack.empty());
// do not handle this value if we know it would be added to a discarded
// container
if (not keep_stack.back())
{
return {false, nullptr};
}
// create value
auto value = BasicJsonType(std::forward<Value>(v));
// check callback
const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
// do not handle this value if we just learnt it shall be discarded
if (not keep)
{
return {false, nullptr};
}
if (ref_stack.empty())
{
root = std::move(value);
return {true, &root};
}
else
{
// skip this value if we already decided to skip the parent
// (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
if (not ref_stack.back())
{
return {false, nullptr};
}
assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
if (ref_stack.back()->is_array())
{
ref_stack.back()->m_value.array->push_back(std::move(value));
return {true, &(ref_stack.back()->m_value.array->back())};
}
else
{
// check if we should store an element for the current key
assert(not key_keep_stack.empty());
const bool store_element = key_keep_stack.back();
key_keep_stack.pop_back();
if (not store_element)
{
return {false, nullptr};
}
assert(object_element);
*object_element = std::move(value);
return {true, object_element};
}
}
}
/// the parsed JSON value
BasicJsonType& root;
/// stack to model hierarchy of values
std::vector<BasicJsonType*> ref_stack;
/// stack to manage which values to keep
std::vector<bool> keep_stack;
/// stack to manage which object keys to keep
std::vector<bool> key_keep_stack;
/// helper to hold the reference for the next object element
BasicJsonType* object_element = nullptr;
/// whether a syntax error occurred
bool errored = false;
/// callback function
const parser_callback_t callback = nullptr;
/// whether to throw exceptions in case of errors
const bool allow_exceptions = true;
/// a discarded value for the callback
BasicJsonType discarded = BasicJsonType::value_t::discarded;
};
template<typename BasicJsonType>
class json_sax_acceptor
{
public:
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
bool null()
{
return true;
}
bool boolean(bool)
{
return true;
}
bool number_integer(number_integer_t)
{
return true;
}
bool number_unsigned(number_unsigned_t)
{
return true;
}
bool number_float(number_float_t, const string_t&)
{
return true;
}
bool string(string_t&)
{
return true;
}
bool start_object(std::size_t = std::size_t(-1))
{
return true;
}
bool key(string_t&)
{
return true;
}
bool end_object()
{
return true;
}
bool start_array(std::size_t = std::size_t(-1))
{
return true;
}
bool end_array()
{
return true;
}
bool parse_error(std::size_t, const std::string&, const detail::exception&)
{
return false;
}
};
}
}

View File

@@ -3,10 +3,8 @@
#include <clocale> // localeconv
#include <cstddef> // size_t
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
#include <cstdio> // snprintf
#include <initializer_list> // initializer_list
#include <ios> // hex, uppercase
#include <iomanip> // setw, setfill
#include <sstream> // stringstream
#include <string> // char_traits, string
#include <vector> // vector
@@ -94,12 +92,14 @@ class lexer
return "end of input";
case token_type::literal_or_value:
return "'[', '{', or a literal";
// LCOV_EXCL_START
default: // catch non-enum values
return "unknown token"; // LCOV_EXCL_LINE
return "unknown token";
// LCOV_EXCL_STOP
}
}
explicit lexer(detail::input_adapter_t adapter)
explicit lexer(detail::input_adapter_t&& adapter)
: ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}
// delete because of pointer members
@@ -747,11 +747,13 @@ class lexer
goto scan_number_any1;
}
// LCOV_EXCL_START
default:
{
// all other characters are rejected outside scan_number()
assert(false); // LCOV_EXCL_LINE
assert(false);
}
// LCOV_EXCL_STOP
}
scan_number_minus:
@@ -1081,7 +1083,16 @@ scan_number_done:
std::char_traits<char>::int_type get()
{
++chars_read;
current = ia->get_character();
if (next_unget)
{
// just reset the next_unget variable and work with current
next_unget = false;
}
else
{
current = ia->get_character();
}
if (JSON_LIKELY(current != std::char_traits<char>::eof()))
{
token_string.push_back(std::char_traits<char>::to_char_type(current));
@@ -1089,13 +1100,20 @@ scan_number_done:
return current;
}
/// unget current character (return it again on next get)
/*!
@brief unget current character (read it again on next get)
We implement unget by setting variable next_unget to true. The input is not
changed - we just simulate ungetting by modifying chars_read and
token_string. The next call to get() will behave as if the unget character
is read again.
*/
void unget()
{
next_unget = true;
--chars_read;
if (JSON_LIKELY(current != std::char_traits<char>::eof()))
{
ia->unget_character();
assert(token_string.size() != 0);
token_string.pop_back();
}
@@ -1131,9 +1149,9 @@ scan_number_done:
}
/// return current string value (implicitly resets the token; useful only once)
string_t&& move_string()
string_t& get_string()
{
return std::move(token_buffer);
return token_buffer;
}
/////////////////////
@@ -1158,10 +1176,9 @@ scan_number_done:
if ('\x00' <= c and c <= '\x1F')
{
// escape control characters
std::stringstream ss;
ss << "<U+" << std::setw(4) << std::uppercase << std::setfill('0')
<< std::hex << static_cast<int>(c) << ">";
result += ss.str();
char cs[9];
snprintf(cs, 9, "<U+%.4X>", static_cast<unsigned char>(c));
result += cs;
}
else
{
@@ -1183,8 +1200,43 @@ scan_number_done:
// actual scanner
/////////////////////
/*!
@brief skip the UTF-8 byte order mark
@return true iff there is no BOM or the correct BOM has been skipped
*/
bool skip_bom()
{
if (get() == 0xEF)
{
if (get() == 0xBB and get() == 0xBF)
{
// we completely parsed the BOM
return true;
}
else
{
// after reading 0xEF, an unexpected character followed
return false;
}
}
else
{
// the first character is not the beginning of the BOM; unget it to
// process is later
unget();
return true;
}
}
token_type scan()
{
// initially, skip the BOM
if (chars_read == 0 and not skip_bom())
{
error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
return token_type::parse_error;
}
// read next character and ignore whitespace
do
{
@@ -1254,6 +1306,9 @@ scan_number_done:
/// the current character
std::char_traits<char>::int_type current = std::char_traits<char>::eof();
/// whether the next get() call should just return current
bool next_unget = false;
/// the number of characters read
std::size_t chars_read = 0;

View File

@@ -9,7 +9,9 @@
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/is_sax.hpp>
#include <nlohmann/detail/input/input_adapters.hpp>
#include <nlohmann/detail/input/json_sax.hpp>
#include <nlohmann/detail/input/lexer.hpp>
#include <nlohmann/detail/value_t.hpp>
@@ -57,11 +59,14 @@ class parser
std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
/// a parser reading from an input adapter
explicit parser(detail::input_adapter_t adapter,
explicit parser(detail::input_adapter_t&& adapter,
const parser_callback_t cb = nullptr,
const bool allow_exceptions_ = true)
: callback(cb), m_lexer(adapter), allow_exceptions(allow_exceptions_)
{}
: callback(cb), m_lexer(std::move(adapter)), allow_exceptions(allow_exceptions_)
{
// read first token
get_token();
}
/*!
@brief public parser interface
@@ -75,31 +80,54 @@ class parser
*/
void parse(const bool strict, BasicJsonType& result)
{
// read first token
get_token();
parse_internal(true, result);
result.assert_invariant();
// in strict mode, input must be completely read
if (strict)
if (callback)
{
get_token();
expect(token_type::end_of_input);
json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
sax_parse_internal(&sdp);
result.assert_invariant();
// in strict mode, input must be completely read
if (strict and (get_token() != token_type::end_of_input))
{
sdp.parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
}
// in case of an error, return discarded value
if (sdp.is_errored())
{
result = value_t::discarded;
return;
}
// set top-level value to null if it was discarded by the callback
// function
if (result.is_discarded())
{
result = nullptr;
}
}
// in case of an error, return discarded value
if (errored)
else
{
result = value_t::discarded;
return;
}
json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
sax_parse_internal(&sdp);
result.assert_invariant();
// set top-level value to null if it was discarded by the callback
// function
if (result.is_discarded())
{
result = nullptr;
// in strict mode, input must be completely read
if (strict and (get_token() != token_type::end_of_input))
{
sdp.parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
}
// in case of an error, return discarded value
if (sdp.is_errored())
{
result = value_t::discarded;
return;
}
}
}
@@ -111,414 +139,311 @@ class parser
*/
bool accept(const bool strict = true)
{
// read first token
get_token();
json_sax_acceptor<BasicJsonType> sax_acceptor;
return sax_parse(&sax_acceptor, strict);
}
if (not accept_internal())
template <typename SAX>
bool sax_parse(SAX* sax, const bool strict = true)
{
(void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
const bool result = sax_parse_internal(sax);
// strict mode: next byte must be EOF
if (result and strict and (get_token() != token_type::end_of_input))
{
return false;
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
}
// strict => last token must be EOF
return not strict or (get_token() == token_type::end_of_input);
return result;
}
private:
/*!
@brief the actual parser
@throw parse_error.101 in case of an unexpected token
@throw parse_error.102 if to_unicode fails or surrogate error
@throw parse_error.103 if to_unicode fails
*/
void parse_internal(bool keep, BasicJsonType& result)
template <typename SAX>
bool sax_parse_internal(SAX* sax)
{
// never parse after a parse error was detected
assert(not errored);
// stack to remember the hieararchy of structured values we are parsing
// true = array; false = object
std::vector<bool> states;
// value to avoid a goto (see comment where set to true)
bool skip_to_state_evaluation = false;
// start with a discarded value
if (not result.is_discarded())
while (true)
{
result.m_value.destroy(result.m_type);
result.m_type = value_t::discarded;
}
switch (last_token)
{
case token_type::begin_object:
if (not skip_to_state_evaluation)
{
if (keep)
// invariant: get_token() was called before each iteration
switch (last_token)
{
if (callback)
case token_type::begin_object:
{
keep = callback(depth++, parse_event_t::object_start, result);
}
if (not callback or keep)
{
// explicitly set result to object to cope with {}
result.m_type = value_t::object;
result.m_value = value_t::object;
}
}
// read next token
get_token();
// closing } -> we are done
if (last_token == token_type::end_object)
{
if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
{
result.m_value.destroy(result.m_type);
result.m_type = value_t::discarded;
}
break;
}
// parse values
string_t key;
BasicJsonType value;
while (true)
{
// store key
if (not expect(token_type::value_string))
{
return;
}
key = m_lexer.move_string();
bool keep_tag = false;
if (keep)
{
if (callback)
if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
{
BasicJsonType k(key);
keep_tag = callback(depth, parse_event_t::key, k);
return false;
}
// closing } -> we are done
if (get_token() == token_type::end_object)
{
if (JSON_UNLIKELY(not sax->end_object()))
{
return false;
}
break;
}
// parse key
if (JSON_UNLIKELY(last_token != token_type::value_string))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
}
else
{
keep_tag = true;
if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
{
return false;
}
}
// parse separator (:)
if (JSON_UNLIKELY(get_token() != token_type::name_separator))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
}
// remember we are now inside an object
states.push_back(false);
// parse values
get_token();
continue;
}
case token_type::begin_array:
{
if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
{
return false;
}
// closing ] -> we are done
if (get_token() == token_type::end_array)
{
if (JSON_UNLIKELY(not sax->end_array()))
{
return false;
}
break;
}
// remember we are now inside an array
states.push_back(true);
// parse values (no need to call get_token)
continue;
}
case token_type::value_float:
{
const auto res = m_lexer.get_number_float();
if (JSON_UNLIKELY(not std::isfinite(res)))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
}
else
{
if (JSON_UNLIKELY(not sax->number_float(res, m_lexer.get_string())))
{
return false;
}
break;
}
}
// parse separator (:)
get_token();
if (not expect(token_type::name_separator))
case token_type::literal_false:
{
return;
if (JSON_UNLIKELY(not sax->boolean(false)))
{
return false;
}
break;
}
// parse and add value
get_token();
value.m_value.destroy(value.m_type);
value.m_type = value_t::discarded;
parse_internal(keep, value);
if (JSON_UNLIKELY(errored))
case token_type::literal_null:
{
return;
if (JSON_UNLIKELY(not sax->null()))
{
return false;
}
break;
}
if (keep and keep_tag and not value.is_discarded())
case token_type::literal_true:
{
result.m_value.object->emplace(std::move(key), std::move(value));
if (JSON_UNLIKELY(not sax->boolean(true)))
{
return false;
}
break;
}
// comma -> next value
get_token();
if (last_token == token_type::value_separator)
case token_type::value_integer:
{
get_token();
continue;
if (JSON_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer())))
{
return false;
}
break;
}
// closing }
if (not expect(token_type::end_object))
case token_type::value_string:
{
return;
}
break;
}
if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
{
result.m_value.destroy(result.m_type);
result.m_type = value_t::discarded;
}
break;
}
case token_type::begin_array:
{
if (keep)
{
if (callback)
{
keep = callback(depth++, parse_event_t::array_start, result);
if (JSON_UNLIKELY(not sax->string(m_lexer.get_string())))
{
return false;
}
break;
}
if (not callback or keep)
case token_type::value_unsigned:
{
// explicitly set result to array to cope with []
result.m_type = value_t::array;
result.m_value = value_t::array;
if (JSON_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned())))
{
return false;
}
break;
}
case token_type::parse_error:
{
// using "uninitialized" to avoid "expected" message
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized)));
}
default: // the last token was unexpected
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value)));
}
}
// read next token
get_token();
// closing ] -> we are done
if (last_token == token_type::end_array)
{
if (callback and not callback(--depth, parse_event_t::array_end, result))
{
result.m_value.destroy(result.m_type);
result.m_type = value_t::discarded;
}
break;
}
// parse values
BasicJsonType value;
while (true)
{
// parse value
value.m_value.destroy(value.m_type);
value.m_type = value_t::discarded;
parse_internal(keep, value);
if (JSON_UNLIKELY(errored))
{
return;
}
if (keep and not value.is_discarded())
{
result.m_value.array->push_back(std::move(value));
}
// comma -> next value
get_token();
if (last_token == token_type::value_separator)
{
get_token();
continue;
}
// closing ]
if (not expect(token_type::end_array))
{
return;
}
break;
}
if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
{
result.m_value.destroy(result.m_type);
result.m_type = value_t::discarded;
}
break;
}
case token_type::literal_null:
else
{
result.m_type = value_t::null;
break;
skip_to_state_evaluation = false;
}
case token_type::value_string:
// we reached this line after we successfully parsed a value
if (states.empty())
{
result.m_type = value_t::string;
result.m_value = m_lexer.move_string();
break;
}
case token_type::literal_true:
{
result.m_type = value_t::boolean;
result.m_value = true;
break;
}
case token_type::literal_false:
{
result.m_type = value_t::boolean;
result.m_value = false;
break;
}
case token_type::value_unsigned:
{
result.m_type = value_t::number_unsigned;
result.m_value = m_lexer.get_number_unsigned();
break;
}
case token_type::value_integer:
{
result.m_type = value_t::number_integer;
result.m_value = m_lexer.get_number_integer();
break;
}
case token_type::value_float:
{
result.m_type = value_t::number_float;
result.m_value = m_lexer.get_number_float();
// throw in case of infinity or NAN
if (JSON_UNLIKELY(not std::isfinite(result.m_value.number_float)))
{
if (allow_exceptions)
{
JSON_THROW(out_of_range::create(406, "number overflow parsing '" +
m_lexer.get_token_string() + "'"));
}
expect(token_type::uninitialized);
}
break;
}
case token_type::parse_error:
{
// using "uninitialized" to avoid "expected" message
if (not expect(token_type::uninitialized))
{
return;
}
break; // LCOV_EXCL_LINE
}
default:
{
// the last token was unexpected; we expected a value
if (not expect(token_type::literal_or_value))
{
return;
}
break; // LCOV_EXCL_LINE
}
}
if (keep and callback and not callback(depth, parse_event_t::value, result))
{
result.m_value.destroy(result.m_type);
result.m_type = value_t::discarded;
}
}
/*!
@brief the actual acceptor
@invariant 1. The last token is not yet processed. Therefore, the caller
of this function must make sure a token has been read.
2. When this function returns, the last token is processed.
That is, the last read character was already considered.
This invariant makes sure that no token needs to be "unput".
*/
bool accept_internal()
{
switch (last_token)
{
case token_type::begin_object:
{
// read next token
get_token();
// closing } -> we are done
if (last_token == token_type::end_object)
{
return true;
}
// parse values
while (true)
{
// parse key
if (last_token != token_type::value_string)
{
return false;
}
// parse separator (:)
get_token();
if (last_token != token_type::name_separator)
{
return false;
}
// parse value
get_token();
if (not accept_internal())
{
return false;
}
// comma -> next value
get_token();
if (last_token == token_type::value_separator)
{
get_token();
continue;
}
// closing }
return (last_token == token_type::end_object);
}
}
case token_type::begin_array:
{
// read next token
get_token();
// closing ] -> we are done
if (last_token == token_type::end_array)
{
return true;
}
// parse values
while (true)
{
// parse value
if (not accept_internal())
{
return false;
}
// comma -> next value
get_token();
if (last_token == token_type::value_separator)
{
get_token();
continue;
}
// closing ]
return (last_token == token_type::end_array);
}
}
case token_type::value_float:
{
// reject infinity or NAN
return std::isfinite(m_lexer.get_number_float());
}
case token_type::literal_false:
case token_type::literal_null:
case token_type::literal_true:
case token_type::value_integer:
case token_type::value_string:
case token_type::value_unsigned:
// empty stack: we reached the end of the hieararchy: done
return true;
}
else
{
if (states.back()) // array
{
// comma -> next value
if (get_token() == token_type::value_separator)
{
// parse a new value
get_token();
continue;
}
default: // the last token was unexpected
return false;
// closing ]
if (JSON_LIKELY(last_token == token_type::end_array))
{
if (JSON_UNLIKELY(not sax->end_array()))
{
return false;
}
// We are done with this array. Before we can parse a
// new value, we need to evaluate the new state first.
// By setting skip_to_state_evaluation to false, we
// are effectively jumping to the beginning of this if.
assert(not states.empty());
states.pop_back();
skip_to_state_evaluation = true;
continue;
}
else
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array)));
}
}
else // object
{
// comma -> next value
if (get_token() == token_type::value_separator)
{
// parse key
if (JSON_UNLIKELY(get_token() != token_type::value_string))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
}
else
{
if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
{
return false;
}
}
// parse separator (:)
if (JSON_UNLIKELY(get_token() != token_type::name_separator))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
}
// parse values
get_token();
continue;
}
// closing }
if (JSON_LIKELY(last_token == token_type::end_object))
{
if (JSON_UNLIKELY(not sax->end_object()))
{
return false;
}
// We are done with this object. Before we can parse a
// new value, we need to evaluate the new state first.
// By setting skip_to_state_evaluation to false, we
// are effectively jumping to the beginning of this if.
assert(not states.empty());
states.pop_back();
skip_to_state_evaluation = true;
continue;
}
else
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object)));
}
}
}
}
}
@@ -528,29 +453,7 @@ class parser
return (last_token = m_lexer.scan());
}
/*!
@throw parse_error.101 if expected token did not occur
*/
bool expect(token_type t)
{
if (JSON_UNLIKELY(t != last_token))
{
errored = true;
expected = t;
if (allow_exceptions)
{
throw_exception();
}
else
{
return false;
}
}
return true;
}
[[noreturn]] void throw_exception() const
std::string exception_message(const token_type expected)
{
std::string error_msg = "syntax error - ";
if (last_token == token_type::parse_error)
@@ -568,22 +471,16 @@ class parser
error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
}
JSON_THROW(parse_error::create(101, m_lexer.get_position(), error_msg));
return error_msg;
}
private:
/// current level of recursion
int depth = 0;
/// callback function
const parser_callback_t callback = nullptr;
/// the type of the last read token
token_type last_token = token_type::uninitialized;
/// the lexer
lexer_t m_lexer;
/// whether a syntax error occurred
bool errored = false;
/// possible reason for the syntax error
token_type expected = token_type::uninitialized;
/// whether to throw exceptions in case of errors
const bool allow_exceptions = true;
};

View File

@@ -8,7 +8,7 @@
#include <nlohmann/detail/iterators/internal_iterator.hpp>
#include <nlohmann/detail/iterators/primitive_iterator.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/value_t.hpp>
namespace nlohmann
@@ -31,7 +31,7 @@ This class implements a both iterators (iterator and const_iterator) for the
@requirement The class satisfies the following concept requirements:
-
[BidirectionalIterator](http://en.cppreference.com/w/cpp/concept/BidirectionalIterator):
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
The iterator that can be moved can be moved in both directions (i.e.
incremented and decremented).
@@ -583,7 +583,7 @@ class iter_impl
@brief return the key of an object iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
typename object_t::key_type key() const
const typename object_t::key_type& key() const
{
assert(m_object != nullptr);

View File

@@ -2,6 +2,7 @@
#include <cstddef> // size_t
#include <string> // string, to_string
#include <iterator> // input_iterator_tag
#include <nlohmann/detail/value_t.hpp>
@@ -16,15 +17,31 @@ template<typename IteratorType> class iteration_proxy
/// helper class for iteration
class iteration_proxy_internal
{
public:
using difference_type = std::ptrdiff_t;
using value_type = iteration_proxy_internal;
using pointer = iteration_proxy_internal*;
using reference = iteration_proxy_internal&;
using iterator_category = std::input_iterator_tag;
private:
/// the iterator
IteratorType anchor;
/// an index for arrays (used to create key names)
std::size_t array_index = 0;
/// last stringified array index
mutable std::size_t array_index_last = 0;
/// a string representation of the array index
mutable std::string array_index_str = "0";
/// an empty string (to return a reference for primitive values)
const std::string empty_str = "";
public:
explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {}
iteration_proxy_internal(const iteration_proxy_internal&) = default;
iteration_proxy_internal& operator=(const iteration_proxy_internal&) = default;
/// dereference operator (needed for range-based for)
iteration_proxy_internal& operator*()
{
@@ -40,6 +57,12 @@ template<typename IteratorType> class iteration_proxy
return *this;
}
/// equality operator (needed for InputIterator)
bool operator==(const iteration_proxy_internal& o) const noexcept
{
return anchor == o.anchor;
}
/// inequality operator (needed for range-based for)
bool operator!=(const iteration_proxy_internal& o) const noexcept
{
@@ -47,7 +70,7 @@ template<typename IteratorType> class iteration_proxy
}
/// return key of the iterator
std::string key() const
const std::string& key() const
{
assert(anchor.m_object != nullptr);
@@ -55,7 +78,14 @@ template<typename IteratorType> class iteration_proxy
{
// use integer array index as key
case value_t::array:
return std::to_string(array_index);
{
if (array_index != array_index_last)
{
array_index_str = std::to_string(array_index);
array_index_last = array_index;
}
return array_index_str;
}
// use key from the object
case value_t::object:
@@ -63,7 +93,7 @@ template<typename IteratorType> class iteration_proxy
// use an empty key for all primitive types
default:
return "";
return empty_str;
}
}

View File

@@ -21,10 +21,10 @@ create @ref const_reverse_iterator).
@requirement The class satisfies the following concept requirements:
-
[BidirectionalIterator](http://en.cppreference.com/w/cpp/concept/BidirectionalIterator):
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
The iterator that can be moved can be moved in both directions (i.e.
incremented and decremented).
- [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator):
- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
It is possible to write to the pointed-to element (only if @a Base is
@ref iterator).
@@ -41,11 +41,11 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
using reference = typename Base::reference;
/// create reverse iterator from iterator
json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
: base_iterator(it) {}
/// create reverse iterator from base class
json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
/// post-increment (it++)
json_reverse_iterator const operator++(int)

View File

@@ -87,7 +87,7 @@ class primitive_iterator_t
primitive_iterator_t const operator++(int) noexcept
{
auto result = *this;
m_it++;
++m_it;
return result;
}
@@ -100,7 +100,7 @@ class primitive_iterator_t
primitive_iterator_t const operator--(int) noexcept
{
auto result = *this;
m_it--;
--m_it;
return result;
}

View File

@@ -4,13 +4,15 @@
// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
// exclude unsupported compilers
#if defined(__clang__)
#if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
#error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
#endif
#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900
#error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
#if defined(__clang__)
#if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
#error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
#endif
#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
#error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
#endif
#endif
#endif
@@ -40,10 +42,12 @@
#define JSON_THROW(exception) throw exception
#define JSON_TRY try
#define JSON_CATCH(exception) catch(exception)
#define JSON_INTERNAL_CATCH(exception) catch(exception)
#else
#define JSON_THROW(exception) std::abort()
#define JSON_TRY if(true)
#define JSON_CATCH(exception) if(false)
#define JSON_INTERNAL_CATCH(exception) if(false)
#endif
// override exception macros
@@ -58,6 +62,12 @@
#if defined(JSON_CATCH_USER)
#undef JSON_CATCH
#define JSON_CATCH JSON_CATCH_USER
#undef JSON_INTERNAL_CATCH
#define JSON_INTERNAL_CATCH JSON_CATCH_USER
#endif
#if defined(JSON_INTERNAL_CATCH_USER)
#undef JSON_INTERNAL_CATCH
#define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
#endif
// manual branch prediction
@@ -92,24 +102,3 @@
basic_json<ObjectType, ArrayType, StringType, BooleanType, \
NumberIntegerType, NumberUnsignedType, NumberFloatType, \
AllocatorType, JSONSerializer>
/*!
@brief Helper to determine whether there's a key_type for T.
This helper is used to tell associative containers apart from other containers
such as sequence containers. For instance, `std::map` passes the test as it
contains a `mapped_type`, whereas `std::vector` fails the test.
@sa http://stackoverflow.com/a/7728728/266378
@since version 1.0.0, overworked in version 2.0.6
*/
#define NLOHMANN_JSON_HAS_HELPER(type) \
template<typename T> struct has_##type { \
private: \
template<typename U, typename = typename U::type> \
static int detect(U &&); \
static void detect(...); \
public: \
static constexpr bool value = \
std::is_integral<decltype(detect(std::declval<T>()))>::value; \
}

View File

@@ -9,6 +9,7 @@
#endif
// clean up
#undef JSON_INTERNAL_CATCH
#undef JSON_CATCH
#undef JSON_THROW
#undef JSON_TRY
@@ -19,4 +20,3 @@
#undef JSON_HAS_CPP_17
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
#undef NLOHMANN_BASIC_JSON_TPL
#undef NLOHMANN_JSON_HAS_HELPER

View File

@@ -1,258 +0,0 @@
#pragma once
#include <ciso646> // not
#include <cstddef> // size_t
#include <limits> // numeric_limits
#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
#include <utility> // declval
#include <nlohmann/json_fwd.hpp>
#include <nlohmann/detail/macro_scope.hpp>
namespace nlohmann
{
/*!
@brief detail namespace with internal helper functions
This namespace collects functions that should not be exposed,
implementations of some @ref basic_json methods, and meta-programming helpers.
@since version 2.1.0
*/
namespace detail
{
/////////////
// helpers //
/////////////
template<typename> struct is_basic_json : std::false_type {};
NLOHMANN_BASIC_JSON_TPL_DECLARATION
struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
// alias templates to reduce boilerplate
template<bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;
template<typename T>
using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
// implementation of C++14 index_sequence and affiliates
// source: https://stackoverflow.com/a/32223343
template<std::size_t... Ints>
struct index_sequence
{
using type = index_sequence;
using value_type = std::size_t;
static constexpr std::size_t size() noexcept
{
return sizeof...(Ints);
}
};
template<class Sequence1, class Sequence2>
struct merge_and_renumber;
template<std::size_t... I1, std::size_t... I2>
struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
: index_sequence < I1..., (sizeof...(I1) + I2)... > {};
template<std::size_t N>
struct make_index_sequence
: merge_and_renumber < typename make_index_sequence < N / 2 >::type,
typename make_index_sequence < N - N / 2 >::type > {};
template<> struct make_index_sequence<0> : index_sequence<> {};
template<> struct make_index_sequence<1> : index_sequence<0> {};
template<typename... Ts>
using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
/*
Implementation of two C++17 constructs: conjunction, negation. This is needed
to avoid evaluating all the traits in a condition
For example: not std::is_same<void, T>::value and has_value_type<T>::value
will not compile when T = void (on MSVC at least). Whereas
conjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value will
stop evaluating if negation<...>::value == false
Please note that those constructs must be used with caution, since symbols can
become very long quickly (which can slow down compilation and cause MSVC
internal compiler errors). Only use it when you have to (see example ahead).
*/
template<class...> struct conjunction : std::true_type {};
template<class B1> struct conjunction<B1> : B1 {};
template<class B1, class... Bn>
struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
template<class B> struct negation : std::integral_constant<bool, not B::value> {};
// dispatch utility (taken from ranges-v3)
template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
template<> struct priority_tag<0> {};
////////////////////////
// has_/is_ functions //
////////////////////////
// source: https://stackoverflow.com/a/37193089/4116453
template <typename T, typename = void>
struct is_complete_type : std::false_type {};
template <typename T>
struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
NLOHMANN_JSON_HAS_HELPER(mapped_type);
NLOHMANN_JSON_HAS_HELPER(key_type);
NLOHMANN_JSON_HAS_HELPER(value_type);
NLOHMANN_JSON_HAS_HELPER(iterator);
template<bool B, class RealType, class CompatibleObjectType>
struct is_compatible_object_type_impl : std::false_type {};
template<class RealType, class CompatibleObjectType>
struct is_compatible_object_type_impl<true, RealType, CompatibleObjectType>
{
static constexpr auto value =
std::is_constructible<typename RealType::key_type, typename CompatibleObjectType::key_type>::value and
std::is_constructible<typename RealType::mapped_type, typename CompatibleObjectType::mapped_type>::value;
};
template<class BasicJsonType, class CompatibleObjectType>
struct is_compatible_object_type
{
static auto constexpr value = is_compatible_object_type_impl <
conjunction<negation<std::is_same<void, CompatibleObjectType>>,
has_mapped_type<CompatibleObjectType>,
has_key_type<CompatibleObjectType>>::value,
typename BasicJsonType::object_t, CompatibleObjectType >::value;
};
template<typename BasicJsonType, typename T>
struct is_basic_json_nested_type
{
static auto constexpr value = std::is_same<T, typename BasicJsonType::iterator>::value or
std::is_same<T, typename BasicJsonType::const_iterator>::value or
std::is_same<T, typename BasicJsonType::reverse_iterator>::value or
std::is_same<T, typename BasicJsonType::const_reverse_iterator>::value;
};
template<class BasicJsonType, class CompatibleArrayType>
struct is_compatible_array_type
{
static auto constexpr value =
conjunction<negation<std::is_same<void, CompatibleArrayType>>,
negation<is_compatible_object_type<
BasicJsonType, CompatibleArrayType>>,
negation<std::is_constructible<typename BasicJsonType::string_t,
CompatibleArrayType>>,
negation<is_basic_json_nested_type<BasicJsonType, CompatibleArrayType>>,
has_value_type<CompatibleArrayType>,
has_iterator<CompatibleArrayType>>::value;
};
template<bool, typename, typename>
struct is_compatible_integer_type_impl : std::false_type {};
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIntegerType>
{
// is there an assert somewhere on overflows?
using RealLimits = std::numeric_limits<RealIntegerType>;
using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
static constexpr auto value =
std::is_constructible<RealIntegerType, CompatibleNumberIntegerType>::value and
CompatibleLimits::is_integer and
RealLimits::is_signed == CompatibleLimits::is_signed;
};
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
struct is_compatible_integer_type
{
static constexpr auto value =
is_compatible_integer_type_impl <
std::is_integral<CompatibleNumberIntegerType>::value and
not std::is_same<bool, CompatibleNumberIntegerType>::value,
RealIntegerType, CompatibleNumberIntegerType > ::value;
};
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
template<typename BasicJsonType, typename T>
struct has_from_json
{
private:
// also check the return type of from_json
template<typename U, typename = enable_if_t<std::is_same<void, decltype(uncvref_t<U>::from_json(
std::declval<BasicJsonType>(), std::declval<T&>()))>::value>>
static int detect(U&&);
static void detect(...);
public:
static constexpr bool value = std::is_integral<decltype(
detect(std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
};
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
// this overload is used for non-default-constructible user-defined-types
template<typename BasicJsonType, typename T>
struct has_non_default_from_json
{
private:
template <
typename U,
typename = enable_if_t<std::is_same<
T, decltype(uncvref_t<U>::from_json(std::declval<BasicJsonType>()))>::value >>
static int detect(U&&);
static void detect(...);
public:
static constexpr bool value = std::is_integral<decltype(detect(
std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
};
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
template<typename BasicJsonType, typename T>
struct has_to_json
{
private:
template<typename U, typename = decltype(uncvref_t<U>::to_json(
std::declval<BasicJsonType&>(), std::declval<T>()))>
static int detect(U&&);
static void detect(...);
public:
static constexpr bool value = std::is_integral<decltype(detect(
std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
};
template <typename BasicJsonType, typename CompatibleCompleteType>
struct is_compatible_complete_type
{
static constexpr bool value =
not std::is_base_of<std::istream, CompatibleCompleteType>::value and
not is_basic_json<CompatibleCompleteType>::value and
not is_basic_json_nested_type<BasicJsonType, CompatibleCompleteType>::value and
has_to_json<BasicJsonType, CompatibleCompleteType>::value;
};
template <typename BasicJsonType, typename CompatibleType>
struct is_compatible_type
: conjunction<is_complete_type<CompatibleType>,
is_compatible_complete_type<BasicJsonType, CompatibleType>>
{
};
// taken from ranges-v3
template<typename T>
struct static_const
{
static constexpr T value{};
};
template<typename T>
constexpr T static_const<T>::value;
}
}

View File

@@ -0,0 +1,63 @@
#pragma once
#include <ciso646> // not
#include <cstddef> // size_t
#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
namespace nlohmann
{
namespace detail
{
// alias templates to reduce boilerplate
template<bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;
template<typename T>
using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
// implementation of C++14 index_sequence and affiliates
// source: https://stackoverflow.com/a/32223343
template<std::size_t... Ints>
struct index_sequence
{
using type = index_sequence;
using value_type = std::size_t;
static constexpr std::size_t size() noexcept
{
return sizeof...(Ints);
}
};
template<class Sequence1, class Sequence2>
struct merge_and_renumber;
template<std::size_t... I1, std::size_t... I2>
struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
: index_sequence < I1..., (sizeof...(I1) + I2)... > {};
template<std::size_t N>
struct make_index_sequence
: merge_and_renumber < typename make_index_sequence < N / 2 >::type,
typename make_index_sequence < N - N / 2 >::type > {};
template<> struct make_index_sequence<0> : index_sequence<> {};
template<> struct make_index_sequence<1> : index_sequence<0> {};
template<typename... Ts>
using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
// dispatch utility (taken from ranges-v3)
template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
template<> struct priority_tag<0> {};
// taken from ranges-v3
template<typename T>
struct static_const
{
static constexpr T value{};
};
template<typename T>
constexpr T static_const<T>::value;
}
}

View File

@@ -0,0 +1,56 @@
#pragma once
#include <type_traits>
#include <nlohmann/detail/meta/void_t.hpp>
// http://en.cppreference.com/w/cpp/experimental/is_detected
namespace nlohmann
{
namespace detail
{
struct nonesuch
{
nonesuch() = delete;
~nonesuch() = delete;
nonesuch(nonesuch const&) = delete;
void operator=(nonesuch const&) = delete;
};
template <class Default,
class AlwaysVoid,
template <class...> class Op,
class... Args>
struct detector
{
using value_t = std::false_type;
using type = Default;
};
template <class Default, template <class...> class Op, class... Args>
struct detector<Default, void_t<Op<Args...>>, Op, Args...>
{
using value_t = std::true_type;
using type = Op<Args...>;
};
template <template <class...> class Op, class... Args>
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
template <template <class...> class Op, class... Args>
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
template <class Default, template <class...> class Op, class... Args>
using detected_or = detector<Default, void, Op, Args...>;
template <class Default, template <class...> class Op, class... Args>
using detected_or_t = typename detected_or<Default, Op, Args...>::type;
template <class Expected, template <class...> class Op, class... Args>
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
template <class To, template <class...> class Op, class... Args>
using is_detected_convertible =
std::is_convertible<detected_t<Op, Args...>, To>;
}
}

View File

@@ -0,0 +1,141 @@
#pragma once
#include <cstdint> // size_t
#include <utility> // declval
#include <nlohmann/detail/meta/detected.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
namespace nlohmann
{
namespace detail
{
template <typename T>
using null_function_t = decltype(std::declval<T&>().null());
template <typename T>
using boolean_function_t =
decltype(std::declval<T&>().boolean(std::declval<bool>()));
template <typename T, typename Integer>
using number_integer_function_t =
decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
template <typename T, typename Unsigned>
using number_unsigned_function_t =
decltype(std::declval<T &>().number_unsigned(std::declval<Unsigned>()));
template <typename T, typename Float, typename String>
using number_float_function_t = decltype(std::declval<T &>().number_float(
std::declval<Float>(), std::declval<const String &>()));
template <typename T, typename String>
using string_function_t =
decltype(std::declval<T &>().string(std::declval<String &>()));
template <typename T>
using start_object_function_t =
decltype(std::declval<T &>().start_object(std::declval<std::size_t>()));
template <typename T, typename String>
using key_function_t =
decltype(std::declval<T &>().key(std::declval<String &>()));
template <typename T>
using end_object_function_t = decltype(std::declval<T &>().end_object());
template <typename T>
using start_array_function_t =
decltype(std::declval<T &>().start_array(std::declval<std::size_t>()));
template <typename T>
using end_array_function_t = decltype(std::declval<T &>().end_array());
template <typename T, typename Exception>
using parse_error_function_t = decltype(std::declval<T &>().parse_error(
std::declval<std::size_t>(), std::declval<const std::string &>(),
std::declval<const Exception &>()));
template <typename SAX, typename BasicJsonType>
struct is_sax
{
private:
static_assert(is_basic_json<BasicJsonType>::value,
"BasicJsonType must be of type basic_json<...>");
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
using exception_t = typename BasicJsonType::exception;
public:
static constexpr bool value =
is_detected_exact<bool, null_function_t, SAX>::value &&
is_detected_exact<bool, boolean_function_t, SAX>::value &&
is_detected_exact<bool, number_integer_function_t, SAX,
number_integer_t>::value &&
is_detected_exact<bool, number_unsigned_function_t, SAX,
number_unsigned_t>::value &&
is_detected_exact<bool, number_float_function_t, SAX, number_float_t,
string_t>::value &&
is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
is_detected_exact<bool, start_object_function_t, SAX>::value &&
is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
is_detected_exact<bool, end_object_function_t, SAX>::value &&
is_detected_exact<bool, start_array_function_t, SAX>::value &&
is_detected_exact<bool, end_array_function_t, SAX>::value &&
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
};
template <typename SAX, typename BasicJsonType>
struct is_sax_static_asserts
{
private:
static_assert(is_basic_json<BasicJsonType>::value,
"BasicJsonType must be of type basic_json<...>");
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
using exception_t = typename BasicJsonType::exception;
public:
static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
"Missing/invalid function: bool null()");
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
"Missing/invalid function: bool boolean(bool)");
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
"Missing/invalid function: bool boolean(bool)");
static_assert(
is_detected_exact<bool, number_integer_function_t, SAX,
number_integer_t>::value,
"Missing/invalid function: bool number_integer(number_integer_t)");
static_assert(
is_detected_exact<bool, number_unsigned_function_t, SAX,
number_unsigned_t>::value,
"Missing/invalid function: bool number_unsigned(number_unsigned_t)");
static_assert(is_detected_exact<bool, number_float_function_t, SAX,
number_float_t, string_t>::value,
"Missing/invalid function: bool number_float(number_float_t, const string_t&)");
static_assert(
is_detected_exact<bool, string_function_t, SAX, string_t>::value,
"Missing/invalid function: bool string(string_t&)");
static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
"Missing/invalid function: bool start_object(std::size_t)");
static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
"Missing/invalid function: bool key(string_t&)");
static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
"Missing/invalid function: bool end_object()");
static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
"Missing/invalid function: bool start_array(std::size_t)");
static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
"Missing/invalid function: bool end_array()");
static_assert(
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
"Missing/invalid function: bool parse_error(std::size_t, const "
"std::string&, const exception&)");
};
}
}

View File

@@ -0,0 +1,251 @@
#pragma once
#include <ciso646> // not
#include <limits> // numeric_limits
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
#include <utility> // declval
#include <nlohmann/json_fwd.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/detected.hpp>
#include <nlohmann/detail/macro_scope.hpp>
namespace nlohmann
{
/*!
@brief detail namespace with internal helper functions
This namespace collects functions that should not be exposed,
implementations of some @ref basic_json methods, and meta-programming helpers.
@since version 2.1.0
*/
namespace detail
{
/////////////
// helpers //
/////////////
template<typename> struct is_basic_json : std::false_type {};
NLOHMANN_BASIC_JSON_TPL_DECLARATION
struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
//////////////////////////
// aliases for detected //
//////////////////////////
template <typename T>
using mapped_type_t = typename T::mapped_type;
template <typename T>
using key_type_t = typename T::key_type;
template <typename T>
using value_type_t = typename T::value_type;
template <typename T>
using difference_type_t = typename T::difference_type;
template <typename T>
using pointer_t = typename T::pointer;
template <typename T>
using reference_t = typename T::reference;
template <typename T>
using iterator_category_t = typename T::iterator_category;
template <typename T>
using iterator_t = typename T::iterator;
template <typename T, typename... Args>
using to_json_function = decltype(T::to_json(std::declval<Args>()...));
template <typename T, typename... Args>
using from_json_function = decltype(T::from_json(std::declval<Args>()...));
template <typename T, typename U>
using get_template_function = decltype(std::declval<T>().template get<U>());
///////////////////
// is_ functions //
///////////////////
template <typename T, typename = void>
struct is_iterator_traits : std::false_type {};
template <typename T>
struct is_iterator_traits<std::iterator_traits<T>>
{
private:
using traits = std::iterator_traits<T>;
public:
static constexpr auto value =
is_detected<value_type_t, traits>::value &&
is_detected<difference_type_t, traits>::value &&
is_detected<pointer_t, traits>::value &&
is_detected<iterator_category_t, traits>::value &&
is_detected<reference_t, traits>::value;
};
// source: https://stackoverflow.com/a/37193089/4116453
template <typename T, typename = void>
struct is_complete_type : std::false_type {};
template <typename T>
struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
template <typename BasicJsonType, typename CompatibleObjectType,
typename = void>
struct is_compatible_object_type_impl : std::false_type {};
template <typename BasicJsonType, typename CompatibleObjectType>
struct is_compatible_object_type_impl <
BasicJsonType, CompatibleObjectType,
enable_if_t<is_detected<mapped_type_t, CompatibleObjectType>::value and
is_detected<key_type_t, CompatibleObjectType>::value >>
{
using object_t = typename BasicJsonType::object_t;
// macOS's is_constructible does not play well with nonesuch...
static constexpr bool value =
std::is_constructible<typename object_t::key_type,
typename CompatibleObjectType::key_type>::value and
std::is_constructible<typename object_t::mapped_type,
typename CompatibleObjectType::mapped_type>::value;
};
template <typename BasicJsonType, typename CompatibleObjectType>
struct is_compatible_object_type
: is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
template <typename BasicJsonType, typename CompatibleStringType,
typename = void>
struct is_compatible_string_type_impl : std::false_type {};
template <typename BasicJsonType, typename CompatibleStringType>
struct is_compatible_string_type_impl <
BasicJsonType, CompatibleStringType,
enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
value_type_t, CompatibleStringType>::value >>
{
static constexpr auto value =
std::is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
};
template <typename BasicJsonType, typename CompatibleStringType>
struct is_compatible_string_type
: is_compatible_string_type_impl<BasicJsonType, CompatibleStringType> {};
template <typename BasicJsonType, typename CompatibleArrayType, typename = void>
struct is_compatible_array_type_impl : std::false_type {};
template <typename BasicJsonType, typename CompatibleArrayType>
struct is_compatible_array_type_impl <
BasicJsonType, CompatibleArrayType,
enable_if_t<is_detected<value_type_t, CompatibleArrayType>::value and
is_detected<iterator_t, CompatibleArrayType>::value >>
{
// This is needed because json_reverse_iterator has a ::iterator type...
// Therefore it is detected as a CompatibleArrayType.
// The real fix would be to have an Iterable concept.
static constexpr bool value = not is_iterator_traits<std::iterator_traits<CompatibleArrayType>>::value;
};
template <typename BasicJsonType, typename CompatibleArrayType>
struct is_compatible_array_type
: is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
template <typename RealIntegerType, typename CompatibleNumberIntegerType,
typename = void>
struct is_compatible_integer_type_impl : std::false_type {};
template <typename RealIntegerType, typename CompatibleNumberIntegerType>
struct is_compatible_integer_type_impl <
RealIntegerType, CompatibleNumberIntegerType,
enable_if_t<std::is_integral<RealIntegerType>::value and
std::is_integral<CompatibleNumberIntegerType>::value and
not std::is_same<bool, CompatibleNumberIntegerType>::value >>
{
// is there an assert somewhere on overflows?
using RealLimits = std::numeric_limits<RealIntegerType>;
using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
static constexpr auto value =
std::is_constructible<RealIntegerType,
CompatibleNumberIntegerType>::value and
CompatibleLimits::is_integer and
RealLimits::is_signed == CompatibleLimits::is_signed;
};
template <typename RealIntegerType, typename CompatibleNumberIntegerType>
struct is_compatible_integer_type
: is_compatible_integer_type_impl<RealIntegerType,
CompatibleNumberIntegerType> {};
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
template <typename BasicJsonType, typename T, typename = void>
struct has_from_json : std::false_type {};
template <typename BasicJsonType, typename T>
struct has_from_json<BasicJsonType, T,
enable_if_t<not is_basic_json<T>::value>>
{
using serializer = typename BasicJsonType::template json_serializer<T, void>;
static constexpr bool value =
is_detected_exact<void, from_json_function, serializer,
const BasicJsonType&, T&>::value;
};
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
// this overload is used for non-default-constructible user-defined-types
template <typename BasicJsonType, typename T, typename = void>
struct has_non_default_from_json : std::false_type {};
template<typename BasicJsonType, typename T>
struct has_non_default_from_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
{
using serializer = typename BasicJsonType::template json_serializer<T, void>;
static constexpr bool value =
is_detected_exact<T, from_json_function, serializer,
const BasicJsonType&>::value;
};
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
template <typename BasicJsonType, typename T, typename = void>
struct has_to_json : std::false_type {};
template <typename BasicJsonType, typename T>
struct has_to_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
{
using serializer = typename BasicJsonType::template json_serializer<T, void>;
static constexpr bool value =
is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
T>::value;
};
template <typename BasicJsonType, typename CompatibleType, typename = void>
struct is_compatible_type_impl: std::false_type {};
template <typename BasicJsonType, typename CompatibleType>
struct is_compatible_type_impl <
BasicJsonType, CompatibleType,
enable_if_t<is_complete_type<CompatibleType>::value >>
{
static constexpr bool value =
has_to_json<BasicJsonType, CompatibleType>::value;
};
template <typename BasicJsonType, typename CompatibleType>
struct is_compatible_type
: is_compatible_type_impl<BasicJsonType, CompatibleType> {};
}
}

View File

@@ -0,0 +1,13 @@
#pragma once
namespace nlohmann
{
namespace detail
{
template <typename ...Ts> struct make_void
{
using type = void;
};
template <typename ...Ts> using void_t = typename make_void<Ts...>::type;
}
}

View File

@@ -149,9 +149,9 @@ class binary_writer
break;
}
case value_t::number_float: // Double-Precision Float
case value_t::number_float:
{
oa->write_character(static_cast<CharType>(0xFB));
oa->write_character(get_cbor_float_prefix(j.m_value.number_float));
write_number(j.m_value.number_float);
break;
}
@@ -409,9 +409,9 @@ class binary_writer
break;
}
case value_t::number_float: // float 64
case value_t::number_float:
{
oa->write_character(static_cast<CharType>(0xCB));
oa->write_character(get_msgpack_float_prefix(j.m_value.number_float));
write_number(j.m_value.number_float);
break;
}
@@ -588,7 +588,7 @@ class binary_writer
if (use_type and not j.m_value.array->empty())
{
assert(use_count);
const char first_prefix = ubjson_prefix(j.front());
const CharType first_prefix = ubjson_prefix(j.front());
const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
[this, first_prefix](const BasicJsonType & v)
{
@@ -599,7 +599,7 @@ class binary_writer
{
prefix_required = false;
oa->write_character(static_cast<CharType>('$'));
oa->write_character(static_cast<CharType>(first_prefix));
oa->write_character(first_prefix);
}
}
@@ -633,7 +633,7 @@ class binary_writer
if (use_type and not j.m_value.object->empty())
{
assert(use_count);
const char first_prefix = ubjson_prefix(j.front());
const CharType first_prefix = ubjson_prefix(j.front());
const bool same_prefix = std::all_of(j.begin(), j.end(),
[this, first_prefix](const BasicJsonType & v)
{
@@ -644,7 +644,7 @@ class binary_writer
{
prefix_required = false;
oa->write_character(static_cast<CharType>('$'));
oa->write_character(static_cast<CharType>(first_prefix));
oa->write_character(first_prefix);
}
}
@@ -712,7 +712,7 @@ class binary_writer
{
if (add_prefix)
{
oa->write_character(static_cast<CharType>('D')); // float64
oa->write_character(get_ubjson_float_prefix(n));
}
write_number(n);
}
@@ -833,7 +833,7 @@ class binary_writer
write_number_with_ubjson_prefix. Therefore, we return 'L' for any
value that does not fit the previous limits.
*/
char ubjson_prefix(const BasicJsonType& j) const noexcept
CharType ubjson_prefix(const BasicJsonType& j) const noexcept
{
switch (j.type())
{
@@ -892,7 +892,7 @@ class binary_writer
}
case value_t::number_float:
return 'D';
return get_ubjson_float_prefix(j.m_value.number_float);
case value_t::string:
return 'S';
@@ -908,6 +908,36 @@ class binary_writer
}
}
static constexpr CharType get_cbor_float_prefix(float)
{
return static_cast<CharType>(0xFA); // Single-Precision Float
}
static constexpr CharType get_cbor_float_prefix(double)
{
return static_cast<CharType>(0xFB); // Double-Precision Float
}
static constexpr CharType get_msgpack_float_prefix(float)
{
return static_cast<CharType>(0xCA); // float 32
}
static constexpr CharType get_msgpack_float_prefix(double)
{
return static_cast<CharType>(0xCB); // float 64
}
static constexpr CharType get_ubjson_float_prefix(float)
{
return 'd'; // float 32
}
static constexpr CharType get_ubjson_float_prefix(double)
{
return 'D'; // float 64
}
private:
/// whether we can assume little endianess
const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess();

View File

@@ -9,17 +9,14 @@
#include <cstddef> // size_t, ptrdiff_t
#include <cstdint> // uint8_t
#include <cstdio> // snprintf
#include <iomanip> // setfill
#include <iterator> // next
#include <limits> // numeric_limits
#include <string> // string
#include <sstream> // stringstream
#include <type_traits> // is_same
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/conversions/to_chars.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/output/output_adapters.hpp>
#include <nlohmann/detail/value_t.hpp>
@@ -389,9 +386,9 @@ class serializer
case UTF8_REJECT: // decode found invalid UTF-8 byte
{
std::stringstream ss;
ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << static_cast<int>(byte);
JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + ss.str()));
std::string sn(3, '\0');
snprintf(&sn[0], sn.size(), "%.2X", byte);
JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn));
}
default: // decode found yet incomplete multi-byte code point
@@ -417,9 +414,9 @@ class serializer
else
{
// we finish reading, but do not accept: string was incomplete
std::stringstream ss;
ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << static_cast<int>(static_cast<uint8_t>(s.back()));
JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + ss.str()));
std::string sn(3, '\0');
snprintf(&sn[0], sn.size(), "%.2X", static_cast<uint8_t>(s.back()));
JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn));
}
}
@@ -445,7 +442,7 @@ class serializer
return;
}
const bool is_negative = (x <= 0) and (x != 0); // see issue #755
const bool is_negative = not (x >= 0); // see issue #755
std::size_t i = 0;
while (x != 0)

File diff suppressed because it is too large Load Diff

View File

@@ -18,10 +18,10 @@ namespace nlohmann
@brief default JSONSerializer template argument
This serializer ignores the template arguments and uses ADL
([argument-dependent lookup](http://en.cppreference.com/w/cpp/language/adl))
([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
for serialization.
*/
template<typename = void, typename = void>
template<typename T = void, typename SFINAE = void>
struct adl_serializer;
template<template<typename U, typename V, typename... Args> class ObjectType =

View File

@@ -1,7 +1,13 @@
project('nlohmann_json', 'cpp')
nlohmann_json_inc = include_directories('single_include/nlohmann')
project('nlohmann_json',
'cpp',
version : '3.3.0',
license : 'MIT',
)
nlohmann_json_dep = declare_dependency(
include_directories : nlohmann_json_inc
include_directories: include_directories('single_include')
)
nlohmann_json_multiple_headers = declare_dependency(
include_directories: include_directories('include')
)

File diff suppressed because it is too large Load Diff

View File

@@ -6,15 +6,14 @@ option(JSON_Coverage "Build test suite with coverage information" OFF)
if(JSON_Sanitizer)
message(STATUS "Building test suite with Clang sanitizer")
if(NOT MSVC)
set(CMAKE_CXX_FLAGS "-std=c++11 -g -O2 -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer")
set(CMAKE_CXX_FLAGS "-g -O2 -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer")
endif()
endif()
if(JSON_Valgrind)
find_program(CMAKE_MEMORYCHECK_COMMAND valgrind)
message(STATUS "Executing test suite with Valgrind (${CMAKE_MEMORYCHECK_COMMAND})")
set(MEMORYCHECK_COMMAND_OPTIONS "--error-exitcode=1 --leak-check=full")
set(memcheck_command "${CMAKE_MEMORYCHECK_COMMAND} ${CMAKE_MEMORYCHECK_COMMAND_OPTIONS}")
set(memcheck_command "${CMAKE_MEMORYCHECK_COMMAND} ${CMAKE_MEMORYCHECK_COMMAND_OPTIONS} --error-exitcode=1 --leak-check=full")
separate_arguments(memcheck_command)
endif()
@@ -62,11 +61,10 @@ add_library(catch_main OBJECT
"src/unit.cpp"
)
set_target_properties(catch_main PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED ON
COMPILE_DEFINITIONS "$<$<CXX_COMPILER_ID:MSVC>:_SCL_SECURE_NO_WARNINGS>"
COMPILE_OPTIONS "$<$<CXX_COMPILER_ID:MSVC>:/EHsc;$<$<CONFIG:Release>:/Od>>"
)
target_compile_features(catch_main PUBLIC cxx_std_11)
target_include_directories(catch_main PRIVATE "thirdparty/catch")
# https://stackoverflow.com/questions/2368811/how-to-set-warning-level-in-cmake
@@ -83,6 +81,9 @@ if(MSVC)
# Disable warning C4566: character represented by universal-character-name '\uFF01' cannot be represented in the current code page (1252)
# Disable warning C4996: 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::operator <<': was declared deprecated
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4389 /wd4309 /wd4566 /wd4996")
# https://github.com/nlohmann/json/issues/1114
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /bigobj")
endif()
#############################################################################
@@ -95,23 +96,21 @@ foreach(file ${files})
string(REGEX REPLACE "unit-([^$]+)" "test-\\1" testcase ${file_basename})
add_executable(${testcase} $<TARGET_OBJECTS:catch_main> ${file})
set_target_properties(${testcase} PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED ON
COMPILE_DEFINITIONS "$<$<CXX_COMPILER_ID:MSVC>:_SCL_SECURE_NO_WARNINGS>"
COMPILE_OPTIONS "$<$<CXX_COMPILER_ID:MSVC>:/EHsc;$<$<CONFIG:Release>:/Od>>"
target_compile_definitions(${testcase} PRIVATE
CATCH_CONFIG_FAST_COMPILE
$<$<CXX_COMPILER_ID:MSVC>:_SCL_SECURE_NO_WARNINGS>
)
target_compile_options(${testcase} PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/EHsc;$<$<CONFIG:Release>:/Od>>
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wno-deprecated;-Wno-float-equal>
$<$<CXX_COMPILER_ID:GNU>:-Wno-deprecated-declarations>
)
target_include_directories(${testcase} PRIVATE
thirdparty/catch
thirdparty/fifo_map
)
target_compile_definitions(${testcase} PRIVATE CATCH_CONFIG_FAST_COMPILE)
target_include_directories(${testcase} PRIVATE "thirdparty/catch")
target_include_directories(${testcase} PRIVATE "thirdparty/fifo_map")
target_include_directories(${testcase} PRIVATE ${NLOHMANN_JSON_INCLUDE_BUILD_DIR})
target_link_libraries(${testcase} ${NLOHMANN_JSON_TARGET_NAME})
if(NOT MSVC)
set_target_properties(${testcase} PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated -Wno-float-equal")
endif()
add_test(NAME "${testcase}_default"
COMMAND ${testcase} ${CATCH_TEST_FILTER}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
@@ -131,5 +130,11 @@ foreach(file ${files})
)
set_tests_properties("${testcase}_valgrind" PROPERTIES LABELS "valgrind")
endif()
endforeach()
#############################################################################
# Test the generated build configs
#############################################################################
add_subdirectory(cmake_import)
add_subdirectory(cmake_import_minver)
add_subdirectory(cmake_add_subdirectory)

View File

@@ -42,7 +42,8 @@ SOURCES = src/unit.cpp \
src/unit-serialization.cpp \
src/unit-testsuites.cpp \
src/unit-ubjson.cpp \
src/unit-unicode.cpp
src/unit-unicode.cpp \
src/unit-wstring.cpp
OBJECTS = $(SOURCES:.cpp=.o)

View File

@@ -0,0 +1,15 @@
add_test(NAME cmake_add_subdirectory_configure
COMMAND ${CMAKE_COMMAND}
-G "${CMAKE_GENERATOR}"
-Dnlohmann_json_source=${PROJECT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/project
)
add_test(NAME cmake_add_subdirectory_build
COMMAND ${CMAKE_COMMAND} --build .
)
set_tests_properties(cmake_add_subdirectory_configure PROPERTIES
FIXTURES_SETUP cmake_add_subdirectory
)
set_tests_properties(cmake_add_subdirectory_build PROPERTIES
FIXTURES_REQUIRED cmake_add_subdirectory
)

Some files were not shown because too many files have changed in this diff Show More