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