mirror of
https://github.com/open-source-parsers/jsoncpp.git
synced 2024-12-12 10:03:51 +01:00
feat: support std::string_view in Value API
This adds direct support for `std::string_view` when available (C++17 and above). The current API can be used with `std::string_view` via the low-level two-pointer methods, but is not ergonomic. E.g., compare: ``` Json::Value node; std::string foo, bar, baz; std::string_view foo_sv, bar_sv, baz_sv; // Efficient & readable: node[foo][bar][baz]; // Less efficient, less readable: node[std::string(foo_sv)][std::string(bar_sv)][std::string(baz_sv)]; // Efficient, but a lot less readable: *node.demand(foo_sv.data(), foo_sv.data() + foo_sv.size()) ->demand(bar_sv.data(), bar_sv.data() + bar_sv.size()) ->demand(baz_sv.data(), baz_sv.data() + baz_sv.size()) // After this change, efficient & readable: node[foo_sv][bar_sv][baz_sv]; ``` * The constructor can take a `std::string_view` parameter. The existing overloads taking `const std::string&` and `const char*` are still necessary to support assignment from those types. * `operator[]`, `get()`, `isMember()` and `removeMember()` take a `std::string_view` parameter. This supersedes the overloads taking `const std::string&` and `const char*`. The overloads taking a pair of pointers (begin, end) are preserved for source compatibility. * `getString()` has an overload with a `std::string_view` output parameter. The one with a pair of pointers is preserved for source compatibility. Signed-off-by: Lev Kandel <lmakhlis@google.com>
This commit is contained in:
parent
dca8a24cf8
commit
dbff9dba38
@ -39,6 +39,10 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
#define JSONCPP_HAS_STRING_VIEW 1
|
||||
#endif
|
||||
|
||||
#include <array>
|
||||
#include <exception>
|
||||
#include <map>
|
||||
@ -46,6 +50,10 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
|
||||
// be used by...
|
||||
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||
@ -342,6 +350,9 @@ public:
|
||||
*/
|
||||
Value(const StaticString& value);
|
||||
Value(const String& value);
|
||||
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||
Value(std::string_view value);
|
||||
#endif
|
||||
Value(bool value);
|
||||
Value(std::nullptr_t ptr) = delete;
|
||||
Value(const Value& other);
|
||||
@ -384,6 +395,12 @@ public:
|
||||
* \return false if !string. (Seg-fault if str or end are NULL.)
|
||||
*/
|
||||
bool getString(char const** begin, char const** end) const;
|
||||
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||
/** Get string_view of string-value.
|
||||
* \return false if !string. (Seg-fault if str is NULL.)
|
||||
*/
|
||||
bool getString(std::string_view* str) const;
|
||||
#endif
|
||||
Int asInt() const;
|
||||
UInt asUInt() const;
|
||||
#if defined(JSON_HAS_INT64)
|
||||
@ -470,6 +487,15 @@ public:
|
||||
bool insert(ArrayIndex index, const Value& newValue);
|
||||
bool insert(ArrayIndex index, Value&& newValue);
|
||||
|
||||
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||
/// Access an object value by name, create a null member if it does not exist.
|
||||
/// \param key may contain embedded nulls.
|
||||
Value& operator[](std::string_view key);
|
||||
/// Access an object value by name, returns null if there is no member with
|
||||
/// that name.
|
||||
/// \param key may contain embedded nulls.
|
||||
const Value& operator[](std::string_view key) const;
|
||||
#else
|
||||
/// Access an object value by name, create a null member if it does not exist.
|
||||
/// \note Because of our implementation, keys are limited to 2^30 -1 chars.
|
||||
/// Exceeding that will cause an exception.
|
||||
@ -484,6 +510,7 @@ public:
|
||||
/// that name.
|
||||
/// \param key may contain embedded nulls.
|
||||
const Value& operator[](const String& key) const;
|
||||
#endif
|
||||
/** \brief Access an object value by name, create a null member if it does not
|
||||
* exist.
|
||||
*
|
||||
@ -497,18 +524,24 @@ public:
|
||||
* \endcode
|
||||
*/
|
||||
Value& operator[](const StaticString& key);
|
||||
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||
/// Return the member named key if it exist, defaultValue otherwise.
|
||||
/// \note deep copy
|
||||
Value get(std::string_view key, const Value& defaultValue) const;
|
||||
#else
|
||||
/// Return the member named key if it exist, defaultValue otherwise.
|
||||
/// \note deep copy
|
||||
Value get(const char* key, const Value& defaultValue) const;
|
||||
/// Return the member named key if it exist, defaultValue otherwise.
|
||||
/// \note deep copy
|
||||
/// \param key may contain embedded nulls.
|
||||
Value get(const String& key, const Value& defaultValue) const;
|
||||
#endif
|
||||
/// Return the member named key if it exist, defaultValue otherwise.
|
||||
/// \note deep copy
|
||||
/// \note key may contain embedded nulls.
|
||||
Value get(const char* begin, const char* end,
|
||||
const Value& defaultValue) const;
|
||||
/// Return the member named key if it exist, defaultValue otherwise.
|
||||
/// \note deep copy
|
||||
/// \param key may contain embedded nulls.
|
||||
Value get(const String& key, const Value& defaultValue) const;
|
||||
/// Most general and efficient version of isMember()const, get()const,
|
||||
/// and operator[]const
|
||||
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
|
||||
@ -525,20 +558,28 @@ public:
|
||||
/// Do nothing if it did not exist.
|
||||
/// \pre type() is objectValue or nullValue
|
||||
/// \post type() is unchanged
|
||||
#if JSONCPP_HAS_STRING_VIEW
|
||||
void removeMember(std::string_view key);
|
||||
#else
|
||||
void removeMember(const char* key);
|
||||
/// Same as removeMember(const char*)
|
||||
/// \param key may contain embedded nulls.
|
||||
void removeMember(const String& key);
|
||||
/// Same as removeMember(const char* begin, const char* end, Value* removed),
|
||||
/// but 'key' is null-terminated.
|
||||
bool removeMember(const char* key, Value* removed);
|
||||
#endif
|
||||
/** \brief Remove the named map member.
|
||||
*
|
||||
* Update 'removed' iff removed.
|
||||
* \param key may contain embedded nulls.
|
||||
* \return true iff removed (no exceptions)
|
||||
*/
|
||||
#if JSONCPP_HAS_STRING_VIEW
|
||||
bool removeMember(std::string_view key, Value* removed);
|
||||
#else
|
||||
bool removeMember(String const& key, Value* removed);
|
||||
/// Same as removeMember(const char* begin, const char* end, Value* removed),
|
||||
/// but 'key' is null-terminated.
|
||||
bool removeMember(const char* key, Value* removed);
|
||||
#endif
|
||||
/// Same as removeMember(String const& key, Value* removed)
|
||||
bool removeMember(const char* begin, const char* end, Value* removed);
|
||||
/** \brief Remove the indexed array element.
|
||||
@ -549,12 +590,18 @@ public:
|
||||
*/
|
||||
bool removeIndex(ArrayIndex index, Value* removed);
|
||||
|
||||
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||
/// Return true if the object has a member named key.
|
||||
/// \param key may contain embedded nulls.
|
||||
bool isMember(std::string_view key) const;
|
||||
#else
|
||||
/// Return true if the object has a member named key.
|
||||
/// \note 'key' must be null-terminated.
|
||||
bool isMember(const char* key) const;
|
||||
/// Return true if the object has a member named key.
|
||||
/// \param key may contain embedded nulls.
|
||||
bool isMember(const String& key) const;
|
||||
#endif
|
||||
/// Same as isMember(String const& key)const
|
||||
bool isMember(const char* begin, const char* end) const;
|
||||
|
||||
|
@ -17,6 +17,10 @@
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
// Provide implementation equivalent of std::snprintf for older _MSC compilers
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
#include <stdarg.h>
|
||||
@ -420,6 +424,14 @@ Value::Value(const String& value) {
|
||||
value.data(), static_cast<unsigned>(value.length()));
|
||||
}
|
||||
|
||||
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||
Value::Value(std::string_view value) {
|
||||
initBasic(stringValue, true);
|
||||
value_.string_ = duplicateAndPrefixStringValue(
|
||||
value.data(), static_cast<unsigned>(value.length()));
|
||||
}
|
||||
#endif
|
||||
|
||||
Value::Value(const StaticString& value) {
|
||||
initBasic(stringValue);
|
||||
value_.string_ = const_cast<char*>(value.c_str());
|
||||
@ -627,6 +639,21 @@ bool Value::getString(char const** begin, char const** end) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||
bool Value::getString(std::string_view* str) const {
|
||||
if (type() != stringValue)
|
||||
return false;
|
||||
if (value_.string_ == nullptr)
|
||||
return false;
|
||||
const char* begin;
|
||||
unsigned length;
|
||||
decodePrefixedString(this->isAllocated(), this->value_.string_, &length,
|
||||
&begin);
|
||||
*str = std::string_view(begin, length);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
String Value::asString() const {
|
||||
switch (type()) {
|
||||
case nullValue:
|
||||
@ -1108,6 +1135,17 @@ Value* Value::demand(char const* begin, char const* end) {
|
||||
"objectValue or nullValue");
|
||||
return &resolveReference(begin, end);
|
||||
}
|
||||
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||
const Value& Value::operator[](std::string_view key) const {
|
||||
Value const* found = find(key.data(), key.data() + key.length());
|
||||
if (!found)
|
||||
return nullSingleton();
|
||||
return *found;
|
||||
}
|
||||
Value& Value::operator[](std::string_view key) {
|
||||
return resolveReference(key.data(), key.data() + key.length());
|
||||
}
|
||||
#else
|
||||
const Value& Value::operator[](const char* key) const {
|
||||
Value const* found = find(key, key + strlen(key));
|
||||
if (!found)
|
||||
@ -1128,6 +1166,7 @@ Value& Value::operator[](const char* key) {
|
||||
Value& Value::operator[](const String& key) {
|
||||
return resolveReference(key.data(), key.data() + key.length());
|
||||
}
|
||||
#endif
|
||||
|
||||
Value& Value::operator[](const StaticString& key) {
|
||||
return resolveReference(key.c_str());
|
||||
@ -1167,12 +1206,18 @@ Value Value::get(char const* begin, char const* end,
|
||||
Value const* found = find(begin, end);
|
||||
return !found ? defaultValue : *found;
|
||||
}
|
||||
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||
Value Value::get(std::string_view key, const Value& defaultValue) const {
|
||||
return get(key.data(), key.data() + key.length(), defaultValue);
|
||||
}
|
||||
#else
|
||||
Value Value::get(char const* key, Value const& defaultValue) const {
|
||||
return get(key, key + strlen(key), defaultValue);
|
||||
}
|
||||
Value Value::get(String const& key, Value const& defaultValue) const {
|
||||
return get(key.data(), key.data() + key.length(), defaultValue);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool Value::removeMember(const char* begin, const char* end, Value* removed) {
|
||||
if (type() != objectValue) {
|
||||
@ -1188,12 +1233,31 @@ bool Value::removeMember(const char* begin, const char* end, Value* removed) {
|
||||
value_.map_->erase(it);
|
||||
return true;
|
||||
}
|
||||
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||
bool Value::removeMember(std::string_view key, Value* removed) {
|
||||
return removeMember(key.data(), key.data() + key.length(), removed);
|
||||
}
|
||||
#else
|
||||
bool Value::removeMember(const char* key, Value* removed) {
|
||||
return removeMember(key, key + strlen(key), removed);
|
||||
}
|
||||
bool Value::removeMember(String const& key, Value* removed) {
|
||||
return removeMember(key.data(), key.data() + key.length(), removed);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||
void Value::removeMember(std::string_view key) {
|
||||
JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
|
||||
"in Json::Value::removeMember(): requires objectValue");
|
||||
if (type() == nullValue)
|
||||
return;
|
||||
|
||||
CZString actualKey(key.data(), unsigned(key.length()),
|
||||
CZString::noDuplication);
|
||||
value_.map_->erase(actualKey);
|
||||
}
|
||||
#else
|
||||
void Value::removeMember(const char* key) {
|
||||
JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
|
||||
"in Json::Value::removeMember(): requires objectValue");
|
||||
@ -1204,6 +1268,7 @@ void Value::removeMember(const char* key) {
|
||||
value_.map_->erase(actualKey);
|
||||
}
|
||||
void Value::removeMember(const String& key) { removeMember(key.c_str()); }
|
||||
#endif
|
||||
|
||||
bool Value::removeIndex(ArrayIndex index, Value* removed) {
|
||||
if (type() != arrayValue) {
|
||||
@ -1233,12 +1298,18 @@ bool Value::isMember(char const* begin, char const* end) const {
|
||||
Value const* value = find(begin, end);
|
||||
return nullptr != value;
|
||||
}
|
||||
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||
bool Value::isMember(std::string_view key) const {
|
||||
return isMember(key.data(), key.data() + key.length());
|
||||
}
|
||||
#else
|
||||
bool Value::isMember(char const* key) const {
|
||||
return isMember(key, key + strlen(key));
|
||||
}
|
||||
bool Value::isMember(String const& key) const {
|
||||
return isMember(key.data(), key.data() + key.length());
|
||||
}
|
||||
#endif
|
||||
|
||||
Value::Members Value::getMemberNames() const {
|
||||
JSON_ASSERT_MESSAGE(
|
||||
|
Loading…
Reference in New Issue
Block a user