/*
 * libmad - MPEG audio decoder library
 * Copyright (C) 2000-2004 Underbit Technologies, Inc.
 *
 * This program 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 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * $Id: stream.c,v 1.12 2004/02/05 09:02:39 rob Exp $
 *
 *
 * c++ adaption:
 * Copyright (c) 2026 - 2026 kio@little-bat.de
 * GPL-2.0 license
 * https://opensource.org/license/gpl-2.0
 */

#include "MadStream.h"
#include "mad_bitptr.h"
#include <stdlib.h>

/*
 * NAME:	stream->reset()
 * DESCRIPTION:	re-initialize stream struct
 */
void MadStream::reset() noexcept
{
	// reset stream but keep main_data[] and preserve options

	buffer	= nullptr;
	bufend	= nullptr;
	skiplen = 0;

	sync	 = 0;
	freerate = 0;

	this_frame = nullptr;
	next_frame = nullptr;
	ptr.init(nullptr);

	anc_ptr.init(nullptr);
	anc_bitlen = 0;

	md_len = 0;
	error  = MAD_ERROR_NONE;
}

/* copy constructor
 * needed for MadFrame::free_bitrate()
 */
MadStream::MadStream(const MadStream& q) noexcept :
	buffer(q.buffer),
	bufend(q.bufend),
	skiplen(q.skiplen),
	sync(q.sync),
	freerate(q.freerate),
	this_frame(q.this_frame),
	next_frame(q.next_frame),
	ptr(q.ptr),
	anc_ptr(q.anc_ptr),
	anc_bitlen(q.anc_bitlen),
	options(q.options),
	main_data(nullptr),
	md_len(0),
	error(MAD_ERROR_NONE),
	rc(0)
{}

/*
 * NAME:	stream->init()
 * DESCRIPTION:	initialize stream struct
 */
MadStream::MadStream(int opts) noexcept
{
	options	  = opts;
	main_data = nullptr;
	reset();
}

/*
 * NAME:	stream->finish()
 * DESCRIPTION:	deallocate any dynamic memory associated with stream
 */
MadStream::~MadStream() noexcept
{
	if (main_data) free(main_data);
	anc_ptr.finish();
	ptr.finish();
}

/*
 * NAME:	stream->buffer()
 * DESCRIPTION:	set stream buffer pointers
 */
void MadStream::set_buffer_pointers(const uchar* buffer, ulong length) noexcept
{
	this->buffer = buffer;
	this->bufend = buffer + length;

	this->this_frame = buffer;
	this->next_frame = buffer;

	this->sync = 1;

	this->ptr.init(buffer);
}

/*
 * NAME:	stream->sync()
 * DESCRIPTION:	locate the next stream sync word
 */
int MadStream::find_next_sync() noexcept
{
	const uchar* ptr = this->ptr.nextbyte();
	const uchar* end = this->bufend;

	while (ptr < end - 1 && !(ptr[0] == 0xff && (ptr[1] & 0xe0) == 0xe0)) ++ptr;

	if (end - ptr < MAD_BUFFER_GUARD) return -1;

	this->ptr.init(ptr);

	return 0;
}

/*
 * NAME:	stream->errorstr()
 * DESCRIPTION:	return a string description of the current error condition
 */
cstr MadStream::errorstr() const noexcept
{
	switch (this->error)
	{
	case MAD_ERROR_NONE: return NO_ERROR; // nullptr

	case MAD_ERROR_BUFLEN: return "input buffer too small (or EOF)";
	case MAD_ERROR_BUFPTR: return "invalid (null) buffer pointer";

	case MAD_ERROR_NOMEM: return "not enough memory";

	case MAD_ERROR_LOSTSYNC: return "lost synchronization";
	case MAD_ERROR_BADLAYER: return "reserved header layer value";
	case MAD_ERROR_BADBITRATE: return "forbidden bitrate value";
	case MAD_ERROR_BADSAMPLERATE: return "reserved sample frequency value";
	case MAD_ERROR_BADEMPHASIS: return "reserved emphasis value";

	case MAD_ERROR_BADCRC: return "CRC check failed";
	case MAD_ERROR_BADBITALLOC: return "forbidden bit allocation value";
	case MAD_ERROR_BADSCALEFACTOR: return "bad scalefactor index";
	case MAD_ERROR_BADMODE: return "bad bitrate/mode combination";
	case MAD_ERROR_BADFRAMELEN: return "bad frame length";
	case MAD_ERROR_BADBIGVALUES: return "bad big_values count";
	case MAD_ERROR_BADBLOCKTYPE: return "reserved block_type";
	case MAD_ERROR_BADSCFSI: return "bad scalefactor selection info";
	case MAD_ERROR_BADDATAPTR: return "bad main_data_begin pointer";
	case MAD_ERROR_BADPART3LEN: return "bad audio data length";
	case MAD_ERROR_BADHUFFTABLE: return "bad Huffman table select";
	case MAD_ERROR_BADHUFFDATA: return "Huffman data overrun";
	case MAD_ERROR_BADSTEREO: return "incompatible block_type for JS";
	}

	return "unknown mp3 stream error";
}

/*

































*/
