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