mirror of
https://github.com/nlohmann/json.git
synced 2026-10-10 08:27:13 +00:00
Copy const rvalue strings and document the accepted inputs
json_document::parse(std::move(const_string)) failed to compile with "no matching read_kind": only a non-const rvalue std::string can be moved from. Treat a const rvalue as a copied byte container. parse() does not accept everything BasicJsonType::parse() does: a FILE* and pointers to or arrays of wide characters are rejected at compile time. List the supported inputs instead. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
3 files changed
+37
-15
No files matched your search
@@ -19,24 +19,33 @@ static basic_json_document parse(IteratorType first, IteratorType last,
|
||||
1. Deserialize from a compatible input, borrowing or owning it depending on its value category and type (see Notes).
|
||||
2. Deserialize from a pair of input iterators.
|
||||
|
||||
Both overloads accept exactly what [`BasicJsonType::parse()`](../basic_json/parse.md) accepts, with the same
|
||||
Both overloads accept the same JSON text as [`BasicJsonType::parse()`](../basic_json/parse.md), with the same
|
||||
`ignore_comments`/`ignore_trailing_commas` options, but build a [`basic_json_document`](index.md) (a flat index into
|
||||
the input) instead of a tree of `BasicJsonType` values.
|
||||
the input) instead of a tree of `BasicJsonType` values. The input must be byte-oriented (see the template parameters
|
||||
below): not every input type of `BasicJsonType::parse()` is supported.
|
||||
|
||||
## Template parameters
|
||||
|
||||
`InputType`
|
||||
: A compatible input, for instance:
|
||||
: A byte-oriented input, one of:
|
||||
|
||||
- a `#!cpp std::string`, `#!cpp std::string_view`, or a C-style array of characters
|
||||
- a pointer to a null-terminated string of single byte characters
|
||||
- a `#!cpp std::string`, `#!cpp std::string_view`, or a C-style array of single-byte characters
|
||||
- a pointer to a null-terminated string of single-byte characters (`#!cpp char`, `#!cpp signed char`,
|
||||
`#!cpp unsigned char`, `#!cpp std::uint8_t`)
|
||||
- a container for which `#!cpp obj.data()` and `#!cpp obj.size()` give contiguous single-byte access, e.g.
|
||||
`#!cpp std::vector<char>` or `#!cpp std::vector<std::uint8_t>`
|
||||
- an `#!cpp std::istream` object, or anything else [`BasicJsonType::parse()`](../basic_json/parse.md) accepts
|
||||
- an `#!cpp std::istream` object
|
||||
- a wide string object (`#!cpp std::wstring`, `#!cpp std::u16string`, `#!cpp std::u32string`), which is converted
|
||||
to UTF-8
|
||||
|
||||
Other inputs are not supported: a `#!cpp FILE*`, and pointers to or arrays of wide characters (`#!cpp wchar_t`,
|
||||
`#!cpp char16_t`, `#!cpp char32_t`) are rejected at compile time by a `#!cpp static_assert`. (Use
|
||||
[`BasicJsonType::parse()`](../basic_json/parse.md) for these.)
|
||||
|
||||
`IteratorType`
|
||||
: a compatible iterator type, for instance a pair of pointers such as `ptr` and `ptr + len`, or a pair of
|
||||
`#!cpp std::string::iterator`
|
||||
: an input iterator type, for instance a pair of pointers such as `ptr` and `ptr + len`, or a pair of
|
||||
`#!cpp std::string::iterator`; the iterators of single-byte characters are borrowed or read like the byte inputs
|
||||
above, those of wide characters are converted to UTF-8
|
||||
|
||||
## Parameters
|
||||
|
||||
@@ -84,8 +93,8 @@ Linear in the length of the input.
|
||||
| `input` | ownership |
|
||||
|--------------------------------------------------------------------------------------|--------------------------------------------------------------|
|
||||
| lvalue byte container (`std::string`, `std::vector<char>`, ...), `std::string_view`, C string, character array | **borrowed** -- `input` must outlive the document |
|
||||
| rvalue `#!cpp std::string` | **owned**, moved in without a copy |
|
||||
| rvalue byte container other than `#!cpp std::string` | **owned**, copied |
|
||||
| non-const rvalue `#!cpp std::string` | **owned**, moved in without a copy |
|
||||
| other rvalue byte container (including a `#!cpp const` rvalue `#!cpp std::string`) | **owned**, copied |
|
||||
| stream, wide string, or anything else read through the general input adapter | **owned**, read into a buffer (a stream is read to its end) |
|
||||
|
||||
For overload (2), a pair of pointers to single-byte integers (e.g. `#!cpp const char*`, `#!cpp std::uint8_t*`) is
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string> // basic_string, char_traits, string
|
||||
#include <type_traits> // decay, integral_constant, is_array, is_lvalue_reference, is_pointer, is_same, remove_reference
|
||||
#include <type_traits> // decay, integral_constant, is_array, is_const, is_integral, is_lvalue_reference, is_pointer, is_same, remove_reference
|
||||
#include <utility> // forward
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
@@ -28,12 +28,12 @@ namespace view
|
||||
/// how a document takes its input
|
||||
enum class input_kind
|
||||
{
|
||||
move_string, ///< rvalue std::string: owned without a copy
|
||||
move_string, ///< non-const rvalue std::string: owned without a copy
|
||||
c_string, ///< const char* (NUL-terminated): borrowed
|
||||
char_array, ///< char array (e.g. a string literal): borrowed
|
||||
borrow_range, ///< lvalue contiguous byte container, or std::string_view: borrowed
|
||||
copy_range, ///< rvalue contiguous byte container: copied
|
||||
adapter, ///< anything else parse() accepts (streams, wide strings, ...): read into a buffer
|
||||
copy_range, ///< rvalue contiguous byte container (a const rvalue std::string too): copied
|
||||
adapter, ///< streams, wide strings, and the rest of what the library's input adapter reads: read into a buffer
|
||||
};
|
||||
|
||||
template<typename InputType>
|
||||
@@ -52,7 +52,7 @@ struct classify_input
|
||||
static constexpr input_kind value =
|
||||
std::is_array<R>::value ? input_kind::char_array
|
||||
: std::is_pointer<D>::value ? input_kind::c_string
|
||||
: (is_rvalue && std::is_same<D, std::string>::value) ? input_kind::move_string
|
||||
: (is_rvalue && !std::is_const<R>::value && std::is_same<D, std::string>::value) ? input_kind::move_string
|
||||
: (is_bytes && (!is_rvalue || is_string_view)) ? input_kind::borrow_range
|
||||
: is_bytes ? input_kind::copy_range
|
||||
: input_kind::adapter;
|
||||
|
||||
@@ -314,6 +314,19 @@ TEST_CASE("json_view")
|
||||
CHECK(from_rvalue.owns_source());
|
||||
CHECK(from_rvalue.root().materialize() == expected);
|
||||
CHECK(json_document::parse(std::vector<char>(text.begin(), text.end())).owns_source());
|
||||
// a const rvalue cannot be moved from, and is not borrowed (it may be a
|
||||
// temporary): it is copied, as is a const rvalue of any container
|
||||
const std::string const_text = text;
|
||||
const json_document from_const_rvalue = json_document::parse(std::move(const_text)); // NOLINT(performance-move-const-arg,hicpp-move-const-arg)
|
||||
CHECK(from_const_rvalue.owns_source());
|
||||
CHECK(from_const_rvalue.source().data() != const_text.data());
|
||||
CHECK(from_const_rvalue.root().materialize() == expected);
|
||||
json_document read_const_rvalue;
|
||||
read_const_rvalue.read(std::move(const_text)); // NOLINT(performance-move-const-arg,hicpp-move-const-arg)
|
||||
CHECK(read_const_rvalue.owns_source());
|
||||
CHECK(read_const_rvalue.root().materialize() == expected);
|
||||
const std::vector<char> const_chars(text.begin(), text.end());
|
||||
CHECK(json_document::parse(std::move(const_chars)).owns_source()); // NOLINT(performance-move-const-arg,hicpp-move-const-arg)
|
||||
CHECK(json_document::parse_copy(text).owns_source());
|
||||
CHECK(json_document::parse_copy(text).root().materialize() == expected);
|
||||
std::istringstream stream(text);
|
||||
|
||||
Reference in new issue
Block a user