JsonBuilder - Fix parameter ambiguity for push_back and AddValue (#28)

All of the AddValue methods (AddValue, push_front, push_back) have two
overloads:

- `(..., T const& data)`
- `(..., JsonType type, unsigned cbData = 0, void const* pbData = NULL)`

For the second overload, the default values are convenient. They provide
a convenient syntax for adding the no-data values like null, array, and
object, e.g. `builder.push_back(parent, name, JsonNull)`.

However, these defaults are ambiguous and a bit dangerous:

- `builder.push_back(parent, name, something)` could be a call to the
  first overload or it could be a call to the second overload with
  defaulted `0, NULL` parameters.
- `builder.push_back(parent, name, type, 43)` compiles without warning
  and silently leaves the value uninitialized. The uninitialized case is
  useful but rare and should only happen with explicit NULL, not by default.

Fix is to remove the defaults:

- `(..., T const& data)`
- `(..., JsonType type, unsigned cbData, void const* pbData)`

However, this breaks the `builder.push_back(parent, name, JsonNull)`
syntax.

Restore that syntax by adding `JsonType` to the list of valid types
accepted by the first overload. Now there is no ambiguity between the
two overloads, and you can't call the cbData + pbData overload without
both size and pointer.

This intentionally breaks `builder.push_back(parent, name, type, size)`,
which must be fixed by `builder.push_back(parent, name, type, size, NULL)`
(assuming it wasn't a bug).
This commit is contained in:
Doug Cook 2024-02-01 11:55:20 -08:00 коммит произвёл GitHub
Родитель 450a68f1bb
Коммит 4f5fa7bfbf
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
2 изменённых файлов: 31 добавлений и 8 удалений

Просмотреть файл

@ -1283,8 +1283,8 @@ class JsonBuilder
const_iterator const& itParent,
NameStringView const& name,
JsonType type,
unsigned cbData = 0,
_In_reads_bytes_(cbData) void const* pbData = nullptr)
unsigned cbData,
_In_reads_bytes_opt_(cbData) void const* pbData)
noexcept(false) // may throw bad_alloc, length_error
{
std::basic_string_view<NameChar> nameView{ name };
@ -1310,8 +1310,8 @@ class JsonBuilder
const_iterator const& itParent,
NameStringView const& name,
JsonType type,
unsigned cbData = 0,
_In_reads_bytes_(cbData) void const* pbData = nullptr)
unsigned cbData,
_In_reads_bytes_opt_(cbData) void const* pbData)
noexcept(false) // may throw bad_alloc, length_error
{
std::basic_string_view<NameChar> nameView{ name };
@ -1337,8 +1337,8 @@ class JsonBuilder
const_iterator const& itParent,
NameStringView const& name,
JsonType type,
unsigned cbData = 0,
_In_reads_bytes_(cbData) void const* pbData = nullptr)
unsigned cbData,
_In_reads_bytes_opt_(cbData) void const* pbData)
noexcept(false) // may throw bad_alloc, length_error
{
std::basic_string_view<NameChar> nameView{ name };
@ -1357,6 +1357,7 @@ class JsonBuilder
Data must be a supported type. Supported types include:
- For null, array, object: JsonType (JsonNull, JsonArray, JsonObject).
- For boolean data: bool.
- For UTF-8 string data: std::string_view, char*.
- For integer data: signed and unsigned char, short, int, long, long long.
@ -1401,6 +1402,7 @@ class JsonBuilder
Data must be a supported type. Supported types include:
- For null, array, object: JsonType (JsonNull, JsonArray, JsonObject).
- For boolean data: bool.
- For UTF-8 string data: std::string_view, char*.
- For integer data: signed and unsigned char, short, int, long, long long.
@ -1444,6 +1446,7 @@ class JsonBuilder
Data must be a supported type. Supported types include:
- For null, array, object: JsonType (JsonNull, JsonArray, JsonObject).
- For boolean data: bool.
- For UTF-8 string data: std::string_view, char*.
- For integer data: signed and unsigned char, short, int, long, long long.
@ -1602,8 +1605,8 @@ private:
const_iterator const& itParent,
NameStringView nameView,
JsonType type,
unsigned cbData = 0,
_In_reads_bytes_(cbData) void const* pbData = nullptr)
unsigned cbData,
_In_reads_bytes_opt_(cbData) void const* pbData)
noexcept(false) // may throw bad_alloc, length_error
{
using char_type = typename JsonInternal::CharTypeOk<typename NameStringView::value_type>::char_type;
@ -2015,6 +2018,8 @@ JSON_DECLARE_JsonImplementType_AddValueSz(wchar_t);
JSON_DECLARE_JsonImplementType_AddValueSz(char16_t);
JSON_DECLARE_JsonImplementType_AddValueSz(char32_t);
JSON_DECLARE_JsonImplementType_AddValue(JsonType, ); // For null, array, object.
#ifdef __cpp_lib_char8_t // Support u8string_view and char8_t, inline so they work even if lib builds as C++17.
// JSON_DECLARE_JsonImplementType(std::u8string_view,, ):

Просмотреть файл

@ -2026,4 +2026,22 @@ JsonImplementType<UuidStruct>::GetUnchecked(JsonValue const& jsonValue) noexcept
emptyUuid;
}
// JsonType
JsonIterator
JsonImplementType<JsonType>::AddValueCommit(
JsonBuilder& builder,
JsonType type)
{
// This method is only for 0-size values like null, array, or object.
// The following types cannot have 0-size values and should not call this:
assert(type != JsonUInt);
assert(type != JsonInt);
assert(type != JsonFloat);
assert(type != JsonBool);
assert(type != JsonTime);
assert(type != JsonUuid);
return builder._newValueCommit(type, 0, nullptr);
}
} // namespace jsonbuilder