9#include <private/qlocking_p.h>
19#include <qplatformdefs.h>
21#include "private/qabstractfileengine_p.h"
22#include "private/qduplicatetracker_p.h"
23#include "private/qnumeric_p.h"
24#include "private/qsimd_p.h"
25#include "private/qtools_p.h"
26#include "private/qsystemerror_p.h"
36#if defined(Q_OS_UNIX) && !defined(Q_OS_NACL) && !defined(Q_OS_INTEGRITY)
50#if defined(__ELF__) || defined(__APPLE__)
51# define RCC_FEATURE_SYMBOL(feature) \
52 extern Q_CORE_EXPORT const quint8 qt_resourceFeature ## feature; \
53 const quint8 qt_resourceFeature ## feature = 0;
55# define RCC_FEATURE_SYMBOL(feature) \
56 Q_CORE_EXPORT quint8 qResourceFeature ## feature() { return 0; }
66#undef RCC_FEATURE_SYMBOL
111 inline int findOffset(
int node)
const {
return node * (14 + (version >= 0x02 ? 8 : 0)); }
114 short flags(
int node)
const;
158 if (
path.startsWith(
"//"_L1))
174{
return resourceGlobalData->resourceMutex; }
177{
return &resourceGlobalData->resourceList; }
323 qWarning(
"QResourceInfo: Resource [%s] has both data and children!",
324 file.toLatin1().constData());
328 }
else if (
res->mappingRootSubdir(
file)) {
353 if (
path.startsWith(u
':'))
356 if (
path.startsWith(u
'/')) {
361 if (that->
load(searchPath))
373 if (
path.startsWith(u
':'))
379 if (
res->mappingRootSubdir(
path, &k) && !k.isEmpty()) {
386 for (
int kid = 0; kid < related_children.size(); ++kid) {
387 k = related_children.at(kid);
403#ifndef QT_NO_COMPRESS
405 return qFromBigEndian<quint32>(
data);
407 Q_ASSERT(!
"QResource: Qt built without support for Zlib compression");
414 size_t n = ZSTD_getFrameContentSize(
data,
size);
415 return ZSTD_isError(
n) ? -1 :
qint64(
n);
418 Q_ASSERT(!
"QResource: Qt built without support for Zstd compression");
429#if defined(QT_NO_COMPRESS) && !QT_CONFIG(zstd)
440#ifndef QT_NO_COMPRESS
441 uLong
len = uLong(bufferSize);
445 qWarning(
"QResource: error decompressing zlib content (%d)",
res);
457 if (ZSTD_isError(usize)) {
458 qWarning(
"QResource: error decompressing zstd content: %s", ZSTD_getErrorName(usize));
542 d->ensureInitialized();
556 d->ensureInitialized();
557 return d->absoluteFilePath;
569 d->ensureInitialized();
570 return !
d->related.isEmpty();
603 d->ensureInitialized();
619 d->ensureInitialized();
636 d->ensureInitialized();
637 return d->uncompressedSize();
652 d->ensureInitialized();
675 if (
n > std::numeric_limits<QByteArray::size_type>::max()) {
676 qWarning(
"QResource: compressed content does not fit into a QByteArray; use QFile instead");
701 d->ensureInitialized();
715 d->ensureInitialized();
733inline uint QResourceRoot::hash(
int node)
const
737 const int offset = findOffset(node);
738 qint32 name_offset = qFromBigEndian<qint32>(tree +
offset);
740 return qFromBigEndian<quint32>(
names + name_offset);
742inline QString QResourceRoot::name(
int node)
const
746 const int offset = findOffset(node);
749 qint32 name_offset = qFromBigEndian<qint32>(tree +
offset);
750 quint16 name_length = qFromBigEndian<qint16>(
names + name_offset);
754 ret.resize(name_length);
756 qFromBigEndian<char16_t>(
names + name_offset, name_length, strData);
771 if (
path.size() >= root.
size() &&
path.startsWith(root))
778#ifdef DEBUG_RESOURCE_MATCH
779 qDebug() <<
"!!!!" <<
"START" <<
path << locale.territory() << locale.language();
786 qint32 child_count = qFromBigEndian<qint32>(tree + 6);
793 while (child_count && splitter.
hasNext()) {
796#ifdef DEBUG_RESOURCE_MATCH
798 for (
int j = 0;
j < child_count; ++
j) {
805 int l = 0,
r = child_count - 1;
806 int sub_node = (l +
r + 1) / 2;
809 if (
h == sub_node_hash)
811 else if (
h < sub_node_hash)
815 sub_node = (l +
r + 1) / 2;
821 if (
hash(sub_node) ==
h) {
822 while (sub_node >
child &&
hash(sub_node - 1) ==
h)
824 for (; sub_node <
child + child_count &&
hash(sub_node) ==
h;
828 int offset = findOffset(sub_node);
829#ifdef DEBUG_RESOURCE_MATCH
839 const qint16 territory = qFromBigEndian<qint16>(tree +
offset);
844#ifdef DEBUG_RESOURCE_MATCH
847 if (territory == locale.territory() &&
language == locale.language()) {
848#ifdef DEBUG_RESOURCE_MATCH
849 qDebug() <<
"!!!!" <<
"FINISHED" << __LINE__ << sub_node;
861#ifdef DEBUG_RESOURCE_MATCH
862 qDebug() <<
"!!!!" <<
"FINISHED" << __LINE__ << sub_node;
872 child_count = qFromBigEndian<qint32>(tree +
offset);
882#ifdef DEBUG_RESOURCE_MATCH
883 qDebug() <<
"!!!!" <<
"FINISHED" << __LINE__ << node;
887short QResourceRoot::flags(
int node)
const
891 const int offset = findOffset(node) + 4;
892 return qFromBigEndian<qint16>(tree +
offset);
900 int offset = findOffset(node) + 4;
908 const qint32 data_offset = qFromBigEndian<qint32>(tree +
offset);
909 const quint32 data_length = qFromBigEndian<quint32>(payloads + data_offset);
910 const uchar *
ret = payloads + data_offset + 4;
920 if (node == -1 || version < 0x02)
923 const int offset = findOffset(node) + 14;
925 return qFromBigEndian<quint64>(tree +
offset);
932 int offset = findOffset(node) + 4;
939 const qint32 child_count = qFromBigEndian<qint32>(tree +
offset);
941 const qint32 child_off = qFromBigEndian<qint32>(tree +
offset);
942 ret.reserve(child_count);
943 for (
int i = child_off;
i < child_off + child_count; ++
i)
972 const unsigned char *
name,
const unsigned char *
data)
974 if (resourceGlobalData.isDestroyed())
978 if (version >= 0x01 && version <= 0x3) {
998 const unsigned char *
name,
const unsigned char *
data)
1000 if (resourceGlobalData.isDestroyed())
1004 if (version >= 0x01 && version <= 0x3) {
1052 const int version = qFromBigEndian<qint32>(
b +
offset);
1055 const int tree_offset = qFromBigEndian<qint32>(
b +
offset);
1058 const int data_offset = qFromBigEndian<qint32>(
b +
offset);
1061 const int name_offset = qFromBigEndian<qint32>(
b +
offset);
1066 file_flags = qFromBigEndian<qint32>(
b +
offset);
1071 if (
size >= 0 && (tree_offset >=
size || data_offset >=
size || name_offset >=
size))
1076#ifndef QT_NO_COMPRESS
1081 if (file_flags & ~acceptableFlags)
1084 if (version >= 0x01 && version <= 0x03) {
1086 setSource(version,
b + tree_offset,
b + name_offset,
b + data_offset);
1097 uchar *unmapPointer;
1105#if defined(QT_USE_MMAP)
1107 munmap(
reinterpret_cast<char *
>(unmapPointer), unmapLength);
1108 unmapPointer =
nullptr;
1126# define MAP_FAILED reinterpret_cast<void *>(-1)
1131 bool fromMM =
false;
1135#if defined(QT_USE_MMAP)
1139 if (!QT_FSTAT(
fd, &st) && st.st_size <= std::numeric_limits<qsizetype>::max()) {
1140 int protection = PROT_READ;
1142 void *
ptr = QT_MMAP(
nullptr, st.st_size,
1147 data_len = st.st_size;
1159 if (
fsize <= std::numeric_limits<qsizetype>::max()) {
1162 ok = (data_len ==
file.
read(
reinterpret_cast<char *
>(
data), data_len));
1175 unmapPointer =
data;
1176 unmapLength = data_len;
1187 if (
r.startsWith(u
':'))
1208 if (!
r.isEmpty() &&
r[0] != u
'/') {
1209 qWarning(
"QDir::registerResource: Registering a resource [%ls] must be rooted in an "
1210 "absolute path (start with /) [%ls]",
1277 if (!
r.isEmpty() &&
r[0] != u
'/') {
1278 qWarning(
"QDir::registerResource: Registering a resource [%p] must be rooted in an "
1279 "absolute path (start with /) [%ls]",
1329#if !defined(QT_BOOTSTRAPPED)
1338 void uncompress()
const;
1355 d->resource.setFileName(
file);
1365 d->resource.setFileName(
file);
1369 std::optional<QFile::Permissions> permissions)
1374 if (
d->resource.fileName().isEmpty()) {
1375 qWarning(
"QResourceFileEngine::open: Missing file name");
1382 if (
d->uncompressed.isNull()) {
1387 if (!
d->resource.isValid()) {
1413 if (!
d->uncompressed.isNull())
1414 memcpy(
data,
d->uncompressed.constData() +
d->offset,
len);
1416 memcpy(
data,
d->resource.data() +
d->offset,
len);
1424 return d->resource.isValid() ?
d->resource.uncompressedSize() : 0;
1436 if (!
d->resource.isValid())
1438 return d->offset ==
size();
1444 if (!
d->resource.isValid())
1447 if (
d->offset >
size())
1456 QAbstractFileEngine::FileFlags
ret;
1457 if (!
d->resource.isValid())
1464 if (
d->resource.isDir())
1471 if (
d->resource.absoluteFilePath() ==
":/"_L1)
1481 const qsizetype slash =
d->resource.fileName().lastIndexOf(u
'/');
1483 return d->resource.fileName();
1484 return d->resource.fileName().mid(slash + 1);
1487 :
d->resource.fileName();
1491 else if (slash <= 1)
1493 return path.left(slash);
1504 return d->resource.fileName();
1509 static const uint nobodyID =
static_cast<uint>(-2);
1517 return d->resource.lastModified();
1544 returnValue->
address =
d->map(options->offset, options->size, options->flags);
1545 return (returnValue->address !=
nullptr);
1549 return d->unmap(options->address);
1575 if (uncompressed.
isNull())
1583bool QResourceFileEnginePrivate::unmap(
uchar *
ptr)
1589void QResourceFileEnginePrivate::uncompress()
const
1592 || !uncompressed.
isEmpty() || resource.
size() == 0)
The QAbstractFileEngineIterator class provides an iterator interface for custom file engines.
\inmodule QtCore \reentrant
FileOwner
\value OwnerUser The user who owns the file.
FileTime
These are used by the fileTime() function.
FileName
These values are used to request a file name in a particular format.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
bool isNull() const noexcept
Returns true if this byte array is null; otherwise returns false.
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
\inmodule QtCore\reentrant
static QDateTime fromMSecsSinceEpoch(qint64 msecs, const QTimeZone &timeZone)
static QString cleanPath(const QString &path)
Returns path with directory separators normalized (that is, platform-native separators converted to "...
bool registerSelf(const uchar *b, qsizetype size)
QString mappingRoot() const override
QDynamicBufferResourceRoot(const QString &_root)
~QDynamicBufferResourceRoot()
ResourceRootType type() const override
const uchar * mappingBuffer() const
ResourceRootType type() const override
bool registerSelf(const QString &f)
QDynamicFileResourceRoot(const QString &_root)
~QDynamicFileResourceRoot()
QString mappingFile() const
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
static QByteArray encodeName(const QString &fileName)
Converts fileName to an 8-bit encoding that you can use in native APIs.
qint64 size() const override
\reimp
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read.
qsizetype size() const noexcept
bool isEmpty() const noexcept
void removeAt(qsizetype i)
const_reference at(qsizetype i) const noexcept
void append(parameter_type t)
QResourceFileEnginePrivate()
bool caseSensitive() const override
Should return true if the underlying file system is case-sensitive; otherwise return false.
bool flush() override
Flushes the open file, returning true if successful; otherwise returns false.
Iterator * beginEntryList(QDir::Filters filters, const QStringList &filterNames) override
qint64 read(char *data, qint64 maxlen) override
Reads a number of characters from the file into data.
bool close() override
Closes the file, returning true if successful; otherwise returns false.
bool open(QIODevice::OpenMode flags, std::optional< QFile::Permissions > permissions) override
Opens the file in the specified mode.
void setFileName(const QString &file) override
Sets the file engine's file name to file.
bool seek(qint64) override
Sets the file position to the given offset.
qint64 pos() const override
Returns the current file position.
QString fileName(QAbstractFileEngine::FileName file) const override
Return the file engine's current file name in the format specified by file.
QResourceFileEngine(const QString &path)
qint64 size() const override
Returns the size of the file.
FileFlags fileFlags(FileFlags type) const override
This function should return the set of OR'd flags that are true for the file engine's file,...
QDateTime fileTime(FileTime time) const override
If time is BirthTime, return when the file was born (created).
bool extension(Extension extension, const ExtensionOption *option=nullptr, ExtensionReturn *output=nullptr) override
Iterator * endEntryList() override
virtual bool atEnd() const
uint ownerId(FileOwner) const override
If owner is OwnerUser return the ID of the user who owns the file.
bool supportsExtension(Extension extension) const override
void ensureChildren() const
qint64 uncompressedSize() const Q_DECL_PURE_FUNCTION
QList< QResourceRoot * > related
void ensureInitialized() const
QResourcePrivate(QResource *_q)
qsizetype decompress(char *buffer, qsizetype bufferSize) const
bool load(const QString &file)
QResource::Compression compressionAlgo(int node)
bool operator==(const QResourceRoot &other) const
void setSource(int v, const uchar *t, const uchar *n, const uchar *d)
bool operator!=(const QResourceRoot &other) const
virtual QString mappingRoot() const
bool isContainer(int node) const
int findNode(const QString &path, const QLocale &locale=QLocale()) const
virtual ResourceRootType type() const
quint64 lastModified(int node) const
QStringList children(int node) const
const uchar * data(int node, qint64 *size) const
bool mappingRootSubdir(const QString &path, QString *match=nullptr) const
QResourceRoot(int version, const uchar *t, const uchar *n, const uchar *d)
qint64 uncompressedSize() const
void setFileName(const QString &file)
Sets a QResource to point to file.
QResource(const QString &file=QString(), const QLocale &locale=QLocale())
Constructs a QResource pointing to file.
QStringList children() const
Returns a list of all resources in this directory, if the resource represents a file the list will be...
qint64 size() const
Returns the size of the stored data backing the resource.
const uchar * data() const
Returns direct access to a segment of read-only data, that this resource represents.
static bool registerResource(const QString &rccFilename, const QString &resourceRoot=QString())
Registers the resource with the given rccFileName at the location in the resource tree specified by m...
QLocale locale() const
Returns the locale used to locate the data for the QResource.
QDateTime lastModified() const
void setLocale(const QLocale &locale)
Sets a QResource to only load the localization of resource to for locale.
QString absoluteFilePath() const
Returns the real path that this QResource represents, if the resource was found via the QDir::searchP...
QString fileName() const
Returns the full path to the file that this QResource represents as it was passed.
bool isValid() const
Returns true if the resource really exists in the resource hierarchy, false otherwise.
~QResource()
Releases the resources of the QResource object.
static bool unregisterResource(const QString &rccFilename, const QString &resourceRoot=QString())
Unregisters the resource with the given rccFileName at the location in the resource tree specified by...
QByteArray uncompressedData() const
bool isDir() const
Returns true if the resource represents a directory and thus may have children() in it,...
Compression compressionAlgorithm() const
QStringSplitter(QStringView sv)
QString toString() const
Returns a deep copy of this string view's data as a QString.
\macro QT_RESTRICTED_CAST_FROM_ASCII
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
void clear()
Clears the contents of the string and makes it null.
qsizetype size() const
Returns the number of characters in this string.
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
QString left(qsizetype n) const
Returns a substring that contains the n leftmost characters of the string.
QString & prepend(QChar c)
static Q_CORE_EXPORT QString stdString(int errorCode=-1)
QHash< int, QWidget * > hash
[35multi]
QMap< QString, QString > map
[6]
Combined button and popup list for selecting options.
constexpr Initialization Uninitialized
static QByteArray cleaned(const QByteArray &input)
#define Q_DECL_PURE_FUNCTION
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
uint qt_hash(QStringView key, uint chained) noexcept
static ControlElement< T > * ptr(QWidget *widget)
std::enable_if_t< std::is_unsigned_v< T >, bool > qAddOverflow(T v1, T v2, T *r)
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLfloat GLfloat GLfloat GLfloat h
GLuint GLuint64EXT address
GLdouble GLdouble GLdouble GLdouble q
GLsizei const GLchar *const * path
static ResourceList * resourceList()
#define RCC_FEATURE_SYMBOL(feature)
static QRecursiveMutex & resourceMutex()
Q_CORE_EXPORT bool qUnregisterResourceData(int version, const unsigned char *tree, const unsigned char *name, const unsigned char *data)
static QString qt_resource_fixResourceRoot(QString r)
QList< QResourceRoot * > ResourceList
static QString cleanPath(const QString &_path)
Q_CORE_EXPORT bool qRegisterResourceData(int version, const unsigned char *tree, const unsigned char *name, const unsigned char *data)
#define qUtf16Printable(string)
static QString absoluteFilePath(const Options *options, const QString &relativeFileName)
#define QT_CONFIG(feature)
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS)
unsigned long long quint64
QT_BEGIN_NAMESPACE typedef uchar * output
const QStringList filters({"Image files (*.png *.xpm *.jpg)", "Text files (*.txt)", "Any files (*)" })
[6]
ResourceList resourceList
QRecursiveMutex resourceMutex