Home | History | Annotate | Download | only in marisa_alpha
      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