⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qresource.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the QtCore module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file.  Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qresource_p.h"#include "qset.h"#include "qhash.h"#include "qlocale.h"#include "qglobal.h"#include "qdatetime.h"#include "qbytearray.h"#include "qstringlist.h"#include "qvector.h"#include "private/qabstractfileengine_p.h"//resource glueclass QResource{    enum Flags    {        Compressed = 0x01,        Directory = 0x02    };    const uchar *tree, *names, *payloads;    int findNode(const QString &path) const;    inline int findOffset(int node) const { return node * 14; } //sizeof each tree element    inline int hash(int offset) const;    inline QString name(int offset) const;public:    inline QResource(): tree(0), names(0), payloads(0) {}    inline QResource(const uchar *t, const uchar *n, const uchar *d)        : tree(t), names(n), payloads(d) {}    bool isContainer(const QString &path) const;    bool exists(const QString &path) const;    QByteArray data(const QString &path) const;    QStringList children(const QString &path) const;    inline bool operator==(const QResource &other) const    { return tree == other.tree && names == other.names && payloads == other.payloads; }    inline bool operator!=(const QResource &other) const    { return !operator==(other); }};Q_DECLARE_TYPEINFO(QResource, Q_MOVABLE_TYPE);inline int QResource::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 QResource::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 QResource::findNode(const QString &path) const{    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;    QLocale locale;    QStringList segments = path.split('/', QString::SkipEmptyParts);    for(int i = 0; child_count && i < segments.size(); ++i) {        const QString &segment = segments[i];        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) + 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;                            if(country == locale.country() && language == locale.language())                                return sub_node;                            else if((country == QLocale::AnyCountry && language == locale.language()) ||                                    (country == QLocale::AnyCountry && language == QLocale::C && node == -1))                                node = sub_node;                            continue;                        } else {                            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;    }    return node;}bool QResource::isContainer(const QString &path) const{    int node = findNode(path);    if(node == -1)        return false;    const int offset = findOffset(node) + 4; //jump past name    const short flags = (tree[offset+0] << 8) + (tree[offset+1] << 0);    return flags & Directory;}bool QResource::exists(const QString &path) const{    return findNode(path) != -1;}QByteArray QResource::data(const QString &path) const{    const int node = findNode(path);    if(node == -1)        return QByteArray();    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    QByteArray ret;    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 *data = payloads+data_offset+4;#ifndef QT_NO_COMPRESS        if(flags & Compressed)            ret = qUncompress(data, data_length);        else            ret = QByteArray((char*)data, data_length);#else        Q_ASSERT_X(!(flags & Compressed), "QResource::data",                   "Qt built without support for compression");        #endif    }    return ret;}QStringList QResource::children(const QString &path) const{    int node = findNode(path);    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;}Q_GLOBAL_STATIC(QStringList, qt_resource_search_paths)bool qt_resource_add_search_path(const QString &path){    if(path[0] != QLatin1Char('/')) {        qWarning("QDir::addResourceSearchPath: Search paths must be absolute (start with /) [%s]",                 path.toLocal8Bit().data());        return false;    }    qt_resource_search_paths()->prepend(path);    return true;}typedef QVector<QResource> ResourceList;Q_GLOBAL_STATIC(ResourceList, resourceList)class QResourceInfo{    QString file, searchFile;    ResourceList related;    uint container : 1;    mutable uint hasData : 1;    mutable uint hasChildren : 1;    mutable uint initialized : 1;    mutable QByteArray mData;    mutable QStringList mChildren;    inline void clear() {        searchFile.clear();        file.clear();        hasData = hasChildren = 0;        container = 0;        related.clear();        initialized = 0;    }    bool loadResource(const QString &);public:    QResourceInfo() { clear(); }    QResourceInfo(const QString &f) : file(f), initialized(0) {}    void setFileName(const QString &f) { clear(); file = f; }    QString fileName() const { return file; }    QString searchFileName() const { ensureInitialized(); return searchFile; }    bool exists() const { ensureInitialized(); return !related.isEmpty(); }    bool isContainer() const { ensureInitialized(); return container; }    QByteArray data() const;    QStringList children() const;    void ensureInitialized() const;};boolQResourceInfo::loadResource(const QString &path){    ensureInitialized();    const ResourceList *list = resourceList();    for(int i = 0; i < list->size(); ++i) {        QResource res = list->at(i);        if(res.exists(path)) {            if(related.isEmpty())                container = res.isContainer(path);            else if(res.isContainer(path) != container)                qWarning("Resource [%s] has both data and children!", file.toLatin1().constData());            related.append(res);        }    }    return !related.isEmpty();}void QResourceInfo::ensureInitialized() const{    if (initialized)        return;    initialized = 1;    QResourceInfo *that = const_cast<QResourceInfo *>(this);    if(file == QLatin1String(":"))        that->file += QLatin1Char('/');    that->searchFile = file;    QString path = file;    if(path.startsWith(QLatin1Char(':')))        path = path.mid(1);    if(path.startsWith(QLatin1Char('/'))) {        that->loadResource(path);        return;    } else {        QStringList searchPaths = *qt_resource_search_paths();        searchPaths << QLatin1String("");        for(int i = 0; i < searchPaths.size(); ++i) {            const QString searchPath(searchPaths.at(i) + QLatin1Char('/') + path);            if(that->loadResource(searchPath)) {                that->searchFile = QLatin1Char(':') + searchPath;                break;            }        }    }}QByteArray QResourceInfo::data() const{    if(container || related.isEmpty())        return QByteArray();    if(!hasData) {        hasData = true;        QString path = searchFile;        if(path.startsWith(QLatin1Char(':')))            path = path.mid(1);        mData = related.at(0).data(path);    }    return mData;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -