From ac0504c1b78abce265cb9e6095925e5621dd6ad3 Mon Sep 17 00:00:00 2001 From: Mirek Fidler Date: Wed, 10 Apr 2024 10:29:08 +0200 Subject: [PATCH] Core: FileMapping refactored --- autotest/FileMapping/FileMapping.cpp | 33 ++++++++++++ autotest/FileMapping/FileMapping.upp | 9 ++++ uppsrc/Core/Core.h | 1 + uppsrc/Core/Core.upp | 3 +- uppsrc/Core/FileMapping.cpp | 57 +++++++-------------- uppsrc/Core/FileMapping.h | 75 ++++++++++++++++++++++++++++ uppsrc/Core/Stream.h | 70 ++------------------------ 7 files changed, 140 insertions(+), 108 deletions(-) create mode 100644 autotest/FileMapping/FileMapping.cpp create mode 100644 autotest/FileMapping/FileMapping.upp create mode 100644 uppsrc/Core/FileMapping.h diff --git a/autotest/FileMapping/FileMapping.cpp b/autotest/FileMapping/FileMapping.cpp new file mode 100644 index 000000000..5ac0e71e1 --- /dev/null +++ b/autotest/FileMapping/FileMapping.cpp @@ -0,0 +1,33 @@ +#include + +using namespace Upp; + +CONSOLE_APP_MAIN +{ + StdLogSetup(LOG_COUT|LOG_FILE); + + String test; + for(int i = 0; i < 100; i++) + test << i << " " << i * 12345678 << "\n"; + + int sz = test.GetCount(); + + String path = GetHomeDirFile("mapped"); + + { + FileMapping m; + m.Create(path, sz); + memcpy(m.Map(), ~test, sz); + } + + ASSERT(LoadFile(path) == test); + + { + FileMapping m(path); + ASSERT(memcmp(m.Map(), ~test, sz) == 0); + } + + DeleteFile(path); + + LOG("============ OK"); +} diff --git a/autotest/FileMapping/FileMapping.upp b/autotest/FileMapping/FileMapping.upp new file mode 100644 index 000000000..d680a78c2 --- /dev/null +++ b/autotest/FileMapping/FileMapping.upp @@ -0,0 +1,9 @@ +uses + Core; + +file + FileMapping.cpp; + +mainconfig + "" = ""; + diff --git a/uppsrc/Core/Core.h b/uppsrc/Core/Core.h index 5cc6bace1..f23aa74b9 100644 --- a/uppsrc/Core/Core.h +++ b/uppsrc/Core/Core.h @@ -318,6 +318,7 @@ class JsonIO; #include "TimeDate.h" #include "Stream.h" +#include "FileMapping.h" #include "Diag.h" #include "Vcont.h" diff --git a/uppsrc/Core/Core.upp b/uppsrc/Core/Core.upp index 0cc8202fb..20c929a00 100644 --- a/uppsrc/Core/Core.upp +++ b/uppsrc/Core/Core.upp @@ -74,9 +74,10 @@ file Stream.h, Stream.cpp, BlockStream.cpp, - FileMapping.cpp, FilterStream.h, FilterStream.cpp, + FileMapping.h, + FileMapping.cpp, Profile.h, Diag.h, Log.cpp, diff --git a/uppsrc/Core/FileMapping.cpp b/uppsrc/Core/FileMapping.cpp index 4313171ae..fe2e1dfa2 100644 --- a/uppsrc/Core/FileMapping.cpp +++ b/uppsrc/Core/FileMapping.cpp @@ -42,60 +42,37 @@ FileMapping::FileMapping(const char *file_) Open(file_); } -bool FileMapping::Open(const char *file) +#ifdef PLATFORM_WIN32 +bool FileMapping::Open(const char *filename, dword mode, int64 wsize) +#else +bool FileMapping::Open(const char *filename, dword mode, mode_t acm) +#endif { Close(); - write = false; + write = (mode & FileStream::MODEMASK) != FileStream::READ; #ifdef PLATFORM_WIN32 - hfile = CreateFileW(ToSystemCharsetW(file), GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - if(hfile == INVALID_HANDLE_VALUE) + if(!FileStream::OpenHandle(filename, mode, hfile, filesize)) return false; - filesize = ::GetFileSize(hfile, NULL); - hmap = CreateFileMapping(hfile, NULL, PAGE_READONLY, 0, 0, NULL); + if(write) + filesize = wsize; + else + wsize = 0; + hmap = CreateFileMapping(hfile, NULL, write ? PAGE_READWRITE : PAGE_READONLY, HIDWORD(wsize), LODWORD(wsize), NULL); if(!hmap) { Close(); return false; } -#endif -#ifdef PLATFORM_POSIX - hfile = open(ToSystemCharset(file), O_RDONLY); - if(hfile == -1) +#else + if(!FileStream::OpenHandle(filename, mode, hfile, filesize, acm)) return false; - if(fstat(hfile, &hfstat) == -1) { - Close(); - return false; - } - filesize = hfstat.st_size; #endif return true; } -bool FileMapping::Create(const char *file, int64 filesize_, bool delete_share) + +bool FileMapping::Create(const char *file, int64 filesize, bool delete_share) { - Close(); - write = true; -#ifdef PLATFORM_WIN32 - hfile = CreateFileW(ToSystemCharsetW(file), GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE | (delete_share ? FILE_SHARE_DELETE : 0), - NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); - if(hfile == INVALID_HANDLE_VALUE) - return false; - long lo = (dword)filesize_, hi = (dword)(filesize_ >> 32); - hmap = CreateFileMapping(hfile, NULL, PAGE_READWRITE, hi, lo, NULL); - if(!hmap) { - Close(); - return false; - } -#endif -#ifdef PLATFORM_POSIX - hfile = open(ToSystemCharset(file), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - if(hfile == -1) - return false; -#endif - filesize = filesize_; - return true; + return Open(file, FileStream::CREATE | (delete_share ? FileStream::DELETESHARE : 0), filesize); } byte *FileMapping::Map(int64 mapoffset, size_t maplen) diff --git a/uppsrc/Core/FileMapping.h b/uppsrc/Core/FileMapping.h new file mode 100644 index 000000000..2bb7e950c --- /dev/null +++ b/uppsrc/Core/FileMapping.h @@ -0,0 +1,75 @@ +class FileMapping { +public: + FileMapping(const char *file = NULL); + ~FileMapping() { Close(); } + +#ifdef PLATFORM_WIN32 + bool Open(const char *filename, dword mode = FileStream::READ, int64 filesize = 0); +#endif + +#ifdef PLATFORM_POSIX + bool Open(const char *filename, dword mode = FileStream::READ, int64 filesize = 0, mode_t acm = 0644); +#endif + + bool Create(const char *file, int64 filesize) { return Create(file, filesize, false); } + + bool Expand(int64 filesize); + byte *Map(int64 mapoffset, size_t maplen); + byte *Map() { return Map(0, GetFileSize()); } + bool Unmap(); + bool Close(); + + bool IsOpen() const { return hfile != INVALID_HANDLE_VALUE; } + + int64 GetFileSize() const { return filesize; } + Time GetTime() const; + String GetData(int64 offset, int len); + + int64 GetOffset() const { return offset; } + size_t GetCount() const { return size; } + + int64 GetRawOffset() const { return rawoffset; } + size_t GetRawCount() const { return rawsize; } + + const byte *operator ~ () const { ASSERT(IsOpen()); return base; } + const byte *begin() const { ASSERT(IsOpen()); return base; } + const byte *end() const { ASSERT(IsOpen()); return base + size; } + const byte& operator [] (int i) const { ASSERT(IsOpen() && i >= 0 && (size_t)i < size); return base[i]; } + + byte *operator ~ () { ASSERT(IsOpen()); return base; } + byte *begin() { ASSERT(IsOpen()); return base; } + byte *end() { ASSERT(IsOpen()); return base + size; } + byte& operator [] (int i) { ASSERT(IsOpen() && i >= 0 && (size_t)i < size); return base[i]; } + +// deprecated: + bool Create(const char *file, int64 filesize, bool delete_share); + + const byte *Begin() const { ASSERT(IsOpen()); return base; } + const byte *End() const { ASSERT(IsOpen()); return base + size; } + const byte *GetIter(int i) const { ASSERT(IsOpen() && i >= 0 && (size_t)i <= size); return base + i; } + + byte *Begin() { ASSERT(IsOpen()); return base; } + byte *End() { ASSERT(IsOpen()); return base + size; } + byte *GetIter(int i) { ASSERT(IsOpen() && i >= 0 && (size_t)i <= size); return base + i; } + +private: +#ifdef PLATFORM_WIN32 + HANDLE hfile; + HANDLE hmap; +#endif +#ifdef PLATFORM_POSIX + enum { INVALID_HANDLE_VALUE = -1 }; + int hfile; + struct stat hfstat; +#endif + byte *base; + byte *rawbase; + int64 filesize; + int64 offset; + int64 rawoffset; + size_t size; + size_t rawsize; + bool write; + + static int MappingGranularity(); +}; diff --git a/uppsrc/Core/Stream.h b/uppsrc/Core/Stream.h index 1441908b5..ce422d98b 100644 --- a/uppsrc/Core/Stream.h +++ b/uppsrc/Core/Stream.h @@ -365,6 +365,7 @@ protected: public: enum { READ, CREATE, APPEND, READWRITE, + MODEMASK = 0x3, NOWRITESHARE = 0x10, SHAREMASK = 0x70, @@ -406,6 +407,8 @@ protected: void SetPos(int64 pos); void Init(int64 size); + + friend class FileMapping; public: operator bool() const { return IsOpen(); } @@ -547,73 +550,6 @@ public: ~TeeStream() { Close(); } }; -class FileMapping { -public: - FileMapping(const char *file = NULL); - ~FileMapping() { Close(); } - - bool Open(const char *file); - bool Create(const char *file, int64 filesize, bool delete_share = false); - - bool Expand(int64 filesize); - byte *Map(int64 mapoffset, size_t maplen); - byte *Map() { return Map(0, GetFileSize()); } - bool Unmap(); - bool Close(); - - bool IsOpen() const { return hfile != INVALID_HANDLE_VALUE; } - - int64 GetFileSize() const { return filesize; } - Time GetTime() const; - String GetData(int64 offset, int len); - - int64 GetOffset() const { return offset; } - size_t GetCount() const { return size; } - - int64 GetRawOffset() const { return rawoffset; } - size_t GetRawCount() const { return rawsize; } - - const byte *operator ~ () const { ASSERT(IsOpen()); return base; } - const byte *begin() const { ASSERT(IsOpen()); return base; } - const byte *end() const { ASSERT(IsOpen()); return base + size; } - const byte& operator [] (int i) const { ASSERT(IsOpen() && i >= 0 && (size_t)i < size); return base[i]; } - - byte *operator ~ () { ASSERT(IsOpen()); return base; } - byte *begin() { ASSERT(IsOpen()); return base; } - byte *end() { ASSERT(IsOpen()); return base + size; } - byte& operator [] (int i) { ASSERT(IsOpen() && i >= 0 && (size_t)i < size); return base[i]; } - - const byte *Begin() const { ASSERT(IsOpen()); return base; } - const byte *End() const { ASSERT(IsOpen()); return base + size; } - const byte *GetIter(int i) const { ASSERT(IsOpen() && i >= 0 && (size_t)i <= size); return base + i; } - - byte *Begin() { ASSERT(IsOpen()); return base; } - byte *End() { ASSERT(IsOpen()); return base + size; } - byte *GetIter(int i) { ASSERT(IsOpen() && i >= 0 && (size_t)i <= size); return base + i; } - -private: -#ifdef PLATFORM_WIN32 - HANDLE hfile; - HANDLE hmap; -#endif -#ifdef PLATFORM_POSIX - enum { INVALID_HANDLE_VALUE = -1 }; - int hfile; - struct stat hfstat; -#endif - byte *base; - byte *rawbase; - int64 filesize; - int64 offset; - int64 rawoffset; - size_t size; - size_t rawsize; - bool write; - - static int MappingGranularity(); -}; - - String LoadStream(Stream& in); bool SaveStream(Stream& out, const String& data);