diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Buffer.cc | 21 | ||||
-rw-r--r-- | src/MMap.cc | 100 |
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; +} |