// 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. // // Licensed under the MIT License (the "License"); you may not use this file except // in compliance with the License. You may obtain a copy of the License at // // http://opensource.org/licenses/MIT // // 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 // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License.
//! Combination of parseFlags /*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream
*/ enum ParseFlag {
kParseNoFlags = 0, //!< No flags are set.
kParseInsituFlag = 1, //!< In-situ(destructive) parsing.
kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings.
kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing.
kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error.
kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower).
kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments.
kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS
};
//! Default implementation of Handler. /*! This can be used as base class of any reader handler. \noteimplementsHandlerconcept
*/ template<typename Encoding = UTF8<>, typename Derived = void> struct BaseReaderHandler { typedeftypename Encoding::Ch Ch;
//! Skip the JSON white spaces in a stream. /*! \param is A input stream for skipping white spaces. \noteThisfunctionhasSSE2/SSE4.2specialization.
*/ template<typename InputStream> void SkipWhitespace(InputStream& is) {
internal::StreamLocalCopy<InputStream> copy(is);
InputStream& s(copy.s);
#ifdef RAPIDJSON_SSE42 //! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once. inlineconstchar *SkipWhitespace_SIMD(constchar* p) { // Fast return for single non-whitespace if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
++p; else return p;
// 16-byte align to the next boundary constchar* nextAligned = reinterpret_cast<constchar*>((reinterpret_cast<size_t>(p) + 15) & ~15); while (p != nextAligned) if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
++p; else return p;
// The rest of string using SIMD staticconstchar whitespace[16] = " \n\r\t"; const __m128i w = _mm_loadu_si128((const __m128i *)&whitespace[0]);
for (;; p += 16) { const __m128i s = _mm_load_si128((const __m128i *)p); constunsigned r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); if (r != 0) { // some of characters is non-whitespace #ifdef _MSC_VER // Find the index of first non-whitespace unsignedlong offset;
_BitScanForward(&offset, r); return p + offset; #else return p + __builtin_ffs(r) - 1; #endif
}
}
}
#elifdefined(RAPIDJSON_SSE2)
//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once. inlineconstchar *SkipWhitespace_SIMD(constchar* p) { // Fast return for single non-whitespace if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
++p; else return p;
// 16-byte align to the next boundary constchar* nextAligned = reinterpret_cast<constchar*>((reinterpret_cast<size_t>(p) + 15) & ~15); while (p != nextAligned) if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
++p; else return p;
// The rest of string staticconstchar whitespaces[4][17] = { " ", "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r", "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"};
for (;; p += 16) { const __m128i s = _mm_load_si128((const __m128i *)p);
__m128i x = _mm_cmpeq_epi8(s, w0);
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); unsignedshort r = (unsignedshort)~_mm_movemask_epi8(x); if (r != 0) { // some of characters may be non-whitespace #ifdef _MSC_VER // Find the index of first non-whitespace unsignedlong offset;
_BitScanForward(&offset, r); return p + offset; #else return p + __builtin_ffs(r) - 1; #endif
}
}
}
#endif// RAPIDJSON_SSE2
#ifdef RAPIDJSON_SIMD //! Template function specialization for InsituStringStream template<> inlinevoid SkipWhitespace(InsituStringStream& is) {
is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
}
//! Template function specialization for StringStream template<> inlinevoid SkipWhitespace(StringStream& is) {
is.src_ = SkipWhitespace_SIMD(is.src_);
} #endif// RAPIDJSON_SIMD
//! 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 objectimplementingHandlerconcept.
// Parse minus bool minus = false; if (s.Peek() == '-') {
minus = true;
s.Take();
}
// Parse int: zero / ( digit1-9 *DIGIT ) unsigned i = 0;
uint64_t i64 = 0; bool use64bit = false; int significandDigit = 0; if (s.Peek() == '0') {
i = 0;
s.TakePush();
} elseif (s.Peek() >= '1' && s.Peek() <= '9') {
i = static_cast<unsigned>(s.TakePush() - '0');
if (minus) while (s.Peek() >= '0' && s.Peek() <= '9') { if (i >= 214748364) { // 2^31 = 2147483648 if (i != 214748364 || s.Peek() > '8') {
i64 = i;
use64bit = true; break;
}
}
i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
significandDigit++;
} else while (s.Peek() >= '0' && s.Peek() <= '9') { if (i >= 429496729) { // 2^32 - 1 = 4294967295 if (i != 429496729 || s.Peek() > '5') {
i64 = i;
use64bit = true; break;
}
}
i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
significandDigit++;
}
} else
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
// Parse 64bit int bool useDouble = false; double d = 0.0; if (use64bit) { if (minus) while (s.Peek() >= '0' && s.Peek() <= '9') { if (i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC)) // 2^63 = 9223372036854775808 if (i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8') {
d = i64;
useDouble = true; break;
}
i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
significandDigit++;
} else while (s.Peek() >= '0' && s.Peek() <= '9') { if (i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999)) // 2^64 - 1 = 18446744073709551615 if (i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5') {
d = i64;
useDouble = true; break;
}
i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
significandDigit++;
}
}
// Force double for big integer if (useDouble) { while (s.Peek() >= '0' && s.Peek() <= '9') { if (d >= 1.7976931348623157e307) // DBL_MAX / 10.0
RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell());
d = d * 10 + (s.TakePush() - '0');
}
}
if (!(s.Peek() >= '0' && s.Peek() <= '9'))
RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell());
if (!useDouble) { #if RAPIDJSON_64BIT // Use i64 to store significand in 64-bit architecture if (!use64bit)
i64 = i;
while (s.Peek() >= '0' && s.Peek() <= '9') { if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path break; else {
i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
--expFrac; if (i64 != 0)
significandDigit++;
}
}
d = (double)i64; #else // Use double to store significand in 32-bit architecture
d = use64bit ? (double)i64 : (double)i; #endif
useDouble = true;
}
while (s.Peek() >= '0' && s.Peek() <= '9') { if (significandDigit < 17) {
d = d * 10.0 + (s.TakePush() - '0');
--expFrac; if (d > 0.0)
significandDigit++;
} else
s.TakePush();
}
} else
decimalPosition = s.Length(); // decimal position at the end of integer.
// Parse exp = e [ minus / plus ] 1*DIGIT int exp = 0; if (s.Peek() == 'e' || s.Peek() == 'E') { if (!useDouble) {
d = use64bit ? i64 : i;
useDouble = true;
}
s.Take();
// Finish parsing, call event according to the type of number. bool cont = true;
size_t length = s.Length(); constchar* decimal = s.Pop(); // Pop stack no matter if it will be used or not.
if (useDouble) { int p = exp + expFrac; if (parseFlags & kParseFullPrecisionFlag)
d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp); else
d = internal::StrtodNormalPrecision(d, p);
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN #define N NumberToken #define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N // Maps from ASCII to Token staticconstunsignedchar tokenMap[256] = {
N16, // 00~0F
N16, // 10~1F
N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F
N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F
N16, // 40~4F
N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F
N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F
N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F
N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF
}; #undef N #undef N16 //!@endcond
RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) { // current state x one lookahead token -> new state staticconstchar G[cIterativeParsingStateCount][kTokenCount] = { // Start
{
IterativeParsingArrayInitialState, // Left bracket
IterativeParsingErrorState, // Right bracket
IterativeParsingObjectInitialState, // Left curly bracket
IterativeParsingErrorState, // Right curly bracket
IterativeParsingErrorState, // Comma
IterativeParsingErrorState, // Colon
IterativeParsingValueState, // String
IterativeParsingValueState, // False
IterativeParsingValueState, // True
IterativeParsingValueState, // Null
IterativeParsingValueState // Number
}, // Finish(sink state)
{
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState
}, // Error(sink state)
{
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState
}, // ObjectInitial
{
IterativeParsingErrorState, // Left bracket
IterativeParsingErrorState, // Right bracket
IterativeParsingErrorState, // Left curly bracket
IterativeParsingObjectFinishState, // Right curly bracket
IterativeParsingErrorState, // Comma
IterativeParsingErrorState, // Colon
IterativeParsingMemberKeyState, // String
IterativeParsingErrorState, // False
IterativeParsingErrorState, // True
IterativeParsingErrorState, // Null
IterativeParsingErrorState // Number
}, // MemberKey
{
IterativeParsingErrorState, // Left bracket
IterativeParsingErrorState, // Right bracket
IterativeParsingErrorState, // Left curly bracket
IterativeParsingErrorState, // Right curly bracket
IterativeParsingErrorState, // Comma
IterativeParsingKeyValueDelimiterState, // Colon
IterativeParsingErrorState, // String
IterativeParsingErrorState, // False
IterativeParsingErrorState, // True
IterativeParsingErrorState, // Null
IterativeParsingErrorState // Number
}, // KeyValueDelimiter
{
IterativeParsingArrayInitialState, // Left bracket(push MemberValue state)
IterativeParsingErrorState, // Right bracket
IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state)
IterativeParsingErrorState, // Right curly bracket
IterativeParsingErrorState, // Comma
IterativeParsingErrorState, // Colon
IterativeParsingMemberValueState, // String
IterativeParsingMemberValueState, // False
IterativeParsingMemberValueState, // True
IterativeParsingMemberValueState, // Null
IterativeParsingMemberValueState // Number
}, // MemberValue
{
IterativeParsingErrorState, // Left bracket
IterativeParsingErrorState, // Right bracket
IterativeParsingErrorState, // Left curly bracket
IterativeParsingObjectFinishState, // Right curly bracket
IterativeParsingMemberDelimiterState, // Comma
IterativeParsingErrorState, // Colon
IterativeParsingErrorState, // String
IterativeParsingErrorState, // False
IterativeParsingErrorState, // True
IterativeParsingErrorState, // Null
IterativeParsingErrorState // Number
}, // MemberDelimiter
{
IterativeParsingErrorState, // Left bracket
IterativeParsingErrorState, // Right bracket
IterativeParsingErrorState, // Left curly bracket
IterativeParsingErrorState, // Right curly bracket
IterativeParsingErrorState, // Comma
IterativeParsingErrorState, // Colon
IterativeParsingMemberKeyState, // String
IterativeParsingErrorState, // False
IterativeParsingErrorState, // True
IterativeParsingErrorState, // Null
IterativeParsingErrorState // Number
}, // ObjectFinish(sink state)
{
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState
}, // ArrayInitial
{
IterativeParsingArrayInitialState, // Left bracket(push Element state)
IterativeParsingArrayFinishState, // Right bracket
IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
IterativeParsingErrorState, // Right curly bracket
IterativeParsingErrorState, // Comma
IterativeParsingErrorState, // Colon
IterativeParsingElementState, // String
IterativeParsingElementState, // False
IterativeParsingElementState, // True
IterativeParsingElementState, // Null
IterativeParsingElementState // Number
}, // Element
{
IterativeParsingErrorState, // Left bracket
IterativeParsingArrayFinishState, // Right bracket
IterativeParsingErrorState, // Left curly bracket
IterativeParsingErrorState, // Right curly bracket
IterativeParsingElementDelimiterState, // Comma
IterativeParsingErrorState, // Colon
IterativeParsingErrorState, // String
IterativeParsingErrorState, // False
IterativeParsingErrorState, // True
IterativeParsingErrorState, // Null
IterativeParsingErrorState // Number
}, // ElementDelimiter
{
IterativeParsingArrayInitialState, // Left bracket(push Element state)
IterativeParsingErrorState, // Right bracket
IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
IterativeParsingErrorState, // Right curly bracket
IterativeParsingErrorState, // Comma
IterativeParsingErrorState, // Colon
IterativeParsingElementState, // String
IterativeParsingElementState, // False
IterativeParsingElementState, // True
IterativeParsingElementState, // Null
IterativeParsingElementState // Number
}, // ArrayFinish(sink state)
{
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState
}, // Single Value (sink state)
{
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState
}
}; // End of G
return (IterativeParsingState)G[state][token];
}
// Make an advance in the token stream and state based on the candidate destination state which was returned by Transit(). // May return a new state on state pop. template <unsigned parseFlags, typename InputStream, typename Handler>
RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) {
(void)token;
switch (dst) { case IterativeParsingErrorState: return dst;
case IterativeParsingObjectInitialState: case IterativeParsingArrayInitialState:
{ // Push the state(Element or MemeberValue) if we are nested in another array or value of member. // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop.
IterativeParsingState n = src; if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState)
n = IterativeParsingElementState; elseif (src == IterativeParsingKeyValueDelimiterState)
n = IterativeParsingMemberValueState; // Push current state.
*stack_.template Push<SizeType>(1) = n; // Initialize and push the member/element count.
*stack_.template Push<SizeType>(1) = 0; // Call handler bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray(); // On handler short circuits the parsing. if (!hr) {
RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); return IterativeParsingErrorState;
} else {
is.Take(); return dst;
}
}
case IterativeParsingMemberKeyState:
ParseString<parseFlags>(is, handler, true); if (HasParseError()) return IterativeParsingErrorState; else return dst;
case IterativeParsingKeyValueDelimiterState:
RAPIDJSON_ASSERT(token == ColonToken);
is.Take(); return dst;
case IterativeParsingMemberValueState: // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
ParseValue<parseFlags>(is, handler); if (HasParseError()) { return IterativeParsingErrorState;
} return dst;
case IterativeParsingElementState: // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
ParseValue<parseFlags>(is, handler); if (HasParseError()) { return IterativeParsingErrorState;
} return dst;
case IterativeParsingMemberDelimiterState: case IterativeParsingElementDelimiterState:
is.Take(); // Update member/element count.
*stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1; return dst;
case IterativeParsingObjectFinishState:
{ // Get member count.
SizeType c = *stack_.template Pop<SizeType>(1); // If the object is not empty, count the last member. if (src == IterativeParsingMemberValueState)
++c; // Restore the state.
IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1)); // Transit to Finish state if this is the topmost scope. if (n == IterativeParsingStartState)
n = IterativeParsingFinishState; // Call handler bool hr = handler.EndObject(c); // On handler short circuits the parsing. if (!hr) {
RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); return IterativeParsingErrorState;
} else {
is.Take(); return n;
}
}
case IterativeParsingArrayFinishState:
{ // Get element count.
SizeType c = *stack_.template Pop<SizeType>(1); // If the array is not empty, count the last element. if (src == IterativeParsingElementState)
++c; // Restore the state.
IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1)); // Transit to Finish state if this is the topmost scope. if (n == IterativeParsingStartState)
n = IterativeParsingFinishState; // Call handler bool hr = handler.EndArray(c); // On handler short circuits the parsing. if (!hr) {
RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); return IterativeParsingErrorState;
} else {
is.Take(); return n;
}
}
default: // This branch is for IterativeParsingValueState actually. // Use `default:` rather than // `case IterativeParsingValueState:` is for code coverage.
// The IterativeParsingStartState is not enumerated in this switch-case. // It is impossible for that case. And it can be caught by following assertion.
// The IterativeParsingFinishState is not enumerated in this switch-case either. // It is a "derivative" state which cannot triggered from Predict() directly. // Therefore it cannot happen here. And it can be caught by following assertion.
RAPIDJSON_ASSERT(dst == IterativeParsingValueState);
// Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
ParseValue<parseFlags>(is, handler); if (HasParseError()) { return IterativeParsingErrorState;
} return IterativeParsingFinishState;
}
}
template <typename InputStream> void HandleError(IterativeParsingState src, InputStream& is) { if (HasParseError()) { // Error flag has been set. return;
}
switch (src) { case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return; case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return; case IterativeParsingObjectInitialState: case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return; case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return; case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return; case IterativeParsingElementState: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return; default: RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); return;
}
}
template <unsigned parseFlags, typename InputStream, typename Handler>
ParseResult IterativeParse(InputStream& is, Handler& handler) {
parseResult_.Clear();
ClearStackOnExit scope(*this);
IterativeParsingState state = IterativeParsingStartState;
SkipWhitespaceAndComments<parseFlags>(is);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); while (is.Peek() != '\0') {
Token t = Tokenize(is.Peek());
IterativeParsingState n = Predict(state, t);
IterativeParsingState d = Transit<parseFlags>(state, t, n, is, handler);
if (d == IterativeParsingErrorState) {
HandleError(state, is); break;
}
state = d;
// Do not further consume streams if a root JSON has been parsed. if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState) break;
// Handle the end of file. if (state != IterativeParsingFinishState)
HandleError(state, is);
return parseResult_;
}
staticconst size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string.
internal::Stack<StackAllocator> stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing.
ParseResult parseResult_;
}; // class GenericReader
//! Reader with UTF8 encoding and default allocator. typedef GenericReader<UTF8<>, UTF8<> > Reader;
RAPIDJSON_NAMESPACE_END
#ifdef __GNUC__
RAPIDJSON_DIAG_POP #endif
#ifdef _MSC_VER
RAPIDJSON_DIAG_POP #endif
#endif// RAPIDJSON_READER_H_
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.33 Sekunden
(vorverarbeitet am 2026-06-17)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.