/*
 * SPDX-FileType: SOURCE
 * SPDX-FileCopyrightText: Michael Bäuerle
 * SPDX-License-Identifier: BSD-2-Clause
 */

#ifndef BXX0_BASE64_DECODE_H
#define BXX0_BASE64_DECODE_H  1

#include <stddef.h>


/*! Library header for libbasexx Base 64 decode module
 *
 * \file      base64_decode.h
 * \author    Michael Bäuerle
 * \date      2024
 * \copyright BSD-2-Clause
 *
 * Public API (compatible between all versions with same major number).
 *
 * API documentation: \ref BASE64_DECODE
 */


/*! \defgroup BASE64_DECODE Base 64 decoder
 *
 * Decode Base 64 (RFC 4648).
 */
/*! \{ */


/*! \name Error codes for comparison with return value of decoder
 *
 * \anchor Decode_Errors
 *
 * All error codes have negative values.
 * <br>
 * Check for error with (0 > ret).
 *
 * Zero means success and valid input data according to RFC 4648.
 * <br>
 * Positive values are returned if flags were used (ORed together).
 * <br>
 * Check for success with (0 <= ret).
 */
/*! \{ */
#define BXX0_BASE64_DECODE_ERROR_SIZE  -1  /*!< Output buffer too small */
#define BXX0_BASE64_DECODE_ERROR_NAC   -2  /*!< Non-Alphabet character */
#define BXX0_BASE64_DECODE_ERROR_TAIL  -3  /*!< Invalid tail before padding */
#define BXX0_BASE64_DECODE_ERROR_PAD   -4  /*!< Invalid padding */
#define BXX0_BASE64_DECODE_ERROR_DAP   -5  /*!< Data after padding */
/*! \} */


/*! \name Flags for decoder (can be ORed together)
 *
 * \anchor Decode_Flags
 */
/*! \{ */
/*! Accept input data without PAD characters in tail */
#define BXX0_BASE64_DECODE_FLAG_NOPAD    0x01

/*! Accept and skip Non-Alphabet characters in input data
 *
 * Pad characters at invalid positions are still treated as errors.
 */
#define BXX0_BASE64_DECODE_FLAG_IGNORE   0x02

/*! Accept unused bits with nonzero value in tail */
#define BXX0_BASE64_DECODE_FLAG_INVTAIL  0x04

/*! Accept additional data after correctly padded tail
 *
 * Required if separately encoded blocks of data are concatenated.
 */
#define BXX0_BASE64_DECODE_FLAG_CONCAT   0x08
/*! \} */


/*! Calculate required output buffer size with preprocessor
 *
 * \param[in] len_in  Size of input data
 *
 * The decoder creates three output bytes for every four input bytes.
 * <br>
 * If the size of the input data is not a multiple of four bytes, up to two
 * additional bytes are extracted from the tail.
 */
#define BXX0_BASE64_DECODE_LEN_OUT(len_in)  (((len_in / 4U) * 3U) + 2U)


/*! Base 64 decoder
 *
 * \param[out]    out      Pointer to buffer for output data
 * \param[in,out] len_out  Pointer to size of output buffer \e out
 * \param[in]     in       Pointer to input buffer
 * \param[in,out] len_in   Pointer to size of data in input buffer \e in
 * \param[in]     flags    Flags (from \ref Decode_Flags )
 *
 * \attention
 * All memory regions accessed by pointer parameters must not overlap!
 *
 * The size of the output buffer must be large enough to process all input data.
 * <br>
 * The required output buffer size can be calculated with the macro
 * \ref BXX0_BASE64_DECODE_LEN_OUT .
 *
 * \e len_out is overwritten with the number of bytes still available in
 * \e out .
 *
 * \e len_in is overwritten with the number of Base 64 characters that were not
 * consumed yet.
 *
 * \return
 * Zero or positive warning code on success. Check for success with (0 <= ret).
 * <br>
 * If the decoder required \ref Decode_Flags to proceed, the corresponding
 * bits for the flags are set in the warning code.
 * Use \ref Decode_Flags constants to check for errors.
 * <br>
 * Negative value on error. Check for error with (0 > ret).
 * Use \ref Decode_Errors constants to check for errors.
 */
signed char bxx0_base64_decode(unsigned char       *out, size_t *len_out,
                               const unsigned char *in , size_t *len_in,
                               unsigned char        flags);


/*! \} */


#endif  /* BXX0_BASE64_DECODE_H */
