diff --git a/.circleci/config.yml b/.circleci/config.yml index 0d2edbf6..f2ec9306 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -19,6 +19,9 @@ jobs: - run: name: Create build files command: 'mkdir build ; cd build ; cmake ..' + - run: + name: Versions + command: 'g++ --version ; uname -a' - run: name: Compile command: 'cmake --build build' diff --git a/.clang-tidy b/.clang-tidy index 0a04d286..feee8194 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -4,14 +4,17 @@ Checks: '-*, clang-analyzer-*, google-*, -google-runtime-references, + -google-explicit-constructor, hicpp-*, -hicpp-no-array-decay, -hicpp-uppercase-literal-suffix, + -hicpp-explicit-conversions, misc-*, -misc-non-private-member-variables-in-classes, llvm-*, -llvm-header-guard, modernize-*, + -modernize-use-trailing-return-type, performance-*, portability-*, readability-*, diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..5d9d51d6 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,6 @@ +# JSON for Modern C++ has been originally written by Niels Lohmann. +# Since 2013 over 140 contributors have helped to improve the library. +# This CODEOWNERS file is only to make sure that @nlohmann is requsted +# for a code review in case of a pull request. + +* @nlohmann diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 00000000..4d010ebd --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,5 @@ +# Security Policy + +## Reporting a Vulnerability + +Usually, all issues are tracked publicly on [GitHub](https://github.com/nlohmann/json/issues). If you want to make a private report (e.g., for a vulnerability or to attach an example that is not meant to be published), please send an email to . You can use [this key](https://keybase.io/nlohmann/pgp_keys.asc?fingerprint=797167ae41c0a6d9232e48457f3cea63ae251b69) for encryption. diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml new file mode 100644 index 00000000..c6f8afb3 --- /dev/null +++ b/.github/workflows/ccpp.yml @@ -0,0 +1,19 @@ +name: C/C++ CI + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: prepare + run: mkdir build + - name: cmake + run: cd build ; cmake .. + - name: build + run: make -C build + - name: test + run: cd build ; ctest -j 10 diff --git a/.travis.yml b/.travis.yml index 484c9350..cccd1066 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,12 +43,15 @@ matrix: - os: linux compiler: clang env: - - COMPILER=clang++-5.0 + - COMPILER=clang++-7 - CMAKE_OPTIONS=-DJSON_Sanitizer=ON + - UBSAN_OPTIONS=print_stacktrace=1,suppressions=$(pwd)/test/src/UBSAN.supp 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-7'] + packages: ['g++-6', 'clang-7', 'ninja-build'] + before_script: + - export PATH=$PATH:/usr/lib/llvm-7/bin # cppcheck - os: linux @@ -152,11 +155,14 @@ matrix: - os: osx osx_image: xcode10.1 + - os: osx + osx_image: xcode10.2 + # Linux / GCC - os: linux compiler: gcc - env: compiler=g++-4.8 + env: COMPILER=g++-4.8 addons: apt: sources: ['ubuntu-toolchain-r-test'] @@ -164,7 +170,7 @@ matrix: - os: linux compiler: gcc - env: compiler=g++-4.9 + env: COMPILER=g++-4.9 addons: apt: sources: ['ubuntu-toolchain-r-test'] @@ -204,13 +210,21 @@ matrix: - os: linux compiler: gcc - env: - - COMPILER=g++-8 - - CXXFLAGS=-std=c++17 + env: COMPILER=g++-9 addons: apt: sources: ['ubuntu-toolchain-r-test'] - packages: ['g++-8', 'ninja-build'] + packages: ['g++-9', 'ninja-build'] + + - os: linux + compiler: gcc + env: + - COMPILER=g++-9 + - CXXFLAGS=-std=c++2a + addons: + apt: + sources: ['ubuntu-toolchain-r-test'] + packages: ['g++-9', 'ninja-build'] # Linux / Clang @@ -322,7 +336,7 @@ script: # compile and execute unit tests - mkdir -p build && cd build - cmake .. ${CMAKE_OPTIONS} -DJSON_MultipleHeaders=${MULTIPLE_HEADERS} -GNinja && cmake --build . --config Release - - ctest -C Release -V -j + - ctest -C Release --timeout 2700 -V -j - cd .. # check if homebrew works (only checks develop branch) diff --git a/CMakeLists.txt b/CMakeLists.txt index f717ff46..d4ed1e89 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.1) ## PROJECT ## name and version ## -project(nlohmann_json VERSION 3.7.0 LANGUAGES CXX) +project(nlohmann_json VERSION 3.7.1 LANGUAGES CXX) ## ## INCLUDE diff --git a/ChangeLog.md b/ChangeLog.md index dffc858d..dea79cae 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,6 +1,139 @@ # Change Log All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [v3.7.1](https://github.com/nlohmann/json/releases/tag/v3.7.1) (2019-11-06) +[Full Changelog](https://github.com/nlohmann/json/compare/v3.7.0...v3.7.1) + +- std::is\_constructible is always true with tuple [\#1825](https://github.com/nlohmann/json/issues/1825) +- Can't compile from\_json\(std::valarray\\). [\#1824](https://github.com/nlohmann/json/issues/1824) +- json class should have a get\_or member function [\#1823](https://github.com/nlohmann/json/issues/1823) +- NLOHMANN\_JSON\_SERIALIZE\_ENUM macro capture's json objects by value [\#1822](https://github.com/nlohmann/json/issues/1822) +- Parse fails when number literals start with zero [\#1820](https://github.com/nlohmann/json/issues/1820) +- Parsing string into json doesn't preserve the order correctly. [\#1817](https://github.com/nlohmann/json/issues/1817) +- Weird behaviour of `contains` with `json\_pointer` [\#1815](https://github.com/nlohmann/json/issues/1815) +- strange behaviour with json\_pointer and .contains\(\) [\#1811](https://github.com/nlohmann/json/issues/1811) +- Can \#1695 be re-opened? [\#1808](https://github.com/nlohmann/json/issues/1808) +- Merge two json objects [\#1807](https://github.com/nlohmann/json/issues/1807) +- std::is\_constructible\\> when to\_json not defined [\#1805](https://github.com/nlohmann/json/issues/1805) +- Private data on parsing [\#1802](https://github.com/nlohmann/json/issues/1802) +- Capturing Line and Position when querying [\#1800](https://github.com/nlohmann/json/issues/1800) +- json error on parsing DBL\_MAX from string [\#1796](https://github.com/nlohmann/json/issues/1796) +- De/Serialisation of vector of tupple object with nested obect need Help please [\#1794](https://github.com/nlohmann/json/issues/1794) +- Output json is corrupted [\#1793](https://github.com/nlohmann/json/issues/1793) +- variable name byte sometimes used as a \#define [\#1792](https://github.com/nlohmann/json/issues/1792) +- Can't read json file [\#1791](https://github.com/nlohmann/json/issues/1791) +- Problems with special German letters [\#1789](https://github.com/nlohmann/json/issues/1789) +- Support for trailing commas [\#1787](https://github.com/nlohmann/json/issues/1787) +- json\_pointer construction bug [\#1786](https://github.com/nlohmann/json/issues/1786) +- Visual Studio 2017 warning [\#1784](https://github.com/nlohmann/json/issues/1784) +- ciso646 header become obsolete [\#1782](https://github.com/nlohmann/json/issues/1782) +- Migrate LGTM.com installation from OAuth to GitHub App [\#1781](https://github.com/nlohmann/json/issues/1781) +- JSON comparison, contains and operator& [\#1778](https://github.com/nlohmann/json/issues/1778) +- pass a json object to a class contructor adds an array around the object [\#1776](https://github.com/nlohmann/json/issues/1776) +- 'Float' number\_float\_function\_t template parameter name conflicts with C '\#define Float float' [\#1775](https://github.com/nlohmann/json/issues/1775) +- A weird building problem :-\( [\#1774](https://github.com/nlohmann/json/issues/1774) +- What is this json\_ref? [\#1772](https://github.com/nlohmann/json/issues/1772) +- Interoperability with other languages [\#1770](https://github.com/nlohmann/json/issues/1770) +- Json dump [\#1768](https://github.com/nlohmann/json/issues/1768) +- json\_pointer\<\>::back\(\) should be const [\#1764](https://github.com/nlohmann/json/issues/1764) +- How to get value from array [\#1762](https://github.com/nlohmann/json/issues/1762) +- Merge two jsons [\#1757](https://github.com/nlohmann/json/issues/1757) +- Unable to locate nlohmann\_jsonConfig.cmake [\#1755](https://github.com/nlohmann/json/issues/1755) +- json.hpp won;t compile VS2019 CLR/CLI app but does in console app [\#1754](https://github.com/nlohmann/json/issues/1754) +- \[Nested Json Objects\] Segmentation fault [\#1753](https://github.com/nlohmann/json/issues/1753) +- remove/replace assert with exceptions [\#1752](https://github.com/nlohmann/json/issues/1752) +- Add array support for update\(\) function [\#1751](https://github.com/nlohmann/json/issues/1751) +- Is there a reason the `get\_to` method is defined in `include/nlohmann/json.hpp` but not in `single\_include/nlohmann/json.hpp`? [\#1750](https://github.com/nlohmann/json/issues/1750) +- how to validate json object before calling dump\(\) [\#1748](https://github.com/nlohmann/json/issues/1748) +- Unable to invoke accessors on json objects in lldb [\#1745](https://github.com/nlohmann/json/issues/1745) +- Escaping string before parsing [\#1743](https://github.com/nlohmann/json/issues/1743) +- Construction in a member initializer list using curly braces is set as 'array' [\#1742](https://github.com/nlohmann/json/issues/1742) +- Read a subkey from json object [\#1740](https://github.com/nlohmann/json/issues/1740) +- Serialize vector of glm:vec2 [\#1739](https://github.com/nlohmann/json/issues/1739) +- Support nlohmann::basic\_json::value with JSON\_NOEXCEPTION [\#1738](https://github.com/nlohmann/json/issues/1738) +- how to know the parse is error [\#1737](https://github.com/nlohmann/json/issues/1737) +- How to check if a given key exists in a JSON object [\#1736](https://github.com/nlohmann/json/issues/1736) +- Allow The Colon Key-Value Delimiter To Have A Space Before It \[@ READ ONLY\] [\#1735](https://github.com/nlohmann/json/issues/1735) +- Allow Tail { "Key": "Value" } Comma \[@ READ ONLY\] [\#1734](https://github.com/nlohmann/json/issues/1734) +- No-throw json::value\(\) [\#1733](https://github.com/nlohmann/json/issues/1733) +- JsonObject.dump\(\) [\#1732](https://github.com/nlohmann/json/issues/1732) +- basic\_json has no member "parse" [\#1731](https://github.com/nlohmann/json/issues/1731) +- Exception "type must be string, but is array" [\#1730](https://github.com/nlohmann/json/issues/1730) +- json::contains usage to find a path [\#1727](https://github.com/nlohmann/json/issues/1727) +- How to create JSON Object from my Structures of Data and Json File from that Object [\#1726](https://github.com/nlohmann/json/issues/1726) +- please provide an API to read JSON from file directly. [\#1725](https://github.com/nlohmann/json/issues/1725) +- How to modify a value stored at a key? [\#1723](https://github.com/nlohmann/json/issues/1723) +- CMake not correctly finding the configuration package for 3.7.0 [\#1721](https://github.com/nlohmann/json/issues/1721) +- name typo in the "spack package management" section of README.md [\#1720](https://github.com/nlohmann/json/issues/1720) +- How to add json to another json? [\#1718](https://github.com/nlohmann/json/issues/1718) +- How can I save json object in file in order? [\#1717](https://github.com/nlohmann/json/issues/1717) +- json::parse\(\) ubsan regression with v3.7.0 [\#1716](https://github.com/nlohmann/json/issues/1716) +- What I am doing wrong?!? [\#1714](https://github.com/nlohmann/json/issues/1714) +- Potential memory leak detected by Valgrind [\#1713](https://github.com/nlohmann/json/issues/1713) +- json::parse is not thread safe? [\#1712](https://github.com/nlohmann/json/issues/1712) +- static analysis alarm by cppcheck [\#1711](https://github.com/nlohmann/json/issues/1711) +- The compilation time is slow [\#1710](https://github.com/nlohmann/json/issues/1710) +- not linking properly with cmake [\#1709](https://github.com/nlohmann/json/issues/1709) +- Error in dump\(\) with int64\_t minimum value [\#1708](https://github.com/nlohmann/json/issues/1708) +- Crash on trying to deserialize json string on 3ds homebrew [\#1707](https://github.com/nlohmann/json/issues/1707) +- Can't compile VS2019. 13 Errors [\#1706](https://github.com/nlohmann/json/issues/1706) +- find an object that matches the search criteria [\#1705](https://github.com/nlohmann/json/issues/1705) +- IntelliSense goes crazy on VS2019 [\#1704](https://github.com/nlohmann/json/issues/1704) +- Installing on Ubuntu 16.04 [\#1703](https://github.com/nlohmann/json/issues/1703) +- Where is json::parse now? [\#1702](https://github.com/nlohmann/json/issues/1702) +- Forward header should't be amalgamated [\#1700](https://github.com/nlohmann/json/issues/1700) +- Json support for Cmake version 2.8.12 [\#1699](https://github.com/nlohmann/json/issues/1699) +- Intruisive scientific notation when using .dump\(\); [\#1698](https://github.com/nlohmann/json/issues/1698) +- Is there support for automatic serialization/deserialization? [\#1696](https://github.com/nlohmann/json/issues/1696) +- on MSVC dump\(\) will hard crash for larger json [\#1693](https://github.com/nlohmann/json/issues/1693) +- puzzled implicit conversions [\#1692](https://github.com/nlohmann/json/issues/1692) +- Information: My project uses this awesome library [\#1691](https://github.com/nlohmann/json/issues/1691) +- Consider listing files explicitly instead of using GLOB [\#1686](https://github.com/nlohmann/json/issues/1686) +- Failing tests on MSVC with VS2019 15.9.13 x64 [\#1685](https://github.com/nlohmann/json/issues/1685) +- Consider putting the user-defined literals in a namespace [\#1682](https://github.com/nlohmann/json/issues/1682) +- Change from v2 to v3. Encoding with cp1252 [\#1680](https://github.com/nlohmann/json/issues/1680) +- How to add Fifo\_map into json using Cmake [\#1679](https://github.com/nlohmann/json/issues/1679) +- include.zip should contain meson.build [\#1672](https://github.com/nlohmann/json/issues/1672) +- \[Question\] How do I parse JSON into custom types? [\#1669](https://github.com/nlohmann/json/issues/1669) +- Binary \(0x05\) data type for BSON to JSON conversion [\#1668](https://github.com/nlohmann/json/issues/1668) +- Possible to call dump from lldb? [\#1666](https://github.com/nlohmann/json/issues/1666) +- Segmentation fault when linked with libunwind [\#1665](https://github.com/nlohmann/json/issues/1665) +- Should I include single-header after my to\_json and from\_json custom functions declaration? Why not? [\#1663](https://github.com/nlohmann/json/issues/1663) +- Errors/Warnings in VS 2019 when Including Header File [\#1659](https://github.com/nlohmann/json/issues/1659) +- Return null object from object's const operator\[\] as well. [\#1658](https://github.com/nlohmann/json/issues/1658) +- Can't stream json object in to std::basic\_stringstream\ [\#1656](https://github.com/nlohmann/json/issues/1656) +- C2440 in vs2015 cannot convert from 'initializer-list' to nlohmann::basic\_json [\#1655](https://github.com/nlohmann/json/issues/1655) +- Issues around get and pointers [\#1653](https://github.com/nlohmann/json/issues/1653) +- Non-member operator== breaks enum \(de\)serialization [\#1647](https://github.com/nlohmann/json/issues/1647) +- Valgrind: bytes in 1 blocks are definitely lost [\#1646](https://github.com/nlohmann/json/issues/1646) +- Convenient way to make 'basic\_json' accept 'QString' as an key type as well? [\#1640](https://github.com/nlohmann/json/issues/1640) +- mongodb: nan, inf [\#1599](https://github.com/nlohmann/json/issues/1599) +- Error in adl\_serializer [\#1590](https://github.com/nlohmann/json/issues/1590) +- Injecting class during serialization [\#1584](https://github.com/nlohmann/json/issues/1584) +- output\_adapter not user extensible [\#1534](https://github.com/nlohmann/json/issues/1534) +- Inclusion of nlohmann/json.hpp causes OS/ABI to change on Linux [\#1410](https://github.com/nlohmann/json/issues/1410) +- Add library versioning using inline namespaces [\#1394](https://github.com/nlohmann/json/issues/1394) +- CBOR byte string support [\#1129](https://github.com/nlohmann/json/issues/1129) +- How to deserialize array with derived objects [\#716](https://github.com/nlohmann/json/issues/716) + +- Add restriction for tuple specialization of to\_json [\#1826](https://github.com/nlohmann/json/pull/1826) ([cbegue](https://github.com/cbegue)) +- Fix for \#1647 [\#1821](https://github.com/nlohmann/json/pull/1821) ([AnthonyVH](https://github.com/AnthonyVH)) +- Fix issue \#1805 [\#1806](https://github.com/nlohmann/json/pull/1806) ([cbegue](https://github.com/cbegue)) +- Fix some spelling errors - mostly in comments & documentation. [\#1803](https://github.com/nlohmann/json/pull/1803) ([flopp](https://github.com/flopp)) +- Update Hedley to v11. [\#1799](https://github.com/nlohmann/json/pull/1799) ([nemequ](https://github.com/nemequ)) +- iteration\_proxy: Fix integer truncation from std::size\_t to int [\#1797](https://github.com/nlohmann/json/pull/1797) ([t-b](https://github.com/t-b)) +- appveyor.yml: Add MSVC 16 2019 support [\#1780](https://github.com/nlohmann/json/pull/1780) ([t-b](https://github.com/t-b)) +- test/CMakeLists.txt: Use an explicit list instead of GLOB [\#1779](https://github.com/nlohmann/json/pull/1779) ([t-b](https://github.com/t-b)) +- Make json\_pointer::back const \(resolves \#1764\) [\#1769](https://github.com/nlohmann/json/pull/1769) ([chris0x44](https://github.com/chris0x44)) +- did you mean 'serialization'? [\#1767](https://github.com/nlohmann/json/pull/1767) ([0xflotus](https://github.com/0xflotus)) +- Allow items\(\) to be used with custom string [\#1765](https://github.com/nlohmann/json/pull/1765) ([crazyjul](https://github.com/crazyjul)) +- Cppcheck fixes [\#1760](https://github.com/nlohmann/json/pull/1760) ([Xav83](https://github.com/Xav83)) +- Fix and add test's for SFINAE problem [\#1741](https://github.com/nlohmann/json/pull/1741) ([tete17](https://github.com/tete17)) +- Fix clang sanitizer invocation [\#1728](https://github.com/nlohmann/json/pull/1728) ([t-b](https://github.com/t-b)) +- Add gcc 9 and compile with experimental C++20 support [\#1724](https://github.com/nlohmann/json/pull/1724) ([t-b](https://github.com/t-b)) +- Fix int64 min issue [\#1722](https://github.com/nlohmann/json/pull/1722) ([t-b](https://github.com/t-b)) +- release: add singleinclude and meson.build to include.zip [\#1694](https://github.com/nlohmann/json/pull/1694) ([eli-schwartz](https://github.com/eli-schwartz)) + ## [v3.7.0](https://github.com/nlohmann/json/releases/tag/v3.7.0) (2019-07-28) [Full Changelog](https://github.com/nlohmann/json/compare/v3.6.1...v3.7.0) @@ -233,7 +366,6 @@ All notable changes to this project will be documented in this file. This projec - Coverity Scan reports an UNCAUGHT\_EXCEPT issue [\#1400](https://github.com/nlohmann/json/issues/1400) - fff [\#1399](https://github.com/nlohmann/json/issues/1399) - sorry this is not an issue, just a Question, How to change a key value in a file and save it ? [\#1398](https://github.com/nlohmann/json/issues/1398) -- Add library versioning using inline namespaces [\#1394](https://github.com/nlohmann/json/issues/1394) - appveyor x64 builds appear to be using Win32 toolset [\#1374](https://github.com/nlohmann/json/issues/1374) - Serializing/Deserializing a Class containing a vector of itself [\#1373](https://github.com/nlohmann/json/issues/1373) - Retrieving array elements. [\#1369](https://github.com/nlohmann/json/issues/1369) @@ -911,7 +1043,6 @@ All notable changes to this project will be documented in this file. This projec - Compile-Error C2100 \(MS VS2015\) in line 887 json.hpp [\#719](https://github.com/nlohmann/json/issues/719) - from\_json not working for boost::optional example [\#718](https://github.com/nlohmann/json/issues/718) - about from\_json and to\_json function [\#717](https://github.com/nlohmann/json/issues/717) -- How to deserialize array with derived objects [\#716](https://github.com/nlohmann/json/issues/716) - How to detect parse failure? [\#715](https://github.com/nlohmann/json/issues/715) - Parse throw std::ios\_base::failure exception when failbit set to true [\#714](https://github.com/nlohmann/json/issues/714) - Is there a way of format just making a pretty print without changing the key's orders ? [\#713](https://github.com/nlohmann/json/issues/713) diff --git a/Makefile b/Makefile index abc97389..9dc8be68 100644 --- a/Makefile +++ b/Makefile @@ -134,7 +134,7 @@ pedantic_clang: # calling GCC with most warnings pedantic_gcc: - $(MAKE) json_unit CXX=/usr/local/bin/g++-9 CXXFLAGS=" \ + $(MAKE) json_unit CXX=g++-9 CXXFLAGS=" \ -std=c++11 \ -Waddress \ -Waddress-of-packed-member \ @@ -435,7 +435,7 @@ fuzzing-stop: # call cppcheck # Note: this target is called by Travis cppcheck: - cppcheck --enable=warning --inline-suppr --inconclusive --force --std=c++11 $(SRCS) --error-exitcode=1 + cppcheck --enable=warning --inline-suppr --inconclusive --force --std=c++11 $(AMALGAMATED_FILE) --error-exitcode=1 # call Clang Static Analyzer clang_analyze: @@ -457,7 +457,7 @@ cpplint: # call Clang-Tidy clang_tidy: - $(COMPILER_DIR)/clang-tidy $(SRCS) -- -Iinclude -std=c++11 + $(COMPILER_DIR)/clang-tidy $(AMALGAMATED_FILE) -- -Iinclude -std=c++11 # call PVS-Studio Analyzer pvs_studio: @@ -594,7 +594,7 @@ ChangeLog.md: release: rm -fr release_files mkdir release_files - zip -9 --recurse-paths -X include.zip $(SRCS) + zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) meson.build gpg --armor --detach-sig include.zip mv include.zip include.zip.asc release_files gpg --armor --detach-sig $(AMALGAMATED_FILE) diff --git a/README.md b/README.md index fa64fbe7..61dc5380 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ [![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&utm_medium=referral&utm_content=nlohmann/json&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) +[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/json.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:json) [![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) @@ -152,11 +153,13 @@ endif() :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`. -If you are using the [Meson Build System](http://mesonbuild.com), then you can get a wrap file by downloading it from [Meson WrapDB](https://wrapdb.mesonbuild.com/nlohmann_json), or simply use `meson wrap install nlohmann_json`. +If you are using the [Meson Build System](http://mesonbuild.com), add this source tree as a [meson subproject](https://mesonbuild.com/Subprojects.html#using-a-subproject). You may also use the `include.zip` published in this project's [Releases](https://github.com/nlohmann/json/releases) to reduce the size of the vendored source tree. Alternatively, you can get a wrap file by downloading it from [Meson WrapDB](https://wrapdb.mesonbuild.com/nlohmann_json), or simply use `meson wrap install nlohmann_json`. Please see the meson project for any issues regarding the packaging. + +The provided meson.build can also be used as an alternative to cmake for installing `nlohmann_json` system-wide in which case a pkg-config file is installed. To use it, simply have your build system require the `nlohmann_json` pkg-config dependency. In Meson, it is preferred to use the [`dependency()`](https://mesonbuild.com/Reference-manual.html#dependency) object with a subproject fallback, rather than using the subproject directly. 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 [Spack](https://www.spack.io/) to manage your dependencies, you can use the [`nlohmann-json` package](https://spack.readthedocs.io/en/latest/package_list.html#nlohmann-json). 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. @@ -927,7 +930,7 @@ NLOHMANN_JSON_SERIALIZE_ENUM( TaskState, { }) ``` -The `NLOHMANN_JSON_SERIALIZE_ENUM()` macro declares a set of `to_json()` / `from_json()` functions for type `TaskState` while avoiding repetition and boilerplate serilization code. +The `NLOHMANN_JSON_SERIALIZE_ENUM()` macro declares a set of `to_json()` / `from_json()` functions for type `TaskState` while avoiding repetition and boilerplate serialization code. **Usage:** @@ -999,11 +1002,12 @@ json j_from_ubjson = json::from_ubjson(v_ubjson); Though it's 2019 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work: -- GCC 4.8 - 9.0 (and possibly later) -- Clang 3.4 - 8.0 (and possibly later) +- GCC 4.8 - 9.2 (and possibly later) +- Clang 3.4 - 9.0 (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) +- Microsoft Visual C++ 2019 / Build Tools 16.3.1+1def00d3d (and possibly later) I would be happy to learn about other compilers/versions. @@ -1024,7 +1028,7 @@ Please note: - 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), [AppVeyor](https://ci.appveyor.com/project/nlohmann/json), and [Doozer](https://doozer.io): +The following compilers are currently used in continuous integration at [Travis](https://travis-ci.org/nlohmann/json), [AppVeyor](https://ci.appveyor.com/project/nlohmann/json), [CircleCI](https://circleci.com/gh/nlohmann/json), and [Doozer](https://doozer.io): | Compiler | Operating System | Version String | |-----------------------|------------------------------|----------------| @@ -1034,11 +1038,13 @@ The following compilers are currently used in continuous integration at [Travis] | 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.3.1 (armv7l) | Ubuntu 16.04 LTS | g++ (Ubuntu/Linaro 5.3.1-14ubuntu2) 5.3.1 20160413 | | GCC 5.5.0 | Ubuntu 14.04.1 LTS | g++-5 (Ubuntu 5.5.0-12ubuntu1~14.04) 5.5.0 20171010 | +| GCC 6.3.0 | Debian 9 (stretch) | g++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516 | | GCC 6.3.1 | Fedora release 24 (Twenty Four) | g++ (GCC) 6.3.1 20161221 (Red Hat 6.3.1-1) | | 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 | +| GCC 9.2.1 | Ubuntu 14.05.1 LTS | g++-9 (Ubuntu 9.2.1-16ubuntu1~14.04.1) 9.2.1 20191030 | | 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) | @@ -1055,8 +1061,10 @@ The following compilers are currently used in continuous integration at [Travis] | 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) | | Clang Xcode 10.1 | OSX 10.13.3 | Apple LLVM version 10.0.0 (clang-1000.11.45.5) | +| Clang Xcode 10.2 | OSX 10.14.4 | Apple LLVM version 10.0.1 (clang-1001.0.46.4) | | 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.7.180.61344, MSVC 19.14.26433.0 | +| Visual Studio 15 2017 | Windows Server 2012 R2 (x64) | Microsoft (R) Build Engine version 15.9.21+g9802d43bc3, MSVC 19.16.27032.1 | +| Visual Studio 16 2019 | Windows Server 2012 R2 (x64) | Microsoft (R) Build Engine version 16.3.1+1def00d3d, MSVC 19.23.28106.4 | ## License @@ -1251,7 +1259,7 @@ I deeply appreciate the help of the following people. - [Ivor Wanders](https://github.com/iwanders) helped reducing the CMake requirement to version 3.1. - [njlr](https://github.com/njlr) updated the Buckaroo instructions. - [Lion](https://github.com/lieff) fixed a compilation issue with GCC 7 on CentOS. -- [Isaac Nickaein](https://github.com/nickaein) improved the integer serilization performance and implemented the `contains()` function. +- [Isaac Nickaein](https://github.com/nickaein) improved the integer serialization performance and implemented the `contains()` function. - [past-due](https://github.com/past-due) suppressed an unfixable warning. - [Elvis Oric](https://github.com/elvisoric) improved Meson support. - [Matěj Plch](https://github.com/Afforix) fixed an example in the README. @@ -1269,6 +1277,16 @@ I deeply appreciate the help of the following people. - [Gabe Ron](https://github.com/Macr0Nerd) implemented the `to_string` method. - [Watal M. Iwasaki](https://github.com/heavywatal) fixed a Clang warning. - [Viktor Kirilov](https://github.com/onqtam) switched the unit tests from [Catch](https://github.com/philsquared/Catch) to [doctest](https://github.com/onqtam/doctest) +- [Juncheng E](https://github.com/ejcjason) fixed a typo. +- [tete17](https://github.com/tete17) fixed a bug in the `contains` function. +- [Xav83](https://github.com/Xav83) fixed some cppcheck warnings. +- [0xflotus](https://github.com/0xflotus) fixed some typos. +- [Christian Deneke](https://github.com/chris0x44) added a const version of `json_pointer::back`. +- [Julien Hamaide](https://github.com/crazyjul) made the `items()` function work with custom string types. +- [Evan Nemerson](https://github.com/nemequ) updated fixed a bug in Hedley and updated this library accordingly. +- [Florian Pigorsch](https://github.com/flopp) fixed a lot of typos. +- [Camille Bégué](https://github.com/cbegue) fixed an issue in the conversion from `std::pair` and `std::tuple` to `json`. +- [Anthony VH](https://github.com/AnthonyVH) fixed a compile error in an enum deserialization. Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone. @@ -1353,7 +1371,7 @@ By default, the library does not preserve the **insertion order of object elemen - 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_a233b02b0839ef798942dd46157cc0fe6.html#a233b02b0839ef798942dd46157cc0fe6) 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_a73ae333487310e3302135189ce8ff5d8.html#a73ae333487310e3302135189ce8ff5d8). - As the exact type of a number is not defined in the [JSON specification](https://tools.ietf.org/html/rfc8259.html), 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 code can be compiled without C++ **runtime type identification** features; that is, you can use the `-fno-rtti` compiler flag. -- **Exceptions** are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION`. In this case, exceptions are replaced by an `abort()` call. +- **Exceptions** are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION`. In this case, exceptions are replaced by `abort()` calls. You can further control this behavior by defining `JSON_THROW_USER´` (overriding `throw`), `JSON_TRY_USER` (overriding `try`), and `JSON_CATCH_USER` (overriding `catch`). Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior. ## Execute unit tests diff --git a/appveyor.yml b/appveyor.yml index 0a92a6c9..9ee5d9a3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,6 +16,20 @@ environment: LINKER_FLAGS: "" GENERATOR: Visual Studio 15 2017 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + configuration: Debug + platform: x86 + CXX_FLAGS: "" + LINKER_FLAGS: "" + GENERATOR: Visual Studio 16 2019 + + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + configuration: Debug + platform: x64 + CXX_FLAGS: "" + LINKER_FLAGS: "" + GENERATOR: Visual Studio 16 2019 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 configuration: Debug COMPILER: mingw @@ -47,13 +61,6 @@ environment: LINKER_FLAGS: "" GENERATOR: Visual Studio 14 2015 - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - configuration: Release - platform: x86 - CXX_FLAGS: "" - LINKER_FLAGS: "" - GENERATOR: Visual Studio 15 2017 - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 configuration: Release platform: x86 @@ -61,43 +68,51 @@ environment: LINKER_FLAGS: "" GENERATOR: Visual Studio 15 2017 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + configuration: Release + platform: x86 + CXX_FLAGS: "" + LINKER_FLAGS: "" + GENERATOR: Visual Studio 16 2019 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 configuration: Release platform: x64 CXX_FLAGS: "" LINKER_FLAGS: "" - GENERATOR: Visual Studio 14 2015 Win64 - - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - configuration: Release - platform: x64 - CXX_FLAGS: "" - LINKER_FLAGS: "" - GENERATOR: Visual Studio 15 2017 Win64 + GENERATOR: Visual Studio 14 2015 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 configuration: Release platform: x64 CXX_FLAGS: "/permissive- /std:c++latest /utf-8 /F4000000" LINKER_FLAGS: "/STACK:4000000" - GENERATOR: Visual Studio 15 2017 Win64 + GENERATOR: Visual Studio 15 2017 + + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + configuration: Release + platform: x64 + CXX_FLAGS: "" + LINKER_FLAGS: "" + GENERATOR: Visual Studio 16 2019 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 + - 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 + - if "%platform%"=="x86" set GENERATOR_PLATFORM=Win32 before_build: # for with_win_header build, inject the inclusion of Windows.h to the single-header library - ps: if ($env:name -Eq "with_win_header") { $header_path = "single_include\nlohmann\json.hpp" } - ps: if ($env:name -Eq "with_win_header") { "#include `n" + (Get-Content $header_path | Out-String) | Set-Content $header_path } - - cmake . -G "%GENERATOR%" -DCMAKE_BUILD_TYPE="%configuration%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_EXE_LINKER_FLAGS="%LINKER_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin" + - if "%GENERATOR%"=="Ninja" (cmake . -G "%GENERATOR%" -DCMAKE_BUILD_TYPE="%configuration%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_EXE_LINKER_FLAGS="%LINKER_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin") else (cmake . -G "%GENERATOR%" -A "%GENERATOR_PLATFORM%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_EXE_LINKER_FLAGS="%LINKER_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin") build_script: - cmake --build . --config "%configuration%" diff --git a/doc/Doxyfile b/doc/Doxyfile index a9c611b4..722797c6 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -5,7 +5,7 @@ #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = "JSON for Modern C++" -PROJECT_NUMBER = 3.7.0 +PROJECT_NUMBER = 3.7.1 PROJECT_BRIEF = PROJECT_LOGO = OUTPUT_DIRECTORY = . diff --git a/doc/avatars.png b/doc/avatars.png index e729b01d..ccd95cf1 100644 Binary files a/doc/avatars.png and b/doc/avatars.png differ diff --git a/doc/examples/README.link b/doc/examples/README.link index 42cc413c..9ac2a1dc 100644 --- a/doc/examples/README.link +++ b/doc/examples/README.link @@ -1 +1 @@ -online \ No newline at end of file +online \ No newline at end of file diff --git a/doc/examples/json_pointer__operator_add.cpp b/doc/examples/json_pointer__operator_add.cpp index 7520feb2..a2bbf59e 100644 --- a/doc/examples/json_pointer__operator_add.cpp +++ b/doc/examples/json_pointer__operator_add.cpp @@ -9,7 +9,7 @@ int main() json::json_pointer ptr("/foo"); std::cout << ptr << '\n'; - // apppend a JSON Pointer + // append a JSON Pointer ptr /= json::json_pointer("/bar/baz"); std::cout << ptr << '\n'; diff --git a/doc/examples/json_pointer__operator_add.link b/doc/examples/json_pointer__operator_add.link index 9fc51060..adc1ad51 100644 --- a/doc/examples/json_pointer__operator_add.link +++ b/doc/examples/json_pointer__operator_add.link @@ -1 +1 @@ -online \ No newline at end of file +online \ No newline at end of file diff --git a/doc/examples/json_pointer__operator_add_binary.cpp b/doc/examples/json_pointer__operator_add_binary.cpp index 620763e1..89e0a6a5 100644 --- a/doc/examples/json_pointer__operator_add_binary.cpp +++ b/doc/examples/json_pointer__operator_add_binary.cpp @@ -8,7 +8,7 @@ int main() // create a JSON pointer json::json_pointer ptr("/foo"); - // apppend a JSON Pointer + // append a JSON Pointer std::cout << ptr / json::json_pointer("/bar/baz") << '\n'; // append a string diff --git a/doc/examples/json_pointer__operator_add_binary.link b/doc/examples/json_pointer__operator_add_binary.link index dabccf5c..4f7ed168 100644 --- a/doc/examples/json_pointer__operator_add_binary.link +++ b/doc/examples/json_pointer__operator_add_binary.link @@ -1 +1 @@ -online \ No newline at end of file +online \ No newline at end of file diff --git a/doc/examples/meta.output b/doc/examples/meta.output index c3557c8d..c0e6bf12 100644 --- a/doc/examples/meta.output +++ b/doc/examples/meta.output @@ -2,7 +2,7 @@ "compiler": { "c++": "201103", "family": "clang", - "version": "10.0.1 (clang-1001.0.46.4)" + "version": "11.0.0 (clang-1100.0.33.8)" }, "copyright": "(C) 2013-2017 Niels Lohmann", "name": "JSON for Modern C++", @@ -11,7 +11,7 @@ "version": { "major": 3, "minor": 7, - "patch": 0, - "string": "3.7.0" + "patch": 1, + "string": "3.7.1" } } diff --git a/doc/index.md b/doc/index.md index 5efff7bb..21759ea2 100644 --- a/doc/index.md +++ b/doc/index.md @@ -329,4 +329,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.7.0 +@version 3.7.1 diff --git a/doc/json.gif b/doc/json.gif index c3e37ed8..1d2923e3 100644 Binary files a/doc/json.gif and b/doc/json.gif differ diff --git a/include/nlohmann/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp index 224fb33f..c389dca7 100644 --- a/include/nlohmann/detail/conversions/from_json.hpp +++ b/include/nlohmann/detail/conversions/from_json.hpp @@ -154,7 +154,7 @@ void from_json(const BasicJsonType& j, std::valarray& l) JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); } l.resize(j.size()); - std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l)); + std::copy(j.begin(), j.end(), std::begin(l)); } template diff --git a/include/nlohmann/detail/conversions/to_chars.hpp b/include/nlohmann/detail/conversions/to_chars.hpp index feafaec8..d99703a5 100644 --- a/include/nlohmann/detail/conversions/to_chars.hpp +++ b/include/nlohmann/detail/conversions/to_chars.hpp @@ -330,7 +330,7 @@ inline cached_power get_cached_power_for_binary_exponent(int e) // ==> 2^(q - 1 + alpha) <= c * 2^(e + q) // ==> 2^(alpha - e - 1) <= c // - // If c were an exakt power of ten, i.e. c = 10^k, one may determine k as + // If c were an exact power of ten, i.e. c = 10^k, one may determine k as // // k = ceil( log_10( 2^(alpha - e - 1) ) ) // = ceil( (alpha - e - 1) * log_10(2) ) diff --git a/include/nlohmann/detail/conversions/to_json.hpp b/include/nlohmann/detail/conversions/to_json.hpp index db9eaf2b..a1def699 100644 --- a/include/nlohmann/detail/conversions/to_json.hpp +++ b/include/nlohmann/detail/conversions/to_json.hpp @@ -154,7 +154,10 @@ struct external_constructor j.m_type = value_t::array; j.m_value = value_t::array; j.m_value.array->resize(arr.size()); - std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin()); + if (arr.size() > 0) + { + std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin()); + } j.assert_invariant(); } }; @@ -299,8 +302,8 @@ void to_json(BasicJsonType& j, const T(&arr)[N]) external_constructor::construct(j, arr); } -template -void to_json(BasicJsonType& j, const std::pair& p) +template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible::value&& std::is_constructible::value, int > = 0 > +void to_json(BasicJsonType& j, const std::pair& p) { j = { p.first, p.second }; } @@ -319,10 +322,10 @@ void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence j = { std::get(t)... }; } -template -void to_json(BasicJsonType& j, const std::tuple& t) +template::value, int > = 0> +void to_json(BasicJsonType& j, const T& t) { - to_json_tuple_impl(j, t, index_sequence_for {}); + to_json_tuple_impl(j, t, make_index_sequence::value> {}); } struct to_json_fn diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp index 22dc55d8..1b6e0f9b 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -647,7 +647,7 @@ class binary_reader const int exp = (half >> 10u) & 0x1Fu; const unsigned int mant = half & 0x3FFu; assert(0 <= exp and exp <= 32); - assert(0 <= mant and mant <= 1024); + assert(mant <= 1024); switch (exp) { case 0: @@ -1929,7 +1929,7 @@ class binary_reader /*! @param[in] format the current format @param[in] detail a detailed error message - @param[in] context further contect information + @param[in] context further context information @return a message string to use in the parse_error exceptions */ std::string exception_message(const input_format_t format, diff --git a/include/nlohmann/detail/input/input_adapters.hpp b/include/nlohmann/detail/input/input_adapters.hpp index b7b11de0..9512a771 100644 --- a/include/nlohmann/detail/input/input_adapters.hpp +++ b/include/nlohmann/detail/input/input_adapters.hpp @@ -131,9 +131,8 @@ class input_stream_adapter : public input_adapter_protocol class input_buffer_adapter : public input_adapter_protocol { public: - JSON_HEDLEY_NON_NULL(2) input_buffer_adapter(const char* b, const std::size_t l) noexcept - : cursor(b), limit(b + l) + : cursor(b), limit(b == nullptr ? nullptr : (b + l)) {} // delete because of pointer members @@ -147,6 +146,7 @@ class input_buffer_adapter : public input_adapter_protocol { if (JSON_HEDLEY_LIKELY(cursor < limit)) { + assert(cursor != nullptr and limit != nullptr); return std::char_traits::to_int_type(*(cursor++)); } diff --git a/include/nlohmann/detail/iterators/iter_impl.hpp b/include/nlohmann/detail/iterators/iter_impl.hpp index 336aba1a..3a362971 100644 --- a/include/nlohmann/detail/iterators/iter_impl.hpp +++ b/include/nlohmann/detail/iterators/iter_impl.hpp @@ -121,8 +121,8 @@ class iter_impl /*! @brief const copy constructor @param[in] other const iterator to copy from - @note This copy constuctor had to be defined explicitely to circumvent a bug - occuring on msvc v19.0 compiler (VS 2015) debug build. For more + @note This copy constructor had to be defined explicitly to circumvent a bug + occurring on msvc v19.0 compiler (VS 2015) debug build. For more information refer to: https://github.com/nlohmann/json/issues/1608 */ iter_impl(const iter_impl& other) noexcept diff --git a/include/nlohmann/detail/iterators/iteration_proxy.hpp b/include/nlohmann/detail/iterators/iteration_proxy.hpp index da2e32b4..c61d9629 100644 --- a/include/nlohmann/detail/iterators/iteration_proxy.hpp +++ b/include/nlohmann/detail/iterators/iteration_proxy.hpp @@ -12,6 +12,11 @@ namespace nlohmann { namespace detail { +template +void int_to_string( string_type& target, std::size_t value ) +{ + target = std::to_string(value); +} template class iteration_proxy_value { public: @@ -20,6 +25,7 @@ template class iteration_proxy_value using pointer = value_type * ; using reference = value_type & ; using iterator_category = std::input_iterator_tag; + using string_type = typename std::remove_cv< typename std::remove_reference().key() ) >::type >::type; private: /// the iterator @@ -29,9 +35,9 @@ template class iteration_proxy_value /// 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"; + mutable string_type array_index_str = "0"; /// an empty string (to return a reference for primitive values) - const std::string empty_str = ""; + const string_type empty_str = ""; public: explicit iteration_proxy_value(IteratorType it) noexcept : anchor(it) {} @@ -64,7 +70,7 @@ template class iteration_proxy_value } /// return key of the iterator - const std::string& key() const + const string_type& key() const { assert(anchor.m_object != nullptr); @@ -75,7 +81,7 @@ template class iteration_proxy_value { if (array_index != array_index_last) { - array_index_str = std::to_string(array_index); + int_to_string( array_index_str, array_index ); array_index_last = array_index; } return array_index_str; diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp index 9076441c..87af3423 100644 --- a/include/nlohmann/detail/json_pointer.hpp +++ b/include/nlohmann/detail/json_pointer.hpp @@ -126,7 +126,7 @@ class json_pointer /*! @brief append an array index at the end of this JSON pointer - @param[in] array_index array index ot append + @param[in] array_index array index to append @return JSON pointer with @a array_index appended @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add} @@ -267,7 +267,7 @@ class json_pointer @since version 3.6.0 */ - const std::string& back() + const std::string& back() const { if (JSON_HEDLEY_UNLIKELY(empty())) { diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 2be7581d..27dddc6b 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -78,30 +78,30 @@ @def NLOHMANN_JSON_SERIALIZE_ENUM @since version 3.4.0 */ -#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ - template \ - inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [e](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.first == e; \ - }); \ - j = ((it != std::end(m)) ? it : std::begin(m))->second; \ - } \ - template \ - inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [j](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.second == j; \ - }); \ - e = ((it != std::end(m)) ? it : std::begin(m))->first; \ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ } // Ugly macros to avoid uglier copy-paste when specializing basic_json. They diff --git a/include/nlohmann/detail/meta/type_traits.hpp b/include/nlohmann/detail/meta/type_traits.hpp index 2b2b2d3b..280f6953 100644 --- a/include/nlohmann/detail/meta/type_traits.hpp +++ b/include/nlohmann/detail/meta/type_traits.hpp @@ -357,5 +357,18 @@ struct is_compatible_type_impl < template struct is_compatible_type : is_compatible_type_impl {}; + +// https://en.cppreference.com/w/cpp/types/conjunction +template struct conjunction : std::true_type { }; +template struct conjunction : B1 { }; +template +struct conjunction +: std::conditional, B1>::type {}; + +template +struct is_constructible_tuple : std::false_type {}; + +template +struct is_constructible_tuple> : conjunction...> {}; } // namespace detail } // namespace nlohmann diff --git a/include/nlohmann/detail/output/binary_writer.hpp b/include/nlohmann/detail/output/binary_writer.hpp index 29093dd3..eb312e8a 100644 --- a/include/nlohmann/detail/output/binary_writer.hpp +++ b/include/nlohmann/detail/output/binary_writer.hpp @@ -861,13 +861,12 @@ class binary_writer */ static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value) { - std::size_t embedded_document_size = 0ul; std::size_t array_index = 0ul; - for (const auto& el : value) + const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), 0ul, [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el) { - embedded_document_size += calc_bson_element_size(std::to_string(array_index++), el); - } + return result + calc_bson_element_size(std::to_string(array_index++), el); + }); return sizeof(std::int32_t) + embedded_document_size + 1ul; } diff --git a/include/nlohmann/detail/output/serializer.hpp b/include/nlohmann/detail/output/serializer.hpp index e6811ceb..0a4ddbda 100644 --- a/include/nlohmann/detail/output/serializer.hpp +++ b/include/nlohmann/detail/output/serializer.hpp @@ -630,7 +630,7 @@ class serializer if (is_negative) { *buffer_ptr = '-'; - abs_value = static_cast(std::abs(static_cast(x))); + abs_value = remove_sign(x); // account one more byte for the minus sign n_chars = 1 + count_digits(abs_value); @@ -811,6 +811,32 @@ class serializer return state; } + /* + * Overload to make the compiler happy while it is instantiating + * dump_integer for number_unsigned_t. + * Must never be called. + */ + number_unsigned_t remove_sign(number_unsigned_t x) + { + assert(false); // LCOV_EXCL_LINE + return x; // LCOV_EXCL_LINE + } + + /* + * Helper function for dump_integer + * + * This function takes a negative signed integer and returns its absolute + * value as unsigned integer. The plus/minus shuffling is necessary as we can + * not directly remove the sign of an arbitrary signed integer as the + * absolute values of INT_MIN and INT_MAX are usually not the same. See + * #1708 for details. + */ + inline number_unsigned_t remove_sign(number_integer_t x) noexcept + { + assert(x < 0 and x < (std::numeric_limits::max)()); + return static_cast(-(x + 1)) + 1; + } + private: /// the output of the serializer output_adapter_t o = nullptr; diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index f5210a6b..23bd3ed4 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . @@ -32,7 +32,7 @@ SOFTWARE. #define NLOHMANN_JSON_VERSION_MAJOR 3 #define NLOHMANN_JSON_VERSION_MINOR 7 -#define NLOHMANN_JSON_VERSION_PATCH 0 +#define NLOHMANN_JSON_VERSION_PATCH 1 #include // all_of, find, for_each #include // assert @@ -953,7 +953,7 @@ class basic_json object = nullptr; // silence warning, see #821 if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) { - JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.7.0")); // LCOV_EXCL_LINE + JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.7.1")); // LCOV_EXCL_LINE } break; } @@ -2633,11 +2633,11 @@ class basic_json detail::has_non_default_from_json::value, int> = 0> ValueType get() const noexcept(noexcept( - JSONSerializer::from_json(std::declval()))) + JSONSerializer::from_json(std::declval()))) { static_assert(not std::is_reference::value, "get() cannot be used with reference types, you might want to use get_ref()"); - return JSONSerializer::from_json(*this); + return JSONSerializer::from_json(*this); } /*! @@ -4010,7 +4010,7 @@ class basic_json @since version 3.6.0 */ template::value, int>::type = 0> + not std::is_same::type, json_pointer>::value, int>::type = 0> bool contains(KeyT && key) const { return is_object() and m_value.object->find(std::forward(key)) != m_value.object->end(); @@ -4019,7 +4019,7 @@ class basic_json /*! @brief check the existence of an element in a JSON object given a JSON pointer - Check wehther the given JSON pointer @a ptr can be resolved in the current + Check whether the given JSON pointer @a ptr can be resolved in the current JSON value. @note This method can be executed on any JSON value type. @@ -8062,7 +8062,7 @@ struct hash /// @note: do not remove the space after '<', /// see https://github.com/nlohmann/json/pull/679 template<> -struct less< ::nlohmann::detail::value_t> +struct less<::nlohmann::detail::value_t> { /*! @brief compare two value_t enum values diff --git a/include/nlohmann/thirdparty/hedley/hedley.hpp b/include/nlohmann/thirdparty/hedley/hedley.hpp index 453e6488..fcc19794 100644 --- a/include/nlohmann/thirdparty/hedley/hedley.hpp +++ b/include/nlohmann/thirdparty/hedley/hedley.hpp @@ -10,11 +10,11 @@ * SPDX-License-Identifier: CC0-1.0 */ -#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 9) +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 11) #if defined(JSON_HEDLEY_VERSION) #undef JSON_HEDLEY_VERSION #endif -#define JSON_HEDLEY_VERSION 9 +#define JSON_HEDLEY_VERSION 11 #if defined(JSON_HEDLEY_STRINGIFY_EX) #undef JSON_HEDLEY_STRINGIFY_EX @@ -381,12 +381,29 @@ #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE #endif -#if defined(__has_cpp_attribute) && defined(__cplusplus) +#if \ + defined(__has_cpp_attribute) && \ + defined(__cplusplus) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) #else #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) #endif +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#endif +#if !defined(__cplusplus) || !defined(__has_cpp_attribute) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#elif \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ + (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#endif + #if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE #endif @@ -540,6 +557,21 @@ #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) #endif +/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#endif +#if defined(__cplusplus) && JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +#else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#endif + #if \ (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ defined(__clang__) || \ @@ -640,6 +672,27 @@ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS #endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") +#elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif + #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL #endif @@ -660,8 +713,8 @@ #undef JSON_HEDLEY_DEPRECATED_FOR #endif #if defined(__cplusplus) && (__cplusplus >= 201402L) - #define JSON_HEDLEY_DEPRECATED(since) [[deprecated("Since " #since)]] - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) [[deprecated("Since " #since "; use " #replacement)]] + #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) #elif \ JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) || \ JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ @@ -686,7 +739,7 @@ #elif \ JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) - #define JSON_HEDLEY_DEPRECATED(since) _declspec(deprecated) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") @@ -712,7 +765,7 @@ #undef JSON_HEDLEY_WARN_UNUSED_RESULT #endif #if defined(__cplusplus) && (__cplusplus >= 201703L) - #define JSON_HEDLEY_WARN_UNUSED_RESULT [[nodiscard]] + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) #elif \ JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ @@ -751,7 +804,7 @@ #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L #define JSON_HEDLEY_NO_RETURN _Noreturn #elif defined(__cplusplus) && (__cplusplus >= 201103L) - #define JSON_HEDLEY_NO_RETURN [[noreturn]] + #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) #elif \ JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ @@ -761,6 +814,8 @@ JSON_HEDLEY_TI_VERSION_CHECK(18,0,0) || \ (JSON_HEDLEY_TI_VERSION_CHECK(17,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") #elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) #elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus) @@ -773,6 +828,15 @@ #define JSON_HEDLEY_NO_RETURN #endif +#if defined(JSON_HEDLEY_NO_ESCAPE) + #undef JSON_HEDLEY_NO_ESCAPE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) + #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) +#else + #define JSON_HEDLEY_NO_ESCAPE +#endif + #if defined(JSON_HEDLEY_UNREACHABLE) #undef JSON_HEDLEY_UNREACHABLE #endif @@ -829,11 +893,14 @@ #define JSON_HEDLEY_ASSUME(expr) ((void) (expr)) #endif - JSON_HEDLEY_DIAGNOSTIC_PUSH -#if \ - JSON_HEDLEY_HAS_WARNING("-Wvariadic-macros") || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) +#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") + #pragma clang diagnostic ignored "-Wpedantic" +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) + #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) #if defined(__clang__) #pragma clang diagnostic ignored "-Wvariadic-macros" #elif defined(JSON_HEDLEY_GCC_VERSION) @@ -881,7 +948,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif #if defined(__cplusplus) #if __cplusplus >= 201103L - #define JSON_HEDLEY_CONSTEXPR constexpr + #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) #endif #endif #if !defined(JSON_HEDLEY_CONSTEXPR) @@ -961,6 +1028,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") #elif JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) #define JSON_HEDLEY_MALLOC __declspec(restrict) #else @@ -981,6 +1050,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) #define JSON_HEDLEY_PURE __attribute__((__pure__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") #elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus) #define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") #else @@ -1001,6 +1072,9 @@ JSON_HEDLEY_DIAGNOSTIC_POP (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) #define JSON_HEDLEY_CONST __attribute__((__const__)) +#elif \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_CONST _Pragma("no_side_effect") #else #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE #endif @@ -1151,28 +1225,16 @@ JSON_HEDLEY_DIAGNOSTIC_POP #if defined(JSON_HEDLEY_FALL_THROUGH) #undef JSON_HEDLEY_FALL_THROUGH #endif -#if \ - defined(__cplusplus) && \ - (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ - !defined(JSON_HEDLEY_PGI_VERSION) - #if \ - (__cplusplus >= 201703L) || \ - ((__cplusplus >= 201103L) && JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)) - #define JSON_HEDLEY_FALL_THROUGH [[fallthrough]] - #elif (__cplusplus >= 201103L) && JSON_HEDLEY_HAS_CPP_ATTRIBUTE(clang::fallthrough) - #define JSON_HEDLEY_FALL_THROUGH [[clang::fallthrough]] - #elif (__cplusplus >= 201103L) && JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) - #define JSON_HEDLEY_FALL_THROUGH [[gnu::fallthrough]] - #endif -#endif -#if !defined(JSON_HEDLEY_FALL_THROUGH) - #if JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(fallthrough,7,0,0) && !defined(JSON_HEDLEY_PGI_VERSION) - #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) - #elif defined(__fallthrough) /* SAL */ - #define JSON_HEDLEY_FALL_THROUGH __fallthrough - #else - #define JSON_HEDLEY_FALL_THROUGH - #endif +#if JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(fallthrough,7,0,0) && !defined(JSON_HEDLEY_PGI_VERSION) + #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) +#elif defined(__fallthrough) /* SAL */ + #define JSON_HEDLEY_FALL_THROUGH __fallthrough +#else + #define JSON_HEDLEY_FALL_THROUGH #endif #if defined(JSON_HEDLEY_RETURNS_NON_NULL) @@ -1208,12 +1270,11 @@ JSON_HEDLEY_DIAGNOSTIC_POP #if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) #undef JSON_HEDLEY_REQUIRE_CONSTEXPR #endif -/* Note the double-underscore. For internal use only; no API - * guarantees! */ -#if defined(JSON_HEDLEY__IS_CONSTEXPR) - #undef JSON_HEDLEY__IS_CONSTEXPR +/* JSON_HEDLEY_IS_CONSTEXPR_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #undef JSON_HEDLEY_IS_CONSTEXPR_ #endif - #if \ JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ @@ -1222,7 +1283,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ JSON_HEDLEY_TI_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) #endif @@ -1236,10 +1297,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) #if defined(__INTPTR_TYPE__) - #define JSON_HEDLEY__IS_CONSTEXPR(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) #else #include - #define JSON_HEDLEY__IS_CONSTEXPR(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) #endif # elif \ (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && !defined(JSON_HEDLEY_SUNPRO_VERSION) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ @@ -1249,10 +1310,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) #if defined(__INTPTR_TYPE__) - #define JSON_HEDLEY__IS_CONSTEXPR(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) #else #include - #define JSON_HEDLEY__IS_CONSTEXPR(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) #endif # elif \ defined(JSON_HEDLEY_GCC_VERSION) || \ @@ -1260,7 +1321,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP defined(JSON_HEDLEY_TINYC_VERSION) || \ defined(JSON_HEDLEY_TI_VERSION) || \ defined(__clang__) -# define JSON_HEDLEY__IS_CONSTEXPR(expr) ( \ +# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ sizeof(void) != \ sizeof(*( \ 1 ? \ @@ -1271,11 +1332,11 @@ JSON_HEDLEY_DIAGNOSTIC_POP ) # endif #endif -#if defined(JSON_HEDLEY__IS_CONSTEXPR) +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) #if !defined(JSON_HEDLEY_IS_CONSTANT) - #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY__IS_CONSTEXPR(expr) + #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) #endif - #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY__IS_CONSTEXPR(expr) ? (expr) : (-1)) + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) #else #if !defined(JSON_HEDLEY_IS_CONSTANT) #define JSON_HEDLEY_IS_CONSTANT(expr) (0) @@ -1315,12 +1376,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP ) # define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) #elif \ - (defined(__cplusplus) && (__cplusplus >= 201703L)) || \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ (defined(__cplusplus) && JSON_HEDLEY_TI_VERSION_CHECK(8,3,0)) -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) static_assert(expr, message) -#elif defined(__cplusplus) && (__cplusplus >= 201103L) -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) static_assert(expr) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) #else # define JSON_HEDLEY_STATIC_ASSERT(expr, message) #endif @@ -1371,6 +1430,23 @@ JSON_HEDLEY_DIAGNOSTIC_POP #define JSON_HEDLEY_CPP_CAST(T, expr) (expr) #endif +#if defined(JSON_HEDLEY_NULL) + #undef JSON_HEDLEY_NULL +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) + #elif defined(NULL) + #define JSON_HEDLEY_NULL NULL + #else + #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) + #endif +#elif defined(NULL) + #define JSON_HEDLEY_NULL NULL +#else + #define JSON_HEDLEY_NULL ((void*) 0) +#endif + #if defined(JSON_HEDLEY_MESSAGE) #undef JSON_HEDLEY_MESSAGE #endif @@ -1413,28 +1489,33 @@ JSON_HEDLEY_DIAGNOSTIC_POP # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) #endif +#if defined(JSON_HEDLEY_REQUIRE) + #undef JSON_HEDLEY_REQUIRE +#endif #if defined(JSON_HEDLEY_REQUIRE_MSG) #undef JSON_HEDLEY_REQUIRE_MSG #endif #if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) # if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") -# define JSON_HEDLEY_REQUIRE_MSG(expr, msg) \ +# define JSON_HEDLEY_REQUIRE(expr) \ JSON_HEDLEY_DIAGNOSTIC_PUSH \ _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ - __attribute__((__diagnose_if__(!(expr), msg, "error"))) \ + __attribute__((diagnose_if(!(expr), #expr, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), msg, "error"))) \ JSON_HEDLEY_DIAGNOSTIC_POP # else -# define JSON_HEDLEY_REQUIRE_MSG(expr, msg) __attribute__((__diagnose_if__(!(expr), msg, "error"))) +# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) # endif #else -# define JSON_HEDLEY_REQUIRE_MSG(expr, msg) +# define JSON_HEDLEY_REQUIRE(expr) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) #endif -#if defined(JSON_HEDLEY_REQUIRE) - #undef JSON_HEDLEY_REQUIRE -#endif -#define JSON_HEDLEY_REQUIRE(expr) JSON_HEDLEY_REQUIRE_MSG(expr, #expr) - #if defined(JSON_HEDLEY_FLAGS) #undef JSON_HEDLEY_FLAGS #endif @@ -1456,6 +1537,15 @@ JSON_HEDLEY_DIAGNOSTIC_POP # define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) #endif +#if defined(JSON_HEDLEY_EMPTY_BASES) + #undef JSON_HEDLEY_EMPTY_BASES +#endif +#if JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0) + #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) +#else + #define JSON_HEDLEY_EMPTY_BASES +#endif + /* Remaining macros are deprecated. */ #if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) diff --git a/include/nlohmann/thirdparty/hedley/hedley_undef.hpp b/include/nlohmann/thirdparty/hedley/hedley_undef.hpp index 9e8f6d48..99076cdf 100644 --- a/include/nlohmann/thirdparty/hedley/hedley_undef.hpp +++ b/include/nlohmann/thirdparty/hedley/hedley_undef.hpp @@ -4,6 +4,7 @@ #undef JSON_HEDLEY_ARRAY_PARAM #undef JSON_HEDLEY_ASSUME #undef JSON_HEDLEY_BEGIN_C_DECLS +#undef JSON_HEDLEY_C_DECL #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE #undef JSON_HEDLEY_CLANG_HAS_BUILTIN #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE @@ -16,21 +17,23 @@ #undef JSON_HEDLEY_CONCAT #undef JSON_HEDLEY_CONCAT_EX #undef JSON_HEDLEY_CONST -#undef JSON_HEDLEY_CONSTEXPR #undef JSON_HEDLEY_CONST_CAST +#undef JSON_HEDLEY_CONSTEXPR #undef JSON_HEDLEY_CPP_CAST #undef JSON_HEDLEY_CRAY_VERSION #undef JSON_HEDLEY_CRAY_VERSION_CHECK -#undef JSON_HEDLEY_C_DECL #undef JSON_HEDLEY_DEPRECATED #undef JSON_HEDLEY_DEPRECATED_FOR #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS #undef JSON_HEDLEY_DIAGNOSTIC_POP #undef JSON_HEDLEY_DIAGNOSTIC_PUSH #undef JSON_HEDLEY_DMC_VERSION #undef JSON_HEDLEY_DMC_VERSION_CHECK +#undef JSON_HEDLEY_EMPTY_BASES #undef JSON_HEDLEY_EMSCRIPTEN_VERSION #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK #undef JSON_HEDLEY_END_C_DECLS @@ -59,6 +62,7 @@ #undef JSON_HEDLEY_HAS_ATTRIBUTE #undef JSON_HEDLEY_HAS_BUILTIN #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE #undef JSON_HEDLEY_HAS_EXTENSION #undef JSON_HEDLEY_HAS_FEATURE @@ -72,15 +76,18 @@ #undef JSON_HEDLEY_INTEL_VERSION #undef JSON_HEDLEY_INTEL_VERSION_CHECK #undef JSON_HEDLEY_IS_CONSTANT +#undef JSON_HEDLEY_IS_CONSTEXPR_ #undef JSON_HEDLEY_LIKELY #undef JSON_HEDLEY_MALLOC #undef JSON_HEDLEY_MESSAGE #undef JSON_HEDLEY_MSVC_VERSION #undef JSON_HEDLEY_MSVC_VERSION_CHECK #undef JSON_HEDLEY_NEVER_INLINE +#undef JSON_HEDLEY_NO_ESCAPE #undef JSON_HEDLEY_NON_NULL #undef JSON_HEDLEY_NO_RETURN #undef JSON_HEDLEY_NO_THROW +#undef JSON_HEDLEY_NULL #undef JSON_HEDLEY_PELLES_VERSION #undef JSON_HEDLEY_PELLES_VERSION_CHECK #undef JSON_HEDLEY_PGI_VERSION diff --git a/meson.build b/meson.build index 5f88dae1..a615c5f3 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project('nlohmann_json', 'cpp', - version : '3.7.0', + version : '3.7.1', license : 'MIT', ) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 2a32a829..6430930d 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . @@ -32,7 +32,7 @@ SOFTWARE. #define NLOHMANN_JSON_VERSION_MAJOR 3 #define NLOHMANN_JSON_VERSION_MINOR 7 -#define NLOHMANN_JSON_VERSION_PATCH 0 +#define NLOHMANN_JSON_VERSION_PATCH 1 #include // all_of, find, for_each #include // assert @@ -122,11 +122,11 @@ struct position_t * SPDX-License-Identifier: CC0-1.0 */ -#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 9) +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 11) #if defined(JSON_HEDLEY_VERSION) #undef JSON_HEDLEY_VERSION #endif -#define JSON_HEDLEY_VERSION 9 +#define JSON_HEDLEY_VERSION 11 #if defined(JSON_HEDLEY_STRINGIFY_EX) #undef JSON_HEDLEY_STRINGIFY_EX @@ -493,12 +493,29 @@ struct position_t #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE #endif -#if defined(__has_cpp_attribute) && defined(__cplusplus) +#if \ + defined(__has_cpp_attribute) && \ + defined(__cplusplus) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) #else #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) #endif +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#endif +#if !defined(__cplusplus) || !defined(__has_cpp_attribute) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#elif \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ + (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#endif + #if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE #endif @@ -652,6 +669,21 @@ struct position_t #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) #endif +/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#endif +#if defined(__cplusplus) && JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +#else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#endif + #if \ (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ defined(__clang__) || \ @@ -752,6 +784,27 @@ struct position_t #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS #endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") +#elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif + #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL #endif @@ -772,8 +825,8 @@ struct position_t #undef JSON_HEDLEY_DEPRECATED_FOR #endif #if defined(__cplusplus) && (__cplusplus >= 201402L) - #define JSON_HEDLEY_DEPRECATED(since) [[deprecated("Since " #since)]] - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) [[deprecated("Since " #since "; use " #replacement)]] + #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) #elif \ JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) || \ JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ @@ -798,7 +851,7 @@ struct position_t #elif \ JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) - #define JSON_HEDLEY_DEPRECATED(since) _declspec(deprecated) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") @@ -824,7 +877,7 @@ struct position_t #undef JSON_HEDLEY_WARN_UNUSED_RESULT #endif #if defined(__cplusplus) && (__cplusplus >= 201703L) - #define JSON_HEDLEY_WARN_UNUSED_RESULT [[nodiscard]] + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) #elif \ JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ @@ -863,7 +916,7 @@ struct position_t #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L #define JSON_HEDLEY_NO_RETURN _Noreturn #elif defined(__cplusplus) && (__cplusplus >= 201103L) - #define JSON_HEDLEY_NO_RETURN [[noreturn]] + #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) #elif \ JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ @@ -873,6 +926,8 @@ struct position_t JSON_HEDLEY_TI_VERSION_CHECK(18,0,0) || \ (JSON_HEDLEY_TI_VERSION_CHECK(17,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") #elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) #elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus) @@ -885,6 +940,15 @@ struct position_t #define JSON_HEDLEY_NO_RETURN #endif +#if defined(JSON_HEDLEY_NO_ESCAPE) + #undef JSON_HEDLEY_NO_ESCAPE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) + #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) +#else + #define JSON_HEDLEY_NO_ESCAPE +#endif + #if defined(JSON_HEDLEY_UNREACHABLE) #undef JSON_HEDLEY_UNREACHABLE #endif @@ -941,11 +1005,14 @@ struct position_t #define JSON_HEDLEY_ASSUME(expr) ((void) (expr)) #endif - JSON_HEDLEY_DIAGNOSTIC_PUSH -#if \ - JSON_HEDLEY_HAS_WARNING("-Wvariadic-macros") || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) +#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") + #pragma clang diagnostic ignored "-Wpedantic" +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) + #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) #if defined(__clang__) #pragma clang diagnostic ignored "-Wvariadic-macros" #elif defined(JSON_HEDLEY_GCC_VERSION) @@ -993,7 +1060,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif #if defined(__cplusplus) #if __cplusplus >= 201103L - #define JSON_HEDLEY_CONSTEXPR constexpr + #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) #endif #endif #if !defined(JSON_HEDLEY_CONSTEXPR) @@ -1073,6 +1140,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") #elif JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) #define JSON_HEDLEY_MALLOC __declspec(restrict) #else @@ -1093,6 +1162,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) #define JSON_HEDLEY_PURE __attribute__((__pure__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") #elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus) #define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") #else @@ -1113,6 +1184,9 @@ JSON_HEDLEY_DIAGNOSTIC_POP (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) #define JSON_HEDLEY_CONST __attribute__((__const__)) +#elif \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_CONST _Pragma("no_side_effect") #else #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE #endif @@ -1263,28 +1337,16 @@ JSON_HEDLEY_DIAGNOSTIC_POP #if defined(JSON_HEDLEY_FALL_THROUGH) #undef JSON_HEDLEY_FALL_THROUGH #endif -#if \ - defined(__cplusplus) && \ - (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ - !defined(JSON_HEDLEY_PGI_VERSION) - #if \ - (__cplusplus >= 201703L) || \ - ((__cplusplus >= 201103L) && JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)) - #define JSON_HEDLEY_FALL_THROUGH [[fallthrough]] - #elif (__cplusplus >= 201103L) && JSON_HEDLEY_HAS_CPP_ATTRIBUTE(clang::fallthrough) - #define JSON_HEDLEY_FALL_THROUGH [[clang::fallthrough]] - #elif (__cplusplus >= 201103L) && JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) - #define JSON_HEDLEY_FALL_THROUGH [[gnu::fallthrough]] - #endif -#endif -#if !defined(JSON_HEDLEY_FALL_THROUGH) - #if JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(fallthrough,7,0,0) && !defined(JSON_HEDLEY_PGI_VERSION) - #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) - #elif defined(__fallthrough) /* SAL */ - #define JSON_HEDLEY_FALL_THROUGH __fallthrough - #else - #define JSON_HEDLEY_FALL_THROUGH - #endif +#if JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(fallthrough,7,0,0) && !defined(JSON_HEDLEY_PGI_VERSION) + #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) +#elif defined(__fallthrough) /* SAL */ + #define JSON_HEDLEY_FALL_THROUGH __fallthrough +#else + #define JSON_HEDLEY_FALL_THROUGH #endif #if defined(JSON_HEDLEY_RETURNS_NON_NULL) @@ -1320,12 +1382,11 @@ JSON_HEDLEY_DIAGNOSTIC_POP #if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) #undef JSON_HEDLEY_REQUIRE_CONSTEXPR #endif -/* Note the double-underscore. For internal use only; no API - * guarantees! */ -#if defined(JSON_HEDLEY__IS_CONSTEXPR) - #undef JSON_HEDLEY__IS_CONSTEXPR +/* JSON_HEDLEY_IS_CONSTEXPR_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #undef JSON_HEDLEY_IS_CONSTEXPR_ #endif - #if \ JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ @@ -1334,7 +1395,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ JSON_HEDLEY_TI_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) #endif @@ -1348,10 +1409,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) #if defined(__INTPTR_TYPE__) - #define JSON_HEDLEY__IS_CONSTEXPR(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) #else #include - #define JSON_HEDLEY__IS_CONSTEXPR(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) #endif # elif \ (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && !defined(JSON_HEDLEY_SUNPRO_VERSION) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ @@ -1361,10 +1422,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) #if defined(__INTPTR_TYPE__) - #define JSON_HEDLEY__IS_CONSTEXPR(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) #else #include - #define JSON_HEDLEY__IS_CONSTEXPR(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) #endif # elif \ defined(JSON_HEDLEY_GCC_VERSION) || \ @@ -1372,7 +1433,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP defined(JSON_HEDLEY_TINYC_VERSION) || \ defined(JSON_HEDLEY_TI_VERSION) || \ defined(__clang__) -# define JSON_HEDLEY__IS_CONSTEXPR(expr) ( \ +# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ sizeof(void) != \ sizeof(*( \ 1 ? \ @@ -1383,11 +1444,11 @@ JSON_HEDLEY_DIAGNOSTIC_POP ) # endif #endif -#if defined(JSON_HEDLEY__IS_CONSTEXPR) +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) #if !defined(JSON_HEDLEY_IS_CONSTANT) - #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY__IS_CONSTEXPR(expr) + #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) #endif - #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY__IS_CONSTEXPR(expr) ? (expr) : (-1)) + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) #else #if !defined(JSON_HEDLEY_IS_CONSTANT) #define JSON_HEDLEY_IS_CONSTANT(expr) (0) @@ -1427,12 +1488,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP ) # define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) #elif \ - (defined(__cplusplus) && (__cplusplus >= 201703L)) || \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ (defined(__cplusplus) && JSON_HEDLEY_TI_VERSION_CHECK(8,3,0)) -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) static_assert(expr, message) -#elif defined(__cplusplus) && (__cplusplus >= 201103L) -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) static_assert(expr) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) #else # define JSON_HEDLEY_STATIC_ASSERT(expr, message) #endif @@ -1483,6 +1542,23 @@ JSON_HEDLEY_DIAGNOSTIC_POP #define JSON_HEDLEY_CPP_CAST(T, expr) (expr) #endif +#if defined(JSON_HEDLEY_NULL) + #undef JSON_HEDLEY_NULL +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) + #elif defined(NULL) + #define JSON_HEDLEY_NULL NULL + #else + #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) + #endif +#elif defined(NULL) + #define JSON_HEDLEY_NULL NULL +#else + #define JSON_HEDLEY_NULL ((void*) 0) +#endif + #if defined(JSON_HEDLEY_MESSAGE) #undef JSON_HEDLEY_MESSAGE #endif @@ -1525,28 +1601,33 @@ JSON_HEDLEY_DIAGNOSTIC_POP # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) #endif +#if defined(JSON_HEDLEY_REQUIRE) + #undef JSON_HEDLEY_REQUIRE +#endif #if defined(JSON_HEDLEY_REQUIRE_MSG) #undef JSON_HEDLEY_REQUIRE_MSG #endif #if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) # if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") -# define JSON_HEDLEY_REQUIRE_MSG(expr, msg) \ +# define JSON_HEDLEY_REQUIRE(expr) \ JSON_HEDLEY_DIAGNOSTIC_PUSH \ _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ - __attribute__((__diagnose_if__(!(expr), msg, "error"))) \ + __attribute__((diagnose_if(!(expr), #expr, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), msg, "error"))) \ JSON_HEDLEY_DIAGNOSTIC_POP # else -# define JSON_HEDLEY_REQUIRE_MSG(expr, msg) __attribute__((__diagnose_if__(!(expr), msg, "error"))) +# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) # endif #else -# define JSON_HEDLEY_REQUIRE_MSG(expr, msg) +# define JSON_HEDLEY_REQUIRE(expr) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) #endif -#if defined(JSON_HEDLEY_REQUIRE) - #undef JSON_HEDLEY_REQUIRE -#endif -#define JSON_HEDLEY_REQUIRE(expr) JSON_HEDLEY_REQUIRE_MSG(expr, #expr) - #if defined(JSON_HEDLEY_FLAGS) #undef JSON_HEDLEY_FLAGS #endif @@ -1568,6 +1649,15 @@ JSON_HEDLEY_DIAGNOSTIC_POP # define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) #endif +#if defined(JSON_HEDLEY_EMPTY_BASES) + #undef JSON_HEDLEY_EMPTY_BASES +#endif +#if JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0) + #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) +#else + #define JSON_HEDLEY_EMPTY_BASES +#endif + /* Remaining macros are deprecated. */ #if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) @@ -1692,30 +1782,30 @@ JSON_HEDLEY_DIAGNOSTIC_POP @def NLOHMANN_JSON_SERIALIZE_ENUM @since version 3.4.0 */ -#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ - template \ - inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [e](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.first == e; \ - }); \ - j = ((it != std::end(m)) ? it : std::begin(m))->second; \ - } \ - template \ - inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [j](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.second == j; \ - }); \ - e = ((it != std::end(m)) ? it : std::begin(m))->first; \ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ } // Ugly macros to avoid uglier copy-paste when specializing basic_json. They @@ -2704,6 +2794,19 @@ struct is_compatible_type_impl < template struct is_compatible_type : is_compatible_type_impl {}; + +// https://en.cppreference.com/w/cpp/types/conjunction +template struct conjunction : std::true_type { }; +template struct conjunction : B1 { }; +template +struct conjunction +: std::conditional, B1>::type {}; + +template +struct is_constructible_tuple : std::false_type {}; + +template +struct is_constructible_tuple> : conjunction...> {}; } // namespace detail } // namespace nlohmann @@ -2922,7 +3025,7 @@ void from_json(const BasicJsonType& j, std::valarray& l) JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); } l.resize(j.size()); - std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l)); + std::copy(j.begin(), j.end(), std::begin(l)); } template @@ -3186,6 +3289,11 @@ namespace nlohmann { namespace detail { +template +void int_to_string( string_type& target, std::size_t value ) +{ + target = std::to_string(value); +} template class iteration_proxy_value { public: @@ -3194,6 +3302,7 @@ template class iteration_proxy_value using pointer = value_type * ; using reference = value_type & ; using iterator_category = std::input_iterator_tag; + using string_type = typename std::remove_cv< typename std::remove_reference().key() ) >::type >::type; private: /// the iterator @@ -3203,9 +3312,9 @@ template class iteration_proxy_value /// 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"; + mutable string_type array_index_str = "0"; /// an empty string (to return a reference for primitive values) - const std::string empty_str = ""; + const string_type empty_str = ""; public: explicit iteration_proxy_value(IteratorType it) noexcept : anchor(it) {} @@ -3238,7 +3347,7 @@ template class iteration_proxy_value } /// return key of the iterator - const std::string& key() const + const string_type& key() const { assert(anchor.m_object != nullptr); @@ -3249,7 +3358,7 @@ template class iteration_proxy_value { if (array_index != array_index_last) { - array_index_str = std::to_string(array_index); + int_to_string( array_index_str, array_index ); array_index_last = array_index; } return array_index_str; @@ -3489,7 +3598,10 @@ struct external_constructor j.m_type = value_t::array; j.m_value = value_t::array; j.m_value.array->resize(arr.size()); - std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin()); + if (arr.size() > 0) + { + std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin()); + } j.assert_invariant(); } }; @@ -3634,8 +3746,8 @@ void to_json(BasicJsonType& j, const T(&arr)[N]) external_constructor::construct(j, arr); } -template -void to_json(BasicJsonType& j, const std::pair& p) +template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible::value&& std::is_constructible::value, int > = 0 > +void to_json(BasicJsonType& j, const std::pair& p) { j = { p.first, p.second }; } @@ -3654,10 +3766,10 @@ void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence j = { std::get(t)... }; } -template -void to_json(BasicJsonType& j, const std::tuple& t) +template::value, int > = 0> +void to_json(BasicJsonType& j, const T& t) { - to_json_tuple_impl(j, t, index_sequence_for {}); + to_json_tuple_impl(j, t, make_index_sequence::value> {}); } struct to_json_fn @@ -3882,9 +3994,8 @@ class input_stream_adapter : public input_adapter_protocol class input_buffer_adapter : public input_adapter_protocol { public: - JSON_HEDLEY_NON_NULL(2) input_buffer_adapter(const char* b, const std::size_t l) noexcept - : cursor(b), limit(b + l) + : cursor(b), limit(b == nullptr ? nullptr : (b + l)) {} // delete because of pointer members @@ -3898,6 +4009,7 @@ class input_buffer_adapter : public input_adapter_protocol { if (JSON_HEDLEY_LIKELY(cursor < limit)) { + assert(cursor != nullptr and limit != nullptr); return std::char_traits::to_int_type(*(cursor++)); } @@ -5675,7 +5787,7 @@ class binary_reader const int exp = (half >> 10u) & 0x1Fu; const unsigned int mant = half & 0x3FFu; assert(0 <= exp and exp <= 32); - assert(0 <= mant and mant <= 1024); + assert(mant <= 1024); switch (exp) { case 0: @@ -6957,7 +7069,7 @@ class binary_reader /*! @param[in] format the current format @param[in] detail a detailed error message - @param[in] context further contect information + @param[in] context further context information @return a message string to use in the parse_error exceptions */ std::string exception_message(const input_format_t format, @@ -9315,8 +9427,8 @@ class iter_impl /*! @brief const copy constructor @param[in] other const iterator to copy from - @note This copy constuctor had to be defined explicitely to circumvent a bug - occuring on msvc v19.0 compiler (VS 2015) debug build. For more + @note This copy constructor had to be defined explicitly to circumvent a bug + occurring on msvc v19.0 compiler (VS 2015) debug build. For more information refer to: https://github.com/nlohmann/json/issues/1608 */ iter_impl(const iter_impl& other) noexcept @@ -10088,7 +10200,7 @@ class json_pointer /*! @brief append an array index at the end of this JSON pointer - @param[in] array_index array index ot append + @param[in] array_index array index to append @return JSON pointer with @a array_index appended @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add} @@ -10229,7 +10341,7 @@ class json_pointer @since version 3.6.0 */ - const std::string& back() + const std::string& back() const { if (JSON_HEDLEY_UNLIKELY(empty())) { @@ -12041,13 +12153,12 @@ class binary_writer */ static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value) { - std::size_t embedded_document_size = 0ul; std::size_t array_index = 0ul; - for (const auto& el : value) + const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), 0ul, [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el) { - embedded_document_size += calc_bson_element_size(std::to_string(array_index++), el); - } + return result + calc_bson_element_size(std::to_string(array_index++), el); + }); return sizeof(std::int32_t) + embedded_document_size + 1ul; } @@ -12868,7 +12979,7 @@ inline cached_power get_cached_power_for_binary_exponent(int e) // ==> 2^(q - 1 + alpha) <= c * 2^(e + q) // ==> 2^(alpha - e - 1) <= c // - // If c were an exakt power of ten, i.e. c = 10^k, one may determine k as + // If c were an exact power of ten, i.e. c = 10^k, one may determine k as // // k = ceil( log_10( 2^(alpha - e - 1) ) ) // = ceil( (alpha - e - 1) * log_10(2) ) @@ -14264,7 +14375,7 @@ class serializer if (is_negative) { *buffer_ptr = '-'; - abs_value = static_cast(std::abs(static_cast(x))); + abs_value = remove_sign(x); // account one more byte for the minus sign n_chars = 1 + count_digits(abs_value); @@ -14445,6 +14556,32 @@ class serializer return state; } + /* + * Overload to make the compiler happy while it is instantiating + * dump_integer for number_unsigned_t. + * Must never be called. + */ + number_unsigned_t remove_sign(number_unsigned_t x) + { + assert(false); // LCOV_EXCL_LINE + return x; // LCOV_EXCL_LINE + } + + /* + * Helper function for dump_integer + * + * This function takes a negative signed integer and returns its absolute + * value as unsigned integer. The plus/minus shuffling is necessary as we can + * not directly remove the sign of an arbitrary signed integer as the + * absolute values of INT_MIN and INT_MAX are usually not the same. See + * #1708 for details. + */ + inline number_unsigned_t remove_sign(number_integer_t x) noexcept + { + assert(x < 0 and x < (std::numeric_limits::max)()); + return static_cast(-(x + 1)) + 1; + } + private: /// the output of the serializer output_adapter_t o = nullptr; @@ -15359,7 +15496,7 @@ class basic_json object = nullptr; // silence warning, see #821 if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) { - JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.7.0")); // LCOV_EXCL_LINE + JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.7.1")); // LCOV_EXCL_LINE } break; } @@ -17039,11 +17176,11 @@ class basic_json detail::has_non_default_from_json::value, int> = 0> ValueType get() const noexcept(noexcept( - JSONSerializer::from_json(std::declval()))) + JSONSerializer::from_json(std::declval()))) { static_assert(not std::is_reference::value, "get() cannot be used with reference types, you might want to use get_ref()"); - return JSONSerializer::from_json(*this); + return JSONSerializer::from_json(*this); } /*! @@ -18416,7 +18553,7 @@ class basic_json @since version 3.6.0 */ template::value, int>::type = 0> + not std::is_same::type, json_pointer>::value, int>::type = 0> bool contains(KeyT && key) const { return is_object() and m_value.object->find(std::forward(key)) != m_value.object->end(); @@ -18425,7 +18562,7 @@ class basic_json /*! @brief check the existence of an element in a JSON object given a JSON pointer - Check wehther the given JSON pointer @a ptr can be resolved in the current + Check whether the given JSON pointer @a ptr can be resolved in the current JSON value. @note This method can be executed on any JSON value type. @@ -22468,7 +22605,7 @@ struct hash /// @note: do not remove the space after '<', /// see https://github.com/nlohmann/json/pull/679 template<> -struct less< ::nlohmann::detail::value_t> +struct less<::nlohmann::detail::value_t> { /*! @brief compare two value_t enum values @@ -22563,6 +22700,7 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std #undef JSON_HEDLEY_ARRAY_PARAM #undef JSON_HEDLEY_ASSUME #undef JSON_HEDLEY_BEGIN_C_DECLS +#undef JSON_HEDLEY_C_DECL #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE #undef JSON_HEDLEY_CLANG_HAS_BUILTIN #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE @@ -22575,21 +22713,23 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std #undef JSON_HEDLEY_CONCAT #undef JSON_HEDLEY_CONCAT_EX #undef JSON_HEDLEY_CONST -#undef JSON_HEDLEY_CONSTEXPR #undef JSON_HEDLEY_CONST_CAST +#undef JSON_HEDLEY_CONSTEXPR #undef JSON_HEDLEY_CPP_CAST #undef JSON_HEDLEY_CRAY_VERSION #undef JSON_HEDLEY_CRAY_VERSION_CHECK -#undef JSON_HEDLEY_C_DECL #undef JSON_HEDLEY_DEPRECATED #undef JSON_HEDLEY_DEPRECATED_FOR #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS #undef JSON_HEDLEY_DIAGNOSTIC_POP #undef JSON_HEDLEY_DIAGNOSTIC_PUSH #undef JSON_HEDLEY_DMC_VERSION #undef JSON_HEDLEY_DMC_VERSION_CHECK +#undef JSON_HEDLEY_EMPTY_BASES #undef JSON_HEDLEY_EMSCRIPTEN_VERSION #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK #undef JSON_HEDLEY_END_C_DECLS @@ -22618,6 +22758,7 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std #undef JSON_HEDLEY_HAS_ATTRIBUTE #undef JSON_HEDLEY_HAS_BUILTIN #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE #undef JSON_HEDLEY_HAS_EXTENSION #undef JSON_HEDLEY_HAS_FEATURE @@ -22631,15 +22772,18 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std #undef JSON_HEDLEY_INTEL_VERSION #undef JSON_HEDLEY_INTEL_VERSION_CHECK #undef JSON_HEDLEY_IS_CONSTANT +#undef JSON_HEDLEY_IS_CONSTEXPR_ #undef JSON_HEDLEY_LIKELY #undef JSON_HEDLEY_MALLOC #undef JSON_HEDLEY_MESSAGE #undef JSON_HEDLEY_MSVC_VERSION #undef JSON_HEDLEY_MSVC_VERSION_CHECK #undef JSON_HEDLEY_NEVER_INLINE +#undef JSON_HEDLEY_NO_ESCAPE #undef JSON_HEDLEY_NON_NULL #undef JSON_HEDLEY_NO_RETURN #undef JSON_HEDLEY_NO_THROW +#undef JSON_HEDLEY_NULL #undef JSON_HEDLEY_PELLES_VERSION #undef JSON_HEDLEY_PELLES_VERSION_CHECK #undef JSON_HEDLEY_PGI_VERSION diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b73dfc9a..762e5582 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -6,7 +6,7 @@ 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 "-g -O2 -fsanitize=address -fsanitize=undefined -fsanitize=integer -fsanitize=nullability -fno-omit-frame-pointer") + set(CMAKE_CXX_FLAGS "-g -O0 -fsanitize=address -fsanitize=undefined -fsanitize=integer -fsanitize=nullability -fno-omit-frame-pointer -fno-sanitize-recover=all -fsanitize-recover=unsigned-integer-overflow") endif() endif() @@ -71,7 +71,7 @@ set_target_properties(doctest_main PROPERTIES COMPILE_DEFINITIONS "$<$:_SCL_SECURE_NO_WARNINGS>" COMPILE_OPTIONS "$<$:/EHsc;$<$:/Od>>" ) -if (${CMAKE_VERSION} VERSION_LESS "3.8.0") +if (${CMAKE_VERSION} VERSION_LESS "3.8.0") target_compile_features(doctest_main PUBLIC cxx_range_for) else() target_compile_features(doctest_main PUBLIC cxx_std_11) @@ -92,7 +92,7 @@ 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::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() @@ -101,7 +101,49 @@ endif() # one executable for each unit test file ############################################################################# -file(GLOB files "src/unit-*.cpp") +set(files + src/unit-algorithms.cpp + src/unit-allocator.cpp + src/unit-alt-string.cpp + src/unit-bson.cpp + src/unit-capacity.cpp + src/unit-cbor.cpp + src/unit-class_const_iterator.cpp + src/unit-class_iterator.cpp + src/unit-class_lexer.cpp + src/unit-class_parser.cpp + src/unit-comparison.cpp + src/unit-concepts.cpp + src/unit-constructor1.cpp + src/unit-constructor2.cpp + src/unit-convenience.cpp + src/unit-conversions.cpp + src/unit-deserialization.cpp + src/unit-element_access1.cpp + src/unit-element_access2.cpp + src/unit-inspection.cpp + src/unit-items.cpp + src/unit-iterators1.cpp + src/unit-iterators2.cpp + src/unit-json_patch.cpp + src/unit-json_pointer.cpp + src/unit-merge_patch.cpp + src/unit-meta.cpp + src/unit-modifiers.cpp + src/unit-msgpack.cpp + src/unit-noexcept.cpp + src/unit-pointer_access.cpp + src/unit-readme.cpp + src/unit-reference_access.cpp + src/unit-regression.cpp + src/unit-serialization.cpp + src/unit-testsuites.cpp + src/unit-to_chars.cpp + src/unit-ubjson.cpp + src/unit-udt.cpp + src/unit-unicode.cpp + src/unit-wstring.cpp) + foreach(file ${files}) get_filename_component(file_basename ${file} NAME_WE) string(REGEX REPLACE "unit-([^$]+)" "test-\\1" testcase ${file_basename}) diff --git a/test/cmake_import/CMakeLists.txt b/test/cmake_import/CMakeLists.txt index 911c342c..24d4a33a 100644 --- a/test/cmake_import/CMakeLists.txt +++ b/test/cmake_import/CMakeLists.txt @@ -1,6 +1,7 @@ add_test(NAME cmake_import_configure COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" + -A "${CMAKE_GENERATOR_PLATFORM}" -Dnlohmann_json_DIR=${PROJECT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/project ) diff --git a/test/cmake_import_minver/CMakeLists.txt b/test/cmake_import_minver/CMakeLists.txt index 8cef2fab..2efcd85f 100644 --- a/test/cmake_import_minver/CMakeLists.txt +++ b/test/cmake_import_minver/CMakeLists.txt @@ -1,6 +1,7 @@ add_test(NAME cmake_import_minver_configure COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" + -A "${CMAKE_GENERATOR_PLATFORM}" -Dnlohmann_json_DIR=${PROJECT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/project ) diff --git a/test/src/UBSAN.supp b/test/src/UBSAN.supp new file mode 100644 index 00000000..b19f0436 --- /dev/null +++ b/test/src/UBSAN.supp @@ -0,0 +1 @@ +unsigned-integer-overflow:stl_bvector.h diff --git a/test/src/fuzzer-driver_afl.cpp b/test/src/fuzzer-driver_afl.cpp index 9aa05abd..7f2d645b 100644 --- a/test/src/fuzzer-driver_afl.cpp +++ b/test/src/fuzzer-driver_afl.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (fuzz test support) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json This file implements a driver for American Fuzzy Lop (afl-fuzz). It relies on diff --git a/test/src/fuzzer-parse_bson.cpp b/test/src/fuzzer-parse_bson.cpp index 54ceba37..a38062e2 100644 --- a/test/src/fuzzer-parse_bson.cpp +++ b/test/src/fuzzer-parse_bson.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (fuzz test support) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json This file implements a parser test suitable for fuzz testing. Given a byte diff --git a/test/src/fuzzer-parse_cbor.cpp b/test/src/fuzzer-parse_cbor.cpp index 3dbc7450..4038bc90 100644 --- a/test/src/fuzzer-parse_cbor.cpp +++ b/test/src/fuzzer-parse_cbor.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (fuzz test support) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json This file implements a parser test suitable for fuzz testing. Given a byte diff --git a/test/src/fuzzer-parse_json.cpp b/test/src/fuzzer-parse_json.cpp index fb32933d..78179c16 100644 --- a/test/src/fuzzer-parse_json.cpp +++ b/test/src/fuzzer-parse_json.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (fuzz test support) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json This file implements a parser test suitable for fuzz testing. Given a byte diff --git a/test/src/fuzzer-parse_msgpack.cpp b/test/src/fuzzer-parse_msgpack.cpp index 2f03ec8e..b14cbed9 100644 --- a/test/src/fuzzer-parse_msgpack.cpp +++ b/test/src/fuzzer-parse_msgpack.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (fuzz test support) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json This file implements a parser test suitable for fuzz testing. Given a byte diff --git a/test/src/fuzzer-parse_ubjson.cpp b/test/src/fuzzer-parse_ubjson.cpp index 178bc9a4..cb43cb92 100644 --- a/test/src/fuzzer-parse_ubjson.cpp +++ b/test/src/fuzzer-parse_ubjson.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (fuzz test support) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json This file implements a parser test suitable for fuzz testing. Given a byte diff --git a/test/src/unit-algorithms.cpp b/test/src/unit-algorithms.cpp index 14a55aa2..87773439 100644 --- a/test/src/unit-algorithms.cpp +++ b/test/src/unit-algorithms.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-allocator.cpp b/test/src/unit-allocator.cpp index f7e8b201..b643bd6e 100644 --- a/test/src/unit-allocator.cpp +++ b/test/src/unit-allocator.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-alt-string.cpp b/test/src/unit-alt-string.cpp index 6a9e36a3..68efa641 100644 --- a/test/src/unit-alt-string.cpp +++ b/test/src/unit-alt-string.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . @@ -38,6 +38,7 @@ SOFTWARE. /* forward declarations */ class alt_string; bool operator<(const char* op1, const alt_string& op2); +void int_to_string(alt_string& target, std::size_t value); /* * This is virtually a string class. @@ -154,6 +155,11 @@ class alt_string friend bool ::operator<(const char*, const alt_string&); }; +void int_to_string(alt_string& target, std::size_t value) +{ + target = std::to_string(value).c_str(); +} + using alt_json = nlohmann::basic_json < std::map, std::vector, @@ -232,6 +238,35 @@ TEST_CASE("alternative string type") CHECK(dump == R"({"foo":"bar"})"); } + SECTION("items") + { + auto doc = alt_json::parse("{\"foo\": \"bar\"}"); + + for ( auto item : doc.items() ) + { + CHECK( item.key() == "foo" ); + CHECK( item.value() == "bar" ); + } + + auto doc_array = alt_json::parse("[\"foo\", \"bar\"]"); + + for ( auto item : doc_array.items() ) + { + if (item.key() == "0" ) + { + CHECK( item.value() == "foo" ); + } + else if (item.key() == "1" ) + { + CHECK( item.value() == "bar" ); + } + else + { + CHECK( false ); + } + } + } + SECTION("equality") { alt_json doc; diff --git a/test/src/unit-bson.cpp b/test/src/unit-bson.cpp index ee5bf06d..cbfbf5ac 100644 --- a/test/src/unit-bson.cpp +++ b/test/src/unit-bson.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . @@ -584,10 +584,9 @@ TEST_CASE("BSON input/output_adapters") { SECTION("std::ostringstream") { - std::ostringstream ss; + std::basic_ostringstream ss; json::to_bson(json_representation, ss); - std::istringstream iss(ss.str()); - json j3 = json::from_bson(iss); + json j3 = json::from_bson(ss.str()); CHECK(json_representation == j3); } diff --git a/test/src/unit-capacity.cpp b/test/src/unit-capacity.cpp index d01ddb4f..78af4815 100644 --- a/test/src/unit-capacity.cpp +++ b/test/src/unit-capacity.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index 399eed28..65fd0ac4 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . @@ -1287,7 +1287,7 @@ TEST_CASE("CBOR") } } - SECTION("additonal deserialization") + SECTION("additional deserialization") { SECTION("0x7b (string)") { @@ -1580,7 +1580,7 @@ TEST_CASE("single CBOR roundtrip") { SECTION("std::ostringstream") { - std::ostringstream ss; + std::basic_ostringstream ss; json::to_cbor(j1, ss); json j3 = json::from_cbor(ss.str()); CHECK(j1 == j3); diff --git a/test/src/unit-class_const_iterator.cpp b/test/src/unit-class_const_iterator.cpp index 6294de31..98f01286 100644 --- a/test/src/unit-class_const_iterator.cpp +++ b/test/src/unit-class_const_iterator.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-class_iterator.cpp b/test/src/unit-class_iterator.cpp index be9bcd97..f389b814 100644 --- a/test/src/unit-class_iterator.cpp +++ b/test/src/unit-class_iterator.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-class_lexer.cpp b/test/src/unit-class_lexer.cpp index bdc1e2f2..5b7d6f8e 100644 --- a/test/src/unit-class_lexer.cpp +++ b/test/src/unit-class_lexer.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-class_parser.cpp b/test/src/unit-class_parser.cpp index 098920fd..b6f0adc3 100644 --- a/test/src/unit-class_parser.cpp +++ b/test/src/unit-class_parser.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . @@ -210,7 +210,7 @@ json parser_helper(const std::string& s) json j; json::parser(nlohmann::detail::input_adapter(s)).parse(true, j); - // if this line was reached, no exception ocurred + // if this line was reached, no exception occurred // -> check if result is the same without exceptions json j_nothrow; CHECK_NOTHROW(json::parser(nlohmann::detail::input_adapter(s), nullptr, false).parse(true, j_nothrow)); diff --git a/test/src/unit-comparison.cpp b/test/src/unit-comparison.cpp index 655fd269..ea04a03a 100644 --- a/test/src/unit-comparison.cpp +++ b/test/src/unit-comparison.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-concepts.cpp b/test/src/unit-concepts.cpp index 4228e18a..dd843372 100644 --- a/test/src/unit-concepts.cpp +++ b/test/src/unit-concepts.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-constructor1.cpp b/test/src/unit-constructor1.cpp index b66044ac..a1d62f91 100644 --- a/test/src/unit-constructor1.cpp +++ b/test/src/unit-constructor1.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-constructor2.cpp b/test/src/unit-constructor2.cpp index e13b5c1c..563ebebc 100644 --- a/test/src/unit-constructor2.cpp +++ b/test/src/unit-constructor2.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-convenience.cpp b/test/src/unit-convenience.cpp index e75261a9..886ca2da 100644 --- a/test/src/unit-convenience.cpp +++ b/test/src/unit-convenience.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-conversions.cpp b/test/src/unit-conversions.cpp index 9d48e29d..ced7064a 100644 --- a/test/src/unit-conversions.cpp +++ b/test/src/unit-conversions.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-deserialization.cpp b/test/src/unit-deserialization.cpp index dcc20492..4bc0f35f 100644 --- a/test/src/unit-deserialization.cpp +++ b/test/src/unit-deserialization.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-element_access1.cpp b/test/src/unit-element_access1.cpp index 58f2d016..f3d69af4 100644 --- a/test/src/unit-element_access1.cpp +++ b/test/src/unit-element_access1.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-element_access2.cpp b/test/src/unit-element_access2.cpp index 43b1368b..32070974 100644 --- a/test/src/unit-element_access2.cpp +++ b/test/src/unit-element_access2.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-inspection.cpp b/test/src/unit-inspection.cpp index d8577359..9fa944d4 100644 --- a/test/src/unit-inspection.cpp +++ b/test/src/unit-inspection.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-items.cpp b/test/src/unit-items.cpp index e94aa0ae..d5bda1b3 100644 --- a/test/src/unit-items.cpp +++ b/test/src/unit-items.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-iterators1.cpp b/test/src/unit-iterators1.cpp index 33634756..9c9d7205 100644 --- a/test/src/unit-iterators1.cpp +++ b/test/src/unit-iterators1.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-iterators2.cpp b/test/src/unit-iterators2.cpp index de4f6ff9..577071e7 100644 --- a/test/src/unit-iterators2.cpp +++ b/test/src/unit-iterators2.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-json_patch.cpp b/test/src/unit-json_patch.cpp index 7310db28..51de2f9a 100644 --- a/test/src/unit-json_patch.cpp +++ b/test/src/unit-json_patch.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-json_pointer.cpp b/test/src/unit-json_pointer.cpp index 9746d80d..ce18f342 100644 --- a/test/src/unit-json_pointer.cpp +++ b/test/src/unit-json_pointer.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . @@ -559,6 +559,10 @@ TEST_CASE("JSON pointers") CHECK(!ptr.empty()); CHECK(j[ptr] == j["answer"]["everything"]); + // check access via const pointer + const auto cptr = ptr; + CHECK(cptr.back() == "everything"); + ptr.pop_back(); ptr.pop_back(); CHECK(ptr.empty()); diff --git a/test/src/unit-merge_patch.cpp b/test/src/unit-merge_patch.cpp index 99840335..ab3acbec 100644 --- a/test/src/unit-merge_patch.cpp +++ b/test/src/unit-merge_patch.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-meta.cpp b/test/src/unit-meta.cpp index a674060f..2a111730 100644 --- a/test/src/unit-meta.cpp +++ b/test/src/unit-meta.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . @@ -43,10 +43,10 @@ TEST_CASE("version information") CHECK(j["url"] == "https://github.com/nlohmann/json"); CHECK(j["version"] == json( { - {"string", "3.7.0"}, + {"string", "3.7.1"}, {"major", 3}, {"minor", 7}, - {"patch", 0} + {"patch", 1} })); CHECK(j.find("platform") != j.end()); diff --git a/test/src/unit-modifiers.cpp b/test/src/unit-modifiers.cpp index cc04cc3b..1336c07b 100644 --- a/test/src/unit-modifiers.cpp +++ b/test/src/unit-modifiers.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-msgpack.cpp b/test/src/unit-msgpack.cpp index 09ff7c51..bcd88f35 100644 --- a/test/src/unit-msgpack.cpp +++ b/test/src/unit-msgpack.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . @@ -1334,7 +1334,7 @@ TEST_CASE("single MessagePack roundtrip") { SECTION("std::ostringstream") { - std::ostringstream ss; + std::basic_ostringstream ss; json::to_msgpack(j1, ss); json j3 = json::from_msgpack(ss.str()); CHECK(j1 == j3); @@ -1359,7 +1359,7 @@ TEST_CASE("MessagePack roundtrips" * doctest::skip()) { SECTION("input from msgpack-python") { - // most of these are exluded due to differences in key order (not a real problem) + // most of these are excluded due to differences in key order (not a real problem) auto exclude_packed = std::set { "test/data/json.org/1.json", diff --git a/test/src/unit-noexcept.cpp b/test/src/unit-noexcept.cpp index 8e46f325..d551bb86 100644 --- a/test/src/unit-noexcept.cpp +++ b/test/src/unit-noexcept.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-pointer_access.cpp b/test/src/unit-pointer_access.cpp index a35675e6..0cd4d86a 100644 --- a/test/src/unit-pointer_access.cpp +++ b/test/src/unit-pointer_access.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-readme.cpp b/test/src/unit-readme.cpp index 5b925e32..56449381 100644 --- a/test/src/unit-readme.cpp +++ b/test/src/unit-readme.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-reference_access.cpp b/test/src/unit-reference_access.cpp index bb7acda7..f26ab9cf 100644 --- a/test/src/unit-reference_access.cpp +++ b/test/src/unit-reference_access.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 866a985b..f0be3132 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . @@ -159,12 +159,55 @@ bool operator==(Data const& lhs, Data const& rhs) using float_json = nlohmann::basic_json; +///////////////////////////////////////////////////////////////////// +// for #1647 +///////////////////////////////////////////////////////////////////// +namespace +{ +struct NonDefaultFromJsonStruct { }; + +inline bool operator== (NonDefaultFromJsonStruct const&, NonDefaultFromJsonStruct const&) +{ + return true; +} + +enum class for_1647 { one, two }; + +NLOHMANN_JSON_SERIALIZE_ENUM(for_1647, +{ + {for_1647::one, "one"}, + {for_1647::two, "two"}, +}) +} + +namespace nlohmann +{ +template <> +struct adl_serializer +{ + static NonDefaultFromJsonStruct from_json (json const&) noexcept + { + return {}; + } +}; +} + +///////////////////////////////////////////////////////////////////// +// for #1805 +///////////////////////////////////////////////////////////////////// + +struct NotSerializableData +{ + int mydata; + float myfloat; +}; + TEST_CASE("regression tests") { SECTION("issue #60 - Double quotation mark is not parsed correctly") { - SECTION("escape_dobulequote") + SECTION("escape_doublequote") { auto s = "[\"\\\"foo\\\"\"]"; json j = json::parse(s); @@ -1739,31 +1782,37 @@ TEST_CASE("regression tests") { SECTION("a bunch of -1, ensure_ascii=true") { + const auto length = 300; + json dump_test; - std::vector data(300, -1); - std::vector vec_string(300, "\\ufffd"); - std::string s{data.data(), data.size()}; - dump_test["1"] = s; - std::ostringstream os; - os << "{\"1\":\""; - std::copy( vec_string.begin(), vec_string.end(), std::ostream_iterator(os)); - os << "\"}"; - s = dump_test.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace); - CHECK(s == os.str()); + dump_test["1"] = std::string(length, -1); + + std::string expected = "{\"1\":\""; + for (int i = 0; i < length; ++i) + { + expected += "\\ufffd"; + } + expected += "\"}"; + + auto s = dump_test.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace); + CHECK(s == expected); } SECTION("a bunch of -2, ensure_ascii=false") { + const auto length = 500; + json dump_test; - std::vector data(500, -2); - std::vector vec_string(500, "\xEF\xBF\xBD"); - std::string s{data.data(), data.size()}; - dump_test["1"] = s; - std::ostringstream os; - os << "{\"1\":\""; - std::copy( vec_string.begin(), vec_string.end(), std::ostream_iterator(os)); - os << "\"}"; - s = dump_test.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace); - CHECK(s == os.str()); + dump_test["1"] = std::string(length, -2); + + std::string expected = "{\"1\":\""; + for (int i = 0; i < length; ++i) + { + expected += "\xEF\xBF\xBD"; + } + expected += "\"}"; + + auto s = dump_test.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace); + CHECK(s == expected); } SECTION("test case in issue #1445") { @@ -1802,6 +1851,51 @@ TEST_CASE("regression tests") json j = json::parse("[-9223372036854775808]"); CHECK(j.dump() == "[-9223372036854775808]"); } + + SECTION("issue #1708 - minimum value of int64_t can be outputted") + { + constexpr auto smallest = (std::numeric_limits::min)(); + json j = smallest; + CHECK(j.dump() == std::to_string(smallest)); + } + + SECTION("issue #1727 - Contains with non-const lvalue json_pointer picks the wrong overload") + { + json j = {{"root", {{"settings", {{"logging", true}}}}}}; + + auto jptr1 = "/root/settings/logging"_json_pointer; + auto jptr2 = json::json_pointer{"/root/settings/logging"}; + + CHECK(j.contains(jptr1)); + CHECK(j.contains(jptr2)); + } + + SECTION("issue #1647 - compile error when deserializing enum if both non-default from_json and non-member operator== exists for other type") + { + { + json j; + NonDefaultFromJsonStruct x = j; + NonDefaultFromJsonStruct y; + CHECK(x == y); + } + + auto val = nlohmann::json("one").get(); + CHECK(val == for_1647::one); + json j = val; + } + + SECTION("issue #1805 - A pair is json constructible only if T1 and T2 are json constructible") + { + static_assert(!std::is_constructible>::value, ""); + static_assert(!std::is_constructible>::value, ""); + static_assert(std::is_constructible>::value, ""); + } + SECTION("issue #1825 - A tuple is json constructible only if all T in Args are json constructible") + { + static_assert(!std::is_constructible>::value, ""); + static_assert(!std::is_constructible>::value, ""); + static_assert(std::is_constructible>::value, ""); + } } #if not defined(JSON_NOEXCEPTION) diff --git a/test/src/unit-serialization.cpp b/test/src/unit-serialization.cpp index 3a0b28e4..9620e3a8 100644 --- a/test/src/unit-serialization.cpp +++ b/test/src/unit-serialization.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . @@ -189,3 +189,20 @@ TEST_CASE("serialization") test("[3,\"false\",false]", "[3,\\\"false\\\",false]"); } } + +TEST_CASE_TEMPLATE("serialization for extreme integer values", T, int32_t, uint32_t, int64_t, uint64_t) +{ + SECTION("minimum") + { + constexpr auto minimum = (std::numeric_limits::min)(); + json j = minimum; + CHECK(j.dump() == std::to_string(minimum)); + } + + SECTION("maximum") + { + constexpr auto maximum = (std::numeric_limits::max)(); + json j = maximum; + CHECK(j.dump() == std::to_string(maximum)); + } +} diff --git a/test/src/unit-testsuites.cpp b/test/src/unit-testsuites.cpp index 7f612381..91fd8482 100644 --- a/test/src/unit-testsuites.cpp +++ b/test/src/unit-testsuites.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-to_chars.cpp b/test/src/unit-to_chars.cpp index ae96ca45..6ff5cd10 100644 --- a/test/src/unit-to_chars.cpp +++ b/test/src/unit-to_chars.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-ubjson.cpp b/test/src/unit-ubjson.cpp index f8220106..753bb483 100644 --- a/test/src/unit-ubjson.cpp +++ b/test/src/unit-ubjson.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit-udt.cpp b/test/src/unit-udt.cpp index 41c952e5..eea54718 100644 --- a/test/src/unit-udt.cpp +++ b/test/src/unit-udt.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . @@ -238,7 +238,7 @@ void from_json(const nlohmann::json& j, contact_book& cb) TEST_CASE("basic usage" * doctest::test_suite("udt")) { - // a bit narcissic maybe :) ? + // a bit narcissistic maybe :) ? const udt::age a { 23 diff --git a/test/src/unit-unicode.cpp b/test/src/unit-unicode.cpp index 4663f9c8..50d1f2a1 100644 --- a/test/src/unit-unicode.cpp +++ b/test/src/unit-unicode.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . @@ -1152,7 +1152,7 @@ TEST_CASE("Unicode" * doctest::skip()) json j; CHECK_NOTHROW(f >> j); - // the array has 1112064 + 1 elemnts (a terminating "null" value) + // the array has 1112064 + 1 elements (a terminating "null" value) // Note: 1112064 = 0x1FFFFF code points - 2048 invalid values between // 0xD800 and 0xDFFF. CHECK(j.size() == 1112065); diff --git a/test/src/unit-wstring.cpp b/test/src/unit-wstring.cpp index ad207092..c8dadb29 100644 --- a/test/src/unit-wstring.cpp +++ b/test/src/unit-wstring.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/src/unit.cpp b/test/src/unit.cpp index e6ebffb5..3930fc42 100644 --- a/test/src/unit.cpp +++ b/test/src/unit.cpp @@ -1,7 +1,7 @@ /* __ _____ _____ _____ __| | __| | | | JSON for Modern C++ (test suite) -| | |__ | | | | | | version 3.7.0 +| | |__ | | | | | | version 3.7.1 |_____|_____|_____|_|___| https://github.com/nlohmann/json Licensed under the MIT License . diff --git a/test/thirdparty/doctest/doctest.h b/test/thirdparty/doctest/doctest.h old mode 100644 new mode 100755 index dbbcd3f5..8b76419a --- a/test/thirdparty/doctest/doctest.h +++ b/test/thirdparty/doctest/doctest.h @@ -48,8 +48,8 @@ #define DOCTEST_VERSION_MAJOR 2 #define DOCTEST_VERSION_MINOR 3 -#define DOCTEST_VERSION_PATCH 1 -#define DOCTEST_VERSION_STR "2.3.1" +#define DOCTEST_VERSION_PATCH 5 +#define DOCTEST_VERSION_STR "2.3.5" #define DOCTEST_VERSION \ (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH) @@ -214,7 +214,8 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom constr DOCTEST_MSVC_SUPPRESS_WARNING(5026) \ DOCTEST_MSVC_SUPPRESS_WARNING(4623) \ DOCTEST_MSVC_SUPPRESS_WARNING(5039) \ - DOCTEST_MSVC_SUPPRESS_WARNING(5045) + DOCTEST_MSVC_SUPPRESS_WARNING(5045) \ + DOCTEST_MSVC_SUPPRESS_WARNING(5105) #define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END DOCTEST_MSVC_SUPPRESS_WARNING_POP @@ -227,7 +228,7 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom constr // GCC C++11 feature support table: https://gcc.gnu.org/projects/cxx-status.html // MSVC version table: // https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering -// MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019) << NOT YET RELEASED - April 2 2019 +// MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019) // MSVC++ 14.1 (15) _MSC_VER == 1910 (Visual Studio 2017) // MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015) // MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013) @@ -306,10 +307,6 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom constr #define DOCTEST_ALIGNMENT(x) __attribute__((aligned(x))) #endif // MSVC -#ifndef DOCTEST_CONFIG_NUM_CAPTURES_ON_STACK -#define DOCTEST_CONFIG_NUM_CAPTURES_ON_STACK 5 -#endif // DOCTEST_CONFIG_NUM_CAPTURES_ON_STACK - // ================================================================================================= // == FEATURE DETECTION END ======================================================================== // ================================================================================================= @@ -342,30 +339,27 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom constr #define DOCTEST_PLATFORM_LINUX #endif // DOCTEST_PLATFORM -// clang-format off -#define DOCTEST_DELETE_COPIES(type) type(const type&) = delete; type& operator=(const type&) = delete -#define DOCTEST_DECLARE_COPIES(type) type(const type&); type& operator=(const type&) -#define DOCTEST_DEFINE_COPIES(type) type::type(const type&) = default; type& type::operator=(const type&) = default -#define DOCTEST_DECLARE_DEFAULTS(type) type(); ~type() -#define DOCTEST_DEFINE_DEFAULTS(type) type::type() = default; type::~type() = default -// clang-format on - #define DOCTEST_GLOBAL_NO_WARNINGS(var) \ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-variable") \ static int var DOCTEST_UNUSED // NOLINT(fuchsia-statically-constructed-objects,cert-err58-cpp) #define DOCTEST_GLOBAL_NO_WARNINGS_END() DOCTEST_CLANG_SUPPRESS_WARNING_POP +#ifndef DOCTEST_BREAK_INTO_DEBUGGER // should probably take a look at https://github.com/scottt/debugbreak #ifdef DOCTEST_PLATFORM_MAC #define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) #elif DOCTEST_MSVC #define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak() #elif defined(__MINGW32__) +DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wredundant-decls") extern "C" __declspec(dllimport) void __stdcall DebugBreak(); +DOCTEST_GCC_SUPPRESS_WARNING_POP #define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak() #else // linux #define DOCTEST_BREAK_INTO_DEBUGGER() ((void)0) #endif // linux +#endif // DOCTEST_BREAK_INTO_DEBUGGER // this is kept here for backwards compatibility since the config option was changed #ifdef DOCTEST_CONFIG_USE_IOSFWD @@ -375,6 +369,10 @@ extern "C" __declspec(dllimport) void __stdcall DebugBreak(); #ifdef DOCTEST_CONFIG_USE_STD_HEADERS #include #include +#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) +// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183 +#include +#endif // VS 2019 #else // DOCTEST_CONFIG_USE_STD_HEADERS #if DOCTEST_CLANG @@ -393,7 +391,7 @@ extern "C" __declspec(dllimport) void __stdcall DebugBreak(); // Forward declaring 'X' in namespace std is not permitted by the C++ Standard. DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4643) -DOCTEST_STD_NAMESPACE_BEGIN +DOCTEST_STD_NAMESPACE_BEGIN // NOLINT (cert-dcl58-cpp) typedef decltype(nullptr) nullptr_t; template struct char_traits; @@ -404,6 +402,14 @@ class basic_ostream; typedef basic_ostream> ostream; template class tuple; +#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) +// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183 +template +class allocator; +template +class basic_string; +using string = basic_string, allocator>; +#endif // VS 2019 DOCTEST_STD_NAMESPACE_END DOCTEST_MSVC_SUPPRESS_WARNING_POP @@ -577,6 +583,10 @@ namespace assertType { DT_WARN_THROWS_WITH = is_throws_with | is_warn, DT_CHECK_THROWS_WITH = is_throws_with | is_check, DT_REQUIRE_THROWS_WITH = is_throws_with | is_require, + + DT_WARN_THROWS_WITH_AS = is_throws_with | is_throws_as | is_warn, + DT_CHECK_THROWS_WITH_AS = is_throws_with | is_throws_as | is_check, + DT_REQUIRE_THROWS_WITH_AS = is_throws_with | is_throws_as | is_require, DT_WARN_NOTHROW = is_nothrow | is_warn, DT_CHECK_NOTHROW = is_nothrow | is_check, @@ -632,9 +642,6 @@ struct DOCTEST_INTERFACE TestCaseData bool m_should_fail; int m_expected_failures; double m_timeout; - - DOCTEST_DECLARE_DEFAULTS(TestCaseData); - DOCTEST_DECLARE_COPIES(TestCaseData); }; struct DOCTEST_INTERFACE AssertData @@ -657,9 +664,7 @@ struct DOCTEST_INTERFACE AssertData // for specific exception-related asserts bool m_threw_as; const char* m_exception_type; - - DOCTEST_DECLARE_DEFAULTS(AssertData); - DOCTEST_DELETE_COPIES(AssertData); + const char* m_exception_string; }; struct DOCTEST_INTERFACE MessageData @@ -668,9 +673,6 @@ struct DOCTEST_INTERFACE MessageData const char* m_file; int m_line; assertType::Enum m_severity; - - DOCTEST_DECLARE_DEFAULTS(MessageData); - DOCTEST_DELETE_COPIES(MessageData); }; struct DOCTEST_INTERFACE SubcaseSignature @@ -679,18 +681,11 @@ struct DOCTEST_INTERFACE SubcaseSignature const char* m_file; int m_line; - SubcaseSignature(const char* name, const char* file, int line); - bool operator<(const SubcaseSignature& other) const; - - DOCTEST_DECLARE_DEFAULTS(SubcaseSignature); - DOCTEST_DECLARE_COPIES(SubcaseSignature); }; struct DOCTEST_INTERFACE IContextScope { - DOCTEST_DELETE_COPIES(IContextScope); - IContextScope(); virtual ~IContextScope(); virtual void stringify(std::ostream*) const = 0; @@ -732,13 +727,10 @@ struct ContextOptions //!OCLINT too many fields bool help; // to print the help bool version; // to print the version - bool count; // if only the count of matching tests is to be retreived + bool count; // if only the count of matching tests is to be retrieved bool list_test_cases; // to list all tests matching the filters bool list_test_suites; // to list all suites matching the filters bool list_reporters; // lists all registered reporters - - DOCTEST_DECLARE_DEFAULTS(ContextOptions); - DOCTEST_DELETE_COPIES(ContextOptions); }; namespace detail { @@ -884,13 +876,16 @@ DOCTEST_INTERFACE String toString(int long long in); DOCTEST_INTERFACE String toString(int long long unsigned in); DOCTEST_INTERFACE String toString(std::nullptr_t in); +#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) +// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183 +DOCTEST_INTERFACE String toString(const std::string& in); +#endif // VS 2019 + class DOCTEST_INTERFACE Approx { public: explicit Approx(double value); - DOCTEST_DECLARE_COPIES(Approx); - Approx operator()(double value) const; #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS @@ -990,12 +985,10 @@ namespace detail { struct DOCTEST_INTERFACE TestFailureException { - DOCTEST_DECLARE_DEFAULTS(TestFailureException); - DOCTEST_DECLARE_COPIES(TestFailureException); }; DOCTEST_INTERFACE bool checkIfShouldThrow(assertType::Enum at); - + #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS [[noreturn]] #endif // DOCTEST_CONFIG_NO_EXCEPTIONS @@ -1009,8 +1002,6 @@ namespace detail { Subcase(const char* name, const char* file, int line); ~Subcase(); - DOCTEST_DELETE_COPIES(Subcase); - operator bool() const; }; @@ -1049,9 +1040,6 @@ namespace detail { Result(bool passed, const String& decomposition = String()); - DOCTEST_DECLARE_DEFAULTS(Result); - DOCTEST_DECLARE_COPIES(Result); - // forbidding some expressions based on this table: http://en.cppreference.com/w/cpp/language/operator_precedence DOCTEST_FORBIT_EXPRESSION(Result, &) DOCTEST_FORBIT_EXPRESSION(Result, ^) @@ -1213,9 +1201,6 @@ namespace detail { ExpressionDecomposer(assertType::Enum at); - DOCTEST_DECLARE_DEFAULTS(ExpressionDecomposer); - DOCTEST_DELETE_COPIES(ExpressionDecomposer); - // The right operator for capturing expressions is "<=" instead of "<<" (based on the operator precedence table) // but then there will be warnings from GCC about "-Wparentheses" and since "_Pragma()" is problematic this will stay for now... // https://github.com/catchorg/Catch2/issues/870 @@ -1236,9 +1221,6 @@ namespace detail { int m_expected_failures; double m_timeout; - DOCTEST_DECLARE_DEFAULTS(TestSuite); - DOCTEST_DECLARE_COPIES(TestSuite); - TestSuite& operator*(const char* in); template @@ -1261,8 +1243,6 @@ namespace detail { TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite, const char* type = "", int template_id = -1); - DOCTEST_DECLARE_DEFAULTS(TestCase); - TestCase(const TestCase& other); DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function @@ -1285,6 +1265,9 @@ namespace detail { DOCTEST_INTERFACE int setTestSuite(const TestSuite& ts); DOCTEST_INTERFACE bool isDebuggerActive(); + template + int instantiationHelper(const T&) { return 0; } + namespace binaryAssertComparison { enum Enum { @@ -1299,7 +1282,7 @@ namespace detail { // clang-format off template struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L), const DOCTEST_REF_WRAP(R) ) const { return false; } }; - + #define DOCTEST_BINARY_RELATIONAL_OP(n, op) \ template struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return op(lhs, rhs); } }; // clang-format on @@ -1314,10 +1297,7 @@ namespace detail { struct DOCTEST_INTERFACE ResultBuilder : public AssertData { ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type = ""); - - DOCTEST_DECLARE_DEFAULTS(ResultBuilder); - DOCTEST_DELETE_COPIES(ResultBuilder); + const char* exception_type = "", const char* exception_string = ""); void setResult(const Result& res); @@ -1419,8 +1399,6 @@ namespace detail { struct DOCTEST_INTERFACE IExceptionTranslator { - DOCTEST_DELETE_COPIES(IExceptionTranslator); - IExceptionTranslator(); virtual ~IExceptionTranslator(); virtual bool translate(String&) const = 0; @@ -1505,107 +1483,27 @@ namespace detail { DOCTEST_INTERFACE void toStream(std::ostream* s, int long long in); DOCTEST_INTERFACE void toStream(std::ostream* s, int long long unsigned in); - class DOCTEST_INTERFACE ContextBuilder - { - friend class ContextScope; + // ContextScope base class used to allow implementing methods of ContextScope + // that don't depend on the template parameter in doctest.cpp. + class DOCTEST_INTERFACE ContextScopeBase : public IContextScope { + protected: + ContextScopeBase(); - struct DOCTEST_INTERFACE ICapture - { - DOCTEST_DELETE_COPIES(ICapture); - ICapture(); - virtual ~ICapture(); - virtual void toStream(std::ostream*) const = 0; - }; - - template - struct Capture : public ICapture //!OCLINT destructor of virtual class - { - const T* capture; - - explicit Capture(const T* in) - : capture(in) {} - void toStream(std::ostream* s) const override { detail::toStream(s, *capture); } - }; - - struct DOCTEST_INTERFACE Chunk - { - char buf[sizeof(Capture)] DOCTEST_ALIGNMENT( - 2 * sizeof(void*)); // place to construct a Capture - - DOCTEST_DECLARE_DEFAULTS(Chunk); - DOCTEST_DELETE_COPIES(Chunk); - }; - - struct DOCTEST_INTERFACE Node - { - Chunk chunk; - Node* next; - - DOCTEST_DECLARE_DEFAULTS(Node); - DOCTEST_DELETE_COPIES(Node); - }; - - Chunk stackChunks[DOCTEST_CONFIG_NUM_CAPTURES_ON_STACK]; - int numCaptures = 0; - Node* head = nullptr; - Node* tail = nullptr; - - ContextBuilder(ContextBuilder& other); - - ContextBuilder& operator=(const ContextBuilder&) = delete; - - void stringify(std::ostream* s) const; - - public: - ContextBuilder(); - ~ContextBuilder(); - - template - DOCTEST_NOINLINE ContextBuilder& operator<<(T& in) { - Capture temp(&in); - - // construct either on stack or on heap - // copy the bytes for the whole object - including the vtable because we cant construct - // the object directly in the buffer using placement new - need the header... - if(numCaptures < DOCTEST_CONFIG_NUM_CAPTURES_ON_STACK) { - my_memcpy(stackChunks[numCaptures].buf, &temp, sizeof(Chunk)); - } else { - auto curr = new Node; - curr->next = nullptr; - if(tail) { - tail->next = curr; - tail = curr; - } else { - head = tail = curr; - } - - my_memcpy(tail->chunk.buf, &temp, sizeof(Chunk)); - } - ++numCaptures; - return *this; - } - - template - ContextBuilder& operator<<(const T&&) { - static_assert(deferred_false::value, - "Cannot pass temporaries or rvalues to the streaming operator because it " - "caches pointers to the passed objects for lazy evaluation!"); - return *this; - } + void destroy(); }; - class DOCTEST_INTERFACE ContextScope : public IContextScope + template class DOCTEST_INTERFACE ContextScope : public ContextScopeBase { - ContextBuilder contextBuilder; + const L &lambda_; public: - explicit ContextScope(ContextBuilder& temp); + explicit ContextScope(const L &lambda) : lambda_(lambda) {} - DOCTEST_DELETE_COPIES(ContextScope); + ContextScope(ContextScope &&other) : lambda_(other.lambda_) {} - ~ContextScope() override; + void stringify(std::ostream* s) const override { lambda_(s); } - void stringify(std::ostream* s) const override; + ~ContextScope() override { destroy(); } }; struct DOCTEST_INTERFACE MessageBuilder : public MessageData @@ -1616,8 +1514,6 @@ namespace detail { MessageBuilder() = delete; ~MessageBuilder(); - DOCTEST_DELETE_COPIES(MessageBuilder); - template MessageBuilder& operator<<(const T& in) { toStream(m_stream, in); @@ -1627,6 +1523,11 @@ namespace detail { bool log(); void react(); }; + + template + ContextScope MakeContextScope(const L &lambda) { + return ContextScope(lambda); + } } // namespace detail #define DOCTEST_DEFINE_DECORATOR(name, type, def) \ @@ -1686,8 +1587,6 @@ class DOCTEST_INTERFACE Context public: explicit Context(int argc = 0, const char* const* argv = nullptr); - DOCTEST_DELETE_COPIES(Context); - ~Context(); void applyCommandLine(int argc, const char* const* argv); @@ -1729,9 +1628,6 @@ struct DOCTEST_INTERFACE CurrentTestCaseStats int numAssertsFailedCurrentTest; double seconds; int failure_flags; // use TestCaseFailureReason::Enum - - DOCTEST_DECLARE_DEFAULTS(CurrentTestCaseStats); - DOCTEST_DELETE_COPIES(CurrentTestCaseStats); }; struct DOCTEST_INTERFACE TestCaseException @@ -1748,9 +1644,6 @@ struct DOCTEST_INTERFACE TestRunStats unsigned numTestCasesFailed; int numAsserts; int numAssertsFailed; - - DOCTEST_DECLARE_DEFAULTS(TestRunStats); - DOCTEST_DELETE_COPIES(TestRunStats); }; struct QueryData @@ -1776,6 +1669,8 @@ struct DOCTEST_INTERFACE IReporter // called when a test case is started (safe to cache a pointer to the input) virtual void test_case_start(const TestCaseData&) = 0; + // called when a test case is reentered because of unfinished subcases (safe to cache a pointer to the input) + virtual void test_case_reenter(const TestCaseData&) = 0; // called when a test case has ended virtual void test_case_end(const CurrentTestCaseStats&) = 0; @@ -1811,7 +1706,7 @@ struct DOCTEST_INTERFACE IReporter namespace detail { typedef IReporter* (*reporterCreatorFunc)(const ContextOptions&); - DOCTEST_INTERFACE void registerReporterImpl(const char* name, int prio, reporterCreatorFunc c); + DOCTEST_INTERFACE void registerReporterImpl(const char* name, int prio, reporterCreatorFunc c, bool isReporter); template IReporter* reporterCreator(const ContextOptions& o) { @@ -1820,8 +1715,8 @@ namespace detail { } // namespace detail template -int registerReporter(const char* name, int priority) { - detail::registerReporterImpl(name, priority, detail::reporterCreator); +int registerReporter(const char* name, int priority, bool isReporter) { + detail::registerReporterImpl(name, priority, detail::reporterCreator, isReporter); return 0; } } // namespace doctest @@ -1920,68 +1815,55 @@ int registerReporter(const char* name, int priority) { } \ typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) -// for typed tests -#define DOCTEST_REGISTER_TYPED_TEST_CASE_IMPL(func, type, decorators, idx) \ - doctest::detail::regTest( \ - doctest::detail::TestCase(func, __FILE__, __LINE__, \ - doctest_detail_test_suite_ns::getCurrentTestSuite(), \ - doctest::detail::type_to_string(), idx) * \ - decorators) - #define DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, iter, func) \ template \ - inline void func(); \ - template \ - struct iter; \ - template \ - struct iter> \ - { \ - iter(int line, int index) { \ - DOCTEST_REGISTER_TYPED_TEST_CASE_IMPL(func, Type, dec, line * 1000 + index); \ - iter>(line, index + 1); \ - } \ - }; \ - template <> \ - struct iter> \ - { \ - iter(int, int) {} \ - }; \ + static void func(); \ + namespace { \ + template \ + struct iter; \ + template \ + struct iter> \ + { \ + iter(const char* file, unsigned line, int index) { \ + doctest::detail::regTest(doctest::detail::TestCase(func, file, line, \ + doctest_detail_test_suite_ns::getCurrentTestSuite(), \ + doctest::detail::type_to_string(), \ + int(line) * 1000 + index) \ + * dec); \ + iter>(file, line, index + 1); \ + } \ + }; \ + template <> \ + struct iter> \ + { \ + iter(const char*, unsigned, int) {} \ + }; \ + } \ template \ - inline void func() + static void func() #define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(dec, T, id) \ DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(id, ITERATOR), \ DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_)) -#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE_IMPL(id, anon, ...) \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY)) = [] { \ - DOCTEST_CAT(id, ITERATOR)> DOCTEST_UNUSED DOCTEST_CAT( \ - anon, inner_dummy)(__LINE__, 0); \ - return 0; \ - }(); \ +#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, anon, ...) \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY)) = \ + doctest::detail::instantiationHelper(DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__>(__FILE__, __LINE__, 0));\ DOCTEST_GLOBAL_NO_WARNINGS_END() #define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_INVOKE_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__) \ + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), std::tuple<__VA_ARGS__>) \ typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) -#define DOCTEST_TEST_CASE_TEMPLATE_APPLY_IMPL(id, anon, ...) \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY)) = [] { \ - DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__> DOCTEST_UNUSED DOCTEST_CAT(anon, inner_dummy)( \ - __LINE__, 0); \ - return 0; \ - }(); \ - DOCTEST_GLOBAL_NO_WARNINGS_END() - #define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_APPLY_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__) \ + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__) \ typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) #define DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, anon, ...) \ DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(anon, ITERATOR), anon); \ - DOCTEST_TEST_CASE_TEMPLATE_INVOKE_IMPL(anon, anon, __VA_ARGS__) \ + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(anon, anon, std::tuple<__VA_ARGS__>) \ template \ - inline void anon() + static void anon() #define DOCTEST_TEST_CASE_TEMPLATE(dec, T, ...) \ DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__) @@ -2040,16 +1922,33 @@ int registerReporter(const char* name, int priority) { DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(DOCTEST_ANONYMOUS(_DOCTEST_ANON_TRANSLATOR_), \ signature) -// for registering +// for registering reporters #define DOCTEST_REGISTER_REPORTER(name, priority, reporter) \ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_REPORTER_)) = \ - doctest::registerReporter(name, priority); \ + doctest::registerReporter(name, priority, true); \ + DOCTEST_GLOBAL_NO_WARNINGS_END() typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) + +// for registering listeners +#define DOCTEST_REGISTER_LISTENER(name, priority, reporter) \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_REPORTER_)) = \ + doctest::registerReporter(name, priority, false); \ DOCTEST_GLOBAL_NO_WARNINGS_END() typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) // for logging -#define DOCTEST_INFO(x) \ - doctest::detail::ContextScope DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_)( \ - doctest::detail::ContextBuilder() << x) +#define DOCTEST_INFO(expression) \ + DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), \ + DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), expression) + +#define DOCTEST_INFO_IMPL(lambda_name, mb_name, s_name, expression) \ + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4626) \ + auto lambda_name = [&](std::ostream* s_name) { \ + doctest::detail::MessageBuilder mb_name(__FILE__, __LINE__, doctest::assertType::is_warn); \ + mb_name.m_stream = s_name; \ + mb_name << expression; \ + }; \ + DOCTEST_MSVC_SUPPRESS_WARNING_POP \ + auto DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope(lambda_name) + #define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := " << x) #define DOCTEST_ADD_AT_IMPL(type, file, line, mb, x) \ @@ -2069,14 +1968,7 @@ int registerReporter(const char* name, int priority) { #define DOCTEST_FAIL_CHECK(x) DOCTEST_ADD_FAIL_CHECK_AT(__FILE__, __LINE__, x) #define DOCTEST_FAIL(x) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, x) -// hack for macros like INFO() that require lvalues -#if __cplusplus >= 201402L || (DOCTEST_MSVC >= DOCTEST_COMPILER(19, 10, 0)) -template -constexpr T to_lvalue = x; -#define DOCTEST_TO_LVALUE(...) to_lvalue -#else // TO_LVALUE -#define DOCTEST_TO_LVALUE(...) TO_LVALUE_CAN_BE_USED_ONLY_IN_CPP14_MODE_OR_WITH_VS_2017_OR_NEWER -#endif // TO_LVALUE +#define DOCTEST_TO_LVALUE(...) __VA_ARGS__ // Not removed to keep backwards compatibility. #ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS @@ -2097,6 +1989,9 @@ constexpr T to_lvalue = x; #else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS +// necessary for _MESSAGE +#define DOCTEST_ASSERT_IMPLEMENT_2 DOCTEST_ASSERT_IMPLEMENT_1 + #define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \ doctest::detail::decomp_assert( \ @@ -2122,11 +2017,11 @@ constexpr T to_lvalue = x; #define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } while((void)0, 0) // clang-format on -#define DOCTEST_ASSERT_THROWS_AS(expr, assert_type, ...) \ +#define DOCTEST_ASSERT_THROWS_AS(expr, assert_type, message, ...) \ do { \ if(!doctest::getContextOptions()->no_throw) { \ doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, #expr, #__VA_ARGS__); \ + __LINE__, #expr, #__VA_ARGS__, message); \ try { \ DOCTEST_CAST_TO_VOID(expr) \ } catch(const doctest::detail::remove_const< \ @@ -2142,7 +2037,7 @@ constexpr T to_lvalue = x; do { \ if(!doctest::getContextOptions()->no_throw) { \ doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, #expr, __VA_ARGS__); \ + __LINE__, #expr, "", __VA_ARGS__); \ try { \ DOCTEST_CAST_TO_VOID(expr) \ } catch(...) { _DOCTEST_RB.translateException(); } \ @@ -2165,14 +2060,18 @@ constexpr T to_lvalue = x; #define DOCTEST_CHECK_THROWS(expr) DOCTEST_ASSERT_THROWS_WITH(expr, DT_CHECK_THROWS, "") #define DOCTEST_REQUIRE_THROWS(expr) DOCTEST_ASSERT_THROWS_WITH(expr, DT_REQUIRE_THROWS, "") -#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_AS, __VA_ARGS__) -#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_AS, __VA_ARGS__) -#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_AS, __VA_ARGS__) +#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_AS, "", __VA_ARGS__) +#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_AS, "", __VA_ARGS__) +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_AS, "", __VA_ARGS__) #define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, DT_WARN_THROWS_WITH, __VA_ARGS__) #define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, DT_CHECK_THROWS_WITH, __VA_ARGS__) #define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, DT_REQUIRE_THROWS_WITH, __VA_ARGS__) +#define DOCTEST_WARN_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_WITH_AS, message, __VA_ARGS__) +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_WITH_AS, message, __VA_ARGS__) +#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_WITH_AS, message, __VA_ARGS__) + #define DOCTEST_WARN_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_WARN_NOTHROW) #define DOCTEST_CHECK_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_CHECK_NOTHROW) #define DOCTEST_REQUIRE_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_REQUIRE_NOTHROW) @@ -2183,9 +2082,12 @@ constexpr T to_lvalue = x; #define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_AS(expr, ex); } while((void)0, 0) #define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_AS(expr, ex); } while((void)0, 0) #define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_AS(expr, ex); } while((void)0, 0) -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_WITH(expr, ex); } while((void)0, 0) -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_WITH(expr, ex); } while((void)0, 0) -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_WITH(expr, ex); } while((void)0, 0) +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_WITH(expr, with); } while((void)0, 0) +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_WITH(expr, with); } while((void)0, 0) +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_WITH(expr, with); } while((void)0, 0) +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex); } while((void)0, 0) +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex); } while((void)0, 0) +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex); } while((void)0, 0) #define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_NOTHROW(expr); } while((void)0, 0) #define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_NOTHROW(expr); } while((void)0, 0) #define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_NOTHROW(expr); } while((void)0, 0) @@ -2260,6 +2162,9 @@ constexpr T to_lvalue = x; #undef DOCTEST_WARN_THROWS_WITH #undef DOCTEST_CHECK_THROWS_WITH #undef DOCTEST_REQUIRE_THROWS_WITH +#undef DOCTEST_WARN_THROWS_WITH_AS +#undef DOCTEST_CHECK_THROWS_WITH_AS +#undef DOCTEST_REQUIRE_THROWS_WITH_AS #undef DOCTEST_WARN_NOTHROW #undef DOCTEST_CHECK_NOTHROW #undef DOCTEST_REQUIRE_NOTHROW @@ -2273,6 +2178,9 @@ constexpr T to_lvalue = x; #undef DOCTEST_WARN_THROWS_WITH_MESSAGE #undef DOCTEST_CHECK_THROWS_WITH_MESSAGE #undef DOCTEST_REQUIRE_THROWS_WITH_MESSAGE +#undef DOCTEST_WARN_THROWS_WITH_AS_MESSAGE +#undef DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE +#undef DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE #undef DOCTEST_WARN_NOTHROW_MESSAGE #undef DOCTEST_CHECK_NOTHROW_MESSAGE #undef DOCTEST_REQUIRE_NOTHROW_MESSAGE @@ -2288,6 +2196,9 @@ constexpr T to_lvalue = x; #define DOCTEST_WARN_THROWS_WITH(expr, ...) ((void)0) #define DOCTEST_CHECK_THROWS_WITH(expr, ...) ((void)0) #define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) ((void)0) +#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) ((void)0) +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) ((void)0) +#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) ((void)0) #define DOCTEST_WARN_NOTHROW(expr) ((void)0) #define DOCTEST_CHECK_NOTHROW(expr) ((void)0) #define DOCTEST_REQUIRE_NOTHROW(expr) ((void)0) @@ -2298,9 +2209,12 @@ constexpr T to_lvalue = x; #define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) #define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) #define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, ex, msg) ((void)0) -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, ex, msg) ((void)0) -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, ex, msg) ((void)0) +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0) +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0) +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0) +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0) +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0) +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0) #define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) ((void)0) #define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) ((void)0) #define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) ((void)0) @@ -2392,6 +2306,7 @@ constexpr T to_lvalue = x; static inline doctest::String DOCTEST_ANONYMOUS(_DOCTEST_ANON_TRANSLATOR_)(signature) #define DOCTEST_REGISTER_REPORTER(name, priority, reporter) +#define DOCTEST_REGISTER_LISTENER(name, priority, reporter) #define DOCTEST_INFO(x) ((void)0) #define DOCTEST_CAPTURE(x) ((void)0) @@ -2425,6 +2340,9 @@ constexpr T to_lvalue = x; #define DOCTEST_WARN_THROWS_WITH(expr, ...) ((void)0) #define DOCTEST_CHECK_THROWS_WITH(expr, ...) ((void)0) #define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) ((void)0) +#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) ((void)0) +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) ((void)0) +#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) ((void)0) #define DOCTEST_WARN_NOTHROW(expr) ((void)0) #define DOCTEST_CHECK_NOTHROW(expr) ((void)0) #define DOCTEST_REQUIRE_NOTHROW(expr) ((void)0) @@ -2435,9 +2353,12 @@ constexpr T to_lvalue = x; #define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) #define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) #define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) ((void)0) -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, ex, msg) ((void)0) -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, ex, msg) ((void)0) -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, ex, msg) ((void)0) +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0) +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0) +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, msg) ((void)0) +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0) +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0) +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) ((void)0) #define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) ((void)0) #define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) ((void)0) #define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) ((void)0) @@ -2508,11 +2429,11 @@ constexpr T to_lvalue = x; #define DOCTEST_SCENARIO_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(" Scenario: " name, T, __VA_ARGS__) #define DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(" Scenario: " name, T, id) -#define DOCTEST_GIVEN(name) SUBCASE(" Given: " name) -#define DOCTEST_WHEN(name) SUBCASE(" When: " name) -#define DOCTEST_AND_WHEN(name) SUBCASE("And when: " name) -#define DOCTEST_THEN(name) SUBCASE(" Then: " name) -#define DOCTEST_AND_THEN(name) SUBCASE(" And: " name) +#define DOCTEST_GIVEN(name) DOCTEST_SUBCASE(" Given: " name) +#define DOCTEST_WHEN(name) DOCTEST_SUBCASE(" When: " name) +#define DOCTEST_AND_WHEN(name) DOCTEST_SUBCASE("And when: " name) +#define DOCTEST_THEN(name) DOCTEST_SUBCASE(" Then: " name) +#define DOCTEST_AND_THEN(name) DOCTEST_SUBCASE(" And: " name) // clang-format on // == SHORT VERSIONS OF THE MACROS @@ -2532,6 +2453,7 @@ constexpr T to_lvalue = x; #define TEST_SUITE_END DOCTEST_TEST_SUITE_END #define REGISTER_EXCEPTION_TRANSLATOR DOCTEST_REGISTER_EXCEPTION_TRANSLATOR #define REGISTER_REPORTER DOCTEST_REGISTER_REPORTER +#define REGISTER_LISTENER DOCTEST_REGISTER_LISTENER #define INFO DOCTEST_INFO #define CAPTURE DOCTEST_CAPTURE #define ADD_MESSAGE_AT DOCTEST_ADD_MESSAGE_AT @@ -2547,18 +2469,21 @@ constexpr T to_lvalue = x; #define WARN_THROWS DOCTEST_WARN_THROWS #define WARN_THROWS_AS DOCTEST_WARN_THROWS_AS #define WARN_THROWS_WITH DOCTEST_WARN_THROWS_WITH +#define WARN_THROWS_WITH_AS DOCTEST_WARN_THROWS_WITH_AS #define WARN_NOTHROW DOCTEST_WARN_NOTHROW #define CHECK DOCTEST_CHECK #define CHECK_FALSE DOCTEST_CHECK_FALSE #define CHECK_THROWS DOCTEST_CHECK_THROWS #define CHECK_THROWS_AS DOCTEST_CHECK_THROWS_AS #define CHECK_THROWS_WITH DOCTEST_CHECK_THROWS_WITH +#define CHECK_THROWS_WITH_AS DOCTEST_CHECK_THROWS_WITH_AS #define CHECK_NOTHROW DOCTEST_CHECK_NOTHROW #define REQUIRE DOCTEST_REQUIRE #define REQUIRE_FALSE DOCTEST_REQUIRE_FALSE #define REQUIRE_THROWS DOCTEST_REQUIRE_THROWS #define REQUIRE_THROWS_AS DOCTEST_REQUIRE_THROWS_AS #define REQUIRE_THROWS_WITH DOCTEST_REQUIRE_THROWS_WITH +#define REQUIRE_THROWS_WITH_AS DOCTEST_REQUIRE_THROWS_WITH_AS #define REQUIRE_NOTHROW DOCTEST_REQUIRE_NOTHROW #define WARN_MESSAGE DOCTEST_WARN_MESSAGE @@ -2566,18 +2491,21 @@ constexpr T to_lvalue = x; #define WARN_THROWS_MESSAGE DOCTEST_WARN_THROWS_MESSAGE #define WARN_THROWS_AS_MESSAGE DOCTEST_WARN_THROWS_AS_MESSAGE #define WARN_THROWS_WITH_MESSAGE DOCTEST_WARN_THROWS_WITH_MESSAGE +#define WARN_THROWS_WITH_AS_MESSAGE DOCTEST_WARN_THROWS_WITH_AS_MESSAGE #define WARN_NOTHROW_MESSAGE DOCTEST_WARN_NOTHROW_MESSAGE #define CHECK_MESSAGE DOCTEST_CHECK_MESSAGE #define CHECK_FALSE_MESSAGE DOCTEST_CHECK_FALSE_MESSAGE #define CHECK_THROWS_MESSAGE DOCTEST_CHECK_THROWS_MESSAGE #define CHECK_THROWS_AS_MESSAGE DOCTEST_CHECK_THROWS_AS_MESSAGE #define CHECK_THROWS_WITH_MESSAGE DOCTEST_CHECK_THROWS_WITH_MESSAGE +#define CHECK_THROWS_WITH_AS_MESSAGE DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE #define CHECK_NOTHROW_MESSAGE DOCTEST_CHECK_NOTHROW_MESSAGE #define REQUIRE_MESSAGE DOCTEST_REQUIRE_MESSAGE #define REQUIRE_FALSE_MESSAGE DOCTEST_REQUIRE_FALSE_MESSAGE #define REQUIRE_THROWS_MESSAGE DOCTEST_REQUIRE_THROWS_MESSAGE #define REQUIRE_THROWS_AS_MESSAGE DOCTEST_REQUIRE_THROWS_AS_MESSAGE #define REQUIRE_THROWS_WITH_MESSAGE DOCTEST_REQUIRE_THROWS_WITH_MESSAGE +#define REQUIRE_THROWS_WITH_AS_MESSAGE DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE #define REQUIRE_NOTHROW_MESSAGE DOCTEST_REQUIRE_NOTHROW_MESSAGE #define SCENARIO DOCTEST_SCENARIO @@ -2686,13 +2614,18 @@ DOCTEST_GCC_SUPPRESS_WARNING_POP #endif // DOCTEST_SINGLE_HEADER #if defined(DOCTEST_CONFIG_IMPLEMENT) || !defined(DOCTEST_SINGLE_HEADER) -#ifndef DOCTEST_LIBRARY_IMPLEMENTATION -#define DOCTEST_LIBRARY_IMPLEMENTATION #ifndef DOCTEST_SINGLE_HEADER #include "doctest_fwd.h" #endif // DOCTEST_SINGLE_HEADER +DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-macros") + +#ifndef DOCTEST_LIBRARY_IMPLEMENTATION +#define DOCTEST_LIBRARY_IMPLEMENTATION + +DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded") @@ -2813,9 +2746,6 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif // WIN32_LEAN_AND_MEAN -#ifndef VC_EXTRA_LEAN -#define VC_EXTRA_LEAN -#endif // VC_EXTRA_LEAN #ifndef NOMINMAX #define NOMINMAX #endif // NOMINMAX @@ -2927,7 +2857,7 @@ namespace detail { return oss.str().c_str(); } - DOCTEST_THREAD_LOCAL std::ostringstream g_oss; + DOCTEST_THREAD_LOCAL std::ostringstream g_oss; // NOLINT(cert-err58-cpp) std::ostream* getTlsOss() { g_oss.clear(); // there shouldn't be anything worth clearing in the flags @@ -3000,10 +2930,11 @@ namespace detail { std::vector stringifiedContexts; // logging from INFO() due to an exception // stuff for subcases - std::set subcasesPassed; - std::set subcasesEnteredLevels; - int subcasesCurrentLevel; - bool should_reenter; + std::vector subcasesStack; + std::set subcasesPassed; + int subcasesCurrentMaxLevel; + bool should_reenter; + std::atomic shouldLogCurrentException; void resetRunData() { numTestCases = 0; @@ -3270,6 +3201,10 @@ const char* assertString(assertType::Enum at) { case assertType::DT_CHECK_THROWS_WITH : return "CHECK_THROWS_WITH"; case assertType::DT_REQUIRE_THROWS_WITH : return "REQUIRE_THROWS_WITH"; + case assertType::DT_WARN_THROWS_WITH_AS : return "WARN_THROWS_WITH_AS"; + case assertType::DT_CHECK_THROWS_WITH_AS : return "CHECK_THROWS_WITH_AS"; + case assertType::DT_REQUIRE_THROWS_WITH_AS : return "REQUIRE_THROWS_WITH_AS"; + case assertType::DT_WARN_NOTHROW : return "WARN_NOTHROW"; case assertType::DT_CHECK_NOTHROW : return "CHECK_NOTHROW"; case assertType::DT_REQUIRE_NOTHROW : return "REQUIRE_NOTHROW"; @@ -3333,21 +3268,6 @@ const char* skipPathFromFilename(const char* file) { DOCTEST_CLANG_SUPPRESS_WARNING_POP DOCTEST_GCC_SUPPRESS_WARNING_POP -DOCTEST_DEFINE_DEFAULTS(TestCaseData); -DOCTEST_DEFINE_COPIES(TestCaseData); - -DOCTEST_DEFINE_DEFAULTS(AssertData); - -DOCTEST_DEFINE_DEFAULTS(MessageData); - -SubcaseSignature::SubcaseSignature(const char* name, const char* file, int line) - : m_name(name) - , m_file(file) - , m_line(line) {} - -DOCTEST_DEFINE_DEFAULTS(SubcaseSignature); -DOCTEST_DEFINE_COPIES(SubcaseSignature); - bool SubcaseSignature::operator<(const SubcaseSignature& other) const { if(m_line != other.m_line) return m_line < other.m_line; @@ -3359,8 +3279,6 @@ bool SubcaseSignature::operator<(const SubcaseSignature& other) const { IContextScope::IContextScope() = default; IContextScope::~IContextScope() = default; -DOCTEST_DEFINE_DEFAULTS(ContextOptions); - #ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING String toString(char* in) { return toString(static_cast(in)); } String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; } @@ -3391,13 +3309,16 @@ DOCTEST_TO_STRING_OVERLOAD(int long long unsigned, "%llu") String toString(std::nullptr_t) { return "NULL"; } +#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) +// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183 +String toString(const std::string& in) { return in.c_str(); } +#endif // VS 2019 + Approx::Approx(double value) : m_epsilon(static_cast(std::numeric_limits::epsilon()) * 100) , m_scale(1.0) , m_value(value) {} -DOCTEST_DEFINE_COPIES(Approx); - Approx Approx::operator()(double value) const { Approx approx(value); approx.epsilon(m_epsilon); @@ -3417,7 +3338,7 @@ Approx& Approx::scale(double newScale) { bool operator==(double lhs, const Approx& rhs) { // Thanks to Richard Harris for his help refining this formula return std::fabs(lhs - rhs.m_value) < - rhs.m_epsilon * (rhs.m_scale + std::max(std::fabs(lhs), std::fabs(rhs.m_value))); + rhs.m_epsilon * (rhs.m_scale + std::max(std::fabs(lhs), std::fabs(rhs.m_value))); } bool operator==(const Approx& lhs, double rhs) { return operator==(rhs, lhs); } bool operator!=(double lhs, const Approx& rhs) { return !operator==(lhs, rhs); } @@ -3452,10 +3373,6 @@ void Context::setAsDefaultForAssertsOutOfTestCases() {} void Context::setAssertHandler(detail::assert_handler) {} int Context::run() { return 0; } -DOCTEST_DEFINE_DEFAULTS(CurrentTestCaseStats); - -DOCTEST_DEFINE_DEFAULTS(TestRunStats); - IReporter::~IReporter() = default; int IReporter::get_num_active_contexts() { return 0; } @@ -3491,7 +3408,12 @@ namespace { // the int (priority) is part of the key for automatic sorting - sadly one can register a // reporter with a duplicate name and a different priority but hopefully that won't happen often :| typedef std::map, reporterCreatorFunc> reporterMap; - reporterMap& getReporters() { + + reporterMap& getReporters() { + static reporterMap data; + return data; + } + reporterMap& getListeners() { static reporterMap data; return data; } @@ -3501,8 +3423,6 @@ namespace detail { for(auto& curr_rep : g_cs->reporters_currently_used) \ curr_rep->function(__VA_ARGS__) - DOCTEST_DEFINE_DEFAULTS(TestFailureException); - DOCTEST_DEFINE_COPIES(TestFailureException); bool checkIfShouldThrow(assertType::Enum at) { if(at & assertType::is_require) //!OCLINT bitwise operator in conditional return true; @@ -3517,7 +3437,10 @@ namespace detail { } #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - [[noreturn]] void throwException() { throw TestFailureException(); } + [[noreturn]] void throwException() { + g_cs->shouldLogCurrentException = false; + throw TestFailureException(); + } // NOLINT(cert-err60-cpp) #else // DOCTEST_CONFIG_NO_EXCEPTIONS void throwException() {} #endif // DOCTEST_CONFIG_NO_EXCEPTIONS @@ -3586,45 +3509,62 @@ namespace { namespace detail { Subcase::Subcase(const char* name, const char* file, int line) - : m_signature(name, file, line) { + : m_signature({name, file, line}) { ContextState* s = g_cs; - // if we have already completed it - if(s->subcasesPassed.count(m_signature) != 0) - return; - // check subcase filters - if(s->subcasesCurrentLevel < s->subcase_filter_levels) { + if(s->subcasesStack.size() < size_t(s->subcase_filter_levels)) { if(!matchesAny(m_signature.m_name, s->filters[6], true, s->case_sensitive)) return; if(matchesAny(m_signature.m_name, s->filters[7], false, s->case_sensitive)) return; } - + // if a Subcase on the same level has already been entered - if(s->subcasesEnteredLevels.count(s->subcasesCurrentLevel) != 0) { + if(s->subcasesStack.size() < size_t(s->subcasesCurrentMaxLevel)) { s->should_reenter = true; return; } - s->subcasesEnteredLevels.insert(s->subcasesCurrentLevel++); + // push the current signature to the stack so we can check if the + // current stack + the current new subcase have been traversed + s->subcasesStack.push_back(m_signature); + if(s->subcasesPassed.count(s->subcasesStack) != 0) { + // pop - revert to previous stack since we've already passed this + s->subcasesStack.pop_back(); + return; + } + + s->subcasesCurrentMaxLevel = s->subcasesStack.size(); m_entered = true; DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); } + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17 + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") Subcase::~Subcase() { if(m_entered) { - ContextState* s = g_cs; - - s->subcasesCurrentLevel--; - // only mark the subcase as passed if no subcases have been skipped - if(s->should_reenter == false) - s->subcasesPassed.insert(m_signature); + // only mark the subcase stack as passed if no subcases have been skipped + if(g_cs->should_reenter == false) + g_cs->subcasesPassed.insert(g_cs->subcasesStack); + g_cs->subcasesStack.pop_back(); + if(std::uncaught_exception() && g_cs->shouldLogCurrentException) { + DOCTEST_ITERATE_THROUGH_REPORTERS( + test_case_exception, {"exception thrown in subcase - will translate later " + "when the whole test case has been exited (cannot " + "translate while there is an active exception)", + false}); + g_cs->shouldLogCurrentException = false; + } DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); } } + DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_GCC_SUPPRESS_WARNING_POP + DOCTEST_MSVC_SUPPRESS_WARNING_POP Subcase::operator bool() const { return m_entered; } @@ -3632,17 +3572,9 @@ namespace detail { : m_passed(passed) , m_decomp(decomposition) {} - DOCTEST_DEFINE_DEFAULTS(Result); - DOCTEST_DEFINE_COPIES(Result); - ExpressionDecomposer::ExpressionDecomposer(assertType::Enum at) : m_at(at) {} - DOCTEST_DEFINE_DEFAULTS(ExpressionDecomposer); - - DOCTEST_DEFINE_DEFAULTS(TestSuite); - DOCTEST_DEFINE_COPIES(TestSuite); - TestSuite& TestSuite::operator*(const char* in) { m_test_suite = in; // clear state @@ -3659,7 +3591,7 @@ namespace detail { const char* type, int template_id) { m_file = file; m_line = line; - m_name = nullptr; + m_name = nullptr; // will be later overridden in operator* m_test_suite = test_suite.m_test_suite; m_description = test_suite.m_description; m_skip = test_suite.m_skip; @@ -3673,8 +3605,6 @@ namespace detail { m_template_id = template_id; } - DOCTEST_DEFINE_DEFAULTS(TestCase); - TestCase::TestCase(const TestCase& other) : TestCaseData() { *this = other; @@ -3885,6 +3815,9 @@ namespace detail { return 0; } +#ifdef DOCTEST_IS_DEBUGGER_ACTIVE + bool isDebuggerActive() { return DOCTEST_IS_DEBUGGER_ACTIVE(); } +#else // DOCTEST_IS_DEBUGGER_ACTIVE #ifdef DOCTEST_PLATFORM_MAC // The following function is taken directly from the following technical note: // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html @@ -3917,6 +3850,7 @@ namespace detail { #else bool isDebuggerActive() { return false; } #endif // Platform +#endif // DOCTEST_IS_DEBUGGER_ACTIVE void registerExceptionTranslatorImpl(const IExceptionTranslator* et) { if(std::find(getExceptionTranslators().begin(), getExceptionTranslators().end(), et) == @@ -3947,64 +3881,17 @@ namespace detail { DOCTEST_THREAD_LOCAL std::vector g_infoContexts; // for logging with INFO() - ContextBuilder::ICapture::ICapture() = default; - ContextBuilder::ICapture::~ICapture() = default; - - ContextBuilder::Chunk::Chunk() = default; - ContextBuilder::Chunk::~Chunk() = default; - - ContextBuilder::Node::Node() = default; - ContextBuilder::Node::~Node() = default; - - // steal the contents of the other - acting as a move constructor... - ContextBuilder::ContextBuilder(ContextBuilder& other) - : numCaptures(other.numCaptures) - , head(other.head) - , tail(other.tail) { - other.numCaptures = 0; - other.head = nullptr; - other.tail = nullptr; - memcpy(stackChunks, other.stackChunks, - unsigned(int(sizeof(Chunk)) * DOCTEST_CONFIG_NUM_CAPTURES_ON_STACK)); - } - - DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wcast-align") - void ContextBuilder::stringify(std::ostream* s) const { - int curr = 0; - // iterate over small buffer - while(curr < numCaptures && curr < DOCTEST_CONFIG_NUM_CAPTURES_ON_STACK) - reinterpret_cast(stackChunks[curr++].buf)->toStream(s); - // iterate over list - auto curr_elem = head; - while(curr < numCaptures) { - reinterpret_cast(curr_elem->chunk.buf)->toStream(s); - curr_elem = curr_elem->next; - ++curr; - } - } - DOCTEST_GCC_SUPPRESS_WARNING_POP - - ContextBuilder::ContextBuilder() = default; - - ContextBuilder::~ContextBuilder() { - // free the linked list - the ones on the stack are left as-is - // no destructors are called at all - there is no need - while(head) { - auto next = head->next; - delete head; - head = next; - } - } - - ContextScope::ContextScope(ContextBuilder& temp) - : contextBuilder(temp) { + ContextScopeBase::ContextScopeBase() { g_infoContexts.push_back(this); } DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17 DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") - ContextScope::~ContextScope() { + // destroy cannot be inlined into the destructor because that would mean calling stringify after + // ContextScope has been destroyed (base class destructors run after derived class destructors). + // Instead, ContextScope calls this method directly from its destructor. + void ContextScopeBase::destroy() { if(std::uncaught_exception()) { std::ostringstream s; this->stringify(&s); @@ -4016,7 +3903,6 @@ namespace detail { DOCTEST_GCC_SUPPRESS_WARNING_POP DOCTEST_MSVC_SUPPRESS_WARNING_POP - void ContextScope::stringify(std::ostream* s) const { contextBuilder.stringify(s); } } // namespace detail namespace { using namespace detail; @@ -4184,7 +4070,7 @@ namespace { #define DOCTEST_OUTPUT_DEBUG_STRING(text) ::OutputDebugStringA(text) #else // TODO: integration with XCode and other IDEs -#define DOCTEST_OUTPUT_DEBUG_STRING(text) +#define DOCTEST_OUTPUT_DEBUG_STRING(text) // NOLINT(clang-diagnostic-unused-macros) #endif // Platform void addAssert(assertType::Enum at) { @@ -4203,8 +4089,10 @@ namespace { DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, {message.c_str(), true}); - while(g_cs->subcasesCurrentLevel--) + while(g_cs->subcasesStack.size()) { + g_cs->subcasesStack.pop_back(); DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); + } g_cs->finalizeTestCaseData(); @@ -4217,24 +4105,23 @@ namespace { namespace detail { ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type) { - m_test_case = g_cs->currentTest; - m_at = at; - m_file = file; - m_line = line; - m_expr = expr; - m_failed = true; - m_threw = false; - m_threw_as = false; - m_exception_type = exception_type; + const char* exception_type, const char* exception_string) { + m_test_case = g_cs->currentTest; + m_at = at; + m_file = file; + m_line = line; + m_expr = expr; + m_failed = true; + m_threw = false; + m_threw_as = false; + m_exception_type = exception_type; + m_exception_string = exception_string; #if DOCTEST_MSVC if(m_expr[0] == ' ') // this happens when variadic macros are disabled under MSVC ++m_expr; #endif // MSVC } - DOCTEST_DEFINE_DEFAULTS(ResultBuilder); - void ResultBuilder::setResult(const Result& res) { m_decomp = res.m_decomp; m_failed = !res.m_passed; @@ -4248,10 +4135,12 @@ namespace detail { bool ResultBuilder::log() { if(m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional m_failed = !m_threw; + } else if((m_at & assertType::is_throws_as) && (m_at & assertType::is_throws_with)) { //!OCLINT + m_failed = !m_threw_as || (m_exception != m_exception_string); } else if(m_at & assertType::is_throws_as) { //!OCLINT bitwise operator in conditional m_failed = !m_threw_as; } else if(m_at & assertType::is_throws_with) { //!OCLINT bitwise operator in conditional - m_failed = m_exception != m_exception_type; + m_failed = m_exception != m_exception_string; } else if(m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional m_failed = m_threw; } @@ -4313,7 +4202,7 @@ namespace detail { const bool isWarn = m_severity & assertType::is_warn; - // warn is just a message in this context so we dont treat it as an assert + // warn is just a message in this context so we don't treat it as an assert if(!isWarn) { addAssert(m_severity); addFailedAssert(m_severity); @@ -4796,6 +4685,10 @@ namespace { void report_query(const QueryData& in) override { test_run_start(); if(opt.list_reporters) { + for(auto& curr : getListeners()) + xml.scopedElement("Listener") + .writeAttribute("priority", curr.first.first) + .writeAttribute("name", curr.first.second); for(auto& curr : getReporters()) xml.scopedElement("Reporter") .writeAttribute("priority", curr.first.first) @@ -4864,6 +4757,8 @@ namespace { test_case_start_impl(in); xml.ensureTagClosed(); } + + void test_case_reenter(const TestCaseData&) override {} void test_case_end(const CurrentTestCaseStats& st) override { xml.startElement("OverallResultsAsserts") @@ -4916,11 +4811,12 @@ namespace { if(rb.m_threw) xml.scopedElement("Exception").writeText(rb.m_exception.c_str()); - if(rb.m_at & (assertType::is_throws_as | assertType::is_throws_with)) { + if(rb.m_at & assertType::is_throws_as) xml.scopedElement("ExpectedException").writeText(rb.m_exception_type); - } else if((rb.m_at & assertType::is_normal) && !rb.m_threw) { + if(rb.m_at & assertType::is_throws_with) + xml.scopedElement("ExpectedExceptionString").writeText(rb.m_exception_string); + if((rb.m_at & assertType::is_normal) && !rb.m_threw) xml.scopedElement("Expanded").writeText(rb.m_decomp.c_str()); - } log_contexts(); @@ -5177,10 +5073,16 @@ namespace { void printRegisteredReporters() { printVersion(); - s << Color::Cyan << "[doctest] " << Color::None << "listing all registered reporters\n"; - for(auto& curr : getReporters()) - s << "priority: " << std::setw(5) << curr.first.first - << " name: " << curr.first.second << "\n"; + auto printReporters = [this] (const reporterMap& reporters, const char* type) { + if(reporters.size()) { + s << Color::Cyan << "[doctest] " << Color::None << "listing all registered " << type << "\n"; + for(auto& curr : reporters) + s << "priority: " << std::setw(5) << curr.first.first + << " name: " << curr.first.second << "\n"; + } + }; + printReporters(getListeners(), "listeners"); + printReporters(getReporters(), "reporters"); } void list_query_results() { @@ -5278,6 +5180,8 @@ namespace { hasLoggedCurrentTestStart = false; tc = ∈ } + + void test_case_reenter(const TestCaseData&) override {} void test_case_end(const CurrentTestCaseStats& st) override { // log the preamble of the test case only if there is something @@ -5310,7 +5214,7 @@ namespace { if(st.failure_flags & TestCaseFailureReason::TooManyFailedAsserts) { s << Color::Red << "Aborting - too many failed asserts!\n"; } - s << Color::None; + s << Color::None; // lgtm [cpp/useless-expression] } void test_case_exception(const TestCaseException& e) override { @@ -5326,9 +5230,9 @@ namespace { if(num_stringified_contexts) { auto stringified_contexts = get_stringified_contexts(); s << Color::None << " logged: "; - for(int i = num_stringified_contexts - 1; i >= 0; --i) { - s << (i == num_stringified_contexts - 1 ? "" : " ") - << stringified_contexts[i] << "\n"; + for(int i = num_stringified_contexts; i > 0; --i) { + s << (i == num_stringified_contexts ? "" : " ") + << stringified_contexts[i - 1] << "\n"; } } s << "\n" << Color::None; @@ -5363,6 +5267,19 @@ namespace { if(rb.m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional s << (rb.m_threw ? "threw as expected!" : "did NOT throw at all!") << "\n"; + } else if((rb.m_at & assertType::is_throws_as) && + (rb.m_at & assertType::is_throws_with)) { //!OCLINT + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" + << rb.m_exception_string << "\", " << rb.m_exception_type << " ) " << Color::None; + if(rb.m_threw) { + if(!rb.m_failed) { + s << "threw as expected!\n"; + } else { + s << "threw a DIFFERENT exception! (contents: " << rb.m_exception << ")\n"; + } + } else { + s << "did NOT throw at all!\n"; + } } else if(rb.m_at & assertType::is_throws_as) { //!OCLINT bitwise operator in conditional s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", " @@ -5374,7 +5291,7 @@ namespace { } else if(rb.m_at & assertType::is_throws_with) { //!OCLINT bitwise operator in conditional s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" - << rb.m_exception_type << "\" ) " << Color::None + << rb.m_exception_string << "\" ) " << Color::None << (rb.m_threw ? (!rb.m_failed ? "threw as expected!" : "threw a DIFFERENT exception: ") : "did NOT throw at all!") @@ -5433,6 +5350,7 @@ namespace { DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_start, DOCTEST_EMPTY, DOCTEST_EMPTY) DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_end, const TestRunStats&, in) DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_start, const TestCaseData&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_reenter, const TestCaseData&, in) DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_end, const CurrentTestCaseStats&, in) DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_exception, const TestCaseException&, in) DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_start, const SubcaseSignature&, in) @@ -5445,55 +5363,33 @@ namespace { DOCTEST_THREAD_LOCAL std::ostringstream DebugOutputWindowReporter::oss; #endif // DOCTEST_PLATFORM_WINDOWS - // the implementation of parseFlag() - bool parseFlagImpl(int argc, const char* const* argv, const char* pattern) { - for(int i = argc - 1; i >= 0; --i) { - auto temp = std::strstr(argv[i], pattern); - if(temp && strlen(temp) == strlen(pattern)) { - // eliminate strings in which the chars before the option are not '-' - bool noBadCharsFound = true; //!OCLINT prefer early exits and continue - while(temp != argv[i]) { - if(*--temp != '-') { - noBadCharsFound = false; - break; - } - } - if(noBadCharsFound && argv[i][0] == '-') - return true; - } - } - return false; - } - - // locates a flag on the command line - bool parseFlag(int argc, const char* const* argv, const char* pattern) { -#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS - // offset (normally 3 for "dt-") to skip prefix - if(parseFlagImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX))) - return true; -#endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS - return parseFlagImpl(argc, argv, pattern); - } - // the implementation of parseOption() - bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String& res) { - for(int i = argc - 1; i >= 0; --i) { - auto temp = std::strstr(argv[i], pattern); - if(temp) { //!OCLINT prefer early exits and continue + bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String* value) { + // going from the end to the beginning and stopping on the first occurrence from the end + for(int i = argc; i > 0; --i) { + auto index = i - 1; + auto temp = std::strstr(argv[index], pattern); + if(temp && (value || strlen(temp) == strlen(pattern))) { //!OCLINT prefer early exits and continue // eliminate matches in which the chars before the option are not '-' bool noBadCharsFound = true; - auto curr = argv[i]; + auto curr = argv[index]; while(curr != temp) { if(*curr++ != '-') { noBadCharsFound = false; break; } } - if(noBadCharsFound && argv[i][0] == '-') { - temp += strlen(pattern); - const unsigned len = strlen(temp); - if(len) { - res = temp; + if(noBadCharsFound && argv[index][0] == '-') { + if(value) { + // parsing the value of an option + temp += strlen(pattern); + const unsigned len = strlen(temp); + if(len) { + *value = temp; + return true; + } + } else { + // just a flag - no value return true; } } @@ -5503,22 +5399,28 @@ namespace { } // parses an option and returns the string after the '=' character - bool parseOption(int argc, const char* const* argv, const char* pattern, String& res, + bool parseOption(int argc, const char* const* argv, const char* pattern, String* value = nullptr, const String& defaultVal = String()) { - res = defaultVal; + if(value) + *value = defaultVal; #ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS // offset (normally 3 for "dt-") to skip prefix - if(parseOptionImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX), res)) + if(parseOptionImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX), value)) return true; #endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS - return parseOptionImpl(argc, argv, pattern, res); + return parseOptionImpl(argc, argv, pattern, value); + } + + // locates a flag on the command line + bool parseFlag(int argc, const char* const* argv, const char* pattern) { + return parseOption(argc, argv, pattern); } // parses a comma separated list of words after a pattern in one of the arguments in argv bool parseCommaSepArgs(int argc, const char* const* argv, const char* pattern, std::vector& res) { String filtersString; - if(parseOption(argc, argv, pattern, filtersString)) { + if(parseOption(argc, argv, pattern, &filtersString)) { // tokenize with "," as a separator // cppcheck-suppress strtokCalled DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") @@ -5546,7 +5448,7 @@ namespace { bool parseIntOption(int argc, const char* const* argv, const char* pattern, optionType type, int& res) { String parsedValue; - if(!parseOption(argc, argv, pattern, parsedValue)) + if(!parseOption(argc, argv, pattern, &parsedValue)) return false; if(type == 0) { @@ -5643,8 +5545,8 @@ void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) { p->var = default #define DOCTEST_PARSE_STR_OPTION(name, sname, var, default) \ - if(parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", strRes, default) || \ - parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", strRes, default) || \ + if(parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", &strRes, default) || \ + parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", &strRes, default) || \ withDefaults) \ p->var = strRes @@ -5788,8 +5690,6 @@ int Context::run() { return EXIT_SUCCESS; }; - DOCTEST_REGISTER_REPORTER("console", 0, ConsoleReporter); - // setup default reporter if none is given through the command line if(p->filters[8].empty()) p->filters[8].push_back("console"); @@ -5800,6 +5700,12 @@ int Context::run() { p->reporters_currently_used.push_back(curr.second(*g_cs)); } + // TODO: check if there is nothing in reporters_currently_used + + // prepend all listeners + for(auto& curr : getListeners()) + p->reporters_currently_used.insert(p->reporters_currently_used.begin(), curr.second(*g_cs)); + #ifdef DOCTEST_PLATFORM_WINDOWS if(isDebuggerActive()) p->reporters_currently_used.push_back(new DebugOutputWindowReporter(*g_cs)); @@ -5920,12 +5826,16 @@ int Context::run() { DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_start, tc); p->timer.start(); + + bool run_test = true; do { // reset some of the fields for subcases (except for the set of fully passed ones) - p->should_reenter = false; - p->subcasesCurrentLevel = 0; - p->subcasesEnteredLevels.clear(); + p->should_reenter = false; + p->subcasesCurrentMaxLevel = 0; + p->subcasesStack.clear(); + + p->shouldLogCurrentException = true; // reset stuff for logging with INFO() p->stringifiedContexts.clear(); @@ -5950,10 +5860,15 @@ int Context::run() { // exit this loop if enough assertions have failed - even if there are more subcases if(p->abort_after > 0 && p->numAssertsFailed + p->numAssertsFailedCurrentTest_atomic >= p->abort_after) { - p->should_reenter = false; + run_test = false; p->failure_flags |= TestCaseFailureReason::TooManyFailedAsserts; } - } while(p->should_reenter == true); + + if(p->should_reenter && run_test) + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_reenter, tc); + if(!p->should_reenter) + run_test = false; + } while(run_test); p->finalizeTestCaseData(); @@ -5977,13 +5892,16 @@ int Context::run() { DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, qdata); } + // see these issues on the reasoning for this: + // - https://github.com/onqtam/doctest/issues/143#issuecomment-414418903 + // - https://github.com/onqtam/doctest/issues/126 + auto DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS = []() DOCTEST_NOINLINE + { std::cout << std::string(); }; + DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS(); + return cleanup_and_return(); } -DOCTEST_DEFINE_DEFAULTS(CurrentTestCaseStats); - -DOCTEST_DEFINE_DEFAULTS(TestRunStats); - IReporter::~IReporter() = default; int IReporter::get_num_active_contexts() { return detail::g_infoContexts.size(); } @@ -5997,16 +5915,14 @@ const String* IReporter::get_stringified_contexts() { } namespace detail { - void registerReporterImpl(const char* name, int priority, reporterCreatorFunc c) { - getReporters().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c)); + void registerReporterImpl(const char* name, int priority, reporterCreatorFunc c, bool isReporter) { + if(isReporter) + getReporters().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c)); + else + getListeners().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c)); } } // namespace detail -// see these issues on the reasoning for this: -// - https://github.com/onqtam/doctest/issues/143#issuecomment-414418903 -// - https://github.com/onqtam/doctest/issues/126 -void DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS() { std::cout << std::string(); } - } // namespace doctest #endif // DOCTEST_CONFIG_DISABLE