Compare commits

...

10 Commits

Author SHA1 Message Date
Niels Lohmann 080cfead28 ♻️ remove unnecessary if
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-05-15 10:22:04 +02:00
dependabot[bot] 630beaeb05 Bump step-security/harden-runner from 2.19.1 to 2.19.2 (#5170)
Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.19.1 to 2.19.2.
- [Release notes](https://github.com/step-security/harden-runner/releases)
- [Commits](https://github.com/step-security/harden-runner/compare/a5ad31d6a139d249332a2605b85202e8c0b78450...9ca718d3bf646d6534007c269a635b3e54cadf99)

---
updated-dependencies:
- dependency-name: step-security/harden-runner
  dependency-version: 2.19.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-14 20:04:56 +02:00
Niels Lohmann 5a05627b1f 🚨 fix warning (#5169) 2026-05-14 15:39:18 +02:00
dependabot[bot] 85cb7ea9aa Bump mkdocs-git-revision-date-localized-plugin in /docs/mkdocs (#5168)
Bumps [mkdocs-git-revision-date-localized-plugin](https://github.com/timvink/mkdocs-git-revision-date-localized-plugin) from 1.5.1 to 1.5.2.
- [Release notes](https://github.com/timvink/mkdocs-git-revision-date-localized-plugin/releases)
- [Commits](https://github.com/timvink/mkdocs-git-revision-date-localized-plugin/compare/v1.5.1...v1.5.2)

---
updated-dependencies:
- dependency-name: mkdocs-git-revision-date-localized-plugin
  dependency-version: 1.5.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-14 09:14:25 +02:00
SamareshSingh 7192763f15 Fix compile error when using nlohmann ordered_map with WITH_DEFAULT macros (#5163)
* Fix compile error when using nlohmann ordered_map with WITH_DEFAULT macros

ordered_map inherits its copy and move assignment from the underlying std vector, which requires value_type to be CopyAssignable. value_type is pair<const Key, T> whose assignment is deleted because of the const Key, so any code that assigns ordered_map (for example the ternary in NLOHMANN_JSON_FROM_WITH_DEFAULT) fails to compile (issue #5122). Provide assignment operators on ordered_map that rebuild via clear plus push_back for copy and transfer the underlying buffer for move, neither of which needs pair assignment. Also switch the map-shaped from_json overload from a transform plus inserter idiom to a range-for plus emplace, which avoids the same hazard.

Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>

* Update ordered_map.hpp

removed unwanted comments

Signed-off-by: SamareshSingh <97642706+ssam18@users.noreply.github.com>
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>

* Update json.hpp

Signed-off-by: SamareshSingh <97642706+ssam18@users.noreply.github.com>
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>

* Address CI issues for ordered_map fix

Declare an explicit defaulted destructor on ordered_map so the rule of five is complete (clang-tidy cppcoreguidelines-special-member-functions and hicpp-special-member-functions). Initialize the ordered_map field in the regression test struct so GCC effective-C++ stops flagging Example_5122 with a missing member initializer.

Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>

* Suppress redundant-member-init lint on Example_5122::c

The empty brace-init on c{} is required by GCC -Weffc++ to mark the member as initialized in the synthesized default constructor, but clang-tidy readability-redundant-member-init flags the same line because ordered_map already has a default constructor. The two checks pull in opposite directions, so add a targeted NOLINT to keep both happy.

Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>

* Address review: strong exception safety in copy-assign, simplify move-assign noexcept

Copy assignment now constructs a temporary copy before move-assigning the
Container subobject, preserving *this if the copy throws. Move assignment
uses std::is_nothrow_move_assignable<Container> for a cleaner noexcept
specifier, matching the style of the move constructor.

Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>

* Restore self-assignment check in copy-assign to satisfy cert-oop54-cpp

clang-tidy's cert-oop54-cpp flagged the previous revision because it could
not recognize the implicit self-safety of the copy-then-move pattern.
Restore the explicit `if (this != &other)` guard — strong exception safety
is preserved since the temporary copy is still constructed before the
move-assign of the Container subobject.

Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>

* Address review: add explicit self-assignment and move-assignment tests for ordered_map

Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>

* Address review: gate -Wself-assign-overloaded suppression on Clang version

-Wself-assign-overloaded was introduced in Clang 7. Older Clang versions fail the build with "unknown warning group" when the suppression pragma references it unconditionally. Use __has_warning inside an __clang__ branch so the suppression is only emitted on Clang versions that recognize the warning. The inner check stays inside the __clang__ guard because GCC does not provide __has_warning and would tokenize-error on the argument list.

Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>

* Address CI: drop unused gating macro to silence -Wunused-macros

The previous attempt defined JSON_TEST_5122_SUPPRESS_SELF_ASSIGN_OVERLOADED
as 0 unconditionally and then overrode it to 1 on Clang versions that recognize the warning. On those Clangs the initial define is immediately
undef'd without being read, which trips Clang's -Wunused-macros under -Weverything in the ci_test_clang job. Drop the macro and gate the
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH/POP pragmas directly with __has_warning inside the existing __clang__ branch.

Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>

---------

Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
Signed-off-by: SamareshSingh <97642706+ssam18@users.noreply.github.com>
2026-05-14 08:54:24 +02:00
Akhilesh Arora 93e49decbd Fix incomplete-type error in set_parents with ordered_json (#5167)
When iteration_proxy_value<iter_impl<ordered_json>> appears in a context
that requires it to be complete (function or lambda parameter), the
compiler instantiates basic_json<ordered_map> and walks into

    set_parents(iterator, typename iterator::difference_type)

while iterator is still incomplete, failing with "invalid use of
incomplete type".

basic_json::difference_type is already std::ptrdiff_t, so just naming
the underlying type directly avoids the dependent lookup. Behavior and
ABI are unchanged. This was the approach suggested in the issue thread.

Added a regression case in unit-ordered_json.cpp using the same trigger
pattern (lambda parameter naming the proxy type).

Fixes #3732

Signed-off-by: Akhilesh Arora <akhildawra@gmail.com>
2026-05-14 08:52:39 +02:00
trdesilva a0a4e7cc0b Add front methods to json_pointers (implements #4889) (#5152)
* Added front, pop_front, and push_front methods to json_pointers in order to facilitate root-to-leaf traversals of JSON object trees. (#4889)

Signed-off-by: trdesilva <5818730+trdesilva@users.noreply.github.com>

* undid VS autoformatting in irrelevant code

Signed-off-by: trdesilva <5818730+trdesilva@users.noreply.github.com>

* Ran make amalgamate, added navigation to json_pointer's new front methods in mkdocs, and fixed errors in documented complexity for those methods.

Signed-off-by: trdesilva <5818730+trdesilva@users.noreply.github.com>

* Fixed GCC 4.8 compile error caused by const iterators

Signed-off-by: trdesilva <5818730+trdesilva@users.noreply.github.com>

* Fixed another gcc-4.8 compile error

Signed-off-by: trdesilva <5818730+trdesilva@users.noreply.github.com>

* amalgamated

Signed-off-by: trdesilva <5818730+trdesilva@users.noreply.github.com>

---------

Signed-off-by: trdesilva <5818730+trdesilva@users.noreply.github.com>
2026-05-13 07:59:16 +02:00
dependabot[bot] 216c50365e Bump peaceiris/actions-gh-pages from 4.0.0 to 4.1.0 (#5166) 2026-05-13 07:23:10 +02:00
dependabot[bot] f0bf4c731a Bump actions/dependency-review-action from 4.9.0 to 5.0.0 (#5165)
Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.9.0 to 5.0.0.
- [Release notes](https://github.com/actions/dependency-review-action/releases)
- [Commits](https://github.com/actions/dependency-review-action/compare/2031cfc080254a8a887f58cffee85186f0e49e48...a1d282b36b6f3519aa1f3fc636f609c47dddb294)

---
updated-dependencies:
- dependency-name: actions/dependency-review-action
  dependency-version: 5.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-12 10:25:16 +02:00
Swastik Bose 4fad446897 docs: add IDs to @requirement tags to fix Doxygen autolinking (#5162)
Signed-off-by: Swastik Bose <cpswastik31@gmail.com>
2026-05-10 11:37:41 +02:00
37 changed files with 479 additions and 56 deletions
+2 -2
View File
@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1 uses: step-security/harden-runner@9ca718d3bf646d6534007c269a635b3e54cadf99 # v2.19.2
with: with:
egress-policy: audit egress-policy: audit
@@ -34,7 +34,7 @@ jobs:
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1 uses: step-security/harden-runner@9ca718d3bf646d6534007c269a635b3e54cadf99 # v2.19.2
with: with:
egress-policy: audit egress-policy: audit
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1 uses: step-security/harden-runner@9ca718d3bf646d6534007c269a635b3e54cadf99 # v2.19.2
with: with:
egress-policy: audit egress-policy: audit
+1 -1
View File
@@ -27,7 +27,7 @@ jobs:
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1 uses: step-security/harden-runner@9ca718d3bf646d6534007c269a635b3e54cadf99 # v2.19.2
with: with:
egress-policy: audit egress-policy: audit
@@ -19,7 +19,7 @@ jobs:
pull-requests: write pull-requests: write
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1 uses: step-security/harden-runner@9ca718d3bf646d6534007c269a635b3e54cadf99 # v2.19.2
with: with:
egress-policy: audit egress-policy: audit
+2 -2
View File
@@ -17,11 +17,11 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1 uses: step-security/harden-runner@9ca718d3bf646d6534007c269a635b3e54cadf99 # v2.19.2
with: with:
egress-policy: audit egress-policy: audit
- name: 'Checkout Repository' - name: 'Checkout Repository'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: 'Dependency Review' - name: 'Dependency Review'
uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0 uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
+1 -1
View File
@@ -27,7 +27,7 @@ jobs:
security-events: write security-events: write
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1 uses: step-security/harden-runner@9ca718d3bf646d6534007c269a635b3e54cadf99 # v2.19.2
with: with:
egress-policy: audit egress-policy: audit
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1 uses: step-security/harden-runner@9ca718d3bf646d6534007c269a635b3e54cadf99 # v2.19.2
with: with:
egress-policy: audit egress-policy: audit
+2 -2
View File
@@ -27,7 +27,7 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1 uses: step-security/harden-runner@9ca718d3bf646d6534007c269a635b3e54cadf99 # v2.19.2
with: with:
egress-policy: audit egress-policy: audit
@@ -40,7 +40,7 @@ jobs:
run: make build -C docs/mkdocs run: make build -C docs/mkdocs
- name: Deploy documentation - name: Deploy documentation
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0 uses: peaceiris/actions-gh-pages@84c30a85c19949d7eee79c4ff27748b70285e453 # v4.1.0
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/mkdocs/site publish_dir: ./docs/mkdocs/site
+1 -1
View File
@@ -36,7 +36,7 @@ jobs:
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1 uses: step-security/harden-runner@9ca718d3bf646d6534007c269a635b3e54cadf99 # v2.19.2
with: with:
egress-policy: audit egress-policy: audit
+1 -1
View File
@@ -32,7 +32,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1 uses: step-security/harden-runner@9ca718d3bf646d6534007c269a635b3e54cadf99 # v2.19.2
with: with:
egress-policy: audit egress-policy: audit
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1 uses: step-security/harden-runner@9ca718d3bf646d6534007c269a635b3e54cadf99 # v2.19.2
with: with:
egress-policy: audit egress-policy: audit
+4 -4
View File
@@ -46,7 +46,7 @@ jobs:
target: [ci_test_amalgamation, ci_test_single_header, ci_cppcheck, ci_cpplint, ci_reproducible_tests, ci_non_git_tests, ci_offline_testdata, ci_reuse_compliance, ci_test_valgrind] target: [ci_test_amalgamation, ci_test_single_header, ci_cppcheck, ci_cpplint, ci_reproducible_tests, ci_non_git_tests, ci_offline_testdata, ci_reuse_compliance, ci_test_valgrind]
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1 uses: step-security/harden-runner@9ca718d3bf646d6534007c269a635b3e54cadf99 # v2.19.2
with: with:
egress-policy: audit egress-policy: audit
@@ -98,7 +98,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1 uses: step-security/harden-runner@9ca718d3bf646d6534007c269a635b3e54cadf99 # v2.19.2
with: with:
egress-policy: audit egress-policy: audit
@@ -251,7 +251,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1 uses: step-security/harden-runner@9ca718d3bf646d6534007c269a635b3e54cadf99 # v2.19.2
with: with:
egress-policy: audit egress-policy: audit
@@ -272,7 +272,7 @@ jobs:
target: [ci_test_examples, ci_test_build_documentation] target: [ci_test_examples, ci_test_build_documentation]
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1 uses: step-security/harden-runner@9ca718d3bf646d6534007c269a635b3e54cadf99 # v2.19.2
with: with:
egress-policy: audit egress-policy: audit
+1 -1
View File
@@ -1 +1 @@
cppcheck==1.5.0 cppcheck==1.5.1
@@ -0,0 +1,37 @@
# <small>nlohmann::json_pointer::</small>front
```cpp
const string_t& front() const;
```
Return the first reference token.
## Return value
First reference token.
## Exceptions
Throws [out_of_range.405](../../home/exceptions.md#jsonexceptionout_of_range405) if the JSON pointer has no parent.
## Complexity
Constant.
## Examples
??? example
The example shows the usage of `front`.
```cpp
--8<-- "examples/json_pointer__front.cpp"
```
Output:
```json
--8<-- "examples/json_pointer__front.output"
```
## Version history
@@ -37,6 +37,9 @@ are the base for JSON patches.
- [**pop_back**](pop_back.md) - remove the last reference token - [**pop_back**](pop_back.md) - remove the last reference token
- [**back**](back.md) - return last reference token - [**back**](back.md) - return last reference token
- [**push_back**](push_back.md) - append an unescaped token at the end of the pointer - [**push_back**](push_back.md) - append an unescaped token at the end of the pointer
- [**pop_front**](pop_front.md) - remove the first reference token
- [**front**](front.md) - return first reference token
- [**push_front**](push_front.md) - append an unescaped token at the start of the pointer
- [**empty**](empty.md) - return whether the pointer points to the root document - [**empty**](empty.md) - return whether the pointer points to the root document
## Literals ## Literals
@@ -0,0 +1,33 @@
# <small>nlohmann::json_pointer::</small>pop_front
```cpp
void pop_front();
```
Remove the first reference token.
## Exceptions
Throws [out_of_range.405](../../home/exceptions.md#jsonexceptionout_of_range405) if the JSON pointer has no parent.
## Complexity
Linear in the number of reference tokens in the `json_pointer`.
## Examples
??? example
The example shows the usage of `pop_front`.
```cpp
--8<-- "examples/json_pointer__pop_front.cpp"
```
Output:
```json
--8<-- "examples/json_pointer__pop_front.output"
```
## Version history
@@ -0,0 +1,36 @@
# <small>nlohmann::json_pointer::</small>push_front
```cpp
void push_front(const string_t& token);
void push_front(string_t&& token);
```
Append an unescaped token at the start of the reference pointer.
## Parameters
`token` (in)
: token to add
## Complexity
Linear in the number of reference tokens in the `json_pointer`.
## Examples
??? example
The example shows the result of `push_front` for different JSON Pointers.
```cpp
--8<-- "examples/json_pointer__push_front.cpp"
```
Output:
```json
--8<-- "examples/json_pointer__push_front.output"
```
## Version history
@@ -0,0 +1,15 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// different JSON Pointers
json::json_pointer ptr1("/foo");
json::json_pointer ptr2("/foo/0");
// call empty()
std::cout << "first reference token of \"" << ptr1 << "\" is \"" << ptr1.front() << "\"\n"
<< "first reference token of \"" << ptr2 << "\" is \"" << ptr2.front() << "\"" << std::endl;
}
@@ -0,0 +1,2 @@
first reference token of "/foo" is "foo"
first reference token of "/foo/0" is "foo"
@@ -0,0 +1,21 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create empty JSON Pointer
json::json_pointer ptr("/foo/bar/baz");
std::cout << "\"" << ptr << "\"\n";
// call pop_front()
ptr.pop_front();
std::cout << "\"" << ptr << "\"\n";
ptr.pop_front();
std::cout << "\"" << ptr << "\"\n";
ptr.pop_front();
std::cout << "\"" << ptr << "\"\n";
}
@@ -0,0 +1,4 @@
"/foo/bar/baz"
"/bar/baz"
"/baz"
""
@@ -0,0 +1,21 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create empty JSON Pointer
json::json_pointer ptr;
std::cout << "\"" << ptr << "\"\n";
// call push_front()
ptr.push_front("foo");
std::cout << "\"" << ptr << "\"\n";
ptr.push_front("0");
std::cout << "\"" << ptr << "\"\n";
ptr.push_front("bar");
std::cout << "\"" << ptr << "\"\n";
}
@@ -0,0 +1,4 @@
""
"/foo"
"/0/foo"
"/bar/0/foo"
+3
View File
@@ -233,6 +233,7 @@ nav:
- '(Constructor)': api/json_pointer/json_pointer.md - '(Constructor)': api/json_pointer/json_pointer.md
- 'back': api/json_pointer/back.md - 'back': api/json_pointer/back.md
- 'empty': api/json_pointer/empty.md - 'empty': api/json_pointer/empty.md
- 'front': api/json_pointer/front.md
- 'operator string_t': api/json_pointer/operator_string_t.md - 'operator string_t': api/json_pointer/operator_string_t.md
- 'operator==': api/json_pointer/operator_eq.md - 'operator==': api/json_pointer/operator_eq.md
- 'operator!=': api/json_pointer/operator_ne.md - 'operator!=': api/json_pointer/operator_ne.md
@@ -240,7 +241,9 @@ nav:
- 'operator/=': api/json_pointer/operator_slasheq.md - 'operator/=': api/json_pointer/operator_slasheq.md
- 'parent_pointer': api/json_pointer/parent_pointer.md - 'parent_pointer': api/json_pointer/parent_pointer.md
- 'pop_back': api/json_pointer/pop_back.md - 'pop_back': api/json_pointer/pop_back.md
- 'pop_front': api/json_pointer/pop_front.md
- 'push_back': api/json_pointer/push_back.md - 'push_back': api/json_pointer/push_back.md
- 'push_front': api/json_pointer/push_front.md
- 'string_t': api/json_pointer/string_t.md - 'string_t': api/json_pointer/string_t.md
- 'to_string': api/json_pointer/to_string.md - 'to_string': api/json_pointer/to_string.md
- json_sax: - json_sax:
+1 -1
View File
@@ -1,7 +1,7 @@
wheel==0.47.0 wheel==0.47.0
mkdocs==1.6.1 # documentation framework mkdocs==1.6.1 # documentation framework
mkdocs-git-revision-date-localized-plugin==1.5.1 # plugin "git-revision-date-localized" mkdocs-git-revision-date-localized-plugin==1.5.2 # plugin "git-revision-date-localized"
mkdocs-material==9.7.6 # theme for mkdocs mkdocs-material==9.7.6 # theme for mkdocs
mkdocs-material-extensions==1.3.1 # extensions mkdocs-material-extensions==1.3.1 # extensions
mkdocs-minify-plugin==0.8.0 # plugin "minify" mkdocs-minify-plugin==0.8.0 # plugin "minify"
@@ -388,14 +388,10 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
ConstructibleObjectType ret; ConstructibleObjectType ret;
const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>(); const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
using value_type = typename ConstructibleObjectType::value_type; for (const auto& p : *inner_object)
std::transform(
inner_object->begin(), inner_object->end(),
std::inserter(ret, ret.begin()),
[](typename BasicJsonType::object_t::value_type const & p)
{ {
return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>()); ret.emplace(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
}); }
obj = std::move(ret); obj = std::move(ret);
} }
@@ -214,10 +214,7 @@ struct external_constructor<value_t::array>
j.m_data.m_type = value_t::array; j.m_data.m_type = value_t::array;
j.m_data.m_value = value_t::array; j.m_data.m_value = value_t::array;
j.m_data.m_value.array->resize(arr.size()); j.m_data.m_value.array->resize(arr.size());
if (arr.size() > 0)
{
std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin()); std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
}
j.set_parents(); j.set_parents();
j.assert_invariant(); j.assert_invariant();
} }
@@ -35,7 +35,7 @@ This class implements a both iterators (iterator and const_iterator) for the
been set (e.g., by a constructor or a copy assignment). If the iterator is been set (e.g., by a constructor or a copy assignment). If the iterator is
default-constructed, it is *uninitialized* and most methods are undefined. default-constructed, it is *uninitialized* and most methods are undefined.
**The library uses assertions to detect calls on uninitialized iterators.** **The library uses assertions to detect calls on uninitialized iterators.**
@requirement The class satisfies the following concept requirements: @requirement REQ-JSON-01 The class satisfies the following concept requirements:
- -
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
The iterator that can be moved can be moved in both directions (i.e. The iterator that can be moved can be moved in both directions (i.e.
@@ -29,7 +29,7 @@ namespace detail
iterator (to create @ref reverse_iterator) and @ref const_iterator (to iterator (to create @ref reverse_iterator) and @ref const_iterator (to
create @ref const_reverse_iterator). create @ref const_reverse_iterator).
@requirement The class satisfies the following concept requirements: @requirement REQ-JSON-02 The class satisfies the following concept requirements:
- -
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
The iterator that can be moved can be moved in both directions (i.e. The iterator that can be moved can be moved in both directions (i.e.
+38
View File
@@ -154,6 +154,44 @@ class json_pointer
return res; return res;
} }
/// @brief remove first reference token
/// @sa https://json.nlohmann.me/api/json_pointer/pop_front/
void pop_front()
{
if (JSON_HEDLEY_UNLIKELY(empty()))
{
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
}
reference_tokens.erase(reference_tokens.begin());
}
/// @brief return first reference token
/// @sa https://json.nlohmann.me/api/json_pointer/front/
const string_t& front() const
{
if (JSON_HEDLEY_UNLIKELY(empty()))
{
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
}
return reference_tokens.front();
}
/// @brief append an unescaped token at the start of the reference pointer
/// @sa https://json.nlohmann.me/api/json_pointer/push_front/
void push_front(const string_t& token)
{
reference_tokens.insert(reference_tokens.begin(), token);
}
/// @brief append an unescaped token at the start of the reference pointer
/// @sa https://json.nlohmann.me/api/json_pointer/push_front/
void push_front(string_t&& token)
{
reference_tokens.insert(reference_tokens.begin(), std::move(token));
}
/// @brief remove last reference token /// @brief remove last reference token
/// @sa https://json.nlohmann.me/api/json_pointer/pop_back/ /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/
void pop_back() void pop_back()
+15 -2
View File
@@ -825,14 +825,27 @@ class serializer
o->write_characters(begin, static_cast<size_t>(end - begin)); o->write_characters(begin, static_cast<size_t>(end - begin));
} }
JSON_HEDLEY_NON_NULL(1)
static int snprintf_float(char* buf, std::size_t size, int d, double x)
{
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
return (std::snprintf)(buf, size, "%.*g", d, x);
}
JSON_HEDLEY_NON_NULL(1)
static int snprintf_float(char* buf, std::size_t size, int d, long double x)
{
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
return (std::snprintf)(buf, size, "%.*lg", d, x);
}
void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/) void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
{ {
// get the number of digits for a float -> text -> float round-trip // get the number of digits for a float -> text -> float round-trip
static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10; static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
// the actual conversion // the actual conversion
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) std::ptrdiff_t len = snprintf_float(number_buffer.data(), number_buffer.size(), d, x);
std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
// negative value indicates an error // negative value indicates an error
JSON_ASSERT(len > 0); JSON_ASSERT(len > 0);
+2 -2
View File
@@ -741,10 +741,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
#endif #endif
} }
iterator set_parents(iterator it, typename iterator::difference_type count_set_parents) iterator set_parents(iterator it, std::ptrdiff_t count_set_parents)
{ {
#if JSON_DIAGNOSTICS #if JSON_DIAGNOSTICS
for (typename iterator::difference_type i = 0; i < count_set_parents; ++i) for (std::ptrdiff_t i = 0; i < count_set_parents; ++i)
{ {
(it + i)->m_parent = this; (it + i)->m_parent = this;
} }
+19
View File
@@ -50,6 +50,25 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
: Container{first, last, alloc} {} : Container{first, last, alloc} {}
ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() ) ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
: Container{init, alloc} {} : Container{init, alloc} {}
ordered_map(const ordered_map&) = default;
ordered_map(ordered_map&&) noexcept(std::is_nothrow_move_constructible<Container>::value) = default;
~ordered_map() = default;
ordered_map& operator=(const ordered_map& other)
{
if (this != &other)
{
ordered_map tmp(other);
Container::operator=(std::move(static_cast<Container&>(tmp)));
}
return *this;
}
ordered_map& operator=(ordered_map&& other) noexcept(std::is_nothrow_move_assignable<Container>::value)
{
Container::operator=(std::move(static_cast<Container&>(other)));
return *this;
}
std::pair<iterator, bool> emplace(const key_type& key, T&& t) std::pair<iterator, bool> emplace(const key_type& key, T&& t)
{ {
+79 -16
View File
@@ -5306,14 +5306,10 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
ConstructibleObjectType ret; ConstructibleObjectType ret;
const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>(); const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
using value_type = typename ConstructibleObjectType::value_type; for (const auto& p : *inner_object)
std::transform(
inner_object->begin(), inner_object->end(),
std::inserter(ret, ret.begin()),
[](typename BasicJsonType::object_t::value_type const & p)
{ {
return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>()); ret.emplace(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
}); }
obj = std::move(ret); obj = std::move(ret);
} }
@@ -6027,10 +6023,7 @@ struct external_constructor<value_t::array>
j.m_data.m_type = value_t::array; j.m_data.m_type = value_t::array;
j.m_data.m_value = value_t::array; j.m_data.m_value = value_t::array;
j.m_data.m_value.array->resize(arr.size()); j.m_data.m_value.array->resize(arr.size());
if (arr.size() > 0)
{
std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin()); std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
}
j.set_parents(); j.set_parents();
j.assert_invariant(); j.assert_invariant();
} }
@@ -13807,7 +13800,7 @@ This class implements a both iterators (iterator and const_iterator) for the
been set (e.g., by a constructor or a copy assignment). If the iterator is been set (e.g., by a constructor or a copy assignment). If the iterator is
default-constructed, it is *uninitialized* and most methods are undefined. default-constructed, it is *uninitialized* and most methods are undefined.
**The library uses assertions to detect calls on uninitialized iterators.** **The library uses assertions to detect calls on uninitialized iterators.**
@requirement The class satisfies the following concept requirements: @requirement REQ-JSON-01 The class satisfies the following concept requirements:
- -
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
The iterator that can be moved can be moved in both directions (i.e. The iterator that can be moved can be moved in both directions (i.e.
@@ -14566,7 +14559,7 @@ namespace detail
iterator (to create @ref reverse_iterator) and @ref const_iterator (to iterator (to create @ref reverse_iterator) and @ref const_iterator (to
create @ref const_reverse_iterator). create @ref const_reverse_iterator).
@requirement The class satisfies the following concept requirements: @requirement REQ-JSON-02 The class satisfies the following concept requirements:
- -
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
The iterator that can be moved can be moved in both directions (i.e. The iterator that can be moved can be moved in both directions (i.e.
@@ -14872,6 +14865,44 @@ class json_pointer
return res; return res;
} }
/// @brief remove first reference token
/// @sa https://json.nlohmann.me/api/json_pointer/pop_front/
void pop_front()
{
if (JSON_HEDLEY_UNLIKELY(empty()))
{
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
}
reference_tokens.erase(reference_tokens.begin());
}
/// @brief return first reference token
/// @sa https://json.nlohmann.me/api/json_pointer/front/
const string_t& front() const
{
if (JSON_HEDLEY_UNLIKELY(empty()))
{
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
}
return reference_tokens.front();
}
/// @brief append an unescaped token at the start of the reference pointer
/// @sa https://json.nlohmann.me/api/json_pointer/push_front/
void push_front(const string_t& token)
{
reference_tokens.insert(reference_tokens.begin(), token);
}
/// @brief append an unescaped token at the start of the reference pointer
/// @sa https://json.nlohmann.me/api/json_pointer/push_front/
void push_front(string_t&& token)
{
reference_tokens.insert(reference_tokens.begin(), std::move(token));
}
/// @brief remove last reference token /// @brief remove last reference token
/// @sa https://json.nlohmann.me/api/json_pointer/pop_back/ /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/
void pop_back() void pop_back()
@@ -19773,14 +19804,27 @@ class serializer
o->write_characters(begin, static_cast<size_t>(end - begin)); o->write_characters(begin, static_cast<size_t>(end - begin));
} }
JSON_HEDLEY_NON_NULL(1)
static int snprintf_float(char* buf, std::size_t size, int d, double x)
{
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
return (std::snprintf)(buf, size, "%.*g", d, x);
}
JSON_HEDLEY_NON_NULL(1)
static int snprintf_float(char* buf, std::size_t size, int d, long double x)
{
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
return (std::snprintf)(buf, size, "%.*lg", d, x);
}
void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/) void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
{ {
// get the number of digits for a float -> text -> float round-trip // get the number of digits for a float -> text -> float round-trip
static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10; static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
// the actual conversion // the actual conversion
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) std::ptrdiff_t len = snprintf_float(number_buffer.data(), number_buffer.size(), d, x);
std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
// negative value indicates an error // negative value indicates an error
JSON_ASSERT(len > 0); JSON_ASSERT(len > 0);
@@ -19994,6 +20038,25 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
: Container{first, last, alloc} {} : Container{first, last, alloc} {}
ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() ) ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
: Container{init, alloc} {} : Container{init, alloc} {}
ordered_map(const ordered_map&) = default;
ordered_map(ordered_map&&) noexcept(std::is_nothrow_move_constructible<Container>::value) = default;
~ordered_map() = default;
ordered_map& operator=(const ordered_map& other)
{
if (this != &other)
{
ordered_map tmp(other);
Container::operator=(std::move(static_cast<Container&>(tmp)));
}
return *this;
}
ordered_map& operator=(ordered_map&& other) noexcept(std::is_nothrow_move_assignable<Container>::value)
{
Container::operator=(std::move(static_cast<Container&>(other)));
return *this;
}
std::pair<iterator, bool> emplace(const key_type& key, T&& t) std::pair<iterator, bool> emplace(const key_type& key, T&& t)
{ {
@@ -20982,10 +21045,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
#endif #endif
} }
iterator set_parents(iterator it, typename iterator::difference_type count_set_parents) iterator set_parents(iterator it, std::ptrdiff_t count_set_parents)
{ {
#if JSON_DIAGNOSTICS #if JSON_DIAGNOSTICS
for (typename iterator::difference_type i = 0; i < count_set_parents; ++i) for (std::ptrdiff_t i = 0; i < count_set_parents; ++i)
{ {
(it + i)->m_parent = this; (it + i)->m_parent = this;
} }
+19 -2
View File
@@ -564,6 +564,14 @@ TEST_CASE("JSON pointers")
CHECK(!ptr.empty()); CHECK(!ptr.empty());
CHECK(j[ptr] == j["answer"]["everything"]); CHECK(j[ptr] == j["answer"]["everything"]);
ptr.pop_front();
CHECK(ptr.front() == "everything");
ptr.pop_front();
CHECK(ptr.empty());
ptr.push_front("everything");
ptr.push_front(answer);
CHECK(j[ptr] == j["answer"]["everything"]);
// check access via const pointer // check access via const pointer
const auto cptr = ptr; const auto cptr = ptr;
CHECK(cptr.back() == "everything"); CHECK(cptr.back() == "everything");
@@ -588,8 +596,17 @@ TEST_CASE("JSON pointers")
CHECK(ptr.empty()); CHECK(ptr.empty());
CHECK(j[ptr] == j); CHECK(j[ptr] == j);
CHECK_THROWS_WITH(ptr.pop_back(), CHECK_THROWS_WITH_AS(ptr.pop_back(),
"[json.exception.out_of_range.405] JSON pointer has no parent"); "[json.exception.out_of_range.405] JSON pointer has no parent", json::out_of_range&);
CHECK_THROWS_WITH_AS(ptr.back(),
"[json.exception.out_of_range.405] JSON pointer has no parent", json::out_of_range&);
CHECK_THROWS_WITH_AS(ptr.pop_front(),
"[json.exception.out_of_range.405] JSON pointer has no parent", json::out_of_range&);
CHECK_THROWS_WITH_AS(ptr.front(),
"[json.exception.out_of_range.405] JSON pointer has no parent", json::out_of_range&);
} }
SECTION("operators") SECTION("operators")
+12
View File
@@ -69,3 +69,15 @@ TEST_CASE("ordered_json")
CHECK(oj1.size() == 4); CHECK(oj1.size() == 4);
CHECK(oj1.dump() == "{\"c\":1,\"b\":2,\"a\":3,\"d\":42}"); CHECK(oj1.dump() == "{\"c\":1,\"b\":2,\"a\":3,\"d\":42}");
} }
TEST_CASE("regression test for issue #3732 - iteration_proxy_value<iter_impl<ordered_json>>")
{
// Naming the proxy type in a function-parameter position forces eager
// instantiation of basic_json<ordered_map>; previously this hit an
// incomplete-type error in set_parents().
auto fn = [](nlohmann::detail::iteration_proxy_value<nlohmann::detail::iter_impl<nlohmann::ordered_json>> const & val)
{
return val.value();
};
static_cast<void>(fn);
}
+89
View File
@@ -1240,4 +1240,93 @@ TEST_CASE("regression test #5074 - single-element brace init with JSON_BRACE_INI
} }
#endif #endif
struct Example_5122
{
float b = 2;
nlohmann::ordered_map<std::string, std::string> c{}; // NOLINT(readability-redundant-member-init): needed for GCC -Weffc++
int a = 1;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Example_5122, b, c, a)
};
TEST_CASE("regression test #5122 - from_json into types holding nlohmann::ordered_map")
{
Example_5122 src;
src.c.emplace("first", "1");
src.c.emplace("second", "2");
ordered_json const j = src;
Example_5122 const dst = j.get<Example_5122>();
CHECK(dst.b == src.b);
CHECK(dst.a == src.a);
REQUIRE(dst.c.size() == src.c.size());
auto src_it = src.c.begin();
auto dst_it = dst.c.begin();
for (; src_it != src.c.end(); ++src_it, ++dst_it)
{
CHECK(dst_it->first == src_it->first);
CHECK(dst_it->second == src_it->second);
}
}
// -Wself-assign-overloaded was introduced in Clang 7. Gate the pragma on
// __has_warning so older Clang versions do not error with "unknown warning
// group". The __has_warning check has to stay inside the __clang__ branch
// because GCC does not provide it and would tokenize-error on the argument.
#if defined(__clang__) && defined(__has_warning)
#if __has_warning("-Wself-assign-overloaded")
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
DOCTEST_CLANG_SUPPRESS_WARNING("-Wself-assign-overloaded")
#endif
#endif
TEST_CASE("regression test #5122 - nlohmann::ordered_map copy-assignment is self-assignment safe")
{
nlohmann::ordered_map<std::string, std::string> m;
m.emplace("first", "1");
m.emplace("second", "2");
// Insertion order is preserved by ordered_map, so we can check it directly.
m = m;
REQUIRE(m.size() == 2);
auto it = m.begin();
CHECK(it->first == "first");
CHECK(it->second == "1");
++it;
CHECK(it->first == "second");
CHECK(it->second == "2");
}
#if defined(__clang__) && defined(__has_warning)
#if __has_warning("-Wself-assign-overloaded")
DOCTEST_CLANG_SUPPRESS_WARNING_POP
#endif
#endif
TEST_CASE("regression test #5122 - nlohmann::ordered_map move-assignment transfers contents")
{
nlohmann::ordered_map<std::string, std::string> src;
src.emplace("first", "1");
src.emplace("second", "2");
nlohmann::ordered_map<std::string, std::string> dst;
dst.emplace("stale", "x");
dst = std::move(src);
REQUIRE(dst.size() == 2);
auto it = dst.begin();
CHECK(it->first == "first");
CHECK(it->second == "1");
++it;
CHECK(it->first == "second");
CHECK(it->second == "2");
// Re-assigning into the moved-from object must leave it in a usable state.
src = nlohmann::ordered_map<std::string, std::string> {};
src.emplace("after-move", "3");
REQUIRE(src.size() == 1);
CHECK(src.begin()->first == "after-move");
}
DOCTEST_CLANG_SUPPRESS_WARNING_POP DOCTEST_CLANG_SUPPRESS_WARNING_POP