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 error->offset = json - head;
325 error->error = lastError;
332template<
typename Iterator,
typename Compare,
typename Assign>
334 Compare compare, Assign assign)
336 first = std::adjacent_find(first, last, compare);
342 Iterator result = first++;
343 Q_ASSERT(compare(*result, *first));
344 assign(*result, *first);
345 Q_ASSERT(first != last);
347 while (++first != last) {
348 if (!compare(*result, *first))
353 Q_ASSERT(result != first);
357 assign(*result, *first);
365 using Forward = QJsonPrivate::KeyIterator;
366 using Value = Forward::value_type;
368 auto compare = [container](
const Value &a,
const Value &b)
370 const auto &aKey = a.key();
371 const auto &bKey = b.key();
373 Q_ASSERT(aKey.flags & QtCbor::Element::HasByteData);
374 Q_ASSERT(bKey.flags & QtCbor::Element::HasByteData);
376 const QtCbor::ByteData *aData = container->byteData(aKey);
377 const QtCbor::ByteData *bData = container->byteData(bKey);
380 return bData ? -1 : 0;
387 if (aKey.flags & QtCbor::Element::StringIsUtf16) {
388 if (bKey.flags & QtCbor::Element::StringIsUtf16)
389 return QtPrivate::compareStrings(aData->asStringView(), bData->asStringView());
391 return -QCborContainerPrivate::compareUtf8(bData, aData->asStringView());
393 if (bKey.flags & QtCbor::Element::StringIsUtf16)
394 return QCborContainerPrivate::compareUtf8(aData, bData->asStringView());
396 return QtPrivate::compareStrings(aData->asUtf8StringView(), bData->asUtf8StringView());
401 auto move = [](Forward::reference target, Forward::reference source)
403 QtCbor::Element &targetValue = target.value();
406 if (targetValue.flags & QtCbor::Element::IsContainer)
407 targetValue.container->deref();
413 source.value() = QtCbor::Element();
417 Forward(container->elements.begin()), Forward(container->elements.end()),
418 [&compare](
const Value &a,
const Value &b) {
return compare(a, b) < 0; });
420 Forward result = customAssigningUniqueLast(
421 Forward(container->elements.begin()), Forward(container->elements.end()),
422 [&compare](
const Value &a,
const Value &b) {
return compare(a, b) == 0; }, move);
424 container->elements.erase(result.elementsIterator(), container->elements.end());
427bool Parser::parseValueIntoContainer()
430 switch (value.type()) {
431 case QCborValue::Undefined:
433 case QCborValue::String:
436 container->append(std::move(value));
443
444
445
449 if (++nestingLevel > nestingLimit) {
450 lastError = QJsonParseError::DeepNesting;
454 char token = nextToken();
455 while (token ==
Quote) {
457 container =
new QCborContainerPrivate;
465 lastError = QJsonParseError::MissingObject;
471 lastError = QJsonParseError::UnterminatedObject;
478 sortContainer(container.data());
483
484
489 char token = nextToken();
491 lastError = QJsonParseError::MissingNameSeparator;
495 lastError = QJsonParseError::UnterminatedObject;
499 return parseValueIntoContainer();
503
504
507 if (++nestingLevel > nestingLimit) {
508 lastError = QJsonParseError::DeepNesting;
513 lastError = QJsonParseError::UnterminatedArray;
521 lastError = QJsonParseError::UnterminatedArray;
525 container =
new QCborContainerPrivate;
527 if (!parseValueIntoContainer())
530 char token = nextToken();
535 lastError = QJsonParseError::UnterminatedArray;
537 lastError = QJsonParseError::MissingValueSeparator;
549
550
551
553QCborValue
Parser::parseValue()
557 if (end - json < 3) {
558 lastError = QJsonParseError::IllegalValue;
561 if (*json++ ==
'u' &&
564 return QCborValue(QCborValue::Null);
566 lastError = QJsonParseError::IllegalValue;
569 if (end - json < 3) {
570 lastError = QJsonParseError::IllegalValue;
573 if (*json++ ==
'r' &&
576 return QCborValue(
true);
578 lastError = QJsonParseError::IllegalValue;
581 if (end - json < 4) {
582 lastError = QJsonParseError::IllegalValue;
585 if (*json++ ==
'a' &&
589 return QCborValue(
false);
591 lastError = QJsonParseError::IllegalValue;
597 return QCborValue(QCborValue::String);
604 return stashedContainer.intoValue(&container);
611 return stashedContainer.intoValue(&container);
618 lastError = QJsonParseError::IllegalValue;
622 lastError = QJsonParseError::MissingObject;
626 return parseNumber();
635
636
637
638
639
640
641
642
643
644
645
646
648QCborValue
Parser::parseNumber()
650 const char *start = json;
654 if (json < end && *json ==
'-')
658 if (json < end && *json ==
'0') {
661 while (json < end && isAsciiDigit(*json))
666 if (json < end && *json ==
'.') {
668 while (json < end && isAsciiDigit(*json)) {
669 isInt = isInt && *json ==
'0';
675 if (json < end && (*json ==
'e' || *json ==
'E')) {
678 if (json < end && (*json ==
'-' || *json ==
'+'))
680 while (json < end && isAsciiDigit(*json))
684 const QByteArray number = QByteArray::fromRawData(start, json - start);
688 qlonglong n = number.toLongLong(&ok);
690 return QCborValue(n);
695 double d = number.toDouble(&ok);
698 lastError = QJsonParseError::IllegalNumber;
703 if (convertDoubleTo(d, &n))
704 return QCborValue(n);
705 return QCborValue(d);
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
733 const int h = fromHex(digit);
748 uchar escaped = *json++;
770 for (
int i = 0; i < 4; ++i) {
786static inline bool scanUtf8Char(
const char *&json,
const char *end,
char32_t *result)
788 auto usrc =
reinterpret_cast<
const qchar8_t*>(json);
789 const auto uend =
reinterpret_cast<
const qchar8_t*>(end);
790 constexpr char32_t Invalid = ~U'\0';
791 const char32_t ch = QUtf8Functions::nextUcs4FromUtf8(usrc, uend, Invalid);
795 json =
reinterpret_cast<
const char *>(usrc);
801 const char *start = json;
820 lastError = QJsonParseError::IllegalUTF8String;
828 lastError = QJsonParseError::UnterminatedString;
835 container->appendAsciiString(start, json - start - 1);
837 container->appendUtf8String(start, json - start - 1);
848 else if (*json ==
'\\') {
850 lastError = QJsonParseError::IllegalEscapeSequence;
855 lastError = QJsonParseError::IllegalUTF8String;
859 ucs4.append(QChar::fromUcs4(ch));
864 lastError = QJsonParseError::UnterminatedString;
868 container->appendByteData(
reinterpret_cast<
const char *>(ucs4.constData()), ucs4.size() * 2,
869 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)