// include/MappedFile.hh // This file is part of libpbe; see http://svn.chezphil.org/libpbe/ // (C) 2007 Philip Endecott // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // any later version. // // This program 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef libpbe_MappedFile_hh #define libpbe_MappedFile_hh #include "FileDescriptor.hh" #include "Exception.hh" #include #include namespace pbe { static char* mmap_helper(pbe::FileDescriptor& fd, size_t length, pbe::FileDescriptor::open_mode_t open_mode, off_t offset, bool copy_on_write) { return reinterpret_cast(fd.mmap(length,open_mode,offset,copy_on_write)); } static char* mmap_helper(std::string fn, pbe::FileDescriptor::open_mode_t open_mode, bool copy_on_write) { pbe::FileDescriptor fd(fn,open_mode); return reinterpret_cast(fd.mmap(fd.file_length(),open_mode,0,copy_on_write)); } static char* mmap_helper(std::string fn, size_t length, pbe::FileDescriptor::open_mode_t open_mode, bool copy_on_write) { pbe::FileDescriptor fd(fn,open_mode); return reinterpret_cast(fd.mmap(length,open_mode,0,copy_on_write)); } static size_t length_helper(std::string fn) { pbe::FileDescriptor fd(fn,pbe::FileDescriptor::read_only); return fd.file_length(); } class MappedFile { public: char* const addr; const size_t length; const off_t offset; MappedFile(pbe::FileDescriptor& fd, size_t length_, pbe::FileDescriptor::open_mode_t open_mode, off_t offset_ = 0, bool copy_on_write = false): addr(mmap_helper(fd,length_,open_mode,offset_,copy_on_write)), length(length_), offset(offset_) {} MappedFile(std::string fn, pbe::FileDescriptor::open_mode_t open_mode = pbe::FileDescriptor::read_only, bool copy_on_write = false): // FIXME there's a horrible hack here, as the fn is opened twice, once for // mmap() and a second time just to init length. addr(mmap_helper(fn,open_mode,copy_on_write)), length(length_helper(fn)), offset(0) {} MappedFile(std::string fn, size_t length_, pbe::FileDescriptor::open_mode_t open_mode = pbe::FileDescriptor::read_only, bool copy_on_write = false): addr(mmap_helper(fn,length_,open_mode,copy_on_write)), length(length_), offset(0) {} ~MappedFile() { int rc = munmap(addr,length); if (rc==-1) { pbe::throw_ErrnoException("munmap()"); } } operator char* () const { return addr; } template T* ptr(int offset) const { return reinterpret_cast(reinterpret_cast(addr)+offset); } template T& ref(int offset) const { return *ptr(offset); } void sync() { int rc = ::msync(addr,length,MS_SYNC|MS_INVALIDATE); if (rc==-1) { throw_ErrnoException("msync()"); } } }; }; #endif