Skip to content

Commit 3d5848a

Browse files
committed
Merge pull request #343 from miloyip/v1.0.2
V1.0.2
2 parents 1034587 + c5cbe97 commit 3d5848a

File tree

14 files changed

+145
-22
lines changed

14 files changed

+145
-22
lines changed

CHANGELOG.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,20 @@ This project adheres to [Semantic Versioning](http://semver.org/).
44

55
## [Unreleased]
66

7+
## [1.0.2] - 2015-05-14
8+
9+
### Added
10+
* Add Value::XXXMember(...) overloads for std::string (#335)
11+
12+
### Fixed
713
* Include rapidjson.h for all internal/error headers.
14+
* Parsing some numbers incorrectly in full-precision mode (`kFullPrecisionParseFlag`) (#342)
15+
* Fix alignment of 64bit platforms (#328)
16+
* Fix MemoryPoolAllocator::Clear() to clear user-buffer (0691502573f1afd3341073dd24b12c3db20fbde4)
17+
18+
### Changed
19+
* CMakeLists for include as a thirdparty in projects (#334, #337)
20+
* Change Document::ParseStream() to use stack allocator for Reader (ffbe38614732af8e0b3abdc8b50071f386a4a685)
821

922
## [1.0.1] - 2015-04-25
1023

@@ -60,6 +73,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
6073

6174
## 0.1 - 2011-11-18
6275

63-
[Unreleased]: https://github.com/miloyip/rapidjson/compare/v1.0.1...HEAD
76+
[Unreleased]: https://github.com/miloyip/rapidjson/compare/v1.0.2...HEAD
77+
[1.0.2]: https://github.com/miloyip/rapidjson/compare/v1.0.1...v1.0.2
6478
[1.0.1]: https://github.com/miloyip/rapidjson/compare/v1.0.0...v1.0.1
6579
[1.0.0]: https://github.com/miloyip/rapidjson/compare/v1.0-beta...v1.0.0

CMakeLists.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
2-
SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMakeModules)
2+
SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules)
33

44
PROJECT(RapidJSON CXX)
55

66
set(LIB_MAJOR_VERSION "1")
77
set(LIB_MINOR_VERSION "0")
8-
set(LIB_PATCH_VERSION "1")
8+
set(LIB_PATCH_VERSION "2")
99
set(LIB_VERSION_STRING "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_PATCH_VERSION}")
1010

1111
# compile in release with debug info mode by default
@@ -17,7 +17,7 @@ SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
1717
option(RAPIDJSON_BUILD_DOC "Build rapidjson documentation." ON)
1818
option(RAPIDJSON_BUILD_EXAMPLES "Build rapidjson examples." ON)
1919
option(RAPIDJSON_BUILD_TESTS "Build rapidjson perftests and unittests." ON)
20-
option(RAPIDJSON_BUILD_THIRDPARTY_GTEST
20+
option(RAPIDJSON_BUILD_THIRDPARTY_GTEST
2121
"Use gtest installation in `thirdparty/gtest` by default if available" OFF)
2222

2323
option(RAPIDJSON_HAS_STDSTRING "" OFF)
@@ -45,7 +45,7 @@ ELSEIF(WIN32)
4545
ENDIF()
4646
SET(CMAKE_INSTALL_DIR "${_CMAKE_INSTALL_DIR}" CACHE PATH "The directory cmake fiels are installed in")
4747

48-
include_directories(${CMAKE_SOURCE_DIR}/include)
48+
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
4949

5050
if(RAPIDJSON_BUILD_DOC)
5151
add_subdirectory(doc)

CMakeModules/FindGTestSrc.cmake

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

2-
SET(GTEST_SEARCH_PATH
2+
SET(GTEST_SEARCH_PATH
33
"${GTEST_SOURCE_DIR}"
4-
"${CMAKE_SOURCE_DIR}/thirdparty/gtest")
4+
"${CMAKE_CURRENT_LIST_DIR}/../thirdparty/gtest")
55

66
IF(UNIX)
77
IF(RAPIDJSON_BUILD_THIRDPARTY_GTEST)
@@ -15,6 +15,7 @@ FIND_PATH(GTEST_SOURCE_DIR
1515
NAMES CMakeLists.txt src/gtest_main.cc
1616
PATHS ${GTEST_SEARCH_PATH})
1717

18+
1819
# Debian installs gtest include directory in /usr/include, thus need to look
1920
# for include directory separately from source directory.
2021
FIND_PATH(GTEST_INCLUDE_DIR

appveyor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version: 1.0.1.{build}
1+
version: 1.0.2.{build}
22

33
configuration:
44
- Debug

doc/CMakeLists.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ find_package(Doxygen)
33
IF(NOT DOXYGEN_FOUND)
44
MESSAGE(STATUS "No Doxygen found. Documentation won't be built")
55
ELSE()
6-
file(GLOB SOURCES ${CMAKE_SOURCE_DIR}/include/*)
7-
file(GLOB MARKDOWN_DOC ${CMAKE_SOURCE_DIR}/doc/*.md)
8-
list(APPEND MARKDOWN_DOC ${CMAKE_SOURCE_DIR}/readme.md)
6+
file(GLOB SOURCES ${CMAKE_CURRENT_LIST_DIR}/../include/*)
7+
file(GLOB MARKDOWN_DOC ${CMAKE_CURRENT_LIST_DIR}/../doc/*.md)
8+
list(APPEND MARKDOWN_DOC ${CMAKE_CURRENT_LIST_DIR}/../readme.md)
99

1010
CONFIGURE_FILE(Doxyfile.in Doxyfile @ONLY)
1111
CONFIGURE_FILE(Doxyfile.zh-cn.in Doxyfile.zh-cn @ONLY)
@@ -15,7 +15,7 @@ ELSE()
1515
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.zh-cn
1616
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/html
1717
DEPENDS ${MARKDOWN_DOC} ${SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile*
18-
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
18+
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../
1919
)
2020

2121
add_custom_target(doc ALL DEPENDS html)

include/rapidjson/allocators.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,11 +143,13 @@ class MemoryPoolAllocator {
143143

144144
//! Deallocates all memory chunks, excluding the user-supplied buffer.
145145
void Clear() {
146-
while(chunkHead_ != 0 && chunkHead_ != userBuffer_) {
146+
while (chunkHead_ && chunkHead_ != userBuffer_) {
147147
ChunkHeader* next = chunkHead_->next;
148148
baseAllocator_->Free(chunkHead_);
149149
chunkHead_ = next;
150150
}
151+
if (chunkHead_ && chunkHead_ == userBuffer_)
152+
chunkHead_->size = 0; // Clear user buffer
151153
}
152154

153155
//! Computes the total capacity of allocated memory chunks.

include/rapidjson/document.h

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,12 @@ class GenericValue {
844844
template <typename SourceAllocator>
845845
const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; }
846846

847+
#if RAPIDJSON_HAS_STDSTRING
848+
//! Get a value from an object associated with name (string object).
849+
GenericValue& operator[](const std::basic_string<Ch>& name) { return (*this)[GenericValue(StringRef(name))]; }
850+
const GenericValue& operator[](const std::basic_string<Ch>& name) const { return (*this)[GenericValue(StringRef(name))]; }
851+
#endif
852+
847853
//! Const member iterator
848854
/*! \pre IsObject() == true */
849855
ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members); }
@@ -867,6 +873,18 @@ class GenericValue {
867873
*/
868874
bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); }
869875

876+
#if RAPIDJSON_HAS_STDSTRING
877+
//! Check whether a member exists in the object with string object.
878+
/*!
879+
\param name Member name to be searched.
880+
\pre IsObject() == true
881+
\return Whether a member with that name exists.
882+
\note It is better to use FindMember() directly if you need the obtain the value as well.
883+
\note Linear time complexity.
884+
*/
885+
bool HasMember(const std::basic_string<Ch>& name) const { return FindMember(name) != MemberEnd(); }
886+
#endif
887+
870888
//! Check whether a member exists in the object with GenericValue name.
871889
/*!
872890
This version is faster because it does not need a StrLen(). It can also handle string with null character.
@@ -923,6 +941,18 @@ class GenericValue {
923941
}
924942
template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
925943

944+
#if RAPIDJSON_HAS_STDSTRING
945+
//! Find member by string object name.
946+
/*!
947+
\param name Member name to be searched.
948+
\pre IsObject() == true
949+
\return Iterator to member, if it exists.
950+
Otherwise returns \ref MemberEnd().
951+
*/
952+
MemberIterator FindMember(const std::basic_string<Ch>& name) { return FindMember(StringRef(name)); }
953+
ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const { return FindMember(StringRef(name)); }
954+
#endif
955+
926956
//! Add a member (name-value pair) to the object.
927957
/*! \param name A string value as name of member.
928958
\param value Value of any type.
@@ -969,6 +999,22 @@ class GenericValue {
969999
return AddMember(name, v, allocator);
9701000
}
9711001

1002+
#if RAPIDJSON_HAS_STDSTRING
1003+
//! Add a string object as member (name-value pair) to the object.
1004+
/*! \param name A string value as name of member.
1005+
\param value constant string reference as value of member.
1006+
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
1007+
\return The value itself for fluent API.
1008+
\pre IsObject()
1009+
\note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
1010+
\note Amortized Constant time complexity.
1011+
*/
1012+
GenericValue& AddMember(GenericValue& name, std::basic_string<Ch>& value, Allocator& allocator) {
1013+
GenericValue v(value, allocator);
1014+
return AddMember(name, v, allocator);
1015+
}
1016+
#endif
1017+
9721018
//! Add any primitive value as member (name-value pair) to the object.
9731019
/*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
9741020
\param name A string value as name of member.
@@ -1087,6 +1133,10 @@ class GenericValue {
10871133
return RemoveMember(n);
10881134
}
10891135

1136+
#if RAPIDJSON_HAS_STDSTRING
1137+
bool RemoveMember(const std::basic_string<Ch>& name) { return RemoveMember(GenericValue(StringRef(name))); }
1138+
#endif
1139+
10901140
template <typename SourceAllocator>
10911141
bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) {
10921142
MemberIterator m = FindMember(name);
@@ -1741,7 +1791,7 @@ class GenericDocument : public GenericValue<Encoding, Allocator> {
17411791
template <unsigned parseFlags, typename SourceEncoding, typename InputStream>
17421792
GenericDocument& ParseStream(InputStream& is) {
17431793
ValueType::SetNull(); // Remove existing root if exist
1744-
GenericReader<SourceEncoding, Encoding, Allocator> reader(&GetAllocator());
1794+
GenericReader<SourceEncoding, Encoding, StackAllocator> reader(&stack_.GetAllocator());
17451795
ClearStackOnExit scope(*this);
17461796
parseResult_ = reader.template Parse<parseFlags>(is, *this);
17471797
if (parseResult_) {

include/rapidjson/internal/strtod.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,13 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
191191
DiyFp rounded(v.f >> precisionSize, v.e + precisionSize);
192192
const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
193193
const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
194-
if (precisionBits >= halfWay + error)
194+
if (precisionBits >= halfWay + error) {
195195
rounded.f++;
196+
if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340)
197+
rounded.f >>= 1;
198+
rounded.e++;
199+
}
200+
}
196201

197202
*result = rounded.ToDouble();
198203

include/rapidjson/rapidjson.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
*/
7070
#define RAPIDJSON_MAJOR_VERSION 1
7171
#define RAPIDJSON_MINOR_VERSION 0
72-
#define RAPIDJSON_PATCH_VERSION 1
72+
#define RAPIDJSON_PATCH_VERSION 2
7373
#define RAPIDJSON_VERSION_STRING \
7474
RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION)
7575

readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
![](doc/logo/rapidjson.png)
22

3-
![](https://img.shields.io/badge/release-v1.0.1-blue.png)
3+
![](https://img.shields.io/badge/release-v1.0.2-blue.png)
44

55
## A fast JSON parser/generator for C++ with both SAX/DOM style API
66

readme.zh-cn.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
![](doc/logo/rapidjson.png)
22

3-
![](https://img.shields.io/badge/release-v1.0.1-blue.png)
3+
![](https://img.shields.io/badge/release-v1.0.2-blue.png)
44

55
## 高效的C++ JSON解析/生成器,提供SAX及DOM风格API
66

test/unittest/documenttest.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ TEST(Document, UserBuffer) {
241241
char parseBuffer[1024];
242242
MemoryPoolAllocator<> valueAllocator(valueBuffer, sizeof(valueBuffer));
243243
MemoryPoolAllocator<> parseAllocator(parseBuffer, sizeof(parseBuffer));
244-
DocumentType doc(&valueAllocator, sizeof(parseBuffer), &parseAllocator);
244+
DocumentType doc(&valueAllocator, sizeof(parseBuffer) / 2, &parseAllocator);
245245
doc.Parse(" { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ");
246246
EXPECT_FALSE(doc.HasParseError());
247247
EXPECT_LE(valueAllocator.Size(), sizeof(valueBuffer));

test/unittest/readertest.cpp

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ static void TestParseDouble() {
193193
EXPECT_DOUBLE_EQ(x, h.actual_); \
194194
} \
195195
}
196-
196+
197197
TEST_DOUBLE(fullPrecision, "0.0", 0.0);
198198
TEST_DOUBLE(fullPrecision, "-0.0", -0.0); // For checking issue #289
199199
TEST_DOUBLE(fullPrecision, "1.0", 1.0);
@@ -327,15 +327,44 @@ static void TestParseDouble() {
327327
if (fullPrecision) {
328328
EXPECT_EQ(d.Uint64Value(), a.Uint64Value());
329329
if (d.Uint64Value() != a.Uint64Value())
330-
printf(" String: %sn Actual: %.17gnExpected: %.17gn", buffer, h.actual_, d.Value());
330+
printf(" String: %s\n Actual: %.17g\nExpected: %.17g\n", buffer, h.actual_, d.Value());
331331
}
332332
else {
333-
EXPECT_EQ(d.Sign(), a.Sign()); /* for 0.0 != -0.0 */
333+
EXPECT_EQ(d.Sign(), a.Sign()); // for 0.0 != -0.0
334334
EXPECT_DOUBLE_EQ(d.Value(), h.actual_);
335335
}
336336
}
337337
}
338338
}
339+
340+
// Issue #340
341+
TEST_DOUBLE(fullPrecision, "7.450580596923828e-9", 7.450580596923828e-9);
342+
{
343+
internal::Double d(1.0);
344+
for (int i = 0; i < 324; i++) {
345+
char buffer[32];
346+
*internal::dtoa(d.Value(), buffer) = '\0';
347+
348+
StringStream s(buffer);
349+
ParseDoubleHandler h;
350+
Reader reader;
351+
ASSERT_EQ(kParseErrorNone, reader.Parse<fullPrecision ? kParseFullPrecisionFlag : 0>(s, h).Code());
352+
EXPECT_EQ(1u, h.step_);
353+
internal::Double a(h.actual_);
354+
if (fullPrecision) {
355+
EXPECT_EQ(d.Uint64Value(), a.Uint64Value());
356+
if (d.Uint64Value() != a.Uint64Value())
357+
printf(" String: %s\n Actual: %.17g\nExpected: %.17g\n", buffer, h.actual_, d.Value());
358+
}
359+
else {
360+
EXPECT_EQ(d.Sign(), a.Sign()); // for 0.0 != -0.0
361+
EXPECT_DOUBLE_EQ(d.Value(), h.actual_);
362+
}
363+
364+
365+
d = d.Value() * 0.5;
366+
}
367+
}
339368
#undef TEST_DOUBLE
340369
}
341370

test/unittest/valuetest.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -957,6 +957,19 @@ TEST(Value, Object) {
957957
EXPECT_EQ(2u, o.MemberCount());
958958
}
959959

960+
#if RAPIDJSON_HAS_STDSTRING
961+
{
962+
// AddMember(StringRefType, const std::string&, Allocator)
963+
Value o(kObjectType);
964+
o.AddMember("b", std::string("Banana"), allocator);
965+
EXPECT_STREQ("Banana", o["b"].GetString());
966+
967+
// RemoveMember(const std::string&)
968+
o.RemoveMember(std::string("b"));
969+
EXPECT_TRUE(o.ObjectEmpty());
970+
}
971+
#endif
972+
960973
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
961974
// AddMember(GenericValue&&, ...) variants
962975
{
@@ -986,6 +999,10 @@ TEST(Value, Object) {
986999
EXPECT_TRUE(y.HasMember("A"));
9871000
EXPECT_TRUE(y.HasMember("B"));
9881001

1002+
#if RAPIDJSON_HAS_STDSTRING
1003+
EXPECT_TRUE(x.HasMember(std::string("A")));
1004+
#endif
1005+
9891006
name.SetString("C\0D");
9901007
EXPECT_TRUE(x.HasMember(name));
9911008
EXPECT_TRUE(y.HasMember(name));
@@ -1009,6 +1026,11 @@ TEST(Value, Object) {
10091026
EXPECT_STREQ("Banana", y["B"].GetString());
10101027
EXPECT_STREQ("CherryD", y[C0D].GetString());
10111028

1029+
#if RAPIDJSON_HAS_STDSTRING
1030+
EXPECT_STREQ("Apple", x["A"].GetString());
1031+
EXPECT_STREQ("Apple", y[std::string("A")].GetString());
1032+
#endif
1033+
10121034
// member iterator
10131035
Value::MemberIterator itr = x.MemberBegin();
10141036
EXPECT_TRUE(itr != x.MemberEnd());

0 commit comments

Comments
 (0)