/*

Copyright (c) 2002-2005, Yauheni Akhotnikau
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

- Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

- The name of the author may not be used to endorse or promote products derived
from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.

*/

/*!
	\file oess_1/io/h/subbinstream.hpp
	\brief Класс %oess_1::io::isubbinstream_t.
*/

#if !defined( _OESS_1__IO__SUBBINSTREAM_HPP_ )
#define _OESS_1__IO__SUBBINSTREAM_HPP_

#include <oess_1/io/h/declspec.hpp>

#include <oess_1/io/h/binbuffer.hpp>

namespace oess_1 {

namespace io {

//
// isubbinstream_t
//

//! Двоичный подпоток ввода.
/*!
	Реализация интерфейса obinstream_t для
	чтения из некоторого потока не более указаного
	количества байт.

	При извлечении их входного потока составных TLV
	(oess_1::tlv::compound_tlv_t) возникает задача прочитать
	из уже существующего потока не более Length байт.
	При этом операции чтения могут выполняться несколькими
	объектами (дочерними TLV) и определить сколько именно
	было прочитано каждым из объектов может быть невозможно.
	Можно было бы создать промежуточный буфер и записать
	в него Length байт из входного потока, а затем осуществлять
	чтение объектов из этого буфера. Но это требует дополнительных
	расходов памяти.

	Класс isubbinstream_t предназначен для решения подобных
	задач. Он перенаправляет все операции чтения в исходный
	поток. Но при этом контролируется, сколько байт было
	прочитано. Считается, что подпоток исчерпывается после
	того, как из исходного потока будет прочитано Length байт.

	Если с помощью класса isubbinstream_t из исходного потока
	было извлечено менее Length байт, то класс isubbinstream_t
	не пытается изъять из исходного потока невыбранные байты.

	\note v.1.1.1
	Сделан производным от oess_1::io::ibinbuffer_t.
*/
class	OESS_1__IO__TYPE	isubbinstream_t :
	public ibinbuffer_t
{
	public :
		isubbinstream_t(
			//! Исходный входной поток.
			ibinstream_t & source,
			//! Максимальная емкость подпотока.
			size_t capacity );
		virtual ~isubbinstream_t();

		//! Емкость подпотока.
		/*!
			\return значение емкости, полученное в конструкторе.
		*/
		size_t
		capacity() const;

		//! Объем находящихся в потоке данных.
		/*!
			\return значение емкости, полученное в конструкторе.
		*/
		virtual size_t
		size() const;

		//! Количество прочитанных из подпотока байт.
		virtual size_t
		pos() const;

		//! Возвращает true, если pos() == capacity().
		virtual bool
		eof() const;

	protected :
		//! Реализация метода из базового класса.
		/*!
			Если нет достаточного объема данных для чтения
			хотя бы одного элемента, то порождается
			исключение.
		*/
		virtual const oess_1::char_t *
		in_reserve(
			//! Количество элементов, которые нужно
			//! прочитать.
			size_t item_count,
			//! Размер одного элемента в байтах.
			size_t item_size,
			//! Количество элементов, доступных по
			//! возвращенному указателю.
			size_t & item_available );

		//! Реализация метода из базового класса.
		virtual void
		in_shift(
			//! Количество успешно прочитанных элементов.
			size_t item_count,
			//! Размер одного элемента в байтах.
			size_t item_size );

	private :
		//! Исходный поток.
		ibinstream_t &	m_source;
		//! Максимальный объем подпотока.
		/*!
			Задается в конструкторе.
		*/
		size_t	m_capacity;
		//! Количество прочитанных из подпотока байт.
		size_t	m_pos;

	private :
		//! Защита от копирования.
		isubbinstream_t(
			const isubbinstream_t & );
		//! Защита от копирования.
		isubbinstream_t &
		operator=(
			const isubbinstream_t & );
};

} /* namespace io */

} /* namespace oess_1 */

#endif

