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

Initial version of base64 encoding#300

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
deanberris merged 5 commits intocpp-netlib:0.10-develfromprantlf:base64_util
Sep 15, 2013
Merged
Changes from1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
PrevPrevious commit
NextNext commit
Add the first version of the stream manipulators performing the BASE6…
…4 encoding
  • Loading branch information
@prantlf
prantlf committedSep 14, 2013
commit153d203e1d96b9910d1e3169511708728f905ce0
237 changes: 237 additions & 0 deletionsboost/network/utils/base64/encode-io.hpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
#ifndef BOOST_NETWORK_UTILS_BASE64_ENCODE_IO_HPP
#define BOOST_NETWORK_UTILS_BASE64_ENCODE_IO_HPP

#include <boost/network/utils/base64/encode.hpp>
#include <boost/archive/iterators/ostream_iterator.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <iterator>

namespace boost {
namespace network {
namespace utils {

// Offers an interface to the BASE64 converter from encode.hpp, which is
// based on stream manipulators to be friendly to the usage with output
// streams combining heterogenous output by using the output operators.
// The encoding state is serialized to long and maintained in te extensible
// internal array of the output stream.
//
// Summarized interface - ostream manipulators and one function:
//
// encode(InputIterator begin, InputIterator end)
// encode(InputRange const & value)
// encode(char const * value)
// encode_rest
// clear_state
// bool empty_state(std::basic_ostream<Char> & output)

namespace base64 {
namespace io {

// force using the ostream_iterator from boost::archive to write wide
// characters reliably, althoth wchar_t may not be a native character type
using namespace boost::archive::iterators;

namespace detail {

// Enables transferring of the input sequence for the BASE64 encoding into
// the ostream operator defined for it, which performs the operation. It
// is to be used from ostream manipulators.
//
// std::basic_ostream<Char> & output = ...;
// output << input_wrapper<InputIterator>(value.begin(), value.end());
template <typename InputIterator>
struct input_wrapper {
input_wrapper(InputIterator begin, InputIterator end)
: begin(begin), end(end) {}

private:
InputIterator begin, end;

// only encoding of an input sequence needs access to it
template <
typename Char,
typename InputIterator2
>
friend std::basic_ostream<Char> &
operator <<(std::basic_ostream<Char> & output,
input_wrapper<InputIterator2> input_wrapper);
};

// The output stream state should be used only in a single scope around
// encoding operations. Constructor performs initialization from the
// output stream internal extensible array and destructor updates it
// according to the encoding result. It inherits from the base64::state
// to gain access to its protected members and allow easy value passing
// to base64::encode.
//
//
// std::basic_ostream<Char> & output = ...;
// {
// state<Char, Value> rest(output);
// base64::encode(..., ostream_iterator<Char>(output), rest);
// }
template <typename Char, typename Value>
struct state : public boost::network::utils::base64::state<Value> {
typedef boost::network::utils::base64::state<Value> super_t;

// initialize the (inherited) contents of the base64::state<> from the
// output stream internal extensible array
state(std::basic_ostream<Char> & output) : super_t(), output(output) {
const unsigned triplet_index_size = sizeof(super_t::triplet_index) * 8;
unsigned long data = static_cast<unsigned long>(storage());
// mask the long value with the bit-size of the triplet_index member
super_t::triplet_index = data & ((1 << triplet_index_size) - 1);
// shift the long value right to remove the the triplet_index value;
// masking is not necessary because the last_encoded_value it is the
// last record stored in the data value
super_t::last_encoded_value = data >> triplet_index_size;
}

// update the value in the output stream internal extensible array by
// the last (inherited) contents of the base64::state<>
~state() {
const unsigned triplet_index_size = sizeof(super_t::triplet_index) * 8;
// store the last_encoded_value in the data value first
unsigned long data =
static_cast<unsigned long>(super_t::last_encoded_value);
// shift the long data value left to make place for storing the
// full triplet_index value there
data <<= triplet_index_size;
data |= static_cast<unsigned long>(super_t::triplet_index);
storage() = static_cast<long>(data);
}

private:
// all data of the base64::state<> must be serializable into a long
// value allocated in the output stream internal extensible array
BOOST_STATIC_ASSERT(sizeof(super_t) <= sizeof(long));

// allow only the construction with an output stream (strict RAII)
state();
state(state<Char, Value> const & source);

std::basic_ostream<Char> & output;

long & storage() {
static int index = std::ios_base::xalloc();
return output.iword(index);
}
};

// Output operator implementing the BASE64 encoding for an input sequence
// which was wrapped by the ostream manipulator; the state must be preserved
// because multiple sequences can be sent in the ouptut by this operator.
template <
typename Char,
typename InputIterator
>
std::basic_ostream<Char> &
operator <<(std::basic_ostream<Char> & output,
input_wrapper<InputIterator> input) {
typedef typename iterator_value<InputIterator>::type value_type;
state<Char, value_type> rest(output);
base64::encode(input.begin, input.end, ostream_iterator<Char>(output), rest);
return output;
}

} // namespace detail

// Encoding ostream manipulator for sequences specified by the pair of begin
// and end iterators.
//
// std::vector<unsigned char> buffer = ...;
// std::basic_ostream<Char> & output = ...;
// output << base64::io::encode(buffer.begin(), buffer.end()) << ... <<
// base64::io::encode_rest<unsigned char>;
template <typename InputIterator>
detail::input_wrapper<InputIterator> encode(InputIterator begin,
InputIterator end) {
return detail::input_wrapper<InputIterator>(begin, end);
}

// Encoding ostream manipulator processing whole sequences which either
// support begin() and end() methods returning boundaries of the sequence
// or the boundaries can be computed by the Boost::Range.
//
// Warning: Buffers identified by C-pointers are processed including their
// termination character, if they have any. This is unexpected at least
// for the storing literals, which have a specialization here to avoid it.
//
// std::vector<unsigned char> buffer = ...;
// std::basic_ostream<Char> & output = ...;
// output << base64::io::encode(buffer) << ... <<
// base64::io::encode_rest<unsigned char>;
template <typename InputRange>
detail::input_wrapper<typename boost::range_const_iterator<InputRange>::type>
encode(InputRange const & value) {
typedef typename boost::range_const_iterator<InputRange>::type InputIterator;
return detail::input_wrapper<InputIterator>(boost::begin(value),
boost::end(value));
}

// Encoding ostream manipulator processing string literals; the usual
// expectation from their encoding is processing only the string content
// without the terminating zero character.
//
// std::basic_ostream<Char> & output = ...;
// output << base64::io::encode("ab") << ... << base64::io::encode_rest<char>;
inline detail::input_wrapper<char const *> encode(char const * value) {
return detail::input_wrapper<char const *>(value, value + strlen(value));
}

// Encoding ostream manipulator which finishes encoding of the previously
// processed chunks. If their total byte-length was divisible by three,
// nothing is needed, if not, the last quantum will be encoded as if padded
// with zeroes, which will be indicated by appending '=' characters to the
// output. This manipulator must be always used at the end of encoding,
// after previous usages of the encode manipulator.
//
// std::basic_ostream<Char> & output = ...;
// output << base64::io::encode("ab") << ... << base64::io::encode_rest<char>;
template <typename Value, typename Char>
std::basic_ostream<Char> & encode_rest(std::basic_ostream<Char> & output) {
detail::state<Char, Value> rest(output);
base64::encode_rest(ostream_iterator<Char>(output), rest);
return output;
}

// Clears the encoding state in the internal array of the output stream.
// Use it to re-use a state object in an unknown state only; Encoding of
// the last chunk must be followed by encode_rest otherwise the end of the
// input sequence may be missing in the encoded output. The encode_rest
// ensures that the rest of the input sequence will be encoded corectly and
// the '=' padding applied as necessary. The encode rest clears the state
// when finished.
//
// std::basic_ostream<Char> & output = ...;
// output << base64::io::encode("ab") << ...;
// output << clear_state<char>;
template <typename Value, typename Char>
std::basic_ostream<Char> & clear_state(std::basic_ostream<Char> & output) {
detail::state<Char, Value> rest(output);
rest.clear();
return output;
}

// Checks if the encoding state in the internal array of the output stream
// is empty.
//
// std::basic_ostream<Char> & output = ...;
// output << base64::io::encode("ab") << ...;
// bool is_complete = base64::io::empty_state<char>(output);
template <typename Value, typename Char>
bool empty_state(std::basic_ostream<Char> & output) {
detail::state<Char, Value> rest(output);
return rest.empty();
}

} // namespace io
} // namespace base64

} // namespace utils
} // namespace network
} // namespace boost

#endif // BOOST_NETWORK_UTILS_BASE64_ENCODE_IO_HPP

[8]ページ先頭

©2009-2025 Movatter.jp