📄 qresource.cpp
字号:
bool QResource::isDir() const{ Q_D(const QResource); d->ensureInitialized(); return d->container;}/*! Returns a list of all resources in this directory, if the resource represents a file the list will be empty. \sa isDir()*/QStringList QResource::children() const{ Q_D(const QResource); d->ensureChildren(); return d->children;}/*! \obsolete 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. Use QDir::addSearchPath() with a prefix instead.*/voidQResource::addSearchPath(const QString &path){ if (!path.startsWith(QLatin1Char('/'))) { qWarning("QResource::addResourceSearchPath: Search paths must be absolute (start with /) [%s]", path.toLocal8Bit().data()); return; } QMutexLocker lock(resourceMutex()); resourceSearchPaths()->prepend(path);}/*! Returns the current search path list. This list is consulted when creating a relative resource. \sa addSearchPath()*/QStringListQResource::searchPaths(){ QMutexLocker lock(resourceMutex()); return *resourceSearchPaths();}inline int QResourceRoot::hash(int node) const{ if(!node) //root return 0; const int offset = findOffset(node); int name_offset = (tree[offset+0] << 24) + (tree[offset+1] << 16) + (tree[offset+2] << 8) + (tree[offset+3] << 0); name_offset += 2; //jump past name length return (names[name_offset+0] << 24) + (names[name_offset+1] << 16) + (names[name_offset+2] << 8) + (names[name_offset+3] << 0);}inline QString QResourceRoot::name(int node) const{ if(!node) // root return QString(); const int offset = findOffset(node); QString ret; int name_offset = (tree[offset+0] << 24) + (tree[offset+1] << 16) + (tree[offset+2] << 8) + (tree[offset+3] << 0); const short name_length = (names[name_offset+0] << 8) + (names[name_offset+1] << 0); name_offset += 2; name_offset += 4; //jump past hash for(int i = 0; i < name_length*2; i+=2) ret += QChar(names[name_offset+i+1], names[name_offset+i]); return ret;}int QResourceRoot::findNode(const QString &_path, const QLocale &locale) const{ QString path = _path; { QString root = mappingRoot(); if(!root.isEmpty()) { if(root == path) { path = QLatin1String("/"); } else { if(!root.endsWith(QLatin1String("/"))) root += QLatin1String("/"); if(path.size() >= root.size() && path.startsWith(root)) path = path.mid(root.length()-1); if(path.isEmpty()) path = QLatin1String("/"); } } }#ifdef DEBUG_RESOURCE_MATCH qDebug() << "!!!!" << "START" << path << locale.country() << locale.language();#endif if(path == QLatin1String("/")) return 0; //the root node is always first int child_count = (tree[6] << 24) + (tree[7] << 16) + (tree[8] << 8) + (tree[9] << 0); int child = (tree[10] << 24) + (tree[11] << 16) + (tree[12] << 8) + (tree[13] << 0); //now iterate up the tree int node = -1; QStringList segments = path.split(QLatin1Char('/'), QString::SkipEmptyParts);#ifdef DEBUG_RESOURCE_MATCH qDebug() << "****" << segments;#endif for(int i = 0; child_count && i < segments.size(); ++i) { const QString &segment = segments[i];#ifdef DEBUG_RESOURCE_MATCH qDebug() << " CHILDREN" << segment; for(int j = 0; j < child_count; ++j) { qDebug() << " " << child+j << " :: " << name(child+j); }#endif const int h = qHash(segment); //do the binary search for the hash int l = 0, r = child_count-1; int sub_node = (l+r+1)/2; while(r != l) { const int sub_node_hash = hash(child+sub_node); if(h == sub_node_hash) break; else if(h < sub_node_hash) r = sub_node - 1; else l = sub_node; sub_node = (l + r + 1) / 2; } sub_node += child; //now do the "harder" compares bool found = false; if(hash(sub_node) == h) { while(sub_node > child && hash(sub_node-1) == h) //backup for collisions --sub_node; for(; sub_node < child+child_count && hash(sub_node) == h; ++sub_node) { //here we go... if(name(sub_node) == segment) { found = true; int offset = findOffset(sub_node);#ifdef DEBUG_RESOURCE_MATCH qDebug() << " TRY" << sub_node << name(sub_node) << offset;#endif offset += 4; //jump past name const short flags = (tree[offset+0] << 8) + (tree[offset+1] << 0); offset += 2; if(i == segments.size()-1) { if(!(flags & Directory)) { const short country = (tree[offset+0] << 8) + (tree[offset+1] << 0); offset += 2; const short language = (tree[offset+0] << 8) + (tree[offset+1] << 0); offset += 2;#ifdef DEBUG_RESOURCE_MATCH qDebug() << " " << "LOCALE" << country << language;#endif if(country == locale.country() && language == locale.language()) {#ifdef DEBUG_RESOURCE_MATCH qDebug() << "!!!!" << "FINISHED" << __LINE__ << sub_node;#endif return sub_node; } else if((country == QLocale::AnyCountry && language == locale.language()) || (country == QLocale::AnyCountry && language == QLocale::C && node == -1)) { node = sub_node; } continue; } else {#ifdef DEBUG_RESOURCE_MATCH qDebug() << "!!!!" << "FINISHED" << __LINE__ << sub_node;#endif return sub_node; } } if(!(flags & Directory)) return -1; child_count = (tree[offset+0] << 24) + (tree[offset+1] << 16) + (tree[offset+2] << 8) + (tree[offset+3] << 0); offset += 4; child = (tree[offset+0] << 24) + (tree[offset+1] << 16) + (tree[offset+2] << 8) + (tree[offset+3] << 0); break; } } } if(!found) break; }#ifdef DEBUG_RESOURCE_MATCH qDebug() << "!!!!" << "FINISHED" << __LINE__ << node;#endif return node;}short QResourceRoot::flags(int node) const{ if(node == -1) return 0; const int offset = findOffset(node) + 4; //jump past name return (tree[offset+0] << 8) + (tree[offset+1] << 0);}const uchar *QResourceRoot::data(int node, qint64 *size) const{ if(node == -1) { *size = 0; return 0; } int offset = findOffset(node) + 4; //jump past name const short flags = (tree[offset+0] << 8) + (tree[offset+1] << 0); offset += 2; offset += 4; //jump past locale if(!(flags & Directory)) { const int data_offset = (tree[offset+0] << 24) + (tree[offset+1] << 16) + (tree[offset+2] << 8) + (tree[offset+3] << 0); const uint data_length = (payloads[data_offset+0] << 24) + (payloads[data_offset+1] << 16) + (payloads[data_offset+2] << 8) + (payloads[data_offset+3] << 0); const uchar *ret = payloads+data_offset+4; *size = data_length; return ret; } *size = 0; return 0;}QStringList QResourceRoot::children(int node) const{ if(node == -1) return QStringList(); int offset = findOffset(node) + 4; //jump past name const short flags = (tree[offset+0] << 8) + (tree[offset+1] << 0); offset += 2; QStringList ret; if(flags & Directory) { const int child_count = (tree[offset+0] << 24) + (tree[offset+1] << 16) + (tree[offset+2] << 8) + (tree[offset+3] << 0); offset += 4; const int child_off = (tree[offset+0] << 24) + (tree[offset+1] << 16) + (tree[offset+2] << 8) + (tree[offset+3] << 0); for(int i = child_off; i < child_off+child_count; ++i) ret << name(i); } return ret;}bool QResourceRoot::mappingRootSubdir(const QString &path, QString *match) const{ const QString root = mappingRoot(); if(!root.isEmpty()) { const QStringList root_segments = root.split(QLatin1Char('/'), QString::SkipEmptyParts), path_segments = path.split(QLatin1Char('/'), QString::SkipEmptyParts); if(path_segments.size() <= root_segments.size()) { int matched = 0; for(int i = 0; i < path_segments.size(); ++i) { if(root_segments[i] != path_segments[i]) break; ++matched; } if(matched == path_segments.size()) { if(match && root_segments.size() > matched) *match = root_segments.at(matched); return true; } } } return false;}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()) { bool found = false; QResourceRoot res(tree, name, data); for(int i = 0; i < resourceList()->size(); ++i) { if(*resourceList()->at(i) == res) { found = true; break; } } if(!found) { QResourceRoot *root = new QResourceRoot(tree, name, data); root->ref.ref(); resourceList()->append(root); } return true; } return false;}Q_CORE_EXPORT bool qUnregisterResourceData(int version, const unsigned char *tree, const unsigned char *name, const unsigned char *data){ QMutexLocker lock(resourceMutex()); if(version == 0x01 && resourceList()) { QResourceRoot res(tree, name, data); for(int i = 0; i < resourceList()->size(); ) { if(*resourceList()->at(i) == res) { QResourceRoot *root = resourceList()->takeAt(i); if(!root->ref.deref()) delete root; } else { ++i; } } return true; } return false;}//run time resource creationclass QDynamicBufferResourceRoot: public QResourceRoot{ QString root; const uchar *buffer;public: inline QDynamicBufferResourceRoot(const QString &_root) : root(_root), buffer(0) { } inline ~QDynamicBufferResourceRoot() { } inline const uchar *mappingBuffer() const { return buffer; } virtual QString mappingRoot() const { return root; } virtual ResourceRootType type() const { return Resource_Buffer; } bool registerSelf(const uchar *b) { //setup the data now int offset = 0; //magic number if(b[offset+0] != 'q' || b[offset+1] != 'r' || b[offset+2] != 'e' || b[offset+3] != 's') { return false; } offset += 4; const int version = (b[offset+0] << 24) + (b[offset+1] << 16) + (b[offset+2] << 8) + (b[offset+3] << 0); offset += 4; const int tree_offset = (b[offset+0] << 24) + (b[offset+1] << 16) + (b[offset+2] << 8) + (b[offset+3] << 0); offset += 4; const int data_offset = (b[offset+0] << 24) + (b[offset+1] << 16) + (b[offset+2] << 8) + (b[offset+3] << 0); offset += 4; const int name_offset = (b[offset+0] << 24) + (b[offset+1] << 16) + (b[offset+2] << 8) + (b[offset+3] << 0); offset += 4; if(version == 0x01) { buffer = b; setSource(b+tree_offset, b+name_offset, b+data_offset); return true; } return false; }};#if defined(Q_OS_UNIX)#define QT_USE_MMAP#endif// most of the headers below are already included in qplatformdefs.h// also this lacks Large File support but that's probably irrelevant#if defined(QT_USE_MMAP)// for mmap#include <sys/mman.h>#include <errno.h>#endifclass QDynamicFileResourceRoot: public QDynamicBufferResourceRoot{ QString fileName; // for mmap'ed files, this is what needs to be unmapped. uchar *unmapPointer; unsigned int unmapLength;public: inline QDynamicFileResourceRoot(const QString &_root) : QDynamicBufferResourceRoot(_root), unmapPointer(0), unmapLength(0) { } ~QDynamicFileResourceRoot() {#if defined(QT_USE_MMAP) if (unmapPointer) { munmap((char*)unmapPointer, unmapLength); unmapPointer = 0; unmapLength = 0; } else#endif { delete [] (uchar *)mappingBuffer(); } } QString mappingFile() const { return fileName; } virtual ResourceRootType type() const { return Resource_File; } bool registerSelf(const QString &f) { bool fromMM = false; uchar *data = 0; unsigned int data_len = 0;#ifdef QT_USE_MMAP#ifndef MAP_FILE#define MAP_FILE 0#endif#ifndef MAP_FAILED#define MAP_FAILED -1#endif int fd = QT_OPEN(QFile::encodeName(f), O_RDONLY,#if defined(Q_OS_WIN) _S_IREAD | _S_IWRITE#else 0666#endif ); if (fd >= 0) { QT_STATBUF st; if (!QT_FSTAT(fd, &st)) { uchar *ptr; ptr = reinterpret_cast<uchar *>( mmap(0, st.st_size, // any address, whole file PROT_READ, // read-only memory MAP_FILE | MAP_PRIVATE, // swap-backed map from file fd, 0)); // from offset 0 of fd if (ptr && ptr != reinterpret_cast<uchar *>(MAP_FAILED)) { data = ptr; data_len = st.st_size; fromMM = true; } } ::close(fd); }#endif // QT_USE_MMAP if(!data) { QFile file(f); if (!file.exists()) return false; data_len = file.size(); data = new uchar[data_len];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -