9
3

iterator_source.hpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Hartmut Kaiser
  3. Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. ==============================================================================*/
  6. #if !defined(BOOST_SPIRIT_ITERATOR_ISTREAM_MAY_05_2007_0110PM)
  7. #define BOOST_SPIRIT_ITERATOR_ISTREAM_MAY_05_2007_0110PM
  8. #if defined(_MSC_VER)
  9. #pragma once
  10. #endif
  11. #include <boost/iostreams/stream.hpp>
  12. #include <iterator> // for std::iterator_traits, std::distance
  13. ///////////////////////////////////////////////////////////////////////////////
  14. namespace boost { namespace spirit { namespace qi { namespace detail
  15. {
  16. ///////////////////////////////////////////////////////////////////////////
  17. template <typename Iterator>
  18. struct base_iterator_source
  19. {
  20. typedef typename std::iterator_traits<Iterator>::value_type char_type;
  21. typedef boost::iostreams::seekable_device_tag category;
  22. base_iterator_source (Iterator const& first_, Iterator const& last_)
  23. : first(first_), last(last_), pos(0)
  24. {}
  25. // Read up to n characters from the input sequence into the buffer s,
  26. // returning the number of characters read, or -1 to indicate
  27. // end-of-sequence.
  28. std::streamsize read (char_type* s, std::streamsize n)
  29. {
  30. if (first == last)
  31. return -1;
  32. std::streamsize bytes_read = 0;
  33. while (n--) {
  34. *s = *first;
  35. ++s; ++bytes_read;
  36. if (++first == last)
  37. break;
  38. }
  39. pos += bytes_read;
  40. return bytes_read;
  41. }
  42. // Write is implemented only to satisfy the requirements of a
  43. // boost::iostreams::seekable_device. We need to have see support to
  44. // be able to figure out how many characters have been actually
  45. // consumed by the stream.
  46. std::streamsize write(const char_type*, std::streamsize)
  47. {
  48. BOOST_ASSERT(false); // not supported
  49. return -1;
  50. }
  51. std::streampos seek(boost::iostreams::stream_offset, std::ios_base::seekdir way)
  52. {
  53. (void)way;
  54. BOOST_ASSERT(way == std::ios_base::cur); // only support queries
  55. return pos; // return current position
  56. }
  57. Iterator first;
  58. Iterator const& last;
  59. std::streamsize pos;
  60. // silence MSVC warning C4512: assignment operator could not be generated
  61. BOOST_DELETED_FUNCTION(base_iterator_source& operator= (base_iterator_source const&))
  62. };
  63. template <typename Iterator, typename Enable = void>
  64. struct iterator_source : base_iterator_source<Iterator>
  65. {
  66. typedef base_iterator_source<Iterator> base_type;
  67. iterator_source (Iterator const& first_, Iterator const& last_)
  68. : base_type(first_, last_) {}
  69. };
  70. // Specialization for random-access iterators. This also allows compilers
  71. // to fully optimize the case when the source range is contiguous
  72. template <typename Iterator>
  73. struct iterator_source<
  74. Iterator,
  75. typename boost::enable_if_c<boost::is_convertible<
  76. typename std::iterator_traits<Iterator>::iterator_category, std::random_access_iterator_tag>::value>::type
  77. > : base_iterator_source<Iterator>
  78. {
  79. typedef base_iterator_source<Iterator> base_type;
  80. iterator_source (Iterator const& first_, Iterator const& last_)
  81. : base_type(first_, last_) {}
  82. typedef typename base_type::char_type char_type;
  83. using base_type::first;
  84. using base_type::last;
  85. using base_type::pos;
  86. // Read up to n characters from the input sequence into the buffer s,
  87. // returning the number of characters read, or -1 to indicate
  88. // end-of-sequence.
  89. std::streamsize read (char_type* s, std::streamsize n)
  90. {
  91. if (first == last)
  92. return -1;
  93. n = (std::min)(static_cast<std::streamsize>(last - first), n);
  94. typedef typename std::iterator_traits<Iterator>::difference_type diff_type;
  95. // copy_n is only part of c++11, so emulate it
  96. std::copy(first, first + static_cast<diff_type>(n), s);
  97. first += static_cast<diff_type>(n);
  98. pos += n;
  99. return n;
  100. }
  101. };
  102. }}}}
  103. #endif