diff --git a/docs/mkdocs/docs/api/basic_json/number_float_t.md b/docs/mkdocs/docs/api/basic_json/number_float_t.md index 8419a392d..282bb6123 100644 --- a/docs/mkdocs/docs/api/basic_json/number_float_t.md +++ b/docs/mkdocs/docs/api/basic_json/number_float_t.md @@ -55,6 +55,10 @@ This implementation does exactly follow this approach, as it uses double precisi smaller than `-1.79769313486232e+308` and values greater than `1.79769313486232e+308` will be stored as NaN internally and be serialized to `null`. +During deserialization (from JSON text or any of the binary formats), a finite number that does not fit into +`number_float_t` is rejected with [`out_of_range.406`](../../home/exceptions.md#jsonexceptionout_of_range406), for +example a double-precision number in a binary format when `number_float_t` is `#!cpp float`. + ### Storage Floating-point number values are stored directly inside a `basic_json` type. diff --git a/docs/mkdocs/docs/api/basic_json/number_integer_t.md b/docs/mkdocs/docs/api/basic_json/number_integer_t.md index d77c6a24d..48d2873ed 100644 --- a/docs/mkdocs/docs/api/basic_json/number_integer_t.md +++ b/docs/mkdocs/docs/api/basic_json/number_integer_t.md @@ -47,8 +47,9 @@ With the default values for `NumberIntegerType` (`std::int64_t`), the default va When the default type is used, the maximal integer number that can be stored is `9223372036854775807` (INT64_MAX) and the minimal integer number that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers that are out of -range will yield over/underflow when used in a constructor. During deserialization, too large or small integer numbers -will automatically be stored as [`number_unsigned_t`](number_unsigned_t.md) or [`number_float_t`](number_float_t.md). +range will yield over/underflow when used in a constructor. During deserialization (from JSON text or any of the binary +formats), too large or small integer numbers will automatically be stored as [`number_unsigned_t`](number_unsigned_t.md) +or [`number_float_t`](number_float_t.md). [RFC 8259](https://tools.ietf.org/html/rfc8259) further states: > Note that when such software is used, numbers that are integers and are in the range [-253+1, 253-1] are diff --git a/docs/mkdocs/docs/api/basic_json/number_unsigned_t.md b/docs/mkdocs/docs/api/basic_json/number_unsigned_t.md index 774fda638..81cc00f77 100644 --- a/docs/mkdocs/docs/api/basic_json/number_unsigned_t.md +++ b/docs/mkdocs/docs/api/basic_json/number_unsigned_t.md @@ -48,8 +48,9 @@ With the default values for `NumberUnsignedType` (`std::uint64_t`), the default When the default type is used, the maximal integer number that can be stored is `18446744073709551615` (UINT64_MAX) and the minimal integer number that can be stored is `0`. Integer numbers that are out of range will yield over/underflow -when used in a constructor. During deserialization, too large or small integer numbers will automatically be stored -as [`number_integer_t`](number_integer_t.md) or [`number_float_t`](number_float_t.md). +when used in a constructor. During deserialization (from JSON text or any of the binary formats), too large or small +integer numbers will automatically be stored as [`number_integer_t`](number_integer_t.md) or +[`number_float_t`](number_float_t.md). [RFC 8259](https://tools.ietf.org/html/rfc8259) further states: > Note that when such software is used, numbers that are integers and are in the range [-253+1, 253-1] are diff --git a/docs/mkdocs/docs/api/macros/index.md b/docs/mkdocs/docs/api/macros/index.md index 872d6cb8c..ffeb9639c 100644 --- a/docs/mkdocs/docs/api/macros/index.md +++ b/docs/mkdocs/docs/api/macros/index.md @@ -58,6 +58,8 @@ header. See also the [macro overview page](../../features/macros.md). - [**JSON_DISABLE_ENUM_SERIALIZATION**](json_disable_enum_serialization.md) - switch off default serialization/deserialization functions for enums - [**JSON_DISABLE_TUPLE_REFERENCE_CONVERSION**](json_disable_tuple_reference_conversion.md) - switch off conversion from a one-element tuple of a JSON reference - [**JSON_USE_IMPLICIT_CONVERSIONS**](json_use_implicit_conversions.md) - control implicit conversions +- [**JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS**](json_use_objects_for_enum_keyed_maps.md) - opt in to storing maps with enum + keys as objects ## Comparison behavior diff --git a/docs/mkdocs/docs/api/macros/json_use_objects_for_enum_keyed_maps.md b/docs/mkdocs/docs/api/macros/json_use_objects_for_enum_keyed_maps.md new file mode 100644 index 000000000..a84d83129 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_use_objects_for_enum_keyed_maps.md @@ -0,0 +1,139 @@ +# JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS + +```cpp +#define JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS /* value */ +``` + +When defined to `1`, maps whose keys are enums (such as `std::map` or `std::unordered_map`) are stored as +JSON objects, using the enum's own conversion for the keys. By default, they are stored as arrays of `[key, value]` +pairs. + +## Default definition + +The default value is `0` (disabled — existing behavior is preserved). + +```cpp +#define JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS 0 +``` + +## Notes + +!!! note "Background" + + JSON object keys are strings, so a map is only stored as an object if its keys can be converted to a string type. + Enums are not, even if [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md) maps them to strings, so a + map with enum keys becomes an array of `[key, value]` pairs: + + ```json + [["stopped", "aa"], ["completed", "bb"]] + ``` + + With this macro, the same map becomes an object + (see [#4378](https://github.com/nlohmann/json/issues/4378)): + + ```json + {"completed": "bb", "stopped": "aa"} + ``` + +!!! note "Maps with non-unique keys" + + Maps that allow duplicate keys, such as `std::multimap` or `std::unordered_multimap`, are not affected + by the macro and are still stored as arrays of `[key, value]` pairs, as an object cannot hold duplicate keys. + +!!! note "Reading" + + Reading is not affected by the macro: a map with enum keys can always be read from both an array of pairs and an + object. For the latter, each key is converted to the enum with its `from_json` function, e.g., the one defined by + [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md). Data written without the macro can therefore + still be read after enabling it. + +!!! warning "Keys must serialize to distinct strings" + + Each key is converted with the enum's `to_json` function. If a key is not converted to a string (for instance, an + enum without [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md), which is stored as an integer, or an + enumerator mapped to `nullptr`), [`type_error.302`](../../home/exceptions.md#jsonexceptiontype_error302) is thrown. + If two keys are converted to the same string (for instance, because + [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md) maps an unlisted enumerator to the first entry), + [`type_error.318`](../../home/exceptions.md#jsonexceptiontype_error318) is thrown. In both cases, the target value + is not changed. + +!!! warning "Opt-in only" + + This macro must be defined **before** including ``. Defining it after the include has no effect. + +!!! note "ABI compatibility" + + The value of this macro is encoded in the [namespace](../../features/namespace.md) (tag `_ekmo`), resulting in + distinct symbol names. Translation units compiled with and without it can therefore be linked into the same program + without One Definition Rule (ODR) violations, but they cannot exchange instances of library types. + +## Examples + +??? example "Default behavior (macro not defined)" + + Without the macro, a map with enum keys is stored as an array of pairs: + + ```cpp + #include + #include + + using json = nlohmann::json; + + enum TaskState { TS_STOPPED, TS_RUNNING, TS_COMPLETED }; + + NLOHMANN_JSON_SERIALIZE_ENUM(TaskState, { + {TS_STOPPED, "stopped"}, + {TS_RUNNING, "running"}, + {TS_COMPLETED, "completed"}, + }) + + int main() + { + std::map m = {{TS_STOPPED, "aa"}, {TS_COMPLETED, "bb"}}; + + json j = m; + // j is [["stopped","aa"],["completed","bb"]] + } + ``` + +??? example "Objects for enum-keyed maps (macro defined to 1)" + + With the macro, the same map is stored as an object: + + ```cpp + #define JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS 1 + #include + #include + + using json = nlohmann::json; + + enum TaskState { TS_STOPPED, TS_RUNNING, TS_COMPLETED }; + + NLOHMANN_JSON_SERIALIZE_ENUM(TaskState, { + {TS_STOPPED, "stopped"}, + {TS_RUNNING, "running"}, + {TS_COMPLETED, "completed"}, + }) + + int main() + { + std::map m = {{TS_STOPPED, "aa"}, {TS_COMPLETED, "bb"}}; + + json j = m; + // j is {"completed":"bb","stopped":"aa"} + + auto m2 = j.get>(); + // m2 == m + } + ``` + +## See also + +- [Specializing enum conversion](../../features/enum_conversion.md) +- [**NLOHMANN_JSON_SERIALIZE_ENUM**](nlohmann_json_serialize_enum.md) - serialize/deserialize an enum +- [**NLOHMANN_JSON_SERIALIZE_ENUM_STRICT**](nlohmann_json_serialize_enum_strict.md) - serialize/deserialize an enum with + exceptions + +## Version history + +- Added in version 3.13.0. diff --git a/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md b/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md index 626055fdf..4af3b07b8 100644 --- a/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md +++ b/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md @@ -41,6 +41,9 @@ inline void from_json(const BasicJsonType& j, type& e); conversion. Select this default pair carefully. See example 1 below. - If an enum or JSON value is specified in multiple conversions, the first matching conversion from the top of the list will be returned when converting to or from JSON. See example 2 below. + - Maps with enum keys (e.g., `std::map`) are stored as arrays of `[key, value]` pairs by default. + Define [`JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS`](json_use_objects_for_enum_keyed_maps.md) to store them as objects + with the converted keys. Such maps can be read from both forms. ## Examples @@ -80,6 +83,7 @@ inline void from_json(const BasicJsonType& j, type& e); - [Specializing enum conversion](../../features/enum_conversion.md) - [`NLOHMANN_JSON_SERIALIZE_ENUM_STRICT`](./nlohmann_json_serialize_enum_strict.md) - [`JSON_DISABLE_ENUM_SERIALIZATION`](json_disable_enum_serialization.md) +- [`JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS`](json_use_objects_for_enum_keyed_maps.md) ## Version history diff --git a/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum_strict.md b/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum_strict.md index 4697c5a95..f5806a490 100644 --- a/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum_strict.md +++ b/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum_strict.md @@ -44,6 +44,9 @@ inline void from_json(const BasicJsonType& j, type& e); `"enum value out of range for "`. - If an enum or JSON value is specified in multiple conversions, the first matching conversion from the top of the list will be returned when converting to or from JSON. See example 2 below. + - Maps with enum keys (e.g., `std::map`) are stored as arrays of `[key, value]` pairs by default. + Define [`JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS`](json_use_objects_for_enum_keyed_maps.md) to store them as objects + with the converted keys. Such maps can be read from both forms. ## Examples @@ -99,6 +102,7 @@ inline void from_json(const BasicJsonType& j, type& e); - [Specializing enum conversion](../../features/enum_conversion.md) - [`NLOHMANN_JSON_SERIALIZE_ENUM`](./nlohmann_json_serialize_enum.md) - [`JSON_DISABLE_ENUM_SERIALIZATION`](json_disable_enum_serialization.md) +- [`JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS`](json_use_objects_for_enum_keyed_maps.md) ## Version history diff --git a/docs/mkdocs/docs/features/binary_formats/cbor.md b/docs/mkdocs/docs/features/binary_formats/cbor.md index 7b5be4631..1b226cd15 100644 --- a/docs/mkdocs/docs/features/binary_formats/cbor.md +++ b/docs/mkdocs/docs/features/binary_formats/cbor.md @@ -168,9 +168,9 @@ The library maps CBOR types to JSON value types as follows: !!! warning "Negative integer overflow" CBOR negative integers (major type 1) are decoded as `-1 - n`. If the encoded magnitude `n` is too large for the - result to fit into `number_integer_t` (`std::int64_t` by default), parsing fails with a - [`parse_error.112`](../../home/exceptions.md#jsonexceptionparse_error112) exception rather than overflowing - silently. + result to fit into `number_integer_t` (`std::int64_t` by default), the result is stored as `number_float_t`, like + a too small integer in JSON text. For example, `-18446744073709551616` (`0x3B` followed by eight `0xFF` bytes) is + stored as `-1.8446744073709552e+19`. !!! warning "Object keys" diff --git a/docs/mkdocs/docs/features/enum_conversion.md b/docs/mkdocs/docs/features/enum_conversion.md index 3efd8e818..1b6e2b874 100644 --- a/docs/mkdocs/docs/features/enum_conversion.md +++ b/docs/mkdocs/docs/features/enum_conversion.md @@ -58,6 +58,23 @@ assert(jPi.get() == TS_INVALID ); --8<-- "examples/nlohmann_json_serialize_enum.output" ``` +## Maps with enum keys + +By default, maps with enum keys, such as `std::map`, are stored as arrays of `[key, value]` +pairs, because JSON object keys must be strings. Define +[`JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS`](../api/macros/json_use_objects_for_enum_keyed_maps.md) before including the +library to store them as objects, with the keys converted by the enum's `to_json()` function: + +```cpp +std::map m = {{TS_STOPPED, "aa"}, {TS_COMPLETED, "bb"}}; + +json j = m; +// default: [["stopped","aa"],["completed","bb"]] +// with JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS: {"completed":"bb","stopped":"aa"} +``` + +Either form can be read back, with or without the macro. + ## Notes Just as in [Arbitrary Type Conversions](arbitrary_types.md) above, diff --git a/docs/mkdocs/docs/features/macros.md b/docs/mkdocs/docs/features/macros.md index 681980315..4fd05c12c 100644 --- a/docs/mkdocs/docs/features/macros.md +++ b/docs/mkdocs/docs/features/macros.md @@ -198,6 +198,13 @@ default. See [full documentation of `JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON`](../api/macros/json_use_legacy_discarded_value_comparison.md). +## `JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS` + +When defined to `1`, maps with enum keys (e.g., `std::map`) are stored as objects, using the enum's conversion for +the keys, instead of arrays of `[key, value]` pairs. It is switched off (`0`) by default. + +See [full documentation of `JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS`](../api/macros/json_use_objects_for_enum_keyed_maps.md). + ## `JSON_USE_SIMDUTF` When defined, UTF-8 validation of JSON strings read from contiguous byte input is delegated to the diff --git a/docs/mkdocs/docs/features/namespace.md b/docs/mkdocs/docs/features/namespace.md index dbddac13d..26e89d09c 100644 --- a/docs/mkdocs/docs/features/namespace.md +++ b/docs/mkdocs/docs/features/namespace.md @@ -21,6 +21,8 @@ The complete default namespace name is derived as follows: - [`JSON_PRECISE_STREAM_POSITION`](../api/macros/json_precise_stream_position.md) defined non-zero appends `_psp`. - [`JSON_STRICT_NUL_HANDLING`](../api/macros/json_strict_nul_handling.md) defined non-zero appends `_snul`. - [`JSON_STRICT_BINARY_UTF8`](../api/macros/json_strict_binary_utf8.md) defined non-zero appends `_sbu8`. + - [`JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS`](../api/macros/json_use_objects_for_enum_keyed_maps.md) defined non-zero + appends `_ekmo`. - The inline namespace ends with the suffix `_v` followed by the 3 components of the version number separated by underscores. To omit the version component, see [Disabling the version component](#disabling-the-version-component) below. diff --git a/docs/mkdocs/docs/features/parsing/error_recovery.md b/docs/mkdocs/docs/features/parsing/error_recovery.md index 7dc09e9ed..825bfa6dd 100644 --- a/docs/mkdocs/docs/features/parsing/error_recovery.md +++ b/docs/mkdocs/docs/features/parsing/error_recovery.md @@ -75,7 +75,7 @@ If the item is complete, but cannot be passed on as it is, it is replaced, and p |---------------------------------------------------------------------|-------------------------|-------------------------------------------------------------------------| | tag | CBOR | ignored | | simple value other than `false`, `true`, and `null`, like undefined | CBOR | `#!json null` | -| negative integer below the range of `number_integer_t` | CBOR | the nearest floating-point number | +| number too large for a custom `number_float_t`, like `float` | all | infinity | | character (`C`) that is not ASCII | BJData, UBJSON | U+FFFD | | invalid high-precision number (`H`) | BJData, UBJSON | the longest valid beginning is kept, as for JSON text, or `#!json null` | | high-precision number too large | BJData, UBJSON | passed as infinity, together with its text | diff --git a/docs/mkdocs/docs/home/exceptions.md b/docs/mkdocs/docs/home/exceptions.md index e7eb8fd03..673c0c8dd 100644 --- a/docs/mkdocs/docs/home/exceptions.md +++ b/docs/mkdocs/docs/home/exceptions.md @@ -331,9 +331,6 @@ An unexpected byte was read in a [binary format](../features/binary_formats/inde [json.exception.parse_error.112] parse error at byte 15: syntax error while parsing BSON binary: byte array length cannot be negative, is -1 ``` ``` - [json.exception.parse_error.112] parse error at byte 9: syntax error while parsing CBOR value: negative integer overflow - ``` - ``` [json.exception.parse_error.112] parse error at byte 5: syntax error while parsing BSON document: document size 6 does not match the number of bytes read (5) ``` @@ -599,6 +596,9 @@ During implicit or explicit value conversion, the JSON type must be compatible w [json.exception.type_error.302] type must be string, but is object ``` +This exception is also thrown with [`JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS`](../api/macros/json_use_objects_for_enum_keyed_maps.md) +if a key of a map with enum keys is not converted to a string, for instance, because the enum is stored as an integer. + ### json.exception.type_error.303 To retrieve a reference to a value stored in a `basic_json` object with `get_ref`, the type of the reference must match the value type. For instance, for a JSON array, the `ReferenceType` must be `array_t &`. @@ -791,6 +791,19 @@ The dynamic type of the object cannot be represented in the requested serializat Encapsulate the JSON value in an object. That is, instead of serializing `#!json true`, serialize `#!json {"value": true}` +### json.exception.type_error.318 + +With [`JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS`](../api/macros/json_use_objects_for_enum_keyed_maps.md), a map with enum +keys is stored as an object. This exception is thrown if two of its keys are converted to the same string, so one of the +entries would be lost. This happens, for instance, if [`NLOHMANN_JSON_SERIALIZE_ENUM`](../api/macros/nlohmann_json_serialize_enum.md) +does not list an enumerator and it is therefore converted like the first listed one. + +!!! failure "Example message" + + ``` + [json.exception.type_error.318] duplicate object key 'red' + ``` + ## Out of range This exception is thrown in case a library function is called on an input parameter that exceeds the expected range, for instance, in the case of array indices or nonexisting object keys. @@ -863,13 +876,18 @@ The JSON Patch operations 'remove' and 'add' cannot be applied to the root eleme ### json.exception.out_of_range.406 -A parsed number could not be stored as without changing it to NaN or INF. +A parsed number could not be stored without changing it to NaN or INF. For the binary formats, this happens when a +finite floating-point number does not fit into [`number_float_t`](../api/basic_json/number_float_t.md), for example a +double-precision number when `number_float_t` is `#!cpp float`. -!!! failure "Example message" +!!! failure "Example messages" ``` number overflow parsing '10E1000' ``` + ``` + [json.exception.out_of_range.406] syntax error while parsing CBOR value: number overflow + ``` ### json.exception.out_of_range.407 diff --git a/docs/mkdocs/mkdocs.yml b/docs/mkdocs/mkdocs.yml index 3bf688922..2c3f2a804 100644 --- a/docs/mkdocs/mkdocs.yml +++ b/docs/mkdocs/mkdocs.yml @@ -314,6 +314,7 @@ nav: - 'JSON_USE_GLOBAL_UDLS': api/macros/json_use_global_udls.md - 'JSON_USE_IMPLICIT_CONVERSIONS': api/macros/json_use_implicit_conversions.md - 'JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON': api/macros/json_use_legacy_discarded_value_comparison.md + - 'JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS': api/macros/json_use_objects_for_enum_keyed_maps.md - 'JSON_USE_SIMDUTF': api/macros/json_use_simdutf.md - 'NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE, NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT, NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE': api/macros/nlohmann_define_derived_type.md - 'NLOHMANN_DEFINE_TYPE_INTRUSIVE, NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT, NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE': api/macros/nlohmann_define_type_intrusive.md diff --git a/include/nlohmann/detail/abi_macros.hpp b/include/nlohmann/detail/abi_macros.hpp index 0153c8706..063b9a0d9 100644 --- a/include/nlohmann/detail/abi_macros.hpp +++ b/include/nlohmann/detail/abi_macros.hpp @@ -50,6 +50,10 @@ #define JSON_STRICT_BINARY_UTF8 0 #endif +#ifndef JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS + #define JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS 0 +#endif + #if JSON_DIAGNOSTICS #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag #else @@ -92,14 +96,20 @@ #define NLOHMANN_JSON_ABI_TAG_STRICT_BINARY_UTF8 #endif +#if JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS + #define NLOHMANN_JSON_ABI_TAG_OBJECTS_FOR_ENUM_KEYED_MAPS _ekmo +#else + #define NLOHMANN_JSON_ABI_TAG_OBJECTS_FOR_ENUM_KEYED_MAPS +#endif + #ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 #endif // Construct the namespace ABI tags component -#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c, d, e, f, g) json_abi ## a ## b ## c ## d ## e ## f ## g -#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c, d, e, f, g) \ - NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c, d, e, f, g) +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c, d, e, f, g, h) json_abi ## a ## b ## c ## d ## e ## f ## g ## h +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c, d, e, f, g, h) \ + NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c, d, e, f, g, h) #define NLOHMANN_JSON_ABI_TAGS \ NLOHMANN_JSON_ABI_TAGS_CONCAT( \ @@ -109,7 +119,8 @@ NLOHMANN_JSON_ABI_TAG_BRACE_INIT_COPY_SEMANTICS, \ NLOHMANN_JSON_ABI_TAG_PRECISE_STREAM_POSITION, \ NLOHMANN_JSON_ABI_TAG_STRICT_NUL_HANDLING, \ - NLOHMANN_JSON_ABI_TAG_STRICT_BINARY_UTF8) + NLOHMANN_JSON_ABI_TAG_STRICT_BINARY_UTF8, \ + NLOHMANN_JSON_ABI_TAG_OBJECTS_FOR_ENUM_KEYED_MAPS) // Construct the namespace version component #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ diff --git a/include/nlohmann/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp index 5274b9857..53f6d01cf 100644 --- a/include/nlohmann/detail/conversions/from_json.hpp +++ b/include/nlohmann/detail/conversions/from_json.hpp @@ -530,11 +530,40 @@ void from_json_pair_array_to_map(const BasicJsonType& j, MapType& m) } } +// read a map with enum keys from an object, using the enum's own from_json for +// the keys (e.g., from NLOHMANN_JSON_SERIALIZE_ENUM); this is the form written +// with JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS +template +inline bool from_json_enum_keyed_object(const BasicJsonType& j, Map& m, std::true_type /*key is enum*/) +{ + if (!j.is_object()) + { + return false; + } + m.clear(); + for (const auto& p : *j.template get_ptr()) + { + m.emplace(BasicJsonType(p.first).template get(), p.second.template get()); + } + return true; +} + +template +inline bool from_json_enum_keyed_object(const BasicJsonType& /*j*/, Map& /*m*/, std::false_type /*key is enum*/) +{ + return false; +} + template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator, typename = enable_if_t < !std::is_constructible < typename BasicJsonType::string_t, Key >::value >> void from_json(const BasicJsonType& j, std::map& m) { + // NOLINTNEXTLINE(modernize-type-traits) we use C++11 + if (from_json_enum_keyed_object(j, m, std::is_enum {})) + { + return; + } from_json_pair_array_to_map(j, m); } @@ -543,6 +572,11 @@ template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename BasicJsonType::string_t, Key >::value >> void from_json(const BasicJsonType& j, std::unordered_map& m) { + // NOLINTNEXTLINE(modernize-type-traits) we use C++11 + if (from_json_enum_keyed_object(j, m, std::is_enum {})) + { + return; + } from_json_pair_array_to_map(j, m); } diff --git a/include/nlohmann/detail/conversions/to_json.hpp b/include/nlohmann/detail/conversions/to_json.hpp index 2dba6c163..5b332d4e9 100644 --- a/include/nlohmann/detail/conversions/to_json.hpp +++ b/include/nlohmann/detail/conversions/to_json.hpp @@ -23,6 +23,7 @@ #include // valarray #include // vector +#include #include #include #include @@ -384,6 +385,9 @@ template < typename BasicJsonType, typename CompatibleArrayType, !is_basic_json::value #if JSON_HAS_RANGE_VIEW_CONVERSION && !is_compatible_range_view::value +#endif +#if JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS + && !is_enum_keyed_map::value #endif , int > = 0 > @@ -438,6 +442,33 @@ inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj) external_constructor::construct(j, obj); } +#if JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS +// store a map with enum keys as an object, using the enum's own to_json for the +// keys (e.g., from NLOHMANN_JSON_SERIALIZE_ENUM); without the macro, such maps +// are stored as arrays of [key, value] pairs +template < typename BasicJsonType, typename EnumKeyedMap, + enable_if_t < is_enum_keyed_map::value&& !is_basic_json::value, int > = 0 > +inline void to_json(BasicJsonType& j, const EnumKeyedMap& map) +{ + typename BasicJsonType::object_t obj; + for (const auto& p : map) + { + BasicJsonType key = p.first; + if (JSON_HEDLEY_UNLIKELY(!key.is_string())) + { + JSON_THROW(type_error::create(302, concat("type must be string, but is ", key.type_name()), &key)); + } + + auto& key_string = *key.template get_ptr(); + if (JSON_HEDLEY_UNLIKELY(!obj.emplace(key_string, BasicJsonType(p.second)).second)) + { + JSON_THROW(type_error::create(318, concat("duplicate object key '", key_string, "'"), &key)); + } + } + external_constructor::construct(j, std::move(obj)); +} +#endif + template inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) { diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp index a325dbc78..77d6061a1 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -225,7 +225,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(current != char_traits::eof())) { return report_error(chars_read, get_token_string(), parse_error::create(110, chars_read, - exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr)); + exception_message(concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr)); } } @@ -357,7 +357,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(document_size < 0 || static_cast(document_size) != chars_read - document_start)) { static_cast(report_error(chars_read, get_token_string(), parse_error::create(112, chars_read, - exception_message(input_format_t::bson, concat("document size ", std::to_string(document_size), " does not match the number of bytes read (", std::to_string(chars_read - document_start), ")"), "document"), nullptr))); + exception_message(concat("document size ", std::to_string(document_size), " does not match the number of bytes read (", std::to_string(chars_read - document_start), ")"), "document"), nullptr))); return repair_requested(); } return true; @@ -457,7 +457,7 @@ class binary_reader if (size < 0) { std::int32_t len{}; - if (!get_number(input_format_t::bson, len)) + if (!get_number(len)) { return false; } @@ -498,7 +498,7 @@ class binary_reader // check_bson_document_size() measures the document from here const std::size_t document_start = chars_read; std::int32_t document_size{}; - if (!get_number(input_format_t::bson, document_size)) + if (!get_number(document_size)) { return false; } @@ -563,7 +563,7 @@ class binary_reader continue; } - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("element list"))) { return false; } @@ -610,7 +610,7 @@ class binary_reader while (true) { get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("cstring"))) { return false; } @@ -682,10 +682,10 @@ class binary_reader skip_requested = true; auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr)); + exception_message(concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr)); } - if (JSON_HEDLEY_UNLIKELY(!get_string(input_format_t::bson, len - static_cast(1), result))) + if (JSON_HEDLEY_UNLIKELY(!get_string(len - static_cast(1), result))) { return false; } @@ -694,8 +694,7 @@ class binary_reader { auto last_token = get_token_string(); static_cast(report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::bson, - "BSON string is not null-terminated", + exception_message("BSON string is not null-terminated", "string"), nullptr))); // when recovering, a byte in place of the terminator is dropped; // the end of the input is not @@ -723,18 +722,18 @@ class binary_reader skip_requested = true; auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr)); + exception_message(concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr)); } // All BSON binary values have a subtype std::uint8_t subtype{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::bson, subtype))) + if (JSON_HEDLEY_UNLIKELY(!get_number(subtype))) { return false; } result.set_subtype(subtype); - return get_binary(input_format_t::bson, len, result); + return get_binary(len, result); } /*! @@ -755,14 +754,14 @@ class binary_reader case 0x01: // double { double number{}; - return get_number(input_format_t::bson, number) && sax->number_float(static_cast(number), ""); + return get_number(number) && emit_float(number); } case 0x02: // string { std::int32_t len{}; string_t value; - return get_number(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value); + return get_number(len) && get_bson_string(len, value) && sax->string(value); } case 0x03: // object @@ -779,13 +778,13 @@ class binary_reader { std::int32_t len{}; binary_t value; - return get_number(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value); + return get_number(len) && get_bson_binary(len, value) && sax->binary(value); } case 0x08: // boolean { std::uint8_t value{}; - return get_number(input_format_t::bson, value) && sax->boolean(value != 0); + return get_number(value) && sax->boolean(value != 0); } case 0x0A: // null @@ -796,19 +795,19 @@ class binary_reader case 0x10: // int32 { std::int32_t value{}; - return get_number(input_format_t::bson, value) && sax->number_integer(conditional_static_cast(value)); + return get_number(value) && emit_signed(value); } case 0x12: // int64 { std::int64_t value{}; - return get_number(input_format_t::bson, value) && sax->number_integer(conditional_static_cast(value)); + return get_number(value) && emit_signed(value); } case 0x11: // uint64 { std::uint64_t value{}; - return get_number(input_format_t::bson, value) && sax->number_unsigned(value); + return get_number(value) && emit_unsigned(value); } default: // anything else is not supported (yet) @@ -831,24 +830,23 @@ class binary_reader bool get_cbor_negative_integer() { NumberType number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::cbor, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(number))) { return false; } - const auto max_val = static_cast((std::numeric_limits::max)()); - if (number > max_val) + + // the value is -1 - number, which fits into number_integer_t + // whenever number does + if (JSON_HEDLEY_LIKELY(value_in_range_of(number))) { - static_cast(report_error(chars_read, get_token_string(), - parse_error::create(112, chars_read, - exception_message(input_format_t::cbor, "negative integer overflow", "value"), nullptr))); - if (!repair_requested()) - { - return false; - } - // too small for number_integer_t: pass the nearest floating-point number - return sax->number_float(static_cast(-1) - static_cast(number), ""); + return sax->number_integer(static_cast(-1) - static_cast(number)); } - return sax->number_integer(conditional_static_cast(static_cast(-1) - static_cast(number))); + + // like the lexer does for JSON text, store a value too small for + // number_integer_t as number_float_t; compute it as long double so + // that emit_float sees a finite value and can detect an overflow of + // number_float_t + return emit_float(static_cast(-1) - static_cast(number)); } /*! @@ -873,7 +871,7 @@ class binary_reader { // EOF case char_traits::eof(): - return unexpect_eof(input_format_t::cbor, "value"); + return unexpect_eof("value"); // Integer 0x00..0x17 (0..23) case 0x00: @@ -905,25 +903,25 @@ class binary_reader case 0x18: // Unsigned integer (one-byte uint8_t follows) { std::uint8_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 0x19: // Unsigned integer (two-byte uint16_t follows) { std::uint16_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 0x1A: // Unsigned integer (four-byte uint32_t follows) { std::uint32_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 0x1B: // Unsigned integer (eight-byte uint64_t follows) { std::uint64_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } // Negative integer -1-0x00..-1-0x17 (-1..-24) @@ -1144,7 +1142,7 @@ class binary_reader { auto last_token = get_token_string(); static_cast(report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr))); + exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr))); if (!repair_requested()) { return false; @@ -1172,7 +1170,7 @@ class binary_reader { auto last_token = get_token_string(); static_cast(report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr))); + exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr))); if (!repair_requested()) { return false; @@ -1237,18 +1235,18 @@ class binary_reader return sax->null(); case 0xF9: // Half-Precision Float (two-byte IEEE 754) - return get_half_float(input_format_t::cbor, false); + return get_half_float(false); case 0xFA: // Single-Precision Float (four-byte IEEE 754) { float number{}; - return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); + return get_number(number) && emit_float(number); } case 0xFB: // Double-Precision Float (eight-byte IEEE 754) { double number{}; - return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); + return get_number(number) && emit_float(number); } default: // anything else (0xFF is handled inside the other types) @@ -1258,7 +1256,7 @@ class binary_reader // 0xF7 for undefined, and 0xF8 followed by a byte) are complete const bool simple_value = (current >= 0xE0 && current <= 0xF3) || current == 0xF7 || current == 0xF8; static_cast(report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr))); + exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr))); if (!simple_value || !repair_requested()) { return false; @@ -1266,7 +1264,7 @@ class binary_reader // when recovering, a simple value becomes null, as RFC 8949, // Section 6.1 suggests for converting to JSON std::uint8_t ignored{}; - return (current != 0xF8 || get_number(input_format_t::cbor, ignored)) && sax->null(); + return (current != 0xF8 || get_number(ignored)) && sax->null(); } } } @@ -1315,38 +1313,38 @@ class binary_reader case 0x76: case 0x77: { - return get_string(input_format_t::cbor, static_cast(current) & 0x1Fu, result); + return get_string(static_cast(current) & 0x1Fu, result); } case 0x78: // UTF-8 string (one-byte uint8_t for n follows) { std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + return get_number(len) && get_string(len, result); } case 0x79: // UTF-8 string (two-byte uint16_t for n follow) { std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + return get_number(len) && get_string(len, result); } case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) { std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + return get_number(len) && get_string(len, result); } case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) { std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + return get_number(len) && get_string(len, result); } default: { auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(113, chars_read, - exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr)); + exception_message(concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr)); } } } @@ -1374,7 +1372,7 @@ class binary_reader while (true) { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("string"))) { return false; } @@ -1487,7 +1485,7 @@ class binary_reader skip_requested = is_cbor_item_head(static_cast(current)); auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(113, chars_read, - exception_message(input_format_t::cbor, concat("only string keys are supported, but found ", found, "; last byte: 0x", last_token), "object key"), nullptr)); + exception_message(concat("only string keys are supported, but found ", found, "; last byte: 0x", last_token), "object key"), nullptr)); } /*! @@ -1534,42 +1532,42 @@ class binary_reader case 0x56: case 0x57: { - return get_binary(input_format_t::cbor, static_cast(current) & 0x1Fu, result); + return get_binary(static_cast(current) & 0x1Fu, result); } case 0x58: // Binary data (one-byte uint8_t for n follows) { std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); + return get_number(len) && + get_binary(len, result); } case 0x59: // Binary data (two-byte uint16_t for n follow) { std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); + return get_number(len) && + get_binary(len, result); } case 0x5A: // Binary data (four-byte uint32_t for n follow) { std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); + return get_number(len) && + get_binary(len, result); } case 0x5B: // Binary data (eight-byte uint64_t for n follow) { std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); + return get_number(len) && + get_binary(len, result); } default: { auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(113, chars_read, - exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr)); + exception_message(concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr)); } } } @@ -1593,7 +1591,7 @@ class binary_reader while (true) { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("binary"))) { return false; } @@ -1651,7 +1649,7 @@ class binary_reader case 0x18: // 1 byte { std::uint8_t n{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::cbor, n))) + if (JSON_HEDLEY_UNLIKELY(!get_number(n))) { return false; } @@ -1662,7 +1660,7 @@ class binary_reader case 0x19: // 2 bytes { std::uint16_t n{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::cbor, n))) + if (JSON_HEDLEY_UNLIKELY(!get_number(n))) { return false; } @@ -1673,7 +1671,7 @@ class binary_reader case 0x1A: // 4 bytes { std::uint32_t n{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::cbor, n))) + if (JSON_HEDLEY_UNLIKELY(!get_number(n))) { return false; } @@ -1684,7 +1682,7 @@ class binary_reader case 0x1B: // 8 bytes { std::uint64_t n{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::cbor, n))) + if (JSON_HEDLEY_UNLIKELY(!get_number(n))) { return false; } @@ -1717,7 +1715,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(!value_in_range_of(len) || len == detail::unknown_size())) { return report_error(chars_read, get_token_string(), out_of_range::create(408, - exception_message(input_format_t::cbor, concat("excessive ", context, " size"), "size"), nullptr)); + exception_message(concat("excessive ", context, " size"), "size"), nullptr)); } result = conditional_static_cast(len); return true; @@ -1853,7 +1851,7 @@ class binary_reader { get(); } - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "value"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("value"))) { return false; } @@ -1868,7 +1866,7 @@ class binary_reader { auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr)); + exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr)); } const auto major_type = static_cast(current) >> 5u; @@ -1878,7 +1876,7 @@ class binary_reader case 24: { std::uint8_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::cbor, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(number))) { return false; } @@ -1889,7 +1887,7 @@ class binary_reader case 25: { std::uint16_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::cbor, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(number))) { return false; } @@ -1900,7 +1898,7 @@ class binary_reader case 26: { std::uint32_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::cbor, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(number))) { return false; } @@ -1910,7 +1908,7 @@ class binary_reader case 27: { - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::cbor, argument))) + if (JSON_HEDLEY_UNLIKELY(!get_number(argument))) { return false; } @@ -1968,7 +1966,7 @@ class binary_reader { // EOF case char_traits::eof(): - return unexpect_eof(input_format_t::msgpack, "value"); + return unexpect_eof("value"); // positive fixint case 0x00: @@ -2208,85 +2206,85 @@ class binary_reader case 0xCA: // float 32 { float number{}; - return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); + return get_number(number) && emit_float(number); } case 0xCB: // float 64 { double number{}; - return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); + return get_number(number) && emit_float(number); } case 0xCC: // uint 8 { std::uint8_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 0xCD: // uint 16 { std::uint16_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 0xCE: // uint 32 { std::uint32_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 0xCF: // uint 64 { std::uint64_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 0xD0: // int 8 { std::int8_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(conditional_static_cast(number)); + return get_number(number) && emit_signed(number); } case 0xD1: // int 16 { std::int16_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(conditional_static_cast(number)); + return get_number(number) && emit_signed(number); } case 0xD2: // int 32 { std::int32_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(conditional_static_cast(number)); + return get_number(number) && emit_signed(number); } case 0xD3: // int 64 { std::int64_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(conditional_static_cast(number)); + return get_number(number) && emit_signed(number); } case 0xDC: // array 16 { std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && enter_array(static_cast(len)); + return get_number(len) && enter_array(static_cast(len)); } case 0xDD: // array 32 { std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && enter_array(conditional_static_cast(len)); + return get_number(len) && enter_array(conditional_static_cast(len)); } case 0xDE: // map 16 { std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && enter_object(static_cast(len)); + return get_number(len) && enter_object(static_cast(len)); } case 0xDF: // map 32 { std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && enter_object(conditional_static_cast(len)); + return get_number(len) && enter_object(conditional_static_cast(len)); } // negative fixint @@ -2328,7 +2326,7 @@ class binary_reader { auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr)); + exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr)); } } } @@ -2345,7 +2343,7 @@ class binary_reader */ bool get_msgpack_string(string_t& result, const char* context = "string") { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("string"))) { return false; } @@ -2386,32 +2384,32 @@ class binary_reader case 0xBE: case 0xBF: { - return get_string(input_format_t::msgpack, static_cast(current) & 0x1Fu, result) && check_string_utf8(result, context); + return get_string(static_cast(current) & 0x1Fu, result) && check_string_utf8(result, context); } case 0xD9: // str 8 { std::uint8_t len{}; - return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result) && check_string_utf8(result, context); + return get_number(len) && get_string(len, result) && check_string_utf8(result, context); } case 0xDA: // str 16 { std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result) && check_string_utf8(result, context); + return get_number(len) && get_string(len, result) && check_string_utf8(result, context); } case 0xDB: // str 32 { std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result) && check_string_utf8(result, context); + return get_number(len) && get_string(len, result) && check_string_utf8(result, context); } default: { auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(113, chars_read, - exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr)); + exception_message(concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr)); } } } @@ -2508,7 +2506,7 @@ class binary_reader skip_requested = true; auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(113, chars_read, - exception_message(input_format_t::msgpack, concat("only string keys are supported, but found ", found, "; last byte: 0x", last_token), "object key"), nullptr)); + exception_message(concat("only string keys are supported, but found ", found, "; last byte: 0x", last_token), "object key"), nullptr)); } /*! @@ -2535,31 +2533,31 @@ class binary_reader case 0xC4: // bin 8 { std::uint8_t len{}; - return get_number(input_format_t::msgpack, len) && - get_binary(input_format_t::msgpack, len, result); + return get_number(len) && + get_binary(len, result); } case 0xC5: // bin 16 { std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && - get_binary(input_format_t::msgpack, len, result); + return get_number(len) && + get_binary(len, result); } case 0xC6: // bin 32 { std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && - get_binary(input_format_t::msgpack, len, result); + return get_number(len) && + get_binary(len, result); } case 0xC7: // ext 8 { std::uint8_t len{}; std::int8_t subtype{}; - return get_number(input_format_t::msgpack, len) && - get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, len, result) && + return get_number(len) && + get_number(subtype) && + get_binary(len, result) && assign_and_return_true(subtype); } @@ -2567,9 +2565,9 @@ class binary_reader { std::uint16_t len{}; std::int8_t subtype{}; - return get_number(input_format_t::msgpack, len) && - get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, len, result) && + return get_number(len) && + get_number(subtype) && + get_binary(len, result) && assign_and_return_true(subtype); } @@ -2577,49 +2575,49 @@ class binary_reader { std::uint32_t len{}; std::int8_t subtype{}; - return get_number(input_format_t::msgpack, len) && - get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, len, result) && + return get_number(len) && + get_number(subtype) && + get_binary(len, result) && assign_and_return_true(subtype); } case 0xD4: // fixext 1 { std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 1, result) && + return get_number(subtype) && + get_binary(1, result) && assign_and_return_true(subtype); } case 0xD5: // fixext 2 { std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 2, result) && + return get_number(subtype) && + get_binary(2, result) && assign_and_return_true(subtype); } case 0xD6: // fixext 4 { std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 4, result) && + return get_number(subtype) && + get_binary(4, result) && assign_and_return_true(subtype); } case 0xD7: // fixext 8 { std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 8, result) && + return get_number(subtype) && + get_binary(8, result) && assign_and_return_true(subtype); } case 0xD8: // fixext 16 { std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 16, result) && + return get_number(subtype) && + get_binary(16, result) && assign_and_return_true(subtype); } @@ -2716,7 +2714,7 @@ class binary_reader { get(); } - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "value"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("value"))) { return false; } @@ -2757,7 +2755,7 @@ class binary_reader case 0xD9: // str 8 { std::uint8_t len{}; - return get_number(input_format_t::msgpack, len) && skip_bytes(len + (head == 0xC7 ? 1u : 0u), context); + return get_number(len) && skip_bytes(len + (head == 0xC7 ? 1u : 0u), context); } case 0xC5: // bin 16 @@ -2765,7 +2763,7 @@ class binary_reader case 0xDA: // str 16 { std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && skip_bytes(len + (head == 0xC8 ? 1u : 0u), context); + return get_number(len) && skip_bytes(len + (head == 0xC8 ? 1u : 0u), context); } case 0xC6: // bin 32 @@ -2773,7 +2771,7 @@ class binary_reader case 0xDB: // str 32 { std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && skip_bytes(static_cast(len) + (head == 0xC9 ? 1u : 0u), context); + return get_number(len) && skip_bytes(static_cast(len) + (head == 0xC9 ? 1u : 0u), context); } case 0xCC: // uint 8 @@ -2813,7 +2811,7 @@ class binary_reader case 0xDE: // map 16 { std::uint16_t len{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::msgpack, len))) + if (JSON_HEDLEY_UNLIKELY(!get_number(len))) { return false; } @@ -2825,7 +2823,7 @@ class binary_reader case 0xDF: // map 32 { std::uint32_t len{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::msgpack, len))) + if (JSON_HEDLEY_UNLIKELY(!get_number(len))) { return false; } @@ -2837,7 +2835,7 @@ class binary_reader { auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr)); + exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr)); } } } @@ -2967,7 +2965,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(len < 0)) { return report_error(chars_read, get_token_string(), parse_error::create(113, chars_read, - exception_message(input_format, "string length must not be negative", "string"), nullptr)); + exception_message("string length must not be negative", "string"), nullptr)); } return true; } @@ -2997,7 +2995,7 @@ class binary_reader get(); } - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("value"))) { return false; } @@ -3007,31 +3005,31 @@ class binary_reader case 'U': { std::uint8_t len{}; - return get_number(input_format, len) && get_string(input_format, len, result) && check_string_utf8(result, context); + return get_number(len) && get_string(len, result) && check_string_utf8(result, context); } case 'i': { std::int8_t len{}; - return get_number(input_format, len) && check_ubjson_string_length(len) && get_string(input_format, len, result) && check_string_utf8(result, context); + return get_number(len) && check_ubjson_string_length(len) && get_string(len, result) && check_string_utf8(result, context); } case 'I': { std::int16_t len{}; - return get_number(input_format, len) && check_ubjson_string_length(len) && get_string(input_format, len, result) && check_string_utf8(result, context); + return get_number(len) && check_ubjson_string_length(len) && get_string(len, result) && check_string_utf8(result, context); } case 'l': { std::int32_t len{}; - return get_number(input_format, len) && check_ubjson_string_length(len) && get_string(input_format, len, result) && check_string_utf8(result, context); + return get_number(len) && check_ubjson_string_length(len) && get_string(len, result) && check_string_utf8(result, context); } case 'L': { std::int64_t len{}; - return get_number(input_format, len) && check_ubjson_string_length(len) && get_string(input_format, len, result) && check_string_utf8(result, context); + return get_number(len) && check_ubjson_string_length(len) && get_string(len, result) && check_string_utf8(result, context); } case 'u': @@ -3041,7 +3039,7 @@ class binary_reader break; } std::uint16_t len{}; - return get_number(input_format, len) && get_string(input_format, len, result) && check_string_utf8(result, context); + return get_number(len) && get_string(len, result) && check_string_utf8(result, context); } case 'm': @@ -3051,7 +3049,7 @@ class binary_reader break; } std::uint32_t len{}; - return get_number(input_format, len) && get_string(input_format, len, result) && check_string_utf8(result, context); + return get_number(len) && get_string(len, result) && check_string_utf8(result, context); } case 'M': @@ -3061,7 +3059,7 @@ class binary_reader break; } std::uint64_t len{}; - return get_number(input_format, len) && get_string(input_format, len, result) && check_string_utf8(result, context); + return get_number(len) && get_string(len, result) && check_string_utf8(result, context); } default: @@ -3078,7 +3076,7 @@ class binary_reader { message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token; } - return report_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr)); + return report_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(message, "string"), nullptr)); } /*! @@ -3157,19 +3155,19 @@ class binary_reader bool get_ubjson_signed_count(std::size_t& result) { SignedType number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(number))) { return false; } if (JSON_HEDLEY_UNLIKELY(number < 0)) { return report_error(chars_read, get_token_string(), parse_error::create(113, chars_read, - exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); + exception_message("count in an optimized container must be positive", "size"), nullptr)); } if (JSON_HEDLEY_UNLIKELY(!value_in_range_of(number))) { return report_error(chars_read, get_token_string(), out_of_range::create(408, - exception_message(input_format, "integer value overflow", "size"), nullptr)); + exception_message("integer value overflow", "size"), nullptr)); } result = static_cast(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char return true; @@ -3198,7 +3196,7 @@ class binary_reader case 'U': { std::uint8_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(number))) { return false; } @@ -3225,7 +3223,7 @@ class binary_reader break; } std::uint16_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(number))) { return false; } @@ -3240,7 +3238,7 @@ class binary_reader break; } std::uint32_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(number))) { return false; } @@ -3255,14 +3253,14 @@ class binary_reader break; } std::uint64_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(number))) { return false; } if (!value_in_range_of(number)) { return report_error(chars_read, get_token_string(), out_of_range::create(408, - exception_message(input_format, "integer value overflow", "size"), nullptr)); + exception_message("integer value overflow", "size"), nullptr)); } result = detail::conditional_static_cast(number); return true; @@ -3276,7 +3274,7 @@ class binary_reader } if (is_ndarray) // ndarray dimensional vector can only contain integers and cannot embed another array { - return report_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimensional vector is not allowed", "size"), nullptr)); + return report_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message("ndarray dimensional vector is not allowed", "size"), nullptr)); } std::vector dim; if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim))) @@ -3317,7 +3315,7 @@ class binary_reader // or SIZE_MAX. if (JSON_HEDLEY_UNLIKELY(result > (std::numeric_limits::max)() / i)) { - return report_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr)); + return report_error(chars_read, get_token_string(), out_of_range::create(408, exception_message("excessive ndarray size caused overflow", "size"), nullptr)); } result *= i; // the pre-check above already rules out result becoming 0 @@ -3326,9 +3324,9 @@ class binary_reader // unknown-size container (see get_ubjson_size_type()) if (result == npos) { - return report_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr)); + return report_error(chars_read, get_token_string(), out_of_range::create(408, exception_message("excessive ndarray size caused overflow", "size"), nullptr)); } - if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast(i)))) + if (JSON_HEDLEY_UNLIKELY(!emit_unsigned(i))) { return false; } @@ -3355,7 +3353,7 @@ class binary_reader { message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token; } - return report_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr)); + return report_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(message, "size"), nullptr)); } /*! @@ -3390,10 +3388,10 @@ class binary_reader { auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr)); + exception_message(concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr)); } - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("type"))) { return false; } @@ -3401,13 +3399,13 @@ class binary_reader get_ignore_noop(); if (JSON_HEDLEY_UNLIKELY(current != '#')) { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("value"))) { return false; } auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr)); + exception_message(concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr)); } const bool is_error = get_ubjson_size_value(result.first, is_ndarray); @@ -3427,7 +3425,7 @@ class binary_reader if (input_format == input_format_t::bjdata && is_ndarray && !inside_ndarray) { return report_error(chars_read, get_token_string(), parse_error::create(112, chars_read, - exception_message(input_format, "ndarray requires both type and size", "size"), nullptr)); + exception_message("ndarray requires both type and size", "size"), nullptr)); } return is_error; } @@ -3444,7 +3442,7 @@ class binary_reader switch (prefix) { case char_traits::eof(): // EOF - return unexpect_eof(input_format, "value"); + return unexpect_eof("value"); case 'T': // true return sax->boolean(true); @@ -3461,37 +3459,37 @@ class binary_reader break; } std::uint8_t number{}; - return get_number(input_format, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 'U': { std::uint8_t number{}; - return get_number(input_format, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 'i': { std::int8_t number{}; - return get_number(input_format, number) && sax->number_integer(conditional_static_cast(number)); + return get_number(number) && emit_signed(number); } case 'I': { std::int16_t number{}; - return get_number(input_format, number) && sax->number_integer(conditional_static_cast(number)); + return get_number(number) && emit_signed(number); } case 'l': { std::int32_t number{}; - return get_number(input_format, number) && sax->number_integer(conditional_static_cast(number)); + return get_number(number) && emit_signed(number); } case 'L': { std::int64_t number{}; - return get_number(input_format, number) && sax->number_integer(conditional_static_cast(number)); + return get_number(number) && emit_signed(number); } case 'u': @@ -3501,7 +3499,7 @@ class binary_reader break; } std::uint16_t number{}; - return get_number(input_format, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 'm': @@ -3511,7 +3509,7 @@ class binary_reader break; } std::uint32_t number{}; - return get_number(input_format, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 'M': @@ -3521,7 +3519,7 @@ class binary_reader break; } std::uint64_t number{}; - return get_number(input_format, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 'h': @@ -3530,19 +3528,19 @@ class binary_reader { break; } - return get_half_float(input_format, true); + return get_half_float(true); } case 'd': { float number{}; - return get_number(input_format, number) && sax->number_float(static_cast(number), ""); + return get_number(number) && emit_float(number); } case 'D': { double number{}; - return get_number(input_format, number) && sax->number_float(static_cast(number), ""); + return get_number(number) && emit_float(number); } case 'H': @@ -3553,7 +3551,7 @@ class binary_reader case 'C': // char { get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("char"))) { return false; } @@ -3561,7 +3559,7 @@ class binary_reader { auto last_token = get_token_string(); static_cast(report_error(chars_read, last_token, parse_error::create(113, chars_read, - exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr))); + exception_message(concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr))); if (!repair_requested()) { return false; @@ -3591,7 +3589,7 @@ class binary_reader break; } auto last_token = get_token_string(); - return report_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr)); + return report_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message("invalid byte: 0x" + last_token, "value"), nullptr)); } /*! @@ -3617,7 +3615,7 @@ class binary_reader { auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr)); + exception_message("invalid byte: 0x" + last_token, "type"), nullptr)); } string_t type = type_name; // sax->string() takes a reference @@ -3654,7 +3652,7 @@ class binary_reader if (input_format == input_format_t::bjdata && size_and_type.first != npos && size_and_type.second == 'B') { binary_t result; - return get_binary(input_format, size_and_type.first, result) && sax->binary(result); + return get_binary(size_and_type.first, result) && sax->binary(result); } if (size_and_type.first != npos) @@ -3667,7 +3665,7 @@ class binary_reader && size_and_type.first > max_valueless_container_size)) { return report_error(chars_read, get_token_string(), out_of_range::create(408, - exception_message(input_format, "excessive array size", "size"), nullptr)); + exception_message("excessive array size", "size"), nullptr)); } if (JSON_HEDLEY_UNLIKELY(!enter_array(size_and_type.first, size_and_type.second))) @@ -3704,7 +3702,7 @@ class binary_reader { auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr)); + exception_message("BJData object does not support ND-array size in optimized format", "object"), nullptr)); } if (size_and_type.first != npos) @@ -3734,7 +3732,7 @@ class binary_reader for (std::size_t i = 0; i < size; ++i) { get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("number"))) { return false; } @@ -3753,7 +3751,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) { static_cast(report_error(chars_read, number_string, parse_error::create(115, chars_read, - exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr))); + exception_message(concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr))); return recover_high_precision_number(number_vector); } @@ -3800,7 +3798,7 @@ class binary_reader case token_type::literal_or_value: default: static_cast(report_error(chars_read, number_string, parse_error::create(115, chars_read, - exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr))); + exception_message(concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr))); return recover_high_precision_number(number_vector); } } @@ -3932,7 +3930,7 @@ class binary_reader { auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::bon8, concat(detail, ": 0x", last_token), context), nullptr)); + exception_message(concat(detail, ": 0x", last_token), context), nullptr)); } /*! @@ -4044,7 +4042,7 @@ class binary_reader if (byte == char_traits::eof()) { - return unexpect_eof(input_format_t::bon8, "value"); + return unexpect_eof("value"); } // string: ASCII character @@ -4081,25 +4079,25 @@ class binary_reader case 0x8C: // int32 { std::int32_t number{}; - return get_number(input_format_t::bon8, number) && emit_bon8_integer(number); + return get_number(number) && emit_bon8_integer(number); } case 0x8D: // int64 { std::int64_t number{}; - return get_number(input_format_t::bon8, number) && emit_bon8_integer(number); + return get_number(number) && emit_bon8_integer(number); } case 0x8E: // binary32 { float number{}; - return get_number(input_format_t::bon8, number) && sax->number_float(static_cast(number), ""); + return get_number(number) && emit_float(number); } case 0x8F: // binary64 { double number{}; - return get_number(input_format_t::bon8, number) && sax->number_float(static_cast(number), ""); + return get_number(number) && emit_float(number); } case 0xF8: @@ -4165,7 +4163,9 @@ class binary_reader @brief pass an integer to the SAX parser Non-negative integers are passed as unsigned, negative integers as signed - numbers, like the other binary formats do. + numbers, like the other binary formats do. A value that does not fit the + number type is passed as described for @ref emit_unsigned and + @ref emit_signed. @param[in] number the integer @return whether the SAX parser accepted the value @@ -4174,9 +4174,9 @@ class binary_reader { if (number >= 0) { - return sax->number_unsigned(static_cast(number)); + return emit_unsigned(static_cast(number)); } - return sax->number_integer(static_cast(number)); + return emit_signed(number); } /*! @@ -4196,7 +4196,7 @@ class binary_reader */ bool get_bon8_integer(const char_int_type lead, const char_int_type second) { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bon8, "number"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("number"))) { return false; } @@ -4228,13 +4228,12 @@ class binary_reader { if (JSON_HEDLEY_UNLIKELY(get_bon8() == char_traits::eof())) { - return unexpect_eof(input_format_t::bon8, "number"); + return unexpect_eof("number"); } value = (value << 8) | static_cast(current); } - return negative ? sax->number_integer(static_cast(-(value + offset))) - : sax->number_unsigned(static_cast(value + offset)); + return emit_bon8_integer(negative ? -(value + offset) : value + offset); } /*! @@ -4252,7 +4251,7 @@ class binary_reader if (byte == char_traits::eof()) { - return unexpect_eof(input_format_t::bon8, "key"); + return unexpect_eof("key"); } if (byte == 0xFF) @@ -4272,7 +4271,7 @@ class binary_reader if (second == char_traits::eof()) { // the input ends inside a character or an integer - return unexpect_eof(input_format_t::bon8, "key"); + return unexpect_eof("key"); } unget_bon8(second); if (is_bon8_continuation(second)) @@ -4308,7 +4307,7 @@ class binary_reader if (byte == char_traits::eof()) { - return unexpect_eof(input_format_t::bon8, "value"); + return unexpect_eof("value"); } if (byte == 0xFE && end_allowed) @@ -4375,7 +4374,7 @@ class binary_reader unget_bon8(byte); return get_bon8_string(ignored); } - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bon8, "number"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("number"))) { return false; } @@ -4396,7 +4395,7 @@ class binary_reader { if (JSON_HEDLEY_UNLIKELY(get_bon8() == char_traits::eof())) { - return unexpect_eof(input_format_t::bon8, "number"); + return unexpect_eof("number"); } } return true; @@ -4460,7 +4459,7 @@ class binary_reader if (byte == char_traits::eof()) { - return unexpect_eof(input_format_t::bon8, "string"); + return unexpect_eof("string"); } // end of string @@ -4491,7 +4490,7 @@ class binary_reader { // the input ends inside a character or an integer: either // way, the message is incomplete - return unexpect_eof(input_format_t::bon8, "string"); + return unexpect_eof("string"); } if (!is_bon8_continuation(second)) { @@ -4532,7 +4531,7 @@ class binary_reader { if (JSON_HEDLEY_UNLIKELY(get_bon8() == char_traits::eof())) { - return unexpect_eof(input_format_t::bon8, "string"); + return unexpect_eof("string"); } if (JSON_HEDLEY_UNLIKELY(!is_bon8_continuation(current))) { @@ -4571,7 +4570,7 @@ class binary_reader @return bool, whether the read was successful */ template - bool get_to(T& dest, const input_format_t format, const char* context) + bool get_to(T& dest, const char* context) { // false positive: new_chars_read is read on the next lines // @infer-ignore DEAD_STORE @@ -4581,7 +4580,7 @@ class binary_reader { // in case of failure, advance position by 1 to report the failing location ++chars_read; - return report_error(chars_read, "", parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr)); + return report_error(chars_read, "", parse_error::create(110, chars_read, exception_message("unexpected end of input", context), nullptr)); } return true; } @@ -4631,7 +4630,6 @@ class binary_reader @brief read a number from the input @tparam NumberType the type of the number - @param[in] format the current format (for diagnostics) @param[out] result number of type @a NumberType @return whether conversion completed @@ -4643,42 +4641,124 @@ class binary_reader should reorder on big endian systems. */ template - bool get_number(const input_format_t format, NumberType& result) + bool get_number(NumberType& result) { // read in the original format - if (JSON_HEDLEY_UNLIKELY(!get_to(result, format, "number"))) + if (JSON_HEDLEY_UNLIKELY(!get_to(result, "number"))) { return false; } - if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata)) + if (is_little_endian != (InputIsLittleEndian || input_format == input_format_t::bjdata)) { byte_swap(result); } return true; } + /*! + @brief pass a signed integer read from the input to the SAX parser + + Like the lexer does for JSON text, a value that does not fit into + number_integer_t is passed as number_unsigned_t if it is non-negative and + fits there, and as number_float_t otherwise. With the default number + types, every integer the binary formats can encode fits, so this only + matters for narrower custom number types. + + @tparam NumberType a signed integer type + @param[in] number the integer + @return whether the SAX parser accepted the value + + @throw out_of_range.406 if @a number overflows number_float_t (see + @ref emit_float) + */ + template + bool emit_signed(const NumberType number) + { + if (JSON_HEDLEY_LIKELY(value_in_range_of(number))) + { + return sax->number_integer(static_cast(number)); + } + if (value_in_range_of(number)) + { + return sax->number_unsigned(static_cast(number)); + } + return emit_float(number); + } + + /*! + @brief pass an unsigned integer read from the input to the SAX parser + + Like the lexer does for JSON text, a value that does not fit into + number_unsigned_t is passed as number_float_t. + + @tparam NumberType an unsigned integer type + @param[in] number the integer + @return whether the SAX parser accepted the value + + @throw out_of_range.406 if @a number overflows number_float_t (see + @ref emit_float) + */ + template + bool emit_unsigned(const NumberType number) + { + if (JSON_HEDLEY_LIKELY(value_in_range_of(number))) + { + return sax->number_unsigned(static_cast(number)); + } + return emit_float(number); + } + + /*! + @brief pass a floating-point number read from the input to the SAX parser + + Like the lexer does for JSON text, a finite value that overflows + number_float_t is rejected instead of silently becoming infinity. Infinity + and NaN in the input are passed on unchanged. Integers only overflow if + number_float_t cannot represent 2^64, e.g., a half-precision type. + + @tparam NumberType a floating-point or integer type + @param[in] number the number + @return whether the SAX parser accepted the value + + @throw out_of_range.406 if a finite @a number overflows number_float_t + */ + template + bool emit_float(const NumberType number) + { + const auto result = static_cast(number); + if (JSON_HEDLEY_UNLIKELY(std::isfinite(number) && !std::isfinite(result))) + { + static_cast(report_error(chars_read, get_token_string(), + out_of_range::create(406, exception_message("number overflow", "value"), nullptr))); + // when recovering, the number becomes infinity, as in JSON text + if (!repair_requested()) + { + return false; + } + } + return sax->number_float(result, ""); + } + /*! @brief read and decode an IEEE 754 half-precision (16-bit) float Used by CBOR (big endian) and BJData (little endian); the two formats only differ in the byte order of the two bytes that make up the half. - - @param[in] format the current format (for diagnostics) @param[in] little_endian whether the two bytes are little endian (BJData) or big endian (CBOR) @return whether reading and decoding succeeded */ - bool get_half_float(const input_format_t format, const bool little_endian) + bool get_half_float(const bool little_endian) { const auto byte1_raw = get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("number"))) { return false; } const auto byte2_raw = get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("number"))) { return false; } @@ -4724,7 +4804,6 @@ class binary_reader @brief create a string by reading characters from the input @tparam NumberType the type of the number - @param[in] format the current format (for diagnostics) @param[in] len number of characters to read @param[out] result string created by reading @a len bytes @@ -4735,8 +4814,7 @@ class binary_reader the input before we run out of string memory. */ template - bool get_string(const input_format_t format, - const NumberType len, + bool get_string(const NumberType len, string_t& result) { // Strings are taken as is by default: none of CBOR (RFC 8949 §3.1 @@ -4748,7 +4826,7 @@ class binary_reader // @ref error_handler, applied once the whole string (all chunks of // an indefinite-length CBOR string included) has been assembled, by // @ref check_string_utf8 at the call site. - return get_bytes(format, len, "string", result); + return get_bytes(len, "string", result); } /*! @@ -4779,7 +4857,7 @@ class binary_reader { auto last_token = get_token_string(); static_cast(report_error(chars_read, last_token, parse_error::create(113, chars_read, - exception_message(input_format, "invalid string: ill-formed UTF-8 byte", context), nullptr))); + exception_message("invalid string: ill-formed UTF-8 byte", context), nullptr))); // when recovering, the string is repaired as with // error_handler_t::replace if (!repair_requested()) @@ -4798,7 +4876,6 @@ class binary_reader @brief create a byte array by reading bytes from the input @tparam NumberType the type of the number - @param[in] format the current format (for diagnostics) @param[in] len number of bytes to read @param[out] result byte array created by reading @a len bytes @@ -4809,11 +4886,10 @@ class binary_reader the input before we run out of memory. */ template - bool get_binary(const input_format_t format, - const NumberType len, + bool get_binary(const NumberType len, binary_t& result) { - return get_bytes(format, len, "binary", result); + return get_bytes(len, "binary", result); } /*! @@ -4821,7 +4897,6 @@ class binary_reader @tparam NumberType the type of the length @tparam ContainerType the destination container (string_t or binary_t) - @param[in] format the current format (for diagnostics) @param[in] len number of bytes to read @param[in] context further context information (for diagnostics) @param[out] result container the bytes are appended to @@ -4836,8 +4911,7 @@ class binary_reader detects a premature end of input. */ template - bool get_bytes(const input_format_t format, - NumberType len, + bool get_bytes(NumberType len, const char* context, ContainerType& result) { @@ -4868,7 +4942,7 @@ class binary_reader result.resize(old_size + bytes_read); ++chars_read; current = char_traits::eof(); - return unexpect_eof(format, context); + return unexpect_eof(context); } // a full chunk was read; get_elements() never returns more than requested JSON_ASSERT(bytes_read == wanted); @@ -5156,7 +5230,7 @@ class binary_reader for (; len != 0; --len) { get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, context))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(context))) { return false; } @@ -5165,17 +5239,16 @@ class binary_reader } /*! - @param[in] format the current format (for diagnostics) @param[in] context further context information (for diagnostics) @return whether the last read character is not EOF */ - JSON_HEDLEY_NON_NULL(3) - bool unexpect_eof(const input_format_t format, const char* context) + JSON_HEDLEY_NON_NULL(2) + bool unexpect_eof(const char* context) { if (JSON_HEDLEY_UNLIKELY(current == char_traits::eof())) { return report_error(chars_read, "", - parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr)); + parse_error::create(110, chars_read, exception_message("unexpected end of input", context), nullptr)); } return true; } @@ -5191,18 +5264,16 @@ class binary_reader } /*! - @param[in] format the current format @param[in] detail a detailed error message @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, - const std::string& detail, + std::string exception_message(const std::string& detail, const std::string& context) const { std::string error_msg = "syntax error while parsing "; - switch (format) + switch (input_format) { case input_format_t::cbor: error_msg += "CBOR"; diff --git a/include/nlohmann/detail/macro_unscope.hpp b/include/nlohmann/detail/macro_unscope.hpp index 55b2ac99e..75bf14c92 100644 --- a/include/nlohmann/detail/macro_unscope.hpp +++ b/include/nlohmann/detail/macro_unscope.hpp @@ -43,6 +43,7 @@ #undef JSON_PRECISE_STREAM_POSITION #undef JSON_STRICT_NUL_HANDLING #undef JSON_STRICT_BINARY_UTF8 + #undef JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS #endif #include diff --git a/include/nlohmann/detail/meta/type_traits.hpp b/include/nlohmann/detail/meta/type_traits.hpp index 68bf4ad2c..69ab05f4e 100644 --- a/include/nlohmann/detail/meta/type_traits.hpp +++ b/include/nlohmann/detail/meta/type_traits.hpp @@ -438,6 +438,30 @@ template struct is_compatible_object_type : is_compatible_object_type_impl {}; +template +using insert_result_t = decltype(std::declval().insert(std::declval&>())); + +template +using insert_result_second_t = decltype(std::declval().insert(std::declval&>()).second); + +// a map-like type (std::map, std::unordered_map, ...) whose keys are enums; see +// JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS +template +struct is_enum_keyed_map : std::false_type {}; + +template +struct is_enum_keyed_map < + T, enable_if_t < is_detected::value&& + is_detected::value >> +{ + // maps with non-unique keys (std::multimap, std::unordered_multimap, ...) + // are excluded, because an object cannot hold duplicate keys; they are + // detected by insert() returning an iterator instead of a pair + // NOLINTNEXTLINE(modernize-type-traits) we use C++11 + static constexpr bool value = std::is_enum::value && + !(is_detected::value && !is_detected::value); +}; + template struct is_constructible_object_type_impl : std::false_type {}; diff --git a/nlohmann_json.natvis b/nlohmann_json.natvis index 17029f1dd..405bc6e54 100644 --- a/nlohmann_json.natvis +++ b/nlohmann_json.natvis @@ -515,6 +515,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -875,6 +935,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -1175,6 +1295,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -1415,6 +1595,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -1595,6 +1835,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -1715,6 +2015,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -1775,6 +2135,126 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -2075,6 +2555,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -2315,6 +2855,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -2495,6 +3095,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -2615,6 +3275,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -2675,6 +3395,126 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -2915,6 +3755,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -3095,6 +3995,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -3215,6 +4175,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -3275,6 +4295,126 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -3455,6 +4595,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -3575,6 +4775,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -3635,6 +4895,126 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -3755,6 +5135,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -3815,6 +5255,126 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -3875,6 +5435,186 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -4115,6 +5855,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -4295,6 +6095,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -4415,6 +6275,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -4475,6 +6395,126 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -4655,6 +6695,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -4775,6 +6875,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -4835,6 +6995,126 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -4955,6 +7235,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -5015,6 +7355,126 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -5075,6 +7535,186 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -5255,6 +7895,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -5375,6 +8075,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -5435,6 +8195,126 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -5555,6 +8435,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -5615,6 +8555,126 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -5675,6 +8735,186 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -5795,6 +9035,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -5855,6 +9155,126 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -5915,6 +9335,186 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -5975,6 +9575,246 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -6155,6 +9995,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -6275,6 +10175,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -6335,6 +10295,126 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -6455,6 +10535,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -6515,6 +10655,126 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -6575,6 +10835,186 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -6695,6 +11135,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -6755,6 +11255,126 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -6815,6 +11435,186 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -6875,6 +11675,246 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -6995,6 +12035,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -7055,6 +12155,126 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -7115,6 +12335,186 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -7175,6 +12575,246 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -7235,6 +12875,306 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -7355,6 +13295,66 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -7415,6 +13415,126 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -7475,6 +13595,186 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -7535,6 +13835,246 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -7595,6 +14135,306 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -7655,6 +14495,366 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + null @@ -7715,4 +14915,484 @@ + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded + + + *(m_data.m_value.object),view(simple) + + + *(m_data.m_value.array),view(simple) + + + + + + + {second} + + second + + + diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 7d64b1c74..cd7296458 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -108,6 +108,10 @@ #define JSON_STRICT_BINARY_UTF8 0 #endif +#ifndef JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS + #define JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS 0 +#endif + #if JSON_DIAGNOSTICS #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag #else @@ -150,14 +154,20 @@ #define NLOHMANN_JSON_ABI_TAG_STRICT_BINARY_UTF8 #endif +#if JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS + #define NLOHMANN_JSON_ABI_TAG_OBJECTS_FOR_ENUM_KEYED_MAPS _ekmo +#else + #define NLOHMANN_JSON_ABI_TAG_OBJECTS_FOR_ENUM_KEYED_MAPS +#endif + #ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 #endif // Construct the namespace ABI tags component -#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c, d, e, f, g) json_abi ## a ## b ## c ## d ## e ## f ## g -#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c, d, e, f, g) \ - NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c, d, e, f, g) +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c, d, e, f, g, h) json_abi ## a ## b ## c ## d ## e ## f ## g ## h +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c, d, e, f, g, h) \ + NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c, d, e, f, g, h) #define NLOHMANN_JSON_ABI_TAGS \ NLOHMANN_JSON_ABI_TAGS_CONCAT( \ @@ -167,7 +177,8 @@ NLOHMANN_JSON_ABI_TAG_BRACE_INIT_COPY_SEMANTICS, \ NLOHMANN_JSON_ABI_TAG_PRECISE_STREAM_POSITION, \ NLOHMANN_JSON_ABI_TAG_STRICT_NUL_HANDLING, \ - NLOHMANN_JSON_ABI_TAG_STRICT_BINARY_UTF8) + NLOHMANN_JSON_ABI_TAG_STRICT_BINARY_UTF8, \ + NLOHMANN_JSON_ABI_TAG_OBJECTS_FOR_ENUM_KEYED_MAPS) // Construct the namespace version component #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ @@ -4422,6 +4433,30 @@ template struct is_compatible_object_type : is_compatible_object_type_impl {}; +template +using insert_result_t = decltype(std::declval().insert(std::declval&>())); + +template +using insert_result_second_t = decltype(std::declval().insert(std::declval&>()).second); + +// a map-like type (std::map, std::unordered_map, ...) whose keys are enums; see +// JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS +template +struct is_enum_keyed_map : std::false_type {}; + +template +struct is_enum_keyed_map < + T, enable_if_t < is_detected::value&& + is_detected::value >> +{ + // maps with non-unique keys (std::multimap, std::unordered_multimap, ...) + // are excluded, because an object cannot hold duplicate keys; they are + // detected by insert() returning an iterator instead of a pair + // NOLINTNEXTLINE(modernize-type-traits) we use C++11 + static constexpr bool value = std::is_enum::value && + !(is_detected::value && !is_detected::value); +}; + template struct is_constructible_object_type_impl : std::false_type {}; @@ -6019,11 +6054,40 @@ void from_json_pair_array_to_map(const BasicJsonType& j, MapType& m) } } +// read a map with enum keys from an object, using the enum's own from_json for +// the keys (e.g., from NLOHMANN_JSON_SERIALIZE_ENUM); this is the form written +// with JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS +template +inline bool from_json_enum_keyed_object(const BasicJsonType& j, Map& m, std::true_type /*key is enum*/) +{ + if (!j.is_object()) + { + return false; + } + m.clear(); + for (const auto& p : *j.template get_ptr()) + { + m.emplace(BasicJsonType(p.first).template get(), p.second.template get()); + } + return true; +} + +template +inline bool from_json_enum_keyed_object(const BasicJsonType& /*j*/, Map& /*m*/, std::false_type /*key is enum*/) +{ + return false; +} + template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator, typename = enable_if_t < !std::is_constructible < typename BasicJsonType::string_t, Key >::value >> void from_json(const BasicJsonType& j, std::map& m) { + // NOLINTNEXTLINE(modernize-type-traits) we use C++11 + if (from_json_enum_keyed_object(j, m, std::is_enum {})) + { + return; + } from_json_pair_array_to_map(j, m); } @@ -6032,6 +6096,11 @@ template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename BasicJsonType::string_t, Key >::value >> void from_json(const BasicJsonType& j, std::unordered_map& m) { + // NOLINTNEXTLINE(modernize-type-traits) we use C++11 + if (from_json_enum_keyed_object(j, m, std::is_enum {})) + { + return; + } from_json_pair_array_to_map(j, m); } @@ -6115,6 +6184,8 @@ NLOHMANN_JSON_NAMESPACE_END #include // valarray #include // vector +// #include + // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ @@ -7090,6 +7161,9 @@ template < typename BasicJsonType, typename CompatibleArrayType, !is_basic_json::value #if JSON_HAS_RANGE_VIEW_CONVERSION && !is_compatible_range_view::value +#endif +#if JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS + && !is_enum_keyed_map::value #endif , int > = 0 > @@ -7144,6 +7218,33 @@ inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj) external_constructor::construct(j, obj); } +#if JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS +// store a map with enum keys as an object, using the enum's own to_json for the +// keys (e.g., from NLOHMANN_JSON_SERIALIZE_ENUM); without the macro, such maps +// are stored as arrays of [key, value] pairs +template < typename BasicJsonType, typename EnumKeyedMap, + enable_if_t < is_enum_keyed_map::value&& !is_basic_json::value, int > = 0 > +inline void to_json(BasicJsonType& j, const EnumKeyedMap& map) +{ + typename BasicJsonType::object_t obj; + for (const auto& p : map) + { + BasicJsonType key = p.first; + if (JSON_HEDLEY_UNLIKELY(!key.is_string())) + { + JSON_THROW(type_error::create(302, concat("type must be string, but is ", key.type_name()), &key)); + } + + auto& key_string = *key.template get_ptr(); + if (JSON_HEDLEY_UNLIKELY(!obj.emplace(key_string, BasicJsonType(p.second)).second)) + { + JSON_THROW(type_error::create(318, concat("duplicate object key '", key_string, "'"), &key)); + } + } + external_constructor::construct(j, std::move(obj)); +} +#endif + template inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) { @@ -14405,7 +14506,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(current != char_traits::eof())) { return report_error(chars_read, get_token_string(), parse_error::create(110, chars_read, - exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr)); + exception_message(concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr)); } } @@ -14537,7 +14638,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(document_size < 0 || static_cast(document_size) != chars_read - document_start)) { static_cast(report_error(chars_read, get_token_string(), parse_error::create(112, chars_read, - exception_message(input_format_t::bson, concat("document size ", std::to_string(document_size), " does not match the number of bytes read (", std::to_string(chars_read - document_start), ")"), "document"), nullptr))); + exception_message(concat("document size ", std::to_string(document_size), " does not match the number of bytes read (", std::to_string(chars_read - document_start), ")"), "document"), nullptr))); return repair_requested(); } return true; @@ -14637,7 +14738,7 @@ class binary_reader if (size < 0) { std::int32_t len{}; - if (!get_number(input_format_t::bson, len)) + if (!get_number(len)) { return false; } @@ -14678,7 +14779,7 @@ class binary_reader // check_bson_document_size() measures the document from here const std::size_t document_start = chars_read; std::int32_t document_size{}; - if (!get_number(input_format_t::bson, document_size)) + if (!get_number(document_size)) { return false; } @@ -14743,7 +14844,7 @@ class binary_reader continue; } - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("element list"))) { return false; } @@ -14790,7 +14891,7 @@ class binary_reader while (true) { get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("cstring"))) { return false; } @@ -14862,10 +14963,10 @@ class binary_reader skip_requested = true; auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr)); + exception_message(concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr)); } - if (JSON_HEDLEY_UNLIKELY(!get_string(input_format_t::bson, len - static_cast(1), result))) + if (JSON_HEDLEY_UNLIKELY(!get_string(len - static_cast(1), result))) { return false; } @@ -14874,8 +14975,7 @@ class binary_reader { auto last_token = get_token_string(); static_cast(report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::bson, - "BSON string is not null-terminated", + exception_message("BSON string is not null-terminated", "string"), nullptr))); // when recovering, a byte in place of the terminator is dropped; // the end of the input is not @@ -14903,18 +15003,18 @@ class binary_reader skip_requested = true; auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr)); + exception_message(concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr)); } // All BSON binary values have a subtype std::uint8_t subtype{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::bson, subtype))) + if (JSON_HEDLEY_UNLIKELY(!get_number(subtype))) { return false; } result.set_subtype(subtype); - return get_binary(input_format_t::bson, len, result); + return get_binary(len, result); } /*! @@ -14935,14 +15035,14 @@ class binary_reader case 0x01: // double { double number{}; - return get_number(input_format_t::bson, number) && sax->number_float(static_cast(number), ""); + return get_number(number) && emit_float(number); } case 0x02: // string { std::int32_t len{}; string_t value; - return get_number(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value); + return get_number(len) && get_bson_string(len, value) && sax->string(value); } case 0x03: // object @@ -14959,13 +15059,13 @@ class binary_reader { std::int32_t len{}; binary_t value; - return get_number(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value); + return get_number(len) && get_bson_binary(len, value) && sax->binary(value); } case 0x08: // boolean { std::uint8_t value{}; - return get_number(input_format_t::bson, value) && sax->boolean(value != 0); + return get_number(value) && sax->boolean(value != 0); } case 0x0A: // null @@ -14976,19 +15076,19 @@ class binary_reader case 0x10: // int32 { std::int32_t value{}; - return get_number(input_format_t::bson, value) && sax->number_integer(conditional_static_cast(value)); + return get_number(value) && emit_signed(value); } case 0x12: // int64 { std::int64_t value{}; - return get_number(input_format_t::bson, value) && sax->number_integer(conditional_static_cast(value)); + return get_number(value) && emit_signed(value); } case 0x11: // uint64 { std::uint64_t value{}; - return get_number(input_format_t::bson, value) && sax->number_unsigned(value); + return get_number(value) && emit_unsigned(value); } default: // anything else is not supported (yet) @@ -15011,24 +15111,23 @@ class binary_reader bool get_cbor_negative_integer() { NumberType number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::cbor, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(number))) { return false; } - const auto max_val = static_cast((std::numeric_limits::max)()); - if (number > max_val) + + // the value is -1 - number, which fits into number_integer_t + // whenever number does + if (JSON_HEDLEY_LIKELY(value_in_range_of(number))) { - static_cast(report_error(chars_read, get_token_string(), - parse_error::create(112, chars_read, - exception_message(input_format_t::cbor, "negative integer overflow", "value"), nullptr))); - if (!repair_requested()) - { - return false; - } - // too small for number_integer_t: pass the nearest floating-point number - return sax->number_float(static_cast(-1) - static_cast(number), ""); + return sax->number_integer(static_cast(-1) - static_cast(number)); } - return sax->number_integer(conditional_static_cast(static_cast(-1) - static_cast(number))); + + // like the lexer does for JSON text, store a value too small for + // number_integer_t as number_float_t; compute it as long double so + // that emit_float sees a finite value and can detect an overflow of + // number_float_t + return emit_float(static_cast(-1) - static_cast(number)); } /*! @@ -15053,7 +15152,7 @@ class binary_reader { // EOF case char_traits::eof(): - return unexpect_eof(input_format_t::cbor, "value"); + return unexpect_eof("value"); // Integer 0x00..0x17 (0..23) case 0x00: @@ -15085,25 +15184,25 @@ class binary_reader case 0x18: // Unsigned integer (one-byte uint8_t follows) { std::uint8_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 0x19: // Unsigned integer (two-byte uint16_t follows) { std::uint16_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 0x1A: // Unsigned integer (four-byte uint32_t follows) { std::uint32_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 0x1B: // Unsigned integer (eight-byte uint64_t follows) { std::uint64_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } // Negative integer -1-0x00..-1-0x17 (-1..-24) @@ -15324,7 +15423,7 @@ class binary_reader { auto last_token = get_token_string(); static_cast(report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr))); + exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr))); if (!repair_requested()) { return false; @@ -15352,7 +15451,7 @@ class binary_reader { auto last_token = get_token_string(); static_cast(report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr))); + exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr))); if (!repair_requested()) { return false; @@ -15417,18 +15516,18 @@ class binary_reader return sax->null(); case 0xF9: // Half-Precision Float (two-byte IEEE 754) - return get_half_float(input_format_t::cbor, false); + return get_half_float(false); case 0xFA: // Single-Precision Float (four-byte IEEE 754) { float number{}; - return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); + return get_number(number) && emit_float(number); } case 0xFB: // Double-Precision Float (eight-byte IEEE 754) { double number{}; - return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); + return get_number(number) && emit_float(number); } default: // anything else (0xFF is handled inside the other types) @@ -15438,7 +15537,7 @@ class binary_reader // 0xF7 for undefined, and 0xF8 followed by a byte) are complete const bool simple_value = (current >= 0xE0 && current <= 0xF3) || current == 0xF7 || current == 0xF8; static_cast(report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr))); + exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr))); if (!simple_value || !repair_requested()) { return false; @@ -15446,7 +15545,7 @@ class binary_reader // when recovering, a simple value becomes null, as RFC 8949, // Section 6.1 suggests for converting to JSON std::uint8_t ignored{}; - return (current != 0xF8 || get_number(input_format_t::cbor, ignored)) && sax->null(); + return (current != 0xF8 || get_number(ignored)) && sax->null(); } } } @@ -15495,38 +15594,38 @@ class binary_reader case 0x76: case 0x77: { - return get_string(input_format_t::cbor, static_cast(current) & 0x1Fu, result); + return get_string(static_cast(current) & 0x1Fu, result); } case 0x78: // UTF-8 string (one-byte uint8_t for n follows) { std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + return get_number(len) && get_string(len, result); } case 0x79: // UTF-8 string (two-byte uint16_t for n follow) { std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + return get_number(len) && get_string(len, result); } case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) { std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + return get_number(len) && get_string(len, result); } case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) { std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + return get_number(len) && get_string(len, result); } default: { auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(113, chars_read, - exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr)); + exception_message(concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr)); } } } @@ -15554,7 +15653,7 @@ class binary_reader while (true) { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("string"))) { return false; } @@ -15667,7 +15766,7 @@ class binary_reader skip_requested = is_cbor_item_head(static_cast(current)); auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(113, chars_read, - exception_message(input_format_t::cbor, concat("only string keys are supported, but found ", found, "; last byte: 0x", last_token), "object key"), nullptr)); + exception_message(concat("only string keys are supported, but found ", found, "; last byte: 0x", last_token), "object key"), nullptr)); } /*! @@ -15714,42 +15813,42 @@ class binary_reader case 0x56: case 0x57: { - return get_binary(input_format_t::cbor, static_cast(current) & 0x1Fu, result); + return get_binary(static_cast(current) & 0x1Fu, result); } case 0x58: // Binary data (one-byte uint8_t for n follows) { std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); + return get_number(len) && + get_binary(len, result); } case 0x59: // Binary data (two-byte uint16_t for n follow) { std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); + return get_number(len) && + get_binary(len, result); } case 0x5A: // Binary data (four-byte uint32_t for n follow) { std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); + return get_number(len) && + get_binary(len, result); } case 0x5B: // Binary data (eight-byte uint64_t for n follow) { std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); + return get_number(len) && + get_binary(len, result); } default: { auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(113, chars_read, - exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr)); + exception_message(concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr)); } } } @@ -15773,7 +15872,7 @@ class binary_reader while (true) { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("binary"))) { return false; } @@ -15831,7 +15930,7 @@ class binary_reader case 0x18: // 1 byte { std::uint8_t n{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::cbor, n))) + if (JSON_HEDLEY_UNLIKELY(!get_number(n))) { return false; } @@ -15842,7 +15941,7 @@ class binary_reader case 0x19: // 2 bytes { std::uint16_t n{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::cbor, n))) + if (JSON_HEDLEY_UNLIKELY(!get_number(n))) { return false; } @@ -15853,7 +15952,7 @@ class binary_reader case 0x1A: // 4 bytes { std::uint32_t n{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::cbor, n))) + if (JSON_HEDLEY_UNLIKELY(!get_number(n))) { return false; } @@ -15864,7 +15963,7 @@ class binary_reader case 0x1B: // 8 bytes { std::uint64_t n{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::cbor, n))) + if (JSON_HEDLEY_UNLIKELY(!get_number(n))) { return false; } @@ -15897,7 +15996,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(!value_in_range_of(len) || len == detail::unknown_size())) { return report_error(chars_read, get_token_string(), out_of_range::create(408, - exception_message(input_format_t::cbor, concat("excessive ", context, " size"), "size"), nullptr)); + exception_message(concat("excessive ", context, " size"), "size"), nullptr)); } result = conditional_static_cast(len); return true; @@ -16033,7 +16132,7 @@ class binary_reader { get(); } - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "value"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("value"))) { return false; } @@ -16048,7 +16147,7 @@ class binary_reader { auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr)); + exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr)); } const auto major_type = static_cast(current) >> 5u; @@ -16058,7 +16157,7 @@ class binary_reader case 24: { std::uint8_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::cbor, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(number))) { return false; } @@ -16069,7 +16168,7 @@ class binary_reader case 25: { std::uint16_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::cbor, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(number))) { return false; } @@ -16080,7 +16179,7 @@ class binary_reader case 26: { std::uint32_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::cbor, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(number))) { return false; } @@ -16090,7 +16189,7 @@ class binary_reader case 27: { - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::cbor, argument))) + if (JSON_HEDLEY_UNLIKELY(!get_number(argument))) { return false; } @@ -16148,7 +16247,7 @@ class binary_reader { // EOF case char_traits::eof(): - return unexpect_eof(input_format_t::msgpack, "value"); + return unexpect_eof("value"); // positive fixint case 0x00: @@ -16388,85 +16487,85 @@ class binary_reader case 0xCA: // float 32 { float number{}; - return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); + return get_number(number) && emit_float(number); } case 0xCB: // float 64 { double number{}; - return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); + return get_number(number) && emit_float(number); } case 0xCC: // uint 8 { std::uint8_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 0xCD: // uint 16 { std::uint16_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 0xCE: // uint 32 { std::uint32_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 0xCF: // uint 64 { std::uint64_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 0xD0: // int 8 { std::int8_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(conditional_static_cast(number)); + return get_number(number) && emit_signed(number); } case 0xD1: // int 16 { std::int16_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(conditional_static_cast(number)); + return get_number(number) && emit_signed(number); } case 0xD2: // int 32 { std::int32_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(conditional_static_cast(number)); + return get_number(number) && emit_signed(number); } case 0xD3: // int 64 { std::int64_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(conditional_static_cast(number)); + return get_number(number) && emit_signed(number); } case 0xDC: // array 16 { std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && enter_array(static_cast(len)); + return get_number(len) && enter_array(static_cast(len)); } case 0xDD: // array 32 { std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && enter_array(conditional_static_cast(len)); + return get_number(len) && enter_array(conditional_static_cast(len)); } case 0xDE: // map 16 { std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && enter_object(static_cast(len)); + return get_number(len) && enter_object(static_cast(len)); } case 0xDF: // map 32 { std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && enter_object(conditional_static_cast(len)); + return get_number(len) && enter_object(conditional_static_cast(len)); } // negative fixint @@ -16508,7 +16607,7 @@ class binary_reader { auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr)); + exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr)); } } } @@ -16525,7 +16624,7 @@ class binary_reader */ bool get_msgpack_string(string_t& result, const char* context = "string") { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("string"))) { return false; } @@ -16566,32 +16665,32 @@ class binary_reader case 0xBE: case 0xBF: { - return get_string(input_format_t::msgpack, static_cast(current) & 0x1Fu, result) && check_string_utf8(result, context); + return get_string(static_cast(current) & 0x1Fu, result) && check_string_utf8(result, context); } case 0xD9: // str 8 { std::uint8_t len{}; - return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result) && check_string_utf8(result, context); + return get_number(len) && get_string(len, result) && check_string_utf8(result, context); } case 0xDA: // str 16 { std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result) && check_string_utf8(result, context); + return get_number(len) && get_string(len, result) && check_string_utf8(result, context); } case 0xDB: // str 32 { std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result) && check_string_utf8(result, context); + return get_number(len) && get_string(len, result) && check_string_utf8(result, context); } default: { auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(113, chars_read, - exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr)); + exception_message(concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr)); } } } @@ -16688,7 +16787,7 @@ class binary_reader skip_requested = true; auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(113, chars_read, - exception_message(input_format_t::msgpack, concat("only string keys are supported, but found ", found, "; last byte: 0x", last_token), "object key"), nullptr)); + exception_message(concat("only string keys are supported, but found ", found, "; last byte: 0x", last_token), "object key"), nullptr)); } /*! @@ -16715,31 +16814,31 @@ class binary_reader case 0xC4: // bin 8 { std::uint8_t len{}; - return get_number(input_format_t::msgpack, len) && - get_binary(input_format_t::msgpack, len, result); + return get_number(len) && + get_binary(len, result); } case 0xC5: // bin 16 { std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && - get_binary(input_format_t::msgpack, len, result); + return get_number(len) && + get_binary(len, result); } case 0xC6: // bin 32 { std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && - get_binary(input_format_t::msgpack, len, result); + return get_number(len) && + get_binary(len, result); } case 0xC7: // ext 8 { std::uint8_t len{}; std::int8_t subtype{}; - return get_number(input_format_t::msgpack, len) && - get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, len, result) && + return get_number(len) && + get_number(subtype) && + get_binary(len, result) && assign_and_return_true(subtype); } @@ -16747,9 +16846,9 @@ class binary_reader { std::uint16_t len{}; std::int8_t subtype{}; - return get_number(input_format_t::msgpack, len) && - get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, len, result) && + return get_number(len) && + get_number(subtype) && + get_binary(len, result) && assign_and_return_true(subtype); } @@ -16757,49 +16856,49 @@ class binary_reader { std::uint32_t len{}; std::int8_t subtype{}; - return get_number(input_format_t::msgpack, len) && - get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, len, result) && + return get_number(len) && + get_number(subtype) && + get_binary(len, result) && assign_and_return_true(subtype); } case 0xD4: // fixext 1 { std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 1, result) && + return get_number(subtype) && + get_binary(1, result) && assign_and_return_true(subtype); } case 0xD5: // fixext 2 { std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 2, result) && + return get_number(subtype) && + get_binary(2, result) && assign_and_return_true(subtype); } case 0xD6: // fixext 4 { std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 4, result) && + return get_number(subtype) && + get_binary(4, result) && assign_and_return_true(subtype); } case 0xD7: // fixext 8 { std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 8, result) && + return get_number(subtype) && + get_binary(8, result) && assign_and_return_true(subtype); } case 0xD8: // fixext 16 { std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 16, result) && + return get_number(subtype) && + get_binary(16, result) && assign_and_return_true(subtype); } @@ -16896,7 +16995,7 @@ class binary_reader { get(); } - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "value"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("value"))) { return false; } @@ -16937,7 +17036,7 @@ class binary_reader case 0xD9: // str 8 { std::uint8_t len{}; - return get_number(input_format_t::msgpack, len) && skip_bytes(len + (head == 0xC7 ? 1u : 0u), context); + return get_number(len) && skip_bytes(len + (head == 0xC7 ? 1u : 0u), context); } case 0xC5: // bin 16 @@ -16945,7 +17044,7 @@ class binary_reader case 0xDA: // str 16 { std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && skip_bytes(len + (head == 0xC8 ? 1u : 0u), context); + return get_number(len) && skip_bytes(len + (head == 0xC8 ? 1u : 0u), context); } case 0xC6: // bin 32 @@ -16953,7 +17052,7 @@ class binary_reader case 0xDB: // str 32 { std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && skip_bytes(static_cast(len) + (head == 0xC9 ? 1u : 0u), context); + return get_number(len) && skip_bytes(static_cast(len) + (head == 0xC9 ? 1u : 0u), context); } case 0xCC: // uint 8 @@ -16993,7 +17092,7 @@ class binary_reader case 0xDE: // map 16 { std::uint16_t len{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::msgpack, len))) + if (JSON_HEDLEY_UNLIKELY(!get_number(len))) { return false; } @@ -17005,7 +17104,7 @@ class binary_reader case 0xDF: // map 32 { std::uint32_t len{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::msgpack, len))) + if (JSON_HEDLEY_UNLIKELY(!get_number(len))) { return false; } @@ -17017,7 +17116,7 @@ class binary_reader { auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr)); + exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr)); } } } @@ -17147,7 +17246,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(len < 0)) { return report_error(chars_read, get_token_string(), parse_error::create(113, chars_read, - exception_message(input_format, "string length must not be negative", "string"), nullptr)); + exception_message("string length must not be negative", "string"), nullptr)); } return true; } @@ -17177,7 +17276,7 @@ class binary_reader get(); } - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("value"))) { return false; } @@ -17187,31 +17286,31 @@ class binary_reader case 'U': { std::uint8_t len{}; - return get_number(input_format, len) && get_string(input_format, len, result) && check_string_utf8(result, context); + return get_number(len) && get_string(len, result) && check_string_utf8(result, context); } case 'i': { std::int8_t len{}; - return get_number(input_format, len) && check_ubjson_string_length(len) && get_string(input_format, len, result) && check_string_utf8(result, context); + return get_number(len) && check_ubjson_string_length(len) && get_string(len, result) && check_string_utf8(result, context); } case 'I': { std::int16_t len{}; - return get_number(input_format, len) && check_ubjson_string_length(len) && get_string(input_format, len, result) && check_string_utf8(result, context); + return get_number(len) && check_ubjson_string_length(len) && get_string(len, result) && check_string_utf8(result, context); } case 'l': { std::int32_t len{}; - return get_number(input_format, len) && check_ubjson_string_length(len) && get_string(input_format, len, result) && check_string_utf8(result, context); + return get_number(len) && check_ubjson_string_length(len) && get_string(len, result) && check_string_utf8(result, context); } case 'L': { std::int64_t len{}; - return get_number(input_format, len) && check_ubjson_string_length(len) && get_string(input_format, len, result) && check_string_utf8(result, context); + return get_number(len) && check_ubjson_string_length(len) && get_string(len, result) && check_string_utf8(result, context); } case 'u': @@ -17221,7 +17320,7 @@ class binary_reader break; } std::uint16_t len{}; - return get_number(input_format, len) && get_string(input_format, len, result) && check_string_utf8(result, context); + return get_number(len) && get_string(len, result) && check_string_utf8(result, context); } case 'm': @@ -17231,7 +17330,7 @@ class binary_reader break; } std::uint32_t len{}; - return get_number(input_format, len) && get_string(input_format, len, result) && check_string_utf8(result, context); + return get_number(len) && get_string(len, result) && check_string_utf8(result, context); } case 'M': @@ -17241,7 +17340,7 @@ class binary_reader break; } std::uint64_t len{}; - return get_number(input_format, len) && get_string(input_format, len, result) && check_string_utf8(result, context); + return get_number(len) && get_string(len, result) && check_string_utf8(result, context); } default: @@ -17258,7 +17357,7 @@ class binary_reader { message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token; } - return report_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr)); + return report_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(message, "string"), nullptr)); } /*! @@ -17337,19 +17436,19 @@ class binary_reader bool get_ubjson_signed_count(std::size_t& result) { SignedType number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(number))) { return false; } if (JSON_HEDLEY_UNLIKELY(number < 0)) { return report_error(chars_read, get_token_string(), parse_error::create(113, chars_read, - exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); + exception_message("count in an optimized container must be positive", "size"), nullptr)); } if (JSON_HEDLEY_UNLIKELY(!value_in_range_of(number))) { return report_error(chars_read, get_token_string(), out_of_range::create(408, - exception_message(input_format, "integer value overflow", "size"), nullptr)); + exception_message("integer value overflow", "size"), nullptr)); } result = static_cast(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char return true; @@ -17378,7 +17477,7 @@ class binary_reader case 'U': { std::uint8_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(number))) { return false; } @@ -17405,7 +17504,7 @@ class binary_reader break; } std::uint16_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(number))) { return false; } @@ -17420,7 +17519,7 @@ class binary_reader break; } std::uint32_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(number))) { return false; } @@ -17435,14 +17534,14 @@ class binary_reader break; } std::uint64_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(number))) { return false; } if (!value_in_range_of(number)) { return report_error(chars_read, get_token_string(), out_of_range::create(408, - exception_message(input_format, "integer value overflow", "size"), nullptr)); + exception_message("integer value overflow", "size"), nullptr)); } result = detail::conditional_static_cast(number); return true; @@ -17456,7 +17555,7 @@ class binary_reader } if (is_ndarray) // ndarray dimensional vector can only contain integers and cannot embed another array { - return report_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimensional vector is not allowed", "size"), nullptr)); + return report_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message("ndarray dimensional vector is not allowed", "size"), nullptr)); } std::vector dim; if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim))) @@ -17497,7 +17596,7 @@ class binary_reader // or SIZE_MAX. if (JSON_HEDLEY_UNLIKELY(result > (std::numeric_limits::max)() / i)) { - return report_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr)); + return report_error(chars_read, get_token_string(), out_of_range::create(408, exception_message("excessive ndarray size caused overflow", "size"), nullptr)); } result *= i; // the pre-check above already rules out result becoming 0 @@ -17506,9 +17605,9 @@ class binary_reader // unknown-size container (see get_ubjson_size_type()) if (result == npos) { - return report_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr)); + return report_error(chars_read, get_token_string(), out_of_range::create(408, exception_message("excessive ndarray size caused overflow", "size"), nullptr)); } - if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast(i)))) + if (JSON_HEDLEY_UNLIKELY(!emit_unsigned(i))) { return false; } @@ -17535,7 +17634,7 @@ class binary_reader { message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token; } - return report_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr)); + return report_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(message, "size"), nullptr)); } /*! @@ -17570,10 +17669,10 @@ class binary_reader { auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr)); + exception_message(concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr)); } - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("type"))) { return false; } @@ -17581,13 +17680,13 @@ class binary_reader get_ignore_noop(); if (JSON_HEDLEY_UNLIKELY(current != '#')) { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("value"))) { return false; } auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr)); + exception_message(concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr)); } const bool is_error = get_ubjson_size_value(result.first, is_ndarray); @@ -17607,7 +17706,7 @@ class binary_reader if (input_format == input_format_t::bjdata && is_ndarray && !inside_ndarray) { return report_error(chars_read, get_token_string(), parse_error::create(112, chars_read, - exception_message(input_format, "ndarray requires both type and size", "size"), nullptr)); + exception_message("ndarray requires both type and size", "size"), nullptr)); } return is_error; } @@ -17624,7 +17723,7 @@ class binary_reader switch (prefix) { case char_traits::eof(): // EOF - return unexpect_eof(input_format, "value"); + return unexpect_eof("value"); case 'T': // true return sax->boolean(true); @@ -17641,37 +17740,37 @@ class binary_reader break; } std::uint8_t number{}; - return get_number(input_format, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 'U': { std::uint8_t number{}; - return get_number(input_format, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 'i': { std::int8_t number{}; - return get_number(input_format, number) && sax->number_integer(conditional_static_cast(number)); + return get_number(number) && emit_signed(number); } case 'I': { std::int16_t number{}; - return get_number(input_format, number) && sax->number_integer(conditional_static_cast(number)); + return get_number(number) && emit_signed(number); } case 'l': { std::int32_t number{}; - return get_number(input_format, number) && sax->number_integer(conditional_static_cast(number)); + return get_number(number) && emit_signed(number); } case 'L': { std::int64_t number{}; - return get_number(input_format, number) && sax->number_integer(conditional_static_cast(number)); + return get_number(number) && emit_signed(number); } case 'u': @@ -17681,7 +17780,7 @@ class binary_reader break; } std::uint16_t number{}; - return get_number(input_format, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 'm': @@ -17691,7 +17790,7 @@ class binary_reader break; } std::uint32_t number{}; - return get_number(input_format, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 'M': @@ -17701,7 +17800,7 @@ class binary_reader break; } std::uint64_t number{}; - return get_number(input_format, number) && sax->number_unsigned(number); + return get_number(number) && emit_unsigned(number); } case 'h': @@ -17710,19 +17809,19 @@ class binary_reader { break; } - return get_half_float(input_format, true); + return get_half_float(true); } case 'd': { float number{}; - return get_number(input_format, number) && sax->number_float(static_cast(number), ""); + return get_number(number) && emit_float(number); } case 'D': { double number{}; - return get_number(input_format, number) && sax->number_float(static_cast(number), ""); + return get_number(number) && emit_float(number); } case 'H': @@ -17733,7 +17832,7 @@ class binary_reader case 'C': // char { get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("char"))) { return false; } @@ -17741,7 +17840,7 @@ class binary_reader { auto last_token = get_token_string(); static_cast(report_error(chars_read, last_token, parse_error::create(113, chars_read, - exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr))); + exception_message(concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr))); if (!repair_requested()) { return false; @@ -17771,7 +17870,7 @@ class binary_reader break; } auto last_token = get_token_string(); - return report_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr)); + return report_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message("invalid byte: 0x" + last_token, "value"), nullptr)); } /*! @@ -17797,7 +17896,7 @@ class binary_reader { auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr)); + exception_message("invalid byte: 0x" + last_token, "type"), nullptr)); } string_t type = type_name; // sax->string() takes a reference @@ -17834,7 +17933,7 @@ class binary_reader if (input_format == input_format_t::bjdata && size_and_type.first != npos && size_and_type.second == 'B') { binary_t result; - return get_binary(input_format, size_and_type.first, result) && sax->binary(result); + return get_binary(size_and_type.first, result) && sax->binary(result); } if (size_and_type.first != npos) @@ -17847,7 +17946,7 @@ class binary_reader && size_and_type.first > max_valueless_container_size)) { return report_error(chars_read, get_token_string(), out_of_range::create(408, - exception_message(input_format, "excessive array size", "size"), nullptr)); + exception_message("excessive array size", "size"), nullptr)); } if (JSON_HEDLEY_UNLIKELY(!enter_array(size_and_type.first, size_and_type.second))) @@ -17884,7 +17983,7 @@ class binary_reader { auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr)); + exception_message("BJData object does not support ND-array size in optimized format", "object"), nullptr)); } if (size_and_type.first != npos) @@ -17914,7 +18013,7 @@ class binary_reader for (std::size_t i = 0; i < size; ++i) { get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("number"))) { return false; } @@ -17933,7 +18032,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) { static_cast(report_error(chars_read, number_string, parse_error::create(115, chars_read, - exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr))); + exception_message(concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr))); return recover_high_precision_number(number_vector); } @@ -17980,7 +18079,7 @@ class binary_reader case token_type::literal_or_value: default: static_cast(report_error(chars_read, number_string, parse_error::create(115, chars_read, - exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr))); + exception_message(concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr))); return recover_high_precision_number(number_vector); } } @@ -18112,7 +18211,7 @@ class binary_reader { auto last_token = get_token_string(); return report_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::bon8, concat(detail, ": 0x", last_token), context), nullptr)); + exception_message(concat(detail, ": 0x", last_token), context), nullptr)); } /*! @@ -18224,7 +18323,7 @@ class binary_reader if (byte == char_traits::eof()) { - return unexpect_eof(input_format_t::bon8, "value"); + return unexpect_eof("value"); } // string: ASCII character @@ -18261,25 +18360,25 @@ class binary_reader case 0x8C: // int32 { std::int32_t number{}; - return get_number(input_format_t::bon8, number) && emit_bon8_integer(number); + return get_number(number) && emit_bon8_integer(number); } case 0x8D: // int64 { std::int64_t number{}; - return get_number(input_format_t::bon8, number) && emit_bon8_integer(number); + return get_number(number) && emit_bon8_integer(number); } case 0x8E: // binary32 { float number{}; - return get_number(input_format_t::bon8, number) && sax->number_float(static_cast(number), ""); + return get_number(number) && emit_float(number); } case 0x8F: // binary64 { double number{}; - return get_number(input_format_t::bon8, number) && sax->number_float(static_cast(number), ""); + return get_number(number) && emit_float(number); } case 0xF8: @@ -18345,7 +18444,9 @@ class binary_reader @brief pass an integer to the SAX parser Non-negative integers are passed as unsigned, negative integers as signed - numbers, like the other binary formats do. + numbers, like the other binary formats do. A value that does not fit the + number type is passed as described for @ref emit_unsigned and + @ref emit_signed. @param[in] number the integer @return whether the SAX parser accepted the value @@ -18354,9 +18455,9 @@ class binary_reader { if (number >= 0) { - return sax->number_unsigned(static_cast(number)); + return emit_unsigned(static_cast(number)); } - return sax->number_integer(static_cast(number)); + return emit_signed(number); } /*! @@ -18376,7 +18477,7 @@ class binary_reader */ bool get_bon8_integer(const char_int_type lead, const char_int_type second) { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bon8, "number"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("number"))) { return false; } @@ -18408,13 +18509,12 @@ class binary_reader { if (JSON_HEDLEY_UNLIKELY(get_bon8() == char_traits::eof())) { - return unexpect_eof(input_format_t::bon8, "number"); + return unexpect_eof("number"); } value = (value << 8) | static_cast(current); } - return negative ? sax->number_integer(static_cast(-(value + offset))) - : sax->number_unsigned(static_cast(value + offset)); + return emit_bon8_integer(negative ? -(value + offset) : value + offset); } /*! @@ -18432,7 +18532,7 @@ class binary_reader if (byte == char_traits::eof()) { - return unexpect_eof(input_format_t::bon8, "key"); + return unexpect_eof("key"); } if (byte == 0xFF) @@ -18452,7 +18552,7 @@ class binary_reader if (second == char_traits::eof()) { // the input ends inside a character or an integer - return unexpect_eof(input_format_t::bon8, "key"); + return unexpect_eof("key"); } unget_bon8(second); if (is_bon8_continuation(second)) @@ -18488,7 +18588,7 @@ class binary_reader if (byte == char_traits::eof()) { - return unexpect_eof(input_format_t::bon8, "value"); + return unexpect_eof("value"); } if (byte == 0xFE && end_allowed) @@ -18555,7 +18655,7 @@ class binary_reader unget_bon8(byte); return get_bon8_string(ignored); } - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bon8, "number"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("number"))) { return false; } @@ -18576,7 +18676,7 @@ class binary_reader { if (JSON_HEDLEY_UNLIKELY(get_bon8() == char_traits::eof())) { - return unexpect_eof(input_format_t::bon8, "number"); + return unexpect_eof("number"); } } return true; @@ -18640,7 +18740,7 @@ class binary_reader if (byte == char_traits::eof()) { - return unexpect_eof(input_format_t::bon8, "string"); + return unexpect_eof("string"); } // end of string @@ -18671,7 +18771,7 @@ class binary_reader { // the input ends inside a character or an integer: either // way, the message is incomplete - return unexpect_eof(input_format_t::bon8, "string"); + return unexpect_eof("string"); } if (!is_bon8_continuation(second)) { @@ -18712,7 +18812,7 @@ class binary_reader { if (JSON_HEDLEY_UNLIKELY(get_bon8() == char_traits::eof())) { - return unexpect_eof(input_format_t::bon8, "string"); + return unexpect_eof("string"); } if (JSON_HEDLEY_UNLIKELY(!is_bon8_continuation(current))) { @@ -18751,7 +18851,7 @@ class binary_reader @return bool, whether the read was successful */ template - bool get_to(T& dest, const input_format_t format, const char* context) + bool get_to(T& dest, const char* context) { // false positive: new_chars_read is read on the next lines // @infer-ignore DEAD_STORE @@ -18761,7 +18861,7 @@ class binary_reader { // in case of failure, advance position by 1 to report the failing location ++chars_read; - return report_error(chars_read, "", parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr)); + return report_error(chars_read, "", parse_error::create(110, chars_read, exception_message("unexpected end of input", context), nullptr)); } return true; } @@ -18811,7 +18911,6 @@ class binary_reader @brief read a number from the input @tparam NumberType the type of the number - @param[in] format the current format (for diagnostics) @param[out] result number of type @a NumberType @return whether conversion completed @@ -18823,42 +18922,124 @@ class binary_reader should reorder on big endian systems. */ template - bool get_number(const input_format_t format, NumberType& result) + bool get_number(NumberType& result) { // read in the original format - if (JSON_HEDLEY_UNLIKELY(!get_to(result, format, "number"))) + if (JSON_HEDLEY_UNLIKELY(!get_to(result, "number"))) { return false; } - if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata)) + if (is_little_endian != (InputIsLittleEndian || input_format == input_format_t::bjdata)) { byte_swap(result); } return true; } + /*! + @brief pass a signed integer read from the input to the SAX parser + + Like the lexer does for JSON text, a value that does not fit into + number_integer_t is passed as number_unsigned_t if it is non-negative and + fits there, and as number_float_t otherwise. With the default number + types, every integer the binary formats can encode fits, so this only + matters for narrower custom number types. + + @tparam NumberType a signed integer type + @param[in] number the integer + @return whether the SAX parser accepted the value + + @throw out_of_range.406 if @a number overflows number_float_t (see + @ref emit_float) + */ + template + bool emit_signed(const NumberType number) + { + if (JSON_HEDLEY_LIKELY(value_in_range_of(number))) + { + return sax->number_integer(static_cast(number)); + } + if (value_in_range_of(number)) + { + return sax->number_unsigned(static_cast(number)); + } + return emit_float(number); + } + + /*! + @brief pass an unsigned integer read from the input to the SAX parser + + Like the lexer does for JSON text, a value that does not fit into + number_unsigned_t is passed as number_float_t. + + @tparam NumberType an unsigned integer type + @param[in] number the integer + @return whether the SAX parser accepted the value + + @throw out_of_range.406 if @a number overflows number_float_t (see + @ref emit_float) + */ + template + bool emit_unsigned(const NumberType number) + { + if (JSON_HEDLEY_LIKELY(value_in_range_of(number))) + { + return sax->number_unsigned(static_cast(number)); + } + return emit_float(number); + } + + /*! + @brief pass a floating-point number read from the input to the SAX parser + + Like the lexer does for JSON text, a finite value that overflows + number_float_t is rejected instead of silently becoming infinity. Infinity + and NaN in the input are passed on unchanged. Integers only overflow if + number_float_t cannot represent 2^64, e.g., a half-precision type. + + @tparam NumberType a floating-point or integer type + @param[in] number the number + @return whether the SAX parser accepted the value + + @throw out_of_range.406 if a finite @a number overflows number_float_t + */ + template + bool emit_float(const NumberType number) + { + const auto result = static_cast(number); + if (JSON_HEDLEY_UNLIKELY(std::isfinite(number) && !std::isfinite(result))) + { + static_cast(report_error(chars_read, get_token_string(), + out_of_range::create(406, exception_message("number overflow", "value"), nullptr))); + // when recovering, the number becomes infinity, as in JSON text + if (!repair_requested()) + { + return false; + } + } + return sax->number_float(result, ""); + } + /*! @brief read and decode an IEEE 754 half-precision (16-bit) float Used by CBOR (big endian) and BJData (little endian); the two formats only differ in the byte order of the two bytes that make up the half. - - @param[in] format the current format (for diagnostics) @param[in] little_endian whether the two bytes are little endian (BJData) or big endian (CBOR) @return whether reading and decoding succeeded */ - bool get_half_float(const input_format_t format, const bool little_endian) + bool get_half_float(const bool little_endian) { const auto byte1_raw = get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("number"))) { return false; } const auto byte2_raw = get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("number"))) { return false; } @@ -18904,7 +19085,6 @@ class binary_reader @brief create a string by reading characters from the input @tparam NumberType the type of the number - @param[in] format the current format (for diagnostics) @param[in] len number of characters to read @param[out] result string created by reading @a len bytes @@ -18915,8 +19095,7 @@ class binary_reader the input before we run out of string memory. */ template - bool get_string(const input_format_t format, - const NumberType len, + bool get_string(const NumberType len, string_t& result) { // Strings are taken as is by default: none of CBOR (RFC 8949 §3.1 @@ -18928,7 +19107,7 @@ class binary_reader // @ref error_handler, applied once the whole string (all chunks of // an indefinite-length CBOR string included) has been assembled, by // @ref check_string_utf8 at the call site. - return get_bytes(format, len, "string", result); + return get_bytes(len, "string", result); } /*! @@ -18959,7 +19138,7 @@ class binary_reader { auto last_token = get_token_string(); static_cast(report_error(chars_read, last_token, parse_error::create(113, chars_read, - exception_message(input_format, "invalid string: ill-formed UTF-8 byte", context), nullptr))); + exception_message("invalid string: ill-formed UTF-8 byte", context), nullptr))); // when recovering, the string is repaired as with // error_handler_t::replace if (!repair_requested()) @@ -18978,7 +19157,6 @@ class binary_reader @brief create a byte array by reading bytes from the input @tparam NumberType the type of the number - @param[in] format the current format (for diagnostics) @param[in] len number of bytes to read @param[out] result byte array created by reading @a len bytes @@ -18989,11 +19167,10 @@ class binary_reader the input before we run out of memory. */ template - bool get_binary(const input_format_t format, - const NumberType len, + bool get_binary(const NumberType len, binary_t& result) { - return get_bytes(format, len, "binary", result); + return get_bytes(len, "binary", result); } /*! @@ -19001,7 +19178,6 @@ class binary_reader @tparam NumberType the type of the length @tparam ContainerType the destination container (string_t or binary_t) - @param[in] format the current format (for diagnostics) @param[in] len number of bytes to read @param[in] context further context information (for diagnostics) @param[out] result container the bytes are appended to @@ -19016,8 +19192,7 @@ class binary_reader detects a premature end of input. */ template - bool get_bytes(const input_format_t format, - NumberType len, + bool get_bytes(NumberType len, const char* context, ContainerType& result) { @@ -19048,7 +19223,7 @@ class binary_reader result.resize(old_size + bytes_read); ++chars_read; current = char_traits::eof(); - return unexpect_eof(format, context); + return unexpect_eof(context); } // a full chunk was read; get_elements() never returns more than requested JSON_ASSERT(bytes_read == wanted); @@ -19336,7 +19511,7 @@ class binary_reader for (; len != 0; --len) { get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, context))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(context))) { return false; } @@ -19345,17 +19520,16 @@ class binary_reader } /*! - @param[in] format the current format (for diagnostics) @param[in] context further context information (for diagnostics) @return whether the last read character is not EOF */ - JSON_HEDLEY_NON_NULL(3) - bool unexpect_eof(const input_format_t format, const char* context) + JSON_HEDLEY_NON_NULL(2) + bool unexpect_eof(const char* context) { if (JSON_HEDLEY_UNLIKELY(current == char_traits::eof())) { return report_error(chars_read, "", - parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr)); + parse_error::create(110, chars_read, exception_message("unexpected end of input", context), nullptr)); } return true; } @@ -19371,18 +19545,16 @@ class binary_reader } /*! - @param[in] format the current format @param[in] detail a detailed error message @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, - const std::string& detail, + std::string exception_message(const std::string& detail, const std::string& context) const { std::string error_msg = "syntax error while parsing "; - switch (format) + switch (input_format) { case input_format_t::cbor: error_msg += "CBOR"; @@ -36395,6 +36567,7 @@ struct formatter // NOLINT(cert-dcl58-c #undef JSON_PRECISE_STREAM_POSITION #undef JSON_STRICT_NUL_HANDLING #undef JSON_STRICT_BINARY_UTF8 + #undef JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS #endif // #include diff --git a/single_include/nlohmann/json_fwd.hpp b/single_include/nlohmann/json_fwd.hpp index 7cadc9b1c..7b8aa5bfd 100644 --- a/single_include/nlohmann/json_fwd.hpp +++ b/single_include/nlohmann/json_fwd.hpp @@ -67,6 +67,10 @@ #define JSON_STRICT_BINARY_UTF8 0 #endif +#ifndef JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS + #define JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS 0 +#endif + #if JSON_DIAGNOSTICS #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag #else @@ -109,14 +113,20 @@ #define NLOHMANN_JSON_ABI_TAG_STRICT_BINARY_UTF8 #endif +#if JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS + #define NLOHMANN_JSON_ABI_TAG_OBJECTS_FOR_ENUM_KEYED_MAPS _ekmo +#else + #define NLOHMANN_JSON_ABI_TAG_OBJECTS_FOR_ENUM_KEYED_MAPS +#endif + #ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 #endif // Construct the namespace ABI tags component -#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c, d, e, f, g) json_abi ## a ## b ## c ## d ## e ## f ## g -#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c, d, e, f, g) \ - NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c, d, e, f, g) +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c, d, e, f, g, h) json_abi ## a ## b ## c ## d ## e ## f ## g ## h +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c, d, e, f, g, h) \ + NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c, d, e, f, g, h) #define NLOHMANN_JSON_ABI_TAGS \ NLOHMANN_JSON_ABI_TAGS_CONCAT( \ @@ -126,7 +136,8 @@ NLOHMANN_JSON_ABI_TAG_BRACE_INIT_COPY_SEMANTICS, \ NLOHMANN_JSON_ABI_TAG_PRECISE_STREAM_POSITION, \ NLOHMANN_JSON_ABI_TAG_STRICT_NUL_HANDLING, \ - NLOHMANN_JSON_ABI_TAG_STRICT_BINARY_UTF8) + NLOHMANN_JSON_ABI_TAG_STRICT_BINARY_UTF8, \ + NLOHMANN_JSON_ABI_TAG_OBJECTS_FOR_ENUM_KEYED_MAPS) // Construct the namespace version component #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ diff --git a/tests/abi/config/default.cpp b/tests/abi/config/default.cpp index e4c627060..d42e883f0 100644 --- a/tests/abi/config/default.cpp +++ b/tests/abi/config/default.cpp @@ -48,6 +48,10 @@ TEST_CASE("default namespace") expected += "_sbu8"; #endif +#if JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS + expected += "_ekmo"; +#endif + expected += "_v" STRINGIZE(NLOHMANN_JSON_VERSION_MAJOR); expected += "_" STRINGIZE(NLOHMANN_JSON_VERSION_MINOR); expected += "_" STRINGIZE(NLOHMANN_JSON_VERSION_PATCH) "::basic_json"; diff --git a/tests/abi/config/noversion.cpp b/tests/abi/config/noversion.cpp index 858964695..ec406c716 100644 --- a/tests/abi/config/noversion.cpp +++ b/tests/abi/config/noversion.cpp @@ -49,6 +49,10 @@ TEST_CASE("default namespace without version component") expected += "_sbu8"; #endif +#if JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS + expected += "_ekmo"; +#endif + expected += "::basic_json"; // fallback for Clang diff --git a/tests/src/unit-binary_formats.cpp b/tests/src/unit-binary_formats.cpp index ed6d89911..846a092fb 100644 --- a/tests/src/unit-binary_formats.cpp +++ b/tests/src/unit-binary_formats.cpp @@ -11,7 +11,12 @@ #include using nlohmann::json; +#include #include +#include +#include +#include +#include #include "make_test_data_available.hpp" TEST_CASE("Binary Formats" * doctest::skip()) @@ -224,3 +229,139 @@ TEST_CASE("Binary Formats" * doctest::skip()) CHECK((100.0 * double(ubjson_3_size) / double(json_size)) == Approx(89.450)); } } + +namespace +{ +// the binary formats as function pointers for "Binary formats with narrow number types"; +// named functions rather than lambdas, because clang 3.5 cannot convert a lambda +// to a function pointer in the braced initializer of the format table +using narrow_json = nlohmann::basic_json; +using bytes = std::vector; + +bytes encode_cbor(const json& j) +{ + return json::to_cbor(j); +} +narrow_json decode_cbor(const bytes& v, bool allow_exceptions) +{ + return narrow_json::from_cbor(v, true, allow_exceptions); +} + +bytes encode_msgpack(const json& j) +{ + return json::to_msgpack(j); +} +narrow_json decode_msgpack(const bytes& v, bool allow_exceptions) +{ + return narrow_json::from_msgpack(v, true, allow_exceptions); +} + +bytes encode_ubjson(const json& j) +{ + return json::to_ubjson(j); +} +narrow_json decode_ubjson(const bytes& v, bool allow_exceptions) +{ + return narrow_json::from_ubjson(v, true, allow_exceptions); +} + +bytes encode_bjdata(const json& j) +{ + return json::to_bjdata(j); +} +narrow_json decode_bjdata(const bytes& v, bool allow_exceptions) +{ + return narrow_json::from_bjdata(v, true, allow_exceptions); +} + +// BSON can only store numbers as object members +bytes encode_bson(const json& j) +{ + return json::to_bson(json{{"a", j}}); +} +narrow_json decode_bson(const bytes& v, bool allow_exceptions) +{ + const auto result = narrow_json::from_bson(v, true, allow_exceptions); + return result.is_discarded() ? result : result.at("a"); +} + +bytes encode_bon8(const json& j) +{ + return json::to_bon8(j); +} +narrow_json decode_bon8(const bytes& v, bool allow_exceptions) +{ + return narrow_json::from_bon8(v, true, allow_exceptions); +} + +} // namespace + +TEST_CASE("Binary formats with narrow number types") +{ + // Numbers that do not fit the number types are handled like the lexer + // handles them in JSON text: an integer that fits neither integer type is + // stored as a floating-point number, and a finite floating-point number + // that overflows number_float_t is rejected with out_of_range.406. + struct binary_format + { + const char* name; + bytes (*encode)(const json&); + narrow_json (*decode)(const bytes&, bool); + }; + + const std::vector formats = + { + {"CBOR", encode_cbor, decode_cbor}, + {"MessagePack", encode_msgpack, decode_msgpack}, + {"UBJSON", encode_ubjson, decode_ubjson}, + {"BJData", encode_bjdata, decode_bjdata}, + {"BSON", encode_bson, decode_bson}, + {"BON8", encode_bon8, decode_bon8}, + }; + + for (const auto& format : formats) + { + const std::string name = format.name; + INFO("format := ", name); + const auto roundtrip = [&format](const json & j) + { + return format.decode(format.encode(j), true); + }; + + // integers that fit keep their type + CHECK(roundtrip(json(-5)).is_number_integer()); + CHECK(roundtrip(json(-5)).get() == -5); + CHECK(roundtrip(json(3000000000u)).is_number_unsigned()); + CHECK(roundtrip(json(3000000000u)).get() == 3000000000u); + + // integers that fit neither integer type are stored as float + CHECK(roundtrip(json(5000000000u)).is_number_float()); + CHECK(roundtrip(json(5000000000u)).get() == 5000000000.0f); + if (name != "BON8") // BON8 cannot encode integers above INT64_MAX + { + CHECK(roundtrip(json(10000000000000000000u)).is_number_float()); + CHECK(roundtrip(json(10000000000000000000u)).get() == 10000000000000000000.0f); + } + CHECK(roundtrip(json(-3000000000LL)).is_number_float()); + CHECK(roundtrip(json(-3000000000LL)).get() == -3000000000.0f); + CHECK(roundtrip(json(-5000000000LL)).is_number_float()); + CHECK(roundtrip(json(-5000000000LL)).get() == -5000000000.0f); + + // floating-point numbers that fit + CHECK(roundtrip(json(1.5)).get() == 1.5f); + const auto just_above_max = std::nextafter(static_cast((std::numeric_limits::max)()), + std::numeric_limits::infinity()); + CHECK(roundtrip(json(just_above_max)).get() == (std::numeric_limits::max)()); + + // infinity and NaN are passed on + CHECK(std::isinf(roundtrip(json(std::numeric_limits::infinity())).get())); + CHECK(std::isnan(roundtrip(json(std::numeric_limits::quiet_NaN())).get())); + + // finite floating-point numbers that overflow number_float_t are rejected + const std::string message = "[json.exception.out_of_range.406] syntax error while parsing " + name + + " value: number overflow"; + CHECK_THROWS_WITH_AS(roundtrip(json(1e300)), message.c_str(), narrow_json::out_of_range&); + CHECK_THROWS_WITH_AS(roundtrip(json(-1e300)), message.c_str(), narrow_json::out_of_range&); + CHECK(format.decode(format.encode(json(1e300)), false).is_discarded()); + } +} diff --git a/tests/src/unit-cbor.cpp b/tests/src/unit-cbor.cpp index f3f4301e5..546e256b1 100644 --- a/tests/src/unit-cbor.cpp +++ b/tests/src/unit-cbor.cpp @@ -3185,7 +3185,8 @@ TEST_CASE("Tagged values") // CBOR encodes negative integers as: result = -1 - n // For type 0x3B, n is an 8-byte uint64_t. Valid range for n with // the default int64_t is [0, INT64_MAX], producing results in [INT64_MIN, -1]. - // When n > INT64_MAX, the result exceeds int64_t range and is rejected. + // When n > INT64_MAX, the result exceeds int64_t range and is stored + // as a floating-point number, as the lexer does for JSON text. SECTION("n = 0 is valid (result = -1)") { @@ -3206,33 +3207,34 @@ TEST_CASE("Tagged values") CHECK(result.get() == (std::numeric_limits::min)()); } - SECTION("n = INT64_MAX + 1 is rejected (overflow)") + SECTION("n = INT64_MAX + 1 is stored as float") { // n = INT64_MAX + 1 (0x8000000000000000) - // result = -1 - n = -9223372036854775809, which exceeds int64_t range + // result = -1 - n = -9223372036854775809, which exceeds int64_t range; + // the nearest double is -9223372036854775808.0 const std::vector input = {0x3B, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - json _; - CHECK_THROWS_WITH_AS(_ = json::from_cbor(input), - "[json.exception.parse_error.112] parse error at byte 9: syntax error while parsing CBOR value: negative integer overflow", - json::parse_error); + const auto result = json::from_cbor(input); + CHECK(result.is_number_float()); + CHECK(result.get() == -9223372036854775808.0); + CHECK(result == json::parse("-9223372036854775809")); } - SECTION("n = UINT64_MAX is rejected (overflow)") + SECTION("n = UINT64_MAX is stored as float") { // n = UINT64_MAX (0xFFFFFFFFFFFFFFFF) // result = -1 - n = -18446744073709551616, which exceeds int64_t range const std::vector input = {0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - json _; - CHECK_THROWS_WITH_AS(_ = json::from_cbor(input), - "[json.exception.parse_error.112] parse error at byte 9: syntax error while parsing CBOR value: negative integer overflow", - json::parse_error); + const auto result = json::from_cbor(input); + CHECK(result.is_number_float()); + CHECK(result.get() == -18446744073709551616.0); + CHECK(result == json::parse("-18446744073709551616")); } - SECTION("overflow with allow_exceptions=false returns discarded") + SECTION("overflow with allow_exceptions=false is not an error") { const std::vector input = {0x3B, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const auto result = json::from_cbor(input, true, false); - CHECK(result.is_discarded()); + CHECK(result.is_number_float()); } } diff --git a/tests/src/unit-enum_keyed_maps.cpp b/tests/src/unit-enum_keyed_maps.cpp new file mode 100644 index 000000000..a6ced6711 --- /dev/null +++ b/tests/src/unit-enum_keyed_maps.cpp @@ -0,0 +1,246 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ (supporting code) +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + +#include "doctest_compatibility.h" + +// skip tests if JSON_DisableEnumSerialization=ON (#4384) +#if defined(JSON_DISABLE_ENUM_SERIALIZATION) && (JSON_DISABLE_ENUM_SERIALIZATION == 1) + #define SKIP_TESTS_FOR_ENUM_SERIALIZATION +#endif + +// This file tests the opt-in JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS, so it defines +// the macro itself rather than relying on a -D flag, and runs in every build. +// The default behavior is tested in unit-enum_keyed_maps_default.cpp. +#ifdef JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS + #undef JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS +#endif + +#define JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS 1 + +#include +using nlohmann::json; +using nlohmann::ordered_json; + +#include +#include +#include +#include +#include +#include +#include + +#define STRINGIZE_EX(x) #x +#define STRINGIZE(x) STRINGIZE_EX(x) + +// NLOHMANN_JSON_SERIALIZE_ENUM uses a static std::pair +DOCTEST_CLANG_SUPPRESS_WARNING_PUSH +DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors") + +namespace +{ +// std::hash is only required for enums since C++14 +struct enum_hash +{ + template + std::size_t operator()(T t) const noexcept + { + return static_cast(t); + } +}; +} // namespace + +// the example from #4378 +enum TaskState // NOLINT(cert-int09-c,readability-enum-initial-value,cppcoreguidelines-use-enum-class) +{ + TS_STOPPED, + TS_RUNNING, + TS_COMPLETED, + TS_INVALID = -1, +}; + +// NOLINTNEXTLINE(misc-const-correctness,misc-use-internal-linkage,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - false positive +NLOHMANN_JSON_SERIALIZE_ENUM(TaskState, +{ + {TS_INVALID, nullptr}, + {TS_STOPPED, "stopped"}, + {TS_RUNNING, "running"}, + {TS_COMPLETED, "completed"}, +}) + +enum class color {red, green, blue}; // blue is not mapped and falls back to "red" + +// NOLINTNEXTLINE(misc-const-correctness,misc-use-internal-linkage,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - false positive +NLOHMANN_JSON_SERIALIZE_ENUM(color, +{ + {color::red, "red"}, + {color::green, "green"}, +}) + +enum class strict_color {red, green, blue}; // blue is not mapped + +// NOLINTNEXTLINE(misc-const-correctness,misc-use-internal-linkage,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - false positive +NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(strict_color, +{ + {strict_color::red, "red"}, + {strict_color::green, "green"}, +}) + +enum class digit {zero, one}; + +// NOLINTNEXTLINE(misc-const-correctness,misc-use-internal-linkage,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - false positive +NLOHMANN_JSON_SERIALIZE_ENUM(digit, +{ + {digit::zero, 0}, + {digit::one, 1}, +}) + +#ifndef SKIP_TESTS_FOR_ENUM_SERIALIZATION +enum class plain {zero, one}; // serialized as integer +#endif + +TEST_CASE("JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS") +{ + SECTION("the macro is part of the ABI tag") + { + const std::string ns = STRINGIZE(NLOHMANN_JSON_NAMESPACE); + CHECK(ns.find("_ekmo") != std::string::npos); + } + + SECTION("std::map (#4378)") + { + using task_map = std::map; + const task_map m = {{TS_STOPPED, "aa"}, {TS_COMPLETED, "bb"}}; + const json j = m; + CHECK(j == json::parse(R"({"stopped":"aa","completed":"bb"})")); + CHECK(j.get() == m); + + json j2; + j2["x"] = m; + CHECK(j2.dump() == R"({"x":{"completed":"bb","stopped":"aa"}})"); + } + + SECTION("std::map with custom comparator") + { + using task_map = std::map>; + const task_map m = {{TS_STOPPED, 1}, {TS_RUNNING, 2}}; + const json j = m; + CHECK(j == json::parse(R"({"stopped":1,"running":2})")); + CHECK(j.get() == m); + } + + SECTION("std::unordered_map") + { + using task_map = std::unordered_map; + const task_map m = {{TS_STOPPED, 1}, {TS_RUNNING, 2}}; + const json j = m; + CHECK(j == json::parse(R"({"stopped":1,"running":2})")); + CHECK(j.get() == m); + } + + SECTION("nested maps") + { + using nested_map = std::map>; + const nested_map m = {{color::green, {{TS_RUNNING, 1}}}, {color::red, {}}}; + const json j = m; + CHECK(j == json::parse(R"({"green":{"running":1},"red":{}})")); + CHECK(j.get() == m); + } + + SECTION("ordered_json keeps the order of the map") + { + using task_map = std::map; + const task_map m = {{TS_STOPPED, 1}, {TS_RUNNING, 2}, {TS_COMPLETED, 3}}; + const ordered_json j = m; + CHECK(j.dump() == R"({"stopped":1,"running":2,"completed":3})"); + CHECK(j.get() == m); + } + + SECTION("empty map") + { + const json j = std::map(); + CHECK(j.is_object()); + CHECK(j.empty()); + } + + SECTION("NLOHMANN_JSON_SERIALIZE_ENUM_STRICT") + { + using color_map = std::map; + const color_map m = {{strict_color::red, 1}, {strict_color::green, 2}}; + const json j = m; + CHECK(j == json::parse(R"({"red":1,"green":2})")); + CHECK(j.get() == m); + + const color_map unmapped = {{strict_color::blue, 1}}; + json _; + CHECK_THROWS_WITH_AS(_ = unmapped, + "[json.exception.out_of_range.410] enum value out of range for strict_color", json::out_of_range&); + } + + SECTION("arrays of [key, value] pairs are still read") + { + using task_map = std::map; + const task_map m = {{TS_STOPPED, 1}}; + CHECK(json::parse(R"([["stopped",1]])").get() == m); + } + + SECTION("other containers are not affected") + { + const std::vector> pairs = {{TS_STOPPED, 1}}; + const std::map string_keys = {{"a", TS_STOPPED}}; + const std::map int_keys = {{1, 2}}; + CHECK(json(pairs) == json::parse(R"([["stopped",1]])")); + CHECK(json(string_keys) == json::parse(R"({"a":"stopped"})")); + CHECK(json(int_keys) == json::parse("[[1,2]]")); + } + + SECTION("maps with non-unique keys are still stored as arrays of pairs") + { + const std::multimap mm = {{TS_STOPPED, 1}, {TS_STOPPED, 2}}; + const std::unordered_multimap umm = {{TS_RUNNING, 3}, {TS_RUNNING, 3}}; + CHECK(json(mm) == json::parse(R"([["stopped",1],["stopped",2]])")); + CHECK(json(umm) == json::parse(R"([["running",3],["running",3]])")); + } + + SECTION("keys that do not serialize to strings") + { + const std::map null_key = {{TS_INVALID, 1}}; + const std::map number_key = {{digit::zero, 1}}; + json j = "unchanged"; + + // mapped to null + CHECK_THROWS_WITH_AS(j = null_key, + "[json.exception.type_error.302] type must be string, but is null", json::type_error&); + + // mapped to a number + CHECK_THROWS_WITH_AS(j = number_key, + "[json.exception.type_error.302] type must be string, but is number", json::type_error&); + +#ifndef SKIP_TESTS_FOR_ENUM_SERIALIZATION + // enum without NLOHMANN_JSON_SERIALIZE_ENUM + const std::map plain_key = {{plain::zero, 1}}; + CHECK_THROWS_WITH_AS(j = plain_key, + "[json.exception.type_error.302] type must be string, but is number", json::type_error&); +#endif + + CHECK(j == "unchanged"); + } + + SECTION("keys that serialize to the same string") + { + const std::map m = {{color::red, 1}, {color::blue, 2}}; + json j = "unchanged"; + + // color::blue is not mapped and falls back to "red" + CHECK_THROWS_WITH_AS(j = m, + "[json.exception.type_error.318] duplicate object key 'red'", json::type_error&); + + CHECK(j == "unchanged"); + } +} + +DOCTEST_CLANG_SUPPRESS_WARNING_POP diff --git a/tests/src/unit-enum_keyed_maps_default.cpp b/tests/src/unit-enum_keyed_maps_default.cpp new file mode 100644 index 000000000..5638b37e1 --- /dev/null +++ b/tests/src/unit-enum_keyed_maps_default.cpp @@ -0,0 +1,144 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ (supporting code) +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + +#include "doctest_compatibility.h" + +// This file tests maps with enum keys with the default setting of +// JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS (or whatever a -D flag sets it to). +// unit-enum_keyed_maps.cpp tests JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS=1. +// These tests are not part of unit-conversions.cpp, because that object file +// is already too big for the MinGW linker of some compilers. + +#include +using nlohmann::json; + +#include +#include +#include +#include +#include + +// NLOHMANN_JSON_SERIALIZE_ENUM uses a static std::pair +DOCTEST_CLANG_SUPPRESS_WARNING_PUSH +DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors") + +enum class cards {kreuz, pik, herz, karo}; + +// NOLINTNEXTLINE(misc-use-internal-linkage,misc-const-correctness,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - false positive +NLOHMANN_JSON_SERIALIZE_ENUM(cards, +{ + {cards::kreuz, "kreuz"}, + {cards::pik, "pik"}, + {cards::herz, "herz"}, + {cards::karo, "karo"} +}) + +enum TaskState // NOLINT(cert-int09-c,readability-enum-initial-value,cppcoreguidelines-use-enum-class) +{ + TS_STOPPED, + TS_RUNNING, + TS_COMPLETED, + TS_INVALID = -1, +}; + +// NOLINTNEXTLINE(misc-const-correctness,misc-use-internal-linkage,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - false positive +NLOHMANN_JSON_SERIALIZE_ENUM(TaskState, +{ + {TS_INVALID, nullptr}, + {TS_STOPPED, "stopped"}, + {TS_RUNNING, "running"}, + {TS_COMPLETED, "completed"}, +}) + +enum class strict_cards {kreuz, pik, herz, karo, andere}; // andere not included in mapping + +// NOLINTNEXTLINE(misc-use-internal-linkage,misc-const-correctness,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - false positive +NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(strict_cards, +{ + {strict_cards::kreuz, "kreuz"}, + {strict_cards::pik, "pik"}, + {strict_cards::herz, "herz"}, + {strict_cards::karo, "karo"} +}) + +namespace +{ +// std::hash is only required for enums since C++14 +struct enum_hash +{ + template + std::size_t operator()(T t) const noexcept + { + return static_cast(t); + } +}; +} // namespace + +// see unit-enum_keyed_maps.cpp for JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS=1 +TEST_CASE("maps with enum keys") +{ + using task_map = std::map; + using task_umap = std::unordered_map; + using task_gmap = std::map>; + using nested_map = std::map>; + using strict_map = std::map; + using int_map = std::map; + using int_umap = std::unordered_map; + + const task_map m = {{TS_STOPPED, "aa"}, {TS_COMPLETED, "bb"}}; + +#if !JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS + SECTION("stored as array of pairs") + { + CHECK(json(m) == json::parse(R"([["stopped","aa"],["completed","bb"]])")); + CHECK(json(task_umap {{TS_RUNNING, "cc"}}) == json::parse(R"([["running","cc"]])")); + } +#endif + + SECTION("read from array of pairs") + { + CHECK(json::parse(R"([["stopped","aa"],["completed","bb"]])").get() == m); + } + + SECTION("read from object (#4378)") + { + const json j = json::parse(R"({"stopped":"aa","completed":"bb"})"); + CHECK(j.get() == m); + CHECK(j.get() == task_umap(m.begin(), m.end())); + CHECK(j.get() == task_gmap(m.begin(), m.end())); + CHECK(json::parse(R"({"kreuz":{"stopped":1}})").get() == nested_map {{cards::kreuz, {{TS_STOPPED, 1}}}}); + CHECK(nlohmann::ordered_json::parse(R"({"stopped":"aa","completed":"bb"})").get() == m); + + // object keys go through the enum's from_json + strict_map sm; + CHECK_THROWS_WITH_AS(json::parse(R"({"what?":1})").get_to(sm), + "[json.exception.out_of_range.410] enum value out of range for strict_cards: \"what?\"", json::out_of_range&); + } + + SECTION("objects are only read for enum keys") + { + // built rather than parsed, so that the messages do not gain a byte + // range with JSON_DIAGNOSTIC_POSITIONS + const json j = {{"1", 2}}; + int_map im; + int_umap ium; + CHECK_THROWS_WITH_AS(j.get_to(im), + "[json.exception.type_error.302] type must be array, but is object", json::type_error&); + CHECK_THROWS_WITH_AS(j.get_to(ium), + "[json.exception.type_error.302] type must be array, but is object", json::type_error&); + } + + SECTION("other types are rejected") + { + task_map tm; + CHECK_THROWS_WITH_AS(json("stopped").get_to(tm), + "[json.exception.type_error.302] type must be array, but is string", json::type_error&); + } +} + +DOCTEST_CLANG_SUPPRESS_WARNING_POP diff --git a/tests/src/unit-regression2.cpp b/tests/src/unit-regression2.cpp index 954331cbc..07236d342 100644 --- a/tests/src/unit-regression2.cpp +++ b/tests/src/unit-regression2.cpp @@ -944,10 +944,11 @@ namespace { /// builds a value from SAX events, asks the parser to recover from its first /// 100 errors, and checks that the events are balanced (see #3989) -class RecoveringParser +template +class BasicRecoveringParser { public: - explicit RecoveringParser(json& j) + explicit BasicRecoveringParser(BasicJsonType& j) : dom(j, false) {} @@ -963,19 +964,19 @@ class RecoveringParser return dom.boolean(val); } - bool number_integer(json::number_integer_t val) + bool number_integer(typename BasicJsonType::number_integer_t val) { value(); return dom.number_integer(val); } - bool number_unsigned(json::number_unsigned_t val) + bool number_unsigned(typename BasicJsonType::number_unsigned_t val) { value(); return dom.number_unsigned(val); } - bool number_float(json::number_float_t val, const std::string& s) + bool number_float(typename BasicJsonType::number_float_t val, const std::string& s) { value(); return dom.number_float(val, s); @@ -987,7 +988,7 @@ class RecoveringParser return dom.string(val); } - bool binary(json::binary_t& val) + bool binary(typename BasicJsonType::binary_t& val) { value(); return dom.binary(val); @@ -1055,7 +1056,7 @@ class RecoveringParser } /// builds the value - nlohmann::detail::json_sax_dom_parser dom; + nlohmann::detail::json_sax_dom_parser dom; std::size_t errors = 0; std::vector messages {}; // NOLINT(readability-redundant-member-init) std::vector stack {}; // NOLINT(readability-redundant-member-init) @@ -1079,6 +1080,8 @@ class RecoveringParser }; +using RecoveringParser = BasicRecoveringParser; + struct BinaryParseResult { json value; @@ -1395,11 +1398,17 @@ TEST_CASE("regression test - #3989 SAX parse_error() returning true") SECTION("binary formats repair numbers that are out of range") { - // CBOR: a negative integer below the range of number_integer_t - const auto cbor = parse_binary_recovering({0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, json::input_format_t::cbor); - CHECK(cbor.errors == 1); - CHECK(cbor.value.is_number_float()); - CHECK(cbor.value.get() == -18446744073709551616.0); + // CBOR: a double too large for a float number_float_t + using float_json = nlohmann::basic_json; + float_json cbor; + BasicRecoveringParser sax(cbor); + const std::vector cbor_input = {0x82, 0xFB, 0x7E, 0x37, 0xE4, 0x3C, 0x88, 0x00, 0x75, 0x9C, 0x01}; // [1e300, 1] + CHECK(!float_json::sax_parse(cbor_input, &sax, float_json::input_format_t::cbor)); + CHECK(sax.errors == 1); + CHECK(sax.messages.front() == "[json.exception.out_of_range.406] syntax error while parsing CBOR value: number overflow"); + REQUIRE(cbor.size() == 2); + CHECK(std::isinf(cbor[0].get())); + CHECK(cbor[1] == 1); // UBJSON: a high-precision number too large for number_float_t const auto ubjson = parse_binary_recovering({'H', 'i', 5, '1', 'e', '9', '9', '9'}, json::input_format_t::ubjson);