From d7def063b6868955a67d4e00862a36641f5d7ea2 Mon Sep 17 00:00:00 2001 From: Jason Volk <jason@zemos.net> Date: Fri, 22 Sep 2017 15:50:28 -0700 Subject: [PATCH] ircd: Add tools for binary/hex/b64 conversions. --- include/ircd/lexical.h | 16 ++++++++ ircd/lexical.cc | 89 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/include/ircd/lexical.h b/include/ircd/lexical.h index 6bf080562..ae4ad7020 100644 --- a/include/ircd/lexical.h +++ b/include/ircd/lexical.h @@ -87,6 +87,22 @@ namespace ircd const size_t LEX_CAST_BUFS {256}; // plenty template<class T> string_view lex_cast(const T &t); + // + // Binary / Hex / Base64 conversion suite + // + + // Binary buffer to null terminated string of hex (out must be 2*in + 1). + string_view u2a(const mutable_buffer &out, const uint8_t *const &in, const size_t &len); + string_view u2a(const mutable_buffer &out, const const_buffer &in); + + // String of hex to binary buffer. + const_buffer a2u(uint8_t *const &out, const size_t &max, const const_buffer &in); + const_buffer a2u(const mutable_buffer &out, const const_buffer &in); + + // Binary buffer to string of base64 + string_view b64encode(const mutable_buffer &out, const uint8_t *const &in, const size_t &len); + string_view b64encode(const mutable_buffer &out, const const_buffer &in); + // // String tokenization. // diff --git a/ircd/lexical.cc b/ircd/lexical.cc index 23af92af5..c37945b5e 100644 --- a/ircd/lexical.cc +++ b/ircd/lexical.cc @@ -22,6 +22,10 @@ #include <RB_INC_BOOST_TOKENIZER_HPP #include <RB_INC_BOOST_LEXICAL_CAST_HPP +#include <boost/archive/iterators/base64_from_binary.hpp> +#include <boost/archive/iterators/insert_linebreaks.hpp> +#include <boost/archive/iterators/transform_width.hpp> +#include <boost/archive/iterators/ostream_iterator.hpp> ircd::string_view ircd::tokens_after(const string_view &str, @@ -231,6 +235,91 @@ ircd::tokens(const string_view &str, std::for_each(begin(view), end(view), closure); } +ircd::string_view +ircd::b64encode(const mutable_buffer &out, + const const_buffer &in) +{ + const auto ptr + { + reinterpret_cast<const uint8_t *>(data(in)) + }; + + return b64encode(out, ptr, size(in)); +} + +ircd::string_view +ircd::b64encode(const mutable_buffer &out, + const uint8_t *const &in, + const size_t &len) +{ + + using transform = boost::archive::iterators::transform_width<unsigned char *, 6, 8>; + using b64fb = boost::archive::iterators::base64_from_binary<transform>; + using ostream_iterator = boost::archive::iterators::ostream_iterator<char>; + + std::stringstream ss; + std::copy(b64fb(in), b64fb(in + len), ostream_iterator(ss)); + const auto outlen(ss.str().copy(data(out), size(out))); + return { data(out), outlen }; +} + +ircd::const_buffer +ircd::a2u(const mutable_buffer &out, + const const_buffer &in) +{ + const auto ptr + { + reinterpret_cast<uint8_t *>(data(out)) + }; + + return a2u(ptr, size(out), in); +} + +ircd::const_buffer +ircd::a2u(uint8_t *const &out, + const size_t &max, + const const_buffer &in) +{ + const size_t len{size(in) / 2}; + for(size_t i(0); i < len; ++i) + { + const char gl[3] + { + in[i * 2], + in[i * 2 + 1], + '\0' + }; + + out[i] = strtol(gl, nullptr, 16); + } + + return { reinterpret_cast<const char *>(out), len }; +} + +ircd::string_view +ircd::u2a(const mutable_buffer &out, + const const_buffer &in) +{ + const auto ptr + { + reinterpret_cast<const uint8_t *>(data(in)) + }; + + return u2a(out, ptr, size(in)); +} + +ircd::string_view +ircd::u2a(const mutable_buffer &out, + const uint8_t *const &in, + const size_t &len) +{ + char *p(data(out)); + for(size_t i(0); i < len; ++i) + p += snprintf(p, size(out) - (p - data(out)), "%02x", in[i]); + + return { data(out), size_t(p - data(out)) }; +} + namespace ircd { const size_t LEX_CAST_BUFSIZE {64};