summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNicolas "Pixel" Noble <pixel@nobis-crew.org>2014-06-03 02:14:32 -0700
committerNicolas "Pixel" Noble <pixel@nobis-crew.org>2014-06-03 02:14:32 -0700
commit0243f128ddc7ee44db1a8b95f76eb726122ee1d5 (patch)
tree849119ab62379a31ef28f6fb8303b8824d0bb142 /src
parent185dc2e4a06c52937a3f260b2469cda7d62f6112 (diff)
Added MMap Handle object.
Diffstat (limited to 'src')
-rw-r--r--src/Buffer.cc21
-rw-r--r--src/MMap.cc100
2 files changed, 118 insertions, 3 deletions
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;
+}