//
// 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 NameScope.h
 * @author Ronald Kluth
 * @date created at 2009/02/08
 * @brief Declaration and implementation of class NameScope
 * @since 0.1
 */

#ifndef LOG_NAMESCOPE_INCLUDED
#define LOG_NAMESCOPE_INCLUDED

#include <cstddef> // size_t
#include <map>
#include <sstream>
#include <string>

namespace Log {

/**
 * @class NameScope
 * @brief This class provides a scope for object names.
 *
 * All named objects receive their name from a name scope. This guarantees
 * that every name created by it is unique within the scope.
 */
class NameScope
{
public:
	/**
	 * @brief Construction
	 * @param defaultName The default name, given to objects which don't request
	 * a specific name
	 * @param defaultSpace The default fill character separating the added number
	 * from the name string
	 */
	NameScope( const std::string& defaultName = "Unnamed", const char defaultSpace = '_' );

	/// Destruction
	virtual ~NameScope();

	/**
	 * @brief Create a unique name for the caller
	 * @param name The basic part of the name, if left blank the default
	 * name is used
	 * @return A unique name string
	 *
	 * This method builds a unique name. If there is already a name in this
	 * scope equal to the requested @c name, the new name gets a number.
	*/
	std::string createUniqueName( std::string name );

protected:
	/// Holds the default name
	const std::string defaultName_;
	/// Holds the default fill character
	const char defaultSpace_;
	/// Holds requested names and their number of occurrences within the scope
	std::map< std::string, std::size_t > nameLookup_;
};

//------------------------------------------------------construction/destruction

inline NameScope::NameScope( const std::string& defaultName, const char defaultSpace )
:	defaultName_( defaultName )
,	defaultSpace_( defaultSpace )
{
}

inline NameScope::~NameScope()
{
}

//---------------------------------------------------------unique label creation

inline std::string NameScope::createUniqueName( std::string name )
{
	if( name.empty() )
	{
		name = defaultName_;
	}

	// get count for this name and increment
	unsigned int number = nameLookup_[ name ]++;

	// append count if the name is not unique
	if( number > 0 )
	{
		std::ostringstream stream;
		stream << name << defaultSpace_ << number;
		return stream.str();
	}

	return name;
}

} // namespace Log

#endif /* LOG_NAMESCOPE_INCLUDED */
