Skip to main content
added 51 characters in body
Source Link
Snowhawk
  • 6.4k
  • 1
  • 18
  • 36

Instead of cycling through each branch on every loop until you get to the sextet you are at, consider a modulo approach. Loop through full sextetssextet groups until you have a partial sextet group left at the end (the remainder). Then you can branch based on what you have left.

Instead of cycling through each branch on every loop, consider a modulo approach. Loop through full sextets until you have a partial sextet left at the end (the remainder). Then you can branch based on what you have left.

Instead of cycling through each branch on every loop until you get to the sextet you are at, consider a modulo approach. Loop through full sextet groups until you have a partial sextet group left at the end (the remainder). Then you can branch based on what you have left.

Source Link
Snowhawk
  • 6.4k
  • 1
  • 18
  • 36

    Base64Encoder() = default;
    ~Base64Encoder() = default;

In general, if you want to explicitly provide special member functions, then explicitly provide them all. Others will advise that if you can avoid defining the special member functions, then do so. Read more here.

class Base64Encoder {
public:
    // ... no default operations declared ...
    const std::string encode(const std::string s) const;

private:
    // ...

    const std::string encode(const std::string s) const;

std::string requires <string> be included.

s is passed by value to const, which incurs an unnecessary copy. Consider using std::string_view if you have . Read more here.

    std::string encode(const std::string_view s) const;

Otherwise, pass by reference to const.

    std::string encode(const std::string& s) const;

    constexpr static unsigned char get_base_64_char(ulong number_of_char) {
        return base64_table.at(number_of_char);
    }

ulong is not a standard unsigned integer type. If you need a fixed-size integer, consider one of the types from <cstdint> (e.g. std::uint8_t). For this use-case, I'd just use std::size_t.

Is number_of_char a clear description of what the value represents? Would index be clearer?

Do you need the bounds checking of base64_table.at()?


    const static unsigned char next_ascii(size_t current_index, const std::string s, size_t length_of_s);

The first const is unnecessary.

size_t is not guaranteed by the standard to exist in the global namespace. Use std::size_t and include <cstddef>. Read more here.


    const static size_t MINIMAL_B64_STRING_LENGTH = 4;

Consider reserving upper case names for the preprocessor.

constexpr?


    std::stringstream encoding;

Do we need a std::stringstream? We can actually calculate the destination buffer length. For base64 encoding, every 3 octets maps to 4 sextets. To find the encoded length \$m\$, find the total number of octets to be read (integral ceiling) and multiply it by the length of each sextet.

$$m = 4 \dot ((n + 2) / 3)$$


    while (i < length_of_s) {
        // if first sextet, ...
        // else if second sextet, ...
        // else if third sextet, ...
        // else must be fourth sextet ...
    }

Instead of cycling through each branch on every loop, consider a modulo approach. Loop through full sextets until you have a partial sextet left at the end (the remainder). Then you can branch based on what you have left.

    for (auto remaining_sextets = s.size() / 3; remaining_sextets--;) {
        encoded += /* first sextet masked and shifted */
        encoded += /* second sextet masked and shifted */
        encoded += /* third sextet masked and shifted */
        encoded += /* fourth sextet masked and shifted */
    }

    switch (len % 3) {
    case 2:
        encoded += /* first sextet masked and shifted */
        encoded += /* second sextet masked and shifted */
        encoded += /* third sextet masked and shifted */
        encoded += '=';
        break;
    case 1:
        encoded += /* first sextet masked and shifted */
        encoded += /* second sextet masked and shifted */
        encoded += '=';
        encoded += '=';
        break;
    case 0:
        break;
    }

    return encoded;