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