/*

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
	\brief Классы %oess_1::io::ifixed_mem_buf_t,
	%oess_1::io::ofixed_mem_buf_t.
*/

#if !defined( _OESS_1__IO__FIXED_MEM_BUF_HPP_ )
#define _OESS_1__IO__FIXED_MEM_BUF_HPP_

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

#include <auto_ptr_3/h/vect_ptr.hpp>

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

namespace oess_1 {

namespace io {

//
// ifixed_mem_buf_t
//

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

	Объект этого класса использует существующий
	буфер, указатель на который получает в
	конструкторе.

	Объект ifixed_mem_buf_t не уничтожает буфер
	в своем деструкторе.

	Считается, что весь буфер заполнен реальными
	данными. Можно изменять только текущую
	позицию в буфере.

	\note v.1.1.1
	Сделан производным от oess_1::io::ibinbuffer_t.
*/
class	OESS_1__IO__TYPE	ifixed_mem_buf_t :
	public ibinbuffer_t
{
	public :
		ifixed_mem_buf_t(
			//! Буфер, из которого осуществляется
			//! чтение данных.
			/*!
				Буфер должен существовать все время,
				пока существует объект ifixed_mem_buf_t.
			*/
			const oess_1::char_t * buf,
			//! Емкость буфера в байтах.
			size_t capacity );
		virtual ~ifixed_mem_buf_t();

		//! Емкость буфера.
		/*!
			\return значение емкости, полученное в конструкторе.
			\deprecated Должен использоваться метод
				oess_1::io::ifixed_mem_buf_t::size().
		*/
		size_t
		capacity() const;

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

		//! Текущая позиция, с которой будет осуществляться
		//! очередная операция чтения.
		virtual size_t
		pos() const;

		//! Установить позицию, с которой будет осуществляться
		//! очередная операци чтения.
		/*!
			Операция выполняется только, если pos меньше,
			чем capacity().
		*/
		void
		set_pos( size_t pos );

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

		//! Указатель на начало всего буфера.
		const oess_1::char_t *
		ptr() const;

		//! Указатель на текущую позицию в буфере.
		const oess_1::char_t *
		current_ptr() 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 :
		//! Буфер, из которого происходит чтение данных.
		const oess_1::char_t *	m_buf;
		//! Емкость буфера.
		/*!
			Задается в конструкторе.
		*/
		size_t	m_capacity;
		//! Текущая позиция в буфере.
		size_t	m_pos;

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

//
// ofixed_mem_buf_t
//

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

	Объект этого класса использует существующий
	буфер, указатель на который получает в
	конструкторе.

	Объект ofixed_mem_buf_t не уничтожает буфер
	в своем деструкторе.

	Подсчитывается объем занесенных в буфер данных,
	возвращаемый методом size().

	\par v.1.1.1
	Сделан производным от oess_1::io::obinbuffer_t.
	
	\par v.1.1.1
	Ранее ofixed_mem_buf_t предполагал, что весь буфер
	заполнен данным (т.е. size() == capacity()). Теперь
	объем данных в буфере вычисляется про помещении данных
	в буфер. Но, в некоторых случаях нужно указать, что
	весь буфер заполнен значениями изначально. Для этого
	предназначен дополнительный необязательный аргумент
	конструктора \a initial_size. Если он не равен 0,
	то считается, что в буфере уже находится initial_size
	байт.
*/
class	OESS_1__IO__TYPE	ofixed_mem_buf_t :
	public obinbuffer_t
{
	public :
		ofixed_mem_buf_t(
			//! Буфер, в который осуществляется
			//! запись данных.
			/*!
				Буфер должен существовать все время,
				пока существует объект оfixed_mem_buf_t.
			*/
			oess_1::char_t * buf,
			//! Емкость буфера в байтах.
			size_t capacity,
			//! Сколько байт в буфере нужно считать занятыми.
			size_t initial_size = 0 );
		virtual ~ofixed_mem_buf_t();

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

		//! Текущий объем помещенных в буфер данных.
		/*!
			\since v.1.1.1 */
		virtual size_t
		size() const;

		//! Текущая позиция, в которую будет осуществляться
		//! очередная операция записи.
		virtual size_t
		pos() const;

		//! Установить позицию, в которую будет осуществляться
		//! очередная операци записи.
		/*!
			Операция выполняется только, если pos меньше,
			чем size().
		*/
		void
		set_pos( size_t pos );

		//! Указатель на начало всего буфера.
		const oess_1::char_t *
		ptr() const;

		//! Указатель на текущую позицию в буфере.
		const oess_1::char_t *
		current_ptr() const;

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

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

	private :
		//! Буфер, в который происходит запись данных.
		oess_1::char_t *	m_buf;
		//! Емкость буфера.
		/*!
			Задается в конструкторе.
		*/
		size_t	m_capacity;
		//! Текущий объем данных, помещенных в буфер.
		size_t	m_size;
		//! Текущая позиция в буфере.
		size_t	m_pos;

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

} /* namespace io */

} /* namespace oess_1 */

#endif
