diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2024-04-23 16:04:06 -0700 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2024-05-02 17:12:32 -0700 |
commit | 315d6b6c2e7f2a843c57c6835f1dc37e549ff647 (patch) | |
tree | 4107bc3326674b56cb221ac48a55ca3682738640 | |
parent | fe6dda9bb9310878b408b2421f60acb7135bd8ba (diff) |
QResource: re-factor the memory-mapping code into two helper functions
So I can more easily extend to Windows support and to reuse them later.
Change-Id: I6979d02a7395405cbf23fffd17c90b32dbbddd94
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
-rw-r--r-- | src/corelib/io/qresource.cpp | 88 |
1 files changed, 47 insertions, 41 deletions
diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index 8f2abff0ab..e40e7aeb0e 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -1109,6 +1109,11 @@ public: class QDynamicFileResourceRoot : public QDynamicBufferResourceRoot { +public: + static uchar *map_sys(QFile &file, qint64 base, qsizetype size); + static void unmap_sys(void *base, qsizetype size); + +private: QString fileName; // for mmap'ed files, this is what needs to be unmapped. uchar *unmapPointer; @@ -1119,16 +1124,10 @@ public: : QDynamicBufferResourceRoot(_root), unmapPointer(nullptr), unmapLength(0) { } ~QDynamicFileResourceRoot() { -#if defined(QT_USE_MMAP) - if (unmapPointer) { - munmap(reinterpret_cast<char *>(unmapPointer), unmapLength); - unmapPointer = nullptr; - unmapLength = 0; - } else -#endif - { + if (unmapPointer) + unmap_sys(unmapPointer, unmapLength); + else delete[] mappingBuffer(); - } } QString mappingFile() const { return fileName; } ResourceRootType type() const override { return Resource_File; } @@ -1144,49 +1143,56 @@ public: # define MAP_FAILED reinterpret_cast<void *>(-1) #endif -bool QDynamicFileResourceRoot::registerSelf(const QString &f) +void QDynamicFileResourceRoot::unmap_sys(void *base, qsizetype size) { - bool fromMM = false; - uchar *data = nullptr; - qsizetype data_len = 0; +#if defined(QT_USE_MMAP) + munmap(base, size); +#endif +} +// Note: caller must ensure \a offset and \a size are acceptable to the OS. +uchar *QDynamicFileResourceRoot::map_sys(QFile &file, qint64 offset, qsizetype size) +{ + Q_ASSERT(file.isOpen()); + void *ptr = nullptr; + if (size < 0) + size = qMin(file.size() - offset, (std::numeric_limits<qsizetype>::max)()); + + // We don't use QFile::map() here because we want to dispose of the QFile object #if defined(QT_USE_MMAP) - int fd = QT_OPEN(QFile::encodeName(f), O_RDONLY); - if (fd >= 0) { - QT_STATBUF st; - if (!QT_FSTAT(fd, &st) && st.st_size <= std::numeric_limits<qsizetype>::max()) { - int protection = PROT_READ; // read-only memory - int flags = MAP_FILE | MAP_PRIVATE; // swap-backed map from file - void *ptr = QT_MMAP(nullptr, st.st_size, // any address, whole file - protection, flags, - fd, 0); // from offset 0 of fd - if (ptr != MAP_FAILED) { - data = static_cast<uchar *>(ptr); - data_len = st.st_size; - fromMM = true; - } - } - QT_CLOSE(fd); - } + int fd = file.handle(); + int protection = PROT_READ; // read-only memory + int flags = MAP_FILE | MAP_PRIVATE; // swap-backed map from file + ptr = QT_MMAP(nullptr, size, protection, flags, fd, offset); + if (ptr == MAP_FAILED) + ptr = nullptr; #endif // QT_USE_MMAP - if (!data) { - QFile file(f); + return static_cast<uchar *>(ptr); +} + +bool QDynamicFileResourceRoot::registerSelf(const QString &f) +{ + QFile file(f); + if (!file.open(QIODevice::ReadOnly)) + return false; + + qint64 data_len = file.size(); + if (data_len > std::numeric_limits<qsizetype>::max()) + return false; + + uchar *data = map_sys(file, 0, data_len); + bool fromMM = !!data; + + if (!fromMM) { bool ok = false; - if (file.open(QIODevice::ReadOnly)) { - qint64 fsize = file.size(); - if (fsize <= std::numeric_limits<qsizetype>::max()) { - data_len = file.size(); - data = new uchar[data_len]; - ok = (data_len == file.read(reinterpret_cast<char *>(data), data_len)); - } - } + data = new uchar[data_len]; + ok = (data_len == file.read(reinterpret_cast<char *>(data), data_len)); if (!ok) { delete[] data; data = nullptr; data_len = 0; return false; } - fromMM = false; } if (data && QDynamicBufferResourceRoot::registerSelf(data, data_len)) { if (fromMM) { |