Commit 3c2c1628 authored by Milo Yip's avatar Milo Yip

Merge pull request #534 from miloyip/issue325

Add encoding validation option for Writer/PrettyWriter
parents 7e383864 964d89e3
...@@ -91,9 +91,14 @@ typedef GenericReader<UTF8<char>, UTF8<char>, CrtAllocator> Reader; ...@@ -91,9 +91,14 @@ typedef GenericReader<UTF8<char>, UTF8<char>, CrtAllocator> Reader;
// writer.h // writer.h
template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator> template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
class Writer; class Writer;
// prettywriter.h
template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
class PrettyWriter;
// document.h // document.h
template <typename Encoding, typename Allocator> template <typename Encoding, typename Allocator>
......
...@@ -31,8 +31,8 @@ RAPIDJSON_NAMESPACE_BEGIN ...@@ -31,8 +31,8 @@ RAPIDJSON_NAMESPACE_BEGIN
\tparam TargetEncoding Encoding of output stream. \tparam TargetEncoding Encoding of output stream.
\tparam StackAllocator Type of allocator for allocating memory of stack. \tparam StackAllocator Type of allocator for allocating memory of stack.
*/ */
template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator> template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> { class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {
public: public:
typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base; typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
typedef typename Base::Ch Ch; typedef typename Base::Ch Ch;
...@@ -42,9 +42,13 @@ public: ...@@ -42,9 +42,13 @@ public:
\param allocator User supplied allocator. If it is null, it will create a private one. \param allocator User supplied allocator. If it is null, it will create a private one.
\param levelDepth Initial capacity of stack. \param levelDepth Initial capacity of stack.
*/ */
PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
//! Set custom indentation. //! Set custom indentation.
/*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r'). /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
\param indentCharCount Number of indent characters for each indentation level. \param indentCharCount Number of indent characters for each indentation level.
......
...@@ -35,6 +35,26 @@ RAPIDJSON_DIAG_OFF(padded) ...@@ -35,6 +35,26 @@ RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
///////////////////////////////////////////////////////////////////////////////
// WriteFlag
/*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS
\ingroup RAPIDJSON_CONFIG
\brief User-defined kWriteDefaultFlags definition.
User can define this as any \c WriteFlag combinations.
*/
#ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
#define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
#endif
//! Combination of writeFlags
enum WriteFlag {
kWriteNoFlags = 0, //!< No flags are set.
kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings.
kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS
};
//! JSON writer //! JSON writer
/*! Writer implements the concept Handler. /*! Writer implements the concept Handler.
It generates JSON text by events to an output os. It generates JSON text by events to an output os.
...@@ -51,7 +71,7 @@ RAPIDJSON_NAMESPACE_BEGIN ...@@ -51,7 +71,7 @@ RAPIDJSON_NAMESPACE_BEGIN
\tparam StackAllocator Type of allocator for allocating memory of stack. \tparam StackAllocator Type of allocator for allocating memory of stack.
\note implements Handler concept \note implements Handler concept
*/ */
template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator> template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
class Writer { class Writer {
public: public:
typedef typename SourceEncoding::Ch Ch; typedef typename SourceEncoding::Ch Ch;
...@@ -318,9 +338,10 @@ protected: ...@@ -318,9 +338,10 @@ protected:
PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]); PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
} }
} }
else else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
if (RAPIDJSON_UNLIKELY(!(Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_)))) Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
return false; Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
return false;
} }
PutUnsafe(*os_, '\"'); PutUnsafe(*os_, '\"');
return true; return true;
......
...@@ -69,7 +69,10 @@ struct Foo { ...@@ -69,7 +69,10 @@ struct Foo {
Reader* reader; Reader* reader;
// writer.h // writer.h
Writer<StringBuffer, UTF8<char>, UTF8<char>, CrtAllocator>* writer; Writer<StringBuffer, UTF8<char>, UTF8<char>, CrtAllocator, 0>* writer;
// prettywriter.h
PrettyWriter<StringBuffer, UTF8<char>, UTF8<char>, CrtAllocator, 0>* prettywriter;
// document.h // document.h
Value* value; Value* value;
...@@ -94,6 +97,7 @@ struct Foo { ...@@ -94,6 +97,7 @@ struct Foo {
#include "rapidjson/memorystream.h" #include "rapidjson/memorystream.h"
#include "rapidjson/document.h" // -> reader.h #include "rapidjson/document.h" // -> reader.h
#include "rapidjson/writer.h" #include "rapidjson/writer.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/schema.h" // -> pointer.h #include "rapidjson/schema.h" // -> pointer.h
Foo::Foo() : Foo::Foo() :
...@@ -139,6 +143,9 @@ Foo::Foo() : ...@@ -139,6 +143,9 @@ Foo::Foo() :
// writer.h // writer.h
writer(RAPIDJSON_NEW((Writer<StringBuffer>))), writer(RAPIDJSON_NEW((Writer<StringBuffer>))),
// prettywriter.h
prettywriter(RAPIDJSON_NEW((PrettyWriter<StringBuffer>))),
// document.h // document.h
value(RAPIDJSON_NEW(Value)), value(RAPIDJSON_NEW(Value)),
document(RAPIDJSON_NEW(Document)), document(RAPIDJSON_NEW(Document)),
...@@ -196,6 +203,9 @@ Foo::~Foo() { ...@@ -196,6 +203,9 @@ Foo::~Foo() {
// writer.h // writer.h
RAPIDJSON_DELETE(writer); RAPIDJSON_DELETE(writer);
// prettywriter.h
RAPIDJSON_DELETE(prettywriter);
// document.h // document.h
RAPIDJSON_DELETE(value); RAPIDJSON_DELETE(value);
RAPIDJSON_DELETE(document); RAPIDJSON_DELETE(document);
......
...@@ -347,6 +347,31 @@ TEST(Writer, InvalidEncoding) { ...@@ -347,6 +347,31 @@ TEST(Writer, InvalidEncoding) {
} }
} }
TEST(Writer, ValidateEncoding) {
{
StringBuffer buffer;
Writer<StringBuffer, UTF8<>, UTF8<>, CrtAllocator, kWriteValidateEncodingFlag> writer(buffer);
writer.StartArray();
EXPECT_TRUE(writer.String("\x24")); // Dollar sign U+0024
EXPECT_TRUE(writer.String("\xC2\xA2")); // Cents sign U+00A2
EXPECT_TRUE(writer.String("\xE2\x82\xAC")); // Euro sign U+20AC
EXPECT_TRUE(writer.String("\xF0\x9D\x84\x9E")); // G clef sign U+1D11E
writer.EndArray();
EXPECT_STREQ("[\"\x24\",\"\xC2\xA2\",\"\xE2\x82\xAC\",\"\xF0\x9D\x84\x9E\"]", buffer.GetString());
}
// Fail in decoding invalid UTF-8 sequence http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
{
StringBuffer buffer;
Writer<StringBuffer, UTF8<>, UTF8<>, CrtAllocator, kWriteValidateEncodingFlag> writer(buffer);
writer.StartArray();
EXPECT_FALSE(writer.String("\xfe"));
EXPECT_FALSE(writer.String("\xff"));
EXPECT_FALSE(writer.String("\xfe\xfe\xff\xff"));
writer.EndArray();
}
}
TEST(Writer, InvalidEventSequence) { TEST(Writer, InvalidEventSequence) {
// {] // {]
{ {
......
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