From f6903f79d49eadfb257412b25ea19b3ecf492376 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Wed, 2 Jul 2014 20:51:10 +0200 Subject: [PATCH] GenericReader: simplify local stream copy optimization rapidjson.h: * StreamLocalCopy: add default argument to copy optimization selector based on StreamTraits of Stream parameter * drop operator->, operator* * make Stream (reference) member public * drop empty destructor reader.h: * add local references, initialized from "copy" (reverts algorithmic bodies back to plain 's.xx()') --- include/rapidjson/rapidjson.h | 23 +++----- include/rapidjson/reader.h | 98 +++++++++++++++++++---------------- 2 files changed, 60 insertions(+), 61 deletions(-) diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index 6e50293..c0175e1 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -209,36 +209,29 @@ struct StreamTraits { enum { copyOptimization = 0 }; }; -template +template::copyOptimization> class StreamLocalCopy; template class StreamLocalCopy { public: - StreamLocalCopy(Stream& original) : original_(original), s_(original) {} - ~StreamLocalCopy() { original_ = s_; } - Stream* operator->() { return &s_; } - Stream& operator*() { return s_; } + StreamLocalCopy(Stream& original) : s(original), original_(original) {} + ~StreamLocalCopy() { original_ = s; } + Stream s; //!< copy private: - StreamLocalCopy& operator=(const StreamLocalCopy&); - + StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; Stream& original_; - Stream s_; }; template class StreamLocalCopy { public: - StreamLocalCopy(Stream& original) : s_(original) {} - ~StreamLocalCopy() {} - Stream* operator->() { return &s_; } - Stream& operator*() { return s_; } + StreamLocalCopy(Stream& original) : s(original) {} + Stream& s; //!< reference private: - StreamLocalCopy& operator=(const StreamLocalCopy&); - - Stream& s_; + StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; }; //! Put N copies of a character to a stream. diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index 5add50b..d14a577 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -135,9 +135,11 @@ struct BaseReaderHandler { */ template void SkipWhitespace(InputStream& is) { - StreamLocalCopy::copyOptimization> s(is); - while (s->Peek() == ' ' || s->Peek() == '\n' || s->Peek() == '\r' || s->Peek() == '\t') - s->Take(); + StreamLocalCopy copy(is); + InputStream& s(copy.s); + + while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t') + s.Take(); } #ifdef RAPIDJSON_SSE42 @@ -448,19 +450,21 @@ private: // Parse string and generate String event. Different code paths for kParseInsituFlag. template void ParseString(InputStream& is, Handler& handler) { - StreamLocalCopy::copyOptimization> s(is); + StreamLocalCopy copy(is); + InputStream& s(copy.s); + if (parseFlags & kParseInsituFlag) { - Ch *head = s->PutBegin(); - ParseStringToStream(*s, *s); + Ch *head = s.PutBegin(); + ParseStringToStream(s, s); if (HasParseError()) return; - size_t length = s->PutEnd(head) - 1; + size_t length = s.PutEnd(head) - 1; RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); handler.String((typename TargetEncoding::Ch*)head, SizeType(length), false); } else { StackStream stackStream(stack_); - ParseStringToStream(*s, stackStream); + ParseStringToStream(s, stackStream); if (HasParseError()) return; handler.String(stack_.template Pop(stackStream.length_), stackStream.length_ - 1, true); @@ -527,43 +531,45 @@ private: template void ParseNumber(InputStream& is, Handler& handler) { - StreamLocalCopy::copyOptimization> s(is); + StreamLocalCopy copy(is); + InputStream& s(copy.s); + // Parse minus bool minus = false; - if (s->Peek() == '-') { + if (s.Peek() == '-') { minus = true; - s->Take(); + s.Take(); } // Parse int: zero / ( digit1-9 *DIGIT ) unsigned i; bool try64bit = false; - if (s->Peek() == '0') { + if (s.Peek() == '0') { i = 0; - s->Take(); + s.Take(); } - else if (s->Peek() >= '1' && s->Peek() <= '9') { - i = static_cast(s->Take() - '0'); + else if (s.Peek() >= '1' && s.Peek() <= '9') { + i = static_cast(s.Take() - '0'); if (minus) - while (s->Peek() >= '0' && s->Peek() <= '9') { + while (s.Peek() >= '0' && s.Peek() <= '9') { if (i >= 214748364) { // 2^31 = 2147483648 - if (i != 214748364 || s->Peek() > '8') { + if (i != 214748364 || s.Peek() > '8') { try64bit = true; break; } } - i = i * 10 + static_cast(s->Take() - '0'); + i = i * 10 + static_cast(s.Take() - '0'); } else - while (s->Peek() >= '0' && s->Peek() <= '9') { + while (s.Peek() >= '0' && s.Peek() <= '9') { if (i >= 429496729) { // 2^32 - 1 = 4294967295 - if (i != 429496729 || s->Peek() > '5') { + if (i != 429496729 || s.Peek() > '5') { try64bit = true; break; } } - i = i * 10 + static_cast(s->Take() - '0'); + i = i * 10 + static_cast(s.Take() - '0'); } } else @@ -575,22 +581,22 @@ private: if (try64bit) { i64 = i; if (minus) - while (s->Peek() >= '0' && s->Peek() <= '9') { + while (s.Peek() >= '0' && s.Peek() <= '9') { if (i64 >= UINT64_C(922337203685477580)) // 2^63 = 9223372036854775808 - if (i64 != UINT64_C(922337203685477580) || s->Peek() > '8') { + if (i64 != UINT64_C(922337203685477580) || s.Peek() > '8') { useDouble = true; break; } - i64 = i64 * 10 + static_cast(s->Take() - '0'); + i64 = i64 * 10 + static_cast(s.Take() - '0'); } else - while (s->Peek() >= '0' && s->Peek() <= '9') { + while (s.Peek() >= '0' && s.Peek() <= '9') { if (i64 >= UINT64_C(1844674407370955161)) // 2^64 - 1 = 18446744073709551615 - if (i64 != UINT64_C(1844674407370955161) || s->Peek() > '5') { + if (i64 != UINT64_C(1844674407370955161) || s.Peek() > '5') { useDouble = true; break; } - i64 = i64 * 10 + static_cast(s->Take() - '0'); + i64 = i64 * 10 + static_cast(s.Take() - '0'); } } @@ -598,59 +604,59 @@ private: double d = 0.0; if (useDouble) { d = (double)i64; - while (s->Peek() >= '0' && s->Peek() <= '9') { + while (s.Peek() >= '0' && s.Peek() <= '9') { if (d >= 1E307) RAPIDJSON_PARSE_ERROR(kParesErrorNumberTooBig, is.Tell()); - d = d * 10 + (s->Take() - '0'); + d = d * 10 + (s.Take() - '0'); } } // Parse frac = decimal-point 1*DIGIT int expFrac = 0; - if (s->Peek() == '.') { + if (s.Peek() == '.') { if (!useDouble) { d = try64bit ? (double)i64 : (double)i; useDouble = true; } - s->Take(); + s.Take(); - if (s->Peek() >= '0' && s->Peek() <= '9') { - d = d * 10 + (s->Take() - '0'); + if (s.Peek() >= '0' && s.Peek() <= '9') { + d = d * 10 + (s.Take() - '0'); --expFrac; } else RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, is.Tell()); - while (s->Peek() >= '0' && s->Peek() <= '9') { + while (s.Peek() >= '0' && s.Peek() <= '9') { if (expFrac > -16) { - d = d * 10 + (s->Peek() - '0'); + d = d * 10 + (s.Peek() - '0'); --expFrac; } - s->Take(); + s.Take(); } } // Parse exp = e [ minus / plus ] 1*DIGIT int exp = 0; - if (s->Peek() == 'e' || s->Peek() == 'E') { + if (s.Peek() == 'e' || s.Peek() == 'E') { if (!useDouble) { d = try64bit ? (double)i64 : (double)i; useDouble = true; } - s->Take(); + s.Take(); bool expMinus = false; - if (s->Peek() == '+') - s->Take(); - else if (s->Peek() == '-') { - s->Take(); + if (s.Peek() == '+') + s.Take(); + else if (s.Peek() == '-') { + s.Take(); expMinus = true; } - if (s->Peek() >= '0' && s->Peek() <= '9') { - exp = s->Take() - '0'; - while (s->Peek() >= '0' && s->Peek() <= '9') { - exp = exp * 10 + (s->Take() - '0'); + if (s.Peek() >= '0' && s.Peek() <= '9') { + exp = s.Take() - '0'; + while (s.Peek() >= '0' && s.Peek() <= '9') { + exp = exp * 10 + (s.Take() - '0'); if (exp > 308) RAPIDJSON_PARSE_ERROR(kParesErrorNumberTooBig, is.Tell()); }