166 lines
4.6 KiB
C++
166 lines
4.6 KiB
C++
#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
|