/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <log4cxx/spi/location/locationinfo.h>
#include <log4cxx/helpers/pool.h>
#include <log4cxx/helpers/widelife.h>

using namespace ::LOG4CXX_NS::spi;
using namespace LOG4CXX_NS::helpers;

/**
  When location information is not available the constant
  <code>NA</code> is returned. Current value of this string
  constant is <b>?</b>.  */
const char* const LocationInfo::NA = "?";
const char* const LocationInfo::NA_METHOD = "?::?";

const LocationInfo& LocationInfo::getLocationUnavailable()
{
	static const WideLife<LocationInfo> unavailable;
	return unavailable;
}

/**
*   Constructor.
*   @remarks Used by LOG4CXX_LOCATION to generate
*       location info for current code site
*/
LocationInfo::LocationInfo( const char* const fileName1,
	const char* const shortFileName1,
	const char* const methodName1,
	int lineNumber1 )
	:  lineNumber( lineNumber1 ),
	   fileName( fileName1 ? fileName1 : LocationInfo::NA ),
	   shortFileName(shortFileName1 ? shortFileName1 : LocationInfo::NA ),
	   methodName( methodName1 ? methodName1 : LocationInfo::NA_METHOD )
{
}

/**
*   Default constructor.
*/
LocationInfo::LocationInfo()
	: lineNumber( -1 ),
	  fileName(LocationInfo::NA),
	  shortFileName(LocationInfo::NA),
	  methodName(LocationInfo::NA_METHOD)
{
}

/**
*   Copy constructor.
*   @param src source location
*/
LocationInfo::LocationInfo( const LocationInfo& src )
	:  lineNumber( src.lineNumber ),
	   fileName( src.fileName ),
	   shortFileName( src.shortFileName ),
	   methodName( src.methodName )
{
}

/**
*  Assignment operator.
* @param src source location
*/
LocationInfo& LocationInfo::operator = ( const LocationInfo& src )
{
	fileName = src.fileName;
	shortFileName = src.shortFileName;
	methodName = src.methodName;
	lineNumber = src.lineNumber;
	return * this;
}

/**
 *   Resets location info to default state.
 */
void LocationInfo::clear()
{
	fileName = NA;
	shortFileName = NA;
	methodName = NA_METHOD;
	lineNumber = -1;
}


/**
 *   Return the file name of the caller.
 *   @returns file name, may be null.
 */
const char* LocationInfo::getFileName() const
{
	return fileName;
}

const char* LocationInfo::getShortFileName() const{
	return shortFileName;
}

/**
  *   Returns the line number of the caller.
  * @returns line number, -1 if not available.
  */
int LocationInfo::getLineNumber() const
{
	return lineNumber;
}

/** Returns the method name of the caller. */
const std::string LocationInfo::getMethodName() const
{
	std::string tmp(methodName);
	size_t parenPos = tmp.find('(');

	if (parenPos != std::string::npos)
	{
		tmp.erase(parenPos);
	}

	size_t colonPos = tmp.rfind("::");

	if (colonPos != std::string::npos)
	{
		tmp.erase(0, colonPos + 2);
	}
	else
	{
		size_t spacePos = tmp.find(' ');

		if (spacePos != std::string::npos)
		{
			tmp.erase(0, spacePos + 1);
		}
	}

	return tmp;
}


const std::string LocationInfo::getClassName() const
{
	std::string tmp(methodName);
	size_t parenPos = tmp.find('(');

	if (parenPos != std::string::npos)
	{
		tmp.erase(parenPos);
	}

	size_t colonPos = tmp.rfind("::");

	if (colonPos != std::string::npos)
	{
		tmp.erase(colonPos);
		size_t spacePos = tmp.find_last_of(' ');

		if (spacePos != std::string::npos)
		{
			tmp.erase(0, spacePos + 1);
		}

		return tmp;
	}

	tmp.erase(0, tmp.length() );
	return tmp;
}


