// MeCab -- Yet Another Part-of-Speech and Morphological Analyzer // // // Copyright(C) 2001-2006 Taku Kudo // Copyright(C) 2004-2006 Nippon Telegraph and Telephone Corporation #ifndef MECAB_MMAP_H #define MECAB_MMAP_H #include #include #ifdef HAVE_CONFIG_H #include "config.h" #endif extern "C" { #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_STAT_H #include #endif #ifdef HAVE_FCNTL_H #include #endif #ifdef HAVE_STRING_H #include #endif #if defined(_WIN32) && !defined(__CYGWIN__) #ifdef HAVE_WINDOWS_H #include #endif #else #ifdef HAVE_SYS_MMAN_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #endif } #include "common.h" #include "utils.h" #include #ifndef O_BINARY #define O_BINARY 0 #endif namespace MeCab { template class Mmap { private: T *text; size_t length; std::string fileName; whatlog what_; #if defined(_WIN32) && !defined(__CYGWIN__) HANDLE hFile; HANDLE hMap; #else int fd; int flag; #endif public: T& operator[](size_t n) { return *(text + n); } const T& operator[](size_t n) const { return *(text + n); } T* begin() { return text; } const T* begin() const { return text; } T* end() { return text + size(); } const T* end() const { return text + size(); } size_t size() { return length/sizeof(T); } const char *what() { return what_.str(); } const char *file_name() { return fileName.c_str(); } size_t file_size() { return length; } bool empty() { return(length == 0); } // This code is imported from sufary, develoved by // TATUO Yamashita Thanks! #if defined(_WIN32) && !defined(__CYGWIN__) bool open(const char *filename, const char *mode = "r") { this->close(); unsigned long mode1, mode2, mode3; fileName = std::string(filename); if (std::strcmp(mode, "r") == 0) { mode1 = GENERIC_READ; mode2 = PAGE_READONLY; mode3 = FILE_MAP_READ; } else if (std::strcmp(mode, "r+") == 0) { mode1 = GENERIC_READ | GENERIC_WRITE; mode2 = PAGE_READWRITE; mode3 = FILE_MAP_ALL_ACCESS; } else { CHECK_FALSE(false) << "unknown open mode:" << filename; } hFile = ::CreateFileW(WPATH(filename), mode1, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); CHECK_FALSE(hFile != INVALID_HANDLE_VALUE) << "CreateFile() failed: " << filename; length = ::GetFileSize(hFile, 0); hMap = ::CreateFileMapping(hFile, 0, mode2, 0, 0, 0); CHECK_FALSE(hMap) << "CreateFileMapping() failed: " << filename; text = reinterpret_cast(::MapViewOfFile(hMap, mode3, 0, 0, 0)); CHECK_FALSE(text) << "MapViewOfFile() failed: " << filename; return true; } void close() { if (text) { ::UnmapViewOfFile(text); } if (hFile != INVALID_HANDLE_VALUE) { ::CloseHandle(hFile); hFile = INVALID_HANDLE_VALUE; } if (hMap) { ::CloseHandle(hMap); hMap = 0; } text = 0; } Mmap(): text(0), hFile(INVALID_HANDLE_VALUE), hMap(0) {} #else bool open(const char *filename, const char *mode = "r") { this->close(); struct stat st; fileName = std::string(filename); if (std::strcmp(mode, "r") == 0) flag = O_RDONLY; else if (std::strcmp(mode, "r+") == 0) flag = O_RDWR; else CHECK_FALSE(false) << "unknown open mode: " << filename; CHECK_FALSE((fd = ::open(filename, flag | O_BINARY)) >= 0) << "open failed: " << filename; CHECK_FALSE(::fstat(fd, &st) >= 0) << "failed to get file size: " << filename; length = st.st_size; #ifdef HAVE_MMAP int prot = PROT_READ; if (flag == O_RDWR) prot |= PROT_WRITE; char *p; CHECK_FALSE((p = reinterpret_cast (::mmap(0, length, prot, MAP_SHARED, fd, 0))) != MAP_FAILED) << "mmap() failed: " << filename; text = reinterpret_cast(p); #else text = new T[length]; CHECK_FALSE(::read(fd, text, length) >= 0) << "read() failed: " << filename; #endif ::close(fd); fd = -1; return true; } void close() { if (fd >= 0) { ::close(fd); fd = -1; } if (text) { #ifdef HAVE_MMAP ::munmap(reinterpret_cast(text), length); text = 0; #else if (flag == O_RDWR) { int fd2; if ((fd2 = ::open(fileName.c_str(), O_RDWR)) >= 0) { ::write(fd2, text, length); ::close(fd2); } } delete [] text; #endif } text = 0; } Mmap() : text(0), fd(-1) {} #endif virtual ~Mmap() { this->close(); } }; } #endif