/*

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/stdsn/h/macro.hpp
	\brief Определение макроса %OESS_SERIALIZER()
*/

#if !defined( _OESS_1__STDSN__MACRO_HPP_ )
#define _OESS_1__STDSN__MACRO_HPP_

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

/*!
	\brief Аналог %OESS_SERIALIZER для случая экспортируемых классов.

	Для экспорта/импорта класса из DLL после ключевого
	слова \c class нужно указать соответствующее значение
	из расширения C++ используемого компилятора (например,
	__declspec(dllexport), __export, __import и т.д.).

	Макрос OESS_SERIALIZER() полностью определяет специальный
	вложенный класс oess_serializer_t, который занимается
	сериализацией. Описание oess_serializer_t делается без
	использования директив экспорта/импорта. Но, если
	OESS_SERIALIZER() используется в экспортируемом классе,
	то и вспомогательный класс oess_serializer_t так же
	должен быть экспортирован. Для осуществления этого
	предназначен макрос %OESS_SERIALIZER_EX.

	\param	T	Имя сериализуемого типа.
	\param	Ex	Набор расширений C++, который будет помещен
	между ключевым словом \c class и именем oess_serializer_t.

	\par Пример:
\code
class	OESS_1__STDSN__TYPE	smart_ptr_t :
	public serializable_t
{
	OESS_SERIALIZER_EX( smart_ptr_t, OESS_1__STDSN__TYPE )
	public :
	...
\endcode
*/
#define OESS_SERIALIZER_EX(T, Ex) \
public : \
	class	Ex	oess_serializer_t { \
		public : \
			static void unpack( oess_1::stdsn::ient_t & s, T & o, \
				oess_1::stdsn::isubclass_extension_t * subclass ); \
			static void unpack_complete( oess_1::stdsn::ient_t & s, T & o ); \
			static void pack( oess_1::stdsn::oent_t & s, const T & o, \
				oess_1::stdsn::osubclass_extension_t * subclass ); \
			static void pack_complete( oess_1::stdsn::oent_t & s, const T & o ); \
			static void	unpack_self( oess_1::stdsn::ient_t & s, T & o, \
				oess_1::stdsn::isubclass_extension_t * subclass ); \
			static void	pack_self( oess_1::stdsn::oent_t & s, const T & o, \
				oess_1::stdsn::osubclass_extension_t * subclass ); \
			static void *	cast( const std::string & cast_to, T * o ); \
			static const std::string &	type_name(); \
			static oess_1::stdsn::serializable_t *	factory(); \
			static const std::string &	scheme(); \
		private : \
			static oess_1::stdsn::factory_registrator_t	m_factory_reg; \
	}; \
	friend class	oess_serializer_t; \
	virtual void	oess_unpack( oess_1::stdsn::ient_t & s ); \
	virtual void	oess_pack( oess_1::stdsn::oent_t & s ) const; \
	virtual void *	oess_cast( const std::string & type_name ); \
	virtual const std::string &	oess_type_name() const; \
	virtual const std::string &	oess_scheme() const; \
	virtual void	oess_get_subclass_extension_path( \
		oess_1::stdsn::subclass_extension_path_t & path, \
		const std::string & terminator ) const; \
	bool oess_present_if( const std::string & ) const; \
	void oess_set_default( const std::string & ); \
private : \
	const oess_1::stdsn::unknown_extension_t & \
	oess_unknown_extension() const; \
	oess_1::stdsn::unknown_extension_t & \
	oess_writeable_unknown_extension();

#define __OESS_1_EMPTY_EX__

/*!
	\brief Объявление в описании сериализуемого класса
	всего, что нужно ObjESSty для сериализации.

	Для сериализации объектов ObjESSty необходимо,
	чтобы в сериализуемом классе был описан ряд специальных
	методов и атрибутов. Макрос OESS_SERIALIZER выполняет
	это описание и скрывает детали реализации механизма
	сериализации.

	Должен применяться следующим образом:
	\code
	class	some_class_t :
		public  oess_1::stdsn::serializable_t
	{
		OESS_SERIALIZER( some_class_t )
		public :
			...
	};
	\endcode

	\note
	Макрос OESS_SERIALIZER использует в своем теле
	управление "открытостью" членов класса (посредством
	public и private). Использование OESS_SERIALIZER
	эквивалентно:
	\code
	class	some_class_t :
		public  oess_1::stdsn::serializable_t
	{
			// Какие-то части сериализации.
			...
		private :
			// Остальное описание класса.
	};
	\endcode
	Поэтому, для описания остальных членов класса желательно
	после макроса OESS_SERIALIZER явно указать степень
	открытости посредством public, private или proceted.

	\param	T	Имя сериализуемого типа.
*/
#define OESS_SERIALIZER(T) OESS_SERIALIZER_EX(T, __OESS_1_EMPTY_EX__ )

#endif

