mirror of
https://github.com/Tencent/rapidjson.git
synced 2025-09-11 17:12:29 +02:00
Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3d5848a7cd | ||
![]() |
c5cbe97f39 | ||
![]() |
78337e9433 | ||
![]() |
fc8247c036 | ||
![]() |
6f830ec76b | ||
![]() |
2bd1171792 | ||
![]() |
de55114f97 | ||
![]() |
91a7e01c1e | ||
![]() |
ffbe386147 | ||
![]() |
0691502573 | ||
![]() |
1034587235 | ||
![]() |
85564d48f5 | ||
![]() |
c59254a86a |
16
CHANGELOG.md
16
CHANGELOG.md
@ -4,7 +4,20 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [1.0.2] - 2015-05-14
|
||||
|
||||
### Added
|
||||
* Add Value::XXXMember(...) overloads for std::string (#335)
|
||||
|
||||
### Fixed
|
||||
* Include rapidjson.h for all internal/error headers.
|
||||
* Parsing some numbers incorrectly in full-precision mode (`kFullPrecisionParseFlag`) (#342)
|
||||
* Fix alignment of 64bit platforms (#328)
|
||||
* Fix MemoryPoolAllocator::Clear() to clear user-buffer (0691502573f1afd3341073dd24b12c3db20fbde4)
|
||||
|
||||
### Changed
|
||||
* CMakeLists for include as a thirdparty in projects (#334, #337)
|
||||
* Change Document::ParseStream() to use stack allocator for Reader (ffbe38614732af8e0b3abdc8b50071f386a4a685)
|
||||
|
||||
## [1.0.1] - 2015-04-25
|
||||
|
||||
@ -60,6 +73,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## 0.1 - 2011-11-18
|
||||
|
||||
[Unreleased]: https://github.com/miloyip/rapidjson/compare/v1.0.1...HEAD
|
||||
[Unreleased]: https://github.com/miloyip/rapidjson/compare/v1.0.2...HEAD
|
||||
[1.0.2]: https://github.com/miloyip/rapidjson/compare/v1.0.1...v1.0.2
|
||||
[1.0.1]: https://github.com/miloyip/rapidjson/compare/v1.0.0...v1.0.1
|
||||
[1.0.0]: https://github.com/miloyip/rapidjson/compare/v1.0-beta...v1.0.0
|
||||
|
@ -1,11 +1,11 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMakeModules)
|
||||
SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules)
|
||||
|
||||
PROJECT(RapidJSON CXX)
|
||||
|
||||
set(LIB_MAJOR_VERSION "1")
|
||||
set(LIB_MINOR_VERSION "0")
|
||||
set(LIB_PATCH_VERSION "1")
|
||||
set(LIB_PATCH_VERSION "2")
|
||||
set(LIB_VERSION_STRING "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_PATCH_VERSION}")
|
||||
|
||||
# compile in release with debug info mode by default
|
||||
@ -17,7 +17,7 @@ SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
option(RAPIDJSON_BUILD_DOC "Build rapidjson documentation." ON)
|
||||
option(RAPIDJSON_BUILD_EXAMPLES "Build rapidjson examples." ON)
|
||||
option(RAPIDJSON_BUILD_TESTS "Build rapidjson perftests and unittests." ON)
|
||||
option(RAPIDJSON_BUILD_THIRDPARTY_GTEST
|
||||
option(RAPIDJSON_BUILD_THIRDPARTY_GTEST
|
||||
"Use gtest installation in `thirdparty/gtest` by default if available" OFF)
|
||||
|
||||
option(RAPIDJSON_HAS_STDSTRING "" OFF)
|
||||
@ -45,7 +45,7 @@ ELSEIF(WIN32)
|
||||
ENDIF()
|
||||
SET(CMAKE_INSTALL_DIR "${_CMAKE_INSTALL_DIR}" CACHE PATH "The directory cmake fiels are installed in")
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/include)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
if(RAPIDJSON_BUILD_DOC)
|
||||
add_subdirectory(doc)
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
SET(GTEST_SEARCH_PATH
|
||||
SET(GTEST_SEARCH_PATH
|
||||
"${GTEST_SOURCE_DIR}"
|
||||
"${CMAKE_SOURCE_DIR}/thirdparty/gtest")
|
||||
"${CMAKE_CURRENT_LIST_DIR}/../thirdparty/gtest")
|
||||
|
||||
IF(UNIX)
|
||||
IF(RAPIDJSON_BUILD_THIRDPARTY_GTEST)
|
||||
@ -15,6 +15,7 @@ FIND_PATH(GTEST_SOURCE_DIR
|
||||
NAMES CMakeLists.txt src/gtest_main.cc
|
||||
PATHS ${GTEST_SEARCH_PATH})
|
||||
|
||||
|
||||
# Debian installs gtest include directory in /usr/include, thus need to look
|
||||
# for include directory separately from source directory.
|
||||
FIND_PATH(GTEST_INCLUDE_DIR
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: 1.0.1.{build}
|
||||
version: 1.0.2.{build}
|
||||
|
||||
configuration:
|
||||
- Debug
|
||||
|
@ -3,9 +3,9 @@ find_package(Doxygen)
|
||||
IF(NOT DOXYGEN_FOUND)
|
||||
MESSAGE(STATUS "No Doxygen found. Documentation won't be built")
|
||||
ELSE()
|
||||
file(GLOB SOURCES ${CMAKE_SOURCE_DIR}/include/*)
|
||||
file(GLOB MARKDOWN_DOC ${CMAKE_SOURCE_DIR}/doc/*.md)
|
||||
list(APPEND MARKDOWN_DOC ${CMAKE_SOURCE_DIR}/readme.md)
|
||||
file(GLOB SOURCES ${CMAKE_CURRENT_LIST_DIR}/../include/*)
|
||||
file(GLOB MARKDOWN_DOC ${CMAKE_CURRENT_LIST_DIR}/../doc/*.md)
|
||||
list(APPEND MARKDOWN_DOC ${CMAKE_CURRENT_LIST_DIR}/../readme.md)
|
||||
|
||||
CONFIGURE_FILE(Doxyfile.in Doxyfile @ONLY)
|
||||
CONFIGURE_FILE(Doxyfile.zh-cn.in Doxyfile.zh-cn @ONLY)
|
||||
@ -15,7 +15,7 @@ ELSE()
|
||||
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.zh-cn
|
||||
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/html
|
||||
DEPENDS ${MARKDOWN_DOC} ${SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile*
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../
|
||||
)
|
||||
|
||||
add_custom_target(doc ALL DEPENDS html)
|
||||
|
@ -143,11 +143,13 @@ public:
|
||||
|
||||
//! Deallocates all memory chunks, excluding the user-supplied buffer.
|
||||
void Clear() {
|
||||
while(chunkHead_ != 0 && chunkHead_ != userBuffer_) {
|
||||
while (chunkHead_ && chunkHead_ != userBuffer_) {
|
||||
ChunkHeader* next = chunkHead_->next;
|
||||
baseAllocator_->Free(chunkHead_);
|
||||
chunkHead_ = next;
|
||||
}
|
||||
if (chunkHead_ && chunkHead_ == userBuffer_)
|
||||
chunkHead_->size = 0; // Clear user buffer
|
||||
}
|
||||
|
||||
//! Computes the total capacity of allocated memory chunks.
|
||||
|
@ -844,6 +844,12 @@ public:
|
||||
template <typename SourceAllocator>
|
||||
const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; }
|
||||
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
//! Get a value from an object associated with name (string object).
|
||||
GenericValue& operator[](const std::basic_string<Ch>& name) { return (*this)[GenericValue(StringRef(name))]; }
|
||||
const GenericValue& operator[](const std::basic_string<Ch>& name) const { return (*this)[GenericValue(StringRef(name))]; }
|
||||
#endif
|
||||
|
||||
//! Const member iterator
|
||||
/*! \pre IsObject() == true */
|
||||
ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members); }
|
||||
@ -867,6 +873,18 @@ public:
|
||||
*/
|
||||
bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); }
|
||||
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
//! Check whether a member exists in the object with string object.
|
||||
/*!
|
||||
\param name Member name to be searched.
|
||||
\pre IsObject() == true
|
||||
\return Whether a member with that name exists.
|
||||
\note It is better to use FindMember() directly if you need the obtain the value as well.
|
||||
\note Linear time complexity.
|
||||
*/
|
||||
bool HasMember(const std::basic_string<Ch>& name) const { return FindMember(name) != MemberEnd(); }
|
||||
#endif
|
||||
|
||||
//! Check whether a member exists in the object with GenericValue name.
|
||||
/*!
|
||||
This version is faster because it does not need a StrLen(). It can also handle string with null character.
|
||||
@ -923,6 +941,18 @@ public:
|
||||
}
|
||||
template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
|
||||
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
//! Find member by string object name.
|
||||
/*!
|
||||
\param name Member name to be searched.
|
||||
\pre IsObject() == true
|
||||
\return Iterator to member, if it exists.
|
||||
Otherwise returns \ref MemberEnd().
|
||||
*/
|
||||
MemberIterator FindMember(const std::basic_string<Ch>& name) { return FindMember(StringRef(name)); }
|
||||
ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const { return FindMember(StringRef(name)); }
|
||||
#endif
|
||||
|
||||
//! Add a member (name-value pair) to the object.
|
||||
/*! \param name A string value as name of member.
|
||||
\param value Value of any type.
|
||||
@ -969,6 +999,22 @@ public:
|
||||
return AddMember(name, v, allocator);
|
||||
}
|
||||
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
//! Add a string object as member (name-value pair) to the object.
|
||||
/*! \param name A string value as name of member.
|
||||
\param value constant string reference as value of member.
|
||||
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
|
||||
\return The value itself for fluent API.
|
||||
\pre IsObject()
|
||||
\note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
|
||||
\note Amortized Constant time complexity.
|
||||
*/
|
||||
GenericValue& AddMember(GenericValue& name, std::basic_string<Ch>& value, Allocator& allocator) {
|
||||
GenericValue v(value, allocator);
|
||||
return AddMember(name, v, allocator);
|
||||
}
|
||||
#endif
|
||||
|
||||
//! Add any primitive value as member (name-value pair) to the object.
|
||||
/*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
|
||||
\param name A string value as name of member.
|
||||
@ -1087,6 +1133,10 @@ public:
|
||||
return RemoveMember(n);
|
||||
}
|
||||
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
bool RemoveMember(const std::basic_string<Ch>& name) { return RemoveMember(GenericValue(StringRef(name))); }
|
||||
#endif
|
||||
|
||||
template <typename SourceAllocator>
|
||||
bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) {
|
||||
MemberIterator m = FindMember(name);
|
||||
@ -1741,7 +1791,7 @@ public:
|
||||
template <unsigned parseFlags, typename SourceEncoding, typename InputStream>
|
||||
GenericDocument& ParseStream(InputStream& is) {
|
||||
ValueType::SetNull(); // Remove existing root if exist
|
||||
GenericReader<SourceEncoding, Encoding, Allocator> reader(&GetAllocator());
|
||||
GenericReader<SourceEncoding, Encoding, StackAllocator> reader(&stack_.GetAllocator());
|
||||
ClearStackOnExit scope(*this);
|
||||
parseResult_ = reader.template Parse<parseFlags>(is, *this);
|
||||
if (parseResult_) {
|
||||
|
@ -97,7 +97,7 @@ public:
|
||||
if (u == 1) return *this;
|
||||
if (*this == 1) return *this = u;
|
||||
|
||||
uint32_t k = 0;
|
||||
uint64_t k = 0;
|
||||
for (size_t i = 0; i < count_; i++) {
|
||||
const uint64_t c = digits_[i] >> 32;
|
||||
const uint64_t d = digits_[i] & 0xFFFFFFFF;
|
||||
@ -246,7 +246,7 @@ private:
|
||||
__extension__ typedef unsigned __int128 uint128;
|
||||
uint128 p = static_cast<uint128>(a) * static_cast<uint128>(b);
|
||||
p += k;
|
||||
*outHigh = p >> 64;
|
||||
*outHigh = static_cast<uint64_t>(p >> 64);
|
||||
return static_cast<uint64_t>(p);
|
||||
#else
|
||||
const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32;
|
||||
|
@ -45,7 +45,7 @@ struct DiyFp {
|
||||
uint64_t u64;
|
||||
} u = { d };
|
||||
|
||||
int biased_e = (u.u64 & kDpExponentMask) >> kDpSignificandSize;
|
||||
int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
|
||||
uint64_t significand = (u.u64 & kDpSignificandMask);
|
||||
if (biased_e != 0) {
|
||||
f = significand + kDpHiddenBit;
|
||||
@ -71,7 +71,7 @@ struct DiyFp {
|
||||
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
|
||||
__extension__ typedef unsigned __int128 uint128;
|
||||
uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f);
|
||||
uint64_t h = p >> 64;
|
||||
uint64_t h = static_cast<uint64_t>(p >> 64);
|
||||
uint64_t l = static_cast<uint64_t>(p);
|
||||
if (l & (uint64_t(1) << 63)) // rounding
|
||||
h++;
|
||||
|
@ -23,29 +23,29 @@ namespace internal {
|
||||
class Double {
|
||||
public:
|
||||
Double() {}
|
||||
Double(double d) : d(d) {}
|
||||
Double(uint64_t u) : u(u) {}
|
||||
Double(double d) : d_(d) {}
|
||||
Double(uint64_t u) : u_(u) {}
|
||||
|
||||
double Value() const { return d; }
|
||||
uint64_t Uint64Value() const { return u; }
|
||||
double Value() const { return d_; }
|
||||
uint64_t Uint64Value() const { return u_; }
|
||||
|
||||
double NextPositiveDouble() const {
|
||||
RAPIDJSON_ASSERT(!Sign());
|
||||
return Double(u + 1).Value();
|
||||
return Double(u_ + 1).Value();
|
||||
}
|
||||
|
||||
bool Sign() const { return (u & kSignMask) != 0; }
|
||||
uint64_t Significand() const { return u & kSignificandMask; }
|
||||
int Exponent() const { return ((u & kExponentMask) >> kSignificandSize) - kExponentBias; }
|
||||
bool Sign() const { return (u_ & kSignMask) != 0; }
|
||||
uint64_t Significand() const { return u_ & kSignificandMask; }
|
||||
int Exponent() const { return static_cast<int>(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); }
|
||||
|
||||
bool IsNan() const { return (u & kExponentMask) == kExponentMask && Significand() != 0; }
|
||||
bool IsInf() const { return (u & kExponentMask) == kExponentMask && Significand() == 0; }
|
||||
bool IsNormal() const { return (u & kExponentMask) != 0 || Significand() == 0; }
|
||||
bool IsZero() const { return (u & (kExponentMask | kSignificandMask)) == 0; }
|
||||
bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; }
|
||||
bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; }
|
||||
bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; }
|
||||
bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; }
|
||||
|
||||
uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); }
|
||||
int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
|
||||
uint64_t ToBias() const { return (u & kSignMask) ? ~u + 1 : u | kSignMask; }
|
||||
uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; }
|
||||
|
||||
static unsigned EffectiveSignificandSize(int order) {
|
||||
if (order >= -1021)
|
||||
@ -66,8 +66,8 @@ private:
|
||||
static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
|
||||
|
||||
union {
|
||||
double d;
|
||||
uint64_t u;
|
||||
double d_;
|
||||
uint64_t u_;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -191,8 +191,13 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
|
||||
DiyFp rounded(v.f >> precisionSize, v.e + precisionSize);
|
||||
const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
|
||||
const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
|
||||
if (precisionBits >= halfWay + error)
|
||||
if (precisionBits >= halfWay + error) {
|
||||
rounded.f++;
|
||||
if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340)
|
||||
rounded.f >>= 1;
|
||||
rounded.e++;
|
||||
}
|
||||
}
|
||||
|
||||
*result = rounded.ToDouble();
|
||||
|
||||
|
@ -69,7 +69,7 @@
|
||||
*/
|
||||
#define RAPIDJSON_MAJOR_VERSION 1
|
||||
#define RAPIDJSON_MINOR_VERSION 0
|
||||
#define RAPIDJSON_PATCH_VERSION 1
|
||||
#define RAPIDJSON_PATCH_VERSION 2
|
||||
#define RAPIDJSON_VERSION_STRING \
|
||||
RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION)
|
||||
|
||||
@ -241,8 +241,12 @@
|
||||
alignment. User can customize by defining the RAPIDJSON_ALIGN function macro.,
|
||||
*/
|
||||
#ifndef RAPIDJSON_ALIGN
|
||||
#if RAPIDJSON_64BIT == 1
|
||||
#define RAPIDJSON_ALIGN(x) ((x + 7u) & ~7u)
|
||||
#else
|
||||
#define RAPIDJSON_ALIGN(x) ((x + 3u) & ~3u)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// RAPIDJSON_UINT64_C2
|
||||
|
@ -1,6 +1,6 @@
|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
## A fast JSON parser/generator for C++ with both SAX/DOM style API
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
## 高效的C++ JSON解析/生成器,提供SAX及DOM风格API
|
||||
|
||||
|
@ -241,7 +241,7 @@ TEST(Document, UserBuffer) {
|
||||
char parseBuffer[1024];
|
||||
MemoryPoolAllocator<> valueAllocator(valueBuffer, sizeof(valueBuffer));
|
||||
MemoryPoolAllocator<> parseAllocator(parseBuffer, sizeof(parseBuffer));
|
||||
DocumentType doc(&valueAllocator, sizeof(parseBuffer), &parseAllocator);
|
||||
DocumentType doc(&valueAllocator, sizeof(parseBuffer) / 2, &parseAllocator);
|
||||
doc.Parse(" { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ");
|
||||
EXPECT_FALSE(doc.HasParseError());
|
||||
EXPECT_LE(valueAllocator.Size(), sizeof(valueBuffer));
|
||||
@ -276,7 +276,7 @@ TEST(Document, UTF16_Document) {
|
||||
GenericValue< UTF16<> >& s = v[L"created_at"];
|
||||
ASSERT_TRUE(s.IsString());
|
||||
|
||||
EXPECT_EQ(0, wcscmp(L"Wed Oct 30 17:13:20 +0000 2012", s.GetString()));
|
||||
EXPECT_EQ(0, memcmp(L"Wed Oct 30 17:13:20 +0000 2012", s.GetString(), (s.GetStringLength() + 1) * sizeof(wchar_t)));
|
||||
}
|
||||
|
||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
|
@ -193,7 +193,7 @@ static void TestParseDouble() {
|
||||
EXPECT_DOUBLE_EQ(x, h.actual_); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
TEST_DOUBLE(fullPrecision, "0.0", 0.0);
|
||||
TEST_DOUBLE(fullPrecision, "-0.0", -0.0); // For checking issue #289
|
||||
TEST_DOUBLE(fullPrecision, "1.0", 1.0);
|
||||
@ -327,15 +327,44 @@ static void TestParseDouble() {
|
||||
if (fullPrecision) {
|
||||
EXPECT_EQ(d.Uint64Value(), a.Uint64Value());
|
||||
if (d.Uint64Value() != a.Uint64Value())
|
||||
printf(" String: %sn Actual: %.17gnExpected: %.17gn", buffer, h.actual_, d.Value());
|
||||
printf(" String: %s\n Actual: %.17g\nExpected: %.17g\n", buffer, h.actual_, d.Value());
|
||||
}
|
||||
else {
|
||||
EXPECT_EQ(d.Sign(), a.Sign()); /* for 0.0 != -0.0 */
|
||||
EXPECT_EQ(d.Sign(), a.Sign()); // for 0.0 != -0.0
|
||||
EXPECT_DOUBLE_EQ(d.Value(), h.actual_);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Issue #340
|
||||
TEST_DOUBLE(fullPrecision, "7.450580596923828e-9", 7.450580596923828e-9);
|
||||
{
|
||||
internal::Double d(1.0);
|
||||
for (int i = 0; i < 324; i++) {
|
||||
char buffer[32];
|
||||
*internal::dtoa(d.Value(), buffer) = '\0';
|
||||
|
||||
StringStream s(buffer);
|
||||
ParseDoubleHandler h;
|
||||
Reader reader;
|
||||
ASSERT_EQ(kParseErrorNone, reader.Parse<fullPrecision ? kParseFullPrecisionFlag : 0>(s, h).Code());
|
||||
EXPECT_EQ(1u, h.step_);
|
||||
internal::Double a(h.actual_);
|
||||
if (fullPrecision) {
|
||||
EXPECT_EQ(d.Uint64Value(), a.Uint64Value());
|
||||
if (d.Uint64Value() != a.Uint64Value())
|
||||
printf(" String: %s\n Actual: %.17g\nExpected: %.17g\n", buffer, h.actual_, d.Value());
|
||||
}
|
||||
else {
|
||||
EXPECT_EQ(d.Sign(), a.Sign()); // for 0.0 != -0.0
|
||||
EXPECT_DOUBLE_EQ(d.Value(), h.actual_);
|
||||
}
|
||||
|
||||
|
||||
d = d.Value() * 0.5;
|
||||
}
|
||||
}
|
||||
#undef TEST_DOUBLE
|
||||
}
|
||||
|
||||
|
@ -957,6 +957,19 @@ TEST(Value, Object) {
|
||||
EXPECT_EQ(2u, o.MemberCount());
|
||||
}
|
||||
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
{
|
||||
// AddMember(StringRefType, const std::string&, Allocator)
|
||||
Value o(kObjectType);
|
||||
o.AddMember("b", std::string("Banana"), allocator);
|
||||
EXPECT_STREQ("Banana", o["b"].GetString());
|
||||
|
||||
// RemoveMember(const std::string&)
|
||||
o.RemoveMember(std::string("b"));
|
||||
EXPECT_TRUE(o.ObjectEmpty());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
// AddMember(GenericValue&&, ...) variants
|
||||
{
|
||||
@ -986,6 +999,10 @@ TEST(Value, Object) {
|
||||
EXPECT_TRUE(y.HasMember("A"));
|
||||
EXPECT_TRUE(y.HasMember("B"));
|
||||
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
EXPECT_TRUE(x.HasMember(std::string("A")));
|
||||
#endif
|
||||
|
||||
name.SetString("C\0D");
|
||||
EXPECT_TRUE(x.HasMember(name));
|
||||
EXPECT_TRUE(y.HasMember(name));
|
||||
@ -1009,6 +1026,11 @@ TEST(Value, Object) {
|
||||
EXPECT_STREQ("Banana", y["B"].GetString());
|
||||
EXPECT_STREQ("CherryD", y[C0D].GetString());
|
||||
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
EXPECT_STREQ("Apple", x["A"].GetString());
|
||||
EXPECT_STREQ("Apple", y[std::string("A")].GetString());
|
||||
#endif
|
||||
|
||||
// member iterator
|
||||
Value::MemberIterator itr = x.MemberBegin();
|
||||
EXPECT_TRUE(itr != x.MemberEnd());
|
||||
|
Loading…
x
Reference in New Issue
Block a user