file_iterator.ipp
来自「CGAL is a collaborative effort of severa」· IPP 代码 · 共 460 行
IPP
460 行
/*============================================================================= Copyright (c) 2003 Giovanni Bajo Copyright (c) 2003 Martin Wille Copyright (c) 2003 Hartmut Kaiser http://spirit.sourceforge.net/ Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)=============================================================================*/#ifndef BOOST_SPIRIT_FILE_ITERATOR_IPP#define BOOST_SPIRIT_FILE_ITERATOR_IPP#ifdef BOOST_SPIRIT_FILEITERATOR_WINDOWS# define WIN32_LEAN_AND_MEAN# include <windows.h>#endif#include <cstdio>#include <boost/shared_ptr.hpp>#ifdef BOOST_SPIRIT_FILEITERATOR_WINDOWS# include <boost/type_traits/remove_pointer.hpp>#endif#ifdef BOOST_SPIRIT_FILEITERATOR_POSIX# include <sys/types.h> // open, stat, mmap, munmap# include <sys/stat.h> // stat# include <fcntl.h> // open# include <unistd.h> // stat, mmap, munmap# include <sys/mman.h> // mmap, mmunmap#endif///////////////////////////////////////////////////////////////////////////////namespace boost { namespace spirit {///////////////////////////////////////////////////////////////////////////////namespace fileiter_impl {using namespace std;/////////////////////////////////////////////////////////////////////////////////// std_file_iterator//// Base class that implements iteration through a file using standard C// stream library (fopen and friends). This class and the following are// the base components on which the iterator is built (through the// iterator adaptor library).//// The opened file stream (FILE) is held with a shared_ptr<>, whose// custom deleter invokes fcose(). This makes the syntax of the class// very easy, especially everything related to copying./////////////////////////////////////////////////////////////////////////////////template <typename CharT>class std_file_iterator{public: typedef CharT value_type; std_file_iterator() {} explicit std_file_iterator(std::string fileName) { FILE* f = fopen(fileName.c_str(), "rb"); // If the file was opened, store it into // the smart pointer. if (f) { m_file.reset(f, fclose); m_pos = 0; m_eof = false; update_char(); } } std_file_iterator(const std_file_iterator& iter) { *this = iter; } std_file_iterator& operator=(const std_file_iterator& iter) { m_file = iter.m_file; m_curChar = iter.m_curChar; m_eof = iter.m_eof; m_pos = iter.m_pos; return *this; } // Nasty bug in Comeau up to 4.3.0.1, we need explicit boolean context // for shared_ptr to evaluate correctly operator bool() const { return m_file ? true : false; } bool operator==(const std_file_iterator& iter) const { return (m_file == iter.m_file) && (m_eof == iter.m_eof) && (m_pos == iter.m_pos); } const CharT& get_cur_char(void) const { return m_curChar; } void prev_char(void) { m_pos -= sizeof(CharT); update_char(); } void next_char(void) { m_pos += sizeof(CharT); update_char(); } void seek_end(void) { fseek(m_file.get(), 0, SEEK_END); m_pos = ftell(m_file.get()) / sizeof(CharT); m_eof = true; } void advance(signed long n) { m_pos += n * sizeof(CharT); update_char(); } long distance(const std_file_iterator& iter) const { return (long)(m_pos - iter.m_pos) / sizeof(CharT); }private: boost::shared_ptr<FILE> m_file; std::size_t m_pos; CharT m_curChar; bool m_eof; void update_char(void) { if ((std::size_t)ftell(m_file.get()) != m_pos) fseek(m_file.get(), m_pos, SEEK_SET); m_eof = (fread(&m_curChar, sizeof(CharT), 1, m_file.get()) < 1); }};/////////////////////////////////////////////////////////////////////////////////// mmap_file_iterator//// File iterator for memory mapped files, for now implemented on Windows and// POSIX platforms. This class has the same interface of std_file_iterator,// and can be used in its place (in fact, it's the default for Windows and// POSIX).////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// mmap_file_iterator, Windows version#ifdef BOOST_SPIRIT_FILEITERATOR_WINDOWStemplate <typename CharT>class mmap_file_iterator{public: typedef CharT value_type; mmap_file_iterator() {} explicit mmap_file_iterator(std::string fileName) { HANDLE hFile = ::CreateFileA( fileName.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL ); if (hFile == INVALID_HANDLE_VALUE) return; // Store the size of the file, it's used to construct // the end iterator m_filesize = ::GetFileSize(hFile, NULL); HANDLE hMap = ::CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, NULL ); if (hMap == NULL) { ::CloseHandle(hFile); return; } LPVOID pMem = ::MapViewOfFile( hMap, FILE_MAP_READ, 0, 0, 0 ); if (pMem == NULL) { ::CloseHandle(hMap); ::CloseHandle(hFile); return; } // We hold both the file handle and the memory pointer. // We can close the hMap handle now because Windows holds internally // a reference to it since there is a view mapped. ::CloseHandle(hMap); // It seems like we can close the file handle as well (because // a reference is hold by the filemap object). ::CloseHandle(hFile); // Store the handles inside the shared_ptr (with the custom destructors) m_mem.reset(static_cast<CharT*>(pMem), ::UnmapViewOfFile); // Start of the file m_curChar = m_mem.get(); } mmap_file_iterator(const mmap_file_iterator& iter) { *this = iter; } mmap_file_iterator& operator=(const mmap_file_iterator& iter) { m_curChar = iter.m_curChar; m_mem = iter.m_mem; m_filesize = iter.m_filesize; return *this; } // Nasty bug in Comeau up to 4.3.0.1, we need explicit boolean context // for shared_ptr to evaluate correctly operator bool() const { return m_mem ? true : false; } bool operator==(const mmap_file_iterator& iter) const { return m_curChar == iter.m_curChar; } const CharT& get_cur_char(void) const { return *m_curChar; } void next_char(void) { m_curChar++; } void prev_char(void) { m_curChar--; } void advance(signed long n) { m_curChar += n; } long distance(const mmap_file_iterator& iter) const { return m_curChar - iter.m_curChar; } void seek_end(void) { m_curChar = m_mem.get() + (m_filesize / sizeof(CharT)); }private:#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION typedef boost::remove_pointer<HANDLE>::type handle_t;#else typedef void handle_t;#endif boost::shared_ptr<CharT> m_mem; std::size_t m_filesize; CharT* m_curChar;};#endif // BOOST_SPIRIT_FILEITERATOR_WINDOWS///////////////////////////////////////////////////////////////////////////////// mmap_file_iterator, POSIX version#ifdef BOOST_SPIRIT_FILEITERATOR_POSIXtemplate <typename CharT>class mmap_file_iterator{private: struct mapping { mapping(void *p, off_t len) : data(p) , size(len) { } CharT const *begin() const { return static_cast<CharT *>(data); } CharT const *end() const { return static_cast<CharT *>(data) + size/sizeof(CharT); } ~mapping() { munmap(data, size); } private: void *data; off_t size; };public: typedef CharT value_type; mmap_file_iterator() {} explicit mmap_file_iterator(std::string file_name) { // open the file int fd = open(file_name.c_str(),#ifdef O_NOCTTY O_NOCTTY | // if stdin was closed then opening a file // would cause the file to become the controlling // terminal if the filename refers to a tty. Setting // O_NOCTTY inhibits this.#endif O_RDONLY); if (fd == -1) return; // call fstat to find get information about the file just // opened (size and file type) struct stat stat_buf; if ((fstat(fd, &stat_buf) != 0) || !S_ISREG(stat_buf.st_mode)) { // if fstat returns an error or if the file isn't a // regular file we give up. close(fd); return; } // perform the actual mapping void *p = mmap(0, stat_buf.st_size, PROT_READ, MAP_SHARED, fd, 0); // it is safe to close() here. POSIX requires that the OS keeps a // second handle to the file while the file is mmapped. close(fd); if (p == MAP_FAILED) return; mapping *m = 0; try { m = new mapping(p, stat_buf.st_size); } catch(...) { munmap(p, stat_buf.st_size); throw; } m_mem.reset(m); // Start of the file m_curChar = m_mem->begin(); } mmap_file_iterator(const mmap_file_iterator& iter) { *this = iter; } mmap_file_iterator& operator=(const mmap_file_iterator& iter) { m_curChar = iter.m_curChar; m_mem = iter.m_mem; return *this; } // Nasty bug in Comeau up to 4.3.0.1, we need explicit boolean context // for shared_ptr to evaluate correctly operator bool() const { return m_mem ? true : false; } bool operator==(const mmap_file_iterator& iter) const { return m_curChar == iter.m_curChar; } const CharT& get_cur_char(void) const { return *m_curChar; } void next_char(void) { m_curChar++; } void prev_char(void) { m_curChar--; } void advance(signed long n) { m_curChar += n; } long distance(const mmap_file_iterator& iter) const { return m_curChar - iter.m_curChar; } void seek_end(void) { m_curChar = m_mem->end(); }private: boost::shared_ptr<mapping> m_mem; CharT const* m_curChar;};#endif // BOOST_SPIRIT_FILEITERATOR_POSIX///////////////////////////////////////////////////////////////////////////////} /* namespace boost::spirit::fileiter_impl */template <typename CharT, typename BaseIteratorT>file_iterator<CharT,BaseIteratorT>file_iterator<CharT,BaseIteratorT>::make_end(void){ file_iterator iter(*this); iter.base_reference().seek_end(); return iter;}template <typename CharT, typename BaseIteratorT>file_iterator<CharT,BaseIteratorT>&file_iterator<CharT,BaseIteratorT>::operator=(const base_t& iter){ base_t::operator=(iter); return *this;}///////////////////////////////////////////////////////////////////////////////}} /* namespace boost::spirit */#endif /* BOOST_SPIRIT_FILE_ITERATOR_IPP */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?