Decode a base64 encoded string * * @param[in] str Base64 encoded string to decode * * @return The decode string in case of a valid, non-empty string otherwise an empty string */
| 56 | * @return The decode string in case of a valid, non-empty string otherwise an empty string |
| 57 | */ |
| 58 | std::string decode_base64(const std::string &str) |
| 59 | { |
| 60 | constexpr const char pad_char = '='; |
| 61 | |
| 62 | // Handle empty string |
| 63 | if (str.empty()) |
| 64 | { |
| 65 | return {}; |
| 66 | } |
| 67 | |
| 68 | // Base64 encoded string has size multiple of 4 |
| 69 | if (str.length() % 4) |
| 70 | { |
| 71 | return {}; |
| 72 | } |
| 73 | |
| 74 | // |
| 75 | // Check encoded string padding |
| 76 | std::size_t padding = (str.rbegin()[0] == pad_char) + (str.rbegin()[1] == pad_char); |
| 77 | const int str_len = str.size(); |
| 78 | |
| 79 | // Reserve memory for the decoded string |
| 80 | // Note each 4 consecutive elements of 6-bit encode 3 bytes |
| 81 | std::string dec_b64; |
| 82 | dec_b64.reserve(((str_len / 4) * 3)); |
| 83 | |
| 84 | // Block decoding function (exclude padding) |
| 85 | int c = 0; |
| 86 | const int end = str_len - 4 - padding; |
| 87 | for (; c <= end; c += 4) |
| 88 | { |
| 89 | const int byte0 = b64_invtab[str[c]]; |
| 90 | const int byte1 = b64_invtab[str[c + 1]]; |
| 91 | const int byte2 = b64_invtab[str[c + 2]]; |
| 92 | const int byte3 = b64_invtab[str[c + 3]]; |
| 93 | |
| 94 | dec_b64.push_back((byte0 << 2) | (byte1 >> 4)); |
| 95 | dec_b64.push_back((byte1 << 4) | (byte2 >> 2)); |
| 96 | dec_b64.push_back((byte2 << 6) | (byte3)); |
| 97 | } |
| 98 | |
| 99 | // Last step that might contain padding symbols |
| 100 | if (padding == 1) |
| 101 | { |
| 102 | const int byte0 = b64_invtab[str[c]]; |
| 103 | const int byte1 = b64_invtab[str[c + 1]]; |
| 104 | const int byte2 = b64_invtab[str[c + 2]]; |
| 105 | |
| 106 | dec_b64.push_back((byte0 << 2) | (byte1 >> 4)); |
| 107 | dec_b64.push_back((byte1 << 4) | (byte2 >> 2)); |
| 108 | } |
| 109 | else if (padding == 2) |
| 110 | { |
| 111 | const int byte0 = b64_invtab[str[c]]; |
| 112 | const int byte1 = b64_invtab[str[c + 1]]; |
| 113 | |
| 114 | dec_b64.push_back((byte0 << 2) | (byte1 >> 4)); |
| 115 | } |