7#include <qcoreapplication.h>
12#include "private/qstringconverter_p.h"
13#include "private/qcborvalue_p.h"
14#include "private/qnumeric_p.h"
15#include <private/qtools_p.h>
21using namespace QtMiscUtils;
24#define JSONERR_OK QT_TRANSLATE_NOOP("QJsonParseError", "no error occurred")
25#define JSONERR_UNTERM_OBJ QT_TRANSLATE_NOOP("QJsonParseError", "unterminated object")
26#define JSONERR_MISS_NSEP QT_TRANSLATE_NOOP("QJsonParseError", "missing name separator")
27#define JSONERR_UNTERM_AR QT_TRANSLATE_NOOP("QJsonParseError", "unterminated array")
28#define JSONERR_MISS_VSEP QT_TRANSLATE_NOOP("QJsonParseError", "missing value separator")
29#define JSONERR_ILLEGAL_VAL QT_TRANSLATE_NOOP("QJsonParseError", "illegal value")
30#define JSONERR_END_OF_NUM QT_TRANSLATE_NOOP("QJsonParseError", "invalid termination by number")
31#define JSONERR_ILLEGAL_NUM QT_TRANSLATE_NOOP("QJsonParseError", "illegal number")
32#define JSONERR_STR_ESC_SEQ QT_TRANSLATE_NOOP("QJsonParseError", "invalid escape sequence")
33#define JSONERR_STR_UTF8 QT_TRANSLATE_NOOP("QJsonParseError", "invalid UTF8 string")
34#define JSONERR_UTERM_STR QT_TRANSLATE_NOOP("QJsonParseError", "unterminated string")
35#define JSONERR_MISS_OBJ QT_TRANSLATE_NOOP("QJsonParseError", "object is missing after a comma")
36#define JSONERR_DEEP_NEST QT_TRANSLATE_NOOP("QJsonParseError", "too deeply nested document")
37#define JSONERR_DOC_LARGE QT_TRANSLATE_NOOP("QJsonParseError", "too large document")
38#define JSONERR_GARBAGEEND QT_TRANSLATE_NOOP("QJsonParseError", "garbage at the end of the document")
41
42
43
44
45
46
47
48
49
50
51
52
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
78
79
80
81
82
83
84
88
89
90
91
92
93
96
97
98
99
100QString QJsonParseError::errorString()
const
107 case UnterminatedObject:
110 case MissingNameSeparator:
113 case UnterminatedArray:
116 case MissingValueSeparator:
122 case TerminationByNumber:
128 case IllegalEscapeSequence:
131 case IllegalUTF8String:
134 case UnterminatedString:
143 case DocumentTooLarge:
150#ifndef QT_BOOTSTRAPPED
151 return QCoreApplication::translate(
"QJsonParseError", sz);
153 return QLatin1StringView(sz);
178 QExplicitlySharedDataPointer<QCborContainerPrivate> stashed;
182 : head(json.data()), json(head), end(json.end())
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
233 uchar utf8bom[3] = { 0xef, 0xbb, 0xbf };
234 if (end - json > 3 &&
235 (uchar)json[0] == utf8bom[0] &&
236 (uchar)json[1] == utf8bom[1] &&
237 (uchar)json[2] == utf8bom[2])
246 if (*json !=
Space &&
260 char token = *json++;
278
279
288 lastError = QJsonParseError::IllegalValue;
293 if (token ==
Quote) {
294 container =
new QCborContainerPrivate;
298 value = QCborContainerPrivate::makeValue(QCborValue::String, 0, container.take(),
299 QCborContainerPrivate::MoveContainer);
301 value = parseValue();
302 if (value.isUndefined())
308 lastError = QJsonParseError::GarbageAtEnd;
315 error->error = QJsonParseError::NoError;
324 using OffType =
decltype(error->offset);
325 error->offset = OffType(json - head);
326 Q_ASSERT(error->offset == json - head);
327 error->error = lastError;
334template<
typename Iterator,
typename Compare,
typename Assign>
336 Compare compare, Assign assign)
338 first = std::adjacent_find(first, last, compare);
344 Iterator result = first++;
345 Q_ASSERT(compare(*result, *first));
346 assign(*result, *first);
347 Q_ASSERT(first != last);
349 while (++first != last) {
350 if (!compare(*result, *first))
355 Q_ASSERT(result != first);
359 assign(*result, *first);
367 using Forward = QJsonPrivate::KeyIterator;
368 using Value = Forward::value_type;
370 auto compare = [container](
const Value &a,
const Value &b)
372 const auto &aKey = a.key();
373 const auto &bKey = b.key();
375 Q_ASSERT(aKey.flags & QtCbor::Element::HasByteData);
376 Q_ASSERT(bKey.flags & QtCbor::Element::HasByteData);
378 const QtCbor::ByteData *aData = container->byteData(aKey);
379 const QtCbor::ByteData *bData = container->byteData(bKey);
382 return bData ? -1 : 0;
389 if (aKey.flags & QtCbor::Element::StringIsUtf16) {
390 if (bKey.flags & QtCbor::Element::StringIsUtf16)
391 return QtPrivate::compareStrings(aData->asStringView(), bData->asStringView());
393 return -QCborContainerPrivate::compareUtf8(bData, aData->asStringView());
395 if (bKey.flags & QtCbor::Element::StringIsUtf16)
396 return QCborContainerPrivate::compareUtf8(aData, bData->asStringView());
398 return QtPrivate::compareStrings(aData->asUtf8StringView(), bData->asUtf8StringView());
403 auto move = [](Forward::reference target, Forward::reference source)
405 QtCbor::Element &targetValue = target.value();
408 if (targetValue.flags & QtCbor::Element::IsContainer)
409 targetValue.container->deref();
415 source.value() = QtCbor::Element();
419 Forward(container->elements.begin()), Forward(container->elements.end()),
420 [&compare](
const Value &a,
const Value &b) {
return compare(a, b) < 0; });
422 Forward result = customAssigningUniqueLast(
423 Forward(container->elements.begin()), Forward(container->elements.end()),
424 [&compare](
const Value &a,
const Value &b) {
return compare(a, b) == 0; }, move);
426 container->elements.erase(result.elementsIterator(), container->elements.end());
429bool Parser::parseValueIntoContainer()
432 switch (value.type()) {
433 case QCborValue::Undefined:
435 case QCborValue::String:
438 container->append(std::move(value));
445
446
447
451 if (++nestingLevel > nestingLimit) {
452 lastError = QJsonParseError::DeepNesting;
456 char token = nextToken();
457 while (token ==
Quote) {
459 container =
new QCborContainerPrivate;
467 lastError = QJsonParseError::MissingObject;
473 lastError = QJsonParseError::UnterminatedObject;
480 sortContainer(container.data());
485
486
491 char token = nextToken();
493 lastError = QJsonParseError::MissingNameSeparator;
497 lastError = QJsonParseError::UnterminatedObject;
501 return parseValueIntoContainer();
505
506
509 if (++nestingLevel > nestingLimit) {
510 lastError = QJsonParseError::DeepNesting;
515 lastError = QJsonParseError::UnterminatedArray;
523 lastError = QJsonParseError::UnterminatedArray;
527 container =
new QCborContainerPrivate;
529 if (!parseValueIntoContainer())
532 char token = nextToken();
537 lastError = QJsonParseError::UnterminatedArray;
539 lastError = QJsonParseError::MissingValueSeparator;
551
552
553
555QCborValue
Parser::parseValue()
559 if (end - json < 3) {
560 lastError = QJsonParseError::IllegalValue;
563 if (*json++ ==
'u' &&
566 return QCborValue(QCborValue::Null);
568 lastError = QJsonParseError::IllegalValue;
571 if (end - json < 3) {
572 lastError = QJsonParseError::IllegalValue;
575 if (*json++ ==
'r' &&
578 return QCborValue(
true);
580 lastError = QJsonParseError::IllegalValue;
583 if (end - json < 4) {
584 lastError = QJsonParseError::IllegalValue;
587 if (*json++ ==
'a' &&
591 return QCborValue(
false);
593 lastError = QJsonParseError::IllegalValue;
599 return QCborValue(QCborValue::String);
606 return stashedContainer.intoValue(&container);
613 return stashedContainer.intoValue(&container);
620 lastError = QJsonParseError::IllegalValue;
624 lastError = QJsonParseError::MissingObject;
628 return parseNumber();
637
638
639
640
641
642
643
644
645
646
647
648
650QCborValue
Parser::parseNumber()
652 const char *start = json;
656 if (json < end && *json ==
'-')
660 if (json < end && *json ==
'0') {
663 while (json < end && isAsciiDigit(*json))
668 if (json < end && *json ==
'.') {
670 while (json < end && isAsciiDigit(*json)) {
671 isInt = isInt && *json ==
'0';
677 if (json < end && (*json ==
'e' || *json ==
'E')) {
680 if (json < end && (*json ==
'-' || *json ==
'+'))
682 while (json < end && isAsciiDigit(*json))
686 const QByteArray number = QByteArray::fromRawData(start, json - start);
690 qlonglong n = number.toLongLong(&ok);
692 return QCborValue(n);
697 double d = number.toDouble(&ok);
700 lastError = QJsonParseError::IllegalNumber;
705 if (convertDoubleTo(d, &n))
706 return QCborValue(n);
707 return QCborValue(d);
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
735 const int h = fromHex(digit);
750 uchar escaped = *json++;
772 for (
int i = 0; i < 4; ++i) {
788static inline bool scanUtf8Char(
const char *&json,
const char *end,
char32_t *result)
790 auto usrc =
reinterpret_cast<
const qchar8_t*>(json);
791 const auto uend =
reinterpret_cast<
const qchar8_t*>(end);
792 constexpr char32_t Invalid = ~U'\0';
793 const char32_t ch = QUtf8Functions::nextUcs4FromUtf8(usrc, uend, Invalid);
797 json =
reinterpret_cast<
const char *>(usrc);
803 const char *start = json;
822 lastError = QJsonParseError::IllegalUTF8String;
830 lastError = QJsonParseError::UnterminatedString;
837 container->appendAsciiString(start, json - start - 1);
839 container->appendUtf8String(start, json - start - 1);
850 else if (*json ==
'\\') {
852 lastError = QJsonParseError::IllegalEscapeSequence;
857 lastError = QJsonParseError::IllegalUTF8String;
861 ucs4.append(QChar::fromUcs4(ch));
866 lastError = QJsonParseError::UnterminatedString;
870 container->appendByteData(
reinterpret_cast<
const char *>(ucs4.constData()), ucs4.size() * 2,
871 QCborValue::String, QtCbor::Element::StringIsUtf16);
\inmodule QtCore\reentrant
QCborValue parse(QJsonParseError *error)
Parser(QUtf8StringView json)
#define JSONERR_UNTERM_AR
#define JSONERR_MISS_VSEP
#define JSONERR_UNTERM_OBJ
static bool scanEscapeSequence(const char *&json, const char *end, char32_t *ch)
static const int nestingLimit
#define JSONERR_ILLEGAL_NUM
#define JSONERR_DOC_LARGE
#define JSONERR_DEEP_NEST
#define JSONERR_UTERM_STR
#define JSONERR_END_OF_NUM
static bool scanUtf8Char(const char *&json, const char *end, char32_t *result)
#define JSONERR_STR_ESC_SEQ
#define JSONERR_ILLEGAL_VAL
static bool addHexDigit(char digit, char32_t *result)
static void sortContainer(QCborContainerPrivate *container)
#define JSONERR_MISS_NSEP
#define JSONERR_GARBAGEEND
static Iterator customAssigningUniqueLast(Iterator first, Iterator last, Compare compare, Assign assign)