Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit153d203

Browse files
committed
Add the first version of the stream manipulators performing the BASE64 encoding
1 parent9328c7e commit153d203

File tree

1 file changed

+237
-0
lines changed

1 file changed

+237
-0
lines changed
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
#ifndef BOOST_NETWORK_UTILS_BASE64_ENCODE_IO_HPP
2+
#defineBOOST_NETWORK_UTILS_BASE64_ENCODE_IO_HPP
3+
4+
#include<boost/network/utils/base64/encode.hpp>
5+
#include<boost/archive/iterators/ostream_iterator.hpp>
6+
#include<boost/range/begin.hpp>
7+
#include<boost/range/end.hpp>
8+
#include<iterator>
9+
10+
namespaceboost {
11+
namespacenetwork {
12+
namespaceutils {
13+
14+
// Offers an interface to the BASE64 converter from encode.hpp, which is
15+
// based on stream manipulators to be friendly to the usage with output
16+
// streams combining heterogenous output by using the output operators.
17+
// The encoding state is serialized to long and maintained in te extensible
18+
// internal array of the output stream.
19+
//
20+
// Summarized interface - ostream manipulators and one function:
21+
//
22+
// encode(InputIterator begin, InputIterator end)
23+
// encode(InputRange const & value)
24+
// encode(char const * value)
25+
// encode_rest
26+
// clear_state
27+
// bool empty_state(std::basic_ostream<Char> & output)
28+
29+
namespacebase64 {
30+
namespaceio {
31+
32+
// force using the ostream_iterator from boost::archive to write wide
33+
// characters reliably, althoth wchar_t may not be a native character type
34+
usingnamespaceboost::archive::iterators;
35+
36+
namespacedetail {
37+
38+
// Enables transferring of the input sequence for the BASE64 encoding into
39+
// the ostream operator defined for it, which performs the operation. It
40+
// is to be used from ostream manipulators.
41+
//
42+
// std::basic_ostream<Char> & output = ...;
43+
// output << input_wrapper<InputIterator>(value.begin(), value.end());
44+
template<typename InputIterator>
45+
structinput_wrapper {
46+
input_wrapper(InputIterator begin, InputIterator end)
47+
: begin(begin), end(end) {}
48+
49+
private:
50+
InputIterator begin, end;
51+
52+
// only encoding of an input sequence needs access to it
53+
template<
54+
typename Char,
55+
typename InputIterator2
56+
>
57+
friend std::basic_ostream<Char> &
58+
operator <<(std::basic_ostream<Char> & output,
59+
input_wrapper<InputIterator2> input_wrapper);
60+
};
61+
62+
// The output stream state should be used only in a single scope around
63+
// encoding operations. Constructor performs initialization from the
64+
// output stream internal extensible array and destructor updates it
65+
// according to the encoding result. It inherits from the base64::state
66+
// to gain access to its protected members and allow easy value passing
67+
// to base64::encode.
68+
//
69+
//
70+
// std::basic_ostream<Char> & output = ...;
71+
// {
72+
// state<Char, Value> rest(output);
73+
// base64::encode(..., ostream_iterator<Char>(output), rest);
74+
// }
75+
template<typename Char,typename Value>
76+
structstate :publicboost::network::utils::base64::state<Value> {
77+
typedef boost::network::utils::base64::state<Value>super_t;
78+
79+
// initialize the (inherited) contents of the base64::state<> from the
80+
// output stream internal extensible array
81+
state(std::basic_ostream<Char> & output) :super_t(), output(output) {
82+
constunsigned triplet_index_size =sizeof(super_t::triplet_index) *8;
83+
unsignedlong data =static_cast<unsignedlong>(storage());
84+
// mask the long value with the bit-size of the triplet_index member
85+
super_t::triplet_index = data & ((1 << triplet_index_size) -1);
86+
// shift the long value right to remove the the triplet_index value;
87+
// masking is not necessary because the last_encoded_value it is the
88+
// last record stored in the data value
89+
super_t::last_encoded_value = data >> triplet_index_size;
90+
}
91+
92+
// update the value in the output stream internal extensible array by
93+
// the last (inherited) contents of the base64::state<>
94+
~state() {
95+
constunsigned triplet_index_size =sizeof(super_t::triplet_index) *8;
96+
// store the last_encoded_value in the data value first
97+
unsignedlong data =
98+
static_cast<unsignedlong>(super_t::last_encoded_value);
99+
// shift the long data value left to make place for storing the
100+
// full triplet_index value there
101+
data <<= triplet_index_size;
102+
data |=static_cast<unsignedlong>(super_t::triplet_index);
103+
storage() =static_cast<long>(data);
104+
}
105+
106+
private:
107+
// all data of the base64::state<> must be serializable into a long
108+
// value allocated in the output stream internal extensible array
109+
BOOST_STATIC_ASSERT(sizeof(super_t) <=sizeof(long));
110+
111+
// allow only the construction with an output stream (strict RAII)
112+
state();
113+
state(state<Char, Value>const & source);
114+
115+
std::basic_ostream<Char> & output;
116+
117+
long &storage() {
118+
staticint index =std::ios_base::xalloc();
119+
return output.iword(index);
120+
}
121+
};
122+
123+
// Output operator implementing the BASE64 encoding for an input sequence
124+
// which was wrapped by the ostream manipulator; the state must be preserved
125+
// because multiple sequences can be sent in the ouptut by this operator.
126+
template<
127+
typename Char,
128+
typename InputIterator
129+
>
130+
std::basic_ostream<Char> &
131+
operator <<(std::basic_ostream<Char> & output,
132+
input_wrapper<InputIterator> input) {
133+
typedeftypename iterator_value<InputIterator>::type value_type;
134+
state<Char, value_type>rest(output);
135+
base64::encode(input.begin, input.end, ostream_iterator<Char>(output), rest);
136+
return output;
137+
}
138+
139+
}// namespace detail
140+
141+
// Encoding ostream manipulator for sequences specified by the pair of begin
142+
// and end iterators.
143+
//
144+
// std::vector<unsigned char> buffer = ...;
145+
// std::basic_ostream<Char> & output = ...;
146+
// output << base64::io::encode(buffer.begin(), buffer.end()) << ... <<
147+
// base64::io::encode_rest<unsigned char>;
148+
template<typename InputIterator>
149+
detail::input_wrapper<InputIterator>encode(InputIterator begin,
150+
InputIterator end) {
151+
return detail::input_wrapper<InputIterator>(begin, end);
152+
}
153+
154+
// Encoding ostream manipulator processing whole sequences which either
155+
// support begin() and end() methods returning boundaries of the sequence
156+
// or the boundaries can be computed by the Boost::Range.
157+
//
158+
// Warning: Buffers identified by C-pointers are processed including their
159+
// termination character, if they have any. This is unexpected at least
160+
// for the storing literals, which have a specialization here to avoid it.
161+
//
162+
// std::vector<unsigned char> buffer = ...;
163+
// std::basic_ostream<Char> & output = ...;
164+
// output << base64::io::encode(buffer) << ... <<
165+
// base64::io::encode_rest<unsigned char>;
166+
template<typename InputRange>
167+
detail::input_wrapper<typename boost::range_const_iterator<InputRange>::type>
168+
encode(InputRangeconst & value) {
169+
typedeftypename boost::range_const_iterator<InputRange>::type InputIterator;
170+
return detail::input_wrapper<InputIterator>(boost::begin(value),
171+
boost::end(value));
172+
}
173+
174+
// Encoding ostream manipulator processing string literals; the usual
175+
// expectation from their encoding is processing only the string content
176+
// without the terminating zero character.
177+
//
178+
// std::basic_ostream<Char> & output = ...;
179+
// output << base64::io::encode("ab") << ... << base64::io::encode_rest<char>;
180+
inline detail::input_wrapper<charconst *>encode(charconst * value) {
181+
return detail::input_wrapper<charconst *>(value, value +strlen(value));
182+
}
183+
184+
// Encoding ostream manipulator which finishes encoding of the previously
185+
// processed chunks. If their total byte-length was divisible by three,
186+
// nothing is needed, if not, the last quantum will be encoded as if padded
187+
// with zeroes, which will be indicated by appending '=' characters to the
188+
// output. This manipulator must be always used at the end of encoding,
189+
// after previous usages of the encode manipulator.
190+
//
191+
// std::basic_ostream<Char> & output = ...;
192+
// output << base64::io::encode("ab") << ... << base64::io::encode_rest<char>;
193+
template<typename Value,typename Char>
194+
std::basic_ostream<Char> &encode_rest(std::basic_ostream<Char> & output) {
195+
detail::state<Char, Value>rest(output);
196+
base64::encode_rest(ostream_iterator<Char>(output), rest);
197+
return output;
198+
}
199+
200+
// Clears the encoding state in the internal array of the output stream.
201+
// Use it to re-use a state object in an unknown state only; Encoding of
202+
// the last chunk must be followed by encode_rest otherwise the end of the
203+
// input sequence may be missing in the encoded output. The encode_rest
204+
// ensures that the rest of the input sequence will be encoded corectly and
205+
// the '=' padding applied as necessary. The encode rest clears the state
206+
// when finished.
207+
//
208+
// std::basic_ostream<Char> & output = ...;
209+
// output << base64::io::encode("ab") << ...;
210+
// output << clear_state<char>;
211+
template<typename Value,typename Char>
212+
std::basic_ostream<Char> &clear_state(std::basic_ostream<Char> & output) {
213+
detail::state<Char, Value>rest(output);
214+
rest.clear();
215+
return output;
216+
}
217+
218+
// Checks if the encoding state in the internal array of the output stream
219+
// is empty.
220+
//
221+
// std::basic_ostream<Char> & output = ...;
222+
// output << base64::io::encode("ab") << ...;
223+
// bool is_complete = base64::io::empty_state<char>(output);
224+
template<typename Value,typename Char>
225+
boolempty_state(std::basic_ostream<Char> & output) {
226+
detail::state<Char, Value>rest(output);
227+
return rest.empty();
228+
}
229+
230+
}// namespace io
231+
}// namespace base64
232+
233+
}// namespace utils
234+
}// namespace network
235+
}// namespace boost
236+
237+
#endif// BOOST_NETWORK_UTILS_BASE64_ENCODE_IO_HPP

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp