File indexing completed on 2025-12-16 10:09:00
0001
0002
0003
0004
0005
0006
0007
0008
0009
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
0045
0046
0047
0048
0049
0050
0051
0052
0053
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
0072
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
0096
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
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
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
0200
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
0231
0232
0233 ::CloseHandle(hMap);
0234
0235
0236
0237 ::CloseHandle(hFile);
0238
0239
0240 m_mem.reset(static_cast<CharT*>(pMem), ::UnmapViewOfFile);
0241
0242
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
0259
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
0296
0297
0298
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
0342 int fd = open(file_name.c_str(),
0343 #ifdef O_NOCTTY
0344 O_NOCTTY |
0345
0346
0347
0348 #endif
0349 O_RDONLY);
0350
0351 if (fd == -1)
0352 return;
0353
0354
0355
0356 struct stat stat_buf;
0357 if ((fstat(fd, &stat_buf) != 0) || !S_ISREG(stat_buf.st_mode))
0358 {
0359
0360 close(fd);
0361 return;
0362 }
0363
0364
0365 void *p = mmap(0, stat_buf.st_size, PROT_READ, MAP_SHARED, fd, 0);
0366
0367
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
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
0402
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
0436
0437
0438 }
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 }}
0461
0462
0463 #endif