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;
// writer.h
template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator>
template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
class Writer;
// prettywriter.h
template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
class PrettyWriter;
// document.h
template <typename Encoding, typename Allocator>
......
......@@ -31,8 +31,8 @@ RAPIDJSON_NAMESPACE_BEGIN
\tparam TargetEncoding Encoding of output stream.
\tparam StackAllocator Type of allocator for allocating memory of stack.
*/
template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator>
class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> {
template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {
public:
typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
typedef typename Base::Ch Ch;
......@@ -42,9 +42,13 @@ public:
\param allocator User supplied allocator. If it is null, it will create a private one.
\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) {}
explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
//! 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.
......
......@@ -35,6 +35,26 @@ RAPIDJSON_DIAG_OFF(padded)
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
/*! Writer implements the concept Handler.
It generates JSON text by events to an output os.
......@@ -51,7 +71,7 @@ RAPIDJSON_NAMESPACE_BEGIN
\tparam StackAllocator Type of allocator for allocating memory of stack.
\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 {
public:
typedef typename SourceEncoding::Ch Ch;
......@@ -318,9 +338,10 @@ protected:
PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
}
}
else
if (RAPIDJSON_UNLIKELY(!(Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
return false;
else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
return false;
}
PutUnsafe(*os_, '\"');
return true;
......
......@@ -69,7 +69,10 @@ struct Foo {
Reader* reader;
// 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
Value* value;
......@@ -94,6 +97,7 @@ struct Foo {
#include "rapidjson/memorystream.h"
#include "rapidjson/document.h" // -> reader.h
#include "rapidjson/writer.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/schema.h" // -> pointer.h
Foo::Foo() :
......@@ -139,6 +143,9 @@ Foo::Foo() :
// writer.h
writer(RAPIDJSON_NEW((Writer<StringBuffer>))),
// prettywriter.h
prettywriter(RAPIDJSON_NEW((PrettyWriter<StringBuffer>))),
// document.h
value(RAPIDJSON_NEW(Value)),
document(RAPIDJSON_NEW(Document)),
......@@ -196,6 +203,9 @@ Foo::~Foo() {
// writer.h
RAPIDJSON_DELETE(writer);
// prettywriter.h
RAPIDJSON_DELETE(prettywriter);
// document.h
RAPIDJSON_DELETE(value);
RAPIDJSON_DELETE(document);
......
......@@ -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) {
// {]
{
......
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