mirror of https://github.com/oxen-io/oxen-mq.git
Add it pair versions of {to,from}_{hex,base32z,base64}
Previously you could only generate a string from a string_view, or could manage the string yourself and pass input iterators plus an output iterator. This commit adds an intermediate version that creates a string from a pair of input iterators.
This commit is contained in:
parent
f296b82ba5
commit
1479a030d7
|
@ -100,14 +100,19 @@ void to_base32z(InputIt begin, InputIt end, OutputIt out) {
|
|||
*out++ = detail::b32z_lut.to_b32z(r << (5 - bits));
|
||||
}
|
||||
|
||||
/// Creates a base32z string from an iterable, std::string-like object
|
||||
template <typename CharT>
|
||||
std::string to_base32z(std::basic_string_view<CharT> s) {
|
||||
/// Creates a base32z string from an iterator pair of a byte sequence.
|
||||
template <typename It>
|
||||
std::string to_base32z(It begin, It end) {
|
||||
std::string base32z;
|
||||
base32z.reserve((s.size()*8 + 4) / 5); // == bytes*8/5, rounded up.
|
||||
to_base32z(s.begin(), s.end(), std::back_inserter(base32z));
|
||||
if constexpr (std::is_base_of_v<std::random_access_iterator_tag, typename std::iterator_traits<It>::iterator_category>)
|
||||
base32z.reserve((std::distance(begin, end)*8 + 4) / 5); // == bytes*8/5, rounded up.
|
||||
to_base32z(begin, end, std::back_inserter(base32z));
|
||||
return base32z;
|
||||
}
|
||||
|
||||
/// Creates a base32z string from an iterable, std::string-like object
|
||||
template <typename CharT>
|
||||
std::string to_base32z(std::basic_string_view<CharT> s) { return to_base32z(s.begin(), s.end()); }
|
||||
inline std::string to_base32z(std::string_view s) { return to_base32z<>(s); }
|
||||
|
||||
/// Returns true if all elements in the range are base32z characters
|
||||
|
@ -177,15 +182,21 @@ void from_base32z(InputIt begin, InputIt end, OutputIt out) {
|
|||
// character you added isn't there by not doing anything here.
|
||||
}
|
||||
|
||||
/// Convert a base32z sequence into a std::string of bytes. Undefined behaviour if any characters
|
||||
/// are not valid (case-insensitive) base32z characters.
|
||||
template <typename It>
|
||||
std::string from_base32z(It begin, It end) {
|
||||
std::string bytes;
|
||||
if constexpr (std::is_base_of_v<std::random_access_iterator_tag, typename std::iterator_traits<It>::iterator_category>)
|
||||
bytes.reserve((std::distance(begin, end)*5 + 7) / 8); // == chars*5/8, rounded up.
|
||||
from_base32z(begin, end, std::back_inserter(bytes));
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// Converts base32z digits from a std::string-like object into a std::string of bytes. Undefined
|
||||
/// behaviour if any characters are not valid (case-insensitive) base32z characters.
|
||||
template <typename CharT>
|
||||
std::string from_base32z(std::basic_string_view<CharT> s) {
|
||||
std::string bytes;
|
||||
bytes.reserve((s.size()*5 + 7) / 8); // == chars*5/8, rounded up.
|
||||
from_base32z(s.begin(), s.end(), std::back_inserter(bytes));
|
||||
return bytes;
|
||||
}
|
||||
std::string from_base32z(std::basic_string_view<CharT> s) { return from_base32z(s.begin(), s.end()); }
|
||||
inline std::string from_base32z(std::string_view s) { return from_base32z<>(s); }
|
||||
|
||||
}
|
||||
|
|
|
@ -116,14 +116,19 @@ void to_base64(InputIt begin, InputIt end, OutputIt out) {
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates a base64 string from an iterable, std::string-like object
|
||||
template <typename CharT>
|
||||
std::string to_base64(std::basic_string_view<CharT> s) {
|
||||
/// Creates and returns a base64 string from an iterator pair of a character sequence
|
||||
template <typename It>
|
||||
std::string to_base64(It begin, It end) {
|
||||
std::string base64;
|
||||
base64.reserve((s.size() + 2) / 3 * 4);
|
||||
to_base64(s.begin(), s.end(), std::back_inserter(base64));
|
||||
if constexpr (std::is_base_of_v<std::random_access_iterator_tag, typename std::iterator_traits<It>::iterator_category>)
|
||||
base64.reserve((std::distance(begin, end) + 2) / 3 * 4); // bytes*4/3, rounded up to the next multiple of 4
|
||||
to_base64(begin, end, std::back_inserter(base64));
|
||||
return base64;
|
||||
}
|
||||
|
||||
/// Creates a base64 string from an iterable, std::string-like object
|
||||
template <typename CharT>
|
||||
std::string to_base64(std::basic_string_view<CharT> s) { return to_base64(s.begin(), s.end()); }
|
||||
inline std::string to_base64(std::string_view s) { return to_base64<>(s); }
|
||||
|
||||
/// Returns true if the range is a base64 encoded value; we allow (but do not require) '=' padding,
|
||||
|
@ -193,15 +198,21 @@ void from_base64(InputIt begin, InputIt end, OutputIt out) {
|
|||
// character here instead of 5).
|
||||
}
|
||||
|
||||
/// Converts base64 digits from a iterator pair of characters into a std::string of bytes.
|
||||
/// Undefined behaviour if any characters are not valid base64 characters.
|
||||
template <typename It>
|
||||
std::string from_base64(It begin, It end) {
|
||||
std::string bytes;
|
||||
if constexpr (std::is_base_of_v<std::random_access_iterator_tag, typename std::iterator_traits<It>::iterator_category>)
|
||||
bytes.reserve(std::distance(begin, end)*6 / 8); // each digit carries 6 bits; this may overallocate by 1-2 bytes due to padding
|
||||
from_base64(begin, end, std::back_inserter(bytes));
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// Converts base64 digits from a std::string-like object into a std::string of bytes. Undefined
|
||||
/// behaviour if any characters are not valid base64 characters.
|
||||
template <typename CharT>
|
||||
std::string from_base64(std::basic_string_view<CharT> s) {
|
||||
std::string bytes;
|
||||
bytes.reserve(s.size()*6 / 8);
|
||||
from_base64(s.begin(), s.end(), std::back_inserter(bytes));
|
||||
return bytes;
|
||||
}
|
||||
std::string from_base64(std::basic_string_view<CharT> s) { return from_base64(s.begin(), s.end()); }
|
||||
inline std::string from_base64(std::string_view s) { return from_base64<>(s); }
|
||||
|
||||
}
|
||||
|
|
33
lokimq/hex.h
33
lokimq/hex.h
|
@ -71,14 +71,19 @@ void to_hex(InputIt begin, InputIt end, OutputIt out) {
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates a hex string from an iterable, std::string-like object
|
||||
template <typename CharT>
|
||||
std::string to_hex(std::basic_string_view<CharT> s) {
|
||||
/// Creates a string of hex digits from a character sequence iterator pair
|
||||
template <typename It>
|
||||
std::string to_hex(It begin, It end) {
|
||||
std::string hex;
|
||||
hex.reserve(s.size() * 2);
|
||||
to_hex(s.begin(), s.end(), std::back_inserter(hex));
|
||||
if constexpr (std::is_base_of_v<std::random_access_iterator_tag, typename std::iterator_traits<It>::iterator_category>)
|
||||
hex.reserve(2 * std::distance(begin, end));
|
||||
to_hex(begin, end, std::back_inserter(hex));
|
||||
return hex;
|
||||
}
|
||||
|
||||
/// Creates a hex string from an iterable, std::string-like object
|
||||
template <typename CharT>
|
||||
std::string to_hex(std::basic_string_view<CharT> s) { return to_hex(s.begin(), s.end()); }
|
||||
inline std::string to_hex(std::string_view s) { return to_hex<>(s); }
|
||||
|
||||
/// Returns true if all elements in the range are hex characters
|
||||
|
@ -119,15 +124,21 @@ void from_hex(InputIt begin, InputIt end, OutputIt out) {
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts a sequence of hex digits to a string of bytes and returns it. Undefined behaviour if
|
||||
/// the input sequence is not an even-length sequence of [0-9a-fA-F] characters.
|
||||
template <typename It>
|
||||
std::string from_hex(It begin, It end) {
|
||||
std::string bytes;
|
||||
if constexpr (std::is_base_of_v<std::random_access_iterator_tag, typename std::iterator_traits<It>::iterator_category>)
|
||||
bytes.reserve(std::distance(begin, end) / 2);
|
||||
from_hex(begin, end, std::back_inserter(bytes));
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// Converts hex digits from a std::string-like object into a std::string of bytes. Undefined
|
||||
/// behaviour if any characters are not in [0-9a-fA-F] or if the input sequence length is not even.
|
||||
template <typename CharT>
|
||||
std::string from_hex(std::basic_string_view<CharT> s) {
|
||||
std::string bytes;
|
||||
bytes.reserve(s.size() / 2);
|
||||
from_hex(s.begin(), s.end(), std::back_inserter(bytes));
|
||||
return bytes;
|
||||
}
|
||||
std::string from_hex(std::basic_string_view<CharT> s) { return from_hex(s.begin(), s.end()); }
|
||||
inline std::string from_hex(std::string_view s) { return from_hex<>(s); }
|
||||
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ TEST_CASE("hex encoding/decoding", "[encoding][decoding][hex]") {
|
|||
lokimq::to_hex(chars.begin(), chars.end(), out.begin());
|
||||
REQUIRE( out == expected );
|
||||
|
||||
REQUIRE( lokimq::to_hex(chars.begin(), chars.end()) == "010a64fe" );
|
||||
|
||||
REQUIRE( lokimq::from_hex("12345678ffEDbca9") == "\x12\x34\x56\x78\xff\xed\xbc\xa9"s );
|
||||
|
||||
REQUIRE( lokimq::is_hex("1234567890abcdefABCDEF1234567890abcdefABCDEF") );
|
||||
|
@ -28,6 +30,8 @@ TEST_CASE("hex encoding/decoding", "[encoding][decoding][hex]") {
|
|||
REQUIRE( lokimq::from_hex(pk_hex) == pk );
|
||||
REQUIRE( lokimq::to_hex(pk) == pk_hex );
|
||||
|
||||
REQUIRE( lokimq::from_hex(pk_hex.begin(), pk_hex.end()) == pk );
|
||||
|
||||
std::vector<std::byte> bytes{{std::byte{0xff}, std::byte{0x42}, std::byte{0x12}, std::byte{0x34}}};
|
||||
std::basic_string_view<std::byte> b{bytes.data(), bytes.size()};
|
||||
REQUIRE( lokimq::to_hex(b) == "ff421234"s );
|
||||
|
@ -77,7 +81,15 @@ TEST_CASE("base32z encoding/decoding", "[encoding][decoding][base32z]") {
|
|||
REQUIRE( lokimq::to_base32z(lokimq::from_base32z("ybndrf4"s)) == "ybndrfa" );
|
||||
|
||||
REQUIRE( lokimq::to_base32z(pk) == pk_b32z );
|
||||
REQUIRE( lokimq::to_base32z(pk.begin(), pk.end()) == pk_b32z );
|
||||
REQUIRE( lokimq::from_base32z(pk_b32z) == pk );
|
||||
REQUIRE( lokimq::from_base32z(pk_b32z.begin(), pk_b32z.end()) == pk );
|
||||
|
||||
std::string pk_b32z_again, pk_again;
|
||||
lokimq::to_base32z(pk.begin(), pk.end(), std::back_inserter(pk_b32z_again));
|
||||
lokimq::from_base32z(pk_b32z.begin(), pk_b32z.end(), std::back_inserter(pk_again));
|
||||
REQUIRE( pk_b32z_again == pk_b32z );
|
||||
REQUIRE( pk_again == pk );
|
||||
|
||||
std::vector<std::byte> bytes{{std::byte{0}, std::byte{255}}};
|
||||
std::basic_string_view<std::byte> b{bytes.data(), bytes.size()};
|
||||
|
@ -159,7 +171,15 @@ TEST_CASE("base64 encoding/decoding", "[encoding][decoding][base64]") {
|
|||
"any carnal pleasure.");
|
||||
|
||||
REQUIRE( lokimq::to_base64(pk) == pk_b64 );
|
||||
REQUIRE( lokimq::to_base64(pk.begin(), pk.end()) == pk_b64 );
|
||||
REQUIRE( lokimq::from_base64(pk_b64) == pk );
|
||||
REQUIRE( lokimq::from_base64(pk_b64.begin(), pk_b64.end()) == pk );
|
||||
|
||||
std::string pk_b64_again, pk_again;
|
||||
lokimq::to_base64(pk.begin(), pk.end(), std::back_inserter(pk_b64_again));
|
||||
lokimq::from_base64(pk_b64.begin(), pk_b64.end(), std::back_inserter(pk_again));
|
||||
REQUIRE( pk_b64_again == pk_b64 );
|
||||
REQUIRE( pk_again == pk );
|
||||
|
||||
std::vector<std::byte> bytes{{std::byte{0}, std::byte{255}}};
|
||||
std::basic_string_view<std::byte> b{bytes.data(), bytes.size()};
|
||||
|
|
Loading…
Reference in New Issue