file_iterator.hpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*=============================================================================
  2. Copyright (c) 2003 Giovanni Bajo
  3. Copyright (c) 2003 Thomas Witt
  4. Copyright (c) 2003 Hartmut Kaiser
  5. http://spirit.sourceforge.net/
  6. Distributed under the Boost Software License, Version 1.0. (See accompanying
  7. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  8. =============================================================================*/
  9. ///////////////////////////////////////////////////////////////////////////////
  10. //
  11. // File Iterator structure
  12. //
  13. // The new structure is designed on layers. The top class (used by the user)
  14. // is file_iterator, which implements a full random access iterator through
  15. // the file, and some specific member functions (constructor that opens
  16. // the file, make_end() to generate the end iterator, operator bool to check
  17. // if the file was opened correctly).
  18. //
  19. // file_iterator implements the random access iterator interface by the means
  20. // of boost::iterator_adaptor, that is inhering an object created with it.
  21. // iterator_adaptor gets a low-level file iterator implementation (with just
  22. // a few member functions) and a policy (that basically describes to it how
  23. // the low-level file iterator interface is). The advantage is that
  24. // with boost::iterator_adaptor only 5 functions are needed to implement
  25. // a fully conformant random access iterator, instead of dozens of functions
  26. // and operators.
  27. //
  28. // There are two low-level file iterators implemented in this module. The
  29. // first (std_file_iterator) uses cstdio stream functions (fopen/fread), which
  30. // support full buffering, and is available everywhere (it's standard C++).
  31. // The second (mmap_file_iterator) is currently available only on Windows
  32. // platforms, and uses memory mapped files, which gives a decent speed boost.
  33. //
  34. ///////////////////////////////////////////////////////////////////////////////
  35. //
  36. // TODO LIST:
  37. //
  38. // - In the Win32 mmap iterator, we could check if keeping a handle to the
  39. // opened file is really required. If it's not, we can just store the file
  40. // length (for make_end()) and save performance. Notice that this should be
  41. // tested under different Windows versions, the behaviour might change.
  42. // - Add some error support (by the means of some exceptions) in case of
  43. // low-level I/O failure.
  44. //
  45. ///////////////////////////////////////////////////////////////////////////////
  46. #ifndef BOOST_SPIRIT_FILE_ITERATOR_HPP
  47. #define BOOST_SPIRIT_FILE_ITERATOR_HPP
  48. #include <string>
  49. #include <boost/config.hpp>
  50. #include <boost/iterator_adaptors.hpp>
  51. #include <boost/spirit/home/classic/namespace.hpp>
  52. #include <boost/spirit/home/classic/core/safe_bool.hpp>
  53. #include <boost/spirit/home/classic/iterator/file_iterator_fwd.hpp>
  54. #if !defined(BOOST_SPIRIT_FILEITERATOR_STD)
  55. # if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \
  56. && !defined(BOOST_DISABLE_WIN32)
  57. # define BOOST_SPIRIT_FILEITERATOR_WINDOWS
  58. # elif defined(BOOST_HAS_UNISTD_H)
  59. extern "C"
  60. {
  61. # include <unistd.h>
  62. }
  63. # ifdef _POSIX_MAPPED_FILES
  64. # define BOOST_SPIRIT_FILEITERATOR_POSIX
  65. # endif // _POSIX_MAPPED_FILES
  66. # endif // BOOST_HAS_UNISTD_H
  67. # if !defined(BOOST_SPIRIT_FILEITERATOR_WINDOWS) && \
  68. !defined(BOOST_SPIRIT_FILEITERATOR_POSIX)
  69. # define BOOST_SPIRIT_FILEITERATOR_STD
  70. # endif
  71. #endif // BOOST_SPIRIT_FILEITERATOR_STD
  72. ///////////////////////////////////////////////////////////////////////////////
  73. namespace boost { namespace spirit {
  74. BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
  75. template <
  76. typename CharT = char,
  77. typename BaseIterator =
  78. #ifdef BOOST_SPIRIT_FILEITERATOR_STD
  79. fileiter_impl::std_file_iterator<CharT>
  80. #else
  81. fileiter_impl::mmap_file_iterator<CharT>
  82. #endif
  83. > class file_iterator;
  84. ///////////////////////////////////////////////////////////////////////////////
  85. namespace fileiter_impl {
  86. /////////////////////////////////////////////////////////////////////////
  87. //
  88. // file_iter_generator
  89. //
  90. // Template meta-function to invoke boost::iterator_adaptor
  91. // NOTE: This cannot be moved into the implementation file because of
  92. // a bug of MSVC 7.0 and previous versions (base classes types are
  93. // looked up at compilation time, not instantion types, and
  94. // file_iterator would break).
  95. //
  96. /////////////////////////////////////////////////////////////////////////
  97. #if !defined(BOOST_ITERATOR_ADAPTORS_VERSION) || \
  98. BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
  99. #error "Please use at least Boost V1.31.0 while compiling the file_iterator class!"
  100. #else // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
  101. template <typename CharT, typename BaseIteratorT>
  102. struct file_iter_generator
  103. {
  104. public:
  105. typedef BaseIteratorT adapted_t;
  106. typedef typename adapted_t::value_type value_type;
  107. typedef boost::iterator_adaptor <
  108. file_iterator<CharT, BaseIteratorT>,
  109. adapted_t,
  110. value_type const,
  111. std::random_access_iterator_tag,
  112. boost::use_default,
  113. std::ptrdiff_t
  114. > type;
  115. };
  116. #endif // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
  117. ///////////////////////////////////////////////////////////////////////////////
  118. } /* namespace impl */
  119. ///////////////////////////////////////////////////////////////////////////////
  120. //
  121. // file_iterator
  122. //
  123. // Iterates through an opened file.
  124. //
  125. // The main iterator interface is implemented by the iterator_adaptors
  126. // library, which wraps a conforming iterator interface around the
  127. // impl::BaseIterator class. This class merely derives the iterator_adaptors
  128. // generated class to implement the custom constructors and make_end()
  129. // member function.
  130. //
  131. ///////////////////////////////////////////////////////////////////////////////
  132. template<typename CharT, typename BaseIteratorT>
  133. class file_iterator
  134. : public fileiter_impl::file_iter_generator<CharT, BaseIteratorT>::type,
  135. public safe_bool<file_iterator<CharT, BaseIteratorT> >
  136. {
  137. private:
  138. typedef typename
  139. fileiter_impl::file_iter_generator<CharT, BaseIteratorT>::type
  140. base_t;
  141. typedef typename
  142. fileiter_impl::file_iter_generator<CharT, BaseIteratorT>::adapted_t
  143. adapted_t;
  144. public:
  145. file_iterator()
  146. {}
  147. file_iterator(std::string const& fileName)
  148. : base_t(adapted_t(fileName))
  149. {}
  150. file_iterator(const base_t& iter)
  151. : base_t(iter)
  152. {}
  153. inline file_iterator& operator=(const base_t& iter);
  154. file_iterator make_end(void);
  155. // operator bool. This borrows a trick from boost::shared_ptr to avoid
  156. // to interfere with arithmetic operations.
  157. bool operator_bool(void) const
  158. { return this->base(); }
  159. private:
  160. friend class ::boost::iterator_core_access;
  161. typename base_t::reference dereference() const
  162. {
  163. return this->base_reference().get_cur_char();
  164. }
  165. void increment()
  166. {
  167. this->base_reference().next_char();
  168. }
  169. void decrement()
  170. {
  171. this->base_reference().prev_char();
  172. }
  173. void advance(typename base_t::difference_type n)
  174. {
  175. this->base_reference().advance(n);
  176. }
  177. template <
  178. typename OtherDerivedT, typename OtherIteratorT,
  179. typename V, typename C, typename R, typename D
  180. >
  181. typename base_t::difference_type distance_to(
  182. iterator_adaptor<OtherDerivedT, OtherIteratorT, V, C, R, D>
  183. const &x) const
  184. {
  185. return x.base().distance(this->base_reference());
  186. }
  187. };
  188. ///////////////////////////////////////////////////////////////////////////////
  189. BOOST_SPIRIT_CLASSIC_NAMESPACE_END
  190. }} /* namespace BOOST_SPIRIT_CLASSIC_NS */
  191. ///////////////////////////////////////////////////////////////////////////////
  192. #include <boost/spirit/home/classic/iterator/impl/file_iterator.ipp> /* implementation */
  193. #endif /* BOOST_SPIRIT_FILE_ITERATOR_HPP */