diff options
-rw-r--r-- | includes/Buffer.h | 22 | ||||
-rw-r--r-- | includes/MMap.h | 22 | ||||
-rw-r--r-- | src/Buffer.cc | 21 | ||||
-rw-r--r-- | src/MMap.cc | 100 | ||||
-rw-r--r-- | win32/project/Balau.vcxproj | 2 | ||||
-rw-r--r-- | win32/project/Balau.vcxproj.filters | 6 |
6 files changed, 160 insertions, 13 deletions
diff --git a/includes/Buffer.h b/includes/Buffer.h index c0d269a..6b5318f 100644 --- a/includes/Buffer.h +++ b/includes/Buffer.h @@ -8,19 +8,21 @@ class Buffer : public SeekableHandle { public: Buffer(const uint8_t * buffer, size_t s) : m_buffer(const_cast<uint8_t *>(buffer)), m_bufSize(s), m_fromConst(true) { } Buffer() throw (GeneralException) { } - virtual ~Buffer(); - virtual void close() throw (GeneralException); - virtual ssize_t read(void * buf, size_t count) throw (GeneralException); - virtual ssize_t write(const void * buf, size_t count) throw (GeneralException); - virtual bool isClosed(); - virtual bool isEOF(); - virtual bool canRead(); - virtual bool canWrite(); - virtual const char * getName(); - virtual off64_t getSize(); + virtual ~Buffer() override; + virtual void close() throw (GeneralException) override; + virtual ssize_t read(void * buf, size_t count) throw (GeneralException) override; + virtual ssize_t write(const void * buf, size_t count) throw (GeneralException) override; + virtual bool isClosed() override; + virtual bool isEOF() override; + virtual bool canRead() override; + virtual bool canWrite() override; + virtual const char * getName() override; + virtual off64_t getSize() override; const uint8_t * getBuffer() { return m_buffer + rtell(); } void reset(); + void clear(); void rewind() { rseek(0); wseek(0); } + void borrow(const uint8_t * buffer, size_t s); private: uint8_t * m_buffer = NULL; bool m_fromConst = false; diff --git a/includes/MMap.h b/includes/MMap.h new file mode 100644 index 0000000..ad55e4c --- /dev/null +++ b/includes/MMap.h @@ -0,0 +1,22 @@ +#pragma once + +#include <Buffer.h> + +namespace Balau { + +class MMapPlatform; + +class MMap : public Buffer { + public: + MMap(const char * fname); + virtual ~MMap() override; + void open() throw (GeneralException); + virtual const char * getName() override { return m_name.to_charp(); } + virtual void close() override; + private: + MMapPlatform * m_platform = NULL; + String m_name; + String m_fname; +}; + +}; diff --git a/src/Buffer.cc b/src/Buffer.cc index 42dbd52..b4dfbec 100644 --- a/src/Buffer.cc +++ b/src/Buffer.cc @@ -60,14 +60,29 @@ ssize_t Balau::Buffer::write(const void * buf, size_t count) throw (GeneralExcep } void Balau::Buffer::reset() { - if (!m_fromConst) - m_buffer = (uint8_t *) realloc(m_buffer, 0); - m_bufSize = 0; + if (!m_fromConst) { + m_buffer = (uint8_t *)realloc(m_buffer, 0); + m_bufSize = 0; + } m_numBlocks = 0; wseek(0); rseek(0); } +void Balau::Buffer::clear() { + reset(); + m_fromConst = false; + m_buffer = NULL; + m_bufSize = 0; +} + +void Balau::Buffer::borrow(const uint8_t * buffer, size_t s) { + clear(); + m_fromConst = true; + m_buffer = const_cast<uint8_t *>(buffer); + m_bufSize = s; +} + bool Balau::Buffer::isClosed() { return false; } bool Balau::Buffer::isEOF() { return rtell() == m_bufSize; } const char * Balau::Buffer::getName() { return "Buffer"; } diff --git a/src/MMap.cc b/src/MMap.cc new file mode 100644 index 0000000..18187b4 --- /dev/null +++ b/src/MMap.cc @@ -0,0 +1,100 @@ +#include <MMap.h> + +#ifdef _WIN32 +#include <windows.h> +#endif + +namespace Balau { + +#ifdef _WIN32 + +class MMapPlatform { + public: + std::tuple<bool, const uint8_t *, size_t> open(String fname) { + bool result = false; + size_t s = 0; + TCHAR * fnameTchar; +#ifdef UNICODE + fname.do_iconv("UTF-8", "UNICODELITTLE"); + fnameTchar = (TCHAR *) alloca(fname.strlen() + 2); + memset(fnameTchar, 0, fname.strlen() + 2); + memcpy(fnameTchar, fname.to_charp(), fname.strlen()); +#else + fnameTchar = fname.to_charp(); +#endif + + m_handle = CreateFile(fnameTchar, GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + + if (m_handle == INVALID_HANDLE_VALUE) + return std::tie(result, m_ptr, s); + + ScopedLambda hc([&]() { if (!result) CloseHandle(m_handle); }); + + LARGE_INTEGER fsize; + if (!GetFileSizeEx(m_handle, (PLARGE_INTEGER) &fsize)) + return std::tie(result, m_ptr, s); + + s = fsize.QuadPart; + + m_mapObject = CreateFileMapping(m_handle, 0, PAGE_READONLY, fsize.HighPart, fsize.LowPart, NULL); + + if (m_mapObject == NULL) // right, because getting NULL (which is 0) is better + return std::tie(result, m_ptr, s); // than getting the usual INVALID_HANDLE_VALUE (which is -1), + // in order to make a sane and uniform API... + { + ScopedLambda mc([&]() { if (!result) CloseHandle(m_mapObject); }); + + // and of course, CreateFileMapping takes the 64 bits size in high / low format, + // whereas MapViewOfFile takes the 64 bits size in a single 64 bits size_t. Sure. Makes sense. + m_ptr = (const uint8_t *)MapViewOfFile(m_mapObject, FILE_MAP_READ, 0, 0, s); + + result = !!m_ptr; + } + + return std::tie(result, m_ptr, s); + } + void close() { + if (m_ptr) + UnmapViewOfFile(m_ptr); + if (m_mapObject) + CloseHandle(m_mapObject); + if (m_handle != INVALID_HANDLE_VALUE) + CloseHandle(m_handle); + m_ptr = NULL; + m_mapObject = (HANDLE) NULL; + m_handle = INVALID_HANDLE_VALUE; + } + HANDLE m_handle = INVALID_HANDLE_VALUE; + HANDLE m_mapObject = (HANDLE) NULL; // see comment above + const uint8_t * m_ptr = NULL; +}; + +#endif + +}; + +Balau::MMap::MMap(const char * fname) { + m_fname = fname; + m_name.set("mmap of %s", m_fname); + m_platform = new MMapPlatform(); +} + +void Balau::MMap::open() { + bool result; + const uint8_t * ptr; + size_t s; + std::tie(result, ptr, s) = m_platform->open(m_fname); + if (!result) + throw GeneralException("Unable to map file"); + + borrow(ptr, s); +} + +void Balau::MMap::close() { + m_platform->close(); + Buffer::close(); +} + +Balau::MMap::~MMap() { + delete m_platform; +} diff --git a/win32/project/Balau.vcxproj b/win32/project/Balau.vcxproj index 9ca610e..d23c043 100644 --- a/win32/project/Balau.vcxproj +++ b/win32/project/Balau.vcxproj @@ -239,6 +239,7 @@ <ClCompile Include="..\..\src\LuaHandle.cc" />
<ClCompile Include="..\..\src\LuaTask.cc" />
<ClCompile Include="..\..\src\Main.cc" />
+ <ClCompile Include="..\..\src\MMap.cc" />
<ClCompile Include="..\..\src\Output.cc" />
<ClCompile Include="..\..\src\Printer.cc" />
<ClCompile Include="..\..\src\Selectable.cc" />
@@ -282,6 +283,7 @@ <ClInclude Include="..\..\includes\LuaHandle.h" />
<ClInclude Include="..\..\includes\LuaTask.h" />
<ClInclude Include="..\..\includes\Main.h" />
+ <ClInclude Include="..\..\includes\MMap.h" />
<ClInclude Include="..\..\includes\Output.h" />
<ClInclude Include="..\..\includes\Printer.h" />
<ClInclude Include="..\..\includes\Selectable.h" />
diff --git a/win32/project/Balau.vcxproj.filters b/win32/project/Balau.vcxproj.filters index 5811d03..bd79687 100644 --- a/win32/project/Balau.vcxproj.filters +++ b/win32/project/Balau.vcxproj.filters @@ -168,6 +168,9 @@ <ClCompile Include="..\..\lcrypt\lcrypt_math.c">
<Filter>Third Party\lcrypt</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\MMap.cc">
+ <Filter>Source</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\includes\Async.h">
@@ -326,6 +329,9 @@ <ClInclude Include="..\..\src\jsoncpp\src\json_batchallocator.h">
<Filter>Third Party\jsoncpp</Filter>
</ClInclude>
+ <ClInclude Include="..\..\includes\MMap.h">
+ <Filter>Headers</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\src\jsoncpp\src\json_internalarray.inl">
|