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 + -
显示快捷键?