diff --git a/doc/dom.zh-cn.md b/doc/dom.zh-cn.md
index d93f603..b709485 100644
--- a/doc/dom.zh-cn.md
+++ b/doc/dom.zh-cn.md
@@ -128,7 +128,7 @@ GenericDocument& GenericDocument::Parse(const Ch* str);
## 解析错误 {#ParseError}
-当解析过程顺利完成,`Document` 便会含有解析结果。当过程出现错误,原来的 DOM 会 * 维持不便 *。可使用 `bool HasParseError()`、`ParseErrorCode GetParseError()` 及 `size_t GetParseOffset()` 获取解析的错误状态。
+当解析过程顺利完成,`Document` 便会含有解析结果。当过程出现错误,原来的 DOM 会*维持不变*。可使用 `bool HasParseError()`、`ParseErrorCode GetParseError()` 及 `size_t GetParseOffset()` 获取解析的错误状态。
解析错误代号 | 描述
--------------------------------------------|---------------------------------------------------
diff --git a/doc/faq.zh-cn.md b/doc/faq.zh-cn.md
index ed100e1..f12d830 100644
--- a/doc/faq.zh-cn.md
+++ b/doc/faq.zh-cn.md
@@ -163,9 +163,9 @@
## Document/Value (DOM)
-1. 什么是转移语意?为什么?
+1. 什么是转移语义?为什么?
- `Value` 不用复制语意,而使用了转移语意。这是指,当把来源值赋值于目标值时,来源值的所有权会转移至目标值。
+ `Value` 不用复制语义,而使用了转移语义。这是指,当把来源值赋值于目标值时,来源值的所有权会转移至目标值。
由于转移快于复制,此设计决定强迫使用者注意到复制的消耗。
diff --git a/doc/schema.md b/doc/schema.md
index a83cebc..8b4195b 100644
--- a/doc/schema.md
+++ b/doc/schema.md
@@ -157,7 +157,7 @@ As `SchemaDocument` does not know how to resolve such URI, it needs a user-provi
~~~
class MyRemoteSchemaDocumentProvider : public IRemoteSchemaDocumentProvider {
public:
- virtual const SchemaDocument* GetRemoteDocument(const char* uri, SizeTyp length) {
+ virtual const SchemaDocument* GetRemoteDocument(const char* uri, SizeType length) {
// Resolve the uri and returns a pointer to that schema.
}
};
@@ -185,7 +185,7 @@ RapidJSON implemented a simple NFA regular expression engine, which is used by d
|Syntax|Description|
|------|-----------|
|`ab` | Concatenation |
-|`a|b` | Alternation |
+|a|b
| Alternation |
|`a?` | Zero or one |
|`a*` | Zero or more |
|`a+` | One or more |
@@ -202,7 +202,7 @@ RapidJSON implemented a simple NFA regular expression engine, which is used by d
|`[^abc]` | Negated character classes |
|`[^a-c]` | Negated character class range |
|`[\b]` | Backspace (U+0008) |
-|`\|`, `\\`, ... | Escape characters |
+|\\|
, `\\`, ... | Escape characters |
|`\f` | Form feed (U+000C) |
|`\n` | Line feed (U+000A) |
|`\r` | Carriage return (U+000D) |
diff --git a/doc/schema.zh-cn.md b/doc/schema.zh-cn.md
index a01c1b1..fa076de 100644
--- a/doc/schema.zh-cn.md
+++ b/doc/schema.zh-cn.md
@@ -157,7 +157,7 @@ JSON Schema 支持 [`$ref` 关键字](http://spacetelescope.github.io/understand
~~~
class MyRemoteSchemaDocumentProvider : public IRemoteSchemaDocumentProvider {
public:
- virtual const SchemaDocument* GetRemoteDocument(const char* uri, SizeTyp length) {
+ virtual const SchemaDocument* GetRemoteDocument(const char* uri, SizeType length) {
// Resolve the uri and returns a pointer to that schema.
}
};
@@ -185,7 +185,7 @@ RapidJSON 实现了一个简单的 NFA 正则表达式引擎,并预设使用
|语法|描述|
|------|-----------|
|`ab` | 串联 |
-|`a|b` | 交替 |
+|a|b
| 交替 |
|`a?` | 零或一次 |
|`a*` | 零或多次 |
|`a+` | 一或多次 |
@@ -202,7 +202,7 @@ RapidJSON 实现了一个简单的 NFA 正则表达式引擎,并预设使用
|`[^abc]` | 字符组取反 |
|`[^a-c]` | 字符组范围取反 |
|`[\b]` | 退格符 (U+0008) |
-|`\|`, `\\`, ... | 转义字符 |
+|\\|
, `\\`, ... | 转义字符 |
|`\f` | 馈页 (U+000C) |
|`\n` | 馈行 (U+000A) |
|`\r` | 回车 (U+000D) |
diff --git a/doc/tutorial.zh-cn.md b/doc/tutorial.zh-cn.md
index 61fb0b2..ec1315c 100644
--- a/doc/tutorial.zh-cn.md
+++ b/doc/tutorial.zh-cn.md
@@ -292,7 +292,7 @@ Value o(kObjectType);
Value a(kArrayType);
~~~~~~~~~~
-## 转移语意(Move Semantics) {#MoveSemantics}
+## 转移语义(Move Semantics) {#MoveSemantics}
在设计 RapidJSON 时有一个非常特别的决定,就是 Value 赋值并不是把来源 Value 复制至目的 Value,而是把把来源 Value 转移(move)至目的 Value。例如:
@@ -302,13 +302,13 @@ Value b(456);
b = a; // a 变成 Null,b 变成数字 123。
~~~~~~~~~~
-
+
-为什么?此语意有何优点?
+为什么?此语义有何优点?
最简单的答案就是性能。对于固定大小的 JSON 类型(Number、True、False、Null),复制它们是简单快捷。然而,对于可变大小的 JSON 类型(String、Array、Object),复制它们会产生大量开销,而且这些开销常常不被察觉。尤其是当我们需要创建临时 Object,把它复制至另一变量,然后再析构它。
-例如,若使用正常 * 复制 * 语意:
+例如,若使用正常 * 复制 * 语义:
~~~~~~~~~~cpp
Value o(kObjectType);
@@ -321,15 +321,15 @@ Value o(kObjectType);
}
~~~~~~~~~~
-
+
那个 `o` Object 需要分配一个和 contacts 相同大小的缓冲区,对 conacts 做深度复制,并最终要析构 contacts。这样会产生大量无必要的内存分配/释放,以及内存复制。
有一些方案可避免实质地复制这些数据,例如引用计数(reference counting)、垃圾回收(garbage collection, GC)。
-为了使 RapidJSON 简单及快速,我们选择了对赋值采用 * 转移 * 语意。这方法与 `std::auto_ptr` 相似,都是在赋值时转移拥有权。转移快得多简单得多,只需要析构原来的 Value,把来源 `memcpy()` 至目标,最后把来源设置为 Null 类型。
+为了使 RapidJSON 简单及快速,我们选择了对赋值采用 * 转移 * 语义。这方法与 `std::auto_ptr` 相似,都是在赋值时转移拥有权。转移快得多简单得多,只需要析构原来的 Value,把来源 `memcpy()` 至目标,最后把来源设置为 Null 类型。
-因此,使用转移语意后,上面的例子变成:
+因此,使用转移语义后,上面的例子变成:
~~~~~~~~~~cpp
Value o(kObjectType);
@@ -341,11 +341,11 @@ Value o(kObjectType);
}
~~~~~~~~~~
-
+
-在 C++11 中这称为转移赋值操作(move assignment operator)。由于 RapidJSON 支持 C++03,它在赋值操作采用转移语意,其它修改形函数如 `AddMember()`, `PushBack()` 也采用转移语意。
+在 C++11 中这称为转移赋值操作(move assignment operator)。由于 RapidJSON 支持 C++03,它在赋值操作采用转移语义,其它修改形函数如 `AddMember()`, `PushBack()` 也采用转移语义。
-### 转移语意及临时值 {#TemporaryValues}
+### 转移语义及临时值 {#TemporaryValues}
有时候,我们想直接构造一个 Value 并传递给一个“转移”函数(如 `PushBack()`、`AddMember()`)。由于临时对象是不能转换为正常的 Value 引用,我们加入了一个方便的 `Move()` 函数:
diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h
index 19f5a6a..f4dd25c 100644
--- a/include/rapidjson/document.h
+++ b/include/rapidjson/document.h
@@ -672,6 +672,9 @@ public:
//! Constructor for double value.
explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; }
+ //! Constructor for float value.
+ explicit GenericValue(float f) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = static_cast(f); data_.f.flags = kNumberDoubleFlag; }
+
//! Constructor for constant string (i.e. do not make a copy of string)
GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); }
@@ -1671,7 +1674,7 @@ public:
GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; }
GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; }
GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; }
- GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(f); return *this; }
+ GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(static_cast(f)); return *this; }
//@}
diff --git a/include/rapidjson/prettywriter.h b/include/rapidjson/prettywriter.h
index c6f0216..abd964f 100644
--- a/include/rapidjson/prettywriter.h
+++ b/include/rapidjson/prettywriter.h
@@ -22,6 +22,11 @@ RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
+#if defined(__clang__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(c++98-compat)
+#endif
+
RAPIDJSON_NAMESPACE_BEGIN
//! Combination of PrettyWriter format flags.
@@ -57,6 +62,11 @@ public:
explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ PrettyWriter(PrettyWriter&& rhs) :
+ Base(std::forward(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {}
+#endif
+
//! Set custom indentation.
/*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
\param indentCharCount Number of indent characters for each indentation level.
@@ -254,6 +264,10 @@ private:
RAPIDJSON_NAMESPACE_END
+#if defined(__clang__)
+RAPIDJSON_DIAG_POP
+#endif
+
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif
diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h
index 19f8849..e53bbd2 100644
--- a/include/rapidjson/reader.h
+++ b/include/rapidjson/reader.h
@@ -575,7 +575,7 @@ private:
}
}
else if (RAPIDJSON_LIKELY(Consume(is, '/')))
- while (is.Peek() != '\0' && is.Take() != '\n');
+ while (is.Peek() != '\0' && is.Take() != '\n') {}
else
RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
diff --git a/include/rapidjson/stringbuffer.h b/include/rapidjson/stringbuffer.h
index 78f34d2..4e38b82 100644
--- a/include/rapidjson/stringbuffer.h
+++ b/include/rapidjson/stringbuffer.h
@@ -78,8 +78,12 @@ public:
return stack_.template Bottom();
}
+ //! Get the size of string in bytes in the string buffer.
size_t GetSize() const { return stack_.GetSize(); }
+ //! Get the length of string in Ch in the string buffer.
+ size_t GetLength() const { return stack_.GetSize() / sizeof(Ch); }
+
static const size_t kDefaultCapacity = 256;
mutable internal::Stack stack_;
diff --git a/include/rapidjson/writer.h b/include/rapidjson/writer.h
index c5a3b98..8f6e174 100644
--- a/include/rapidjson/writer.h
+++ b/include/rapidjson/writer.h
@@ -42,6 +42,7 @@ RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_DIAG_OFF(unreachable-code)
+RAPIDJSON_DIAG_OFF(c++98-compat)
#endif
RAPIDJSON_NAMESPACE_BEGIN
@@ -103,6 +104,13 @@ public:
Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ Writer(Writer&& rhs) :
+ os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) {
+ rhs.os_ = 0;
+ }
+#endif
+
//! Reset the writer with a new stream.
/*!
This function reset the writer with a new stream and default settings,
diff --git a/test/unittest/prettywritertest.cpp b/test/unittest/prettywritertest.cpp
index a372f79..13d1a8d 100644
--- a/test/unittest/prettywritertest.cpp
+++ b/test/unittest/prettywritertest.cpp
@@ -18,6 +18,11 @@
#include "rapidjson/stringbuffer.h"
#include "rapidjson/filewritestream.h"
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(c++98-compat)
+#endif
+
using namespace rapidjson;
static const char kJson[] = "{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3,-1],\"u64\":1234567890123456789,\"i64\":-1234567890123456789}";
@@ -201,3 +206,30 @@ TEST(PrettyWriter, RawValue) {
"}",
buffer.GetString());
}
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+
+static PrettyWriter WriterGen(StringBuffer &target) {
+ PrettyWriter writer(target);
+ writer.StartObject();
+ writer.Key("a");
+ writer.Int(1);
+ return writer;
+}
+
+TEST(PrettyWriter, MoveCtor) {
+ StringBuffer buffer;
+ PrettyWriter writer(WriterGen(buffer));
+ writer.EndObject();
+ EXPECT_TRUE(writer.IsComplete());
+ EXPECT_STREQ(
+ "{\n"
+ " \"a\": 1\n"
+ "}",
+ buffer.GetString());
+}
+#endif
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif
diff --git a/test/unittest/stringbuffertest.cpp b/test/unittest/stringbuffertest.cpp
index ded513c..8a36102 100644
--- a/test/unittest/stringbuffertest.cpp
+++ b/test/unittest/stringbuffertest.cpp
@@ -26,6 +26,7 @@ using namespace rapidjson;
TEST(StringBuffer, InitialSize) {
StringBuffer buffer;
EXPECT_EQ(0u, buffer.GetSize());
+ EXPECT_EQ(0u, buffer.GetLength());
EXPECT_STREQ("", buffer.GetString());
}
@@ -34,14 +35,17 @@ TEST(StringBuffer, Put) {
buffer.Put('A');
EXPECT_EQ(1u, buffer.GetSize());
+ EXPECT_EQ(1u, buffer.GetLength());
EXPECT_STREQ("A", buffer.GetString());
}
TEST(StringBuffer, PutN_Issue672) {
GenericStringBuffer, MemoryPoolAllocator<> > buffer;
EXPECT_EQ(0, buffer.GetSize());
+ EXPECT_EQ(0, buffer.GetLength());
rapidjson::PutN(buffer, ' ', 1);
EXPECT_EQ(1, buffer.GetSize());
+ EXPECT_EQ(1, buffer.GetLength());
}
TEST(StringBuffer, Clear) {
@@ -52,6 +56,7 @@ TEST(StringBuffer, Clear) {
buffer.Clear();
EXPECT_EQ(0u, buffer.GetSize());
+ EXPECT_EQ(0u, buffer.GetLength());
EXPECT_STREQ("", buffer.GetString());
}
@@ -60,6 +65,7 @@ TEST(StringBuffer, Push) {
buffer.Push(5);
EXPECT_EQ(5u, buffer.GetSize());
+ EXPECT_EQ(5u, buffer.GetLength());
// Causes sudden expansion to make the stack's capacity equal to size
buffer.Push(65536u);
@@ -76,9 +82,19 @@ TEST(StringBuffer, Pop) {
buffer.Pop(3);
EXPECT_EQ(2u, buffer.GetSize());
+ EXPECT_EQ(2u, buffer.GetLength());
EXPECT_STREQ("AB", buffer.GetString());
}
+TEST(StringBuffer, GetLength_Issue744) {
+ GenericStringBuffer > buffer;
+ buffer.Put('A');
+ buffer.Put('B');
+ buffer.Put('C');
+ EXPECT_EQ(3u * sizeof(wchar_t), buffer.GetSize());
+ EXPECT_EQ(3u, buffer.GetLength());
+}
+
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
#if 0 // Many old compiler does not support these. Turn it off temporaily.
@@ -130,18 +146,23 @@ TEST(StringBuffer, MoveConstructor) {
x.Put('D');
EXPECT_EQ(4u, x.GetSize());
+ EXPECT_EQ(4u, x.GetLength());
EXPECT_STREQ("ABCD", x.GetString());
// StringBuffer y(x); // does not compile (!is_copy_constructible)
StringBuffer y(std::move(x));
EXPECT_EQ(0u, x.GetSize());
+ EXPECT_EQ(0u, x.GetLength());
EXPECT_EQ(4u, y.GetSize());
+ EXPECT_EQ(4u, y.GetLength());
EXPECT_STREQ("ABCD", y.GetString());
// StringBuffer z = y; // does not compile (!is_copy_assignable)
StringBuffer z = std::move(y);
EXPECT_EQ(0u, y.GetSize());
+ EXPECT_EQ(0u, y.GetLength());
EXPECT_EQ(4u, z.GetSize());
+ EXPECT_EQ(4u, z.GetLength());
EXPECT_STREQ("ABCD", z.GetString());
}
@@ -153,13 +174,14 @@ TEST(StringBuffer, MoveAssignment) {
x.Put('D');
EXPECT_EQ(4u, x.GetSize());
+ EXPECT_EQ(4u, x.GetLength());
EXPECT_STREQ("ABCD", x.GetString());
StringBuffer y;
// y = x; // does not compile (!is_copy_assignable)
y = std::move(x);
EXPECT_EQ(0u, x.GetSize());
- EXPECT_EQ(4u, y.GetSize());
+ EXPECT_EQ(4u, y.GetLength());
EXPECT_STREQ("ABCD", y.GetString());
}
diff --git a/test/unittest/writertest.cpp b/test/unittest/writertest.cpp
index 29f7626..d346e0f 100644
--- a/test/unittest/writertest.cpp
+++ b/test/unittest/writertest.cpp
@@ -20,6 +20,11 @@
#include "rapidjson/stringbuffer.h"
#include "rapidjson/memorybuffer.h"
+#ifdef __clang__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(c++98-compat)
+#endif
+
using namespace rapidjson;
TEST(Writer, Compact) {
@@ -495,3 +500,25 @@ TEST(Writer, RawValue) {
EXPECT_TRUE(writer.IsComplete());
EXPECT_STREQ("{\"a\":1,\"raw\":[\"Hello\\nWorld\", 123.456]}", buffer.GetString());
}
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+static Writer WriterGen(StringBuffer &target) {
+ Writer writer(target);
+ writer.StartObject();
+ writer.Key("a");
+ writer.Int(1);
+ return writer;
+}
+
+TEST(Writer, MoveCtor) {
+ StringBuffer buffer;
+ Writer writer(WriterGen(buffer));
+ writer.EndObject();
+ EXPECT_TRUE(writer.IsComplete());
+ EXPECT_STREQ("{\"a\":1}", buffer.GetString());
+}
+#endif
+
+#ifdef __clang__
+RAPIDJSON_DIAG_POP
+#endif