1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4
5//
6// W A R N I N G
7// -------------
8//
9// This file is not part of the Qt API. It exists purely as an
10// implementation detail. This header file may change from version to
11// version without notice, or even be removed.
12//
13// We mean it.
14//
15
16//
17// W A R N I N G
18// -------------
19//
20// This file is automatically generated from qxmlstream.g.
21// Changes should be made to that file, not here. Any change to this file will
22// be lost!
23//
24// To regenerate this file, run:
25// qlalr --no-debug --no-lines --qt qxmlstream.g
26//
27
28#include <QtCore/private/qglobal_p.h>
29#include <qxmlstream.h>
30#include "qxmlstream_p.h"
31#include "qxmlutils_p.h"
32#include <qstringconverter.h>
33
34#include <memory>
35
36#ifndef QXMLSTREAMPARSER_P_H
37#define QXMLSTREAMPARSER_P_H
38
39QT_BEGIN_NAMESPACE
40
41#if QT_CONFIG(xmlstreamreader)
42
43bool QXmlStreamReaderPrivate::parse()
44{
45 // cleanup currently reported token
46
47 using namespace Qt::StringLiterals;
48
49 switch (type) {
50 case QXmlStreamReader::StartElement:
51 name.clear();
52 prefix.clear();
53 qualifiedName.clear();
54 namespaceUri.clear();
55 publicNamespaceDeclarations.clear();
56 attributes.clear();
57 if (isEmptyElement) {
58 setType(QXmlStreamReader::EndElement);
59 Tag tag = tagStack_pop();
60 namespaceUri = tag.namespaceDeclaration.namespaceUri;
61 prefix = tag.namespaceDeclaration.prefix;
62 name = tag.name;
63 qualifiedName = tag.qualifiedName;
64 isEmptyElement = false;
65 return true;
66 }
67 clearTextBuffer();
68 break;
69 case QXmlStreamReader::EndElement:
70 name.clear();
71 prefix.clear();
72 qualifiedName.clear();
73 namespaceUri.clear();
74 clearTextBuffer();
75 break;
76 case QXmlStreamReader::DTD:
77 publicNotationDeclarations.clear();
78 publicEntityDeclarations.clear();
79 dtdName.clear();
80 dtdPublicId.clear();
81 dtdSystemId.clear();
82 Q_FALLTHROUGH();
83 case QXmlStreamReader::Comment:
84 case QXmlStreamReader::Characters:
85 isCDATA = false;
86 isWhitespace = true;
87 text.clear();
88 clearTextBuffer();
89 break;
90 case QXmlStreamReader::EntityReference:
91 text.clear();
92 name.clear();
93 clearTextBuffer();
94 break;
95 case QXmlStreamReader::ProcessingInstruction:
96 processingInstructionTarget.clear();
97 processingInstructionData.clear();
98 clearTextBuffer();
99 break;
100 case QXmlStreamReader::NoToken:
101 case QXmlStreamReader::Invalid:
102 break;
103 case QXmlStreamReader::StartDocument:
104 lockEncoding = true;
105 documentVersion.clear();
106 documentEncoding.clear();
107 if (decoder.isValid() && decoder.hasError()) {
108 raiseWellFormedError(message: QXmlStream::tr(sourceText: "Encountered incorrectly encoded content."));
109 readBuffer.clear();
110 return false;
111 }
112 Q_FALLTHROUGH();
113 default:
114 clearTextBuffer();
115 ;
116 }
117
118 setType(QXmlStreamReader::NoToken);
119
120
121 // the main parse loop
122 int act, r;
123
124 if (resumeReduction) {
125 act = state_stack[tos-1];
126 r = resumeReduction;
127 resumeReduction = 0;
128 goto ResumeReduction;
129 }
130
131 act = state_stack[tos];
132
133 forever {
134 if (token == -1 && - TERMINAL_COUNT != action_index[act]) {
135 uint cu = getChar();
136 token = NOTOKEN;
137 token_char = cu == ~0U ? cu : ushort(cu);
138 if ((cu != ~0U) && (cu & 0xff0000)) {
139 token = cu >> 16;
140 } else switch (token_char) {
141 case 0xfffe:
142 case 0xffff:
143 token = XML_ERROR;
144 break;
145 case '\r':
146 token = SPACE;
147 if (cu == '\r') {
148 if ((token_char = filterCarriageReturn())) {
149 ++lineNumber;
150 lastLineStart = characterOffset + readBufferPos;
151 break;
152 }
153 } else {
154 break;
155 }
156 Q_FALLTHROUGH();
157 case ~0U: {
158 token = EOF_SYMBOL;
159 if (!tagsDone && !inParseEntity) {
160 int a = t_action(state: act, token);
161 if (a < 0) {
162 raiseError(error: QXmlStreamReader::PrematureEndOfDocumentError);
163 return false;
164 }
165 }
166
167 } break;
168 case '\n':
169 ++lineNumber;
170 lastLineStart = characterOffset + readBufferPos;
171 Q_FALLTHROUGH();
172 case ' ':
173 case '\t':
174 token = SPACE;
175 break;
176 case '&':
177 token = AMPERSAND;
178 break;
179 case '#':
180 token = HASH;
181 break;
182 case '\'':
183 token = QUOTE;
184 break;
185 case '\"':
186 token = DBLQUOTE;
187 break;
188 case '<':
189 token = LANGLE;
190 break;
191 case '>':
192 token = RANGLE;
193 break;
194 case '[':
195 token = LBRACK;
196 break;
197 case ']':
198 token = RBRACK;
199 break;
200 case '(':
201 token = LPAREN;
202 break;
203 case ')':
204 token = RPAREN;
205 break;
206 case '|':
207 token = PIPE;
208 break;
209 case '=':
210 token = EQ;
211 break;
212 case '%':
213 token = PERCENT;
214 break;
215 case '/':
216 token = SLASH;
217 break;
218 case ':':
219 token = COLON;
220 break;
221 case ';':
222 token = SEMICOLON;
223 break;
224 case ',':
225 token = COMMA;
226 break;
227 case '-':
228 token = DASH;
229 break;
230 case '+':
231 token = PLUS;
232 break;
233 case '*':
234 token = STAR;
235 break;
236 case '.':
237 token = DOT;
238 break;
239 case '?':
240 token = QUESTIONMARK;
241 break;
242 case '!':
243 token = BANG;
244 break;
245 case '0':
246 case '1':
247 case '2':
248 case '3':
249 case '4':
250 case '5':
251 case '6':
252 case '7':
253 case '8':
254 case '9':
255 token = DIGIT;
256 break;
257 default:
258 if (cu < 0x20)
259 token = NOTOKEN;
260 else
261 token = LETTER;
262 break;
263 }
264 }
265
266 act = t_action (state: act, token);
267 if (act == ACCEPT_STATE) {
268 // reset the parser in case someone resumes (process instructions can follow a valid document)
269 tos = 0;
270 state_stack[tos++] = 0;
271 state_stack[tos] = 0;
272 return true;
273 } else if (act > 0) {
274 if (++tos >= stack_size-1)
275 reallocateStack();
276
277 Value &val = sym_stack[tos];
278 val.c = token_char;
279 val.pos = textBuffer.size();
280 val.prefix = 0;
281 val.len = 1;
282 if (token_char)
283 textBuffer += QChar(token_char);
284
285 state_stack[tos] = act;
286 token = -1;
287
288
289 } else if (act < 0) {
290 r = - act - 1;
291
292#if defined (QLALR_DEBUG)
293 int ridx = rule_index[r];
294 printf ("%3d) %s ::=", r + 1, spell[rule_info[ridx]]);
295 ++ridx;
296 for (int i = ridx; i < ridx + rhs[r]; ++i) {
297 int symbol = rule_info[i];
298 if (const char *name = spell[symbol])
299 printf (" %s", name);
300 else
301 printf (" #%d", symbol);
302 }
303 printf ("\n");
304#endif
305
306 tos -= rhs[r];
307 act = state_stack[tos++];
308 ResumeReduction:
309 switch (r) {
310
311 case 0:
312 setType(QXmlStreamReader::EndDocument);
313 break;
314
315 case 1:
316 if (type != QXmlStreamReader::Invalid) {
317 if (hasSeenTag || inParseEntity) {
318 setType(QXmlStreamReader::EndDocument);
319 } else {
320 raiseError(error: QXmlStreamReader::NotWellFormedError, message: QXmlStream::tr(sourceText: "Start tag expected."));
321 // reset the parser
322 tos = 0;
323 state_stack[tos++] = 0;
324 state_stack[tos] = 0;
325 return false;
326 }
327 }
328 break;
329
330 case 10: {
331 auto reference = entityReferenceStack.pop();
332 auto it = reference.hash->find(key: reference.name);
333 Q_ASSERT(it != reference.hash->end());
334 it->isCurrentlyReferenced = false;
335 if (entityReferenceStack.isEmpty())
336 entityLength = 0;
337 clearSym();
338 } break;
339
340 case 11:
341 if (!scanString(str: spell[VERSION], tokenToInject: VERSION, requireSpace: false) && atEnd) {
342 resume(rule: 11);
343 return false;
344 }
345 break;
346
347 case 12:
348 setType(QXmlStreamReader::StartDocument);
349 documentVersion = symString(index: 6);
350 startDocument();
351 break;
352
353 case 13:
354 hasExternalDtdSubset = true;
355 dtdSystemId = symString(index: 2);
356 break;
357
358 case 14:
359 checkPublicLiteral(publicId: symString(index: 2));
360 dtdPublicId = symString(index: 2);
361 dtdSystemId = symString(index: 4);
362 hasExternalDtdSubset = true;
363 break;
364
365 case 16:
366 if (!scanPublicOrSystem() && atEnd) {
367 resume(rule: 16);
368 return false;
369 }
370 dtdName = symString(index: 3);
371 break;
372
373 case 17:
374 case 18:
375 dtdName = symString(index: 3);
376 Q_FALLTHROUGH();
377
378 case 19:
379 case 20:
380 setType(QXmlStreamReader::DTD);
381 text = &textBuffer;
382 break;
383
384 case 21:
385 scanDtd = true;
386 break;
387
388 case 22:
389 scanDtd = false;
390 break;
391
392 case 37:
393 if (!scanString(str: spell[EMPTY], tokenToInject: EMPTY, requireSpace: false)
394 && !scanString(str: spell[ANY], tokenToInject: ANY, requireSpace: false)
395 && atEnd) {
396 resume(rule: 37);
397 return false;
398 }
399 break;
400
401 case 43:
402 if (!scanString(str: spell[PCDATA], tokenToInject: PCDATA, requireSpace: false) && atEnd) {
403 resume(rule: 43);
404 return false;
405 }
406 break;
407
408 case 68: {
409 lastAttributeIsCData = true;
410 } break;
411
412 case 78:
413 if (!scanAfterDefaultDecl() && atEnd) {
414 resume(rule: 78);
415 return false;
416 }
417 break;
418
419 case 83:
420 sym(index: 1) = sym(index: 2);
421 lastAttributeValue.clear();
422 lastAttributeIsCData = false;
423 if (!scanAttType() && atEnd) {
424 resume(rule: 83);
425 return false;
426 }
427 break;
428
429 case 84: {
430 DtdAttribute &dtdAttribute = dtdAttributes.push();
431 dtdAttribute.tagName.clear();
432 dtdAttribute.isCDATA = lastAttributeIsCData;
433 dtdAttribute.attributePrefix = addToStringStorage(s: symPrefix(index: 1));
434 dtdAttribute.attributeName = addToStringStorage(s: symString(index: 1));
435 dtdAttribute.attributeQualifiedName = addToStringStorage(s: symName(index: 1));
436 dtdAttribute.isNamespaceAttribute = (dtdAttribute.attributePrefix == "xmlns"_L1
437 || (dtdAttribute.attributePrefix.isEmpty()
438 && dtdAttribute.attributeName == "xmlns"_L1));
439 if (lastAttributeValue.isNull()) {
440 dtdAttribute.defaultValue.clear();
441 } else {
442 if (dtdAttribute.isCDATA)
443 dtdAttribute.defaultValue = addToStringStorage(s: lastAttributeValue);
444 else
445 dtdAttribute.defaultValue = addToStringStorage(s: lastAttributeValue.toString().simplified());
446
447 }
448 } break;
449
450 case 88: {
451 if (referenceToUnparsedEntityDetected && !standalone)
452 break;
453 qsizetype n = dtdAttributes.size();
454 XmlStringRef tagName = addToStringStorage(s: symName(index: 3));
455 while (n--) {
456 DtdAttribute &dtdAttribute = dtdAttributes[n];
457 if (!dtdAttribute.tagName.isNull())
458 break;
459 dtdAttribute.tagName = tagName;
460 for (qsizetype i = 0; i < n; ++i) {
461 if ((dtdAttributes[i].tagName.isNull() || dtdAttributes[i].tagName == tagName)
462 && dtdAttributes[i].attributeQualifiedName == dtdAttribute.attributeQualifiedName) {
463 dtdAttribute.attributeQualifiedName.clear(); // redefined, delete it
464 break;
465 }
466 }
467 }
468 } break;
469
470 case 89: {
471 if (!scanPublicOrSystem() && atEnd) {
472 resume(rule: 89);
473 return false;
474 }
475 EntityDeclaration &entityDeclaration = entityDeclarations.push();
476 entityDeclaration.clear();
477 entityDeclaration.name = symString(index: 3);
478 } break;
479
480 case 90: {
481 if (!scanPublicOrSystem() && atEnd) {
482 resume(rule: 90);
483 return false;
484 }
485 EntityDeclaration &entityDeclaration = entityDeclarations.push();
486 entityDeclaration.clear();
487 entityDeclaration.name = symString(index: 5);
488 entityDeclaration.parameter = true;
489 } break;
490
491 case 91: {
492 if (!scanNData() && atEnd) {
493 resume(rule: 91);
494 return false;
495 }
496 EntityDeclaration &entityDeclaration = entityDeclarations.top();
497 entityDeclaration.systemId = symString(index: 3);
498 entityDeclaration.external = true;
499 } break;
500
501 case 92: {
502 if (!scanNData() && atEnd) {
503 resume(rule: 92);
504 return false;
505 }
506 EntityDeclaration &entityDeclaration = entityDeclarations.top();
507 checkPublicLiteral(publicId: (entityDeclaration.publicId = symString(index: 3)));
508 entityDeclaration.systemId = symString(index: 5);
509 entityDeclaration.external = true;
510 } break;
511
512 case 93: {
513 EntityDeclaration &entityDeclaration = entityDeclarations.top();
514 entityDeclaration.notationName = symString(index: 3);
515 if (entityDeclaration.parameter)
516 raiseWellFormedError(message: QXmlStream::tr(sourceText: "NDATA in parameter entity declaration."));
517 }
518 Q_FALLTHROUGH();
519
520 case 94:
521 case 95: {
522 if (referenceToUnparsedEntityDetected && !standalone) {
523 entityDeclarations.pop();
524 break;
525 }
526 EntityDeclaration &entityDeclaration = entityDeclarations.top();
527 if (!entityDeclaration.external)
528 entityDeclaration.value = symString(index: 2);
529 auto &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash;
530 if (!hash.contains(key: entityDeclaration.name)) {
531 Entity entity(entityDeclaration.name.toString(),
532 entityDeclaration.value.toString());
533 entity.unparsed = (!entityDeclaration.notationName.isNull());
534 entity.external = entityDeclaration.external;
535 hash.insert(key: qToStringViewIgnoringNull(s: entity.name), value: entity);
536 }
537 } break;
538
539 case 96: {
540 setType(QXmlStreamReader::ProcessingInstruction);
541 const qsizetype pos = sym(index: 4).pos + sym(index: 4).len;
542 processingInstructionTarget = symString(index: 3);
543 if (scanUntil(str: "?>")) {
544 processingInstructionData = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 2);
545 if (!processingInstructionTarget.view().compare(s: "xml"_L1, cs: Qt::CaseInsensitive)) {
546 raiseWellFormedError(message: QXmlStream::tr(sourceText: "XML declaration not at start of document."));
547 }
548 else if (!QXmlUtils::isNCName(ncName: processingInstructionTarget))
549 raiseWellFormedError(message: QXmlStream::tr(sourceText: "%1 is an invalid processing instruction name.")
550 .arg(a: processingInstructionTarget));
551 } else if (type != QXmlStreamReader::Invalid){
552 resume(rule: 96);
553 return false;
554 }
555 } break;
556
557 case 97:
558 setType(QXmlStreamReader::ProcessingInstruction);
559 processingInstructionTarget = symString(index: 3);
560 if (!processingInstructionTarget.view().compare(s: "xml"_L1, cs: Qt::CaseInsensitive))
561 raiseWellFormedError(message: QXmlStream::tr(sourceText: "Invalid processing instruction name."));
562 break;
563
564 case 98:
565 if (!scanAfterLangleBang() && atEnd) {
566 resume(rule: 98);
567 return false;
568 }
569 break;
570
571 case 99:
572 if (!scanUntil(str: "--")) {
573 resume(rule: 99);
574 return false;
575 }
576 break;
577
578 case 100: {
579 setType(QXmlStreamReader::Comment);
580 const qsizetype pos = sym(index: 1).pos + 4;
581 text = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
582 } break;
583
584 case 101: {
585 setType(QXmlStreamReader::Characters);
586 isCDATA = true;
587 isWhitespace = false;
588 const qsizetype pos = sym(index: 2).pos;
589 if (scanUntil(str: "]]>", tokenToInject: -1)) {
590 text = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
591 } else {
592 resume(rule: 101);
593 return false;
594 }
595 } break;
596
597 case 102: {
598 if (!scanPublicOrSystem() && atEnd) {
599 resume(rule: 102);
600 return false;
601 }
602 NotationDeclaration &notationDeclaration = notationDeclarations.push();
603 notationDeclaration.name = symString(index: 3);
604 } break;
605
606 case 103: {
607 NotationDeclaration &notationDeclaration = notationDeclarations.top();
608 notationDeclaration.systemId = symString(index: 3);
609 notationDeclaration.publicId.clear();
610 } break;
611
612 case 104: {
613 NotationDeclaration &notationDeclaration = notationDeclarations.top();
614 notationDeclaration.systemId.clear();
615 checkPublicLiteral(publicId: (notationDeclaration.publicId = symString(index: 3)));
616 } break;
617
618 case 105: {
619 NotationDeclaration &notationDeclaration = notationDeclarations.top();
620 checkPublicLiteral(publicId: (notationDeclaration.publicId = symString(index: 3)));
621 notationDeclaration.systemId = symString(index: 5);
622 } break;
623
624 case 129:
625 isWhitespace = false;
626 Q_FALLTHROUGH();
627
628 case 130:
629 sym(index: 1).len += fastScanContentCharList();
630 if (atEnd && !inParseEntity) {
631 resume(rule: 130);
632 return false;
633 }
634 break;
635
636 case 139:
637 if (!textBuffer.isEmpty()) {
638 setType(QXmlStreamReader::Characters);
639 text = &textBuffer;
640 }
641 break;
642
643 case 140:
644 case 141:
645 clearSym();
646 break;
647
648 case 142:
649 case 143:
650 sym(index: 1) = sym(index: 2);
651 break;
652
653 case 144:
654 case 145:
655 case 146:
656 case 147:
657 sym(index: 1).len += sym(index: 2).len;
658 break;
659
660 case 173:
661 if (normalizeLiterals)
662 textBuffer.data()[textBuffer.size()-1] = u' ';
663 break;
664
665 case 174:
666 sym(index: 1).len += fastScanLiteralContent();
667 if (atEnd) {
668 resume(rule: 174);
669 return false;
670 }
671 break;
672
673 case 175: {
674 if (!QXmlUtils::isPublicID(candidate: symString(index: 1))) {
675 raiseWellFormedError(message: QXmlStream::tr(sourceText: "%1 is an invalid PUBLIC identifier.").arg(a: symString(index: 1)));
676 resume(rule: 175);
677 return false;
678 }
679 } break;
680
681 case 176:
682 case 177:
683 clearSym();
684 break;
685
686 case 178:
687 case 179:
688 sym(index: 1) = sym(index: 2);
689 break;
690
691 case 180:
692 case 181:
693 case 182:
694 case 183:
695 sym(index: 1).len += sym(index: 2).len;
696 break;
697
698 case 213:
699 case 214:
700 clearSym();
701 break;
702
703 case 215:
704 case 216:
705 sym(index: 1) = sym(index: 2);
706 lastAttributeValue = symString(index: 1);
707 break;
708
709 case 217:
710 case 218:
711 case 219:
712 case 220:
713 sym(index: 1).len += sym(index: 2).len;
714 break;
715
716 case 229: {
717 XmlStringRef prefix = symPrefix(index: 1);
718 if (prefix.isEmpty() && symString(index: 1) == "xmlns"_L1 && namespaceProcessing) {
719 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
720 namespaceDeclaration.prefix.clear();
721
722 const XmlStringRef ns(symString(index: 5));
723 if (ns.view() == "http://www.w3.org/2000/xmlns/"_L1 ||
724 ns.view() == "http://www.w3.org/XML/1998/namespace"_L1)
725 raiseWellFormedError(message: QXmlStream::tr(sourceText: "Illegal namespace declaration."));
726 else
727 namespaceDeclaration.namespaceUri = addToStringStorage(s: ns);
728 } else {
729 Attribute &attribute = attributeStack.push();
730 attribute.key = sym(index: 1);
731 attribute.value = sym(index: 5);
732
733 XmlStringRef attributeQualifiedName = symName(index: 1);
734 bool normalize = false;
735 for (const DtdAttribute &dtdAttribute : std::as_const(t&: dtdAttributes)) {
736 if (!dtdAttribute.isCDATA
737 && dtdAttribute.tagName == qualifiedName
738 && dtdAttribute.attributeQualifiedName == attributeQualifiedName
739 ) {
740 normalize = true;
741 break;
742 }
743 }
744 if (normalize) {
745 // normalize attribute value (simplify and trim)
746 const qsizetype pos = textBuffer.size();
747 qsizetype n = 0;
748 bool wasSpace = true;
749 for (qsizetype i = 0; i < attribute.value.len; ++i) {
750 QChar c = textBuffer.at(i: attribute.value.pos + i);
751 if (c.unicode() == ' ') {
752 if (wasSpace)
753 continue;
754 wasSpace = true;
755 } else {
756 wasSpace = false;
757 }
758 textBuffer += textBuffer.at(i: attribute.value.pos + i);
759 ++n;
760 }
761 if (wasSpace)
762 while (n && textBuffer.at(i: pos + n - 1).unicode() == ' ')
763 --n;
764 attribute.value.pos = pos;
765 attribute.value.len = n;
766 }
767 if (prefix == "xmlns"_L1 && namespaceProcessing) {
768 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
769 XmlStringRef namespacePrefix = symString(symbol: attribute.key);
770 XmlStringRef namespaceUri = symString(symbol: attribute.value);
771 attributeStack.pop();
772 if (((namespacePrefix == "xml"_L1)
773 ^ (namespaceUri == "http://www.w3.org/XML/1998/namespace"_L1))
774 || namespaceUri == "http://www.w3.org/2000/xmlns/"_L1
775 || namespaceUri.isEmpty()
776 || namespacePrefix == "xmlns"_L1)
777 raiseWellFormedError(message: QXmlStream::tr(sourceText: "Illegal namespace declaration."));
778
779 namespaceDeclaration.prefix = addToStringStorage(s: namespacePrefix);
780 namespaceDeclaration.namespaceUri = addToStringStorage(s: namespaceUri);
781 }
782 }
783 } break;
784
785 case 235: {
786 normalizeLiterals = true;
787 Tag &tag = tagStack_push();
788 prefix = tag.namespaceDeclaration.prefix = addToStringStorage(s: symPrefix(index: 2));
789 name = tag.name = addToStringStorage(s: symString(index: 2));
790 qualifiedName = tag.qualifiedName = addToStringStorage(s: symName(index: 2));
791 if ((!prefix.isEmpty() && !QXmlUtils::isNCName(ncName: prefix)) || !QXmlUtils::isNCName(ncName: name))
792 raiseWellFormedError(message: QXmlStream::tr(sourceText: "Invalid XML name."));
793 } break;
794
795 case 236:
796 isEmptyElement = true;
797 Q_FALLTHROUGH();
798
799 case 237:
800 setType(QXmlStreamReader::StartElement);
801 resolveTag();
802 if (tagStack.size() == 1 && hasSeenTag && !inParseEntity)
803 raiseWellFormedError(message: QXmlStream::tr(sourceText: "Extra content at end of document."));
804 hasSeenTag = true;
805 break;
806
807 case 238: {
808 setType(QXmlStreamReader::EndElement);
809 Tag tag = tagStack_pop();
810
811 namespaceUri = tag.namespaceDeclaration.namespaceUri;
812 prefix = tag.namespaceDeclaration.prefix;
813 name = tag.name;
814 qualifiedName = tag.qualifiedName;
815 if (qualifiedName != symName(index: 3))
816 raiseWellFormedError(message: QXmlStream::tr(sourceText: "Opening and ending tag mismatch."));
817 } break;
818
819 case 239:
820 if (entitiesMustBeDeclared()) {
821 raiseWellFormedError(message: QXmlStream::tr(sourceText: "Entity '%1' not declared.").arg(a: unresolvedEntity));
822 break;
823 }
824 setType(QXmlStreamReader::EntityReference);
825 name = &unresolvedEntity;
826 break;
827
828 case 240: {
829 sym(index: 1).len += sym(index: 2).len + 1;
830 QStringView reference = symView(index: 2);
831 if (const auto it = entityHash.find(key: reference); it != entityHash.end()) {
832 Entity &entity = *it;
833 if (entity.unparsed) {
834 raiseWellFormedError(message: QXmlStream::tr(sourceText: "Reference to unparsed entity '%1'.").arg(a: reference));
835 } else {
836 if (!entity.hasBeenParsed) {
837 parseEntity(value: entity.value);
838 entity.hasBeenParsed = true;
839 }
840 if (entity.literal)
841 putStringLiteral(s: entity.value);
842 else if (referenceEntity(hash: &entityHash, entity))
843 putReplacement(s: entity.value);
844 textBuffer.chop(n: 2 + sym(index: 2).len);
845 clearSym();
846 }
847 break;
848 }
849
850 if (entityResolver) {
851 QString replacementText = resolveUndeclaredEntity(name: reference.toString());
852 if (!replacementText.isNull()) {
853 putReplacement(s: replacementText);
854 textBuffer.chop(n: 2 + sym(index: 2).len);
855 clearSym();
856 break;
857 }
858 }
859
860 injectToken(tokenToInject: UNRESOLVED_ENTITY);
861 unresolvedEntity = symString(index: 2).toString();
862 textBuffer.chop(n: 2 + sym(index: 2).len);
863 clearSym();
864
865 } break;
866
867 case 241: {
868 sym(index: 1).len += sym(index: 2).len + 1;
869 QStringView reference = symView(index: 2);
870 if (const auto it = parameterEntityHash.find(key: reference); it != parameterEntityHash.end()) {
871 referenceToParameterEntityDetected = true;
872 Entity &entity = *it;
873 if (entity.unparsed || entity.external) {
874 referenceToUnparsedEntityDetected = true;
875 } else {
876 if (referenceEntity(hash: &parameterEntityHash, entity))
877 putString(s: entity.value);
878 textBuffer.chop(n: 2 + sym(index: 2).len);
879 clearSym();
880 }
881 } else if (entitiesMustBeDeclared()) {
882 raiseWellFormedError(message: QXmlStream::tr(sourceText: "Entity '%1' not declared.").arg(a: symString(index: 2)));
883 }
884 } break;
885
886 case 242:
887 sym(index: 1).len += sym(index: 2).len + 1;
888 break;
889
890 case 243: {
891 sym(index: 1).len += sym(index: 2).len + 1;
892 QStringView reference = symView(index: 2);
893 if (const auto it = entityHash.find(key: reference); it != entityHash.end()) {
894 Entity &entity = *it;
895 if (entity.unparsed || entity.value.isNull()) {
896 raiseWellFormedError(message: QXmlStream::tr(sourceText: "Reference to external entity '%1' in attribute value.").arg(a: reference));
897 break;
898 }
899 if (!entity.hasBeenParsed) {
900 parseEntity(value: entity.value);
901 entity.hasBeenParsed = true;
902 }
903 if (entity.literal)
904 putStringLiteral(s: entity.value);
905 else if (referenceEntity(hash: &entityHash, entity))
906 putReplacementInAttributeValue(s: entity.value);
907 textBuffer.chop(n: 2 + sym(index: 2).len);
908 clearSym();
909 break;
910 }
911
912 if (entityResolver) {
913 QString replacementText = resolveUndeclaredEntity(name: reference.toString());
914 if (!replacementText.isNull()) {
915 putReplacement(s: replacementText);
916 textBuffer.chop(n: 2 + sym(index: 2).len);
917 clearSym();
918 break;
919 }
920 }
921 if (entitiesMustBeDeclared()) {
922 raiseWellFormedError(message: QXmlStream::tr(sourceText: "Entity '%1' not declared.").arg(a: reference));
923 }
924 } break;
925
926 case 244: {
927 if (char32_t s = resolveCharRef(symbolIndex: 3)) {
928 putStringLiteral(s: QChar::fromUcs4(c: s));
929 textBuffer.chop(n: 3 + sym(index: 3).len);
930 clearSym();
931 } else {
932 raiseWellFormedError(message: QXmlStream::tr(sourceText: "Invalid character reference."));
933 }
934 } break;
935
936 case 247:
937 case 248:
938 sym(index: 1).len += sym(index: 2).len;
939 break;
940
941 case 259:
942 sym(index: 1).len += fastScanSpace();
943 if (atEnd) {
944 resume(rule: 259);
945 return false;
946 }
947 break;
948
949 case 262: {
950 Value &val = sym(index: 1);
951 if (auto res = fastScanName(val: &val))
952 val.len += *res;
953 else
954 return false;
955
956 if (atEnd) {
957 resume(rule: 262);
958 return false;
959 }
960 } break;
961
962 case 263:
963 if (auto res = fastScanName())
964 sym(index: 1).len += *res;
965 else
966 return false;
967
968 if (atEnd) {
969 resume(rule: 263);
970 return false;
971 }
972 break;
973
974 case 264:
975 case 265:
976 case 266:
977 case 267:
978 case 268:
979 sym(index: 1).len += fastScanNMTOKEN();
980 if (atEnd) {
981 resume(rule: 268);
982 return false;
983 }
984
985 break;
986
987 default:
988 ;
989 } // switch
990 act = state_stack[tos] = nt_action (state: act, nt: lhs[r] - TERMINAL_COUNT);
991 if (type != QXmlStreamReader::NoToken)
992 return true;
993 } else {
994 parseError();
995 break;
996 }
997 }
998 return false;
999}
1000
1001#endif // feature xmlstreamreader
1002
1003QT_END_NAMESPACE
1004
1005#endif
1006
1007

source code of qtbase/src/corelib/serialization/qxmlstreamparser_p.h