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