/* aKode: MMapFile Copyright (C) 2004 Allan Sandfeld Jensen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "akodelib.h" extern "C" { #ifdef HAVE_FEATURES_H // Needed for older glibc versions. #include #ifndef __USE_XOPEN2K #define __USE_XOPEN2K #endif #endif #include #ifdef HAVE_SYS_TYPES_H #include #endif #include #include #include #include #if defined(HAVE_MADVISE) && defined(NEED_MADVISE_PROTOTYPE) extern int madvise(void*,size_t,int); #endif } #include "mmapfile.h" namespace aKode { MMapFile::MMapFile(const char* filename) : File(filename), fd(-1), handle(0), len(0), pos(0) {} MMapFile::~MMapFile() { close(); } bool MMapFile::openRO() { if(handle) return true; struct stat stat; fd = ::open(filename, O_RDONLY); if (fstat(fd, &stat) < 0) return false; len = stat.st_size; pos = 0; handle = mmap(0, len, PROT_READ, MAP_SHARED, fd, 0); if (handle == MAP_FAILED) { ::close(fd); handle = 0; return false; } return true; } void MMapFile::close() { if(handle) { munmap((char*)handle,len); ::close(fd); } handle = 0; } long MMapFile::read(char* ptr, long num) { if(!handle) return -1; if (pos+num > len) num = len-pos; memcpy(ptr, (char*)handle+pos, num); pos += num; return num; } long MMapFile::write(const char*, long) { return false; } ssize_t MMapFile::lseek(long to, int whence) { if(!handle) return false; long newpos = 0; switch (whence) { case SEEK_SET: newpos = to; break; case SEEK_CUR: newpos = pos + to; break; case SEEK_END: newpos = len + to; break; default: return length(); } if (newpos > len || newpos < 0) return -1; pos = newpos; return newpos; } long MMapFile::position() const { if(!handle) return -1; return pos; } long MMapFile::length() const { if(!handle) return -1; return len; } bool MMapFile::error() const { return (!handle); } bool MMapFile::eof() const { if(!handle) return true; return pos >= len; } void MMapFile::fadvise() { if(!handle) return; #if defined(HAVE_POSIX_MADVISE) && defined(POSIX_MADV_SEQUENTIAL) posix_madvise((char*)handle+pos, len-pos, POSIX_MADV_SEQUENTIAL); #elif defined(HAVE_MADVISE) && defined(MADV_SEQUENTIAL) madvise((char*)handle+pos, len-pos, MADV_SEQUENTIAL); #endif } } //namespace