Add a wrapper for constant string references
This commit is contained in:
parent
3bfffa3cf9
commit
4007301e1f
@ -174,6 +174,51 @@ struct GenericMemberIterator<true,Encoding,Allocator> {
|
|||||||
|
|
||||||
#endif // RAPIDJSON_NOMEMBERITERATORCLASS
|
#endif // RAPIDJSON_NOMEMBERITERATORCLASS
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// GenericStringRef
|
||||||
|
|
||||||
|
//! Reference to a constant string (not taking a copy)
|
||||||
|
template<typename CharType>
|
||||||
|
struct GenericStringRef {
|
||||||
|
typedef CharType Ch; //!< character type of the string
|
||||||
|
|
||||||
|
//! Create string reference from \c const character array
|
||||||
|
template<SizeType N>
|
||||||
|
GenericStringRef(const CharType (&str)[N])
|
||||||
|
: s(str), length(N-1) {}
|
||||||
|
|
||||||
|
//! Explicitly create string reference from \c const character pointer
|
||||||
|
explicit GenericStringRef(const CharType* str)
|
||||||
|
: s(str), length(internal::StrLen(str)){}
|
||||||
|
|
||||||
|
//! Create constant string reference from pointer and length
|
||||||
|
GenericStringRef(const CharType* str, SizeType len)
|
||||||
|
: s(str), length(len) { RAPIDJSON_ASSERT(s != NULL); }
|
||||||
|
|
||||||
|
//! implicit conversion to plain CharType pointer
|
||||||
|
operator const Ch *() const { return s; }
|
||||||
|
|
||||||
|
const Ch* s; //!< plain CharType pointer
|
||||||
|
const SizeType length; //!< length of the string (excluding the trailing NULL terminator)
|
||||||
|
|
||||||
|
private:
|
||||||
|
//! Disallow construction from non-const array
|
||||||
|
template<SizeType N>
|
||||||
|
GenericStringRef(CharType (&str)[N]) /* = delete */;
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Mark a character pointer as constant string
|
||||||
|
template<typename CharType>
|
||||||
|
inline GenericStringRef<CharType> StringRef(const CharType* str) {
|
||||||
|
return GenericStringRef<CharType>(str, internal::StrLen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Mark a character pointer as constant string
|
||||||
|
template<typename CharType>
|
||||||
|
inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) {
|
||||||
|
return GenericStringRef<CharType>(str, SizeType(length));
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// GenericValue
|
// GenericValue
|
||||||
|
|
||||||
@ -196,6 +241,7 @@ public:
|
|||||||
typedef Encoding EncodingType; //!< Encoding type from template parameter.
|
typedef Encoding EncodingType; //!< Encoding type from template parameter.
|
||||||
typedef Allocator AllocatorType; //!< Allocator type from template parameter.
|
typedef Allocator AllocatorType; //!< Allocator type from template parameter.
|
||||||
typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
|
typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
|
||||||
|
typedef GenericStringRef<Ch> StringRefType; //!< Reference to a constant string
|
||||||
typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator; //!< Member iterator for iterating in object.
|
typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator; //!< Member iterator for iterating in object.
|
||||||
typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object.
|
typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object.
|
||||||
typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array.
|
typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array.
|
||||||
@ -207,9 +253,11 @@ public:
|
|||||||
//! Default constructor creates a null value.
|
//! Default constructor creates a null value.
|
||||||
GenericValue() : data_(), flags_(kNullFlag) {}
|
GenericValue() : data_(), flags_(kNullFlag) {}
|
||||||
|
|
||||||
//! Copy constructor is not permitted.
|
|
||||||
private:
|
private:
|
||||||
|
//! Copy constructor is not permitted.
|
||||||
GenericValue(const GenericValue& rhs);
|
GenericValue(const GenericValue& rhs);
|
||||||
|
//! Disabled constructor for arbitrary pointers.
|
||||||
|
template<typename T> explicit GenericValue(T*);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -283,16 +331,16 @@ public:
|
|||||||
explicit GenericValue(double d) : data_(), flags_(kNumberDoubleFlag) { data_.n.d = d; }
|
explicit GenericValue(double d) : data_(), flags_(kNumberDoubleFlag) { data_.n.d = d; }
|
||||||
|
|
||||||
//! Constructor for constant string (i.e. do not make a copy of string)
|
//! Constructor for constant string (i.e. do not make a copy of string)
|
||||||
GenericValue(const Ch* s, SizeType length) : data_(), flags_() { SetStringRaw(s, length); }
|
GenericValue(const Ch* s, SizeType length) : data_(), flags_() { SetStringRaw(StringRef(s, length)); }
|
||||||
|
|
||||||
//! Constructor for constant string (i.e. do not make a copy of string)
|
//! Constructor for constant string (i.e. do not make a copy of string)
|
||||||
explicit GenericValue(const Ch* s) : data_(), flags_() { SetStringRaw(s, internal::StrLen(s)); }
|
explicit GenericValue(StringRefType s) : data_(), flags_() { SetStringRaw(s); }
|
||||||
|
|
||||||
//! Constructor for copy-string (i.e. do make a copy of string)
|
//! Constructor for copy-string (i.e. do make a copy of string)
|
||||||
GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_(), flags_() { SetStringRaw(s, length, allocator); }
|
GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s, length), allocator); }
|
||||||
|
|
||||||
//! Constructor for copy-string (i.e. do make a copy of string)
|
//! Constructor for copy-string (i.e. do make a copy of string)
|
||||||
GenericValue(const Ch*s, Allocator& allocator) : data_(), flags_() { SetStringRaw(s, internal::StrLen(s), allocator); }
|
GenericValue(const Ch*s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); }
|
||||||
|
|
||||||
//! Destructor.
|
//! Destructor.
|
||||||
/*! Need to destruct elements of array, members of object, or copy-string.
|
/*! Need to destruct elements of array, members of object, or copy-string.
|
||||||
@ -339,12 +387,17 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Assignment of constant string reference (no copy)
|
||||||
|
GenericValue& operator=(StringRefType str) {
|
||||||
|
return (*this).template operator=<StringRefType>(str);
|
||||||
|
}
|
||||||
//! Assignment with primitive types.
|
//! Assignment with primitive types.
|
||||||
/*! \tparam T Either Type, int, unsigned, int64_t, uint64_t, const Ch*
|
/*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
|
||||||
\param value The value to be assigned.
|
\param value The value to be assigned.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
GenericValue& operator=(T value) {
|
RAPIDJSON_DISABLEIF_RETURN(internal::IsPointer<T>,GenericValue&)
|
||||||
|
operator=(T value) {
|
||||||
this->~GenericValue();
|
this->~GenericValue();
|
||||||
new (this) GenericValue(value);
|
new (this) GenericValue(value);
|
||||||
return *this;
|
return *this;
|
||||||
@ -428,7 +481,7 @@ public:
|
|||||||
A better approach is to use the now public FindMember().
|
A better approach is to use the now public FindMember().
|
||||||
*/
|
*/
|
||||||
GenericValue& operator[](const Ch* name) {
|
GenericValue& operator[](const Ch* name) {
|
||||||
GenericValue n(name, internal::StrLen(name));
|
GenericValue n(StringRef(name));
|
||||||
return (*this)[n];
|
return (*this)[n];
|
||||||
}
|
}
|
||||||
const GenericValue& operator[](const Ch* name) const { return const_cast<GenericValue&>(*this)[name]; }
|
const GenericValue& operator[](const Ch* name) const { return const_cast<GenericValue&>(*this)[name]; }
|
||||||
@ -481,7 +534,7 @@ public:
|
|||||||
\c std::map, this has been changed to MemberEnd() now.
|
\c std::map, this has been changed to MemberEnd() now.
|
||||||
*/
|
*/
|
||||||
MemberIterator FindMember(const Ch* name) {
|
MemberIterator FindMember(const Ch* name) {
|
||||||
GenericValue n(name, internal::StrLen(name));
|
GenericValue n(StringRef(name));
|
||||||
return FindMember(n);
|
return FindMember(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,19 +583,23 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericValue& AddMember(const Ch* name, Allocator& nameAllocator, GenericValue& value, Allocator& allocator) {
|
//! Add a member (name-value pair) to the object.
|
||||||
GenericValue n(name, internal::StrLen(name), nameAllocator);
|
GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) {
|
||||||
|
GenericValue n(name);
|
||||||
return AddMember(n, value, allocator);
|
return AddMember(n, value, allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericValue& AddMember(const Ch* name, GenericValue& value, Allocator& allocator) {
|
//! Add a constant string value as member (name-value pair) to the object.
|
||||||
GenericValue n(name, internal::StrLen(name));
|
GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) {
|
||||||
return AddMember(n, value, allocator);
|
GenericValue v(value);
|
||||||
|
return AddMember(name, v, allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Add any primitive value as member (name-value pair) to the object.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
GenericValue& AddMember(const Ch* name, T value, Allocator& allocator) {
|
RAPIDJSON_DISABLEIF_RETURN(internal::IsPointer<T>,GenericValue&)
|
||||||
GenericValue n(name, internal::StrLen(name));
|
AddMember(StringRefType name, T value, Allocator& allocator) {
|
||||||
|
GenericValue n(name);
|
||||||
GenericValue v(value);
|
GenericValue v(value);
|
||||||
return AddMember(n, v, allocator);
|
return AddMember(n, v, allocator);
|
||||||
}
|
}
|
||||||
@ -553,7 +610,7 @@ public:
|
|||||||
\note Removing member is implemented by moving the last member. So the ordering of members is changed.
|
\note Removing member is implemented by moving the last member. So the ordering of members is changed.
|
||||||
*/
|
*/
|
||||||
bool RemoveMember(const Ch* name) {
|
bool RemoveMember(const Ch* name) {
|
||||||
GenericValue n(name, internal::StrLen(name));
|
GenericValue n(StringRef(name));
|
||||||
return RemoveMember(n);
|
return RemoveMember(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -657,7 +714,7 @@ int z = a[0u].GetInt(); // This works too.
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Append a value at the end of the array.
|
//! Append a GenericValue at the end of the array.
|
||||||
/*! \param value The value to be appended.
|
/*! \param value The value to be appended.
|
||||||
\param allocator The allocator for allocating memory. It must be the same one use previously.
|
\param allocator The allocator for allocating memory. It must be the same one use previously.
|
||||||
\return The value itself for fluent API.
|
\return The value itself for fluent API.
|
||||||
@ -672,8 +729,15 @@ int z = a[0u].GetInt(); // This works too.
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Append a constant string reference at the end of the array.
|
||||||
|
GenericValue& PushBack(StringRefType value, Allocator& allocator) {
|
||||||
|
return (*this).template PushBack<StringRefType>(value, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Append a primitive value at the end of the array.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
GenericValue& PushBack(T value, Allocator& allocator) {
|
RAPIDJSON_DISABLEIF_RETURN(internal::IsPointer<T>,GenericValue&)
|
||||||
|
PushBack(T value, Allocator& allocator) {
|
||||||
GenericValue v(value);
|
GenericValue v(value);
|
||||||
return PushBack(v, allocator);
|
return PushBack(v, allocator);
|
||||||
}
|
}
|
||||||
@ -728,13 +792,13 @@ int z = a[0u].GetInt(); // This works too.
|
|||||||
\param length The length of source string, excluding the trailing null terminator.
|
\param length The length of source string, excluding the trailing null terminator.
|
||||||
\return The value itself for fluent API.
|
\return The value itself for fluent API.
|
||||||
*/
|
*/
|
||||||
GenericValue& SetString(const Ch* s, SizeType length) { this->~GenericValue(); SetStringRaw(s, length); return *this; }
|
GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); }
|
||||||
|
|
||||||
//! Set this value as a string without copying source string.
|
//! Set this value as a string without copying source string.
|
||||||
/*! \param s source string pointer.
|
/*! \param s source string reference
|
||||||
\return The value itself for fluent API.
|
\return The value itself for fluent API.
|
||||||
*/
|
*/
|
||||||
GenericValue& SetString(const Ch* s) { return SetString(s, internal::StrLen(s)); }
|
GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; }
|
||||||
|
|
||||||
//! Set this value as a string by copying from source string.
|
//! Set this value as a string by copying from source string.
|
||||||
/*! This version has better performance with supplied length, and also support string containing null character.
|
/*! This version has better performance with supplied length, and also support string containing null character.
|
||||||
@ -743,14 +807,14 @@ int z = a[0u].GetInt(); // This works too.
|
|||||||
\param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator().
|
\param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator().
|
||||||
\return The value itself for fluent API.
|
\return The value itself for fluent API.
|
||||||
*/
|
*/
|
||||||
GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, length, allocator); return *this; }
|
GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; }
|
||||||
|
|
||||||
//! Set this value as a string by copying from source string.
|
//! Set this value as a string by copying from source string.
|
||||||
/*! \param s source string.
|
/*! \param s source string.
|
||||||
\param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator().
|
\param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator().
|
||||||
\return The value itself for fluent API.
|
\return The value itself for fluent API.
|
||||||
*/
|
*/
|
||||||
GenericValue& SetString(const Ch* s, Allocator& allocator) { SetString(s, internal::StrLen(s), allocator); return *this; }
|
GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); }
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
@ -906,21 +970,19 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Initialize this value as constant string, without calling destructor.
|
//! Initialize this value as constant string, without calling destructor.
|
||||||
void SetStringRaw(const Ch* s, SizeType length) {
|
void SetStringRaw(StringRefType s) {
|
||||||
RAPIDJSON_ASSERT(s != NULL);
|
|
||||||
flags_ = kConstStringFlag;
|
flags_ = kConstStringFlag;
|
||||||
data_.s.str = s;
|
data_.s.str = s;
|
||||||
data_.s.length = length;
|
data_.s.length = s.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Initialize this value as copy string with initial data, without calling destructor.
|
//! Initialize this value as copy string with initial data, without calling destructor.
|
||||||
void SetStringRaw(const Ch* s, SizeType length, Allocator& allocator) {
|
void SetStringRaw(StringRefType s, Allocator& allocator) {
|
||||||
RAPIDJSON_ASSERT(s != NULL);
|
|
||||||
flags_ = kCopyStringFlag;
|
flags_ = kCopyStringFlag;
|
||||||
data_.s.str = (Ch *)allocator.Malloc((length + 1) * sizeof(Ch));
|
data_.s.str = (Ch *)allocator.Malloc((s.length + 1) * sizeof(Ch));
|
||||||
data_.s.length = length;
|
data_.s.length = s.length;
|
||||||
memcpy(const_cast<Ch*>(data_.s.str), s, length * sizeof(Ch));
|
memcpy(const_cast<Ch*>(data_.s.str), s, s.length * sizeof(Ch));
|
||||||
const_cast<Ch*>(data_.s.str)[length] = '\0';
|
const_cast<Ch*>(data_.s.str)[s.length] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Assignment without calling destructor
|
//! Assignment without calling destructor
|
||||||
|
@ -30,6 +30,9 @@ template <typename T> struct IsSame<T,T> : TrueType {};
|
|||||||
template <typename T> struct IsConst : FalseType {};
|
template <typename T> struct IsConst : FalseType {};
|
||||||
template <typename T> struct IsConst<const T> : TrueType {};
|
template <typename T> struct IsConst<const T> : TrueType {};
|
||||||
|
|
||||||
|
template <typename T> struct IsPointer : FalseType {};
|
||||||
|
template <typename T> struct IsPointer<T*> : TrueType {};
|
||||||
|
|
||||||
template <typename CT, typename T>
|
template <typename CT, typename T>
|
||||||
struct IsMoreConst {
|
struct IsMoreConst {
|
||||||
enum { Value =
|
enum { Value =
|
||||||
@ -64,6 +67,9 @@ template <typename T> struct RemoveSfinaeFptr<SfinaeResultTag&(*)(T)> { typedef
|
|||||||
typename ::rapidjson::internal::EnableIf \
|
typename ::rapidjson::internal::EnableIf \
|
||||||
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
|
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
|
||||||
|
|
||||||
|
#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
|
||||||
|
typename ::rapidjson::internal::DisableIf<cond,returntype>::Type
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace rapidjson
|
} // namespace rapidjson
|
||||||
//@endcond
|
//@endcond
|
||||||
|
Loading…
x
Reference in New Issue
Block a user