1f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#if defined _WIN32 || defined _WIN64 2f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#include <sys/types.h> 3f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#include <sys/stat.h> 4f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#include <Windows.h> 5f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#else // defined _WIN32 || defined _WIN64 6f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#include <sys/mman.h> 7f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#include <sys/stat.h> 8f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#include <sys/types.h> 9f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#include <fcntl.h> 10f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#include <unistd.h> 11f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#endif // defined _WIN32 || defined _WIN64 12f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 13f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#include "mapper.h" 14f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 15f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamathnamespace marisa { 16f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 17f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#if defined _WIN32 || defined _WIN64 18f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan KamathMapper::Mapper() 19f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath : ptr_(NULL), origin_(NULL), avail_(0), size_(0), 20f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath file_(NULL), map_(NULL) {} 21f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 22f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan KamathMapper::Mapper(const void *ptr, std::size_t size) 23f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath : ptr_(ptr), origin_(NULL), avail_(size), size_(0), 24f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath file_(NULL), map_(NULL) { 250172f3c6f03973e56208e013178ec68365255c60Narayan Kamath MARISA_THROW_IF((ptr == NULL) || (size == 0), MARISA_PARAM_ERROR); 26f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath} 27f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#else // defined _WIN32 || defined _WIN64 28f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan KamathMapper::Mapper() 29f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath : ptr_(NULL), origin_(MAP_FAILED), avail_(0), size_(0), fd_(-1) {} 30f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 31f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan KamathMapper::Mapper(const void *ptr, std::size_t size) 32f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath : ptr_(ptr), origin_(MAP_FAILED), avail_(size), size_(0), fd_(-1) { 330172f3c6f03973e56208e013178ec68365255c60Narayan Kamath MARISA_THROW_IF((ptr == NULL) || (size == 0), MARISA_PARAM_ERROR); 34f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath} 35f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#endif // defined _WIN32 || defined _WIN64 36f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 37f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#if defined _WIN32 || defined _WIN64 38f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan KamathMapper::~Mapper() { 39f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath if (origin_ != NULL) { 40f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath ::UnmapViewOfFile(origin_); 41f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath } 42f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 43f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath if (map_ != NULL) { 44f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath ::CloseHandle(map_); 45f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath } 46f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 47f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath if (file_ != NULL) { 48f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath ::CloseHandle(file_); 49f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath } 50f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath} 51f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#else // defined _WIN32 || defined _WIN64 52f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan KamathMapper::~Mapper() { 53f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath if (origin_ != MAP_FAILED) { 54f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath ::munmap(origin_, size_); 55f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath } 56f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 57f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath if (fd_ != -1) { 58f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath ::close(fd_); 59f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath } 60f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath} 61f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#endif // defined _WIN32 || defined _WIN64 62f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 63f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#if defined _WIN32 || defined _WIN64 64f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamathvoid Mapper::open(const char *filename, long offset, int whence) { 65f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath MARISA_THROW_IF(is_open(), MARISA_STATE_ERROR); 66f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath MARISA_THROW_IF(filename == NULL, MARISA_PARAM_ERROR); 67f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 68f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath struct __stat64 st; 69f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath if (::_stat64(filename, &st) != 0) { 70f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath MARISA_THROW(MARISA_IO_ERROR); 71f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath } 72f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath const UInt64 file_size = st.st_size; 73f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath MARISA_THROW_IF(file_size > MARISA_UINT32_MAX, MARISA_SIZE_ERROR); 74f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 75f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath Mapper temp; 76f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath temp.size_ = (std::size_t)file_size; 77f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 78f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath temp.file_ = ::CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, 79f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 80f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath MARISA_THROW_IF(temp.file_ == NULL, MARISA_IO_ERROR); 81f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 82f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath temp.map_ = ::CreateFileMapping(temp.file_, NULL, PAGE_READONLY, 0, 0, NULL); 83f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath MARISA_THROW_IF(temp.map_ == NULL, MARISA_IO_ERROR); 84f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 85f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath temp.origin_ = ::MapViewOfFile(temp.map_, FILE_MAP_READ, 0, 0, 0); 86f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath MARISA_THROW_IF(temp.origin_ == NULL, MARISA_IO_ERROR); 87f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 88f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath temp.seek(offset, whence); 89f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath temp.swap(this); 90f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath} 91f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#else // defined _WIN32 || defined _WIN64 92f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamathvoid Mapper::open(const char *filename, long offset, int whence) { 93f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath MARISA_THROW_IF(is_open(), MARISA_STATE_ERROR); 94f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath MARISA_THROW_IF(filename == NULL, MARISA_PARAM_ERROR); 95f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 96f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath struct stat st; 97f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath if (::stat(filename, &st) != 0) { 98f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath MARISA_THROW(MARISA_IO_ERROR); 99f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath } 100f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath UInt64 file_size = st.st_size; 101f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath MARISA_THROW_IF(file_size > MARISA_UINT32_MAX, MARISA_SIZE_ERROR); 102f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 103f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath Mapper temp; 104f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath temp.size_ = (std::size_t)file_size; 105f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 106f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath temp.fd_ = ::open(filename, O_RDONLY); 107f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath MARISA_THROW_IF(temp.fd_ == -1, MARISA_IO_ERROR); 108f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 109f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath temp.origin_ = ::mmap(NULL, temp.size_, PROT_READ, MAP_SHARED, temp.fd_, 0); 110f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath MARISA_THROW_IF(temp.origin_ == MAP_FAILED, MARISA_IO_ERROR); 111f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 112f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath temp.seek(offset, whence); 113f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath temp.swap(this); 114f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath} 115f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#endif // defined _WIN32 || defined _WIN64 116f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 117f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamathvoid Mapper::clear() { 118f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath Mapper().swap(this); 119f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath} 120f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 121f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamathvoid Mapper::swap(Mapper *rhs) { 122f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath MARISA_THROW_IF(rhs == NULL, MARISA_PARAM_ERROR); 123f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath Swap(&ptr_, &rhs->ptr_); 124f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath Swap(&avail_, &rhs->avail_); 125f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath Swap(&origin_, &rhs->origin_); 126f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath Swap(&size_, &rhs->size_); 127f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#if defined _WIN32 || defined _WIN64 128f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath Swap(&file_, &rhs->file_); 129f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath Swap(&map_, &rhs->map_); 130f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#else // defined _WIN32 || defined _WIN64 131f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath Swap(&fd_, &rhs->fd_); 132f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath#endif // defined _WIN32 || defined _WIN64 133f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath} 134f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 135f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamathvoid Mapper::seek(long offset, int whence) { 136f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath switch (whence) { 137f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath case SEEK_SET: 138f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath case SEEK_CUR: { 139f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath MARISA_THROW_IF((offset < 0) || ((unsigned long)offset > size_), 140f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath MARISA_IO_ERROR); 141f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath ptr_ = static_cast<const UInt8 *>(origin_) + offset; 142f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath avail_ = (std::size_t)(size_ - offset); 143f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath return; 144f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath } 145f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath case SEEK_END: { 146f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath MARISA_THROW_IF((offset > 0) || ((unsigned long)-offset > size_), 147f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath MARISA_IO_ERROR); 148f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath ptr_ = static_cast<const UInt8 *>(origin_) + size_ + offset; 149f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath avail_ = (std::size_t)-offset; 150f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath return; 151f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath } 152f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath default: { 153f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath MARISA_THROW(MARISA_PARAM_ERROR); 154f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath } 155f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath } 156f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath} 157f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 158f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamathconst void *Mapper::map_data(std::size_t size) { 159f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath MARISA_THROW_IF(!is_open(), MARISA_STATE_ERROR); 160f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath MARISA_THROW_IF(size > avail_, MARISA_IO_ERROR); 161f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath ptr_ = static_cast<const UInt8 *>(ptr_) + size; 162f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath avail_ -= size; 163f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath return static_cast<const UInt8 *>(ptr_) - size; 164f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath} 165f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath 166f163f6985a63328d07e3de249ad3daf4a0c67d8aNarayan Kamath} // namespace marisa 167