MMFile
This commit is contained in:
@ -212,4 +212,146 @@ namespace IACore
|
||||
private:
|
||||
std::fstream m_fs;
|
||||
};
|
||||
|
||||
class MMFile
|
||||
{
|
||||
public:
|
||||
MMFile() = default;
|
||||
|
||||
// RAII - Automatically unmap on destruction
|
||||
~MMFile()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
// Disable copy (managing ownership of raw handles is messy)
|
||||
MMFile(const MMFile &) = delete;
|
||||
MMFile &operator=(const MMFile &) = delete;
|
||||
|
||||
// Open and Map
|
||||
bool Map(const std::string &filepath)
|
||||
{
|
||||
Close(); // Cleanup any existing map
|
||||
|
||||
#if IA_PLATFORM_WINDOWS > 0
|
||||
// 1. Open File
|
||||
hFile_ = ::CreateFileA(filepath.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (hFile_ == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
// 2. Get File Size
|
||||
LARGE_INTEGER size;
|
||||
if (!::GetFileSizeEx(hFile_, &size))
|
||||
{
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
size_ = static_cast<size_t>(size.QuadPart);
|
||||
|
||||
// 3. Create Mapping Object
|
||||
hMapping_ = ::CreateFileMappingA(hFile_, nullptr, PAGE_READONLY, 0, 0, nullptr);
|
||||
if (!hMapping_)
|
||||
{
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4. Map View
|
||||
data_ = ::MapViewOfFile(hMapping_, FILE_MAP_READ, 0, 0, 0);
|
||||
if (!data_)
|
||||
{
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
#else // LINUX / POSIX
|
||||
// 1. Open File
|
||||
fd_ = ::open(filepath.c_str(), O_RDONLY);
|
||||
if (fd_ == -1)
|
||||
return false;
|
||||
|
||||
// 2. Get File Size
|
||||
struct stat sb;
|
||||
if (fstat(fd_, &sb) == -1)
|
||||
{
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
size_ = static_cast<size_t>(sb.st_size);
|
||||
|
||||
// 3. mmap
|
||||
// PROT_READ: Read only
|
||||
// MAP_PRIVATE: Copy-on-write (safe if you accidentally modify, though we return const)
|
||||
data_ = ::mmap(nullptr, size_, PROT_READ, MAP_PRIVATE, fd_, 0);
|
||||
if (data_ == MAP_FAILED)
|
||||
{
|
||||
data_ = nullptr;
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (data_)
|
||||
{
|
||||
::UnmapViewOfFile(data_);
|
||||
data_ = nullptr;
|
||||
}
|
||||
if (hMapping_)
|
||||
{
|
||||
::CloseHandle(hMapping_);
|
||||
hMapping_ = nullptr;
|
||||
}
|
||||
if (hFile_ != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
::CloseHandle(hFile_);
|
||||
hFile_ = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
#else
|
||||
if (data_)
|
||||
{
|
||||
::munmap(data_, size_);
|
||||
data_ = nullptr;
|
||||
}
|
||||
if (fd_ != -1)
|
||||
{
|
||||
::close(fd_);
|
||||
fd_ = -1;
|
||||
}
|
||||
#endif
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
// Accessors
|
||||
const void *GetData() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
size_t GetSize() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return data_ != nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
void *data_ = nullptr;
|
||||
size_t size_ = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
HANDLE hFile_ = INVALID_HANDLE_VALUE;
|
||||
HANDLE hMapping_ = nullptr;
|
||||
#else
|
||||
int fd_ = -1;
|
||||
#endif
|
||||
};
|
||||
} // namespace IACore
|
||||
@ -495,6 +495,9 @@ STATIC CONST FLOAT64 FLOAT64_EPSILON = DBL_EPSILON;
|
||||
#elif IA_PLATFORM_UNIX
|
||||
# include <unistd.h>
|
||||
# include <sys/wait.h>
|
||||
# include <sys/mman.h>
|
||||
# include <sys/stat.h>
|
||||
# include <fcntl.h>
|
||||
# include <spawn.h>
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user