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