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 auto symbol = symQName(1);
435 symbol.resetBackingStorage(addToStringStorage(symbol.all()));
436 dtdAttribute.attributePrefix = symbol.prefix();
437 dtdAttribute.attributeName = symbol.localPart();
438 dtdAttribute.attributeQualifiedName = symbol.qname();
439 dtdAttribute.isNamespaceAttribute = (dtdAttribute.attributePrefix == "xmlns"_L1
440 || (dtdAttribute.attributePrefix.isEmpty()
441 && dtdAttribute.attributeName == "xmlns"_L1));
442 if (lastAttributeValue.isNull()) {
443 dtdAttribute.defaultValue.clear();
444 } else {
445 if (dtdAttribute.isCDATA)
446 dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue);
447 else
448 dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue.toString().simplified());
449
450 }
451 } break;
452
453 case 88: {
454 if (referenceToUnparsedEntityDetected && !standalone)
455 break;
456 qsizetype n = dtdAttributes.size();
457 XmlStringRef tagName = addToStringStorage(symName(3));
458 while (n--) {
459 DtdAttribute &dtdAttribute = dtdAttributes[n];
460 if (!dtdAttribute.tagName.isNull())
461 break;
462 dtdAttribute.tagName = tagName;
463 for (qsizetype i = 0; i < n; ++i) {
464 if ((dtdAttributes[i].tagName.isNull() || dtdAttributes[i].tagName == tagName)
465 && dtdAttributes[i].attributeQualifiedName == dtdAttribute.attributeQualifiedName) {
466 dtdAttribute.attributeQualifiedName.clear(); // redefined, delete it
467 break;
468 }
469 }
470 }
471 } break;
472
473 case 89: {
474 if (!scanPublicOrSystem() && atEnd) {
475 resume(89);
476 return false;
477 }
478 EntityDeclaration &entityDeclaration = entityDeclarations.push();
479 entityDeclaration.clear();
480 entityDeclaration.name = symString(3);
481 } break;
482
483 case 90: {
484 if (!scanPublicOrSystem() && atEnd) {
485 resume(90);
486 return false;
487 }
488 EntityDeclaration &entityDeclaration = entityDeclarations.push();
489 entityDeclaration.clear();
490 entityDeclaration.name = symString(5);
491 entityDeclaration.parameter = true;
492 } break;
493
494 case 91: {
495 if (!scanNData() && atEnd) {
496 resume(91);
497 return false;
498 }
499 EntityDeclaration &entityDeclaration = entityDeclarations.top();
500 entityDeclaration.systemId = symString(3);
501 entityDeclaration.external = true;
502 } break;
503
504 case 92: {
505 if (!scanNData() && atEnd) {
506 resume(92);
507 return false;
508 }
509 EntityDeclaration &entityDeclaration = entityDeclarations.top();
510 checkPublicLiteral((entityDeclaration.publicId = symString(3)));
511 entityDeclaration.systemId = symString(5);
512 entityDeclaration.external = true;
513 } break;
514
515 case 93: {
516 EntityDeclaration &entityDeclaration = entityDeclarations.top();
517 entityDeclaration.notationName = symString(3);
518 if (entityDeclaration.parameter)
519 raiseWellFormedError(QXmlStream::tr("NDATA in parameter entity declaration."));
520 }
521 Q_FALLTHROUGH();
522
523 case 94:
524 case 95: {
525 if (referenceToUnparsedEntityDetected && !standalone) {
526 entityDeclarations.pop();
527 break;
528 }
529 EntityDeclaration &entityDeclaration = entityDeclarations.top();
530 if (!entityDeclaration.external)
531 entityDeclaration.value = symString(2);
532 auto &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash;
533 if (!hash.contains(entityDeclaration.name)) {
534 Entity entity(entityDeclaration.name.toString(),
535 entityDeclaration.value.toString());
536 entity.unparsed = (!entityDeclaration.notationName.isNull());
537 entity.external = entityDeclaration.external;
538 hash.insert(qToStringViewIgnoringNull(entity.name), entity);
539 }
540 } break;
541
542 case 96: {
543 setType(QXmlStreamReader::ProcessingInstruction);
544 const qsizetype pos = sym(4).pos + sym(4).len;
545 processingInstructionTarget = symString(3);
546 if (scanUntil("?>")) {
547 processingInstructionData = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 2);
548 if (!processingInstructionTarget.view().compare("xml"_L1, Qt::CaseInsensitive)) {
549 raiseWellFormedError(QXmlStream::tr("XML declaration not at start of document."));
550 }
551 else if (!QXmlUtils::isNCName(processingInstructionTarget))
552 raiseWellFormedError(QXmlStream::tr("%1 is an invalid processing instruction name.")
553 .arg(processingInstructionTarget));
554 } else if (type != QXmlStreamReader::Invalid){
555 resume(96);
556 return false;
557 }
558 } break;
559
560 case 97:
561 setType(QXmlStreamReader::ProcessingInstruction);
562 processingInstructionTarget = symString(3);
563 if (!processingInstructionTarget.view().compare("xml"_L1, Qt::CaseInsensitive))
564 raiseWellFormedError(QXmlStream::tr("Invalid processing instruction name."));
565 break;
566
567 case 98:
568 if (!scanAfterLangleBang() && atEnd) {
569 resume(98);
570 return false;
571 }
572 break;
573
574 case 99:
575 if (!scanUntil("--")) {
576 resume(99);
577 return false;
578 }
579 break;
580
581 case 100: {
582 setType(QXmlStreamReader::Comment);
583 const qsizetype pos = sym(1).pos + 4;
584 text = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
585 } break;
586
587 case 101: {
588 setType(QXmlStreamReader::Characters);
589 isCDATA = true;
590 isWhitespace = false;
591 const qsizetype pos = sym(2).pos;
592 if (scanUntil("]]>", -1)) {
593 text = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
594 } else {
595 resume(101);
596 return false;
597 }
598 } break;
599
600 case 102: {
601 if (!scanPublicOrSystem() && atEnd) {
602 resume(102);
603 return false;
604 }
605 NotationDeclaration &notationDeclaration = notationDeclarations.push();
606 notationDeclaration.name = symString(3);
607 } break;
608
609 case 103: {
610 NotationDeclaration &notationDeclaration = notationDeclarations.top();
611 notationDeclaration.systemId = symString(3);
612 notationDeclaration.publicId.clear();
613 } break;
614
615 case 104: {
616 NotationDeclaration &notationDeclaration = notationDeclarations.top();
617 notationDeclaration.systemId.clear();
618 checkPublicLiteral((notationDeclaration.publicId = symString(3)));
619 } break;
620
621 case 105: {
622 NotationDeclaration &notationDeclaration = notationDeclarations.top();
623 checkPublicLiteral((notationDeclaration.publicId = symString(3)));
624 notationDeclaration.systemId = symString(5);
625 } break;
626
627 case 129:
628 isWhitespace = false;
629 Q_FALLTHROUGH();
630
631 case 130:
632 sym(1).len += fastScanContentCharList();
633 if (atEnd && !inParseEntity) {
634 resume(130);
635 return false;
636 }
637 break;
638
639 case 139:
640 if (!textBuffer.isEmpty()) {
641 setType(QXmlStreamReader::Characters);
642 text = &textBuffer;
643 }
644 break;
645
646 case 140:
647 case 141:
648 clearSym();
649 break;
650
651 case 142:
652 case 143:
653 sym(1) = sym(2);
654 break;
655
656 case 144:
657 case 145:
658 case 146:
659 case 147:
660 sym(1).len += sym(2).len;
661 break;
662
663 case 173:
664 if (normalizeLiterals)
665 textBuffer.data()[textBuffer.size()-1] = u' ';
666 break;
667
668 case 174:
669 sym(1).len += fastScanLiteralContent();
670 if (atEnd) {
671 resume(174);
672 return false;
673 }
674 break;
675
676 case 175: {
677 if (!QXmlUtils::isPublicID(symString(1))) {
678 raiseWellFormedError(QXmlStream::tr("%1 is an invalid PUBLIC identifier.").arg(symString(1)));
679 resume(175);
680 return false;
681 }
682 } break;
683
684 case 176:
685 case 177:
686 clearSym();
687 break;
688
689 case 178:
690 case 179:
691 sym(1) = sym(2);
692 break;
693
694 case 180:
695 case 181:
696 case 182:
697 case 183:
698 sym(1).len += sym(2).len;
699 break;
700
701 case 213:
702 case 214:
703 clearSym();
704 break;
705
706 case 215:
707 case 216:
708 sym(1) = sym(2);
709 lastAttributeValue = symString(1);
710 break;
711
712 case 217:
713 case 218:
714 case 219:
715 case 220:
716 sym(1).len += sym(2).len;
717 break;
718
719 case 229: {
720 const XmlStringRef prfx = symPrefix(1);
721 if (prfx.isEmpty() && symString(1) == "xmlns"_L1 && namespaceProcessing) {
722 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
723 namespaceDeclaration.prefix.clear();
724
725 const XmlStringRef ns(symString(5));
726 if (ns.view() == "http://www.w3.org/2000/xmlns/"_L1 ||
727 ns.view() == "http://www.w3.org/XML/1998/namespace"_L1)
728 raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
729 else
730 namespaceDeclaration.namespaceUri = addToStringStorage(ns);
731 } else {
732 Attribute &attribute = attributeStack.push();
733 attribute.key = sym(1);
734 attribute.value = sym(5);
735
736 XmlStringRef attributeQualifiedName = symName(1);
737 bool normalize = false;
738 for (const DtdAttribute &dtdAttribute : std::as_const(dtdAttributes)) {
739 if (!dtdAttribute.isCDATA
740 && dtdAttribute.tagName == qualifiedName
741 && dtdAttribute.attributeQualifiedName == attributeQualifiedName
742 ) {
743 normalize = true;
744 break;
745 }
746 }
747 if (normalize) {
748 // normalize attribute value (simplify and trim)
749 const qsizetype pos = textBuffer.size();
750 qsizetype n = 0;
751 bool wasSpace = true;
752 for (qsizetype i = 0; i < attribute.value.len; ++i) {
753 QChar c = textBuffer.at(attribute.value.pos + i);
754 if (c.unicode() == ' ') {
755 if (wasSpace)
756 continue;
757 wasSpace = true;
758 } else {
759 wasSpace = false;
760 }
761 textBuffer += textBuffer.at(attribute.value.pos + i);
762 ++n;
763 }
764 if (wasSpace)
765 while (n && textBuffer.at(pos + n - 1).unicode() == ' ')
766 --n;
767 attribute.value.pos = pos;
768 attribute.value.len = n;
769 }
770 if (prfx == "xmlns"_L1 && namespaceProcessing) {
771 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
772 XmlStringRef namespacePrefix = symString(attribute.key);
773 XmlStringRef namespaceUri = symString(attribute.value);
774 attributeStack.pop();
775 if (((namespacePrefix == "xml"_L1)
776 ^ (namespaceUri == "http://www.w3.org/XML/1998/namespace"_L1))
777 || namespaceUri == "http://www.w3.org/2000/xmlns/"_L1
778 || namespaceUri.isEmpty()
779 || namespacePrefix == "xmlns"_L1)
780 raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
781
782 namespaceDeclaration.prefix = addToStringStorage(namespacePrefix);
783 namespaceDeclaration.namespaceUri = addToStringStorage(namespaceUri);
784 }
785 }
786 } break;
787
788 case 235: {
789 normalizeLiterals = true;
790 Tag &tag = tagStack_push();
791 auto symbol = symQName(2);
792 symbol.resetBackingStorage(addToStringStorage(symbol.all()));
793 prefix = tag.namespaceDeclaration.prefix = symbol.prefix();
794 name = tag.name = symbol.localPart();
795 qualifiedName = tag.qualifiedName = symbol.qname();
796 if ((!prefix.isEmpty() && !QXmlUtils::isNCName(prefix)) || !QXmlUtils::isNCName(name))
797 raiseWellFormedError(QXmlStream::tr("Invalid XML name."));
798 } break;
799
800 case 236:
801 isEmptyElement = true;
802 Q_FALLTHROUGH();
803
804 case 237:
805 setType(QXmlStreamReader::StartElement);
806 resolveTag();
807 if (tagStack.size() == 1 && hasSeenTag && !inParseEntity)
808 raiseWellFormedError(QXmlStream::tr("Extra content at end of document."));
809 hasSeenTag = true;
810 break;
811
812 case 238: {
813 setType(QXmlStreamReader::EndElement);
814 Tag tag = tagStack_pop();
815
816 namespaceUri = tag.namespaceDeclaration.namespaceUri;
817 prefix = tag.namespaceDeclaration.prefix;
818 name = tag.name;
819 qualifiedName = tag.qualifiedName;
820 if (qualifiedName != symName(3))
821 raiseWellFormedError(QXmlStream::tr("Opening and ending tag mismatch."));
822 } break;
823
824 case 239:
825 if (entitiesMustBeDeclared()) {
826 raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(unresolvedEntity));
827 break;
828 }
829 setType(QXmlStreamReader::EntityReference);
830 name = &unresolvedEntity;
831 break;
832
833 case 240: {
834 sym(1).len += sym(2).len + 1;
835 QStringView reference = symView(2);
836 if (const auto it = entityHash.find(reference); it != entityHash.end()) {
837 Entity &entity = *it;
838 if (entity.unparsed) {
839 raiseWellFormedError(QXmlStream::tr("Reference to unparsed entity '%1'.").arg(reference));
840 } else {
841 if (!entity.hasBeenParsed) {
842 parseEntity(entity.value);
843 entity.hasBeenParsed = true;
844 }
845 if (entity.literal)
846 putStringLiteral(entity.value);
847 else if (referenceEntity(&entityHash, entity))
848 putReplacement(entity.value);
849 textBuffer.chop(2 + sym(2).len);
850 clearSym();
851 }
852 break;
853 }
854
855 if (entityResolver) {
856 QString replacementText = resolveUndeclaredEntity(reference.toString());
857 if (!replacementText.isNull()) {
858 putReplacement(replacementText);
859 textBuffer.chop(2 + sym(2).len);
860 clearSym();
861 break;
862 }
863 }
864
865 injectToken(UNRESOLVED_ENTITY);
866 unresolvedEntity = symString(2).toString();
867 textBuffer.chop(2 + sym(2).len);
868 clearSym();
869
870 } break;
871
872 case 241: {
873 sym(1).len += sym(2).len + 1;
874 QStringView reference = symView(2);
875 if (const auto it = parameterEntityHash.find(reference); it != parameterEntityHash.end()) {
876 referenceToParameterEntityDetected = true;
877 Entity &entity = *it;
878 if (entity.unparsed || entity.external) {
879 referenceToUnparsedEntityDetected = true;
880 } else {
881 if (referenceEntity(&parameterEntityHash, entity))
882 putString(entity.value);
883 textBuffer.chop(2 + sym(2).len);
884 clearSym();
885 }
886 } else if (entitiesMustBeDeclared()) {
887 raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(symString(2)));
888 }
889 } break;
890
891 case 242:
892 sym(1).len += sym(2).len + 1;
893 break;
894
895 case 243: {
896 sym(1).len += sym(2).len + 1;
897 QStringView reference = symView(2);
898 if (const auto it = entityHash.find(reference); it != entityHash.end()) {
899 Entity &entity = *it;
900 if (entity.unparsed || entity.value.isNull()) {
901 raiseWellFormedError(QXmlStream::tr("Reference to external entity '%1' in attribute value.").arg(reference));
902 break;
903 }
904 if (!entity.hasBeenParsed) {
905 parseEntity(entity.value);
906 entity.hasBeenParsed = true;
907 }
908 if (entity.literal)
909 putStringLiteral(entity.value);
910 else if (referenceEntity(&entityHash, entity))
911 putReplacementInAttributeValue(entity.value);
912 textBuffer.chop(2 + sym(2).len);
913 clearSym();
914 break;
915 }
916
917 if (entityResolver) {
918 QString replacementText = resolveUndeclaredEntity(reference.toString());
919 if (!replacementText.isNull()) {
920 putReplacement(replacementText);
921 textBuffer.chop(2 + sym(2).len);
922 clearSym();
923 break;
924 }
925 }
926 if (entitiesMustBeDeclared()) {
927 raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(reference));
928 }
929 } break;
930
931 case 244: {
932 if (char32_t s = resolveCharRef(3)) {
933 putStringLiteral(QChar::fromUcs4(s));
934 textBuffer.chop(3 + sym(3).len);
935 clearSym();
936 } else {
937 raiseWellFormedError(QXmlStream::tr("Invalid character reference."));
938 }
939 } break;
940
941 case 247:
942 case 248:
943 sym(1).len += sym(2).len;
944 break;
945
946 case 259:
947 sym(1).len += fastScanSpace();
948 if (atEnd) {
949 resume(259);
950 return false;
951 }
952 break;
953
954 case 262: {
955 Value &val = sym(1);
956 if (auto res = fastScanName(&val))
957 val.len += *res;
958 else
959 return false;
960
961 if (atEnd) {
962 resume(262);
963 return false;
964 }
965 } break;
966
967 case 263:
968 if (auto res = fastScanName())
969 sym(1).len += *res;
970 else
971 return false;
972
973 if (atEnd) {
974 resume(263);
975 return false;
976 }
977 break;
978
979 case 264:
980 case 265:
981 case 266:
982 case 267:
983 case 268:
984 sym(1).len += fastScanNMTOKEN();
985 if (atEnd) {
986 resume(268);
987 return false;
988 }
989
990 break;
991
992 default:
993 ;
994 } // switch
995 act = state_stack[tos] = nt_action (act, lhs[r] - TERMINAL_COUNT);
996 if (type != QXmlStreamReader::NoToken)
997 return true;
998 } else {
999 parseError();
1000 break;
1001 }
1002 }
1003 return false;
1004}
1005
1006#endif // feature xmlstreamreader
1007
1008QT_END_NAMESPACE
1009
1010#endif
Combined button and popup list for selecting options.