//
// Copyright (c) 2009-2010 Ronald Kluth
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

/**
 * @file DeclareInfoType.h
 * @author Ronald Kluth
 * @date created at 2009/06/05
 * @brief Declaration and implementation of macro CPPLOG_DECLARE_INFO_TYPE
 * @since 0.1
 */

#ifndef LOG_DECLAREINFOTYPE_INCLUDED
#define LOG_DECLAREINFOTYPE_INCLUDED

#include "StringLiteral.h"
#include "detail/InfoType.h"

/**
 * @def CPPLOG_DECLARE_INFO_TYPE( PP_InfoTypeName, PP_StringName, PP_ValueType )
 * @brief Macro to ease the creation of arbitrary record info types
 * @param InfoTypeName The actual type name to be used
 * @param StringName String representation for this type
 * @param ValueType Type of the values the info type objects hold
 *
 * This macro is used to create record info types. In order for records to
 * carry arbitrary values, these must be wrapped by @c InfoType classes.
 * When expanded by the C++ preprocessor, this macro creates a new @c struct
 * that is used as a tag to distinguish specializations of the class template
 * InfoType holding the same value type.
 * Additionally, it provides a static method @c getName that returns the given
 * string representation (the second macro parameter). This string can be used
 * during the automatic extraction of log record info data, e.g. to associate
 * a piece of data with a table column in a database. The third macro parameter
 * defines the type of the values this info type can hold. The value to be
 * carried must be passed with the constructor and cannot be changed afterwards.
 * Info types can transport copies as well as pointers or references to data.
 *
 * Example:
 * @code
 * CPPLOG_DECLARE_INFO_TYPE( FuncInfo, "Function", std::string );
 * Channel< Record > channel;
 * void foo()
 * {
 *   channel << Record( "function called" ) + FuncInfo( "foo()" );
 * }
 * @endcode
 */
#define CPPLOG_DECLARE_INFO_TYPE( PP_InfoTypeName, PP_StringName, PP_ValueType )		\
																						\
	struct PP_InfoTypeName##NameHolder													\
	{																					\
		static const Log::StringLiteral& getName() 										\
		{ 																				\
			static Log::StringLiteral name( PP_StringName ); 							\
			return name; 																\
		} 																				\
	}; 																					\
																						\
	typedef Log::Detail::InfoType< PP_InfoTypeName##NameHolder, PP_ValueType > PP_InfoTypeName;


#endif /* LOG_DECLAREINFOTYPE_INCLUDED */
