Merge pull request #589 from jnicholls/rawnumber
RawNumber Improvements / Clang Test Fix / Whitespace Cleanup
This commit is contained in:
commit
62a9a6b0d8
@ -1,5 +1,5 @@
|
|||||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
@ -7,9 +7,9 @@
|
|||||||
//
|
//
|
||||||
// http://opensource.org/licenses/MIT
|
// http://opensource.org/licenses/MIT
|
||||||
//
|
//
|
||||||
// Unless required by applicable law or agreed to in writing, software distributed
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// specific language governing permissions and limitations under the License.
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
#ifndef RAPIDJSON_READER_H_
|
#ifndef RAPIDJSON_READER_H_
|
||||||
@ -127,7 +127,7 @@ RAPIDJSON_NAMESPACE_BEGIN
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// ParseFlag
|
// ParseFlag
|
||||||
|
|
||||||
/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS
|
/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS
|
||||||
\ingroup RAPIDJSON_CONFIG
|
\ingroup RAPIDJSON_CONFIG
|
||||||
\brief User-defined kParseDefaultFlags definition.
|
\brief User-defined kParseDefaultFlags definition.
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ enum ParseFlag {
|
|||||||
|
|
||||||
/*! \class rapidjson::Handler
|
/*! \class rapidjson::Handler
|
||||||
\brief Concept for receiving events from GenericReader upon parsing.
|
\brief Concept for receiving events from GenericReader upon parsing.
|
||||||
The functions return true if no error occurs. If they return false,
|
The functions return true if no error occurs. If they return false,
|
||||||
the event publisher should terminate the process.
|
the event publisher should terminate the process.
|
||||||
\code
|
\code
|
||||||
concept Handler {
|
concept Handler {
|
||||||
@ -425,7 +425,7 @@ inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
|
|||||||
|
|
||||||
#ifdef RAPIDJSON_SIMD
|
#ifdef RAPIDJSON_SIMD
|
||||||
//! Template function specialization for InsituStringStream
|
//! Template function specialization for InsituStringStream
|
||||||
template<> inline void SkipWhitespace(InsituStringStream& is) {
|
template<> inline void SkipWhitespace(InsituStringStream& is) {
|
||||||
is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
|
is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,17 +443,17 @@ template<> inline void SkipWhitespace(EncodedInputStream<UTF8<>, MemoryStream>&
|
|||||||
// GenericReader
|
// GenericReader
|
||||||
|
|
||||||
//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator.
|
//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator.
|
||||||
/*! GenericReader parses JSON text from a stream, and send events synchronously to an
|
/*! GenericReader parses JSON text from a stream, and send events synchronously to an
|
||||||
object implementing Handler concept.
|
object implementing Handler concept.
|
||||||
|
|
||||||
It needs to allocate a stack for storing a single decoded string during
|
It needs to allocate a stack for storing a single decoded string during
|
||||||
non-destructive parsing.
|
non-destructive parsing.
|
||||||
|
|
||||||
For in-situ parsing, the decoded string is directly written to the source
|
For in-situ parsing, the decoded string is directly written to the source
|
||||||
text string, no temporary buffer is required.
|
text string, no temporary buffer is required.
|
||||||
|
|
||||||
A GenericReader object can be reused for parsing multiple JSON text.
|
A GenericReader object can be reused for parsing multiple JSON text.
|
||||||
|
|
||||||
\tparam SourceEncoding Encoding of the input stream.
|
\tparam SourceEncoding Encoding of the input stream.
|
||||||
\tparam TargetEncoding Encoding of the parse output.
|
\tparam TargetEncoding Encoding of the parse output.
|
||||||
\tparam StackAllocator Allocator type for stack.
|
\tparam StackAllocator Allocator type for stack.
|
||||||
@ -525,7 +525,7 @@ public:
|
|||||||
|
|
||||||
//! Whether a parse error has occured in the last parsing.
|
//! Whether a parse error has occured in the last parsing.
|
||||||
bool HasParseError() const { return parseResult_.IsError(); }
|
bool HasParseError() const { return parseResult_.IsError(); }
|
||||||
|
|
||||||
//! Get the \ref ParseErrorCode of last parsing.
|
//! Get the \ref ParseErrorCode of last parsing.
|
||||||
ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); }
|
ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); }
|
||||||
|
|
||||||
@ -585,7 +585,7 @@ private:
|
|||||||
void ParseObject(InputStream& is, Handler& handler) {
|
void ParseObject(InputStream& is, Handler& handler) {
|
||||||
RAPIDJSON_ASSERT(is.Peek() == '{');
|
RAPIDJSON_ASSERT(is.Peek() == '{');
|
||||||
is.Take(); // Skip '{'
|
is.Take(); // Skip '{'
|
||||||
|
|
||||||
if (RAPIDJSON_UNLIKELY(!handler.StartObject()))
|
if (RAPIDJSON_UNLIKELY(!handler.StartObject()))
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
||||||
|
|
||||||
@ -628,12 +628,12 @@ private:
|
|||||||
SkipWhitespaceAndComments<parseFlags>(is);
|
SkipWhitespaceAndComments<parseFlags>(is);
|
||||||
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
||||||
break;
|
break;
|
||||||
case '}':
|
case '}':
|
||||||
is.Take();
|
is.Take();
|
||||||
if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
|
if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
|
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -654,10 +654,10 @@ private:
|
|||||||
void ParseArray(InputStream& is, Handler& handler) {
|
void ParseArray(InputStream& is, Handler& handler) {
|
||||||
RAPIDJSON_ASSERT(is.Peek() == '[');
|
RAPIDJSON_ASSERT(is.Peek() == '[');
|
||||||
is.Take(); // Skip '['
|
is.Take(); // Skip '['
|
||||||
|
|
||||||
if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
|
if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
||||||
|
|
||||||
SkipWhitespaceAndComments<parseFlags>(is);
|
SkipWhitespaceAndComments<parseFlags>(is);
|
||||||
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
|
||||||
|
|
||||||
@ -780,7 +780,7 @@ private:
|
|||||||
*stack_.template Push<Ch>() = c;
|
*stack_.template Push<Ch>() = c;
|
||||||
++length_;
|
++length_;
|
||||||
}
|
}
|
||||||
|
|
||||||
RAPIDJSON_FORCEINLINE void* Push(SizeType count) {
|
RAPIDJSON_FORCEINLINE void* Push(SizeType count) {
|
||||||
length_ += count;
|
length_ += count;
|
||||||
return stack_.template Push<Ch>(count);
|
return stack_.template Push<Ch>(count);
|
||||||
@ -838,10 +838,10 @@ private:
|
|||||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||||
#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
static const char escape[256] = {
|
static const char escape[256] = {
|
||||||
Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/',
|
Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/',
|
||||||
Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
|
Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
|
||||||
0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
|
0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
|
||||||
0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
|
Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
|
||||||
};
|
};
|
||||||
#undef Z16
|
#undef Z16
|
||||||
@ -893,8 +893,8 @@ private:
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
size_t offset = is.Tell();
|
size_t offset = is.Tell();
|
||||||
if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ?
|
if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ?
|
||||||
!Transcoder<SEncoding, TEncoding>::Validate(is, os) :
|
!Transcoder<SEncoding, TEncoding>::Validate(is, os) :
|
||||||
!Transcoder<SEncoding, TEncoding>::Transcode(is, os))))
|
!Transcoder<SEncoding, TEncoding>::Transcode(is, os))))
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset);
|
RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset);
|
||||||
}
|
}
|
||||||
@ -954,7 +954,7 @@ private:
|
|||||||
}
|
}
|
||||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s);
|
_mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
is.src_ = p;
|
is.src_ = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -977,7 +977,7 @@ private:
|
|||||||
if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
|
if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
|
||||||
is.src_ = p;
|
is.src_ = p;
|
||||||
is.dst_ = q;
|
is.dst_ = q;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
*q++ = *p++;
|
*q++ = *p++;
|
||||||
@ -1063,11 +1063,11 @@ private:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<typename InputStream, bool backup>
|
template<typename InputStream, bool backup, bool pushOnTake>
|
||||||
class NumberStream;
|
class NumberStream;
|
||||||
|
|
||||||
template<typename InputStream>
|
template<typename InputStream>
|
||||||
class NumberStream<InputStream, false> {
|
class NumberStream<InputStream, false, false> {
|
||||||
public:
|
public:
|
||||||
typedef typename InputStream::Ch Ch;
|
typedef typename InputStream::Ch Ch;
|
||||||
|
|
||||||
@ -1090,10 +1090,10 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename InputStream>
|
template<typename InputStream>
|
||||||
class NumberStream<InputStream, true> : public NumberStream<InputStream, false> {
|
class NumberStream<InputStream, true, false> : public NumberStream<InputStream, false, false> {
|
||||||
typedef NumberStream<InputStream, false> Base;
|
typedef NumberStream<InputStream, false, false> Base;
|
||||||
public:
|
public:
|
||||||
NumberStream(GenericReader& reader, InputStream& is) : NumberStream<InputStream, false>(reader, is), stackStream(reader.stack_) {}
|
NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {}
|
||||||
~NumberStream() {}
|
~NumberStream() {}
|
||||||
|
|
||||||
RAPIDJSON_FORCEINLINE Ch TakePush() {
|
RAPIDJSON_FORCEINLINE Ch TakePush() {
|
||||||
@ -1101,9 +1101,9 @@ private:
|
|||||||
return Base::is.Take();
|
return Base::is.Take();
|
||||||
}
|
}
|
||||||
|
|
||||||
RAPIDJSON_FORCEINLINE void Push(char c) {
|
RAPIDJSON_FORCEINLINE void Push(char c) {
|
||||||
stackStream.Put(c);
|
stackStream.Put(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Length() { return stackStream.Length(); }
|
size_t Length() { return stackStream.Length(); }
|
||||||
|
|
||||||
@ -1116,13 +1116,25 @@ private:
|
|||||||
StackStream<char> stackStream;
|
StackStream<char> stackStream;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename InputStream>
|
||||||
|
class NumberStream<InputStream, true, true> : public NumberStream<InputStream, true, false> {
|
||||||
|
typedef NumberStream<InputStream, true, false> Base;
|
||||||
|
public:
|
||||||
|
NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {}
|
||||||
|
~NumberStream() {}
|
||||||
|
|
||||||
|
RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); }
|
||||||
|
};
|
||||||
|
|
||||||
template<unsigned parseFlags, typename InputStream, typename Handler>
|
template<unsigned parseFlags, typename InputStream, typename Handler>
|
||||||
void ParseNumber(InputStream& is, Handler& handler) {
|
void ParseNumber(InputStream& is, Handler& handler) {
|
||||||
internal::StreamLocalCopy<InputStream> copy(is);
|
internal::StreamLocalCopy<InputStream> copy(is);
|
||||||
NumberStream<InputStream,
|
NumberStream<InputStream,
|
||||||
((parseFlags & kParseNumbersAsStringsFlag) != 0) ?
|
((parseFlags & kParseNumbersAsStringsFlag) != 0) ?
|
||||||
((parseFlags & kParseInsituFlag) == 0) :
|
((parseFlags & kParseInsituFlag) == 0) :
|
||||||
((parseFlags & kParseFullPrecisionFlag) != 0)> s(*this, copy.s);
|
((parseFlags & kParseFullPrecisionFlag) != 0),
|
||||||
|
(parseFlags & kParseNumbersAsStringsFlag) != 0 &&
|
||||||
|
(parseFlags & kParseInsituFlag) == 0> s(*this, copy.s);
|
||||||
|
|
||||||
size_t startOffset = s.Tell();
|
size_t startOffset = s.Tell();
|
||||||
|
|
||||||
@ -1173,7 +1185,7 @@ private:
|
|||||||
bool useDouble = false;
|
bool useDouble = false;
|
||||||
double d = 0.0;
|
double d = 0.0;
|
||||||
if (use64bit) {
|
if (use64bit) {
|
||||||
if (minus)
|
if (minus)
|
||||||
while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
|
while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
|
||||||
if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808
|
if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808
|
||||||
if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) {
|
if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) {
|
||||||
@ -1210,9 +1222,6 @@ private:
|
|||||||
int expFrac = 0;
|
int expFrac = 0;
|
||||||
size_t decimalPosition;
|
size_t decimalPosition;
|
||||||
if (Consume(s, '.')) {
|
if (Consume(s, '.')) {
|
||||||
if (((parseFlags & kParseNumbersAsStringsFlag) != 0) && ((parseFlags & kParseInsituFlag) == 0)) {
|
|
||||||
s.Push('.');
|
|
||||||
}
|
|
||||||
decimalPosition = s.Length();
|
decimalPosition = s.Length();
|
||||||
|
|
||||||
if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9')))
|
if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9')))
|
||||||
@ -1223,7 +1232,7 @@ private:
|
|||||||
// Use i64 to store significand in 64-bit architecture
|
// Use i64 to store significand in 64-bit architecture
|
||||||
if (!use64bit)
|
if (!use64bit)
|
||||||
i64 = i;
|
i64 = i;
|
||||||
|
|
||||||
while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
|
while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
|
||||||
if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path
|
if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path
|
||||||
break;
|
break;
|
||||||
@ -1260,11 +1269,7 @@ private:
|
|||||||
// Parse exp = e [ minus / plus ] 1*DIGIT
|
// Parse exp = e [ minus / plus ] 1*DIGIT
|
||||||
int exp = 0;
|
int exp = 0;
|
||||||
if (Consume(s, 'e') || Consume(s, 'E')) {
|
if (Consume(s, 'e') || Consume(s, 'E')) {
|
||||||
if ( ((parseFlags & kParseNumbersAsStringsFlag) != 0) && ((parseFlags & kParseInsituFlag) == 0) ) {
|
if (!useDouble) {
|
||||||
s.Push( 'e' );
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!useDouble) {
|
|
||||||
d = static_cast<double>(use64bit ? i64 : i);
|
d = static_cast<double>(use64bit ? i64 : i);
|
||||||
useDouble = true;
|
useDouble = true;
|
||||||
}
|
}
|
||||||
@ -1316,14 +1321,15 @@ private:
|
|||||||
cont = handler.RawNumber(str, SizeType(length), false);
|
cont = handler.RawNumber(str, SizeType(length), false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
StackStream<typename TargetEncoding::Ch> stackStream(stack_);
|
|
||||||
SizeType numCharsToCopy = static_cast<SizeType>(s.Length());
|
SizeType numCharsToCopy = static_cast<SizeType>(s.Length());
|
||||||
|
StringStream srcStream(s.Pop());
|
||||||
|
StackStream<typename TargetEncoding::Ch> dstStream(stack_);
|
||||||
while (numCharsToCopy--) {
|
while (numCharsToCopy--) {
|
||||||
Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, stackStream);
|
Transcoder<UTF8<>, TargetEncoding>::Transcode(srcStream, dstStream);
|
||||||
}
|
}
|
||||||
stackStream.Put('\0');
|
dstStream.Put('\0');
|
||||||
const typename TargetEncoding::Ch* str = stackStream.Pop();
|
const typename TargetEncoding::Ch* str = dstStream.Pop();
|
||||||
const SizeType length = static_cast<SizeType>(stackStream.Length()) - 1;
|
const SizeType length = static_cast<SizeType>(dstStream.Length()) - 1;
|
||||||
cont = handler.RawNumber(str, SizeType(length), true);
|
cont = handler.RawNumber(str, SizeType(length), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1369,10 +1375,10 @@ private:
|
|||||||
case '"': ParseString<parseFlags>(is, handler); break;
|
case '"': ParseString<parseFlags>(is, handler); break;
|
||||||
case '{': ParseObject<parseFlags>(is, handler); break;
|
case '{': ParseObject<parseFlags>(is, handler); break;
|
||||||
case '[': ParseArray <parseFlags>(is, handler); break;
|
case '[': ParseArray <parseFlags>(is, handler); break;
|
||||||
default :
|
default :
|
||||||
ParseNumber<parseFlags>(is, handler);
|
ParseNumber<parseFlags>(is, handler);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1444,7 +1450,7 @@ private:
|
|||||||
#undef N
|
#undef N
|
||||||
#undef N16
|
#undef N16
|
||||||
//!@endcond
|
//!@endcond
|
||||||
|
|
||||||
if (sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256)
|
if (sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256)
|
||||||
return static_cast<Token>(tokenMap[static_cast<unsigned char>(c)]);
|
return static_cast<Token>(tokenMap[static_cast<unsigned char>(c)]);
|
||||||
else
|
else
|
||||||
@ -1775,7 +1781,7 @@ private:
|
|||||||
// Error flag has been set.
|
// Error flag has been set.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (src) {
|
switch (src) {
|
||||||
case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return;
|
case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return;
|
||||||
case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return;
|
case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return;
|
||||||
@ -1788,7 +1794,7 @@ private:
|
|||||||
case IterativeParsingElementDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return;
|
case IterativeParsingElementDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return;
|
||||||
case IterativeParsingElementState: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return;
|
case IterativeParsingElementState: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return;
|
||||||
default: RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); return;
|
default: RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <unsigned parseFlags, typename InputStream, typename Handler>
|
template <unsigned parseFlags, typename InputStream, typename Handler>
|
||||||
|
@ -38,6 +38,11 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
|||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal")
|
||||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal -Wimplicit-fallthrough -Weverything")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal -Wimplicit-fallthrough -Weverything")
|
||||||
|
# If the user is running a newer version of Clang that includes the
|
||||||
|
# -Wdouble-promotion, we will ignore that warning.
|
||||||
|
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 3.7)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-double-promotion")
|
||||||
|
endif()
|
||||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS=1)
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS=1)
|
||||||
endif()
|
endif()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||||
@ -7,9 +7,9 @@
|
|||||||
//
|
//
|
||||||
// http://opensource.org/licenses/MIT
|
// http://opensource.org/licenses/MIT
|
||||||
//
|
//
|
||||||
// Unless required by applicable law or agreed to in writing, software distributed
|
// Unless required by applicable law or agreed to in writing, software distributed
|
||||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
// specific language governing permissions and limitations under the License.
|
// specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
#include "unittest.h"
|
#include "unittest.h"
|
||||||
@ -241,13 +241,13 @@ static void TestParseDouble() {
|
|||||||
TEST_DOUBLE(fullPrecision, "0.017976931348623157e+310", 1.7976931348623157e+308); // Max double in another form
|
TEST_DOUBLE(fullPrecision, "0.017976931348623157e+310", 1.7976931348623157e+308); // Max double in another form
|
||||||
|
|
||||||
// Since
|
// Since
|
||||||
// abs((2^-1022 - 2^-1074) - 2.2250738585072012e-308) = 3.109754131239141401123495768877590405345064751974375599... ¡Á 10^-324
|
// abs((2^-1022 - 2^-1074) - 2.2250738585072012e-308) = 3.109754131239141401123495768877590405345064751974375599... <EFBFBD><EFBFBD> 10^-324
|
||||||
// abs((2^-1022) - 2.2250738585072012e-308) = 1.830902327173324040642192159804623318305533274168872044... ¡Á 10 ^ -324
|
// abs((2^-1022) - 2.2250738585072012e-308) = 1.830902327173324040642192159804623318305533274168872044... <EFBFBD><EFBFBD> 10 ^ -324
|
||||||
// So 2.2250738585072012e-308 should round to 2^-1022 = 2.2250738585072014e-308
|
// So 2.2250738585072012e-308 should round to 2^-1022 = 2.2250738585072014e-308
|
||||||
TEST_DOUBLE(fullPrecision, "2.2250738585072012e-308", 2.2250738585072014e-308); // http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
|
TEST_DOUBLE(fullPrecision, "2.2250738585072012e-308", 2.2250738585072014e-308); // http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
|
||||||
|
|
||||||
// More closer to normal/subnormal boundary
|
// More closer to normal/subnormal boundary
|
||||||
// boundary = 2^-1022 - 2^-1075 = 2.225073858507201136057409796709131975934819546351645648... ¡Á 10^-308
|
// boundary = 2^-1022 - 2^-1075 = 2.225073858507201136057409796709131975934819546351645648... <EFBFBD><EFBFBD> 10^-308
|
||||||
TEST_DOUBLE(fullPrecision, "2.22507385850720113605740979670913197593481954635164564e-308", 2.2250738585072009e-308);
|
TEST_DOUBLE(fullPrecision, "2.22507385850720113605740979670913197593481954635164564e-308", 2.2250738585072009e-308);
|
||||||
TEST_DOUBLE(fullPrecision, "2.22507385850720113605740979670913197593481954635164565e-308", 2.2250738585072014e-308);
|
TEST_DOUBLE(fullPrecision, "2.22507385850720113605740979670913197593481954635164565e-308", 2.2250738585072014e-308);
|
||||||
|
|
||||||
@ -297,7 +297,7 @@ static void TestParseDouble() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cover trimming
|
// Cover trimming
|
||||||
TEST_DOUBLE(fullPrecision,
|
TEST_DOUBLE(fullPrecision,
|
||||||
"2.22507385850720113605740979670913197593481954635164564802342610972482222202107694551652952390813508"
|
"2.22507385850720113605740979670913197593481954635164564802342610972482222202107694551652952390813508"
|
||||||
"7914149158913039621106870086438694594645527657207407820621743379988141063267329253552286881372149012"
|
"7914149158913039621106870086438694594645527657207407820621743379988141063267329253552286881372149012"
|
||||||
"9811224514518898490572223072852551331557550159143974763979834118019993239625482890171070818506906306"
|
"9811224514518898490572223072852551331557550159143974763979834118019993239625482890171070818506906306"
|
||||||
@ -306,7 +306,7 @@ static void TestParseDouble() {
|
|||||||
"5722898802581825451803257070188608721131280795122334262883686223215037756666225039825343359745688844"
|
"5722898802581825451803257070188608721131280795122334262883686223215037756666225039825343359745688844"
|
||||||
"2390026549819838548794829220689472168983109969836584681402285424333066033985088644580400103493397042"
|
"2390026549819838548794829220689472168983109969836584681402285424333066033985088644580400103493397042"
|
||||||
"7567186443383770486037861622771738545623065874679014086723327636718751234567890123456789012345678901"
|
"7567186443383770486037861622771738545623065874679014086723327636718751234567890123456789012345678901"
|
||||||
"e-308",
|
"e-308",
|
||||||
2.2250738585072014e-308);
|
2.2250738585072014e-308);
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -457,12 +457,12 @@ template <typename Encoding>
|
|||||||
struct ParseStringHandler : BaseReaderHandler<Encoding, ParseStringHandler<Encoding> > {
|
struct ParseStringHandler : BaseReaderHandler<Encoding, ParseStringHandler<Encoding> > {
|
||||||
ParseStringHandler() : str_(0), length_(0), copy_() {}
|
ParseStringHandler() : str_(0), length_(0), copy_() {}
|
||||||
~ParseStringHandler() { EXPECT_TRUE(str_ != 0); if (copy_) free(const_cast<typename Encoding::Ch*>(str_)); }
|
~ParseStringHandler() { EXPECT_TRUE(str_ != 0); if (copy_) free(const_cast<typename Encoding::Ch*>(str_)); }
|
||||||
|
|
||||||
ParseStringHandler(const ParseStringHandler&);
|
ParseStringHandler(const ParseStringHandler&);
|
||||||
ParseStringHandler& operator=(const ParseStringHandler&);
|
ParseStringHandler& operator=(const ParseStringHandler&);
|
||||||
|
|
||||||
bool Default() { ADD_FAILURE(); return false; }
|
bool Default() { ADD_FAILURE(); return false; }
|
||||||
bool String(const typename Encoding::Ch* str, size_t length, bool copy) {
|
bool String(const typename Encoding::Ch* str, size_t length, bool copy) {
|
||||||
EXPECT_EQ(0, str_);
|
EXPECT_EQ(0, str_);
|
||||||
if (copy) {
|
if (copy) {
|
||||||
str_ = static_cast<typename Encoding::Ch*>(malloc((length + 1) * sizeof(typename Encoding::Ch)));
|
str_ = static_cast<typename Encoding::Ch*>(malloc((length + 1) * sizeof(typename Encoding::Ch)));
|
||||||
@ -470,7 +470,7 @@ struct ParseStringHandler : BaseReaderHandler<Encoding, ParseStringHandler<Encod
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
str_ = str;
|
str_ = str;
|
||||||
length_ = length;
|
length_ = length;
|
||||||
copy_ = copy;
|
copy_ = copy;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -499,7 +499,7 @@ TEST(Reader, ParseString) {
|
|||||||
EXPECT_EQ(StrLen(e), h2.length_); \
|
EXPECT_EQ(StrLen(e), h2.length_); \
|
||||||
}
|
}
|
||||||
|
|
||||||
// String constant L"\xXX" can only specify character code in bytes, which is not endianness-neutral.
|
// String constant L"\xXX" can only specify character code in bytes, which is not endianness-neutral.
|
||||||
// And old compiler does not support u"" and U"" string literal. So here specify string literal by array of Ch.
|
// And old compiler does not support u"" and U"" string literal. So here specify string literal by array of Ch.
|
||||||
// In addition, GCC 4.8 generates -Wnarrowing warnings when character code >= 128 are assigned to signed integer types.
|
// In addition, GCC 4.8 generates -Wnarrowing warnings when character code >= 128 are assigned to signed integer types.
|
||||||
// Therefore, utype is added for declaring unsigned array, and then cast it to Encoding::Ch.
|
// Therefore, utype is added for declaring unsigned array, and then cast it to Encoding::Ch.
|
||||||
@ -650,7 +650,7 @@ TEST(Reader, ParseString_Error) {
|
|||||||
|
|
||||||
// http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
|
// http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
|
||||||
|
|
||||||
// 3 Malformed sequences
|
// 3 Malformed sequences
|
||||||
|
|
||||||
// 3.1 Unexpected continuation bytes
|
// 3.1 Unexpected continuation bytes
|
||||||
{
|
{
|
||||||
@ -684,19 +684,19 @@ TEST(Reader, ParseString_Error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4 Overlong sequences
|
// 4 Overlong sequences
|
||||||
|
|
||||||
// 4.1 Examples of an overlong ASCII character
|
// 4.1 Examples of an overlong ASCII character
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xC0u, 0xAFu, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xC0u, 0xAFu, '\"', ']', '\0'));
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xE0u, 0x80u, 0xAFu, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xE0u, 0x80u, 0xAFu, '\"', ']', '\0'));
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xF0u, 0x80u, 0x80u, 0xAFu, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xF0u, 0x80u, 0x80u, 0xAFu, '\"', ']', '\0'));
|
||||||
|
|
||||||
// 4.2 Maximum overlong sequences
|
// 4.2 Maximum overlong sequences
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xC1u, 0xBFu, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xC1u, 0xBFu, '\"', ']', '\0'));
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xE0u, 0x9Fu, 0xBFu, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xE0u, 0x9Fu, 0xBFu, '\"', ']', '\0'));
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xF0u, 0x8Fu, 0xBFu, 0xBFu, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xF0u, 0x8Fu, 0xBFu, 0xBFu, '\"', ']', '\0'));
|
||||||
|
|
||||||
// 4.3 Overlong representation of the NUL character
|
// 4.3 Overlong representation of the NUL character
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xC0u, 0x80u, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xC0u, 0x80u, '\"', ']', '\0'));
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xE0u, 0x80u, 0x80u, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xE0u, 0x80u, 0x80u, '\"', ']', '\0'));
|
||||||
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xF0u, 0x80u, 0x80u, 0x80u, '\"', ']', '\0'));
|
TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xF0u, 0x80u, 0x80u, 0x80u, '\"', ']', '\0'));
|
||||||
@ -790,14 +790,14 @@ struct ParseObjectHandler : BaseReaderHandler<UTF8<>, ParseObjectHandler> {
|
|||||||
|
|
||||||
bool Default() { ADD_FAILURE(); return false; }
|
bool Default() { ADD_FAILURE(); return false; }
|
||||||
bool Null() { EXPECT_EQ(8u, step_); step_++; return true; }
|
bool Null() { EXPECT_EQ(8u, step_); step_++; return true; }
|
||||||
bool Bool(bool b) {
|
bool Bool(bool b) {
|
||||||
switch(step_) {
|
switch(step_) {
|
||||||
case 4: EXPECT_TRUE(b); step_++; return true;
|
case 4: EXPECT_TRUE(b); step_++; return true;
|
||||||
case 6: EXPECT_FALSE(b); step_++; return true;
|
case 6: EXPECT_FALSE(b); step_++; return true;
|
||||||
default: ADD_FAILURE(); return false;
|
default: ADD_FAILURE(); return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool Int(int i) {
|
bool Int(int i) {
|
||||||
switch(step_) {
|
switch(step_) {
|
||||||
case 10: EXPECT_EQ(123, i); step_++; return true;
|
case 10: EXPECT_EQ(123, i); step_++; return true;
|
||||||
case 15: EXPECT_EQ(1, i); step_++; return true;
|
case 15: EXPECT_EQ(1, i); step_++; return true;
|
||||||
@ -808,7 +808,7 @@ struct ParseObjectHandler : BaseReaderHandler<UTF8<>, ParseObjectHandler> {
|
|||||||
}
|
}
|
||||||
bool Uint(unsigned i) { return Int(static_cast<int>(i)); }
|
bool Uint(unsigned i) { return Int(static_cast<int>(i)); }
|
||||||
bool Double(double d) { EXPECT_EQ(12u, step_); EXPECT_DOUBLE_EQ(3.1416, d); step_++; return true; }
|
bool Double(double d) { EXPECT_EQ(12u, step_); EXPECT_DOUBLE_EQ(3.1416, d); step_++; return true; }
|
||||||
bool String(const char* str, size_t, bool) {
|
bool String(const char* str, size_t, bool) {
|
||||||
switch(step_) {
|
switch(step_) {
|
||||||
case 1: EXPECT_STREQ("hello", str); step_++; return true;
|
case 1: EXPECT_STREQ("hello", str); step_++; return true;
|
||||||
case 2: EXPECT_STREQ("world", str); step_++; return true;
|
case 2: EXPECT_STREQ("world", str); step_++; return true;
|
||||||
@ -1045,7 +1045,7 @@ struct StreamTraits<CustomStringStream<Encoding> > {
|
|||||||
};
|
};
|
||||||
|
|
||||||
} // namespace rapidjson
|
} // namespace rapidjson
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TEST(Reader, CustomStringStream) {
|
TEST(Reader, CustomStringStream) {
|
||||||
const char* json = "{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] } ";
|
const char* json = "{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] } ";
|
||||||
@ -1069,7 +1069,7 @@ public:
|
|||||||
return c == std::char_traits<char>::eof() ? '\0' : static_cast<Ch>(c);
|
return c == std::char_traits<char>::eof() ? '\0' : static_cast<Ch>(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ch Take() {
|
Ch Take() {
|
||||||
int c = is_.get();
|
int c = is_.get();
|
||||||
return c == std::char_traits<char>::eof() ? '\0' : static_cast<Ch>(c);
|
return c == std::char_traits<char>::eof() ? '\0' : static_cast<Ch>(c);
|
||||||
}
|
}
|
||||||
@ -1097,7 +1097,7 @@ TEST(Reader, Parse_IStreamWrapper_StringStream) {
|
|||||||
Reader reader;
|
Reader reader;
|
||||||
ParseArrayHandler<4> h;
|
ParseArrayHandler<4> h;
|
||||||
reader.Parse(is, h);
|
reader.Parse(is, h);
|
||||||
EXPECT_FALSE(reader.HasParseError());
|
EXPECT_FALSE(reader.HasParseError());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test iterative parsing.
|
// Test iterative parsing.
|
||||||
@ -1195,7 +1195,7 @@ struct IterativeParsingReaderHandler {
|
|||||||
bool StartObject() { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_STARTOBJECT; return true; }
|
bool StartObject() { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_STARTOBJECT; return true; }
|
||||||
|
|
||||||
bool Key (const Ch*, SizeType, bool) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_KEY; return true; }
|
bool Key (const Ch*, SizeType, bool) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_KEY; return true; }
|
||||||
|
|
||||||
bool EndObject(SizeType c) {
|
bool EndObject(SizeType c) {
|
||||||
RAPIDJSON_ASSERT(LogCount < LogCapacity);
|
RAPIDJSON_ASSERT(LogCount < LogCapacity);
|
||||||
Logs[LogCount++] = LOG_ENDOBJECT;
|
Logs[LogCount++] = LOG_ENDOBJECT;
|
||||||
@ -1446,7 +1446,7 @@ TEST(Reader, ParseEmptyOnelineComment) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(Reader, ParseMultipleCommentsInARow) {
|
TEST(Reader, ParseMultipleCommentsInARow) {
|
||||||
const char* json =
|
const char* json =
|
||||||
"{/* first comment *//* second */\n"
|
"{/* first comment *//* second */\n"
|
||||||
"/* third */ /*fourth*/// last one\n"
|
"/* third */ /*fourth*/// last one\n"
|
||||||
"\"hello\" : \"world\", \"t\" : true, \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] }";
|
"\"hello\" : \"world\", \"t\" : true, \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] }";
|
||||||
@ -1541,7 +1541,8 @@ struct NumbersAsStringsHandler {
|
|||||||
// 'str' is not null-terminated
|
// 'str' is not null-terminated
|
||||||
bool RawNumber(const char* str, SizeType length, bool) {
|
bool RawNumber(const char* str, SizeType length, bool) {
|
||||||
EXPECT_TRUE(str != 0);
|
EXPECT_TRUE(str != 0);
|
||||||
EXPECT_TRUE(strncmp(str, "3.1416", length) == 0);
|
EXPECT_TRUE(expected_len_ == length);
|
||||||
|
EXPECT_TRUE(strncmp(str, expected_, length) == 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool String(const char*, SizeType, bool) { return true; }
|
bool String(const char*, SizeType, bool) { return true; }
|
||||||
@ -1550,24 +1551,84 @@ struct NumbersAsStringsHandler {
|
|||||||
bool EndObject(SizeType) { return true; }
|
bool EndObject(SizeType) { return true; }
|
||||||
bool StartArray() { return true; }
|
bool StartArray() { return true; }
|
||||||
bool EndArray(SizeType) { return true; }
|
bool EndArray(SizeType) { return true; }
|
||||||
|
|
||||||
|
NumbersAsStringsHandler(const char* expected)
|
||||||
|
: expected_(expected)
|
||||||
|
, expected_len_(strlen(expected)) {}
|
||||||
|
|
||||||
|
const char* expected_;
|
||||||
|
size_t expected_len_;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST(Reader, NumbersAsStrings) {
|
TEST(Reader, NumbersAsStrings) {
|
||||||
{
|
{
|
||||||
const char* json = "{ \"pi\": 3.1416 } ";
|
const char* json = "{ \"pi\": 3.1416 } ";
|
||||||
StringStream s(json);
|
StringStream s(json);
|
||||||
NumbersAsStringsHandler h;
|
NumbersAsStringsHandler h("3.1416");
|
||||||
Reader reader;
|
Reader reader;
|
||||||
EXPECT_TRUE(reader.Parse<kParseNumbersAsStringsFlag>(s, h));
|
EXPECT_TRUE(reader.Parse<kParseNumbersAsStringsFlag>(s, h));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
char* json = StrDup("{ \"pi\": 3.1416 } ");
|
char* json = StrDup("{ \"pi\": 3.1416 } ");
|
||||||
InsituStringStream s(json);
|
InsituStringStream s(json);
|
||||||
NumbersAsStringsHandler h;
|
NumbersAsStringsHandler h("3.1416");
|
||||||
Reader reader;
|
Reader reader;
|
||||||
EXPECT_TRUE(reader.Parse<kParseInsituFlag|kParseNumbersAsStringsFlag>(s, h));
|
EXPECT_TRUE(reader.Parse<kParseInsituFlag|kParseNumbersAsStringsFlag>(s, h));
|
||||||
free(json);
|
free(json);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
const char* json = "{ \"gigabyte\": 1.0e9 } ";
|
||||||
|
StringStream s(json);
|
||||||
|
NumbersAsStringsHandler h("1.0e9");
|
||||||
|
Reader reader;
|
||||||
|
EXPECT_TRUE(reader.Parse<kParseNumbersAsStringsFlag>(s, h));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char* json = StrDup("{ \"gigabyte\": 1.0e9 } ");
|
||||||
|
InsituStringStream s(json);
|
||||||
|
NumbersAsStringsHandler h("1.0e9");
|
||||||
|
Reader reader;
|
||||||
|
EXPECT_TRUE(reader.Parse<kParseInsituFlag|kParseNumbersAsStringsFlag>(s, h));
|
||||||
|
free(json);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const char* json = "{ \"pi\": 314.159e-2 } ";
|
||||||
|
StringStream s(json);
|
||||||
|
NumbersAsStringsHandler h("314.159e-2");
|
||||||
|
Reader reader;
|
||||||
|
EXPECT_TRUE(reader.Parse<kParseNumbersAsStringsFlag>(s, h));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char* json = StrDup("{ \"gigabyte\": 314.159e-2 } ");
|
||||||
|
InsituStringStream s(json);
|
||||||
|
NumbersAsStringsHandler h("314.159e-2");
|
||||||
|
Reader reader;
|
||||||
|
EXPECT_TRUE(reader.Parse<kParseInsituFlag|kParseNumbersAsStringsFlag>(s, h));
|
||||||
|
free(json);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const char* json = "{ \"negative\": -1.54321 } ";
|
||||||
|
StringStream s(json);
|
||||||
|
NumbersAsStringsHandler h("-1.54321");
|
||||||
|
Reader reader;
|
||||||
|
EXPECT_TRUE(reader.Parse<kParseNumbersAsStringsFlag>(s, h));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char* json = StrDup("{ \"negative\": -1.54321 } ");
|
||||||
|
InsituStringStream s(json);
|
||||||
|
NumbersAsStringsHandler h("-1.54321");
|
||||||
|
Reader reader;
|
||||||
|
EXPECT_TRUE(reader.Parse<kParseInsituFlag|kParseNumbersAsStringsFlag>(s, h));
|
||||||
|
free(json);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const char* json = "{ \"pi\": 314.159e-2 } ";
|
||||||
|
std::stringstream ss(json);
|
||||||
|
IStreamWrapper s(ss);
|
||||||
|
NumbersAsStringsHandler h("314.159e-2");
|
||||||
|
Reader reader;
|
||||||
|
EXPECT_TRUE(reader.Parse<kParseNumbersAsStringsFlag>(s, h));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <unsigned extraFlags>
|
template <unsigned extraFlags>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user