std::vector Base64::fromBase64()

in src/Base64.cpp [23:91]


std::vector<std::uint8_t> Base64::fromBase64(std::string_view encoded)
{
	std::vector<std::uint8_t> result;

	if (encoded.empty())
	{
		return result;
	}

	result.reserve((encoded.size() + (encoded.size() % 4)) * 3 / 4);

	// First decode all of the full unpadded segments 24 bits at a time
	while (encoded.size() >= 4 && encoded[3] != padding)
	{
		const uint32_t segment = (static_cast<uint32_t>(verifyFromBase64(encoded[0])) << 18)
			| (static_cast<uint32_t>(verifyFromBase64(encoded[1])) << 12)
			| (static_cast<uint32_t>(verifyFromBase64(encoded[2])) << 6)
			| static_cast<uint32_t>(verifyFromBase64(encoded[3]));

		result.emplace_back(static_cast<std::uint8_t>((segment & 0xFF0000) >> 16));
		result.emplace_back(static_cast<std::uint8_t>((segment & 0xFF00) >> 8));
		result.emplace_back(static_cast<std::uint8_t>(segment & 0xFF));

		encoded = encoded.substr(4);
	}

	// Get any leftover partial segment with 2 or 3 non-padding characters
	if (encoded.size() > 1)
	{
		const bool triplet = (encoded.size() > 2 && padding != encoded[2]);
		const std::uint8_t tail = (triplet ? verifyFromBase64(encoded[2]) : 0);
		const uint16_t segment = (static_cast<uint16_t>(verifyFromBase64(encoded[0])) << 10)
			| (static_cast<uint16_t>(verifyFromBase64(encoded[1])) << 4)
			| (static_cast<uint16_t>(tail) >> 2);

		if (triplet)
		{
			if (tail & 0x3)
			{
				throw std::logic_error { "invalid padding at the end of a base64 encoded string" };
			}

			result.emplace_back(static_cast<std::uint8_t>((segment & 0xFF00) >> 8));
			result.emplace_back(static_cast<std::uint8_t>(segment & 0xFF));

			encoded = encoded.substr(3);
		}
		else
		{
			if (segment & 0xFF)
			{
				throw std::logic_error { "invalid padding at the end of a base64 encoded string" };
			}

			result.emplace_back(static_cast<std::uint8_t>((segment & 0xFF00) >> 8));

			encoded = encoded.substr(2);
		}
	}

	// Make sure anything that's left is 0 - 2 characters of padding
	if ((encoded.size() > 0 && padding != encoded[0])
		|| (encoded.size() > 1 && padding != encoded[1]) || encoded.size() > 2)
	{
		throw std::logic_error { "invalid padding at the end of a base64 encoded string" };
	}

	return result;
}