container_device.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
  2. // (C) Copyright 2005-2007 Jonathan Turkanis
  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. // See http://www.boost.org/libs/iostreams for documentation.
  6. #ifndef BOOST_IOSTREAMS_EXAMPLE_CONTAINTER_DEVICE_HPP_INCLUDED
  7. #define BOOST_IOSTREAMS_EXAMPLE_CONTAINTER_DEVICE_HPP_INCLUDED
  8. #include <algorithm> // copy, min.
  9. #include <cassert>
  10. #include <boost/config.hpp> // BOOST_NO_STDC_NAMESPACE.
  11. #include <boost/iostreams/categories.hpp>
  12. #include <boost/iostreams/detail/ios.hpp> // failure.
  13. // Must come last.
  14. #include <boost/iostreams/detail/config/disable_warnings.hpp>
  15. namespace boost { namespace iostreams { namespace example {
  16. //
  17. // Model of Source which reads from an STL-compatible sequence
  18. // whose iterators are random-access iterators.
  19. //
  20. template<typename Container>
  21. class container_source {
  22. public:
  23. typedef typename Container::value_type char_type;
  24. typedef source_tag category;
  25. container_source(Container& container)
  26. : container_(container), pos_(0)
  27. { }
  28. std::streamsize read(char_type* s, std::streamsize n)
  29. {
  30. using namespace std;
  31. std::streamsize amt =
  32. static_cast<std::streamsize>(container_.size() - pos_);
  33. std::streamsize result = (min)(n, amt);
  34. if (result != 0) {
  35. std::copy( container_.begin() + pos_,
  36. container_.begin() + pos_ + result,
  37. s );
  38. pos_ += result;
  39. return result;
  40. } else {
  41. return -1; // EOF
  42. }
  43. }
  44. Container& container() { return container_; }
  45. private:
  46. container_source operator=(const container_source&);
  47. typedef typename Container::size_type size_type;
  48. Container& container_;
  49. size_type pos_;
  50. };
  51. //
  52. // Model of Sink which appends to an STL-compatible sequence.
  53. //
  54. template<typename Container>
  55. class container_sink {
  56. public:
  57. typedef typename Container::value_type char_type;
  58. typedef sink_tag category;
  59. container_sink(Container& container) : container_(container) { }
  60. std::streamsize write(const char_type* s, std::streamsize n)
  61. {
  62. container_.insert(container_.end(), s, s + n);
  63. return n;
  64. }
  65. Container& container() { return container_; }
  66. private:
  67. container_sink operator=(const container_sink&);
  68. Container& container_;
  69. };
  70. //
  71. // Model of SeekableDevice which accessS an TL-compatible sequence
  72. // whose iterators are random-access iterators.
  73. //
  74. template<typename Container>
  75. class container_device {
  76. public:
  77. typedef typename Container::value_type char_type;
  78. typedef seekable_device_tag category;
  79. container_device(Container& container)
  80. : container_(container), pos_(0)
  81. { }
  82. std::streamsize read(char_type* s, std::streamsize n)
  83. {
  84. using namespace std;
  85. std::streamsize amt =
  86. static_cast<std::streamsize>(container_.size() - pos_);
  87. std::streamsize result = (min)(n, amt);
  88. if (result != 0) {
  89. std::copy( container_.begin() + pos_,
  90. container_.begin() + pos_ + result,
  91. s );
  92. pos_ += result;
  93. return result;
  94. } else {
  95. return -1; // EOF
  96. }
  97. }
  98. std::streamsize write(const char_type* s, std::streamsize n)
  99. {
  100. using namespace std;
  101. std::streamsize result = 0;
  102. if (pos_ != container_.size()) {
  103. std::streamsize amt =
  104. static_cast<std::streamsize>(container_.size() - pos_);
  105. result = (min)(n, amt);
  106. std::copy(s, s + result, container_.begin() + pos_);
  107. pos_ += result;
  108. }
  109. if (result < n) {
  110. container_.insert(container_.end(), s, s + n);
  111. pos_ = container_.size();
  112. }
  113. return n;
  114. }
  115. stream_offset seek(stream_offset off, BOOST_IOS::seekdir way)
  116. {
  117. using namespace std;
  118. // Determine new value of pos_
  119. stream_offset next;
  120. if (way == BOOST_IOS::beg) {
  121. next = off;
  122. } else if (way == BOOST_IOS::cur) {
  123. next = pos_ + off;
  124. } else if (way == BOOST_IOS::end) {
  125. next = container_.size() + off - 1;
  126. } else {
  127. throw BOOST_IOSTREAMS_FAILURE("bad seek direction");
  128. }
  129. // Check for errors
  130. if (next < 0 || next > static_cast<stream_offset>(container_.size()))
  131. throw BOOST_IOSTREAMS_FAILURE("bad seek offset");
  132. pos_ = next;
  133. return pos_;
  134. }
  135. Container& container() { return container_; }
  136. private:
  137. container_device operator=(const container_device&);
  138. typedef typename Container::size_type size_type;
  139. Container& container_;
  140. size_type pos_;
  141. };
  142. } } } // End namespaces example, iostreams, boost.
  143. #include <boost/iostreams/detail/config/enable_warnings.hpp>
  144. #endif // #ifndef BOOST_IOSTREAMS_EXAMPLE_CONTAINTER_DEVICE_HPP_INCLUDED