| 116 | } |
| 117 | |
| 118 | std::vector<uint8_t> Base64::decode(const std::string_view base64String) { |
| 119 | if (base64String.size() == 0) { |
| 120 | return std::vector<uint8_t>{}; |
| 121 | } |
| 122 | if (!is_valid_base64_str(base64String)) { |
| 123 | throw std::runtime_error{"Invalid base64 string"}; |
| 124 | } |
| 125 | |
| 126 | const auto unpadded = base64String.substr(0, base64String.find_first_of('=')); |
| 127 | const auto full_quads = unpadded.size() / 4; |
| 128 | |
| 129 | // 4 base64 characters encode 3 bytes |
| 130 | std::vector<uint8_t> decoded_bytes; |
| 131 | decoded_bytes.reserve((full_quads + 1) * 3); |
| 132 | |
| 133 | for (size_t i = 0; i < full_quads; i++) { |
| 134 | const auto quad = unpadded.substr(i * 4, 4); |
| 135 | const auto bytes = decode_quad(quad[0], quad[1], quad[2], quad[3]); |
| 136 | std::copy(bytes.begin(), bytes.end(), back_inserter(decoded_bytes)); |
| 137 | } |
| 138 | |
| 139 | const auto last_quad = unpadded.substr(full_quads * 4); |
| 140 | if (last_quad.size() == 0) { |
| 141 | return decoded_bytes; |
| 142 | } |
| 143 | |
| 144 | // handle padding |
| 145 | if ((last_quad.size() == 2) || (last_quad[2] == '=')) { |
| 146 | const auto bytes = decode_quad(last_quad[0], last_quad[1], 'A', 'A'); |
| 147 | decoded_bytes.push_back(bytes[0]); |
| 148 | } else { |
| 149 | const auto bytes = |
| 150 | decode_quad(last_quad[0], last_quad[1], last_quad[2], 'A'); |
| 151 | std::copy_n(bytes.begin(), 2, back_inserter(decoded_bytes)); |
| 152 | } |
| 153 | |
| 154 | return decoded_bytes; |
| 155 | } |
| 156 | |
| 157 | } // namespace comm |
no test coverage detected