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