Commit df70ee82 authored by Milo Yip's avatar Milo Yip

Merge pull request #107 from pah/feature/basic_string

GenericValue: add optional support for std::string
parents 1adeecb1 ae3e12d7
......@@ -12,6 +12,7 @@ env:
- CONF=release BITS=32
global:
- GITHUB_REPO='miloyip/rapidjson'
- DEFINES='-DRAPIDJSON_HAS_STDSTRING'
- secure: "HrsaCb+N66EG1HR+LWH1u51SjaJyRwJEDzqJGYMB7LJ/bfqb9mWKF1fLvZGk46W5t7TVaXRDD5KHFx9DPWvKn4gRUVkwTHEy262ah5ORh8M6n/6VVVajeV/AYt2C0sswdkDBDO4Xq+xy5gdw3G8s1A4Inbm73pUh+6vx+7ltBbk="
before_install:
......
......@@ -21,6 +21,8 @@
#ifndef RAPIDJSON_DOCUMENT_H_
#define RAPIDJSON_DOCUMENT_H_
/*! \file document.h */
#include "reader.h"
#include "internal/strfunc.h"
#include <new> // placement new
......@@ -33,6 +35,26 @@ RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_HAS_STDSTRING
#ifdef RAPIDJSON_DOXYGEN_RUNNING
#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation
#endif
#ifdef RAPIDJSON_HAS_STDSTRING
/*! \def RAPIDJSON_HAS_STDSTRING
\ingroup RAPIDJSON_CONFIG
\brief Enable RapidJSON support for \c std::string
By defining this preprocessor symbol, several convenience functions for using
\ref rapidjson::GenericValue with \c std::string are enabled, especially
for construction and comparison.
\hideinitializer
*/
#include <string>
#endif // RAPIDJSON_HAS_STDSTRING
#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
#include "internal/meta.h"
#include <iterator> // std::iterator, std::random_access_iterator_tag
......@@ -56,6 +78,9 @@ struct GenericMember {
GenericValue<Encoding, Allocator> value; //!< value of member.
};
///////////////////////////////////////////////////////////////////////////////
// GenericMemberIterator
#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
//! (Constant) member iterator for a JSON object value
......@@ -338,6 +363,25 @@ inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length)
return GenericStringRef<CharType>(str, SizeType(length));
}
#ifdef RAPIDJSON_HAS_STDSTRING
//! Mark a string object as constant string
/*! Mark a string object (e.g. \c std::string) as a "string literal".
This function can be used to avoid copying a string to be referenced as a
value in a JSON GenericValue object, if the string's lifetime is known
to be valid long enough.
\tparam CharType character type of the string
\param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
\return GenericStringRef string reference object
\relatesalso GenericStringRef
\note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
*/
template<typename CharType>
inline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& str) {
return GenericStringRef<CharType>(str.data(), SizeType(str.size()));
}
#endif
///////////////////////////////////////////////////////////////////////////////
// GenericValue
......@@ -470,6 +514,13 @@ public:
//! Constructor for copy-string (i.e. do make a copy of string)
GenericValue(const Ch*s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); }
#ifdef RAPIDJSON_HAS_STDSTRING
//! Constructor for copy-string from a string object (i.e. do make a copy of string)
/*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
*/
GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); }
#endif
//! Destructor.
/*! Need to destruct elements of array, members of object, or copy-string.
*/
......@@ -619,28 +670,35 @@ public:
}
}
//! Not-equal-to operator
bool operator!=(const GenericValue& rhs) const { return !(*this == rhs); }
//! Equal-to operator with const C-string pointer
bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); }
//! (Not-)Equal-to operator with const C-string pointer.
friend bool operator==(const GenericValue& lhs, const Ch* rhs) { return lhs == GenericValue(StringRef(rhs)); }
friend bool operator!=(const GenericValue& lhs, const Ch* rhs) { return !(lhs == rhs); }
friend bool operator==(const Ch* lhs, const GenericValue& rhs) { return GenericValue(StringRef(lhs)) == rhs; }
friend bool operator!=(const Ch* lhs, const GenericValue& rhs) { return !(lhs == rhs); }
//! (Not-)Equal-to operator with non-const C-string pointer.
friend bool operator==(const GenericValue& lhs, Ch* rhs) { return lhs == GenericValue(StringRef(rhs)); }
friend bool operator!=(const GenericValue& lhs, Ch* rhs) { return !(lhs == rhs); }
friend bool operator==(Ch* lhs, const GenericValue& rhs) { return GenericValue(StringRef(lhs)) == rhs; }
friend bool operator!=(Ch* lhs, const GenericValue& rhs) { return !(lhs == rhs); }
#ifdef RAPIDJSON_HAS_STDSTRING
//! Equal-to operator with string object
/*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
*/
bool operator==(const std::basic_string<Ch>& rhs) const { return *this == GenericValue(StringRef(rhs)); }
#endif
//! (Not-)Equal-to operator with primitive types.
//! Equal-to operator with primitive types
/*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false
*/
template <typename T> friend bool operator==(const GenericValue& lhs, const T& rhs) { return lhs == GenericValue(rhs); }
template <typename T> friend bool operator!=(const GenericValue& lhs, const T& rhs) { return !(lhs == rhs); }
template <typename T> friend bool operator==(const T& lhs, const GenericValue& rhs) { return GenericValue(lhs) == rhs; }
template <typename T> friend bool operator!=(const T& lhs, const GenericValue& rhs) { return !(lhs == rhs); }
template <typename T> RAPIDJSON_DISABLEIF_RETURN(internal::IsPointer<T>, bool) operator==(const T& rhs) const { return *this == GenericValue(rhs); }
//! Not-equal-to operator with arbitrary types
/*! \return !(*this == rhs)
*/
template <typename T> bool operator!=(const T& rhs) const { return !(*this == rhs); }
//! Equal-to operator with arbitrary types (symmetric version)
/*! \return (rhs == lhs)
*/
template <typename T> friend bool operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; }
//! Not-Equal-to operator with arbitrary types (symmetric version)
/*! \return !(rhs == lhs)
*/
template <typename T> friend bool operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); }
//@}
//!@name Type
......@@ -1207,6 +1265,17 @@ int z = a[0u].GetInt(); // This works too.
*/
GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); }
#if RAPIDJSON_HAS_STDSTRING
//! Set this value as a string by copying from source string.
/*! \param s source string.
\param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size()
\note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
*/
GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), s.size(), allocator); }
#endif
//@}
//! Generate events of this value to a Handler.
......
......@@ -537,6 +537,44 @@ TEST(Value, String) {
s[0] = '\0';
EXPECT_STREQ("World", w.GetString());
EXPECT_EQ(5u, w.GetStringLength());
#ifdef RAPIDJSON_HAS_STDSTRING
{
std::string str = "Hello World";
str[5] = '\0';
EXPECT_STREQ(str.data(),"Hello"); // embedded '\0'
EXPECT_EQ(str.size(), 11u);
// no copy
Value vs0(StringRef(str));
EXPECT_TRUE(vs0.IsString());
EXPECT_EQ(vs0.GetString(), str.data());
EXPECT_EQ(vs0.GetStringLength(), str.size());
TestEqual(vs0, str);
// do copy
Value vs1(str, allocator);
EXPECT_TRUE(vs1.IsString());
EXPECT_NE(vs1.GetString(), str.data());
EXPECT_NE(vs1.GetString(), str); // not equal due to embedded '\0'
EXPECT_EQ(vs1.GetStringLength(), str.size());
TestEqual(vs1, str);
// SetString
str = "World";
vs0.SetNull().SetString(str, allocator);
EXPECT_TRUE(vs0.IsString());
EXPECT_STREQ(vs0.GetString(), str.c_str());
EXPECT_EQ(vs0.GetStringLength(), str.size());
TestEqual(str, vs0);
TestUnequal(str, vs1);
// vs1 = str; // should not compile
vs1 = StringRef(str);
TestEqual(str, vs1);
TestEqual(vs0, vs1);
}
#endif // RAPIDJSON_HAS_STDSTRING
}
TEST(Value, Array) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment