diff options
Diffstat (limited to 'src/corelib/serialization/qjsonparser.cpp')
-rw-r--r-- | src/corelib/serialization/qjsonparser.cpp | 122 |
1 files changed, 66 insertions, 56 deletions
diff --git a/src/corelib/serialization/qjsonparser.cpp b/src/corelib/serialization/qjsonparser.cpp index acc2bc383f..ba4887225d 100644 --- a/src/corelib/serialization/qjsonparser.cpp +++ b/src/corelib/serialization/qjsonparser.cpp @@ -11,23 +11,30 @@ #include "private/qstringconverter_p.h" #include "private/qcborvalue_p.h" #include "private/qnumeric_p.h" +#include <private/qtools_p.h> //#define PARSER_DEBUG #ifdef PARSER_DEBUG +# error currently broken after `current` was moved to StashedContainer Q_CONSTINIT static int indent = 0; -#define BEGIN qDebug() << QByteArray(4*indent++, ' ').constData() << "pos=" << current -#define END --indent -#define DEBUG qDebug() << QByteArray(4*indent, ' ').constData() +# define QT_PARSER_TRACING_BEGIN \ + qDebug() << QByteArray(4 * indent++, ' ').constData() << "pos=" << current +# define QT_PARSER_TRACING_END --indent +# define QT_PARSER_TRACING_DEBUG qDebug() << QByteArray(4 * indent, ' ').constData() #else -#define BEGIN if (1) ; else qDebug() -#define END do {} while (0) -#define DEBUG if (1) ; else qDebug() +# define QT_PARSER_TRACING_BEGIN QT_NO_QDEBUG_MACRO() +# define QT_PARSER_TRACING_END \ + do { \ + } while (0) +# define QT_PARSER_TRACING_DEBUG QT_NO_QDEBUG_MACRO() #endif static const int nestingLimit = 1024; QT_BEGIN_NAMESPACE +using namespace QtMiscUtils; + // error strings for the JSON parser #define JSONERR_OK QT_TRANSLATE_NOOP("QJsonParseError", "no error occurred") #define JSONERR_UNTERM_OBJ QT_TRANSLATE_NOOP("QJsonParseError", "unterminated object") @@ -50,12 +57,13 @@ QT_BEGIN_NAMESPACE \inmodule QtCore \ingroup json \ingroup shared + \ingroup qtserialization \reentrant \since 5.0 \brief The QJsonParseError class is used to report errors during JSON parsing. - \sa {JSON Support in Qt}, {JSON Save Game Example} + \sa {JSON Support in Qt}, {Saving and Loading a Game} */ /*! @@ -297,7 +305,7 @@ QCborValue Parser::parse(QJsonParseError *error) QCborValue data; - DEBUG << Qt::hex << (uint)token; + QT_PARSER_TRACING_DEBUG << Qt::hex << (uint)token; if (token == BeginArray) { container = new QCborContainerPrivate; if (!parseArray()) @@ -321,7 +329,7 @@ QCborValue Parser::parse(QJsonParseError *error) goto error; } - END; + QT_PARSER_TRACING_END; { if (error) { error->offset = 0; @@ -453,7 +461,7 @@ bool Parser::parseObject() return false; } - BEGIN << "parseObject" << json; + QT_PARSER_TRACING_BEGIN << "parseObject" << json; char token = nextToken(); while (token == Quote) { @@ -471,13 +479,13 @@ bool Parser::parseObject() } } - DEBUG << "end token=" << token; + QT_PARSER_TRACING_DEBUG << "end token=" << token; if (token != EndObject) { lastError = QJsonParseError::UnterminatedObject; return false; } - END; + QT_PARSER_TRACING_END; --nestingLevel; @@ -491,7 +499,7 @@ bool Parser::parseObject() */ bool Parser::parseMember() { - BEGIN << "parseMember"; + QT_PARSER_TRACING_BEGIN << "parseMember"; if (!parseString()) return false; @@ -507,7 +515,7 @@ bool Parser::parseMember() if (!parseValue()) return false; - END; + QT_PARSER_TRACING_END; return true; } @@ -516,7 +524,7 @@ bool Parser::parseMember() */ bool Parser::parseArray() { - BEGIN << "parseArray"; + QT_PARSER_TRACING_BEGIN << "parseArray"; if (++nestingLevel > nestingLimit) { lastError = QJsonParseError::DeepNesting; @@ -552,8 +560,8 @@ bool Parser::parseArray() } } - DEBUG << "size =" << (container ? container->elements.size() : 0); - END; + QT_PARSER_TRACING_DEBUG << "size =" << (container ? container->elements.size() : 0); + QT_PARSER_TRACING_END; --nestingLevel; @@ -567,7 +575,7 @@ value = false / null / true / object / array / number / string bool Parser::parseValue() { - BEGIN << "parse Value" << json; + QT_PARSER_TRACING_BEGIN << "parse Value" << json; switch (*json++) { case 'n': @@ -579,8 +587,8 @@ bool Parser::parseValue() *json++ == 'l' && *json++ == 'l') { container->append(QCborValue(QCborValue::Null)); - DEBUG << "value: null"; - END; + QT_PARSER_TRACING_DEBUG << "value: null"; + QT_PARSER_TRACING_END; return true; } lastError = QJsonParseError::IllegalValue; @@ -594,8 +602,8 @@ bool Parser::parseValue() *json++ == 'u' && *json++ == 'e') { container->append(QCborValue(true)); - DEBUG << "value: true"; - END; + QT_PARSER_TRACING_DEBUG << "value: true"; + QT_PARSER_TRACING_END; return true; } lastError = QJsonParseError::IllegalValue; @@ -610,8 +618,8 @@ bool Parser::parseValue() *json++ == 's' && *json++ == 'e') { container->append(QCborValue(false)); - DEBUG << "value: false"; - END; + QT_PARSER_TRACING_DEBUG << "value: false"; + QT_PARSER_TRACING_END; return true; } lastError = QJsonParseError::IllegalValue; @@ -619,24 +627,24 @@ bool Parser::parseValue() case Quote: { if (!parseString()) return false; - DEBUG << "value: string"; - END; + QT_PARSER_TRACING_DEBUG << "value: string"; + QT_PARSER_TRACING_END; return true; } case BeginArray: { StashedContainer stashedContainer(&container, QCborValue::Array); if (!parseArray()) return false; - DEBUG << "value: array"; - END; + QT_PARSER_TRACING_DEBUG << "value: array"; + QT_PARSER_TRACING_END; return true; } case BeginObject: { StashedContainer stashedContainer(&container, QCborValue::Map); if (!parseObject()) return false; - DEBUG << "value: object"; - END; + QT_PARSER_TRACING_DEBUG << "value: object"; + QT_PARSER_TRACING_END; return true; } case ValueSeparator: @@ -652,8 +660,8 @@ bool Parser::parseValue() --json; if (!parseNumber()) return false; - DEBUG << "value: number"; - END; + QT_PARSER_TRACING_DEBUG << "value: number"; + QT_PARSER_TRACING_END; } return true; @@ -679,7 +687,7 @@ bool Parser::parseValue() bool Parser::parseNumber() { - BEGIN << "parseNumber" << json; + QT_PARSER_TRACING_BEGIN << "parseNumber" << json; const char *start = json; bool isInt = true; @@ -692,14 +700,14 @@ bool Parser::parseNumber() if (json < end && *json == '0') { ++json; } else { - while (json < end && *json >= '0' && *json <= '9') + while (json < end && isAsciiDigit(*json)) ++json; } // frac = decimal-point 1*DIGIT if (json < end && *json == '.') { ++json; - while (json < end && *json >= '0' && *json <= '9') { + while (json < end && isAsciiDigit(*json)) { isInt = isInt && *json == '0'; ++json; } @@ -711,7 +719,7 @@ bool Parser::parseNumber() ++json; if (json < end && (*json == '-' || *json == '+')) ++json; - while (json < end && *json >= '0' && *json <= '9') + while (json < end && isAsciiDigit(*json)) ++json; } @@ -721,14 +729,14 @@ bool Parser::parseNumber() } const QByteArray number = QByteArray::fromRawData(start, json - start); - DEBUG << "numberstring" << number; + QT_PARSER_TRACING_DEBUG << "numberstring" << number; if (isInt) { bool ok; qlonglong n = number.toLongLong(&ok); if (ok) { container->append(QCborValue(n)); - END; + QT_PARSER_TRACING_END; return true; } } @@ -747,7 +755,7 @@ bool Parser::parseNumber() else container->append(QCborValue(d)); - END; + QT_PARSER_TRACING_END; return true; } @@ -776,15 +784,13 @@ bool Parser::parseNumber() static inline bool addHexDigit(char digit, char32_t *result) { *result <<= 4; - if (digit >= '0' && digit <= '9') - *result |= (digit - '0'); - else if (digit >= 'a' && digit <= 'f') - *result |= (digit - 'a') + 10; - else if (digit >= 'A' && digit <= 'F') - *result |= (digit - 'A') + 10; - else - return false; - return true; + const int h = fromHex(digit); + if (h != -1) { + *result |= h; + return true; + } + + return false; } static inline bool scanEscapeSequence(const char *&json, const char *end, char32_t *ch) @@ -793,7 +799,7 @@ static inline bool scanEscapeSequence(const char *&json, const char *end, char32 if (json >= end) return false; - DEBUG << "scan escape" << (char)*json; + QT_PARSER_TRACING_DEBUG << "scan escape" << (char)*json; uchar escaped = *json++; switch (escaped) { case '"': @@ -837,7 +843,7 @@ static inline bool scanUtf8Char(const char *&json, const char *end, char32_t *re const auto *usrc = reinterpret_cast<const uchar *>(json); const auto *uend = reinterpret_cast<const uchar *>(end); const uchar b = *usrc++; - int res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(b, result, usrc, uend); + qsizetype res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(b, result, usrc, uend); if (res < 0) return false; @@ -851,7 +857,7 @@ bool Parser::parseString() // try to parse a utf-8 string without escape sequences, and note whether it's 7bit ASCII. - BEGIN << "parse string" << json; + QT_PARSER_TRACING_BEGIN << "parse string" << json; bool isUtf8 = true; bool isAscii = true; while (json < end) { @@ -872,10 +878,10 @@ bool Parser::parseString() } if (ch > 0x7f) isAscii = false; - DEBUG << " " << ch << char(ch); + QT_PARSER_TRACING_DEBUG << " " << ch << char(ch); } ++json; - DEBUG << "end of string"; + QT_PARSER_TRACING_DEBUG << "end of string"; if (json >= end) { lastError = QJsonParseError::UnterminatedString; return false; @@ -887,11 +893,11 @@ bool Parser::parseString() container->appendAsciiString(start, json - start - 1); else container->appendUtf8String(start, json - start - 1); - END; + QT_PARSER_TRACING_END; return true; } - DEBUG << "has escape sequences"; + QT_PARSER_TRACING_DEBUG << "has escape sequences"; json = start; @@ -922,8 +928,12 @@ bool Parser::parseString() container->appendByteData(reinterpret_cast<const char *>(ucs4.constData()), ucs4.size() * 2, QCborValue::String, QtCbor::Element::StringIsUtf16); - END; + QT_PARSER_TRACING_END; return true; } QT_END_NAMESPACE + +#undef QT_PARSER_TRACING_BEGIN +#undef QT_PARSER_TRACING_END +#undef QT_PARSER_TRACING_DEBUG |