/**
 * @file       kyassert.hpp
 * @brief      アサーションモジュール
 * @author     Nomura Kei
 * @copyright  2003 - 2017  Nomura Kei
 * License: New BSD License (3-cclause BSD license)
 */
#ifndef KYASSERT_HPP
#define KYASSERT_HPP

#include <exception>
#include <string>

namespace ky
{

class AssertError : public std::exception
{
	public:
		AssertError() throw();
		AssertError(const AssertError& e) throw();
		AssertError(const std::string& msg) throw();
		AssertError(const std::string& msg, const char* file, int line, const char* func) throw();
		virtual ~AssertError() throw();
		virtual const char* what() const throw();
		const std::string& getFileName() const throw();
		int                getLineNumber() const throw();
		const std::string& getFunctionName() const throw();

	protected:
		std::string message;

	private:
		std::string fileName;
		int         lineNumber;
		std::string functionName;
};

namespace Assertion
{
	void assertEquals (bool               expected, bool               actual, const char* file, int line, const char* func) throw(AssertError);
	void assertEquals (char               expected, char               actual, const char* file, int line, const char* func) throw(AssertError);
	void assertEquals (double             expected, double             actual, const char* file, int line, const char* func) throw(AssertError);
	void assertEquals (float              expected, float              actual, const char* file, int line, const char* func) throw(AssertError);
	void assertEquals (int                expected, int                actual, const char* file, int line, const char* func) throw(AssertError);
	void assertEquals (long               expected, long               actual, const char* file, int line, const char* func) throw(AssertError);
	void assertEquals (const std::string& expected, const std::string& actual, const char* file, int line, const char* func) throw(AssertError);
	void assertEquals (const char*        expected, const char*        actual, const char* file, int line, const char* func) throw(AssertError);
	void assertEquals (const std::string& expected, const char*        actual, const char* file, int line, const char* func) throw(AssertError);
	void assertEquals (const char*        expected, const std::string& actual, const char* file, int line, const char* func) throw(AssertError);
	void assertTrue   (bool condition                                        , const char* file, int line, const char* func) throw(AssertError);
	void assertFalse  (bool condition                                        , const char* file, int line, const char* func) throw(AssertError);
	void assertNull   (void* obj                                             , const char* file, int line, const char* func) throw(AssertError);
	void assertNotNull(void* obj                                             , const char* file, int line, const char* func) throw(AssertError);
	void fail         (                                                        const char* file, int line, const char* func) throw(AssertError);
}	// namespace Assertion
}	// namespace ky



#ifndef __FUNCTION__
#define __FUNCTION__ __func__
#endif


/**
 * 指定された actual が, expected と同一でない場合, AssertError を throw します.
 *
 * @param expected 期待する値
 * @param actual   比較する値
 */
#define assertEquals(expected, actual) assertEquals(expected, actual, __FILE__, __LINE__, __FUNCTION__)


/**
 * 指定された condition が true でない場合, AssertError を throw します.
 *
 * @param condition 比較する値
 */
#define assertTrue(condition)  assertTrue(condition , __FILE__, __LINE__, __FUNCTION__)


/**
 * 指定された condition が false でない場合, AssertError を throw します.
 *
 * @param condition 比較する値
 */
#define assertFalse(condition) assertFalse(condition, __FILE__, __LINE__, __FUNCTION__)


/**
 * 指定された obj が 0 (null) でない場合, AssertError を throw します.
 *
 * @param obj null か否か確認する値
 */
#define assertNull(condition) assertNull(obj, __FILE__, __LINE__, __FUNCTION__)


/**
 * 指定された obj が 0 (null) の場合, AssertError を throw します.
 *
 * @param obj null か否か確認する値
 */
#define assertNotNull(condition) assertNotNull(obj, __FILE__, __LINE__, __FUNCTION__)


/**
 * 常に AssertError を throw します.
 */
#define fail() fail(__FILE__, __LINE__, __FUNCTION__)


#endif	// KYASSERT_HPP

