forked fromglynos/cpp-netlib
- Notifications
You must be signed in to change notification settings - Fork425
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
Uh oh!
There was an error while loading.Please reload this page.
Merged
Changes from1 commit
Commits
Show all changes
5 commits Select commitHold shift + click to select a range
9328c7e Add the first version of the BASE64 encoding functions
prantlf153d203 Add the first version of the stream manipulators performing the BASE6…
prantlf95137e2 Add tests for the BASE64 encoding
prantlfc98c471 Add experimental implementations of BASE64 encoding with a testing/be…
prantlfefd0c27 Remove padding_length() from the encoding state; the count of padding…
prantlfFile filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
Add experimental implementations of BASE64 encoding with a testing/be…
…nchmarking tool and conclusion
- Loading branch information
Uh oh!
There was an error while loading.Please reload this page.
commitc98c4714c74ed781fdab0ca7f79b18fbcacd8b0a
There are no files selected for viewing
1 change: 1 addition & 0 deletionsCMakeLists.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletionslibs/network/experiment/CMakeLists.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| # Copyright (c) Dean Michael Berris 2010. | ||
| # Distributed under the Boost Software License, Version 1.0. | ||
| # (See accompanying file LICENSE_1_0.txt or copy at | ||
| # http://www.boost.org/LICENSE_1_0.txt) | ||
| include_directories(${CPP-NETLIB_SOURCE_DIR}) | ||
| set(CMAKE_BUILD_TYPE Release) | ||
| if (Boost_FOUND) | ||
| add_executable(cpp-netlib-utils_base64_experiment utils_base64_experiment.cpp) | ||
| target_link_libraries(cpp-netlib-utils_base64_experiment ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) | ||
| if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") | ||
| target_link_libraries(cpp-netlib-utils_base64_experiment rt) | ||
| endif() | ||
| set_target_properties(cpp-netlib-utils_base64_experiment | ||
| PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) | ||
| endif() |
426 changes: 426 additions & 0 deletionslibs/network/experiment/utils/base64-standalone.hpp
Large diffs are not rendered by default.
Oops, something went wrong.
Uh oh!
There was an error while loading.Please reload this page.
252 changes: 252 additions & 0 deletionslibs/network/experiment/utils/base64-stateful_buffer.hpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,252 @@ | ||
| #ifndef BOOST_NETWORK_UTILS_BASE64_STATEFUL_BUFFER_HPP | ||
| #define BOOST_NETWORK_UTILS_BASE64_STATEFUL_BUFFER_HPP | ||
| #include <boost/archive/iterators/base64_from_binary.hpp> | ||
| #include <boost/archive/iterators/transform_width.hpp> | ||
| #include <boost/range/begin.hpp> | ||
| #include <boost/range/end.hpp> | ||
| #include <boost/array.hpp> | ||
| #include <algorithm> | ||
| #include <iterator> | ||
| #include <string> | ||
| namespace boost { | ||
| namespace network { | ||
| namespace utils { | ||
| // Uses base64_from_binary and transform_width to implement a BASE64 | ||
| // converter working on an iterator range. Because the transform_width | ||
| // encodes immediately every input byte, while the BASE64 encoding processes | ||
| // the input by byte-triplets, if the input sequence does not end at the | ||
| // three-byte boundary, the rest is remembered in an encoding state to | ||
| // be able to continue with the next chunk. It uses an internal buffer | ||
| // of 4095 input octets to be able to read the input by octet-triplets. | ||
| // | ||
| // Summarized interface: | ||
| // | ||
| // struct state<Value> { | ||
| // bool empty () const; | ||
| // void clear(); | ||
| // } | ||
| // | ||
| // OutputIterator encode(InputIterator begin, InputIterator end, | ||
| // OutputIterator output, State & rest) | ||
| // OutputIterator encode_rest(OutputIterator output, State & rest) | ||
| // OutputIterator encode(InputRange const & input, OutputIterator output, | ||
| // State & rest) | ||
| // OutputIterator encode(char const * value, OutputIterator output, | ||
| // state<char> & rest) | ||
| // std::basic_string<Char> encode(InputRange const & value, State & rest) | ||
| // std::basic_string<Char> encode(char const * value, state<char> & rest) | ||
| // | ||
| // OutputIterator encode(InputIterator begin, InputIterator end, | ||
| // OutputIterator output) | ||
| // OutputIterator encode(InputRange const & input, OutputIterator output) | ||
| // OutputIterator encode(char const * value, OutputIterator output) | ||
| // std::basic_string<Char> encode(InputRange const & value) | ||
| // std::basic_string<Char> encode(char const * value) { | ||
| namespace base64_stateful_buffer { | ||
| // 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; | ||
| template <typename Value> | ||
| struct state { | ||
| state() : size(0) {} | ||
| state(state<Value> const & source) | ||
| : data(source.data), size(source.size) {} | ||
| bool empty() const { return size == 0; } | ||
| void clear() { size = 0; } | ||
| private: | ||
| typedef boost::array<Value, 3> data_type; | ||
| typedef typename data_type::const_iterator const_iterator_type; | ||
| template <typename InputIterator> | ||
| void fill(InputIterator begin, InputIterator end) { | ||
| // make sure that there is always zero padding for the incomplete | ||
| // triplet; the encode will read three bytes from the vector | ||
| data.fill(0); | ||
| size = std::copy(begin, end, data.begin()) - data.begin(); | ||
| } | ||
| template <typename OutputIterator> | ||
| OutputIterator write(OutputIterator output) { | ||
| return std::copy(data.begin(), data.begin() + size, output); | ||
| } | ||
| const_iterator_type begin() const { return data.begin(); } | ||
| const_iterator_type end() const { return data.begin() + size; } | ||
| data_type data; | ||
| std::size_t size; | ||
| template < | ||
| typename InputIterator, | ||
| typename OutputIterator, | ||
| typename State | ||
| > | ||
| friend OutputIterator encode(InputIterator begin, | ||
| InputIterator end, | ||
| OutputIterator output, | ||
| State & rest); | ||
| template < | ||
| typename State, | ||
| typename OutputIterator | ||
| > | ||
| friend OutputIterator encode_rest(OutputIterator output, | ||
| State & rest); | ||
| }; | ||
| template < | ||
| typename InputIterator, | ||
| typename OutputIterator, | ||
| typename State | ||
| > | ||
| OutputIterator encode(InputIterator begin, | ||
| InputIterator end, | ||
| OutputIterator output, | ||
| State & rest) { | ||
| typedef typename iterator_value<InputIterator>::type value_type; | ||
| // declare the buffer type for 1365 octet triplets; make sure that the | ||
| // number is divisible by three if you change it (!) | ||
| const std::size_t BufferSize = 4095; | ||
| BOOST_STATIC_ASSERT(BufferSize / 3 * 3 == BufferSize); | ||
| typedef boost::array<value_type, BufferSize> buffer_type; | ||
| // declare the encoding iterator type | ||
| typedef base64_from_binary< | ||
| transform_width<InputIterator, 6, 8> | ||
| > base64_text; | ||
| if (begin != end) { | ||
| // declare the buffer, a variable to remmeber its size and the size | ||
| // which can be encoded (the nearest lower size divisible by three) | ||
| buffer_type buffer; | ||
| std::size_t buffer_size = 0, encode_size = 0; | ||
| // if the previous state contained an incomplete octet triplet, put | ||
| // it to the start of the buffer to get it prepended to the input | ||
| if (!rest.empty()) { | ||
| buffer_size = rest.size; | ||
| rest.write(buffer.begin()); | ||
| rest.clear(); | ||
| } | ||
| // iterate over the entire input | ||
| while (begin != end) { | ||
| // fill the buffer with the input as much as possible | ||
| while (begin != end && buffer_size < buffer.size()) | ||
| buffer[buffer_size++] = *begin++; | ||
| // if the buffer could not be filled completely, compute | ||
| // the size which can be encoded immediately. | ||
| encode_size = buffer_size / 3 * 3; | ||
| if (encode_size > 0) { | ||
| // encode the buffer part of the size divisible by three | ||
| base64_text base64_begin(buffer.begin()), | ||
| base64_end(buffer.begin() + encode_size); | ||
| output = std::copy(base64_begin, base64_end, output); | ||
| // zero the buffer size to prepare for the next iteration | ||
| buffer_size = 0; | ||
| } | ||
| } | ||
| // if the complete buffer could not be encoded, store the last | ||
| // incomplete octet triplet to the transiting state | ||
| if (buffer_size > encode_size) | ||
| rest.fill(buffer.begin() + encode_size, | ||
| buffer.begin() + buffer_size); | ||
| } | ||
| return output; | ||
| } | ||
| template < | ||
| typename State, | ||
| typename OutputIterator | ||
| > | ||
| OutputIterator encode_rest(OutputIterator output, | ||
| State & rest) { | ||
| typedef typename State::const_iterator_type iterator_type; | ||
| // declare the encoding iterator type | ||
| typedef base64_from_binary< | ||
| transform_width<iterator_type, 6, 8> | ||
| > base64_text; | ||
| if (!rest.empty()) { | ||
| // encode the incomplete octet triplet using zeros as padding | ||
| // (an artificial input continuation) | ||
| base64_text base64_begin(rest.begin()), base64_end(rest.end()); | ||
| output = std::copy(base64_begin, base64_end, output); | ||
| // at least one padding '=' will be always needed - at least two | ||
| // bits are missing in the finally encoded 6-bit value | ||
| if (rest.size > 0) { | ||
| *output++ = '='; | ||
| // if the last octet was the first in the triplet (the index was, | ||
| // four bits are missing in the finally encoded 6-bit value; | ||
| // another '=' character is needed for the another two bits | ||
| if (rest.size == 1) | ||
| *output++ = '='; | ||
| } | ||
| rest.clear(); | ||
| } | ||
| return output; | ||
| } | ||
| template < | ||
| typename InputIterator, | ||
| typename OutputIterator | ||
| > | ||
| OutputIterator encode(InputIterator begin, | ||
| InputIterator end, | ||
| OutputIterator output) { | ||
| state<typename iterator_value<InputIterator>::type> rest; | ||
| output = encode(begin, end, output, rest); | ||
| return encode_rest(output, rest); | ||
| } | ||
| template < | ||
| typename InputRange, | ||
| typename OutputIterator | ||
| > | ||
| OutputIterator encode(InputRange const & value, | ||
| OutputIterator output) { | ||
| return encode(boost::begin(value), boost::end(value), output); | ||
| } | ||
| template <typename OutputIterator> | ||
| OutputIterator encode(char const * value, | ||
| OutputIterator output) { | ||
| return encode(value, value + strlen(value), output); | ||
| } | ||
| template < | ||
| typename Char, | ||
| typename InputRange | ||
| > | ||
| std::basic_string<Char> encode(InputRange const & value) { | ||
| std::basic_string<Char> result; | ||
| encode(value, std::back_inserter(result)); | ||
| return result; | ||
| } | ||
| template <typename Char> | ||
| std::basic_string<Char> encode(char const * value) { | ||
| std::basic_string<Char> result; | ||
| encode(value, std::back_inserter(result)); | ||
| return result; | ||
| } | ||
| // the function overloads for string literals encode the input without | ||
| // the terminating zero, which is usually expected, because the trailing | ||
| // zero byte is not considered a part of the string value; the overloads | ||
| // foran input range would wrap the string literal by Boost.Range and | ||
| // encodethe full memory occupated by the string literal - including the | ||
| // unwanted last zero byte | ||
| } // namespace base64_stateful_buffer | ||
| } // namespace utils | ||
| } // namespace network | ||
| } // namespace boost | ||
| #endif // BOOST_NETWORK_UTILS_BASE64_STATEFUL_BUFFER_HPP |
Oops, something went wrong.
Uh oh!
There was an error while loading.Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.