mirror of
https://github.com/nlohmann/json.git
synced 2026-09-28 02:30:32 +00:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de261db5ae | ||
|
|
013923dc89 | ||
|
|
82601da6ec | ||
|
|
1cd636bd61 |
@@ -363,7 +363,7 @@ std::cout << j_string << " == " << serialized_string << std::endl;
|
||||
|
||||
[`.dump()`](https://json.nlohmann.me/api/basic_json/dump/) returns the originally stored string value.
|
||||
|
||||
Note the library only supports UTF-8. When you store strings with different encodings in the library, calling [`dump()`](https://json.nlohmann.me/api/basic_json/dump/) may throw an exception unless `json::error_handler_t::replace`, `json::error_handler_t::ignore`, or `json::error_handler_t::keep` are used as error handlers.
|
||||
Note the library only supports UTF-8. When you store strings with different encodings in the library, calling [`dump()`](https://json.nlohmann.me/api/basic_json/dump/) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers.
|
||||
|
||||
#### To/from streams (e.g., files, string streams)
|
||||
|
||||
@@ -1915,7 +1915,7 @@ The library supports **Unicode input** as follows:
|
||||
- [Unicode noncharacters](https://www.unicode.org/faq/private_use.html#nonchar1) will not be replaced by the library.
|
||||
- Invalid surrogates (e.g., incomplete pairs such as `\uDEAD`) will yield parse errors.
|
||||
- The strings stored in the library are UTF-8 encoded. When using the default string type (`std::string`), note that its length/size functions return the number of stored bytes rather than the number of characters or glyphs.
|
||||
- When you store strings with different encodings in the library, calling [`dump()`](https://json.nlohmann.me/api/basic_json/dump/) may throw an exception unless `json::error_handler_t::replace`, `json::error_handler_t::ignore`, or `json::error_handler_t::keep` are used as error handlers.
|
||||
- When you store strings with different encodings in the library, calling [`dump()`](https://json.nlohmann.me/api/basic_json/dump/) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers.
|
||||
- To store wide strings (e.g., `std::wstring`), you need to convert them to a UTF-8 encoded `std::string` before, see [an example](https://json.nlohmann.me/home/faq/#wide-string-handling).
|
||||
|
||||
### Comments in JSON
|
||||
|
||||
@@ -16,6 +16,7 @@ INSERT INTO searchIndex(name, type, path) VALUES ('basic_json', 'Class', 'api/ba
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::accept', 'Function', 'api/basic_json/accept/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::array', 'Function', 'api/basic_json/array/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::array_t', 'Type', 'api/basic_json/array_t/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::as_base_class', 'Method', 'api/basic_json/as_base_class/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::at', 'Method', 'api/basic_json/at/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::back', 'Method', 'api/basic_json/back/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::basic_json', 'Constructor', 'api/basic_json/basic_json/index.html');
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
# <small>nlohmann::basic_json::</small>as_base_class
|
||||
|
||||
```cpp
|
||||
json_base_class_t& as_base_class() noexcept;
|
||||
const json_base_class_t& as_base_class() const noexcept;
|
||||
```
|
||||
|
||||
Returns a reference to this object as its custom base class [`json_base_class_t`](json_base_class_t.md). No copy is
|
||||
made.
|
||||
|
||||
Since `basic_json` derives from `json_base_class_t`, a member of `basic_json` hides any member of the custom base class
|
||||
with the same name. This function makes such hidden members accessible again.
|
||||
|
||||
## Return value
|
||||
|
||||
reference to this object as [`json_base_class_t`](json_base_class_t.md)
|
||||
|
||||
## Exception safety
|
||||
|
||||
No-throw guarantee: this function never throws exceptions.
|
||||
|
||||
## Complexity
|
||||
|
||||
Constant.
|
||||
|
||||
## Notes
|
||||
|
||||
The function is equivalent to `static_cast<json_base_class_t&>(j)` (or `static_cast<const json_base_class_t&>(j)`).
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example shows how to use `as_base_class` to access members of the custom base class that are hidden by members
|
||||
of `basic_json`.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/as_base_class.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
--8<-- "examples/as_base_class.output"
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [json_base_class_t](json_base_class_t.md) - type of the custom base class
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.13.0.
|
||||
@@ -25,15 +25,10 @@ and `ensure_ascii` parameters.
|
||||
result consists of ASCII characters only.
|
||||
|
||||
`error_handler` (in)
|
||||
: how to react on decoding errors; there are four possible values (see [`error_handler_t`](error_handler_t.md)):
|
||||
|
||||
- `strict`: throw a [`type_error`](../../home/exceptions.md#type-errors) exception in case a decoding error occurs
|
||||
(default),
|
||||
- `replace`: replace invalid UTF-8 sequences with U+FFFD (� REPLACEMENT CHARACTER),
|
||||
- `ignore`: ignore invalid UTF-8 sequences during serialization; all valid bytes are copied to the output unchanged,
|
||||
and invalid bytes are dropped, and
|
||||
- `keep`: keep invalid UTF-8 sequences during serialization; all bytes are copied to the output unchanged, so the
|
||||
result is not valid UTF-8.
|
||||
: how to react on decoding errors; there are three possible values (see [`error_handler_t`](error_handler_t.md):
|
||||
`strict` (throws an exception in case a decoding error occurs; default), `replace` (replace invalid UTF-8 sequences
|
||||
with U+FFFD), and `ignore` (ignore invalid UTF-8 sequences during serialization; all valid bytes are copied to the
|
||||
output unchanged, and invalid bytes are dropped)).
|
||||
|
||||
## Return value
|
||||
|
||||
@@ -99,4 +94,3 @@ Binary values are serialized as an object containing two keys:
|
||||
- Indentation character `indent_char`, option `ensure_ascii` and exceptions added in version 3.0.0.
|
||||
- Error handlers added in version 3.4.0.
|
||||
- Serialization of binary values added in version 3.8.0.
|
||||
- Error handler value `keep` added in version 3.13.0.
|
||||
|
||||
@@ -4,13 +4,12 @@
|
||||
enum class error_handler_t {
|
||||
strict,
|
||||
replace,
|
||||
ignore,
|
||||
keep
|
||||
ignore
|
||||
};
|
||||
```
|
||||
|
||||
This enumeration is used in the [`dump`](dump.md) function to choose how to treat decoding errors while serializing a
|
||||
`basic_json` value. Four values are differentiated:
|
||||
`basic_json` value. Three values are differentiated:
|
||||
|
||||
strict
|
||||
: throw a `type_error` exception in case of invalid UTF-8
|
||||
@@ -21,12 +20,6 @@ replace
|
||||
ignore
|
||||
: ignore invalid UTF-8 sequences; all valid bytes are copied to the output unchanged, and invalid bytes are dropped
|
||||
|
||||
keep
|
||||
: keep invalid UTF-8 sequences; all bytes are copied to the output unchanged. Valid characters are still escaped as
|
||||
usual (e.g., `"`, `\\`, and control characters), so the result has valid JSON syntax, but it is not valid UTF-8.
|
||||
In particular, [`parse`](parse.md) rejects it, and with `ensure_ascii` set to `true`, the invalid bytes are the
|
||||
only non-ASCII bytes of the output.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
@@ -47,4 +40,3 @@ keep
|
||||
## Version history
|
||||
|
||||
- Added in version 3.4.0.
|
||||
- Added value `keep` in version 3.13.0.
|
||||
|
||||
@@ -200,6 +200,7 @@ Direct access to the stored value of a JSON value.
|
||||
- [**get_ref**](get_ref.md) - get a reference value
|
||||
- [**operator ValueType**](operator_ValueType.md) - get a value
|
||||
- [**get_binary**](get_binary.md) - get a binary value
|
||||
- [**as_base_class**](as_base_class.md) - access the custom base class
|
||||
|
||||
### Element access
|
||||
|
||||
|
||||
@@ -27,6 +27,18 @@ A `CustomBaseClass` with non-static data members forfeits `basic_json`'s
|
||||
[standard layout](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType) guarantee. See
|
||||
[Template Parameter Requirements](../../features/types/template_parameters.md#custombaseclass).
|
||||
|
||||
#### Name conflicts
|
||||
|
||||
Since `basic_json` derives from `CustomBaseClass`, members of `basic_json` hide members of `CustomBaseClass` with the
|
||||
same name. Hidden members remain accessible via [`as_base_class`](as_base_class.md) or by casting the value to
|
||||
`json_base_class_t`.
|
||||
|
||||
!!! warning "Avoid generic member names"
|
||||
|
||||
Future versions of the library may add members to `basic_json` that hide members of `CustomBaseClass` that are
|
||||
accessible today. To reduce the risk of such conflicts, avoid generic names for the members of `CustomBaseClass`,
|
||||
for instance by using a distinctive prefix.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
@@ -43,6 +55,11 @@ A `CustomBaseClass` with non-static data members forfeits `basic_json`'s
|
||||
--8<-- "examples/json_base_class_t.output"
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [as_base_class](as_base_class.md) - access the custom base class
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.12.0.
|
||||
- Made a public member type in version 3.13.0; it was private before, so it could not be named outside the class.
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
class base_class_with_hidden_members
|
||||
{
|
||||
public:
|
||||
const char* type_name() const noexcept
|
||||
{
|
||||
return "my_type_name";
|
||||
}
|
||||
|
||||
std::size_t size() const noexcept
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
};
|
||||
|
||||
using json = nlohmann::basic_json <
|
||||
std::map,
|
||||
std::vector,
|
||||
std::string,
|
||||
bool,
|
||||
std::int64_t,
|
||||
std::uint64_t,
|
||||
double,
|
||||
std::allocator,
|
||||
nlohmann::adl_serializer,
|
||||
std::vector<std::uint8_t>,
|
||||
base_class_with_hidden_members
|
||||
>;
|
||||
|
||||
int main()
|
||||
{
|
||||
json j = {1, 2, 3};
|
||||
|
||||
// the members of basic_json hide the members of the base class
|
||||
std::cout << j.type_name() << ' ' << j.size() << '\n';
|
||||
|
||||
// access the hidden members of the base class
|
||||
std::cout << j.as_base_class().type_name() << ' ' << j.as_base_class().size() << '\n';
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
array 3
|
||||
my_type_name 42
|
||||
@@ -1,4 +1,3 @@
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
@@ -22,12 +21,4 @@ int main()
|
||||
<< "\nstring with ignored invalid characters: "
|
||||
<< j_invalid.dump(-1, ' ', false, json::error_handler_t::ignore)
|
||||
<< '\n';
|
||||
|
||||
// the invalid byte is kept; print the result byte-wise to make it visible
|
||||
std::cout << "string with kept invalid characters:";
|
||||
for (const unsigned char c : j_invalid.dump(-1, ' ', false, json::error_handler_t::keep))
|
||||
{
|
||||
std::cout << ' ' << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(c);
|
||||
}
|
||||
std::cout << '\n';
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
[json.exception.type_error.316] invalid UTF-8 byte at index 2: 0xA9
|
||||
string with replaced invalid characters: "ä�ü"
|
||||
string with ignored invalid characters: "äü"
|
||||
string with kept invalid characters: 22 c3 a4 a9 c3 bc 22
|
||||
|
||||
@@ -64,7 +64,6 @@ serialization fails by default. The fourth argument of `dump` selects an
|
||||
- `strict` (default) — throw a [`type_error.316`](../home/exceptions.md#jsonexceptiontype_error316) exception.
|
||||
- `replace` — replace invalid bytes with the Unicode replacement character U+FFFD (`�`).
|
||||
- `ignore` — silently drop invalid bytes.
|
||||
- `keep` — copy invalid bytes to the output unchanged; the result is not valid UTF-8.
|
||||
|
||||
??? example
|
||||
|
||||
|
||||
@@ -755,7 +755,6 @@ The `dump()` function only works with UTF-8 encoded strings; that is, if you ass
|
||||
- Pass an error handler as last parameter to the `dump()` function to avoid this exception:
|
||||
- `json::error_handler_t::replace` will replace invalid bytes sequences with `U+FFFD`
|
||||
- `json::error_handler_t::ignore` will silently ignore invalid byte sequences
|
||||
- `json::error_handler_t::keep` will copy invalid byte sequences to the output unchanged
|
||||
|
||||
### json.exception.type_error.317
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ The library supports **Unicode input** as follows:
|
||||
- The library will not replace [Unicode noncharacters](http://www.unicode.org/faq/private_use.html#nonchar1).
|
||||
- Invalid surrogates (e.g., incomplete pairs such as `\uDEAD`) will yield parse errors.
|
||||
- The strings stored in the library are UTF-8 encoded. When using the default string type (`std::string`), note that its length/size functions return the number of stored bytes rather than the number of characters or glyphs.
|
||||
- When you store strings with different encodings in the library, calling [`dump()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a50ec80b02d0f3f51130d4abb5d1cfdc5.html#a50ec80b02d0f3f51130d4abb5d1cfdc5) may throw an exception unless `json::error_handler_t::replace`, `json::error_handler_t::ignore`, or `json::error_handler_t::keep` are used as error handlers.
|
||||
- When you store strings with different encodings in the library, calling [`dump()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a50ec80b02d0f3f51130d4abb5d1cfdc5.html#a50ec80b02d0f3f51130d4abb5d1cfdc5) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers.
|
||||
|
||||
In most cases, the parser is right to complain, because the input is not UTF-8 encoded. This is especially true for Microsoft Windows, where Latin-1 or ISO 8859-1 is often the standard encoding.
|
||||
|
||||
|
||||
@@ -114,6 +114,7 @@ nav:
|
||||
- 'accept': api/basic_json/accept.md
|
||||
- 'array': api/basic_json/array.md
|
||||
- 'array_t': api/basic_json/array_t.md
|
||||
- 'as_base_class': api/basic_json/as_base_class.md
|
||||
- 'at': api/basic_json/at.md
|
||||
- 'back': api/basic_json/back.md
|
||||
- 'begin': api/basic_json/begin.md
|
||||
|
||||
@@ -48,8 +48,7 @@ enum class error_handler_t
|
||||
{
|
||||
strict, ///< throw a type_error exception in case of invalid UTF-8
|
||||
replace, ///< replace invalid UTF-8 sequences with U+FFFD
|
||||
ignore, ///< ignore invalid UTF-8 sequences
|
||||
keep ///< keep invalid UTF-8 sequences; their bytes are copied unchanged
|
||||
ignore ///< ignore invalid UTF-8 sequences
|
||||
};
|
||||
|
||||
template<typename BasicJsonType>
|
||||
@@ -1020,47 +1019,6 @@ class serializer
|
||||
break;
|
||||
}
|
||||
|
||||
case error_handler_t::keep:
|
||||
{
|
||||
// drop whatever the incomplete sequence left in
|
||||
// the buffer (only copied if !EnsureAscii) and copy
|
||||
// the ill-formed bytes from the input instead
|
||||
bytes = bytes_after_last_accept;
|
||||
|
||||
if (undumped_chars > 0)
|
||||
{
|
||||
// the pending bytes of the incomplete sequence
|
||||
// are ill-formed; the current byte may be OK for
|
||||
// itself, so we would like to read it again
|
||||
for (std::size_t j = i - undumped_chars; j < i; ++j)
|
||||
{
|
||||
string_buffer[bytes++] = s[j];
|
||||
}
|
||||
--i;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the current byte cannot start any sequence
|
||||
string_buffer[bytes++] = s[i];
|
||||
}
|
||||
|
||||
// write buffer and reset index; there must be 13 bytes
|
||||
// left, as this is the maximal number of bytes to be
|
||||
// written ("\uxxxx\uxxxx\0") for one code point
|
||||
if (string_buffer.size() - bytes < 13)
|
||||
{
|
||||
put_buffer(string_buffer, bytes);
|
||||
bytes = 0;
|
||||
}
|
||||
|
||||
bytes_after_last_accept = bytes;
|
||||
undumped_chars = 0;
|
||||
|
||||
// continue processing the string
|
||||
state = UTF8_ACCEPT;
|
||||
break;
|
||||
}
|
||||
|
||||
default: // LCOV_EXCL_LINE
|
||||
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
||||
}
|
||||
@@ -1106,15 +1064,6 @@ class serializer
|
||||
break;
|
||||
}
|
||||
|
||||
case error_handler_t::keep:
|
||||
{
|
||||
// write all accepted bytes
|
||||
put_buffer(string_buffer, bytes_after_last_accept);
|
||||
// copy the bytes of the incomplete sequence unchanged
|
||||
put_string(s, s.size() - undumped_chars, s.size());
|
||||
break;
|
||||
}
|
||||
|
||||
case error_handler_t::replace:
|
||||
{
|
||||
// write all accepted bytes
|
||||
|
||||
@@ -153,7 +153,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// workaround type for MSVC
|
||||
using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
|
||||
using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
|
||||
|
||||
JSON_PRIVATE_UNLESS_TESTED:
|
||||
// convenience aliases for types residing in namespace detail;
|
||||
@@ -213,6 +212,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
using cbor_tag_handler_t = detail::cbor_tag_handler_t;
|
||||
/// how to encode BJData
|
||||
using bjdata_version_t = detail::bjdata_version_t;
|
||||
/// base class used to inject custom functionality into each instance of basic_json
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/json_base_class_t/
|
||||
using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
|
||||
/// helper type for initializer lists of basic_json values
|
||||
using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
|
||||
|
||||
@@ -2690,6 +2692,20 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
return *get_ptr<const binary_t*>();
|
||||
}
|
||||
|
||||
/// @brief access the custom base class
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/as_base_class/
|
||||
json_base_class_t& as_base_class() noexcept
|
||||
{
|
||||
return static_cast<json_base_class_t&>(*this);
|
||||
}
|
||||
|
||||
/// @brief access the custom base class
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/as_base_class/
|
||||
const json_base_class_t& as_base_class() const noexcept
|
||||
{
|
||||
return static_cast<const json_base_class_t&>(*this);
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
////////////////////
|
||||
|
||||
@@ -23931,8 +23931,7 @@ enum class error_handler_t
|
||||
{
|
||||
strict, ///< throw a type_error exception in case of invalid UTF-8
|
||||
replace, ///< replace invalid UTF-8 sequences with U+FFFD
|
||||
ignore, ///< ignore invalid UTF-8 sequences
|
||||
keep ///< keep invalid UTF-8 sequences; their bytes are copied unchanged
|
||||
ignore ///< ignore invalid UTF-8 sequences
|
||||
};
|
||||
|
||||
template<typename BasicJsonType>
|
||||
@@ -24903,47 +24902,6 @@ class serializer
|
||||
break;
|
||||
}
|
||||
|
||||
case error_handler_t::keep:
|
||||
{
|
||||
// drop whatever the incomplete sequence left in
|
||||
// the buffer (only copied if !EnsureAscii) and copy
|
||||
// the ill-formed bytes from the input instead
|
||||
bytes = bytes_after_last_accept;
|
||||
|
||||
if (undumped_chars > 0)
|
||||
{
|
||||
// the pending bytes of the incomplete sequence
|
||||
// are ill-formed; the current byte may be OK for
|
||||
// itself, so we would like to read it again
|
||||
for (std::size_t j = i - undumped_chars; j < i; ++j)
|
||||
{
|
||||
string_buffer[bytes++] = s[j];
|
||||
}
|
||||
--i;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the current byte cannot start any sequence
|
||||
string_buffer[bytes++] = s[i];
|
||||
}
|
||||
|
||||
// write buffer and reset index; there must be 13 bytes
|
||||
// left, as this is the maximal number of bytes to be
|
||||
// written ("\uxxxx\uxxxx\0") for one code point
|
||||
if (string_buffer.size() - bytes < 13)
|
||||
{
|
||||
put_buffer(string_buffer, bytes);
|
||||
bytes = 0;
|
||||
}
|
||||
|
||||
bytes_after_last_accept = bytes;
|
||||
undumped_chars = 0;
|
||||
|
||||
// continue processing the string
|
||||
state = UTF8_ACCEPT;
|
||||
break;
|
||||
}
|
||||
|
||||
default: // LCOV_EXCL_LINE
|
||||
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
||||
}
|
||||
@@ -24989,15 +24947,6 @@ class serializer
|
||||
break;
|
||||
}
|
||||
|
||||
case error_handler_t::keep:
|
||||
{
|
||||
// write all accepted bytes
|
||||
put_buffer(string_buffer, bytes_after_last_accept);
|
||||
// copy the bytes of the incomplete sequence unchanged
|
||||
put_string(s, s.size() - undumped_chars, s.size());
|
||||
break;
|
||||
}
|
||||
|
||||
case error_handler_t::replace:
|
||||
{
|
||||
// write all accepted bytes
|
||||
@@ -26087,7 +26036,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// workaround type for MSVC
|
||||
using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
|
||||
using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
|
||||
|
||||
JSON_PRIVATE_UNLESS_TESTED:
|
||||
// convenience aliases for types residing in namespace detail;
|
||||
@@ -26147,6 +26095,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
using cbor_tag_handler_t = detail::cbor_tag_handler_t;
|
||||
/// how to encode BJData
|
||||
using bjdata_version_t = detail::bjdata_version_t;
|
||||
/// base class used to inject custom functionality into each instance of basic_json
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/json_base_class_t/
|
||||
using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
|
||||
/// helper type for initializer lists of basic_json values
|
||||
using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
|
||||
|
||||
@@ -28624,6 +28575,20 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
return *get_ptr<const binary_t*>();
|
||||
}
|
||||
|
||||
/// @brief access the custom base class
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/as_base_class/
|
||||
json_base_class_t& as_base_class() noexcept
|
||||
{
|
||||
return static_cast<json_base_class_t&>(*this);
|
||||
}
|
||||
|
||||
/// @brief access the custom base class
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/as_base_class/
|
||||
const json_base_class_t& as_base_class() const noexcept
|
||||
{
|
||||
return static_cast<const json_base_class_t&>(*this);
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
////////////////////
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "doctest_compatibility.h"
|
||||
|
||||
@@ -333,3 +335,71 @@ TEST_CASE("JSON Visit Node")
|
||||
);
|
||||
CHECK(expected.empty());
|
||||
}
|
||||
|
||||
// Test accessing members of a custom base class that are hidden by members of nlohmann::basic_json
|
||||
class base_class_with_hidden_members
|
||||
{
|
||||
public:
|
||||
const char* type_name() const noexcept
|
||||
{
|
||||
return "custom type_name";
|
||||
}
|
||||
|
||||
std::size_t size() const noexcept
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
std::size_t m_size = 42;
|
||||
};
|
||||
|
||||
using json_with_hidden_base_members =
|
||||
nlohmann::basic_json <
|
||||
std::map,
|
||||
std::vector,
|
||||
std::string,
|
||||
bool,
|
||||
std::int64_t,
|
||||
std::uint64_t,
|
||||
double,
|
||||
std::allocator,
|
||||
nlohmann::adl_serializer,
|
||||
std::vector<std::uint8_t>,
|
||||
base_class_with_hidden_members
|
||||
>;
|
||||
|
||||
TEST_CASE("JSON Node as_base_class")
|
||||
{
|
||||
using json = json_with_hidden_base_members;
|
||||
|
||||
static_assert(std::is_same<decltype(std::declval<json&>().as_base_class()), json::json_base_class_t&>::value, "");
|
||||
static_assert(std::is_same<decltype(std::declval<const json&>().as_base_class()), const json::json_base_class_t&>::value, "");
|
||||
static_assert(noexcept(std::declval<json&>().as_base_class()), "");
|
||||
static_assert(noexcept(std::declval<const json&>().as_base_class()), "");
|
||||
|
||||
SECTION("non-const")
|
||||
{
|
||||
json j = {1, 2, 3};
|
||||
|
||||
CHECK(std::string(j.type_name()) == "array");
|
||||
CHECK(j.size() == 3);
|
||||
CHECK(std::string(j.as_base_class().type_name()) == "custom type_name");
|
||||
CHECK(j.as_base_class().size() == 42);
|
||||
CHECK(&j.as_base_class() == &static_cast<json::json_base_class_t&>(j));
|
||||
|
||||
j.as_base_class().m_size = 7;
|
||||
CHECK(j.as_base_class().size() == 7);
|
||||
CHECK(j.size() == 3);
|
||||
}
|
||||
|
||||
SECTION("const")
|
||||
{
|
||||
const json j = {1, 2, 3};
|
||||
|
||||
CHECK(std::string(j.type_name()) == "array");
|
||||
CHECK(j.size() == 3);
|
||||
CHECK(std::string(j.as_base_class().type_name()) == "custom type_name");
|
||||
CHECK(j.as_base_class().size() == 42);
|
||||
CHECK(&j.as_base_class() == &static_cast<const json::json_base_class_t&>(j));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -766,15 +766,6 @@ TEST_CASE("regression tests 2")
|
||||
CHECK(j == k);
|
||||
}
|
||||
|
||||
SECTION("issue #4552 - UTF-8 invalid characters are not always ignored when dumping with error_handler_t::ignore")
|
||||
{
|
||||
json node;
|
||||
node["test"] = "test\334\005";
|
||||
CHECK(node.dump(-1, ' ', false, json::error_handler_t::ignore) == "{\"test\":\"test\\u0005\"}");
|
||||
CHECK(node.dump(-1, ' ', false, json::error_handler_t::keep) == "{\"test\":\"test\334\\u0005\"}");
|
||||
CHECK(node.dump(-1, ' ', true, json::error_handler_t::keep) == "{\"test\":\"test\334\\u0005\"}");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("regression test - parser callback must not lose a duplicate key's prior value")
|
||||
|
||||
@@ -92,8 +92,6 @@ TEST_CASE("serialization")
|
||||
CHECK(j.dump(-1, ' ', false, json::error_handler_t::ignore) == "\"äü\"");
|
||||
CHECK(j.dump(-1, ' ', false, json::error_handler_t::replace) == "\"ä\xEF\xBF\xBDü\"");
|
||||
CHECK(j.dump(-1, ' ', true, json::error_handler_t::replace) == "\"\\u00e4\\ufffd\\u00fc\"");
|
||||
CHECK(j.dump(-1, ' ', false, json::error_handler_t::keep) == "\"ä\xA9ü\"");
|
||||
CHECK(j.dump(-1, ' ', true, json::error_handler_t::keep) == "\"\\u00e4\xA9\\u00fc\"");
|
||||
}
|
||||
|
||||
SECTION("invalid character (regression guard for shared UTF-8 decoder, see #5529)")
|
||||
@@ -116,8 +114,6 @@ TEST_CASE("serialization")
|
||||
CHECK(j.dump(-1, ' ', false, json::error_handler_t::ignore) == "\"123\"");
|
||||
CHECK(j.dump(-1, ' ', false, json::error_handler_t::replace) == "\"123\xEF\xBF\xBD\"");
|
||||
CHECK(j.dump(-1, ' ', true, json::error_handler_t::replace) == "\"123\\ufffd\"");
|
||||
CHECK(j.dump(-1, ' ', false, json::error_handler_t::keep) == "\"123\xC2\"");
|
||||
CHECK(j.dump(-1, ' ', true, json::error_handler_t::keep) == "\"123\xC2\"");
|
||||
}
|
||||
|
||||
SECTION("unexpected character")
|
||||
@@ -130,39 +126,6 @@ TEST_CASE("serialization")
|
||||
CHECK(j.dump(-1, ' ', false, json::error_handler_t::ignore) == "\"123456\"");
|
||||
CHECK(j.dump(-1, ' ', false, json::error_handler_t::replace) == "\"123\xEF\xBF\xBD\x34\x35\x36\"");
|
||||
CHECK(j.dump(-1, ' ', true, json::error_handler_t::replace) == "\"123\\ufffd456\"");
|
||||
CHECK(j.dump(-1, ' ', false, json::error_handler_t::keep) == "\"123\xF1\xB0\x34\x35\x36\"");
|
||||
CHECK(j.dump(-1, ' ', true, json::error_handler_t::keep) == "\"123\xF1\xB0\x34\x35\x36\"");
|
||||
}
|
||||
|
||||
SECTION("keep: valid characters are still escaped")
|
||||
{
|
||||
// an invalid byte followed by characters that must be escaped
|
||||
const json j = "\xC2\"\\\n\xFF\x05";
|
||||
CHECK(j.dump(-1, ' ', false, json::error_handler_t::keep) == "\"\xC2\\\"\\\\\\n\xFF\\u0005\"");
|
||||
CHECK(j.dump(-1, ' ', true, json::error_handler_t::keep) == "\"\xC2\\\"\\\\\\n\xFF\\u0005\"");
|
||||
}
|
||||
|
||||
SECTION("keep: truncated multibyte sequences")
|
||||
{
|
||||
CHECK(json("\xF0\x9F\x98").dump(-1, ' ', false, json::error_handler_t::keep) == "\"\xF0\x9F\x98\"");
|
||||
CHECK(json("\xF0\x9F\x98").dump(-1, ' ', true, json::error_handler_t::keep) == "\"\xF0\x9F\x98\"");
|
||||
CHECK(json("\xF0\x9F\x98" "a").dump(-1, ' ', false, json::error_handler_t::keep) == "\"\xF0\x9F\x98" "a\"");
|
||||
CHECK(json("\xF0\x9F\x98" "a").dump(-1, ' ', true, json::error_handler_t::keep) == "\"\xF0\x9F\x98" "a\"");
|
||||
}
|
||||
|
||||
SECTION("keep: long string with many invalid bytes")
|
||||
{
|
||||
// exceeds the internal string buffer several times
|
||||
std::string input;
|
||||
std::string expected = "\"";
|
||||
for (int i = 0; i < 2000; ++i)
|
||||
{
|
||||
input += "\xFF\xE2\x82\n\xC3\xA4";
|
||||
expected += "\xFF\xE2\x82\\n\xC3\xA4";
|
||||
}
|
||||
expected += "\"";
|
||||
const json j = input;
|
||||
CHECK(j.dump(-1, ' ', false, json::error_handler_t::keep) == expected);
|
||||
}
|
||||
|
||||
SECTION("U+FFFD Substitution of Maximal Subparts")
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
using nlohmann::json;
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
@@ -76,11 +75,8 @@ void check_utf8dump(bool success_expected, int byte1, int byte2 = -1, int byte3
|
||||
static std::string s_replaced2;
|
||||
static std::string s_replaced_ascii;
|
||||
static std::string s_replaced2_ascii;
|
||||
static std::string s_kept;
|
||||
static std::string s_kept2;
|
||||
static std::string s_kept_ascii;
|
||||
|
||||
// dumping with ignore/replace/keep must not throw in any case
|
||||
// dumping with ignore/replace must not throw in any case
|
||||
s_ignored = j.dump(-1, ' ', false, json::error_handler_t::ignore);
|
||||
s_ignored2 = j2.dump(-1, ' ', false, json::error_handler_t::ignore);
|
||||
s_ignored_ascii = j.dump(-1, ' ', true, json::error_handler_t::ignore);
|
||||
@@ -89,9 +85,6 @@ void check_utf8dump(bool success_expected, int byte1, int byte2 = -1, int byte3
|
||||
s_replaced2 = j2.dump(-1, ' ', false, json::error_handler_t::replace);
|
||||
s_replaced_ascii = j.dump(-1, ' ', true, json::error_handler_t::replace);
|
||||
s_replaced2_ascii = j2.dump(-1, ' ', true, json::error_handler_t::replace);
|
||||
s_kept = j.dump(-1, ' ', false, json::error_handler_t::keep);
|
||||
s_kept2 = j2.dump(-1, ' ', false, json::error_handler_t::keep);
|
||||
s_kept_ascii = j.dump(-1, ' ', true, json::error_handler_t::keep);
|
||||
|
||||
if (success_expected)
|
||||
{
|
||||
@@ -101,7 +94,6 @@ void check_utf8dump(bool success_expected, int byte1, int byte2 = -1, int byte3
|
||||
// all dumps should agree on the string
|
||||
CHECK(s_strict == s_ignored);
|
||||
CHECK(s_strict == s_replaced);
|
||||
CHECK(s_strict == s_kept);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -113,20 +105,6 @@ void check_utf8dump(bool success_expected, int byte1, int byte2 = -1, int byte3
|
||||
|
||||
// check that replace string contains a replacement character
|
||||
CHECK(s_replaced.find("\xEF\xBF\xBD") != std::string::npos);
|
||||
|
||||
// ignore drops the invalid bytes, keep copies them
|
||||
CHECK(s_ignored != s_kept);
|
||||
CHECK(s_ignored_ascii != s_kept_ascii);
|
||||
|
||||
// unless a byte needs escaping, keep copies the input unchanged
|
||||
const bool needs_escaping = std::any_of(json_string.begin(), json_string.end(), [](char c)
|
||||
{
|
||||
return static_cast<unsigned char>(c) < 0x20 || c == '"' || c == '\\';
|
||||
});
|
||||
if (!needs_escaping)
|
||||
{
|
||||
CHECK(s_kept == "\"" + json_string + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
// check that prefix and suffix are preserved
|
||||
@@ -138,8 +116,6 @@ void check_utf8dump(bool success_expected, int byte1, int byte2 = -1, int byte3
|
||||
CHECK(s_replaced2.substr(s_replaced2.size() - 4, 3) == "xyz");
|
||||
CHECK(s_replaced2_ascii.substr(1, 3) == "abc");
|
||||
CHECK(s_replaced2_ascii.substr(s_replaced2_ascii.size() - 4, 3) == "xyz");
|
||||
CHECK(s_kept2.substr(1, 3) == "abc");
|
||||
CHECK(s_kept2.substr(s_kept2.size() - 4, 3) == "xyz");
|
||||
}
|
||||
|
||||
void check_utf8string(bool success_expected, int byte1, int byte2, int byte3, int byte4);
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
using nlohmann::json;
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
@@ -76,11 +75,8 @@ void check_utf8dump(bool success_expected, int byte1, int byte2 = -1, int byte3
|
||||
static std::string s_replaced2;
|
||||
static std::string s_replaced_ascii;
|
||||
static std::string s_replaced2_ascii;
|
||||
static std::string s_kept;
|
||||
static std::string s_kept2;
|
||||
static std::string s_kept_ascii;
|
||||
|
||||
// dumping with ignore/replace/keep must not throw in any case
|
||||
// dumping with ignore/replace must not throw in any case
|
||||
s_ignored = j.dump(-1, ' ', false, json::error_handler_t::ignore);
|
||||
s_ignored2 = j2.dump(-1, ' ', false, json::error_handler_t::ignore);
|
||||
s_ignored_ascii = j.dump(-1, ' ', true, json::error_handler_t::ignore);
|
||||
@@ -89,9 +85,6 @@ void check_utf8dump(bool success_expected, int byte1, int byte2 = -1, int byte3
|
||||
s_replaced2 = j2.dump(-1, ' ', false, json::error_handler_t::replace);
|
||||
s_replaced_ascii = j.dump(-1, ' ', true, json::error_handler_t::replace);
|
||||
s_replaced2_ascii = j2.dump(-1, ' ', true, json::error_handler_t::replace);
|
||||
s_kept = j.dump(-1, ' ', false, json::error_handler_t::keep);
|
||||
s_kept2 = j2.dump(-1, ' ', false, json::error_handler_t::keep);
|
||||
s_kept_ascii = j.dump(-1, ' ', true, json::error_handler_t::keep);
|
||||
|
||||
if (success_expected)
|
||||
{
|
||||
@@ -101,7 +94,6 @@ void check_utf8dump(bool success_expected, int byte1, int byte2 = -1, int byte3
|
||||
// all dumps should agree on the string
|
||||
CHECK(s_strict == s_ignored);
|
||||
CHECK(s_strict == s_replaced);
|
||||
CHECK(s_strict == s_kept);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -113,20 +105,6 @@ void check_utf8dump(bool success_expected, int byte1, int byte2 = -1, int byte3
|
||||
|
||||
// check that replace string contains a replacement character
|
||||
CHECK(s_replaced.find("\xEF\xBF\xBD") != std::string::npos);
|
||||
|
||||
// ignore drops the invalid bytes, keep copies them
|
||||
CHECK(s_ignored != s_kept);
|
||||
CHECK(s_ignored_ascii != s_kept_ascii);
|
||||
|
||||
// unless a byte needs escaping, keep copies the input unchanged
|
||||
const bool needs_escaping = std::any_of(json_string.begin(), json_string.end(), [](char c)
|
||||
{
|
||||
return static_cast<unsigned char>(c) < 0x20 || c == '"' || c == '\\';
|
||||
});
|
||||
if (!needs_escaping)
|
||||
{
|
||||
CHECK(s_kept == "\"" + json_string + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
// check that prefix and suffix are preserved
|
||||
@@ -138,8 +116,6 @@ void check_utf8dump(bool success_expected, int byte1, int byte2 = -1, int byte3
|
||||
CHECK(s_replaced2.substr(s_replaced2.size() - 4, 3) == "xyz");
|
||||
CHECK(s_replaced2_ascii.substr(1, 3) == "abc");
|
||||
CHECK(s_replaced2_ascii.substr(s_replaced2_ascii.size() - 4, 3) == "xyz");
|
||||
CHECK(s_kept2.substr(1, 3) == "abc");
|
||||
CHECK(s_kept2.substr(s_kept2.size() - 4, 3) == "xyz");
|
||||
}
|
||||
|
||||
void check_utf8string(bool success_expected, int byte1, int byte2, int byte3, int byte4);
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
using nlohmann::json;
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
@@ -76,11 +75,8 @@ void check_utf8dump(bool success_expected, int byte1, int byte2 = -1, int byte3
|
||||
static std::string s_replaced2;
|
||||
static std::string s_replaced_ascii;
|
||||
static std::string s_replaced2_ascii;
|
||||
static std::string s_kept;
|
||||
static std::string s_kept2;
|
||||
static std::string s_kept_ascii;
|
||||
|
||||
// dumping with ignore/replace/keep must not throw in any case
|
||||
// dumping with ignore/replace must not throw in any case
|
||||
s_ignored = j.dump(-1, ' ', false, json::error_handler_t::ignore);
|
||||
s_ignored2 = j2.dump(-1, ' ', false, json::error_handler_t::ignore);
|
||||
s_ignored_ascii = j.dump(-1, ' ', true, json::error_handler_t::ignore);
|
||||
@@ -89,9 +85,6 @@ void check_utf8dump(bool success_expected, int byte1, int byte2 = -1, int byte3
|
||||
s_replaced2 = j2.dump(-1, ' ', false, json::error_handler_t::replace);
|
||||
s_replaced_ascii = j.dump(-1, ' ', true, json::error_handler_t::replace);
|
||||
s_replaced2_ascii = j2.dump(-1, ' ', true, json::error_handler_t::replace);
|
||||
s_kept = j.dump(-1, ' ', false, json::error_handler_t::keep);
|
||||
s_kept2 = j2.dump(-1, ' ', false, json::error_handler_t::keep);
|
||||
s_kept_ascii = j.dump(-1, ' ', true, json::error_handler_t::keep);
|
||||
|
||||
if (success_expected)
|
||||
{
|
||||
@@ -101,7 +94,6 @@ void check_utf8dump(bool success_expected, int byte1, int byte2 = -1, int byte3
|
||||
// all dumps should agree on the string
|
||||
CHECK(s_strict == s_ignored);
|
||||
CHECK(s_strict == s_replaced);
|
||||
CHECK(s_strict == s_kept);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -113,20 +105,6 @@ void check_utf8dump(bool success_expected, int byte1, int byte2 = -1, int byte3
|
||||
|
||||
// check that replace string contains a replacement character
|
||||
CHECK(s_replaced.find("\xEF\xBF\xBD") != std::string::npos);
|
||||
|
||||
// ignore drops the invalid bytes, keep copies them
|
||||
CHECK(s_ignored != s_kept);
|
||||
CHECK(s_ignored_ascii != s_kept_ascii);
|
||||
|
||||
// unless a byte needs escaping, keep copies the input unchanged
|
||||
const bool needs_escaping = std::any_of(json_string.begin(), json_string.end(), [](char c)
|
||||
{
|
||||
return static_cast<unsigned char>(c) < 0x20 || c == '"' || c == '\\';
|
||||
});
|
||||
if (!needs_escaping)
|
||||
{
|
||||
CHECK(s_kept == "\"" + json_string + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
// check that prefix and suffix are preserved
|
||||
@@ -138,8 +116,6 @@ void check_utf8dump(bool success_expected, int byte1, int byte2 = -1, int byte3
|
||||
CHECK(s_replaced2.substr(s_replaced2.size() - 4, 3) == "xyz");
|
||||
CHECK(s_replaced2_ascii.substr(1, 3) == "abc");
|
||||
CHECK(s_replaced2_ascii.substr(s_replaced2_ascii.size() - 4, 3) == "xyz");
|
||||
CHECK(s_kept2.substr(1, 3) == "abc");
|
||||
CHECK(s_kept2.substr(s_kept2.size() - 4, 3) == "xyz");
|
||||
}
|
||||
|
||||
void check_utf8string(bool success_expected, int byte1, int byte2, int byte3, int byte4);
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
using nlohmann::json;
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
@@ -76,11 +75,8 @@ void check_utf8dump(bool success_expected, int byte1, int byte2 = -1, int byte3
|
||||
static std::string s_replaced2;
|
||||
static std::string s_replaced_ascii;
|
||||
static std::string s_replaced2_ascii;
|
||||
static std::string s_kept;
|
||||
static std::string s_kept2;
|
||||
static std::string s_kept_ascii;
|
||||
|
||||
// dumping with ignore/replace/keep must not throw in any case
|
||||
// dumping with ignore/replace must not throw in any case
|
||||
s_ignored = j.dump(-1, ' ', false, json::error_handler_t::ignore);
|
||||
s_ignored2 = j2.dump(-1, ' ', false, json::error_handler_t::ignore);
|
||||
s_ignored_ascii = j.dump(-1, ' ', true, json::error_handler_t::ignore);
|
||||
@@ -89,9 +85,6 @@ void check_utf8dump(bool success_expected, int byte1, int byte2 = -1, int byte3
|
||||
s_replaced2 = j2.dump(-1, ' ', false, json::error_handler_t::replace);
|
||||
s_replaced_ascii = j.dump(-1, ' ', true, json::error_handler_t::replace);
|
||||
s_replaced2_ascii = j2.dump(-1, ' ', true, json::error_handler_t::replace);
|
||||
s_kept = j.dump(-1, ' ', false, json::error_handler_t::keep);
|
||||
s_kept2 = j2.dump(-1, ' ', false, json::error_handler_t::keep);
|
||||
s_kept_ascii = j.dump(-1, ' ', true, json::error_handler_t::keep);
|
||||
|
||||
if (success_expected)
|
||||
{
|
||||
@@ -101,7 +94,6 @@ void check_utf8dump(bool success_expected, int byte1, int byte2 = -1, int byte3
|
||||
// all dumps should agree on the string
|
||||
CHECK(s_strict == s_ignored);
|
||||
CHECK(s_strict == s_replaced);
|
||||
CHECK(s_strict == s_kept);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -113,20 +105,6 @@ void check_utf8dump(bool success_expected, int byte1, int byte2 = -1, int byte3
|
||||
|
||||
// check that replace string contains a replacement character
|
||||
CHECK(s_replaced.find("\xEF\xBF\xBD") != std::string::npos);
|
||||
|
||||
// ignore drops the invalid bytes, keep copies them
|
||||
CHECK(s_ignored != s_kept);
|
||||
CHECK(s_ignored_ascii != s_kept_ascii);
|
||||
|
||||
// unless a byte needs escaping, keep copies the input unchanged
|
||||
const bool needs_escaping = std::any_of(json_string.begin(), json_string.end(), [](char c)
|
||||
{
|
||||
return static_cast<unsigned char>(c) < 0x20 || c == '"' || c == '\\';
|
||||
});
|
||||
if (!needs_escaping)
|
||||
{
|
||||
CHECK(s_kept == "\"" + json_string + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
// check that prefix and suffix are preserved
|
||||
@@ -138,8 +116,6 @@ void check_utf8dump(bool success_expected, int byte1, int byte2 = -1, int byte3
|
||||
CHECK(s_replaced2.substr(s_replaced2.size() - 4, 3) == "xyz");
|
||||
CHECK(s_replaced2_ascii.substr(1, 3) == "abc");
|
||||
CHECK(s_replaced2_ascii.substr(s_replaced2_ascii.size() - 4, 3) == "xyz");
|
||||
CHECK(s_kept2.substr(1, 3) == "abc");
|
||||
CHECK(s_kept2.substr(s_kept2.size() - 4, 3) == "xyz");
|
||||
}
|
||||
|
||||
void check_utf8string(bool success_expected, int byte1, int byte2, int byte3, int byte4);
|
||||
|
||||
Reference in New Issue
Block a user