| 1 | // (C) Copyright Jonathan Turkanis 2005. |
|---|
| 2 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
|---|
| 3 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) |
|---|
| 4 | |
|---|
| 5 | // See http://www.boost.org/libs/iostreams for documentation. |
|---|
| 6 | |
|---|
| 7 | #ifndef BOOST_IOSTREAMS_CONTAINTER_DEVICE_HPP_INCLUDED |
|---|
| 8 | #define BOOST_IOSTREAMS_CONTAINTER_DEVICE_HPP_INCLUDED |
|---|
| 9 | |
|---|
| 10 | #include <algorithm> // copy, min. |
|---|
| 11 | #include <boost/config.hpp> // BOOST_NO_STDC_NAMESPACE. |
|---|
| 12 | #include <boost/iostreams/categories.hpp> |
|---|
| 13 | #include <boost/iostreams/detail/ios.hpp> // failure. |
|---|
| 14 | |
|---|
| 15 | namespace boost { namespace iostreams { namespace example { |
|---|
| 16 | |
|---|
| 17 | // |
|---|
| 18 | // Model of Source which reads from an STL-compatible sequence |
|---|
| 19 | // whose iterators are random-access iterators. |
|---|
| 20 | // |
|---|
| 21 | template<typename Container> |
|---|
| 22 | class container_source { |
|---|
| 23 | public: |
|---|
| 24 | typedef typename Container::value_type char_type; |
|---|
| 25 | typedef source_tag category; |
|---|
| 26 | container_source(Container& container) |
|---|
| 27 | : container_(container), pos_(0) |
|---|
| 28 | { } |
|---|
| 29 | std::streamsize read(char_type* s, std::streamsize n) |
|---|
| 30 | { |
|---|
| 31 | using namespace std; |
|---|
| 32 | streamsize amt = static_cast<streamsize>(container_.size() - pos_); |
|---|
| 33 | 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 | typedef typename Container::size_type size_type; |
|---|
| 47 | Container& container_; |
|---|
| 48 | size_type pos_; |
|---|
| 49 | }; |
|---|
| 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& container_; |
|---|
| 68 | }; |
|---|
| 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 | |
|---|
| 83 | std::streamsize read(char_type* s, std::streamsize n) |
|---|
| 84 | { |
|---|
| 85 | using namespace std; |
|---|
| 86 | streamsize amt = static_cast<streamsize>(container_.size() - pos_); |
|---|
| 87 | 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 | streamsize result = 0; |
|---|
| 102 | if (pos_ != container_.size()) { |
|---|
| 103 | streamsize amt = |
|---|
| 104 | static_cast<streamsize>(container_.size() - pos_); |
|---|
| 105 | streamsize 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 | |
|---|
| 119 | // Determine new value of pos_ |
|---|
| 120 | stream_offset next; |
|---|
| 121 | if (way == BOOST_IOS::beg) { |
|---|
| 122 | next = off; |
|---|
| 123 | } else if (way == BOOST_IOS::cur) { |
|---|
| 124 | next = pos_ + off; |
|---|
| 125 | } else if (way == BOOST_IOS::end) { |
|---|
| 126 | next = container_.size() + off - 1; |
|---|
| 127 | } |
|---|
| 128 | |
|---|
| 129 | // Check for errors |
|---|
| 130 | if (next < 0 || next >= container_.size()) |
|---|
| 131 | throw BOOST_IOSTREAMS_FAILURE("bad seek offset"); |
|---|
| 132 | |
|---|
| 133 | pos_ = next; |
|---|
| 134 | return pos_; |
|---|
| 135 | } |
|---|
| 136 | |
|---|
| 137 | Container& container() { return container_; } |
|---|
| 138 | private: |
|---|
| 139 | typedef typename Container::size_type size_type; |
|---|
| 140 | Container& container_; |
|---|
| 141 | size_type pos_; |
|---|
| 142 | }; |
|---|
| 143 | |
|---|
| 144 | } } } // End namespaces example, iostreams, boost. |
|---|
| 145 | |
|---|
| 146 | #endif // #ifndef BOOST_IOSTREAMS_CONTAINTER_DEVICE_HPP_INCLUDED |
|---|