Files
clients/MorphereAnalyzer/mmap.h
admin 2e7d343f4a MorphereAnalyzer
git-svn-id: svn://192.168.0.12/source@76 8346c931-da38-4b9b-9d4c-e48b93cbd075
2015-04-17 02:44:11 +00:00

215 lines
4.7 KiB
C++

// MeCab -- Yet Another Part-of-Speech and Morphological Analyzer
//
//
// Copyright(C) 2001-2006 Taku Kudo <taku@chasen.org>
// Copyright(C) 2004-2006 Nippon Telegraph and Telephone Corporation
#ifndef MECAB_MMAP_H
#define MECAB_MMAP_H
#include <errno.h>
#include <string>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
extern "C" {
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
#else
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#endif
}
#include "common.h"
#include "utils.h"
#include <winnt.h>
#ifndef O_BINARY
#define O_BINARY 0
#endif
namespace MeCab {
template <class T> 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 <yto@nais.to> 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<T *>(::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<char *>
(::mmap(0, length, prot, MAP_SHARED, fd, 0)))
!= MAP_FAILED)
<< "mmap() failed: " << filename;
text = reinterpret_cast<T *>(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<char *>(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