Add stream copying optimization switch depending stream type.
An unit test is added
This commit is contained in:
parent
6f7d6642ef
commit
bcf7cee788
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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_);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user