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()')
This commit is contained in:
parent
ebbfaf1c13
commit
f6903f79d4
@ -209,36 +209,29 @@ struct StreamTraits {
|
||||
enum { copyOptimization = 0 };
|
||||
};
|
||||
|
||||
template<typename Stream, bool>
|
||||
template<typename Stream, bool = StreamTraits<Stream>::copyOptimization>
|
||||
class StreamLocalCopy;
|
||||
|
||||
template<typename Stream>
|
||||
class StreamLocalCopy<Stream, 1> {
|
||||
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<typename Stream>
|
||||
class StreamLocalCopy<Stream, 0> {
|
||||
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.
|
||||
|
@ -135,9 +135,11 @@ struct BaseReaderHandler {
|
||||
*/
|
||||
template<typename InputStream>
|
||||
void SkipWhitespace(InputStream& is) {
|
||||
StreamLocalCopy<InputStream, StreamTraits<InputStream>::copyOptimization> s(is);
|
||||
while (s->Peek() == ' ' || s->Peek() == '\n' || s->Peek() == '\r' || s->Peek() == '\t')
|
||||
s->Take();
|
||||
StreamLocalCopy<InputStream> 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<unsigned parseFlags, typename InputStream, typename Handler>
|
||||
void ParseString(InputStream& is, Handler& handler) {
|
||||
StreamLocalCopy<InputStream, StreamTraits<InputStream>::copyOptimization> s(is);
|
||||
StreamLocalCopy<InputStream> copy(is);
|
||||
InputStream& s(copy.s);
|
||||
|
||||
if (parseFlags & kParseInsituFlag) {
|
||||
Ch *head = s->PutBegin();
|
||||
ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(*s, *s);
|
||||
Ch *head = s.PutBegin();
|
||||
ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(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<parseFlags, SourceEncoding, TargetEncoding>(*s, stackStream);
|
||||
ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream);
|
||||
if (HasParseError())
|
||||
return;
|
||||
handler.String(stack_.template Pop<typename TargetEncoding::Ch>(stackStream.length_), stackStream.length_ - 1, true);
|
||||
@ -527,43 +531,45 @@ private:
|
||||
|
||||
template<unsigned parseFlags, typename InputStream, typename Handler>
|
||||
void ParseNumber(InputStream& is, Handler& handler) {
|
||||
StreamLocalCopy<InputStream, StreamTraits<InputStream>::copyOptimization> s(is);
|
||||
StreamLocalCopy<InputStream> 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<unsigned>(s->Take() - '0');
|
||||
else if (s.Peek() >= '1' && s.Peek() <= '9') {
|
||||
i = static_cast<unsigned>(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<unsigned>(s->Take() - '0');
|
||||
i = i * 10 + static_cast<unsigned>(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<unsigned>(s->Take() - '0');
|
||||
i = i * 10 + static_cast<unsigned>(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<unsigned>(s->Take() - '0');
|
||||
i64 = i64 * 10 + static_cast<unsigned>(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<unsigned>(s->Take() - '0');
|
||||
i64 = i64 * 10 + static_cast<unsigned>(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());
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user