/*
 * This file is part of the Aaru Data Preservation Suite.
 * Copyright (c) 2019-2025 Natalia Portillo.
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of the
 * License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */

/* lh5_mem.c
 *
 * In-memory I/O glue for LH5 decompression.
 * Implements mem_getc(), mem_putc(), and the top-level
 * lh5_decompress() entry point.
 */

#include "lh5.h"
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include "../library.h"

/* Forward-declaration of the decompression driver in lzh.c */
extern int lzh_decode(void);

/* Buffer I/O state (see lh5_mem.h for externs) */
const uint8_t *in_ptr;
size_t         in_left;
uint8_t       *out_ptr;
size_t         out_left;
int            mem_error;

/*
 * mem_getc(): return next compressed byte, or 0 when in_left==0.
 * Never sets mem_error on input underflow.
 */
int mem_getc(void)
{
    if(in_left == 0) { return 0; /* mimic feof → subbitbuf = 0 */ }
    int c = *in_ptr++;
    in_left--;
    return c;
}

/*
 * mem_putc(): write one output byte, set mem_error on overflow.
 */
int mem_putc(int c)
{
    if(out_left == 0)
    {
        mem_error = 1;
        return EOF;
    }
    *out_ptr++ = (uint8_t)c;
    out_left--;
    return c;
}

/*
 * Top-level in-memory decompressor.
 *
 * in_buf  points to 'in_len' bytes of compressed data.
 * out_buf must have at least *out_len bytes available.
 * On return *out_len is set to the number of bytes written.
 *
 * Returns  0 on success
 *         -1 on error (bad stream or output too small)
 */
AARU_EXPORT int AARU_CALL lh5_decompress(const uint8_t *in_buf, size_t in_len, uint8_t *out_buf, size_t *out_len)
{
    /* Initialize buffer pointers and error flag */
    in_ptr    = in_buf;
    in_left   = in_len;
    out_ptr   = out_buf;
    out_left  = *out_len;
    mem_error = 0;

    /* Invoke the core LH5 decode routine (now buffer-based) */
    if(lzh_decode() != 0 || mem_error) { return -1; }

    /* Compute actual output size */
    *out_len = (size_t)(out_ptr - out_buf);
    return 0;
}
