| 226 | } |
| 227 | |
| 228 | inline std::string decode(const std::string& base, const std::array<int8_t, 256>& rdata, |
| 229 | const std::vector<std::string>& fill) { |
| 230 | const auto pad = count_padding(base, fill); |
| 231 | if (pad.count > 2) throw std::runtime_error("Invalid input: too much fill"); |
| 232 | |
| 233 | const size_t size = base.size() - pad.length; |
| 234 | if ((size + pad.count) % 4 != 0) throw std::runtime_error("Invalid input: incorrect total size"); |
| 235 | |
| 236 | size_t out_size = size / 4 * 3; |
| 237 | std::string res; |
| 238 | res.reserve(out_size); |
| 239 | |
| 240 | auto get_sextet = [&](size_t offset) { return alphabet::index(rdata, base[offset]); }; |
| 241 | |
| 242 | size_t fast_size = size - size % 4; |
| 243 | for (size_t i = 0; i < fast_size;) { |
| 244 | uint32_t sextet_a = get_sextet(i++); |
| 245 | uint32_t sextet_b = get_sextet(i++); |
| 246 | uint32_t sextet_c = get_sextet(i++); |
| 247 | uint32_t sextet_d = get_sextet(i++); |
| 248 | |
| 249 | uint32_t triple = |
| 250 | (sextet_a << 3 * 6) + (sextet_b << 2 * 6) + (sextet_c << 1 * 6) + (sextet_d << 0 * 6); |
| 251 | |
| 252 | res += static_cast<char>((triple >> 2 * 8) & 0xFFU); |
| 253 | res += static_cast<char>((triple >> 1 * 8) & 0xFFU); |
| 254 | res += static_cast<char>((triple >> 0 * 8) & 0xFFU); |
| 255 | } |
| 256 | |
| 257 | if (pad.count == 0) return res; |
| 258 | |
| 259 | uint32_t triple = (get_sextet(fast_size) << 3 * 6) + (get_sextet(fast_size + 1) << 2 * 6); |
| 260 | |
| 261 | switch (pad.count) { |
| 262 | case 1: |
| 263 | triple |= (get_sextet(fast_size + 2) << 1 * 6); |
| 264 | res += static_cast<char>((triple >> 2 * 8) & 0xFFU); |
| 265 | res += static_cast<char>((triple >> 1 * 8) & 0xFFU); |
| 266 | break; |
| 267 | case 2: res += static_cast<char>((triple >> 2 * 8) & 0xFFU); break; |
| 268 | default: break; |
| 269 | } |
| 270 | |
| 271 | return res; |
| 272 | } |
| 273 | |
| 274 | inline std::string decode(const std::string& base, const std::array<int8_t, 256>& rdata, |
| 275 | const std::string& fill) { |
nothing calls this directly
no test coverage detected