Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:09:00

0001 /*=============================================================================
0002     Copyright (c) 2003 Giovanni Bajo
0003     Copyright (c) 2003 Martin Wille
0004     Copyright (c) 2003 Hartmut Kaiser
0005     http://spirit.sourceforge.net/
0006 
0007     Use, modification and distribution is subject to the Boost Software
0008     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0009     http://www.boost.org/LICENSE_1_0.txt)
0010 =============================================================================*/
0011 
0012 #ifndef BOOST_SPIRIT_FILE_ITERATOR_IPP
0013 #define BOOST_SPIRIT_FILE_ITERATOR_IPP
0014 
0015 #ifdef BOOST_SPIRIT_FILEITERATOR_WINDOWS
0016 #  include <windows.h>
0017 #endif
0018 
0019 #include <cstdio>
0020 #include <boost/shared_ptr.hpp>
0021 
0022 #ifdef BOOST_SPIRIT_FILEITERATOR_WINDOWS
0023 #  include <boost/type_traits/remove_pointer.hpp>
0024 #endif
0025 
0026 #ifdef BOOST_SPIRIT_FILEITERATOR_POSIX
0027 #  include <sys/types.h> // open, stat, mmap, munmap
0028 #  include <sys/stat.h>  // stat
0029 #  include <fcntl.h>     // open
0030 #  include <unistd.h>    // stat, mmap, munmap
0031 #  include <sys/mman.h>  // mmap, mmunmap
0032 #endif
0033 
0034 ///////////////////////////////////////////////////////////////////////////////
0035 namespace boost { namespace spirit {
0036 
0037 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
0038 
0039 ///////////////////////////////////////////////////////////////////////////////
0040 namespace fileiter_impl {
0041 
0042 ///////////////////////////////////////////////////////////////////////////////
0043 //
0044 //  std_file_iterator
0045 //
0046 //  Base class that implements iteration through a file using standard C
0047 //  stream library (fopen and friends). This class and the following are
0048 //  the base components on which the iterator is built (through the
0049 //  iterator adaptor library).
0050 //
0051 //  The opened file stream (FILE) is held with a shared_ptr<>, whose
0052 //  custom deleter invokes fcose(). This makes the syntax of the class
0053 //  very easy, especially everything related to copying.
0054 //
0055 ///////////////////////////////////////////////////////////////////////////////
0056 
0057 template <typename CharT>
0058 class std_file_iterator
0059 {
0060 public:
0061     typedef CharT value_type;
0062 
0063     std_file_iterator()
0064     {}
0065 
0066     explicit std_file_iterator(std::string const& fileName)
0067     {
0068         using namespace std;
0069         FILE* f = fopen(fileName.c_str(), "rb");
0070 
0071         // If the file was opened, store it into
0072         //  the smart pointer.
0073         if (f)
0074         {
0075             m_file.reset(f, fclose);
0076             m_pos = 0;
0077             m_eof = false;
0078             update_char();
0079         }
0080     }
0081 
0082     std_file_iterator(const std_file_iterator& iter)
0083     { *this = iter; }
0084 
0085     std_file_iterator& operator=(const std_file_iterator& iter)
0086     {
0087         m_file = iter.m_file;
0088         m_curChar = iter.m_curChar;
0089         m_eof = iter.m_eof;
0090         m_pos = iter.m_pos;
0091 
0092         return *this;
0093     }
0094 
0095     // Nasty bug in Comeau up to 4.3.0.1, we need explicit boolean context
0096     //  for shared_ptr to evaluate correctly
0097     operator bool() const
0098     { return m_file ? true : false; }
0099 
0100     bool operator==(const std_file_iterator& iter) const
0101     {
0102         return (m_file == iter.m_file) && (m_eof == iter.m_eof) &&
0103             (m_pos == iter.m_pos);
0104     }
0105 
0106     const CharT& get_cur_char(void) const
0107     {
0108         return m_curChar;
0109     }
0110 
0111     void prev_char(void)
0112     {
0113         m_pos -= sizeof(CharT);
0114         update_char();
0115     }
0116 
0117     void next_char(void)
0118     {
0119         m_pos += sizeof(CharT);
0120         update_char();
0121     }
0122 
0123     void seek_end(void)
0124     {
0125         using namespace std;
0126         fseek(m_file.get(), 0, SEEK_END);
0127         m_pos = ftell(m_file.get()) / sizeof(CharT);
0128         m_eof = true;
0129     }
0130 
0131     void advance(std::ptrdiff_t n)
0132     {
0133         m_pos += static_cast<long>(n) * sizeof(CharT);
0134         update_char();
0135     }
0136 
0137     std::ptrdiff_t distance(const std_file_iterator& iter) const
0138     {
0139         return (std::ptrdiff_t)(m_pos - iter.m_pos) / sizeof(CharT);
0140     }
0141 
0142 private:
0143     boost::shared_ptr<std::FILE> m_file;
0144     long m_pos;
0145     CharT m_curChar;
0146     bool m_eof;
0147 
0148     void update_char(void)
0149     {
0150         using namespace std;
0151         if (ftell(m_file.get()) != m_pos)
0152             fseek(m_file.get(), m_pos, SEEK_SET);
0153 
0154         m_eof = (fread(&m_curChar, sizeof(CharT), 1, m_file.get()) < 1);
0155     }
0156 };
0157 
0158 
0159 ///////////////////////////////////////////////////////////////////////////////
0160 //
0161 //  mmap_file_iterator
0162 //
0163 //  File iterator for memory mapped files, for now implemented on Windows and
0164 //  POSIX  platforms. This class has the same interface of std_file_iterator,
0165 //  and can be used in its place (in fact, it's the default for Windows and
0166 //  POSIX).
0167 //
0168 ///////////////////////////////////////////////////////////////////////////////
0169 
0170 ///////////////////////////////////////////////////////////////////////////////
0171 // mmap_file_iterator, Windows version
0172 #ifdef BOOST_SPIRIT_FILEITERATOR_WINDOWS
0173 template <typename CharT>
0174 class mmap_file_iterator
0175 {
0176 public:
0177     typedef CharT value_type;
0178 
0179     mmap_file_iterator()
0180       : m_filesize(0), m_curChar(0)
0181     {}
0182 
0183     explicit mmap_file_iterator(std::string const& fileName)
0184       : m_filesize(0), m_curChar(0)
0185     {
0186         HANDLE hFile = ::CreateFileA(
0187             fileName.c_str(),
0188             GENERIC_READ,
0189             FILE_SHARE_READ,
0190             NULL,
0191             OPEN_EXISTING,
0192             FILE_FLAG_SEQUENTIAL_SCAN,
0193             NULL
0194         );
0195 
0196         if (hFile == INVALID_HANDLE_VALUE)
0197             return;
0198 
0199         // Store the size of the file, it's used to construct
0200         //  the end iterator
0201         m_filesize = ::GetFileSize(hFile, NULL);
0202 
0203         HANDLE hMap = ::CreateFileMapping(
0204             hFile,
0205             NULL,
0206             PAGE_READONLY,
0207             0, 0,
0208             NULL
0209         );
0210 
0211         if (hMap == NULL)
0212         {
0213             ::CloseHandle(hFile);
0214             return;
0215         }
0216 
0217         LPVOID pMem = ::MapViewOfFile(
0218             hMap,
0219             FILE_MAP_READ,
0220             0, 0, 0
0221         );
0222 
0223         if (pMem == NULL)
0224         {
0225             ::CloseHandle(hMap);
0226             ::CloseHandle(hFile);
0227             return;
0228         }
0229 
0230         // We hold both the file handle and the memory pointer.
0231         // We can close the hMap handle now because Windows holds internally
0232         //  a reference to it since there is a view mapped.
0233         ::CloseHandle(hMap);
0234 
0235         // It seems like we can close the file handle as well (because
0236         //  a reference is hold by the filemap object).
0237         ::CloseHandle(hFile);
0238 
0239         // Store the handles inside the shared_ptr (with the custom destructors)
0240         m_mem.reset(static_cast<CharT*>(pMem), ::UnmapViewOfFile);
0241 
0242         // Start of the file
0243         m_curChar = m_mem.get();
0244     }
0245 
0246     mmap_file_iterator(const mmap_file_iterator& iter)
0247     { *this = iter; }
0248 
0249     mmap_file_iterator& operator=(const mmap_file_iterator& iter)
0250     {
0251         m_curChar = iter.m_curChar;
0252         m_mem = iter.m_mem;
0253         m_filesize = iter.m_filesize;
0254 
0255         return *this;
0256     }
0257 
0258     // Nasty bug in Comeau up to 4.3.0.1, we need explicit boolean context
0259     //  for shared_ptr to evaluate correctly
0260     operator bool() const
0261     { return m_mem ? true : false; }
0262 
0263     bool operator==(const mmap_file_iterator& iter) const
0264     { return m_curChar == iter.m_curChar; }
0265 
0266     const CharT& get_cur_char(void) const
0267     { return *m_curChar; }
0268 
0269     void next_char(void)
0270     { m_curChar++; }
0271 
0272     void prev_char(void)
0273     { m_curChar--; }
0274 
0275     void advance(std::ptrdiff_t n)
0276     { m_curChar += n; }
0277 
0278     std::ptrdiff_t distance(const mmap_file_iterator& iter) const
0279     { return m_curChar - iter.m_curChar; }
0280 
0281     void seek_end(void)
0282     {
0283         m_curChar = m_mem.get() +
0284             (m_filesize / sizeof(CharT));
0285     }
0286 
0287 private:
0288     typedef boost::remove_pointer<HANDLE>::type handle_t;
0289 
0290     boost::shared_ptr<CharT> m_mem;
0291     std::size_t m_filesize;
0292     CharT* m_curChar;
0293 };
0294 
0295 #endif // BOOST_SPIRIT_FILEITERATOR_WINDOWS
0296 
0297 ///////////////////////////////////////////////////////////////////////////////
0298 // mmap_file_iterator, POSIX version
0299 #ifdef BOOST_SPIRIT_FILEITERATOR_POSIX
0300 template <typename CharT>
0301 class mmap_file_iterator
0302 {
0303 private:
0304     struct mapping
0305     {
0306         mapping(void *p, off_t len)
0307             : data(p)
0308             , size(len)
0309         { }
0310 
0311         CharT const *begin() const
0312         {
0313             return static_cast<CharT *>(data);
0314         }
0315 
0316         CharT const *end() const
0317         {
0318             return static_cast<CharT *>(data) + size/sizeof(CharT);
0319         }
0320 
0321         ~mapping()
0322         {
0323             munmap(static_cast<char*>(data), size);
0324         }
0325 
0326     private:
0327         void *data;
0328         off_t size;
0329     };
0330 
0331 public:
0332     typedef CharT value_type;
0333 
0334     mmap_file_iterator()
0335       : m_curChar(0)
0336     {}
0337 
0338     explicit mmap_file_iterator(std::string const& file_name)
0339       : m_curChar(0)
0340     {
0341         // open the file
0342        int fd = open(file_name.c_str(),
0343 #ifdef O_NOCTTY
0344             O_NOCTTY | // if stdin was closed then opening a file
0345                        // would cause the file to become the controlling
0346                        // terminal if the filename refers to a tty. Setting
0347                        // O_NOCTTY inhibits this.
0348 #endif
0349             O_RDONLY);
0350 
0351         if (fd == -1)
0352             return;
0353 
0354         // call fstat to find get information about the file just
0355         // opened (size and file type)
0356         struct stat stat_buf;
0357         if ((fstat(fd, &stat_buf) != 0) || !S_ISREG(stat_buf.st_mode))
0358         {   // if fstat returns an error or if the file isn't a
0359             // regular file we give up.
0360             close(fd);
0361             return;
0362         }
0363 
0364         // perform the actual mapping
0365         void *p = mmap(0, stat_buf.st_size, PROT_READ, MAP_SHARED, fd, 0);
0366         // it is safe to close() here. POSIX requires that the OS keeps a
0367         // second handle to the file while the file is mmapped.
0368         close(fd);
0369 
0370         if (p == MAP_FAILED)
0371             return;
0372 
0373         mapping *m = 0;
0374         try
0375         {
0376             m = new mapping(p, stat_buf.st_size);
0377         }
0378         catch(...)
0379         {
0380             munmap(static_cast<char*>(p), stat_buf.st_size);
0381             throw;
0382         }
0383 
0384         m_mem.reset(m);
0385 
0386         // Start of the file
0387         m_curChar = m_mem->begin();
0388     }
0389 
0390     mmap_file_iterator(const mmap_file_iterator& iter)
0391     { *this = iter; }
0392 
0393     mmap_file_iterator& operator=(const mmap_file_iterator& iter)
0394     {
0395         m_curChar = iter.m_curChar;
0396         m_mem = iter.m_mem;
0397 
0398         return *this;
0399     }
0400 
0401     // Nasty bug in Comeau up to 4.3.0.1, we need explicit boolean context
0402     //  for shared_ptr to evaluate correctly
0403     operator bool() const
0404     { return m_mem ? true : false; }
0405 
0406     bool operator==(const mmap_file_iterator& iter) const
0407     { return m_curChar == iter.m_curChar; }
0408 
0409     const CharT& get_cur_char(void) const
0410     { return *m_curChar; }
0411 
0412     void next_char(void)
0413     { m_curChar++; }
0414 
0415     void prev_char(void)
0416     { m_curChar--; }
0417 
0418     void advance(signed long n)
0419     { m_curChar += n; }
0420 
0421     long distance(const mmap_file_iterator& iter) const
0422     { return m_curChar - iter.m_curChar; }
0423 
0424     void seek_end(void)
0425     {
0426         m_curChar = m_mem->end();
0427     }
0428 
0429 private:
0430 
0431     boost::shared_ptr<mapping> m_mem;
0432     CharT const* m_curChar;
0433 };
0434 
0435 #endif // BOOST_SPIRIT_FILEITERATOR_POSIX
0436 
0437 ///////////////////////////////////////////////////////////////////////////////
0438 } /* namespace boost::spirit::fileiter_impl */
0439 
0440 template <typename CharT, typename BaseIteratorT>
0441 file_iterator<CharT,BaseIteratorT>
0442 file_iterator<CharT,BaseIteratorT>::make_end(void)
0443 {
0444     file_iterator iter(*this);
0445     iter.base_reference().seek_end();
0446     return iter;
0447 }
0448 
0449 template <typename CharT, typename BaseIteratorT>
0450 file_iterator<CharT,BaseIteratorT>&
0451 file_iterator<CharT,BaseIteratorT>::operator=(const base_t& iter)
0452 {
0453     base_t::operator=(iter);
0454     return *this;
0455 }
0456 
0457 ///////////////////////////////////////////////////////////////////////////////
0458 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
0459 
0460 }} /* namespace boost::spirit */
0461 
0462 
0463 #endif /* BOOST_SPIRIT_FILE_ITERATOR_IPP */