#if defined _WIN32 || defined _WIN64 #include <sys/types.h> #include <sys/stat.h> #include <Windows.h> #else // defined _WIN32 || defined _WIN64 #include <sys/mman.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h> #endif // defined _WIN32 || defined _WIN64 #include "mapper.h" namespace marisa { #if defined _WIN32 || defined _WIN64 Mapper::Mapper() : ptr_(NULL), origin_(NULL), avail_(0), size_(0), file_(NULL), map_(NULL) {} Mapper::Mapper(const void *ptr, std::size_t size) : ptr_(ptr), origin_(NULL), avail_(size), size_(0), file_(NULL), map_(NULL) { MARISA_THROW_IF((ptr == NULL) || (size == 0), MARISA_PARAM_ERROR); } #else // defined _WIN32 || defined _WIN64 Mapper::Mapper() : ptr_(NULL), origin_(MAP_FAILED), avail_(0), size_(0), fd_(-1) {} Mapper::Mapper(const void *ptr, std::size_t size) : ptr_(ptr), origin_(MAP_FAILED), avail_(size), size_(0), fd_(-1) { MARISA_THROW_IF((ptr == NULL) || (size == 0), MARISA_PARAM_ERROR); } #endif // defined _WIN32 || defined _WIN64 #if defined _WIN32 || defined _WIN64 Mapper::~Mapper() { if (origin_ != NULL) { ::UnmapViewOfFile(origin_); } if (map_ != NULL) { ::CloseHandle(map_); } if (file_ != NULL) { ::CloseHandle(file_); } } #else // defined _WIN32 || defined _WIN64 Mapper::~Mapper() { if (origin_ != MAP_FAILED) { ::munmap(origin_, size_); } if (fd_ != -1) { ::close(fd_); } } #endif // defined _WIN32 || defined _WIN64 #if defined _WIN32 || defined _WIN64 void Mapper::open(const char *filename, long offset, int whence) { MARISA_THROW_IF(is_open(), MARISA_STATE_ERROR); MARISA_THROW_IF(filename == NULL, MARISA_PARAM_ERROR); struct __stat64 st; if (::_stat64(filename, &st) != 0) { MARISA_THROW(MARISA_IO_ERROR); } const UInt64 file_size = st.st_size; MARISA_THROW_IF(file_size > MARISA_UINT32_MAX, MARISA_SIZE_ERROR); Mapper temp; temp.size_ = (std::size_t)file_size; temp.file_ = ::CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); MARISA_THROW_IF(temp.file_ == NULL, MARISA_IO_ERROR); temp.map_ = ::CreateFileMapping(temp.file_, NULL, PAGE_READONLY, 0, 0, NULL); MARISA_THROW_IF(temp.map_ == NULL, MARISA_IO_ERROR); temp.origin_ = ::MapViewOfFile(temp.map_, FILE_MAP_READ, 0, 0, 0); MARISA_THROW_IF(temp.origin_ == NULL, MARISA_IO_ERROR); temp.seek(offset, whence); temp.swap(this); } #else // defined _WIN32 || defined _WIN64 void Mapper::open(const char *filename, long offset, int whence) { MARISA_THROW_IF(is_open(), MARISA_STATE_ERROR); MARISA_THROW_IF(filename == NULL, MARISA_PARAM_ERROR); struct stat st; if (::stat(filename, &st) != 0) { MARISA_THROW(MARISA_IO_ERROR); } UInt64 file_size = st.st_size; MARISA_THROW_IF(file_size > MARISA_UINT32_MAX, MARISA_SIZE_ERROR); Mapper temp; temp.size_ = (std::size_t)file_size; temp.fd_ = ::open(filename, O_RDONLY); MARISA_THROW_IF(temp.fd_ == -1, MARISA_IO_ERROR); temp.origin_ = ::mmap(NULL, temp.size_, PROT_READ, MAP_SHARED, temp.fd_, 0); MARISA_THROW_IF(temp.origin_ == MAP_FAILED, MARISA_IO_ERROR); temp.seek(offset, whence); temp.swap(this); } #endif // defined _WIN32 || defined _WIN64 void Mapper::clear() { Mapper().swap(this); } void Mapper::swap(Mapper *rhs) { MARISA_THROW_IF(rhs == NULL, MARISA_PARAM_ERROR); Swap(&ptr_, &rhs->ptr_); Swap(&avail_, &rhs->avail_); Swap(&origin_, &rhs->origin_); Swap(&size_, &rhs->size_); #if defined _WIN32 || defined _WIN64 Swap(&file_, &rhs->file_); Swap(&map_, &rhs->map_); #else // defined _WIN32 || defined _WIN64 Swap(&fd_, &rhs->fd_); #endif // defined _WIN32 || defined _WIN64 } void Mapper::seek(long offset, int whence) { switch (whence) { case SEEK_SET: case SEEK_CUR: { MARISA_THROW_IF((offset < 0) || ((unsigned long)offset > size_), MARISA_IO_ERROR); ptr_ = static_cast<const UInt8 *>(origin_) + offset; avail_ = (std::size_t)(size_ - offset); return; } case SEEK_END: { MARISA_THROW_IF((offset > 0) || ((unsigned long)-offset > size_), MARISA_IO_ERROR); ptr_ = static_cast<const UInt8 *>(origin_) + size_ + offset; avail_ = (std::size_t)-offset; return; } default: { MARISA_THROW(MARISA_PARAM_ERROR); } } } const void *Mapper::map_data(std::size_t size) { MARISA_THROW_IF(!is_open(), MARISA_STATE_ERROR); MARISA_THROW_IF(size > avail_, MARISA_IO_ERROR); ptr_ = static_cast<const UInt8 *>(ptr_) + size; avail_ -= size; return static_cast<const UInt8 *>(ptr_) - size; } } // namespace marisa