/* SPDX-FileCopyrightText: 2025-2026 - Sébastien Wilmet <swilmet@gnome.org>
 * SPDX-License-Identifier: LGPL-3.0-or-later
 */

#include "gfls-encoding-conversion.h"
#include "gfls-iconv.h"

/**
 * gfls_encoding_try_convert:
 * @input_bytes: a #GBytes.
 * @to_codeset: destination codeset.
 * @from_codeset: source codeset.
 *
 * Tries a conversion on @input_bytes, discarding the output.
 *
 * @from_codeset and @to_codeset must be compatible with iconv, see
 * gfls_iconv_open().
 *
 * If @input_bytes ends with an incomplete multi-byte character, that part is
 * ignored. So @input_bytes can be for example the first chunk of a file when
 * loading it.
 *
 * Returns: %TRUE if and only if @input_bytes can be converted without errors,
 *   without invalid characters and without fallback characters.
 * Since: 0.4
 */
gboolean
gfls_encoding_try_convert (GBytes      *input_bytes,
			   const gchar *to_codeset,
			   const gchar *from_codeset)
{
	GflsIconv *conv;
	const gchar *input_buffer;
	gsize input_buffer_size = 0;
	gchar *input_buffer_pos;
	gsize input_buffer_n_bytes_left;
	GflsIconvResult conv_result;
	gboolean success = FALSE;

	g_return_val_if_fail (input_bytes != NULL, FALSE);
	g_return_val_if_fail (to_codeset != NULL, FALSE);
	g_return_val_if_fail (from_codeset != NULL, FALSE);

	conv = gfls_iconv_new ();

	if (!gfls_iconv_open (conv, to_codeset, from_codeset, NULL))
	{
		success = FALSE;
		goto out;
	}

	input_buffer = g_bytes_get_data (input_bytes, &input_buffer_size);

	input_buffer_pos = (gchar *) input_buffer;
	input_buffer_n_bytes_left = input_buffer_size;

	conv_result = gfls_iconv_feed_discard_output (conv,
						      &input_buffer_pos, &input_buffer_n_bytes_left,
						      NULL);

	switch (conv_result)
	{
		case GFLS_ICONV_RESULT_OK:
		case GFLS_ICONV_RESULT_INCOMPLETE_INPUT:
			success = TRUE;
			break;

		case GFLS_ICONV_RESULT_ERROR:
		case GFLS_ICONV_RESULT_ILLEGAL_SEQUENCE:
		case GFLS_ICONV_RESULT_OUTPUT_BUFFER_FULL:
		case GFLS_ICONV_RESULT_LOSSY_CONVERSION:
		default:
			success = FALSE;
			break;
	}

	/* TODO: call gfls_iconv_feed_discard_output() with @inbuf and
	 * @inbytes_left set to NULL. (But testing it completely is more
	 * difficult).
	 */

out:
	gfls_iconv_free (conv);
	return success;
}
