summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--includes/Buffer.h22
-rw-r--r--includes/MMap.h22
-rw-r--r--src/Buffer.cc21
-rw-r--r--src/MMap.cc100
-rw-r--r--win32/project/Balau.vcxproj2
-rw-r--r--win32/project/Balau.vcxproj.filters6
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">