]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/include/boost/spirit/home/classic/iterator/impl/file_iterator.ipp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / spirit / include / boost / spirit / home / classic / iterator / impl / file_iterator.ipp
1 /*=============================================================================
2 Copyright (c) 2003 Giovanni Bajo
3 Copyright (c) 2003 Martin Wille
4 Copyright (c) 2003 Hartmut Kaiser
5 http://spirit.sourceforge.net/
6
7 Use, modification and distribution is subject to the Boost Software
8 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9 http://www.boost.org/LICENSE_1_0.txt)
10 =============================================================================*/
11
12 #ifndef BOOST_SPIRIT_FILE_ITERATOR_IPP
13 #define BOOST_SPIRIT_FILE_ITERATOR_IPP
14
15 #ifdef BOOST_SPIRIT_FILEITERATOR_WINDOWS
16 # include <windows.h>
17 #endif
18
19 #include <cstdio>
20 #include <boost/shared_ptr.hpp>
21
22 #ifdef BOOST_SPIRIT_FILEITERATOR_WINDOWS
23 # include <boost/type_traits/remove_pointer.hpp>
24 #endif
25
26 #ifdef BOOST_SPIRIT_FILEITERATOR_POSIX
27 # include <sys/types.h> // open, stat, mmap, munmap
28 # include <sys/stat.h> // stat
29 # include <fcntl.h> // open
30 # include <unistd.h> // stat, mmap, munmap
31 # include <sys/mman.h> // mmap, mmunmap
32 #endif
33
34 ///////////////////////////////////////////////////////////////////////////////
35 namespace boost { namespace spirit {
36
37 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
38
39 ///////////////////////////////////////////////////////////////////////////////
40 namespace fileiter_impl {
41
42 ///////////////////////////////////////////////////////////////////////////////
43 //
44 // std_file_iterator
45 //
46 // Base class that implements iteration through a file using standard C
47 // stream library (fopen and friends). This class and the following are
48 // the base components on which the iterator is built (through the
49 // iterator adaptor library).
50 //
51 // The opened file stream (FILE) is held with a shared_ptr<>, whose
52 // custom deleter invokes fcose(). This makes the syntax of the class
53 // very easy, especially everything related to copying.
54 //
55 ///////////////////////////////////////////////////////////////////////////////
56
57 template <typename CharT>
58 class std_file_iterator
59 {
60 public:
61 typedef CharT value_type;
62
63 std_file_iterator()
64 {}
65
66 explicit std_file_iterator(std::string const& fileName)
67 {
68 using namespace std;
69 FILE* f = fopen(fileName.c_str(), "rb");
70
71 // If the file was opened, store it into
72 // the smart pointer.
73 if (f)
74 {
75 m_file.reset(f, fclose);
76 m_pos = 0;
77 m_eof = false;
78 update_char();
79 }
80 }
81
82 std_file_iterator(const std_file_iterator& iter)
83 { *this = iter; }
84
85 std_file_iterator& operator=(const std_file_iterator& iter)
86 {
87 m_file = iter.m_file;
88 m_curChar = iter.m_curChar;
89 m_eof = iter.m_eof;
90 m_pos = iter.m_pos;
91
92 return *this;
93 }
94
95 // Nasty bug in Comeau up to 4.3.0.1, we need explicit boolean context
96 // for shared_ptr to evaluate correctly
97 operator bool() const
98 { return m_file ? true : false; }
99
100 bool operator==(const std_file_iterator& iter) const
101 {
102 return (m_file == iter.m_file) && (m_eof == iter.m_eof) &&
103 (m_pos == iter.m_pos);
104 }
105
106 const CharT& get_cur_char(void) const
107 {
108 return m_curChar;
109 }
110
111 void prev_char(void)
112 {
113 m_pos -= sizeof(CharT);
114 update_char();
115 }
116
117 void next_char(void)
118 {
119 m_pos += sizeof(CharT);
120 update_char();
121 }
122
123 void seek_end(void)
124 {
125 using namespace std;
126 fseek(m_file.get(), 0, SEEK_END);
127 m_pos = ftell(m_file.get()) / sizeof(CharT);
128 m_eof = true;
129 }
130
131 void advance(std::ptrdiff_t n)
132 {
133 m_pos += n * sizeof(CharT);
134 update_char();
135 }
136
137 std::ptrdiff_t distance(const std_file_iterator& iter) const
138 {
139 return (std::ptrdiff_t)(m_pos - iter.m_pos) / sizeof(CharT);
140 }
141
142 private:
143 boost::shared_ptr<std::FILE> m_file;
144 std::size_t m_pos;
145 CharT m_curChar;
146 bool m_eof;
147
148 void update_char(void)
149 {
150 using namespace std;
151 if ((std::size_t)ftell(m_file.get()) != m_pos)
152 fseek(m_file.get(), m_pos, SEEK_SET);
153
154 m_eof = (fread(&m_curChar, sizeof(CharT), 1, m_file.get()) < 1);
155 }
156 };
157
158
159 ///////////////////////////////////////////////////////////////////////////////
160 //
161 // mmap_file_iterator
162 //
163 // File iterator for memory mapped files, for now implemented on Windows and
164 // POSIX platforms. This class has the same interface of std_file_iterator,
165 // and can be used in its place (in fact, it's the default for Windows and
166 // POSIX).
167 //
168 ///////////////////////////////////////////////////////////////////////////////
169
170 ///////////////////////////////////////////////////////////////////////////////
171 // mmap_file_iterator, Windows version
172 #ifdef BOOST_SPIRIT_FILEITERATOR_WINDOWS
173 template <typename CharT>
174 class mmap_file_iterator
175 {
176 public:
177 typedef CharT value_type;
178
179 mmap_file_iterator()
180 : m_filesize(0), m_curChar(0)
181 {}
182
183 explicit mmap_file_iterator(std::string const& fileName)
184 : m_filesize(0), m_curChar(0)
185 {
186 HANDLE hFile = ::CreateFileA(
187 fileName.c_str(),
188 GENERIC_READ,
189 FILE_SHARE_READ,
190 NULL,
191 OPEN_EXISTING,
192 FILE_FLAG_SEQUENTIAL_SCAN,
193 NULL
194 );
195
196 if (hFile == INVALID_HANDLE_VALUE)
197 return;
198
199 // Store the size of the file, it's used to construct
200 // the end iterator
201 m_filesize = ::GetFileSize(hFile, NULL);
202
203 HANDLE hMap = ::CreateFileMapping(
204 hFile,
205 NULL,
206 PAGE_READONLY,
207 0, 0,
208 NULL
209 );
210
211 if (hMap == NULL)
212 {
213 ::CloseHandle(hFile);
214 return;
215 }
216
217 LPVOID pMem = ::MapViewOfFile(
218 hMap,
219 FILE_MAP_READ,
220 0, 0, 0
221 );
222
223 if (pMem == NULL)
224 {
225 ::CloseHandle(hMap);
226 ::CloseHandle(hFile);
227 return;
228 }
229
230 // We hold both the file handle and the memory pointer.
231 // We can close the hMap handle now because Windows holds internally
232 // a reference to it since there is a view mapped.
233 ::CloseHandle(hMap);
234
235 // It seems like we can close the file handle as well (because
236 // a reference is hold by the filemap object).
237 ::CloseHandle(hFile);
238
239 // Store the handles inside the shared_ptr (with the custom destructors)
240 m_mem.reset(static_cast<CharT*>(pMem), ::UnmapViewOfFile);
241
242 // Start of the file
243 m_curChar = m_mem.get();
244 }
245
246 mmap_file_iterator(const mmap_file_iterator& iter)
247 { *this = iter; }
248
249 mmap_file_iterator& operator=(const mmap_file_iterator& iter)
250 {
251 m_curChar = iter.m_curChar;
252 m_mem = iter.m_mem;
253 m_filesize = iter.m_filesize;
254
255 return *this;
256 }
257
258 // Nasty bug in Comeau up to 4.3.0.1, we need explicit boolean context
259 // for shared_ptr to evaluate correctly
260 operator bool() const
261 { return m_mem ? true : false; }
262
263 bool operator==(const mmap_file_iterator& iter) const
264 { return m_curChar == iter.m_curChar; }
265
266 const CharT& get_cur_char(void) const
267 { return *m_curChar; }
268
269 void next_char(void)
270 { m_curChar++; }
271
272 void prev_char(void)
273 { m_curChar--; }
274
275 void advance(std::ptrdiff_t n)
276 { m_curChar += n; }
277
278 std::ptrdiff_t distance(const mmap_file_iterator& iter) const
279 { return m_curChar - iter.m_curChar; }
280
281 void seek_end(void)
282 {
283 m_curChar = m_mem.get() +
284 (m_filesize / sizeof(CharT));
285 }
286
287 private:
288 typedef boost::remove_pointer<HANDLE>::type handle_t;
289
290 boost::shared_ptr<CharT> m_mem;
291 std::size_t m_filesize;
292 CharT* m_curChar;
293 };
294
295 #endif // BOOST_SPIRIT_FILEITERATOR_WINDOWS
296
297 ///////////////////////////////////////////////////////////////////////////////
298 // mmap_file_iterator, POSIX version
299 #ifdef BOOST_SPIRIT_FILEITERATOR_POSIX
300 template <typename CharT>
301 class mmap_file_iterator
302 {
303 private:
304 struct mapping
305 {
306 mapping(void *p, off_t len)
307 : data(p)
308 , size(len)
309 { }
310
311 CharT const *begin() const
312 {
313 return static_cast<CharT *>(data);
314 }
315
316 CharT const *end() const
317 {
318 return static_cast<CharT *>(data) + size/sizeof(CharT);
319 }
320
321 ~mapping()
322 {
323 munmap(static_cast<char*>(data), size);
324 }
325
326 private:
327 void *data;
328 off_t size;
329 };
330
331 public:
332 typedef CharT value_type;
333
334 mmap_file_iterator()
335 : m_curChar(0)
336 {}
337
338 explicit mmap_file_iterator(std::string const& file_name)
339 : m_curChar(0)
340 {
341 // open the file
342 int fd = open(file_name.c_str(),
343 #ifdef O_NOCTTY
344 O_NOCTTY | // if stdin was closed then opening a file
345 // would cause the file to become the controlling
346 // terminal if the filename refers to a tty. Setting
347 // O_NOCTTY inhibits this.
348 #endif
349 O_RDONLY);
350
351 if (fd == -1)
352 return;
353
354 // call fstat to find get information about the file just
355 // opened (size and file type)
356 struct stat stat_buf;
357 if ((fstat(fd, &stat_buf) != 0) || !S_ISREG(stat_buf.st_mode))
358 { // if fstat returns an error or if the file isn't a
359 // regular file we give up.
360 close(fd);
361 return;
362 }
363
364 // perform the actual mapping
365 void *p = mmap(0, stat_buf.st_size, PROT_READ, MAP_SHARED, fd, 0);
366 // it is safe to close() here. POSIX requires that the OS keeps a
367 // second handle to the file while the file is mmapped.
368 close(fd);
369
370 if (p == MAP_FAILED)
371 return;
372
373 mapping *m = 0;
374 try
375 {
376 m = new mapping(p, stat_buf.st_size);
377 }
378 catch(...)
379 {
380 munmap(static_cast<char*>(p), stat_buf.st_size);
381 throw;
382 }
383
384 m_mem.reset(m);
385
386 // Start of the file
387 m_curChar = m_mem->begin();
388 }
389
390 mmap_file_iterator(const mmap_file_iterator& iter)
391 { *this = iter; }
392
393 mmap_file_iterator& operator=(const mmap_file_iterator& iter)
394 {
395 m_curChar = iter.m_curChar;
396 m_mem = iter.m_mem;
397
398 return *this;
399 }
400
401 // Nasty bug in Comeau up to 4.3.0.1, we need explicit boolean context
402 // for shared_ptr to evaluate correctly
403 operator bool() const
404 { return m_mem ? true : false; }
405
406 bool operator==(const mmap_file_iterator& iter) const
407 { return m_curChar == iter.m_curChar; }
408
409 const CharT& get_cur_char(void) const
410 { return *m_curChar; }
411
412 void next_char(void)
413 { m_curChar++; }
414
415 void prev_char(void)
416 { m_curChar--; }
417
418 void advance(signed long n)
419 { m_curChar += n; }
420
421 long distance(const mmap_file_iterator& iter) const
422 { return m_curChar - iter.m_curChar; }
423
424 void seek_end(void)
425 {
426 m_curChar = m_mem->end();
427 }
428
429 private:
430
431 boost::shared_ptr<mapping> m_mem;
432 CharT const* m_curChar;
433 };
434
435 #endif // BOOST_SPIRIT_FILEITERATOR_POSIX
436
437 ///////////////////////////////////////////////////////////////////////////////
438 } /* namespace boost::spirit::fileiter_impl */
439
440 template <typename CharT, typename BaseIteratorT>
441 file_iterator<CharT,BaseIteratorT>
442 file_iterator<CharT,BaseIteratorT>::make_end(void)
443 {
444 file_iterator iter(*this);
445 iter.base_reference().seek_end();
446 return iter;
447 }
448
449 template <typename CharT, typename BaseIteratorT>
450 file_iterator<CharT,BaseIteratorT>&
451 file_iterator<CharT,BaseIteratorT>::operator=(const base_t& iter)
452 {
453 base_t::operator=(iter);
454 return *this;
455 }
456
457 ///////////////////////////////////////////////////////////////////////////////
458 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
459
460 }} /* namespace boost::spirit */
461
462
463 #endif /* BOOST_SPIRIT_FILE_ITERATOR_IPP */