cleanup file engine, notably the Qt resource part

this is fixes QTBUG-11223, I also would like to take it step further
and make the resources requests prefixed with "qrc:/" so that the
check when to use QResourceFileEngine is even more reliable but
that will require backwards incompatible change so it will be done
in future release.

Signed-off-by: Ivailo Monev <xakepa10@laimg.moc>
This commit is contained in:
Ivailo Monev 2020-01-11 02:29:34 +00:00
parent 9beb757ddf
commit e02ce5c0e0
19 changed files with 71 additions and 547 deletions

2
README
View file

@ -79,7 +79,7 @@ QTBUG-25114, QTBUG-24672, QTBUG-23524 (WIP), QTBUG-56088, QTBUG-42189,
QTBUG-39285, QTBUG-18173, QTBUG-28968, QTBUG-34336, QTBUG-40974, QTBUG-44286,
QTBUG-12564, QTBUG-20028, QTBUG-71967, QTBUG-70956, QTBUG-71446, QTBUG-61307,
QTBUG-27287, QTBUG-25143, QTBUG-22833, QTBUG-57399, QTBUG-59159, QTBUG-15773,
QTBUG-70506, QTBUG-46054
QTBUG-70506, QTBUG-46054, QTBUG-11223
Unless you use QMake and QDoc porting to Katie or even supporting it along with
Qt4 in the same codebase is trivial and requires only minor changes because

View file

@ -39,6 +39,9 @@
// built-in handlers
#include "qfsfileengine.h"
#include "qdiriterator.h"
#ifndef QT_BOOTSTRAPPED
# include "qresource_p.h"
#endif
#include "qfilesystementry_p.h"
#include "qfilesystemmetadata_p.h"
@ -90,25 +93,6 @@ QT_BEGIN_NAMESPACE
\sa QAbstractFileEngine, QAbstractFileEngine::create()
*/
static bool qt_file_engine_handlers_in_use = false;
/*
All application-wide handlers are stored in this list. The mutex must be
acquired to ensure thread safety.
*/
Q_GLOBAL_STATIC_WITH_ARGS(QReadWriteLock, fileEngineHandlerMutex, (QReadWriteLock::Recursive))
static bool qt_abstractfileenginehandlerlist_shutDown = false;
class QAbstractFileEngineHandlerList : public QList<QAbstractFileEngineHandler *>
{
public:
~QAbstractFileEngineHandlerList()
{
QWriteLocker locker(fileEngineHandlerMutex());
qt_abstractfileenginehandlerlist_shutDown = true;
}
};
Q_GLOBAL_STATIC(QAbstractFileEngineHandlerList, fileEngineHandlers)
/*!
Constructs a file handler and registers it with Qt. Once created this
handler's create() function will be called (along with all the other
@ -120,9 +104,6 @@ Q_GLOBAL_STATIC(QAbstractFileEngineHandlerList, fileEngineHandlers)
*/
QAbstractFileEngineHandler::QAbstractFileEngineHandler()
{
QWriteLocker locker(fileEngineHandlerMutex());
qt_file_engine_handlers_in_use = true;
fileEngineHandlers()->prepend(this);
}
/*!
@ -131,36 +112,6 @@ QAbstractFileEngineHandler::QAbstractFileEngineHandler()
*/
QAbstractFileEngineHandler::~QAbstractFileEngineHandler()
{
QWriteLocker locker(fileEngineHandlerMutex());
// Remove this handler from the handler list only if the list is valid.
if (!qt_abstractfileenginehandlerlist_shutDown) {
QAbstractFileEngineHandlerList *handlers = fileEngineHandlers();
handlers->removeOne(this);
if (handlers->isEmpty())
qt_file_engine_handlers_in_use = false;
}
}
/*
\ìnternal
Handles calls to custom file engine handlers.
*/
QAbstractFileEngine *qt_custom_file_engine_handler_create(const QString &path)
{
if (qt_file_engine_handlers_in_use) {
QReadLocker locker(fileEngineHandlerMutex());
// check for registered handlers that can load the file
QAbstractFileEngineHandlerList *handlers = fileEngineHandlers();
for (int i = 0; i < handlers->size(); i++) {
QAbstractFileEngine *engine = handlers->at(i)->create(path);
if (engine)
return engine;
}
}
return 0;
}
/*!
@ -191,17 +142,17 @@ QAbstractFileEngine *qt_custom_file_engine_handler_create(const QString &path)
*/
QAbstractFileEngine *QAbstractFileEngine::create(const QString &fileName)
{
QFileSystemEntry entry(fileName);
QFileSystemMetaData metaData;
QAbstractFileEngine *engine = QFileSystemEngine::resolveEntryAndCreateLegacyEngine(entry, metaData);
#ifndef QT_NO_FSFILEENGINE
if (!engine)
// fall back to regular file engine
return new QFSFileEngine(entry.filePath());
#ifndef QT_BOOTSTRAPPED
// check if a resource file is being handled
if(fileName.startsWith(":/"))
return new QResourceFileEngine(fileName);
#endif
#ifndef QT_NO_FSFILEENGINE
// fall back to regular file engine
return new QFSFileEngine(fileName);
#else
return Q_NULLPTR;
#endif
return engine;
}
/*!

View file

@ -65,8 +65,6 @@ public:
Q_DECLARE_PUBLIC(QAbstractFileEngine)
};
QAbstractFileEngine *qt_custom_file_engine_handler_create(const QString &path);
QT_END_NAMESPACE
#endif // QABSTRACTFILEENGINE_P_H

View file

@ -60,15 +60,6 @@
QT_BEGIN_NAMESPACE
#ifndef QT_BOOTSTRAPPED
struct QCoreGlobalData {
QMap<QString, QStringList> dirSearchPaths;
QReadWriteLock dirSearchPathsLock;
};
Q_GLOBAL_STATIC(QCoreGlobalData, globalData)
#endif
//************* QDirPrivate
QDirPrivate::QDirPrivate(const QString &path, const QStringList &nameFilters_, QDir::SortFlags sort_, QDir::Filters filters_)
: QSharedData()
@ -99,7 +90,7 @@ QDirPrivate::QDirPrivate(const QDirPrivate &copy)
, nameFilters(copy.nameFilters)
, sort(copy.sort)
, filters(copy.filters)
, fileEngine(0)
, fileEngine(Q_NULLPTR)
, fileListsInitialized(false)
, dirEntry(copy.dirEntry)
, metaData(copy.metaData)
@ -155,7 +146,7 @@ inline void QDirPrivate::setPath(const QString &path)
p.truncate(p.length() - 1);
}
dirEntry = QFileSystemEntry(p);
dirEntry = QFileSystemEntry(QDir::fromNativeSeparators(path));
metaData.clear();
initFileEngine();
clearFileLists();
@ -316,7 +307,7 @@ inline void QDirPrivate::initFileLists(const QDir &dir) const
inline void QDirPrivate::initFileEngine()
{
delete fileEngine;
fileEngine = QFileSystemEngine::resolveEntryAndCreateLegacyEngine(dirEntry, metaData);
fileEngine = QAbstractFileEngine::create(dirEntry.filePath());
}
/*!
@ -855,80 +846,6 @@ void QDir::setNameFilters(const QStringList &nameFilters)
d->nameFilters = nameFilters;
}
#ifndef QT_BOOTSTRAPPED
/*!
\since 4.3
Sets or replaces Qt's search paths for file names with the prefix \a prefix
to \a searchPaths.
To specify a prefix for a file name, prepend the prefix followed by a single
colon (e.g., "images:undo.png", "xmldocs:books.xml"). \a prefix can only
contain letters or numbers (e.g., it cannot contain a colon, nor a slash).
Qt uses this search path to locate files with a known prefix. The search
path entries are tested in order, starting with the first entry.
\snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 8
File name prefix must be at least 2 characters long to avoid conflicts with
Windows drive letters.
Search paths may contain paths to \l{The Qt Resource System}.
*/
void QDir::setSearchPaths(const QString &prefix, const QStringList &searchPaths)
{
if (Q_UNLIKELY(prefix.length() < 2)) {
qWarning("QDir::setSearchPaths: Prefix must be longer than 1 character");
return;
}
for (int i = 0; i < prefix.count(); ++i) {
if (!prefix.at(i).isLetterOrNumber()) {
qWarning("QDir::setSearchPaths: Prefix can only contain letters or numbers");
return;
}
}
QWriteLocker lock(&globalData()->dirSearchPathsLock);
if (searchPaths.isEmpty()) {
globalData()->dirSearchPaths.remove(prefix);
} else {
globalData()->dirSearchPaths.insert(prefix, searchPaths);
}
}
/*!
\since 4.3
Adds \a path to the search path for \a prefix.
\sa setSearchPaths()
*/
void QDir::addSearchPath(const QString &prefix, const QString &path)
{
if (path.isEmpty())
return;
QWriteLocker lock(&globalData()->dirSearchPathsLock);
globalData()->dirSearchPaths[prefix] += path;
}
/*!
\since 4.3
Returns the search paths for \a prefix.
\sa setSearchPaths(), addSearchPath()
*/
QStringList QDir::searchPaths(const QString &prefix)
{
QReadLocker lock(&globalData()->dirSearchPathsLock);
return globalData()->dirSearchPaths.value(prefix);
}
#endif // QT_BOOTSTRAPPED
/*!
Returns the value set by setFilter()
*/

View file

@ -112,10 +112,6 @@ public:
QString absolutePath() const;
QString canonicalPath() const;
static void setSearchPaths(const QString &prefix, const QStringList &searchPaths);
static void addSearchPath(const QString &prefix, const QString &path);
static QStringList searchPaths(const QString &prefix);
QString dirName() const;
QString filePath(const QString &fileName) const;
QString absoluteFilePath(const QString &fileName) const;

View file

@ -163,7 +163,7 @@ QDirIteratorPrivate::QDirIteratorPrivate(const QFileSystemEntry &entry, const QS
#endif
QFileSystemMetaData metaData;
if (resolveEngine)
engine.reset(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(dirEntry, metaData));
engine.reset(QAbstractFileEngine::create(dirEntry.filePath()));
QFileInfo fileInfo(new QFileInfoPrivate(dirEntry, metaData));
// Populate fields for hasNext() and next()

View file

@ -69,7 +69,7 @@ public:
: QSharedData(copy),
fileEntry(copy.fileEntry),
metaData(copy.metaData),
fileEngine(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(fileEntry, metaData)),
fileEngine(QAbstractFileEngine::create(fileEntry.filePath())),
#ifndef QT_NO_FSFILEENGINE
isDefaultConstructed(false),
#else
@ -78,8 +78,9 @@ public:
cache_enabled(copy.cache_enabled), fileFlags(0), cachedFlags(0), fileSize(0)
{}
inline QFileInfoPrivate(const QString &file)
: fileEntry(file),
fileEngine(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(fileEntry, metaData)),
: QSharedData(),
fileEntry(file),
fileEngine(QAbstractFileEngine::create(file)),
#ifndef QT_NO_FSFILEENGINE
isDefaultConstructed(false),
#else
@ -93,7 +94,7 @@ public:
: QSharedData(),
fileEntry(file),
metaData(data),
fileEngine(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(fileEntry, metaData)),
fileEngine(QAbstractFileEngine::create(fileEntry.filePath())),
isDefaultConstructed(false),
cache_enabled(true), fileFlags(0), cachedFlags(0), fileSize(0)
{

View file

@ -42,102 +42,6 @@
QT_BEGIN_NAMESPACE
static inline bool _q_checkEntry(QFileSystemEntry &entry, QFileSystemMetaData &data, bool resolvingEntry)
{
if (resolvingEntry) {
if (!QFileSystemEngine::fillMetaData(entry, data, QFileSystemMetaData::ExistsAttribute)
|| !data.exists()) {
data.clear();
return false;
}
}
return true;
}
static inline bool _q_checkEntry(QAbstractFileEngine *&engine, bool resolvingEntry)
{
if (resolvingEntry) {
if (!(engine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::ExistsFlag)) {
delete engine;
engine = 0;
return false;
}
}
return true;
}
static bool _q_resolveEntryAndCreateLegacyEngine_recursive(QFileSystemEntry &entry, QFileSystemMetaData &data,
QAbstractFileEngine *&engine, bool resolvingEntry = false)
{
QString const &filePath = entry.filePath();
if ((engine = qt_custom_file_engine_handler_create(filePath)))
return _q_checkEntry(engine, resolvingEntry);
#ifndef QT_BOOTSTRAPPED
for (int prefixSeparator = 0; prefixSeparator < filePath.size(); ++prefixSeparator) {
QChar const ch = filePath[prefixSeparator];
if (ch == QLatin1Char('/'))
break;
if (ch == QLatin1Char(':')) {
if (prefixSeparator == 0) {
engine = new QResourceFileEngine(filePath);
return _q_checkEntry(engine, resolvingEntry);
}
if (prefixSeparator == 1)
break;
const QStringList &paths = QDir::searchPaths(filePath.left(prefixSeparator));
for (int i = 0; i < paths.count(); i++) {
entry = QFileSystemEntry(QDir::cleanPath(paths.at(i) + QLatin1Char('/') + filePath.mid(prefixSeparator + 1)));
// Recurse!
if (_q_resolveEntryAndCreateLegacyEngine_recursive(entry, data, engine, true))
return true;
}
// entry may have been clobbered at this point.
return false;
}
// There's no need to fully validate the prefix here. Consulting the
// unicode tables could be expensive and validation is already
// performed in QDir::setSearchPaths.
//
// if (!ch.isLetterOrNumber())
// break;
}
#endif // QT_BOOTSTRAPPED
return _q_checkEntry(entry, data, resolvingEntry);
}
/*!
\internal
Resolves the \a entry (see QDir::searchPaths) and returns an engine for
it, but never a QFSFileEngine.
Returns a file engine that can be used to access the entry. Returns 0 if
QFileSystemEngine API should be used to query and interact with the file
system object.
*/
QAbstractFileEngine *QFileSystemEngine::resolveEntryAndCreateLegacyEngine(
QFileSystemEntry &entry, QFileSystemMetaData &data) {
QFileSystemEntry copy = entry;
QAbstractFileEngine *engine = 0;
if (_q_resolveEntryAndCreateLegacyEngine_recursive(copy, data, engine))
// Reset entry to resolved copy.
entry = copy;
else
data.clear();
return engine;
}
//these unix functions are in this file, because they are shared by symbian port
//for open C file handles.
#ifdef Q_OS_UNIX

View file

@ -87,9 +87,6 @@ public:
static bool setCurrentPath(const QFileSystemEntry &entry);
static QFileSystemEntry currentPath();
static QAbstractFileEngine *resolveEntryAndCreateLegacyEngine(QFileSystemEntry &entry,
QFileSystemMetaData &data);
};
QT_END_NAMESPACE

View file

@ -693,24 +693,8 @@ QAbstractFileEngine::Iterator *QFSFileEngine::beginEntryList(QDir::Filters filte
{
return new QFSFileEngineIterator(filters, filterNames);
}
/*!
\internal
*/
QAbstractFileEngine::Iterator *QFSFileEngine::endEntryList()
{
return 0;
}
#endif
/*!
\internal
*/
QStringList QFSFileEngine::entryList(QDir::Filters filters, const QStringList &filterNames) const
{
return QAbstractFileEngine::entryList(filters, filterNames);
}
/*!
\reimp
*/

View file

@ -70,7 +70,6 @@ public:
bool setSize(qint64 size);
bool caseSensitive() const;
bool isRelativePath() const;
QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const;
FileFlags fileFlags(FileFlags type) const;
bool setPermissions(uint perms);
QString fileName(FileName file) const;
@ -82,7 +81,6 @@ public:
#ifndef QT_NO_FILESYSTEMITERATOR
Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames);
Iterator *endEntryList();
#endif
qint64 read(char *data, qint64 maxlen);

View file

@ -129,8 +129,6 @@ Q_GLOBAL_STATIC_WITH_ARGS(QMutex, resourceMutex, (QMutex::Recursive))
typedef QList<QResourceRoot*> ResourceList;
Q_GLOBAL_STATIC(ResourceList, resourceList)
Q_GLOBAL_STATIC(QStringList, resourceSearchPaths)
/*!
\class QResource
\brief The QResource class provides an interface for reading directly from resources.
@ -153,8 +151,7 @@ Q_GLOBAL_STATIC(QStringList, resourceSearchPaths)
A QResource can either be loaded with an absolute path, either treated
as a file system rooted with a \c{/} character, or in resource notation
rooted with a \c{:} character. A relative resource can also be opened
which will be found in the list of paths returned by QDir::searchPaths().
rooted with a \c{:} character.
A QResource that is representing a file will have data backing it, this
data can possibly be compressed, in which case qUncompress() must be
@ -249,7 +246,7 @@ QResourcePrivate::load(const QString &file)
size = 0;
compressed = false;
}
} else if(res->isContainer(node) != container) {
} else if(Q_UNLIKELY(res->isContainer(node) != container)) {
qWarning("QResourceInfo: Resource [%s] has both data and children!", file.toLatin1().constData());
}
res->ref.ref();
@ -272,29 +269,12 @@ QResourcePrivate::ensureInitialized() const
if(!related.isEmpty())
return;
QResourcePrivate *that = const_cast<QResourcePrivate *>(this);
if(fileName == QLatin1String(":"))
that->fileName += QLatin1Char('/');
that->absoluteFilePath = fileName;
if(!that->absoluteFilePath.startsWith(QLatin1Char(':')))
that->absoluteFilePath.prepend(QLatin1Char(':'));
if(!that->absoluteFilePath.startsWith(QLatin1String(":/")))
that->absoluteFilePath.prepend(QLatin1String(":/"));
QString path = fileName;
if(path.startsWith(QLatin1Char(':')))
path = path.mid(1);
if(path.startsWith(QLatin1Char('/'))) {
that->load(path);
} else {
QMutexLocker lock(resourceMutex());
QStringList searchPaths = *resourceSearchPaths();
searchPaths << QLatin1String("");
for(int i = 0; i < searchPaths.size(); ++i) {
const QString searchPath(searchPaths.at(i) + QLatin1Char('/') + path);
if(that->load(searchPath)) {
that->absoluteFilePath = QLatin1Char(':') + searchPath;
break;
}
}
if(fileName.startsWith(QLatin1String(":/"))) {
that->load(fileName.mid(1));
}
}
@ -308,14 +288,12 @@ QResourcePrivate::ensureChildren() const
QString path = absoluteFilePath, k;
if(path.startsWith(QLatin1Char(':')))
path = path.mid(1);
QSet<QString> kids;
QString cleaned = QDir::cleanPath(path);
for(int i = 0; i < related.size(); ++i) {
QResourceRoot *res = related.at(i);
if(res->mappingRootSubdir(path, &k) && !k.isEmpty()) {
if(!kids.contains(k)) {
children += k;
kids.insert(k);
if(!children.contains(k)) {
children.append(k);
}
} else {
const int node = res->findNode(cleaned);
@ -323,9 +301,8 @@ QResourcePrivate::ensureChildren() const
QStringList related_children = res->children(node);
for(int kid = 0; kid < related_children.size(); ++kid) {
k = related_children.at(kid);
if(!kids.contains(k)) {
children += k;
kids.insert(k);
if(!children.contains(k)) {
children.append(k);
}
}
}
@ -337,7 +314,7 @@ QResourcePrivate::ensureChildren() const
Constructs a QResource pointing to \a file. \a locale is used to
load a specific localization of a resource data.
\sa QFileInfo, QDir::searchPaths(), setFileName(), setLocale()
\sa QFileInfo, setFileName(), setLocale()
*/
QResource::QResource(const QString &file, const QLocale &locale) : d_ptr(new QResourcePrivate())
@ -381,9 +358,7 @@ QLocale QResource::locale() const
}
/*!
Sets a QResource to point to \a file. \a file can either be absolute,
in which case it is opened directly, if relative then the file will be
tried to be found in QDir::searchPaths().
Sets a QResource to point to \a file. \a file should be absolute.
\sa absoluteFilePath()
*/
@ -410,8 +385,7 @@ QString QResource::fileName() const
}
/*!
Returns the real path that this QResource represents, if the resource
was found via the QDir::searchPaths() it will be indicated in the path.
Returns the real path that this QResource represents.
\sa fileName()
*/
@ -517,48 +491,6 @@ QStringList QResource::children() const
return d->children;
}
/*!
\obsolete
Use QDir::addSearchPath() with a prefix instead.
Adds \a path to the search paths searched in to find resources that are
not specified with an absolute path. The \a path must be an absolute
path (start with \c{/}).
The default search path is to search only in the root (\c{:/}). The last
path added will be consulted first upon next QResource creation.
*/
void
QResource::addSearchPath(const QString &path)
{
if (!path.startsWith(QLatin1Char('/'))) {
qWarning("QResource::addSearchPath: Search paths must be absolute (start with /) [%s]",
path.toLocal8Bit().data());
return;
}
QMutexLocker lock(resourceMutex());
resourceSearchPaths()->prepend(path);
}
/*!
\obsolete
Use QDir::searchPaths() instead.
Returns the current search path list. This list is consulted when
creating a relative resource.
\sa QDir::addSearchPath() QDir::setSearchPaths()
*/
QStringList
QResource::searchPaths()
{
QMutexLocker lock(resourceMutex());
return *resourceSearchPaths();
}
inline int QResourceRoot::hash(int node) const
{
if(!node) //root
@ -805,7 +737,7 @@ Q_CORE_EXPORT bool qRegisterResourceData(int version, const unsigned char *tree,
const unsigned char *name, const unsigned char *data)
{
QMutexLocker lock(resourceMutex());
if(version == 0x01 && resourceList()) {
if(version == Q_RCC_OUTPUT_REVISION && resourceList()) {
bool found = false;
QResourceRoot res(tree, name, data);
for(int i = 0; i < resourceList()->size(); ++i) {
@ -828,7 +760,7 @@ Q_CORE_EXPORT bool qUnregisterResourceData(int version, const unsigned char *tre
const unsigned char *name, const unsigned char *data)
{
QMutexLocker lock(resourceMutex());
if(version == 0x01 && resourceList()) {
if(version == Q_RCC_OUTPUT_REVISION && resourceList()) {
QResourceRoot res(tree, name, data);
for(int i = 0; i < resourceList()->size(); ) {
if(*resourceList()->at(i) == res) {
@ -885,7 +817,7 @@ public:
(b[offset+2] << 8) + (b[offset+3] << 0);
offset += 4;
if(version == 0x01) {
if(version == Q_RCC_OUTPUT_REVISION) {
buffer = b;
setSource(b+tree_offset, b+name_offset, b+data_offset);
return true;
@ -909,12 +841,9 @@ public:
bool registerSelf(const QString &f) {
QFile file(f);
if (!file.exists())
return false;
unsigned int data_len = file.size();
uchar *data = new uchar[data_len];
if (file.open(QIODevice::ReadOnly)) {
unsigned int data_len = file.size();
uchar *data = new uchar[data_len];
if (data_len != (uint)file.read((char*)data, data_len)) {
delete [] data;
data = 0;
@ -929,17 +858,6 @@ public:
}
};
static QString qt_resource_fixResourceRoot(QString r) {
if(!r.isEmpty()) {
if(r.startsWith(QLatin1Char(':')))
r = r.mid(1);
if(!r.isEmpty())
r = QDir::cleanPath(r);
}
return r;
}
/*!
\fn bool QResource::registerResource(const QString &rccFileName, const QString &mapRoot)
@ -953,14 +871,13 @@ static QString qt_resource_fixResourceRoot(QString r) {
bool
QResource::registerResource(const QString &rccFilename, const QString &resourceRoot)
{
QString r = qt_resource_fixResourceRoot(resourceRoot);
if(!r.isEmpty() && r[0] != QLatin1Char('/')) {
qWarning("QDir::registerResource: Registering a resource [%s] must be rooted in an absolute path (start with /) [%s]",
if(Q_UNLIKELY(!resourceRoot.startsWith(QLatin1String(":/")))) {
qWarning("QResource::registerResource: Registering a resource [%s] must be rooted in an absolute path (start with :/) [%s]",
rccFilename.toLocal8Bit().data(), resourceRoot.toLocal8Bit().data());
return false;
}
QDynamicFileResourceRoot *root = new QDynamicFileResourceRoot(r);
QDynamicFileResourceRoot *root = new QDynamicFileResourceRoot(resourceRoot);
if(root->registerSelf(rccFilename)) {
root->ref.ref();
QMutexLocker lock(resourceMutex());
@ -985,15 +902,13 @@ QResource::registerResource(const QString &rccFilename, const QString &resourceR
bool
QResource::unregisterResource(const QString &rccFilename, const QString &resourceRoot)
{
QString r = qt_resource_fixResourceRoot(resourceRoot);
QMutexLocker lock(resourceMutex());
ResourceList *list = resourceList();
for(int i = 0; i < list->size(); ++i) {
QResourceRoot *res = list->at(i);
if(res->type() == QResourceRoot::Resource_File) {
QDynamicFileResourceRoot *root = reinterpret_cast<QDynamicFileResourceRoot*>(res);
if(root->mappingFile() == rccFilename && root->mappingRoot() == r) {
QDynamicFileResourceRoot *root = reinterpret_cast<QDynamicFileResourceRoot*>(res);
if(root->mappingFile() == rccFilename && root->mappingRoot() == resourceRoot) {
resourceList()->removeAt(i);
if(!root->ref.deref()) {
delete root;
@ -1001,7 +916,7 @@ QResource::unregisterResource(const QString &rccFilename, const QString &resourc
}
return false;
}
}
}
}
return false;
}
@ -1024,14 +939,13 @@ QResource::unregisterResource(const QString &rccFilename, const QString &resourc
bool
QResource::registerResource(const uchar *rccData, const QString &resourceRoot)
{
QString r = qt_resource_fixResourceRoot(resourceRoot);
if(!r.isEmpty() && r[0] != QLatin1Char('/')) {
qWarning("QDir::registerResource: Registering a resource [%p] must be rooted in an absolute path (start with /) [%s]",
if(Q_UNLIKELY(!resourceRoot.startsWith(QLatin1String(":/")))) {
qWarning("QResource::registerResource: Registering a resource [%p] must be rooted in an absolute path (start with :/) [%s]",
rccData, resourceRoot.toLocal8Bit().data());
return false;
}
QDynamicBufferResourceRoot *root = new QDynamicBufferResourceRoot(r);
QDynamicBufferResourceRoot *root = new QDynamicBufferResourceRoot(resourceRoot);
if(root->registerSelf(rccData)) {
root->ref.ref();
QMutexLocker lock(resourceMutex());
@ -1056,23 +970,21 @@ QResource::registerResource(const uchar *rccData, const QString &resourceRoot)
bool
QResource::unregisterResource(const uchar *rccData, const QString &resourceRoot)
{
QString r = qt_resource_fixResourceRoot(resourceRoot);
QMutexLocker lock(resourceMutex());
ResourceList *list = resourceList();
for(int i = 0; i < list->size(); ++i) {
QResourceRoot *res = list->at(i);
if(res->type() == QResourceRoot::Resource_Buffer) {
QDynamicBufferResourceRoot *root = reinterpret_cast<QDynamicBufferResourceRoot*>(res);
if(root->mappingBuffer() == rccData && root->mappingRoot() == r) {
QDynamicBufferResourceRoot *root = reinterpret_cast<QDynamicBufferResourceRoot*>(res);
if(root->mappingBuffer() == rccData && root->mappingRoot() == resourceRoot) {
resourceList()->removeAt(i);
if(!root->ref.deref()) {
delete root;
return true;
}
return false;
return false;
}
}
}
}
return false;
}
@ -1107,11 +1019,6 @@ bool QResourceFileEngine::setSize(qint64)
return false;
}
QStringList QResourceFileEngine::entryList(QDir::Filters filters, const QStringList &filterNames) const
{
return QAbstractFileEngine::entryList(filters, filterNames);
}
bool QResourceFileEngine::caseSensitive() const
{
return true;
@ -1123,11 +1030,7 @@ QResourceFileEngine::QResourceFileEngine(const QString &file) :
Q_D(QResourceFileEngine);
d->resource.setFileName(file);
if(d->resource.isCompressed() && d->resource.size()) {
#ifndef QT_NO_COMPRESS
d->uncompressed = qFastUncompress(reinterpret_cast<const char*>(d->resource.data()), d->resource.size());
#else
Q_ASSERT(!"QResourceFileEngine::open: Qt built without support for compression");
#endif
}
}
@ -1144,7 +1047,7 @@ void QResourceFileEngine::setFileName(const QString &file)
bool QResourceFileEngine::open(QIODevice::OpenMode flags)
{
Q_D(QResourceFileEngine);
if (d->resource.fileName().isEmpty()) {
if (Q_UNLIKELY(d->resource.fileName().isEmpty())) {
qWarning("QResourceFileEngine::open: Missing file name");
return false;
}
@ -1280,20 +1183,18 @@ bool QResourceFileEngine::setPermissions(uint)
QString QResourceFileEngine::fileName(FileName file) const
{
Q_D(const QResourceFileEngine);
const QString filepath = d->resource.fileName();
if(file == BaseName) {
int slash = d->resource.fileName().lastIndexOf(QLatin1Char('/'));
if (slash == -1)
return d->resource.fileName();
return d->resource.fileName().mid(slash + 1);
} else if(file == PathName || file == AbsolutePathName) {
const QString path = (file == AbsolutePathName) ? d->resource.absoluteFilePath() : d->resource.fileName();
const int slash = path.lastIndexOf(QLatin1Char('/'));
int slash = filepath.lastIndexOf(QLatin1Char('/'));
if (slash == -1)
return QLatin1String(":");
else if (slash <= 1)
return filepath;
return filepath.mid(slash + 1);
} else if(file == PathName || file == AbsolutePathName) {
const QString path = (file == AbsolutePathName) ? d->resource.absoluteFilePath() : filepath;
const int slash = path.lastIndexOf(QLatin1Char('/'));
if (slash <= 1 || slash == path.size())
return QLatin1String(":/");
return path.left(slash);
} else if(file == CanonicalName || file == CanonicalPathName) {
const QString absoluteFilePath = d->resource.absoluteFilePath();
if(file == CanonicalPathName) {
@ -1303,7 +1204,7 @@ QString QResourceFileEngine::fileName(FileName file) const
}
return absoluteFilePath;
}
return d->resource.fileName();
return filepath;
}
bool QResourceFileEngine::isRelativePath() const
@ -1336,14 +1237,6 @@ QAbstractFileEngine::Iterator *QResourceFileEngine::beginEntryList(QDir::Filters
return new QResourceFileEngineIterator(filters, filterNames);
}
/*!
\internal
*/
QAbstractFileEngine::Iterator *QResourceFileEngine::endEntryList()
{
return 0;
}
bool QResourceFileEngine::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
{
Q_D(QResourceFileEngine);

View file

@ -41,6 +41,7 @@ QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
#define Q_RCC_OUTPUT_REVISION 0x02
class QResourcePrivate;
@ -63,9 +64,6 @@ public:
qint64 size() const;
const uchar *data() const;
static void addSearchPath(const QString &path);
static QStringList searchPaths();
static bool registerResource(const QString &rccFilename, const QString &resourceRoot=QString());
static bool unregisterResource(const QString &rccFilename, const QString &resourceRoot=QString());

View file

@ -84,8 +84,6 @@ public:
virtual bool setSize(qint64 size);
virtual QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const;
virtual bool caseSensitive() const;
virtual FileFlags fileFlags(FileFlags type) const;
@ -100,7 +98,6 @@ public:
virtual QDateTime fileTime(FileTime time) const;
virtual Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames);
virtual Iterator *endEntryList();
bool extension(Extension extension, const ExtensionOption *option = Q_NULLPTR, ExtensionReturn *output = Q_NULLPTR);
bool supportsExtension(Extension extension) const;

View file

@ -145,7 +145,7 @@ RCCFileInfo::~RCCFileInfo()
QString RCCFileInfo::resourceName() const
{
QString resource = m_name;
QString resource = (m_name.isEmpty() ? QLatin1String("/") : m_name);
for (RCCFileInfo *p = m_parent; p; p = p->m_parent)
resource = resource.prepend(p->m_name + QLatin1Char('/'));
return QLatin1Char(':') + resource;
@ -735,7 +735,7 @@ bool RCCResourceLibrary::writeHeader()
writeString("\n**\n");
writeString("** WARNING! All changes made in this file will be lost!\n");
writeString( "*****************************************************************************/\n\n");
writeString("#include <QtCore/qglobal.h>\n\n");
writeString("#include <QtCore/qresource.h>\n\n");
} else if (m_format == Binary) {
writeString("qres");
writeNumber4(0);
@ -907,7 +907,7 @@ bool RCCResourceLibrary::writeInitializer()
{
if (m_format == C_Code) {
QByteArray initLatin = m_initName.toLatin1();
QByteArray resourceDataString = "\n (0x01, qt_resource_struct_" + initLatin +
QByteArray resourceDataString = "\n (Q_RCC_OUTPUT_REVISION, qt_resource_struct_" + initLatin +
", qt_resource_name_" + initLatin +
", qt_resource_data_" + initLatin + ");\n";
//write("\nQT_BEGIN_NAMESPACE\n");
@ -958,10 +958,10 @@ bool RCCResourceLibrary::writeInitializer()
} else if (m_format == Binary) {
int i = 4;
char *p = m_out.data();
p[i++] = 0; // 0x01
p[i++] = 0; // Q_RCC_OUTPUT_REVISION
p[i++] = 0;
p[i++] = 0;
p[i++] = 1;
p[i++] = 2;
p[i++] = (m_treeOffset >> 24) & 0xff;
p[i++] = (m_treeOffset >> 16) & 0xff;

View file

@ -1 +0,0 @@
mostly empty

View file

@ -1 +0,0 @@
mostly empty

View file

@ -139,11 +139,6 @@ private slots:
void nativeSeparators();
void searchPaths();
void searchPaths_data();
void entryListWithSearchPaths();
void longFileName_data();
void longFileName();
@ -1130,107 +1125,6 @@ void tst_QDir::nativeSeparators()
QCOMPARE(QDir::fromNativeSeparators(QLatin1String("\\")), QString("\\"));
}
void tst_QDir::searchPaths_data()
{
QTest::addColumn<QString>("filename");
QTest::addColumn<QString>("searchPathPrefixes");
QTest::addColumn<QString>("searchPaths");
QTest::addColumn<QString>("expectedAbsolutePath");
QString srcdir = SRCDIR;
if (srcdir.isEmpty())
srcdir = QDir::currentPath();
else
srcdir.chop(1); // remove ending slash
QString searchDir = srcdir + "/searchdir";
// sanity
QTest::newRow("nopath") << "picker.png" << QString() << QString() << QString();
QTest::newRow("emptysearchpath") << "subdir1/picker.png" << QString() << QString() << QString();
QTest::newRow("searchpathwithoutprefix") << SRCDIR "searchdir/subdir1/picker.png" << QString("searchpath") << QString("searchdir") << (searchDir+"/subdir1/picker.png");
// new
QTest::newRow("novalidsearchpath") << "searchpath:subdir1/picker.png" << QString() << QString() << QString();
QTest::newRow("invalidsearchpath") << "searchpath:subdir1/picker.png" << QString("invalid") << QString("invalid") << QString();
QTest::newRow("onlyvalidsearchpath") << "searchpath:subdir1/picker.png" << QString("searchpath") << QString(SRCDIR "searchdir") << (searchDir+"/subdir1/picker.png");
QTest::newRow("validandinvalidsearchpath") << "searchpath:subdir1/picker.png" << QString("invalid;searchpath") << QString("invalid;" SRCDIR "searchdir") << (searchDir+"/subdir1/picker.png");
QTest::newRow("precedence1") << "searchpath:picker.png" << QString("invalid;searchpath") << QString("invalid;" SRCDIR "searchdir/subdir1," SRCDIR "searchdir/subdir2") << (searchDir+"/subdir1/picker.png");
QTest::newRow("precedence2") << "searchpath:picker.png" << QString("invalid;searchpath") << QString("invalid;" SRCDIR "searchdir/subdir2," SRCDIR "searchdir/subdir1") << (searchDir+"/subdir2/picker.png");
QTest::newRow("precedence3") << "searchpath2:picker.png" << QString("searchpath1;searchpath2") << QString(SRCDIR "searchdir/subdir1;" SRCDIR "searchdir/subdir2") << (searchDir+"/subdir2/picker.png");
// re
}
void tst_QDir::searchPaths()
{
QFETCH(QString, filename);
QFETCH(QString, searchPathPrefixes);
QStringList searchPathPrefixList = searchPathPrefixes.split(";", QString::SkipEmptyParts);
QFETCH(QString, searchPaths);
QStringList searchPathsList = searchPaths.split(";", QString::SkipEmptyParts);
QFETCH(QString, expectedAbsolutePath);
bool exists = !expectedAbsolutePath.isEmpty();
for (int i = 0; i < searchPathPrefixList.count(); ++i) {
QDir::setSearchPaths(searchPathPrefixList.at(i), searchPathsList.at(i).split(","));
}
for (int i = 0; i < searchPathPrefixList.count(); ++i) {
QVERIFY(QDir::searchPaths(searchPathPrefixList.at(i)) == searchPathsList.at(i).split(","));
}
QCOMPARE(QFile(filename).exists(), exists);
QCOMPARE(QFileInfo(filename).exists(), exists);
if (exists) {
QCOMPARE(QFileInfo(filename).absoluteFilePath(), expectedAbsolutePath);
}
for (int i = 0; i < searchPathPrefixList.count(); ++i) {
QDir::setSearchPaths(searchPathPrefixList.at(i), QStringList());
}
for (int i = 0; i < searchPathPrefixList.count(); ++i) {
QVERIFY(QDir::searchPaths(searchPathPrefixList.at(i)).isEmpty());
}
for (int i = 0; i < searchPathPrefixList.count(); ++i) {
foreach (QString path, searchPathsList.at(i).split(",")) {
QDir::addSearchPath(searchPathPrefixList.at(i), path);
}
}
for (int i = 0; i < searchPathPrefixList.count(); ++i) {
QVERIFY(QDir::searchPaths(searchPathPrefixList.at(i)) == searchPathsList.at(i).split(","));
}
QCOMPARE(QFile(filename).exists(), exists);
QCOMPARE(QFileInfo(filename).exists(), exists);
if (exists) {
QCOMPARE(QFileInfo(filename).absoluteFilePath(), expectedAbsolutePath);
}
for (int i = 0; i < searchPathPrefixList.count(); ++i) {
QDir::setSearchPaths(searchPathPrefixList.at(i), QStringList());
}
for (int i = 0; i < searchPathPrefixList.count(); ++i) {
QVERIFY(QDir::searchPaths(searchPathPrefixList.at(i)).isEmpty());
}
}
void tst_QDir::entryListWithSearchPaths()
{
QDir realDir(":/tst_qdir/resources/entryList");
QVERIFY(realDir.exists());
QVERIFY(!realDir.entryList().isEmpty());
QVERIFY(realDir.entryList().contains("file3.data"));
QDir::setSearchPaths("searchpath", QStringList(":/tst_qdir/resources"));
QDir dir("searchpath:entryList/");
QCOMPARE(dir.path(), QString(":/tst_qdir/resources/entryList"));
QVERIFY(dir.exists());
QStringList entryList = dir.entryList();
QVERIFY(entryList.contains("file3.data"));
}
void tst_QDir::longFileName_data()
{
QTest::addColumn<int>("length");

View file

@ -887,9 +887,7 @@ void tst_QFileInfo::isLocalFs()
QFileInfo info(path);
QFileInfoPrivate *privateInfo = getPrivate(info);
QCOMPARE((privateInfo->fileEngine == 0), isLocalFs);
if (privateInfo->fileEngine)
QCOMPARE(bool(privateInfo->fileEngine->fileFlags(QAbstractFileEngine::LocalDiskFlag)
QCOMPARE(bool(privateInfo->fileEngine->fileFlags(QAbstractFileEngine::LocalDiskFlag)
& QAbstractFileEngine::LocalDiskFlag), isLocalFs);
}