-
Notifications
You must be signed in to change notification settings - Fork 102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use memory mapped files access #1781
base: master
Are you sure you want to change the base?
Changes from all commits
e687a27
0b737db
59266c4
044c9f8
8766d1f
5a59485
9a22f3e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ add_library(archives STATIC | |
) | ||
|
||
target_link_libraries(archives | ||
mio::mio | ||
7zip | ||
${SPRING_MINIZIP_LIBRARY} | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ | |
#include <string> | ||
#include <vector> | ||
#include <fstream> | ||
#include <filesystem> | ||
#include <algorithm> | ||
#include <cassert> | ||
#include <cctype> | ||
|
@@ -48,6 +49,13 @@ CFileHandler::CFileHandler(const string& fileName, const string& modes) | |
|
||
/******************************************************************************/ | ||
|
||
std::span<const uint8_t> CFileHandler::GetSpan() const | ||
{ | ||
return mmap ? | ||
std::span(mmap->data(), mmap->size()) : | ||
std::span(fileBuffer.data(), fileBuffer.size()); | ||
} | ||
|
||
bool CFileHandler::TryReadFromPWD(const string& fileName) | ||
{ | ||
#ifndef TOOLS | ||
|
@@ -57,31 +65,75 @@ bool CFileHandler::TryReadFromPWD(const string& fileName) | |
#else | ||
const std::string fullpath(fileName); | ||
#endif | ||
ifs.open(fullpath.c_str(), std::ios::in | std::ios::binary); | ||
if (ifs && !ifs.bad() && ifs.is_open()) { | ||
ifs.seekg(0, std::ios_base::end); | ||
fileSize = ifs.tellg(); | ||
ifs.seekg(0, std::ios_base::beg); | ||
return true; | ||
std::error_code ec; | ||
std::filesystem::directory_entry entry(fileName, ec); | ||
if (ec) | ||
return false; | ||
|
||
if (!entry.exists()) | ||
return false; | ||
|
||
if (!entry.is_regular_file()) | ||
return false; | ||
|
||
fileSize = entry.file_size(); | ||
|
||
mmap = std::make_unique<mio::ummap_source>(fileName); | ||
if (!mmap->is_open()) { | ||
mmap = nullptr; | ||
return false; | ||
} | ||
ifs.close(); | ||
return false; | ||
|
||
if (!mmap->is_mapped()) { | ||
mmap = nullptr; | ||
return false; | ||
} | ||
|
||
if (mmap->size() != fileSize) { | ||
mmap = nullptr; | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
|
||
bool CFileHandler::TryReadFromRawFS(const string& fileName) | ||
{ | ||
#ifndef TOOLS | ||
const string rawpath = dataDirsAccess.LocateFile(fileName); | ||
ifs.open(rawpath.c_str(), std::ios::in | std::ios::binary); | ||
if (ifs && !ifs.bad() && ifs.is_open()) { | ||
ifs.seekg(0, std::ios_base::end); | ||
fileSize = ifs.tellg(); | ||
ifs.seekg(0, std::ios_base::beg); | ||
return true; | ||
|
||
std::error_code ec; | ||
std::filesystem::directory_entry entry(rawpath, ec); | ||
if (ec) | ||
return false; | ||
|
||
if (!entry.exists()) | ||
return false; | ||
|
||
if (!entry.is_regular_file()) | ||
return false; | ||
|
||
fileSize = entry.file_size(); | ||
|
||
mmap = std::make_unique<mio::ummap_source>(rawpath); | ||
if (!mmap->is_open()) { | ||
mmap = nullptr; | ||
return false; | ||
} | ||
|
||
if (!mmap->is_mapped()) { | ||
mmap = nullptr; | ||
return false; | ||
} | ||
|
||
if (mmap->size() != fileSize) { | ||
mmap = nullptr; | ||
return false; | ||
} | ||
|
||
return true; | ||
#endif | ||
ifs.close(); | ||
return false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The non-TOOLS path will have two unconditional |
||
} | ||
|
||
|
@@ -128,7 +180,7 @@ void CFileHandler::Close() | |
fileSize = -1; | ||
loadCode = -3; | ||
|
||
ifs.close(); | ||
mmap = nullptr; | ||
fileBuffer.clear(); | ||
} | ||
|
||
|
@@ -168,20 +220,20 @@ bool CFileHandler::FileExists(const std::string& filePath, const std::string& mo | |
|
||
int CFileHandler::Read(void* buf, int length) | ||
{ | ||
if (ifs.is_open()) { | ||
ifs.read(static_cast<char*>(buf), length); | ||
return ifs.gcount(); | ||
} | ||
if (fileSize <= 0) | ||
return 0; | ||
|
||
if (fileBuffer.empty()) | ||
if (fileBuffer.empty() && !mmap) | ||
return 0; | ||
|
||
const auto span = GetSpan(); | ||
|
||
if ((length + filePos) > fileSize) | ||
length = fileSize - filePos; | ||
|
||
if (length > 0) { | ||
assert(fileBuffer.size() >= (filePos + length)); | ||
memcpy(buf, &fileBuffer[filePos], length); | ||
assert(span.size() >= (filePos + length)); | ||
std::memcpy(buf, span.data() + filePos, length); | ||
filePos += length; | ||
} | ||
|
||
|
@@ -210,17 +262,6 @@ int CFileHandler::ReadString(void* buf, int length) | |
|
||
void CFileHandler::Seek(int length, std::ios_base::seekdir where) | ||
{ | ||
if (ifs.is_open()) { | ||
// Status bits must be cleared before seeking, otherwise it might fail | ||
// in the common case of EOF | ||
// http://en.cppreference.com/w/cpp/io/basic_istream/seekg | ||
ifs.clear(); | ||
ifs.seekg(length, where); | ||
return; | ||
} | ||
if (fileBuffer.empty()) | ||
return; | ||
|
||
switch (where) { | ||
case std::ios_base::beg: { filePos = length; } break; | ||
case std::ios_base::cur: { filePos += length; } break; | ||
|
@@ -231,21 +272,12 @@ void CFileHandler::Seek(int length, std::ios_base::seekdir where) | |
|
||
bool CFileHandler::Eof() const | ||
{ | ||
if (ifs.is_open()) | ||
return ifs.eof(); | ||
|
||
if (!fileBuffer.empty()) | ||
return (filePos >= fileSize); | ||
|
||
return true; | ||
return (filePos >= fileSize); | ||
} | ||
|
||
|
||
int CFileHandler::GetPos() | ||
{ | ||
if (ifs.is_open()) | ||
return ifs.tellg(); | ||
|
||
return filePos; | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,10 @@ | |
#include <vector> | ||
#include <string> | ||
#include <fstream> | ||
#include <memory> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this be added to some .cpp file(s) instead? Looks like no new code was added below so probably doesn't need to be in the header (gets applies everywhere the .h is included even if not all .cpp files need it) |
||
#include <span> | ||
#include <cinttypes> | ||
#include <mio/mmap.hpp> | ||
|
||
#include "VFSModes.h" | ||
|
||
|
@@ -52,18 +55,15 @@ class CFileHandler | |
|
||
std::vector<std::uint8_t>& GetBuffer() { return fileBuffer; } | ||
|
||
static bool InReadDir(const std::string& path); | ||
static bool InWriteDir(const std::string& path); | ||
|
||
static std::vector<std::string> FindFiles(const std::string& path, const std::string& pattern); | ||
static std::vector<std::string> DirList(const std::string& path, const std::string& pattern, const std::string& modes, bool recursive); | ||
static std::vector<std::string> SubDirs(const std::string& path, const std::string& pattern, const std::string& modes, bool recursive); | ||
|
||
static std::string AllowModes(const std::string& modes, const std::string& allowed); | ||
static std::string ForbidModes(const std::string& modes, const std::string& forbidden); | ||
|
||
|
||
protected: | ||
std::span<const uint8_t> GetSpan() const; | ||
|
||
virtual bool TryReadFromPWD(const std::string& fileName); | ||
virtual bool TryReadFromRawFS(const std::string& fileName); | ||
|
@@ -76,8 +76,9 @@ class CFileHandler | |
static bool InsertVFSDirs(std::vector<std::string>& dirSet, const std::string& path, const std::string& pattern, bool recursive, int section); | ||
|
||
std::string fileName; | ||
std::ifstream ifs; | ||
std::vector<std::uint8_t> fileBuffer; | ||
std::vector<uint8_t> fileBuffer; | ||
|
||
std::unique_ptr<mio::ummap_source> mmap; | ||
|
||
int filePos = 0; | ||
int fileSize = -1; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps this could be
static
to the function instead of class member?