From 84984af0e11029716a5a601869964470dff2d0be Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Sun, 26 Feb 2012 21:04:57 +0000 Subject: Remove usage of QtXml from rcc, add test Ported from QDom to QXmlStreamReader. This enables removal of QtXml classes from bootstrap. A new rcc test was added, copying the data from the QResourceFileEngine test. The new test runs rcc to create binary resources, dynamically loads them under various locales and checks that they do contain the expected files. Change-Id: I15d23dfda45de851a421156951ce2a60af4c1f7f Reviewed-by: Lars Knoll Reviewed-by: hjk --- src/tools/rcc/rcc.cpp | 304 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 182 insertions(+), 122 deletions(-) (limited to 'src/tools/rcc') diff --git a/src/tools/rcc/rcc.cpp b/src/tools/rcc/rcc.cpp index dfe23983b7..8a9afec690 100644 --- a/src/tools/rcc/rcc.cpp +++ b/src/tools/rcc/rcc.cpp @@ -50,8 +50,7 @@ #include #include #include - -#include +#include QT_BEGIN_NAMESPACE @@ -356,6 +355,12 @@ RCCResourceLibrary::~RCCResourceLibrary() delete m_root; } +enum RCCXmlTag { + RccTag, + ResourceTag, + FileTag +}; + bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice, const QString &fname, QString currentPath, bool ignoreErrors) { @@ -364,98 +369,168 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice, if (!currentPath.isEmpty() && !currentPath.endsWith(slash)) currentPath += slash; - QDomDocument document; - { - QString errorMsg; - int errorLine = 0; - int errorColumn = 0; - if (!document.setContent(inputDevice, &errorMsg, &errorLine, &errorColumn)) { - if (ignoreErrors) - return true; - const QString msg = QString::fromUtf8("RCC Parse Error: '%1' Line: %2 Column: %3 [%4]\n").arg(fname).arg(errorLine).arg(errorColumn).arg(errorMsg); - m_errorDevice->write(msg.toUtf8()); - return false; - } - } - - QDomElement domRoot = document.firstChildElement(m_strings.TAG_RCC).toElement(); - if (!domRoot.isNull() && domRoot.tagName() == m_strings.TAG_RCC) { - for (QDomNode node = domRoot.firstChild(); !node.isNull(); node = node.nextSibling()) { - if (!node.isElement()) - continue; - - QDomElement child = node.toElement(); - if (!child.isNull() && child.tagName() == m_strings.TAG_RESOURCE) { - QLocale::Language language = QLocale::c().language(); - QLocale::Country country = QLocale::c().country(); - - if (child.hasAttribute(m_strings.ATTRIBUTE_LANG)) { - QString attribute = child.attribute(m_strings.ATTRIBUTE_LANG); - QLocale lang = QLocale(attribute); - language = lang.language(); - if (2 == attribute.length()) { - // Language only - country = QLocale::AnyCountry; - } else { - country = lang.country(); + QXmlStreamReader reader(inputDevice); + QStack tokens; + + QString prefix; + QLocale::Language language = QLocale::c().language(); + QLocale::Country country = QLocale::c().country(); + QString alias; + int compressLevel = m_compressLevel; + int compressThreshold = m_compressThreshold; + + while (!reader.atEnd()) { + QXmlStreamReader::TokenType t = reader.readNext(); + switch (t) { + case QXmlStreamReader::StartElement: + if (reader.name() == m_strings.TAG_RCC) { + if (!tokens.isEmpty()) + reader.raiseError(QLatin1String("expected tag")); + else + tokens.push(RccTag); + } else if (reader.name() == m_strings.TAG_RESOURCE) { + if (tokens.isEmpty() || tokens.top() != RccTag) { + reader.raiseError(QLatin1String("unexpected tag")); + } else { + tokens.push(ResourceTag); + + QXmlStreamAttributes attributes = reader.attributes(); + language = QLocale::c().language(); + country = QLocale::c().country(); + + if (attributes.hasAttribute(m_strings.ATTRIBUTE_LANG)) { + QString attribute = attributes.value(m_strings.ATTRIBUTE_LANG).toString(); + QLocale lang = QLocale(attribute); + language = lang.language(); + if (2 == attribute.length()) { + // Language only + country = QLocale::AnyCountry; + } else { + country = lang.country(); + } } + + prefix.clear(); + if (attributes.hasAttribute(m_strings.ATTRIBUTE_PREFIX)) + prefix = attributes.value(m_strings.ATTRIBUTE_PREFIX).toString(); + if (!prefix.startsWith(slash)) + prefix.prepend(slash); + if (!prefix.endsWith(slash)) + prefix += slash; + } + } else if (reader.name() == m_strings.TAG_FILE) { + if (tokens.isEmpty() || tokens.top() != ResourceTag) { + reader.raiseError(QLatin1String("unexpected tag")); + } else { + tokens.push(FileTag); + + QXmlStreamAttributes attributes = reader.attributes(); + alias.clear(); + if (attributes.hasAttribute(m_strings.ATTRIBUTE_ALIAS)) + alias = attributes.value(m_strings.ATTRIBUTE_ALIAS).toString(); + + compressLevel = m_compressLevel; + if (attributes.hasAttribute(m_strings.ATTRIBUTE_COMPRESS)) + compressLevel = attributes.value(m_strings.ATTRIBUTE_COMPRESS).toString().toInt(); + + compressThreshold = m_compressThreshold; + if (attributes.hasAttribute(m_strings.ATTRIBUTE_THRESHOLD)) + compressThreshold = attributes.value(m_strings.ATTRIBUTE_THRESHOLD).toString().toInt(); + + // Special case for -no-compress. Overrides all other settings. + if (m_compressLevel == -2) + compressLevel = 0; + } + } else { + reader.raiseError(QString(QLatin1String("unexpected tag: %1")).arg(reader.name().toString())); + } + break; + + case QXmlStreamReader::EndElement: + if (reader.name() == m_strings.TAG_RCC) { + if (!tokens.isEmpty() && tokens.top() == RccTag) + tokens.pop(); + else + reader.raiseError(QLatin1String("unexpected closing tag")); + } else if (reader.name() == m_strings.TAG_RESOURCE) { + if (!tokens.isEmpty() && tokens.top() == ResourceTag) + tokens.pop(); + else + reader.raiseError(QLatin1String("unexpected closing tag")); + } else if (reader.name() == m_strings.TAG_FILE) { + if (!tokens.isEmpty() && tokens.top() == FileTag) + tokens.pop(); + else + reader.raiseError(QLatin1String("unexpected closing tag")); + } + break; + + case QXmlStreamReader::Characters: + if (reader.isWhitespace()) + break; + if (tokens.isEmpty() || tokens.top() != FileTag) { + reader.raiseError(QLatin1String("unexpected text")); + } else { + QString fileName = reader.text().toString(); + if (fileName.isEmpty()) { + const QString msg = QString::fromLatin1("RCC: Warning: Null node in XML of '%1'\n").arg(fname); + m_errorDevice->write(msg.toUtf8()); } - QString prefix; - if (child.hasAttribute(m_strings.ATTRIBUTE_PREFIX)) - prefix = child.attribute(m_strings.ATTRIBUTE_PREFIX); - if (!prefix.startsWith(slash)) - prefix.prepend(slash); - if (!prefix.endsWith(slash)) - prefix += slash; - - for (QDomNode res = child.firstChild(); !res.isNull(); res = res.nextSibling()) { - if (res.isElement() && res.toElement().tagName() == m_strings.TAG_FILE) { - - QString fileName(res.firstChild().toText().data()); - if (fileName.isEmpty()) { - const QString msg = QString::fromUtf8("RCC: Warning: Null node in XML of '%1'\n").arg(fname); - m_errorDevice->write(msg.toUtf8()); - } - QString alias; - if (res.toElement().hasAttribute(m_strings.ATTRIBUTE_ALIAS)) - alias = res.toElement().attribute(m_strings.ATTRIBUTE_ALIAS); - else - alias = fileName; - - int compressLevel = m_compressLevel; - if (res.toElement().hasAttribute(m_strings.ATTRIBUTE_COMPRESS)) - compressLevel = res.toElement().attribute(m_strings.ATTRIBUTE_COMPRESS).toInt(); - int compressThreshold = m_compressThreshold; - if (res.toElement().hasAttribute(m_strings.ATTRIBUTE_THRESHOLD)) - compressThreshold = res.toElement().attribute(m_strings.ATTRIBUTE_THRESHOLD).toInt(); - - // Special case for -no-compress. Overrides all other settings. - if (m_compressLevel == -2) - compressLevel = 0; - - alias = QDir::cleanPath(alias); - while (alias.startsWith(QLatin1String("../"))) - alias.remove(0, 3); - alias = QDir::cleanPath(m_resourceRoot) + prefix + alias; - - QString absFileName = fileName; - if (QDir::isRelativePath(absFileName)) - absFileName.prepend(currentPath); - QFileInfo file(absFileName); - if (!file.exists()) { - m_failedResources.push_back(absFileName); - const QString msg = QString::fromUtf8("RCC: Error in '%1': Cannot find file '%2'\n").arg(fname).arg(fileName); - m_errorDevice->write(msg.toUtf8()); - if (ignoreErrors) - continue; - else - return false; - } else if (file.isFile()) { + if (alias.isNull()) + alias = fileName; + + alias = QDir::cleanPath(alias); + while (alias.startsWith(QLatin1String("../"))) + alias.remove(0, 3); + alias = QDir::cleanPath(m_resourceRoot) + prefix + alias; + + QString absFileName = fileName; + if (QDir::isRelativePath(absFileName)) + absFileName.prepend(currentPath); + QFileInfo file(absFileName); + if (!file.exists()) { + m_failedResources.push_back(absFileName); + const QString msg = QString::fromLatin1("RCC: Error in '%1': Cannot find file '%2'\n").arg(fname).arg(fileName); + m_errorDevice->write(msg.toUtf8()); + if (ignoreErrors) + continue; + else + return false; + } else if (file.isFile()) { + const bool arc = + addFile(alias, + RCCFileInfo(alias.section(slash, -1), + file, + language, + country, + RCCFileInfo::NoFlags, + compressLevel, + compressThreshold) + ); + if (!arc) + m_failedResources.push_back(absFileName); + } else { + QDir dir; + if (file.isDir()) { + dir.setPath(file.filePath()); + } else { + dir.setPath(file.path()); + dir.setNameFilters(QStringList(file.fileName())); + if (alias.endsWith(file.fileName())) + alias = alias.left(alias.length()-file.fileName().length()); + } + if (!alias.endsWith(slash)) + alias += slash; + QDirIterator it(dir, QDirIterator::FollowSymlinks|QDirIterator::Subdirectories); + while (it.hasNext()) { + it.next(); + QFileInfo child(it.fileInfo()); + if (child.fileName() != QLatin1String(".") && child.fileName() != QLatin1String("..")) { const bool arc = - addFile(alias, - RCCFileInfo(alias.section(slash, -1), - file, + addFile(alias + child.fileName(), + RCCFileInfo(child.fileName(), + child, language, country, RCCFileInfo::NoFlags, @@ -463,44 +538,29 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice, compressThreshold) ); if (!arc) - m_failedResources.push_back(absFileName); - } else { - QDir dir; - if (file.isDir()) { - dir.setPath(file.filePath()); - } else { - dir.setPath(file.path()); - dir.setNameFilters(QStringList(file.fileName())); - if (alias.endsWith(file.fileName())) - alias = alias.left(alias.length()-file.fileName().length()); - } - if (!alias.endsWith(slash)) - alias += slash; - QDirIterator it(dir, QDirIterator::FollowSymlinks|QDirIterator::Subdirectories); - while (it.hasNext()) { - it.next(); - QFileInfo child(it.fileInfo()); - if (child.fileName() != QLatin1String(".") && child.fileName() != QLatin1String("..")) { - const bool arc = - addFile(alias + child.fileName(), - RCCFileInfo(child.fileName(), - child, - language, - country, - RCCFileInfo::NoFlags, - compressLevel, - compressThreshold) - ); - if (!arc) - m_failedResources.push_back(child.fileName()); - } - } + m_failedResources.push_back(child.fileName()); } } } } + break; + + default: + break; } } + + if (reader.hasError()) { + if (ignoreErrors) + return true; + int errorLine = reader.lineNumber(); + int errorColumn = reader.columnNumber(); + QString errorMessage = reader.errorString(); + QString msg = QString::fromLatin1("RCC Parse Error: '%1' Line: %2 Column: %3 [%4]\n").arg(fname).arg(errorLine).arg(errorColumn).arg(errorMessage); + m_errorDevice->write(msg.toUtf8()); + return false; + } + if (m_root == 0) { const QString msg = QString::fromUtf8("RCC: Warning: No resources in '%1'.\n").arg(fname); m_errorDevice->write(msg.toUtf8()); -- cgit v1.2.3