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