/*

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/defs/h/err_code.hpp
	\brief Класс err_code_t.
*/

#if !defined( _OESS_1__DEFS__ERR_CODE_HPP_ )
#define _OESS_1__DEFS__ERR_CODE_HPP_

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

#include <iostream>

#include <string>

#include <oess_1/defs/h/types.hpp>

namespace oess_1 {

//! Код ошибки с пояснениями.
/*!
	Тип предназначен для связывание в одном объекте
	целочисленого кода ошибки, описания места возникновения
	ошибки и, возможно, описания ошибки.
*/
struct OESS_1__DEFS__TYPE	err_code_t {
	//! Целочисленный код ошибки.
	int_t	m_code;

	//! Имя файла, в котором был создан объект err_code_t.
	std::string	m_file;

	//! Номер строки файла, в которой был создан объект
	//! err_code_t.
	/*!
		Предполагается, что для задания этого поля
		всегда будет использоваться стандартный марос
		\c __LINE__.
	*/
	int	m_line;

	//! Текстовое описание ошибки. Возможно пустое.
	/*!
		Предполагается, что для кода отсутствия ошибки
		(обычно 0), это поле будет пустым.

		\note Предпочтительнее использовать
		описания, не содержащие русских букв. В противном
		случае в Windows возникнут проблемы с кодировками
		(например, консоль использует CP866, а оконная
		система -- CP1251).
	*/
	std::string	m_desc;

	/*!
		Предназначен для кода отсутствия ошибки.
		Полю m_code присваивается 0, заполняются
		только поля m_file и m_line.
	*/
	err_code_t(
		//! Имя файла, в котором был создан объект err_code_t.
		const std::string & file,
		//! Номер строки файла, в которой был создан объект
		//! err_code_t.
		int line );

	/*!
		Предназначен для полного определения объекта.
	*/
	err_code_t(
		//! Целочисленный код ошибки.
		int_t code,
		//! Имя файла, в котором был создан объект err_code_t.
		const std::string & file,
		//! Номер строки файла, в которой был создан объект
		//! err_code_t.
		int line,
		//! Текстовое описание ошибки.
		const std::string & desc );

	//! Конструктор копирования.
	err_code_t(
		const err_code_t & o );

	~err_code_t();

	//! Опреатор копирования.
	err_code_t &
	operator=(
		const err_code_t & o );

	//! Отличен ли от нуля?
	/*!
		\return true, если m_code отличен от нуля (что свидетельствует
		о наличии ошибки). false, если m_code равен 0 (нет ошибки).
	*/
	inline
	operator bool() const {
		return ( 0 != m_code );
	}

	//! Равенство с целым.
	/*!
		Предназначен для случаев:
		\code
		if( err == 3 ) ...
		\endcode
	*/
	inline bool
	operator==( int c ) const {
		return ( c == m_code );
	}

	//! Равенство.
	/*!
		Сравнивается только m_code.
	*/
	inline bool
	operator==( const err_code_t & o ) const {
		return ( m_code == o.m_code );
	}

	//! Неравенство с целым.
	/*!
		Предназначен для случаев:
		\code
		if( err != 3 ) ...
		\endcode
	*/
	inline bool
	operator!=( int c ) const {
		return ( c != m_code );
	}

	//! Неравенство.
	/*!
		Сравнивается только m_code.
	*/
	inline bool
	operator!=( const err_code_t & o ) const {
		return ( m_code != o.m_code );
	}

	//! Равен ли нулю?
	/*!
		\return true, если m_code равен 0 (нет ошибки).
		false, если m_code отличен от нуля (что свидетельствует
		о наличии ошибки).
	*/
	inline bool
	operator!() const {
		return ( !m_code );
	}
};

//! Создать и инициализировать анономный, временный объект err_code_t.
/*!
	\param code	Целочисленный код ошибки.
	\param desc	Выражение, дающее в результате const std::string &
		или const char *.

	Например:
	\code
	oess_1::err_code_t
	some_func()
	{
		if( ... )
			return oess_1_make_err( -1, "invalid argument" );

		if( ... )
			return oess_1_make_err( -2,
				std::string( "log" ) + ": file not found" );
	}
	\endcode
*/
#define oess_1_make_err(code, desc) oess_1::err_code_t(code, __FILE__, __LINE__, desc)

//! Внутренняя функция ObjESSty.
/*!
	\if oess_full_api
	Отображение объекта err_code_t в указанный поток вывода.

	Предназначена для реализации оператора '<<' для
	объекта err_code_t.
	\endif
*/
OESS_1__DEFS__FUNC( std::ostream & )
err_code_to_std_ostream( std::ostream & o, const err_code_t & c );

//! Отображение объекта err_code_t в указанный поток вывода.
/*!
	Отображает объект в виде:

	<имя файла>:<номер строки>:<код ошибки> [<описание>]
*/
inline std::ostream &
operator<<( std::ostream & o, const err_code_t & c )
{
	return err_code_to_std_ostream( o, c );
}

} /* namespace oess_1 */

#endif
