/* Copyright 2020, Michele Santullo
 * This file is part of orotool.
 *
 * Orotool is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Orotool is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Orotool.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "base64.hpp"
#include <config.h>
#define restrict __restrict__
#include "gnulib/lib/base64.h"
#include <cassert>
#include <stdexcept>
#include <cstring>

#if defined(base64_decode)
#	undef base64_decode
#endif

#if defined(base64_encode)
#	undef base64_encode
#endif

namespace duck {

std::vector<char> base64_decode (std::string_view text) {
	base64_decode_context ctx;
	base64_decode_ctx_init(&ctx);
	std::vector<char> retval(3 * (text.size() / 4) + 3);

	size_t out_size = retval.size();
	const bool success = base64_decode_ctx(&ctx, text.data(), text.size(), retval.data(), &out_size);
	if (not success)
		throw std::runtime_error("Base64 decode failed");

	assert(out_size <= retval.size());
	retval.resize(out_size);
	return retval;
}

std::string base64_encode (const std::vector<uint8_t>& data) {
	const std::size_t size = (data.size() + 2) / 3 * 4 + 1;
	std::string ret(size, '@');
	::base64_encode(
		reinterpret_cast<const char*>(data.data()),
		data.size(),
		ret.data(),
		ret.size()
	);

	ret.resize(std::strlen(ret.data()));
	return ret;
}

} //namespace duck

#undef restrict
