| 493 | |
| 494 | template <class OutputBuffer, class InputIterator> |
| 495 | inline OutputBuffer encode_into(InputIterator begin, InputIterator end) { |
| 496 | typedef std::decay_t<decltype(*begin)> input_value_type; |
| 497 | static_assert(std::is_same_v<input_value_type, char> || |
| 498 | std::is_same_v<input_value_type, signed char> || |
| 499 | std::is_same_v<input_value_type, unsigned char> || |
| 500 | std::is_same_v<input_value_type, std::byte>); |
| 501 | typedef typename OutputBuffer::value_type output_value_type; |
| 502 | static_assert(std::is_same_v<output_value_type, char> || |
| 503 | std::is_same_v<output_value_type, signed char> || |
| 504 | std::is_same_v<output_value_type, unsigned char> || |
| 505 | std::is_same_v<output_value_type, std::byte>); |
| 506 | const size_t binarytextsize = end - begin; |
| 507 | const size_t encodedsize = (binarytextsize / 3 + (binarytextsize % 3 > 0)) |
| 508 | << 2; |
| 509 | OutputBuffer encoded(encodedsize, detail::padding_char); |
| 510 | |
| 511 | const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&*begin); |
| 512 | char* currEncoding = reinterpret_cast<char*>(&encoded[0]); |
| 513 | |
| 514 | for (size_t i = binarytextsize / 3; i; --i) { |
| 515 | const uint8_t t1 = *bytes++; |
| 516 | const uint8_t t2 = *bytes++; |
| 517 | const uint8_t t3 = *bytes++; |
| 518 | *currEncoding++ = detail::encode_table_0[t1]; |
| 519 | *currEncoding++ = |
| 520 | detail::encode_table_1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)]; |
| 521 | *currEncoding++ = |
| 522 | detail::encode_table_1[((t2 & 0x0F) << 2) | ((t3 >> 6) & 0x03)]; |
| 523 | *currEncoding++ = detail::encode_table_1[t3]; |
| 524 | } |
| 525 | |
| 526 | switch (binarytextsize % 3) { |
| 527 | case 0: { |
| 528 | break; |
| 529 | } |
| 530 | case 1: { |
| 531 | const uint8_t t1 = bytes[0]; |
| 532 | *currEncoding++ = detail::encode_table_0[t1]; |
| 533 | *currEncoding++ = detail::encode_table_1[(t1 & 0x03) << 4]; |
| 534 | // *currEncoding++ = detail::padding_char; |
| 535 | // *currEncoding++ = detail::padding_char; |
| 536 | break; |
| 537 | } |
| 538 | case 2: { |
| 539 | const uint8_t t1 = bytes[0]; |
| 540 | const uint8_t t2 = bytes[1]; |
| 541 | *currEncoding++ = detail::encode_table_0[t1]; |
| 542 | *currEncoding++ = |
| 543 | detail::encode_table_1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)]; |
| 544 | *currEncoding++ = detail::encode_table_1[(t2 & 0x0F) << 2]; |
| 545 | // *currEncoding++ = detail::padding_char; |
| 546 | break; |
| 547 | } |
| 548 | default: { |
| 549 | throw std::runtime_error{"Invalid base64 encoded data"}; |
| 550 | } |
| 551 | } |
| 552 | |