4#include "QtCore/qxmlstream.h"
6#if QT_CONFIG(xmlstream)
18#include <private/qoffsetstringarray_p.h>
19#include <private/qtools_p.h>
24#include <private/qstringconverter_p.h>
25#include <private/qstringiterator_p.h>
33enum { StreamEOF = ~0U };
36template <
typename Range>
41 auto begin() {
return std::make_reverse_iterator(std::end(*
r)); }
42 auto end() {
return std::make_reverse_iterator(std::begin(*
r)); }
48template <
typename Range>
49void reversed(
const Range &&) =
delete;
55 return R{haystack,
uchar(needle)};
61 return R{haystack,
uchar(needle)};
67 return R{haystack, needle};
73 return R{haystack, needle};
79 return R{haystack, needle};
88#define WRAP(method, Needle) \
89 auto method (QAnyStringView s, Needle needle) noexcept \
91 return s.visit([needle](auto s) { \
92 auto r = transform(s, needle); \
93 return r.haystack. method (r.needle); \
208QXmlStreamEntityResolver::~QXmlStreamEntityResolver()
231QString QXmlStreamEntityResolver::resolveUndeclaredEntity(
const QString &)
236#if QT_CONFIG(xmlstreamreader)
241 return entityResolver->resolveUndeclaredEntity(
name);
259void QXmlStreamReader::setEntityResolver(QXmlStreamEntityResolver *resolver)
261 Q_D(QXmlStreamReader);
262 d->entityResolver = resolver;
272QXmlStreamEntityResolver *QXmlStreamReader::entityResolver()
const
274 Q_D(
const QXmlStreamReader);
275 return d->entityResolver;
430QXmlStreamReader::QXmlStreamReader()
466 Q_D(QXmlStreamReader);
469 d->dataBuffer =
data.toUtf8();
471 d->lockEncoding =
true;
477 d->lockEncoding =
true;
490QXmlStreamReader::QXmlStreamReader(
const QByteArray &
data, PrivateConstructorTag)
493 Q_D(QXmlStreamReader);
494 d->dataBuffer =
data;
500QXmlStreamReader::~QXmlStreamReader()
502 Q_D(QXmlStreamReader);
521 Q_D(QXmlStreamReader);
522 if (
d->deleteDevice) {
524 d->deleteDevice =
false;
537QIODevice *QXmlStreamReader::device()
const
539 Q_D(
const QXmlStreamReader);
565 Q_D(QXmlStreamReader);
568 d->lockEncoding =
true;
569 if (!
d->decoder.isValid())
571 addDataImpl(
data.toUtf8());
575 if (!
d->decoder.isValid())
592 Q_D(QXmlStreamReader);
594 qWarning(
"QXmlStreamReader: addData() with device()");
597 d->dataBuffer +=
data;
606void QXmlStreamReader::clear()
608 Q_D(QXmlStreamReader);
632bool QXmlStreamReader::atEnd()
const
634 Q_D(
const QXmlStreamReader);
636 && ((
d->type == QXmlStreamReader::Invalid &&
d->error == PrematureEndOfDocumentError)
637 || (
d->type == QXmlStreamReader::EndDocument))) {
639 return d->device->atEnd();
641 return !
d->dataBuffer.size();
643 return (
d->atEnd ||
d->type == QXmlStreamReader::Invalid);
665QXmlStreamReader::TokenType QXmlStreamReader::readNext()
667 Q_D(QXmlStreamReader);
669 if (!
d->hasCheckedStartDocument)
670 if (!
d->checkStartDocument())
673 if (
d->atEnd &&
d->type != EndDocument &&
d->type !=
Invalid)
674 d->raiseError(PrematureEndOfDocumentError);
675 else if (!
d->atEnd &&
d->type == EndDocument)
676 d->raiseWellFormedError(QXmlStream::tr(
"Extra content at end of document."));
677 }
else if (
d->error == PrematureEndOfDocumentError) {
699QXmlStreamReader::TokenType QXmlStreamReader::tokenType()
const
701 Q_D(
const QXmlStreamReader);
722bool QXmlStreamReader::readNextStartElement()
724 while (readNext() !=
Invalid) {
725 if (isEndElement() || isEndDocument())
727 else if (isStartElement())
744void QXmlStreamReader::skipCurrentElement()
750 else if (isStartElement())
766 "ProcessingInstruction"
786void QXmlStreamReader::setNamespaceProcessing(
bool enable)
788 Q_D(QXmlStreamReader);
789 d->namespaceProcessing =
enable;
792bool QXmlStreamReader::namespaceProcessing()
const
794 Q_D(
const QXmlStreamReader);
795 return d->namespaceProcessing;
802QString QXmlStreamReader::tokenString()
const
804 Q_D(
const QXmlStreamReader);
814 return QLatin1StringView(QXmlStreamReader_XmlContextString.at(
static_cast<int>(ctxt)));
821 tagStack.reserve(16);
822 tagStackStringStorage.reserve(32);
823 tagStackStringStorageSize = 0;
824 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
825 namespaceDeclaration.prefix = addToStringStorage(u
"xml");
826 namespaceDeclaration.namespaceUri = addToStringStorage(u
"http://www.w3.org/XML/1998/namespace");
827 initialTagStackStringStorageSize = tagStackStringStorageSize;
831#if QT_CONFIG(xmlstreamreader)
837 deleteDevice =
false;
840 state_stack =
nullptr;
842 entityResolver =
nullptr;
844#define ADD_PREDEFINED(n, v) \
846 Entity e = Entity::createLiteral(n##_L1, v##_L1); \
847 entityHash.insert(qToStringViewIgnoringNull(e.name), std::move(e)); \
849 ADD_PREDEFINED(
"lt",
"<");
850 ADD_PREDEFINED(
"gt",
">");
851 ADD_PREDEFINED(
"amp",
"&");
852 ADD_PREDEFINED(
"apos",
"'");
853 ADD_PREDEFINED(
"quot",
"\"");
902 type = QXmlStreamReader::NoToken;
903 error = QXmlStreamReader::NoError;
914 Q_Q(QXmlStreamReader);
961 if (peekc == StreamEOF) {
1020 while ((
c =
getChar()) != StreamEOF) {
1035 if (
c < 0x20 || (
c > 0xFFFD &&
c < 0x10000) ||
c > QChar::LastValidCodePoint ) {
1047 if (tokenToInject >= 0)
1087 if (tokenToInject >= 0)
1195 while ((
c =
getChar()) != StreamEOF) {
1224 if (!(
c & 0xff0000)) {
1245 while ((
c =
getChar()) != StreamEOF) {
1278 while ((
c =
getChar()) != StreamEOF) {
1320 if (!(
c & 0xff0000)) {
1343 while ((
c =
getChar()) != StreamEOF) {
1348 return std::nullopt;
1377 if (
val &&
val->prefix ==
n + 1) {
1385 if (
val->prefix == 0) {
1410enum NameChar { NameBeginning, NameNotBeginning, NotName };
1412static const char Begi =
static_cast<char>(NameBeginning);
1413static const char NtBg =
static_cast<char>(NameNotBeginning);
1414static const char NotN =
static_cast<char>(NotName);
1416static const char nameCharTable[128] =
1419 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
1420 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
1422 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
1423 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
1425 NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
1426 NotN, NotN, NotN, NotN, NotN, NtBg, NtBg, NotN,
1428 NtBg, NtBg, NtBg, NtBg, NtBg, NtBg, NtBg, NtBg,
1429 NtBg, NtBg, Begi, NotN, NotN, NotN, NotN, NotN,
1431 NotN, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
1432 Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
1434 Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
1435 Begi, Begi, Begi, NotN, NotN, NotN, NotN, Begi,
1437 NotN, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
1438 Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
1440 Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
1441 Begi, Begi, Begi, NotN, NotN, NotN, NotN, NotN
1444static inline NameChar fastDetermineNameChar(
QChar ch)
1448 return static_cast<NameChar
>(nameCharTable[uc]);
1450 QChar::Category cat =
ch.category();
1452 if ((cat >= QChar::Letter_Uppercase && cat <= QChar::Letter_Other)
1453 || cat == QChar::Number_Letter)
1454 return NameBeginning;
1455 if ((cat >= QChar::Number_DecimalDigit && cat <= QChar::Number_Other)
1456 || (cat >= QChar::Mark_NonSpacing && cat <= QChar::Mark_Enclosing))
1457 return NameNotBeginning;
1465 while ((
c =
getChar()) != StreamEOF) {
1466 if (fastDetermineNameChar(
QChar(
c)) == NotName) {
1504 char16_t c =
it->unicode();
1505 if (
c ==
'\n' ||
c ==
'\r')
1515 char16_t c =
it->unicode();
1516 if (
c ==
'&' ||
c ==
';')
1518 else if (
c ==
'\n' ||
c ==
'\r')
1586 if (namespaceDeclaration.prefix ==
prefix) {
1587 return namespaceDeclaration.namespaceUri;
1609 if (!dtdAttribute.isNamespaceAttribute
1610 || dtdAttribute.defaultValue.isNull()
1612 || dtdAttribute.attributeQualifiedName.
isNull())
1619 if (dtdAttribute.attributePrefix.isEmpty() && dtdAttribute.attributeName ==
"xmlns"_L1) {
1621 namespaceDeclaration.prefix.clear();
1624 if (
ns ==
"http://www.w3.org/2000/xmlns/"_L1 ||
1625 ns ==
"http://www.w3.org/XML/1998/namespace"_L1)
1628 namespaceDeclaration.namespaceUri =
ns;
1629 }
else if (dtdAttribute.attributePrefix ==
"xmlns"_L1) {
1631 XmlStringRef namespacePrefix = dtdAttribute.attributeName;
1633 if (((namespacePrefix ==
"xml"_L1)
1634 ^ (
namespaceUri ==
"http://www.w3.org/XML/1998/namespace"_L1))
1637 || namespacePrefix ==
"xmlns"_L1)
1640 namespaceDeclaration.prefix = namespacePrefix;
1679 if (dtdAttribute.isNamespaceAttribute
1680 || dtdAttribute.defaultValue.isNull()
1682 || dtdAttribute.attributeQualifiedName.
isNull())
1693 attribute.m_name = dtdAttribute.attributeName;
1694 attribute.m_qualifiedName = dtdAttribute.attributeQualifiedName;
1695 attribute.m_value = dtdAttribute.defaultValue;
1697 if (!dtdAttribute.attributePrefix.isEmpty()) {
1714 publicNamespaceDeclaration.m_prefix = namespaceDeclaration.prefix;
1715 publicNamespaceDeclaration.m_namespaceUri = namespaceDeclaration.namespaceUri;
1725 publicNotationDeclaration.m_name = notationDeclaration.name;
1726 publicNotationDeclaration.m_systemId = notationDeclaration.systemId;
1727 publicNotationDeclaration.m_publicId = notationDeclaration.publicId;
1735 publicEntityDeclaration.m_name = entityDeclaration.name;
1736 publicEntityDeclaration.m_notationName = entityDeclaration.notationName;
1737 publicEntityDeclaration.m_systemId = entityDeclaration.systemId;
1738 publicEntityDeclaration.m_publicId = entityDeclaration.publicId;
1739 publicEntityDeclaration.m_value = entityDeclaration.value;
1750 if (
sym(symbolIndex).
c ==
'x')
1755 ok &= (
s == 0x9 ||
s == 0xa ||
s == 0xd || (
s >= 0x20 &&
s <= 0xd7ff)
1756 || (
s >= 0xe000 &&
s <= 0xfffd) || (
s >= 0x10000 &&
s <= QChar::LastValidCodePoint));
1766 const char16_t *
data = publicId.
utf16();
1769 for (
i = publicId.
size() - 1;
i >= 0; --
i) {
1772 case ' ':
case '\n':
case '\r':
case '-':
case '(':
case ')':
1773 case '+':
case ',':
case '.':
case '/':
case ':':
case '=':
1774 case '?':
case ';':
case '!':
case '*':
case '#':
case '@':
1775 case '$':
case '_':
case '%':
case '\'':
case '\"':
1799 type = QXmlStreamReader::StartDocument;
1802 raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
1812 err = QXmlStream::tr(
"Invalid XML version string.");
1814 err = QXmlStream::tr(
"Unsupported XML version.");
1833 err = QXmlStream::tr(
"The standalone pseudo attribute must appear after the encoding.");
1835 err = QXmlStream::tr(
"%1 is an invalid encoding name.").
arg(
value);
1841 err = QXmlStream::tr(
"Encoding %1 is unsupported").
arg(
value);
1849 if (
value ==
"yes"_L1)
1851 else if (
value ==
"no"_L1)
1854 err = QXmlStream::tr(
"Standalone accepts only yes or no.");
1856 err = QXmlStream::tr(
"Invalid attribute in XML declaration: %1 = %2").
arg(
key).
arg(
value);
1868 this->error =
error;
1871 if (
error == QXmlStreamReader::PrematureEndOfDocumentError)
1872 errorString = QXmlStream::tr(
"Premature end of document.");
1873 else if (
error == QXmlStreamReader::CustomError)
1874 errorString = QXmlStream::tr(
"Invalid document.");
1877 type = QXmlStreamReader::Invalid;
1888 raiseError(QXmlStreamReader::NotWellFormedError,
1889 QXmlStream::tr(
"Length of XML attribute name exceeds implementation limits (4KiB "
1897 raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
1911 if (nexpected < nmax)
1916 if (nexpected && nexpected < nmax) {
1918 QString exp_str = QXmlStream::tr(
"'%1'",
"expected")
1920 if (nexpected == 2) {
1922 exp_str = QXmlStream::tr(
"%1 or '%2'",
"expected")
1924 }
else if (nexpected > 2) {
1926 for (;
s < nexpected - 1; ++
s) {
1928 exp_str = QXmlStream::tr(
"%1, '%2'",
"expected")
1932 exp_str = QXmlStream::tr(
"%1, or '%2'",
"expected")
1935 error_message = QXmlStream::tr(
"Expected %1, but got '%2'.")
1946 if (
error == QXmlStreamReader::NoError)
1947 raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
1954qint64 QXmlStreamReader::lineNumber()
const
1956 Q_D(
const QXmlStreamReader);
1957 return d->lineNumber + 1;
1964qint64 QXmlStreamReader::columnNumber()
const
1966 Q_D(
const QXmlStreamReader);
1967 return d->characterOffset -
d->lastLineStart +
d->readBufferPos;
1974qint64 QXmlStreamReader::characterOffset()
const
1976 Q_D(
const QXmlStreamReader);
1977 return d->characterOffset +
d->readBufferPos;
1986 Q_D(
const QXmlStreamReader);
1997QXmlStreamNotationDeclarations QXmlStreamReader::notationDeclarations()
const
1999 Q_D(
const QXmlStreamReader);
2000 if (
d->notationDeclarations.size())
2012QXmlStreamEntityDeclarations QXmlStreamReader::entityDeclarations()
const
2014 Q_D(
const QXmlStreamReader);
2015 if (
d->entityDeclarations.size())
2029 Q_D(
const QXmlStreamReader);
2030 if (
d->type == QXmlStreamReader::DTD)
2044 Q_D(
const QXmlStreamReader);
2045 if (
d->type == QXmlStreamReader::DTD)
2046 return d->dtdPublicId;
2059 Q_D(
const QXmlStreamReader);
2060 if (
d->type == QXmlStreamReader::DTD)
2061 return d->dtdSystemId;
2074int QXmlStreamReader::entityExpansionLimit()
const
2076 Q_D(
const QXmlStreamReader);
2077 return d->entityExpansionLimit;
2095void QXmlStreamReader::setEntityExpansionLimit(
int limit)
2097 Q_D(QXmlStreamReader);
2098 d->entityExpansionLimit =
limit;
2110QXmlStreamNamespaceDeclarations QXmlStreamReader::namespaceDeclarations()
const
2112 Q_D(
const QXmlStreamReader);
2113 if (
d->publicNamespaceDeclarations.isEmpty() &&
d->type == StartElement)
2129void QXmlStreamReader::addExtraNamespaceDeclaration(
const QXmlStreamNamespaceDeclaration &extraNamespaceDeclaration)
2131 Q_D(QXmlStreamReader);
2133 namespaceDeclaration.
prefix =
d->addToStringStorage(extraNamespaceDeclaration.prefix());
2134 namespaceDeclaration.
namespaceUri =
d->addToStringStorage(extraNamespaceDeclaration.namespaceUri());
2144void QXmlStreamReader::addExtraNamespaceDeclarations(
const QXmlStreamNamespaceDeclarations &extraNamespaceDeclarations)
2146 for (
const auto &extraNamespaceDeclaration : extraNamespaceDeclarations)
2147 addExtraNamespaceDeclaration(extraNamespaceDeclaration);
2168QString QXmlStreamReader::readElementText(ReadElementTextBehaviour behaviour)
2170 Q_D(QXmlStreamReader);
2171 if (isStartElement()) {
2174 switch (readNext()) {
2176 case EntityReference:
2181 case ProcessingInstruction:
2185 if (behaviour == SkipChildElements) {
2186 skipCurrentElement();
2188 }
else if (behaviour == IncludeChildElements) {
2189 result += readElementText(behaviour);
2194 if (
d->error || behaviour == ErrorOnUnexpectedElement) {
2196 d->raiseError(UnexpectedElementError, QXmlStream::tr(
"Expected character data."));
2211 Q_D(QXmlStreamReader);
2212 d->raiseError(CustomError,
message);
2220QString QXmlStreamReader::errorString()
const
2222 Q_D(
const QXmlStreamReader);
2223 if (
d->type == QXmlStreamReader::Invalid)
2224 return d->errorString;
2232QXmlStreamReader::Error QXmlStreamReader::error()
const
2234 Q_D(
const QXmlStreamReader);
2235 if (
d->type == QXmlStreamReader::Invalid)
2243QStringView QXmlStreamReader::processingInstructionTarget()
const
2245 Q_D(
const QXmlStreamReader);
2246 return d->processingInstructionTarget;
2252QStringView QXmlStreamReader::processingInstructionData()
const
2254 Q_D(
const QXmlStreamReader);
2255 return d->processingInstructionData;
2267 Q_D(
const QXmlStreamReader);
2278 Q_D(
const QXmlStreamReader);
2279 return d->namespaceUri;
2294QStringView QXmlStreamReader::qualifiedName()
const
2296 Q_D(
const QXmlStreamReader);
2297 return d->qualifiedName;
2311 Q_D(
const QXmlStreamReader);
2318QXmlStreamAttributes QXmlStreamReader::attributes()
const
2320 Q_D(
const QXmlStreamReader);
2321 return d->attributes;
2346QXmlStreamAttribute::QXmlStreamAttribute()
2348 m_isDefault =
false;
2356 m_namespaceUri = namespaceUri;
2357 m_name = m_qualifiedName =
name;
2359 m_namespaceUri = namespaceUri;
2365QXmlStreamAttribute::QXmlStreamAttribute(
const QString &qualifiedName,
const QString &
value)
2368 m_name = qualifiedName.
mid(colon + 1);
2369 m_qualifiedName = qualifiedName;
2475QXmlStreamNotationDeclaration::QXmlStreamNotationDeclaration()
2537QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration()
2546QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration(
const QString &prefix,
const QString &namespaceUri)
2549 m_namespaceUri = namespaceUri;
2595QXmlStreamEntityDeclaration::QXmlStreamEntityDeclaration()
2666 if (
attribute.qualifiedName() == qualifiedName)
2687 append(QXmlStreamAttribute(qualifiedName,
value));
2690#if QT_CONFIG(xmlstreamreader)
2727bool QXmlStreamReader::isWhitespace()
const
2729 Q_D(
const QXmlStreamReader);
2730 return d->type == QXmlStreamReader::Characters &&
d->isWhitespace;
2738bool QXmlStreamReader::isCDATA()
const
2740 Q_D(
const QXmlStreamReader);
2741 return d->type == QXmlStreamReader::Characters &&
d->isCDATA;
2754bool QXmlStreamReader::isStandaloneDocument()
const
2756 Q_D(
const QXmlStreamReader);
2757 return d->standalone;
2770bool QXmlStreamReader::hasStandaloneDeclaration()
const
2772 Q_D(
const QXmlStreamReader);
2773 return d->hasStandalone;
2783QStringView QXmlStreamReader::documentVersion()
const
2785 Q_D(
const QXmlStreamReader);
2786 if (
d->type == QXmlStreamReader::StartDocument)
2787 return d->documentVersion;
2798QStringView QXmlStreamReader::documentEncoding()
const
2800 Q_D(
const QXmlStreamReader);
2801 if (
d->type == QXmlStreamReader::StartDocument)
2802 return d->documentEncoding;
2883#if QT_CONFIG(xmlstreamwriter)
2887 QXmlStreamWriter *q_ptr;
2888 Q_DECLARE_PUBLIC(QXmlStreamWriter)
2890 enum class StartElementOption {
2892 OmitNamespaceDeclarations = 1,
2895 QXmlStreamWriterPrivate(QXmlStreamWriter *
q);
2896 ~QXmlStreamWriterPrivate() {
2902 void writeEscaped(
QAnyStringView,
bool escapeWhitespace =
false);
2903 bool finishStartElement(
bool contents =
true);
2905 StartElementOption
option = StartElementOption::KeepEverything);
2908 uint deleteDevice :1;
2909 uint inStartElement :1;
2910 uint inEmptyElement :1;
2911 uint lastWasStartElement :1;
2912 uint wroteSomething :1;
2914 uint hasEncodingError :1;
2915 uint autoFormatting :1;
2916 std::string autoFormattingIndent;
2917 NamespaceDeclaration emptyNamespace;
2921 NamespaceDeclaration &findNamespace(
QAnyStringView namespaceUri,
bool writeDeclaration =
false,
bool noDefault =
false);
2922 void writeNamespaceDeclaration(
const NamespaceDeclaration &namespaceDeclaration);
2924 int namespacePrefixCount;
2926 void indent(
int level);
2934QXmlStreamWriterPrivate::QXmlStreamWriterPrivate(QXmlStreamWriter *
q)
2935 : autoFormattingIndent(4,
' ')
2939 stringDevice =
nullptr;
2940 deleteDevice =
false;
2941 inStartElement = inEmptyElement =
false;
2942 wroteSomething =
false;
2944 hasEncodingError =
false;
2945 lastWasStartElement =
false;
2946 lastNamespaceDeclaration = 1;
2947 autoFormatting =
false;
2948 namespacePrefixCount = 0;
2957 s.visit([&] (
auto s) { doWriteToDevice(
s); });
2958 }
else if (stringDevice) {
2959 s.visit([&] (
auto s) { stringDevice->append(
s); });
2961 qWarning(
"QXmlStreamWriter: No device");
2965void QXmlStreamWriterPrivate::writeEscaped(
QAnyStringView s,
bool escapeWhitespace)
2968 char32_t operator()(
const char *&
it,
const char *)
const
2972 char32_t operator()(
const char *&
it,
const char *
end)
const
2976 char32_t *
output = &utf32;
2978 return n < 0 ? 0 : utf32;
2985 char32_t result = decoder.next(u
'\0');
2986 it = decoder.position();
2993 s.visit([&] (
auto s) {
2994 using View =
decltype(
s);
2995 using Decoder = std::conditional_t<std::is_same_v<View, QLatin1StringView>, NextLatin1,
2996 std::conditional_t<std::is_same_v<View, QUtf8StringView>, NextUtf8, NextUtf16>>;
2999 const auto end =
s.end();
3008 char32_t uc = decoder(next_it,
end);
3010 replacement =
"<"_L1;
3012 }
else if (uc == u
'>') {
3013 replacement =
">"_L1;
3015 }
else if (uc == u
'&') {
3016 replacement =
"&"_L1;
3018 }
else if (uc == u
'\"') {
3019 replacement =
"""_L1;
3021 }
else if (uc == u
'\t') {
3022 if (escapeWhitespace) {
3023 replacement =
"	"_L1;
3026 }
else if (uc == u
'\n') {
3027 if (escapeWhitespace) {
3028 replacement =
" "_L1;
3031 }
else if (uc == u
'\v' || uc == u
'\f') {
3032 hasEncodingError =
true;
3034 }
else if (uc == u
'\r') {
3035 if (escapeWhitespace) {
3036 replacement =
" "_L1;
3039 }
else if (uc <= u
'\x1F' || uc == u
'\uFFFE' || uc == u
'\uFFFF') {
3040 hasEncodingError =
true;
3046 escaped.append(
View{mark,
it});
3047 escaped.append(replacement);
3056void QXmlStreamWriterPrivate::writeNamespaceDeclaration(
const NamespaceDeclaration &namespaceDeclaration) {
3057 if (namespaceDeclaration.prefix.isEmpty()) {
3059 write(namespaceDeclaration.namespaceUri);
3063 write(namespaceDeclaration.prefix);
3065 write(namespaceDeclaration.namespaceUri);
3070bool QXmlStreamWriterPrivate::finishStartElement(
bool contents)
3072 bool hadSomethingWritten = wroteSomething;
3074 if (!inStartElement)
3075 return hadSomethingWritten;
3077 if (inEmptyElement) {
3079 QXmlStreamWriterPrivate::Tag
tag = tagStack_pop();
3080 lastNamespaceDeclaration =
tag.namespaceDeclarationsSize;
3081 lastWasStartElement =
false;
3085 inStartElement = inEmptyElement =
false;
3086 lastNamespaceDeclaration = namespaceDeclarations.size();
3087 return hadSomethingWritten;
3093 const bool prefixIsXml = prefix ==
"xml"_L1;
3094 const bool namespaceUriIsXml = namespaceUri ==
"http://www.w3.org/XML/1998/namespace"_L1;
3095 if (prefixIsXml && !namespaceUriIsXml) {
3096 qWarning(
"Reserved prefix 'xml' must not be bound to a different namespace name "
3097 "than 'http://www.w3.org/XML/1998/namespace'");
3098 }
else if (!prefixIsXml && namespaceUriIsXml) {
3100 qWarning(
"The prefix '%ls' must not be bound to namespace name "
3101 "'http://www.w3.org/XML/1998/namespace' which 'xml' is already bound to",
3104 if (namespaceUri ==
"http://www.w3.org/2000/xmlns/"_L1) {
3106 qWarning(
"The prefix '%ls' must not be bound to namespace name "
3107 "'http://www.w3.org/2000/xmlns/'",
3110 auto &namespaceDeclaration = namespaceDeclarations.push();
3111 namespaceDeclaration.prefix = addToStringStorage(prefix);
3112 namespaceDeclaration.namespaceUri = addToStringStorage(namespaceUri);
3113 return namespaceDeclaration;
3118 for (NamespaceDeclaration &namespaceDeclaration :
reversed(namespaceDeclarations)) {
3119 if (namespaceDeclaration.namespaceUri == namespaceUri) {
3120 if (!noDefault || !namespaceDeclaration.prefix.isEmpty())
3121 return namespaceDeclaration;
3125 return emptyNamespace;
3126 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
3131 int n = ++namespacePrefixCount;
3134 qsizetype j = namespaceDeclarations.size() - 2;
3135 while (
j >= 0 && namespaceDeclarations.at(
j).prefix !=
s)
3140 namespaceDeclaration.prefix = addToStringStorage(
s);
3142 namespaceDeclaration.namespaceUri = addToStringStorage(namespaceUri);
3143 if (writeDeclaration)
3144 writeNamespaceDeclaration(namespaceDeclaration);
3145 return namespaceDeclaration;
3150void QXmlStreamWriterPrivate::indent(
int level)
3154 write(autoFormattingIndent);
3157void QXmlStreamWriterPrivate::doWriteToDevice(
QStringView s)
3160 char buffer [3 * MaxChunkSize];
3162 while (!
s.isEmpty()) {
3163 const qsizetype chunkSize = std::min(
s.size(), MaxChunkSize);
3166 s =
s.sliced(chunkSize);
3168 if (
state.remainingChars > 0)
3169 hasEncodingError =
true;
3182 char buffer [2 * MaxChunkSize];
3183 while (!
s.isEmpty()) {
3184 const qsizetype chunkSize = std::min(
s.size(), MaxChunkSize);
3187 s =
s.sliced(chunkSize);
3196QXmlStreamWriter::QXmlStreamWriter()
3197 : d_ptr(new QXmlStreamWriterPrivate(
this))
3205 : d_ptr(new QXmlStreamWriterPrivate(
this))
3207 Q_D(QXmlStreamWriter);
3216 : d_ptr(new QXmlStreamWriterPrivate(
this))
3218 Q_D(QXmlStreamWriter);
3221 d->deleteDevice =
true;
3228QXmlStreamWriter::QXmlStreamWriter(
QString *
string)
3229 : d_ptr(new QXmlStreamWriterPrivate(
this))
3231 Q_D(QXmlStreamWriter);
3238QXmlStreamWriter::~QXmlStreamWriter()
3251 Q_D(QXmlStreamWriter);
3254 d->stringDevice =
nullptr;
3255 if (
d->deleteDevice) {
3257 d->deleteDevice =
false;
3268QIODevice *QXmlStreamWriter::device()
const
3270 Q_D(
const QXmlStreamWriter);
3298void QXmlStreamWriter::setAutoFormatting(
bool enable)
3300 Q_D(QXmlStreamWriter);
3309bool QXmlStreamWriter::autoFormatting()
const
3311 Q_D(
const QXmlStreamWriter);
3312 return d->autoFormatting;
3329void QXmlStreamWriter::setAutoFormattingIndent(
int spacesOrTabs)
3331 Q_D(QXmlStreamWriter);
3332 d->autoFormattingIndent.assign(
size_t(
qAbs(spacesOrTabs)), spacesOrTabs >= 0 ?
' ' :
'\t');
3335int QXmlStreamWriter::autoFormattingIndent()
const
3337 Q_D(
const QXmlStreamWriter);
3339 return indent.count(u
' ') - indent.count(u
'\t');
3351bool QXmlStreamWriter::hasError()
const
3353 Q_D(
const QXmlStreamWriter);
3354 return d->hasIoError ||
d->hasEncodingError;
3370 Q_D(QXmlStreamWriter);
3374 d->write(qualifiedName);
3376 d->writeEscaped(
value,
true);
3393 Q_D(QXmlStreamWriter);
3396 QXmlStreamWriterPrivate::NamespaceDeclaration &namespaceDeclaration =
d->findNamespace(namespaceUri,
true,
true);
3398 if (!namespaceDeclaration.prefix.isEmpty()) {
3399 d->write(namespaceDeclaration.prefix);
3404 d->writeEscaped(
value,
true);
3416void QXmlStreamWriter::writeAttribute(
const QXmlStreamAttribute&
attribute)
3434void QXmlStreamWriter::writeAttributes(
const QXmlStreamAttributes& attributes)
3436 Q_D(QXmlStreamWriter);
3439 for (
const auto &attr : attributes)
3457 Q_D(QXmlStreamWriter);
3458 d->finishStartElement();
3459 d->write(
"<![CDATA[");
3486 Q_D(QXmlStreamWriter);
3487 d->finishStartElement();
3488 d->writeEscaped(
text);
3501 Q_D(QXmlStreamWriter);
3503 if (!
d->finishStartElement(
false) &&
d->autoFormatting)
3504 d->indent(
d->tagStack.size());
3508 d->inStartElement =
d->lastWasStartElement =
false;
3520 Q_D(QXmlStreamWriter);
3521 d->finishStartElement();
3522 if (
d->autoFormatting)
3525 if (
d->autoFormatting)
3538void QXmlStreamWriter::writeEmptyElement(
QAnyStringView qualifiedName)
3540 Q_D(QXmlStreamWriter);
3542 d->writeStartElement({}, qualifiedName);
3543 d->inEmptyElement =
true;
3559 Q_D(QXmlStreamWriter);
3561 d->writeStartElement(namespaceUri,
name);
3562 d->inEmptyElement =
true;
3608void QXmlStreamWriter::writeEndDocument()
3610 Q_D(QXmlStreamWriter);
3611 while (
d->tagStack.size())
3621void QXmlStreamWriter::writeEndElement()
3623 Q_D(QXmlStreamWriter);
3624 if (
d->tagStack.isEmpty())
3628 if (
d->inStartElement && !
d->inEmptyElement) {
3630 d->lastWasStartElement =
d->inStartElement =
false;
3631 QXmlStreamWriterPrivate::Tag
tag =
d->tagStack_pop();
3632 d->lastNamespaceDeclaration =
tag.namespaceDeclarationsSize;
3636 if (!
d->finishStartElement(
false) && !
d->lastWasStartElement &&
d->autoFormatting)
3637 d->indent(
d->tagStack.size()-1);
3638 if (
d->tagStack.isEmpty())
3640 d->lastWasStartElement =
false;
3641 QXmlStreamWriterPrivate::Tag
tag =
d->tagStack_pop();
3642 d->lastNamespaceDeclaration =
tag.namespaceDeclarationsSize;
3644 if (!
tag.namespaceDeclaration.prefix.isEmpty()) {
3645 d->write(
tag.namespaceDeclaration.prefix);
3662 Q_D(QXmlStreamWriter);
3663 d->finishStartElement();
3689 Q_D(QXmlStreamWriter);
3692 d->findNamespace(namespaceUri,
d->inStartElement);
3694 auto &namespaceDeclaration =
d->addExtraNamespace(namespaceUri, prefix);
3695 if (
d->inStartElement)
3696 d->writeNamespaceDeclaration(namespaceDeclaration);
3714void QXmlStreamWriter::writeDefaultNamespace(
QAnyStringView namespaceUri)
3716 Q_D(QXmlStreamWriter);
3717 Q_ASSERT(namespaceUri !=
"http://www.w3.org/XML/1998/namespace"_L1);
3718 Q_ASSERT(namespaceUri !=
"http://www.w3.org/2000/xmlns/"_L1);
3719 QXmlStreamWriterPrivate::NamespaceDeclaration &namespaceDeclaration =
d->namespaceDeclarations.push();
3720 namespaceDeclaration.prefix.clear();
3721 namespaceDeclaration.namespaceUri =
d->addToStringStorage(namespaceUri);
3722 if (
d->inStartElement)
3723 d->writeNamespaceDeclaration(namespaceDeclaration);
3736 Q_D(QXmlStreamWriter);
3738 if (!
d->finishStartElement(
false) &&
d->autoFormatting)
3739 d->indent(
d->tagStack.size());
3742 if (!
data.isNull()) {
3758void QXmlStreamWriter::writeStartDocument()
3760 writeStartDocument(
"1.0"_L1);
3774 Q_D(QXmlStreamWriter);
3775 d->finishStartElement(
false);
3776 d->write(
"<?xml version=\"");
3779 d->write(
"\" encoding=\"UTF-8");
3792void QXmlStreamWriter::writeStartDocument(
QAnyStringView version,
bool standalone)
3794 Q_D(QXmlStreamWriter);
3795 d->finishStartElement(
false);
3796 d->write(
"<?xml version=\"");
3799 d->write(
"\" encoding=\"UTF-8");
3801 d->write(
"\" standalone=\"yes\"?>");
3803 d->write(
"\" standalone=\"no\"?>");
3817void QXmlStreamWriter::writeStartElement(
QAnyStringView qualifiedName)
3819 Q_D(QXmlStreamWriter);
3821 d->writeStartElement({}, qualifiedName);
3838 Q_D(QXmlStreamWriter);
3840 d->writeStartElement(namespaceUri,
name);
3844 StartElementOption
option)
3846 if (!finishStartElement(
false) && autoFormatting)
3847 indent(tagStack.size());
3849 Tag &
tag = tagStack_push();
3850 tag.name = addToStringStorage(
name);
3851 tag.namespaceDeclaration = findNamespace(namespaceUri);
3853 if (!
tag.namespaceDeclaration.prefix.isEmpty()) {
3854 write(
tag.namespaceDeclaration.prefix);
3858 inStartElement = lastWasStartElement =
true;
3860 if (
option != StartElementOption::OmitNamespaceDeclarations) {
3861 for (
qsizetype i = lastNamespaceDeclaration;
i < namespaceDeclarations.size(); ++
i)
3862 writeNamespaceDeclaration(namespaceDeclarations[
i]);
3864 tag.namespaceDeclarationsSize = lastNamespaceDeclaration;
3867#if QT_CONFIG(xmlstreamreader)
3875void QXmlStreamWriter::writeCurrentToken(
const QXmlStreamReader &reader)
3877 Q_D(QXmlStreamWriter);
3878 switch (
reader.tokenType()) {
3879 case QXmlStreamReader::NoToken:
3881 case QXmlStreamReader::StartDocument:
3882 writeStartDocument();
3884 case QXmlStreamReader::EndDocument:
3887 case QXmlStreamReader::StartElement: {
3889 QList<QXmlStreamPrivateTagStack::NamespaceDeclaration> extraNamespaces;
3890 for (
const auto &namespaceDeclaration :
reader.namespaceDeclarations()) {
3891 auto &extraNamespace =
d->addExtraNamespace(namespaceDeclaration.namespaceUri(),
3892 namespaceDeclaration.prefix());
3893 extraNamespaces.append(extraNamespace);
3895 d->writeStartElement(
3897 QXmlStreamWriterPrivate::StartElementOption::OmitNamespaceDeclarations);
3899 for (
const auto &extraNamespace :
std::as_const(extraNamespaces))
3900 d->writeNamespaceDeclaration(extraNamespace);
3901 writeAttributes(
reader.attributes());
3903 case QXmlStreamReader::EndElement:
3906 case QXmlStreamReader::Characters:
3912 case QXmlStreamReader::Comment:
3915 case QXmlStreamReader::DTD:
3918 case QXmlStreamReader::EntityReference:
3919 writeEntityReference(
reader.name());
3921 case QXmlStreamReader::ProcessingInstruction:
3922 writeProcessingInstruction(
reader.processingInstructionTarget(),
3923 reader.processingInstructionData());
3927 qWarning(
"QXmlStreamWriter: writeCurrentToken() with invalid state.");
3932static constexpr bool isTokenAllowedInContext(QXmlStreamReader::TokenType
type,
3936 case QXmlStreamReader::StartDocument:
3937 case QXmlStreamReader::DTD:
3940 case QXmlStreamReader::StartElement:
3941 case QXmlStreamReader::EndElement:
3942 case QXmlStreamReader::Characters:
3943 case QXmlStreamReader::EntityReference:
3944 case QXmlStreamReader::EndDocument:
3947 case QXmlStreamReader::Comment:
3948 case QXmlStreamReader::ProcessingInstruction:
3951 case QXmlStreamReader::NoToken:
3952 case QXmlStreamReader::Invalid:
3957#if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900)
3958 Q_UNREACHABLE_RETURN(
false);
3974 if (
type == QXmlStreamReader::Invalid ||
type == QXmlStreamReader::NoToken)
3978 const bool result = isTokenAllowedInContext(
type, currentContext);
3979 if (
result || currentContext == XmlContext::Body)
3983 currentContext = XmlContext::Body;
3984 return isTokenAllowedInContext(
type, currentContext);
3994 Q_Q(QXmlStreamReader);
3997 const XmlContext
context = currentContext;
3998 const bool ok = isValidToken(
type);
4001 if (
error != QXmlStreamReader::Error::NoError)
4005 raiseError(QXmlStreamReader::UnexpectedElementError,
4006 QXmlStream::tr(
"Unexpected token type %1 in %2.")
4011 if (
type != QXmlStreamReader::DTD)
4016 raiseError(QXmlStreamReader::UnexpectedElementError,
4017 QXmlStream::tr(
"Found second DTD token in %1.").
arg(contextString(
context)));
IOBluetoothDevice * device
QString toString() const
Returns a deep copy of this string view's data as a QString.
constexpr bool isEmpty() const noexcept
Returns whether this string view is empty - that is, whether {size() == 0}.
\inmodule QtCore \reentrant
constexpr qsizetype size() const noexcept
constexpr const_pointer data() const noexcept
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
void clear()
Clears the contents of the byte array and makes it null.
void resize(qsizetype size)
Sets the size of the byte array to size bytes.
\inmodule QtCore \reentrant
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read.
QString text(const QString &key) const
bool hasError() const noexcept
Returns true if a conversion could not correctly convert a character.
bool isValid() const noexcept
Returns true if this is a valid string converter that can be used for encoding or decoding text.
static Q_CORE_EXPORT std::optional< Encoding > encodingForData(QByteArrayView data, char16_t expectedFirstCharacter=0) noexcept
Returns the encoding for the content of data if it can be determined.
bool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
constexpr const storage_type * utf16() const noexcept
constexpr qsizetype size() const noexcept
Returns the size of this string view, in UTF-16 code units (that is, surrogate pairs count as two for...
uint toUInt(bool *ok=nullptr, int base=10) const
Returns the string view converted to an {unsigned int} using base base, which is 10 by default and mu...
\macro QT_RESTRICTED_CAST_FROM_ASCII
qsizetype indexOf(QLatin1StringView s, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
void reserve(qsizetype size)
Ensures the string has space for at least size characters.
QString sliced(qsizetype pos) const &
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString mid(qsizetype position, qsizetype n=-1) const &
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
void clear()
Clears the contents of the string and makes it null.
bool isNull() const
Returns true if this string is null; otherwise returns false.
qsizetype size() const noexcept
Returns the number of characters in this string.
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
QString first(qsizetype n) const &
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
void resize(qsizetype size)
Sets the size of the string to size characters.
static int t_action(int state, int token)
static const char *const spell[]
QXmlStreamReaderPrivate(QXmlStreamReader *q)
bool scanAfterLangleBang()
uint referenceToUnparsedEntityDetected
void parseEntity(const QString &value)
void raiseError(QXmlStreamReader::Error error, const QString &message=QString())
~QXmlStreamReaderPrivate()
XmlStringRef documentVersion
XmlStringRef qualifiedName
bool scanUntil(const char *str, short tokenToInject=-1)
XmlStringRef symPrefix(int index)
void checkPublicLiteral(QStringView publicId)
XmlContext currentContext
bool isValidToken(QXmlStreamReader::TokenType type)
bool lastAttributeIsCData
uint referenceToParameterEntityDetected
XmlStringRef namespaceUri
qsizetype fastScanLiteralContent()
QXmlStreamEntityDeclarations publicEntityDeclarations
QString resolveUndeclaredEntity(const QString &name)
std::optional< qsizetype > fastScanName(Value *val=nullptr)
QXmlStreamAttributes attributes
void putString(QStringView s, qsizetype from=0)
Value & sym(int index) const
uint resolveCharRef(int symbolIndex)
QXmlStreamSimpleStack< EntityDeclaration > entityDeclarations
qsizetype fastScanNMTOKEN()
void putStringLiteral(QStringView s)
void putReplacement(QStringView s)
bool scanAfterDefaultDecl()
std::unique_ptr< QXmlStreamReaderPrivate > entityParser
XmlStringRef symName(int index)
uint filterCarriageReturn()
void putReplacementInAttributeValue(QStringView s)
QXmlStreamSimpleStack< Attribute > attributeStack
XmlStringRef namespaceForPrefix(QStringView prefix)
qsizetype fastScanSpace()
void raiseNamePrefixTooLongError()
void resolvePublicNamespaces()
QXmlStreamSimpleStack< uint > putStack
QHash< QStringView, Entity > parameterEntityHash
void raiseWellFormedError(const QString &message)
QXmlStreamNotationDeclarations publicNotationDeclarations
XmlStringRef documentEncoding
QXmlStreamNamespaceDeclarations publicNamespaceDeclarations
QXmlStreamSimpleStack< DtdAttribute > dtdAttributes
uint hasExternalDtdSubset
qsizetype fastScanContentCharList()
void injectToken(ushort tokenToInject)
bool checkStartDocument()
XmlStringRef symString(int index)
QXmlStreamReader::Error error
QXmlStreamSimpleStack< NotationDeclaration > notationDeclarations
bool scanString(const char *str, short tokenToInject, bool requireSpace=true)
uint hasCheckedStartDocument
bool scanPublicOrSystem()
void reserve(qsizetype extraCapacity)
static bool isEncName(QStringView encName)
list append(new Employee("Blackpool", "Stephen"))
QSet< QString >::iterator it
Combined button and popup list for selecting options.
int toUtf8(char16_t u, OutputPtr &dst, InputPtr &src, InputPtr end)
constexpr bool isAsciiLetterOrNumber(char32_t c) noexcept
constexpr O reversed(O o) noexcept
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QByteArrayView haystack, QByteArrayView needle) noexcept
QImageReader reader("image.png")
[1]
static void writeAttribute(QXmlStreamWriter *stream, const QVariant &attribute)
AudioChannelLayoutTag tag
DBusConnection const char * rule
DBusConnection const char DBusError * error
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
EGLOutputLayerEXT EGLint attribute
constexpr const T & qMax(const T &a, const T &b)
constexpr T qAbs(const T &t)
constexpr auto qOffsetStringArray(const char(&...strings)[Nx]) noexcept
static bool contains(const QJsonArray &haystack, unsigned needle)
GLint GLenum GLsizei GLsizei GLsizei depth
GLenum GLuint GLint level
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint GLsizei const GLchar * message
GLuint GLenum GLenum transform
GLdouble GLdouble GLdouble GLdouble q
GLsizei const GLchar *const * string
[0]
GLbitfield GLuint readBuffer
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
#define qUtf16Printable(string)
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
QT_BEGIN_NAMESPACE typedef uchar * output
Q_CHECK_PTR(a=new int[80])
gzip write("uncompressed data")
writeStartElement(qualifiedName)
[0]
\inmodule QtCore \reentrant
static Q_CORE_EXPORT QByteArray convertFromUnicode(QStringView in)
static Q_CORE_EXPORT char * convertFromLatin1(char *out, QLatin1StringView in)