Commit bcf7cee7 authored by Milo Yip's avatar Milo Yip

Add stream copying optimization switch depending stream type.

An unit test is added
parent 6f7d6642
......@@ -69,6 +69,11 @@ private:
bool eof_;
};
template<>
struct StreamTraits<FileReadStream> {
typedef FileReadStream StreamCopyType; // Enable stream copy optimization.
};
} // namespace rapidjson
#endif // RAPIDJSON_FILESTREAM_H_
......@@ -193,6 +193,24 @@ concept Stream {
\endcode
*/
//! Provides additional information for stream.
/*!
By using traits pattern, this type provides a default configuration for stream.
For custom stream, this type can be specialized for other configuration.
See TEST(Reader, CustomStringStream) in readertest.cpp for example.
*/
template<typename Stream>
struct StreamTraits {
//! Whether to make local copy of stream for optimization during parsing.
/*!
If it is defined as Stream&, it will not make a local copy.
If it is defined as Stream, it will make a local copy for optimization.
By default, for safety, streams do not use local copy optimization, i.e. it is defined as Stream&.
Stream that can be copied fast should specialize this, like StreamTraits<StringStream>.
*/
typedef Stream& StreamCopyType;
};
//! Put N copies of a character to a stream.
template<typename Stream, typename Ch>
inline void PutN(Stream& stream, Ch c, size_t n) {
......@@ -225,6 +243,11 @@ struct GenericStringStream {
const Ch* head_; //!< Original head of the string.
};
template <typename Encoding>
struct StreamTraits<GenericStringStream<Encoding>> {
typedef GenericStringStream<Encoding> StreamCopyType; // Enable stream copy optimization.
};
typedef GenericStringStream<UTF8<> > StringStream;
///////////////////////////////////////////////////////////////////////////////
......@@ -256,6 +279,11 @@ struct GenericInsituStringStream {
Ch* head_;
};
template <typename Encoding>
struct StreamTraits<GenericInsituStringStream<Encoding>> {
typedef GenericInsituStringStream<Encoding> StreamCopyType; // Enable stream copy optimization.
};
typedef GenericInsituStringStream<UTF8<> > InsituStringStream;
///////////////////////////////////////////////////////////////////////////////
......
......@@ -109,7 +109,7 @@ struct BaseReaderHandler {
*/
template<typename InputStream>
void SkipWhitespace(InputStream& is) {
InputStream s = is; // Use a local copy for optimization
StreamTraits<InputStream>::StreamCopyType s = is; // Use a local copy for optimization
while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t')
s.Take();
is = s;
......@@ -378,7 +378,7 @@ private:
// Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
template<typename InputStream>
unsigned ParseHex4(InputStream& is) {
InputStream s = is; // Use a local copy for optimization
StreamTraits<InputStream>::StreamCopyType s = is; // Use a local copy for optimization
unsigned codepoint = 0;
for (int i = 0; i < 4; i++) {
Ch c = s.Take();
......@@ -419,7 +419,7 @@ private:
// Parse string and generate String event. Different code paths for kParseInsituFlag.
template<unsigned parseFlags, typename InputStream, typename Handler>
void ParseString(InputStream& is, Handler& handler) {
InputStream s = is; // Local copy for optimization
StreamTraits<InputStream>::StreamCopyType s = is; // Local copy for optimization
if (parseFlags & kParseInsituFlag) {
Ch *head = s.PutBegin();
ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s);
......@@ -499,7 +499,7 @@ private:
template<unsigned parseFlags, typename InputStream, typename Handler>
void ParseNumber(InputStream& is, Handler& handler) {
InputStream s = is; // Local copy for optimization
StreamTraits<InputStream>::StreamCopyType s = is; // Local copy for optimization
// Parse minus
bool minus = false;
if (s.Peek() == '-') {
......
......@@ -592,4 +592,52 @@ TEST(Reader, SkipWhitespace) {
SkipWhitespace(ss);
EXPECT_EQ(expected[i], ss.Take());
}
}
\ No newline at end of file
}
// Test implementing a stream without copy stream optimization.
// Clone from GenericStringStream except that copy constructor is disabled.
template <typename Encoding>
class CustomStringStream {
public:
typedef typename Encoding::Ch Ch;
CustomStringStream(const Ch *src) : src_(src), head_(src) {}
Ch Peek() const { return *src_; }
Ch Take() { return *src_++; }
size_t Tell() const { return static_cast<size_t>(src_ - head_); }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
void Put(Ch) { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
private:
// Not support copy constructor.
CustomStringStream(const CustomStringStream&);
const Ch* src_; //!< Current read position.
const Ch* head_; //!< Original head of the string.
};
// If the following code is compiled, it should generate compilation error as predicted.
// Because CustomStringStream<> is not copyable via making copy constructor private.
#if 0
namespace rapidjson {
template <typename Encoding>
struct StreamTraits<CustomStringStream<Encoding>> {
typedef CustomStringStream<Encoding> StreamCopyType;
};
} // namespace rapdijson
#endif
TEST(Reader, CustomStringStream) {
const char* json = "{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] } ";
CustomStringStream<UTF8<char>> s(json);
ParseObjectHandler h;
Reader reader;
reader.ParseObject<0>(s, h);
EXPECT_EQ(20u, h.step_);
}
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