#include "clErrorClass.h"

// -------------------------------------------------------
// ---------           clErrorClass           ------------
// -------------------------------------------------------
// -------------------------------------------------------

// -------------------------------------------------------
//! \brief  エラーしたときに呼ばれる.
//! \param  なし.
//! \return なし.
clErrorClass::clErrorClass()
{
	__CONSTRUCTOR

	err_status = -1;
	getCLMessage(err_status); 
	err_func = "unknown";
	err_msg = "error";
}

// -------------------------------------------------------
//! \brief  エラーのステータスを受け取ってクラス変数に格納.
//! \param  a_msg    例外を投げるときのメッセージ.
//! \param  function エラーの発生場所(関数名).
//! \return なし.
clErrorClass::clErrorClass(const std::string &a_msg, const std::string &function)
{
	__CONSTRUCTOR

	err_status = -1;
	getCLMessage(err_status);
	err_func = function;
	err_msg = a_msg;
}

// -------------------------------------------------------
//! \brief  エラーのステータスを受け取ってクラス変数に格納.
//! \param  status   例外を投げるときのエラー番号.
//! \param  a_msg    例外を投げるときのメッセージ.
//! \param  function エラーの発生場所(関数名).
//! \return なし.
clErrorClass::clErrorClass(const cl_int &status, const std::string &a_msg, const std::string &function)
{
	__CONSTRUCTOR

	err_status = status;
	getCLMessage(err_status);
	err_func = function;
	err_msg = a_msg;
}

// -------------------------------------------------------
//! \brief  エラーのステータスを受け取ってクラス変数に格納.
//! \param  status   例外を投げるときのエラー番号.
//! \param  function エラーの発生場所(関数名).
//! \return なし.
clErrorClass::clErrorClass(const cl_int &status, const std::string &function)
{
	__CONSTRUCTOR

	err_status = status;
	getCLMessage(err_status);	// 受け取ったエラーステータスに対応するメッセージをクラス変数に格納
	err_msg = "";
}

// -------------------------------------------------------
//! \brief  特に何もしない.
//! \param  なし.
//! \return なし.
clErrorClass::~clErrorClass()
{
	__DESTRUCTOR
}

// -------------------------------------------------------
//! \brief  OpenCLのエラーメッセージをstring型で返す.
//! \param  なし.
//! \return const string 型のOpenCLのエラーメッセージ.
inline const std::string clErrorClass::clMsg() const
{
	return cl_err_msg;
}

// -------------------------------------------------------
//! \brief  OpenCLのエラーメッセージをchar型で返す.
//! \param  なし.
//! \return const char pointer 型のOpenCLのエラーメッセージ.
inline const char *clErrorClass::clMsgC() const
{
	return cl_err_msg.c_str();
}

// -------------------------------------------------------
//! \brief  エラーを出力する.
//! \param  なし.
//! \return なし.
void clErrorClass::showErrMsg() const
{
	std::cerr << std::endl;
	std::cerr << "ErrorFunction  : " << err_func   << std::endl;
	std::cerr << "ErrorMessage   : " << err_msg    << std::endl;
	std::cerr << "CLErrorMessage : " << cl_err_msg << std::endl;
	std::cerr << std::endl;
}

// -------------------------------------------------------
//! \brief OpenCLのエラーメッセージをクラス変数に格納.
//! \param status 例外を投げるときのエラー番号.
//! \return なし
void clErrorClass::getCLMessage(const cl_int status)
{
	switch(status){
	case CL_BUILD_PROGRAM_FAILURE:
		cl_err_msg = "Program build failed";
		break;
	case CL_COMPILER_NOT_AVAILABLE:
		cl_err_msg = "OpenCL compiler is not available";
		break;
	case CL_DEVICE_NOT_AVAILABLE:
		cl_err_msg = "Device is not available";
		break;
	case CL_IMAGE_FORMAT_NOT_SUPPORTED:
		cl_err_msg = "Image format is not supported";
		break;
	case CL_INVALID_ARG_INDEX:
		cl_err_msg = "Invalid arg index";
		break;
	case CL_INVALID_ARG_SIZE:
		cl_err_msg = "Invalid arg size";
		break;
	case CL_INVALID_ARG_VALUE:
		cl_err_msg = "Invalid arg value";
		break;
	case CL_INVALID_BINARY:
		cl_err_msg = "Invalid binary";
		break;
	case CL_INVALID_BUFFER_SIZE:
		cl_err_msg = "Invalid buffer size";
		break;
	case CL_INVALID_BUILD_OPTIONS:
		cl_err_msg = "Invalid build options";
		break;
	case CL_INVALID_COMMAND_QUEUE:
		cl_err_msg = "Invalid command queue";
		break;
	case CL_INVALID_CONTEXT:
		cl_err_msg = "Invalid context";
		break;
	case CL_INVALID_DEVICE:
		cl_err_msg = "Invalid device";
		break;
	case CL_INVALID_DEVICE_TYPE:
		cl_err_msg = "Invalid device type";
		break;
	case CL_INVALID_EVENT:
		cl_err_msg = "Invalid event";
		break;
	case CL_INVALID_EVENT_WAIT_LIST:
		cl_err_msg = "Invalid event wait list";
		break;
	case CL_INVALID_GL_OBJECT:
		cl_err_msg = "Invalid OpenGL object";
		break;
	case CL_INVALID_GLOBAL_OFFSET:
		cl_err_msg = "Invalid global offset";
		break;
	case CL_INVALID_HOST_PTR:
		cl_err_msg = "Invalid host pointer";
		break;
	case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR:
		cl_err_msg = "Invalid image format descriptor";
		break;
	case CL_INVALID_IMAGE_SIZE:
		cl_err_msg = "Invalid image size";
		break;
	case CL_INVALID_KERNEL:
		cl_err_msg = "Invalid kernel";
		break;
	case CL_INVALID_KERNEL_ARGS:
		cl_err_msg = "Invalid kernel args";
		break;
	case CL_INVALID_KERNEL_DEFINITION:
		cl_err_msg = "Invalid kernel definition";
		break;
	case CL_INVALID_KERNEL_NAME:
		cl_err_msg = "Invalid kernel name";
		break;
	case CL_INVALID_MEM_OBJECT:
		cl_err_msg = "Invalid memory object";
		break;
	case CL_INVALID_MIP_LEVEL:
		cl_err_msg = "Invalid MIP level";
		break;
	case CL_INVALID_OPERATION:
		cl_err_msg = "Invalid operation";
		break;
	case CL_INVALID_PLATFORM:
		cl_err_msg = "Invalid platform";
		break;
	case CL_INVALID_PROGRAM:
		cl_err_msg = "Invalid program";
		break;
	case CL_INVALID_PROGRAM_EXECUTABLE:
		cl_err_msg = "Invalid program executable";
		break;
	case CL_INVALID_QUEUE_PROPERTIES:
		cl_err_msg = "Invalid queue properties";
		break;
	case CL_INVALID_SAMPLER:
		cl_err_msg = "Invalid sampler";
		break;
	case CL_INVALID_VALUE:
		cl_err_msg = "Invalid value";
		break;
	case CL_INVALID_WORK_DIMENSION:
		cl_err_msg = "Invalid work dimension";
		break;
	case CL_INVALID_WORK_GROUP_SIZE:
		cl_err_msg = "Invalid work group size";
		break;
	case CL_INVALID_WORK_ITEM_SIZE:
		cl_err_msg = "Invalid work item size";
		break;
	case CL_MAP_FAILURE:
		cl_err_msg = "Memory mapping failed";
		break;
	case CL_MEM_COPY_OVERLAP:
		cl_err_msg = "Copying overlapped memory address";
		break;
	case CL_MEM_OBJECT_ALLOCATION_FAILURE:
		cl_err_msg = "Memory object allocation failure";
		break;
	case CL_OUT_OF_HOST_MEMORY:
		cl_err_msg = "Out of host memory";
		break;
	case CL_OUT_OF_RESOURCES:
		cl_err_msg = "Out of resources";
		break;
	case CL_PROFILING_INFO_NOT_AVAILABLE:
		cl_err_msg = "Profiling info is not available";
		break;
	case CL_SUCCESS:
		cl_err_msg = "succeeded";
		break;
	default:
		cl_err_msg = "Unknown error code: " + status;
		break;
	}
}
