#include "clPlatformClass.h"

//--------------------------------------------------------
//----------        clPlatformClass       ------------
//--------------------------------------------------------
// -------------------------------------------------------

// -------------------------------------------------------
//! \brief  プラットフォームの情報を取得する関数を呼び出す.
//! \param  platform_id プラットフォームのID.
//! \return なし.
clPlatformClass::clPlatformClass(cl_platform_id platform_id):
    num_info(NULL),
    any(NULL)
{try{
    __CONSTRUCTOR;
	this->setPlatform(platform_id);
}
catch(clErrorClass &err){err.showErrMsg();}catch(...){std::cerr << "unknown error." << std::endl;}}

// -------------------------------------------------------
//! \brief  デストラクタ. 確保した配列などを解放する.
//! \param  なし.
//! \return なし.
clPlatformClass::~clPlatformClass()
{
    __DESTRUCTOR;
    platform_info = NULL;
    for(unsigned int i=0; i<num_info; ++i){
        delete [] any[i];
    }
    delete [] any;
	any = NULL;
}

// -------------------------------------------------------
//! \brief  プラットフォームの詳細情報を取得する.
/*! プラットフォームの詳細情報を取得するために情報格納用の構造体を作成し
　　値を格納する */
//! \param  platform_id 取得するプラットフォームのID.
//! \return なし.
inline void clPlatformClass::setPlatform(cl_platform_id platform_id) throw(clErrorClass)
{
    static cl_platform_info tmp[]={
        CL_PLATFORM_PROFILE        ,
        CL_PLATFORM_VERSION        ,
        CL_PLATFORM_NAME           ,
        CL_PLATFORM_VENDOR         ,
        CL_PLATFORM_EXTENSIONS
    };
    this->num_info                = sizeof(tmp)/sizeof(*tmp);    
    this->platform_info           = tmp;
    this->any                     = new __int8*[this->num_info];

    cl_int status;    // エラー判定用
    size_t size_ret;
    for(unsigned int i=0; i<this->num_info; ++i){
        status = clGetPlatformInfo(platform_id,
                                   this->platform_info[i],
                                   NULL,
                                   NULL,
                                   &size_ret);
        if(status != CL_SUCCESS){
            throw clErrorClass(status, "clGetPlatformInfo get size faild", __FUNCTION__);
        }
        // プラットフォームの情報を取得する
		this->any[i] = new __int8[size_ret];
        status = clGetPlatformInfo(platform_id,
                                   this->platform_info[i],
                                   size_ret,
                                   this->any[i],
                                   NULL);
        if(status != CL_SUCCESS){
            throw clErrorClass(status, "clGetPlatformInfo faild", __FUNCTION__);
        }
    }
}

// -------------------------------------------------------
//! \brief  取得する情報を指定してプラットフォームの情報を表示する.
//! \param  num           知りたいプラットフォームの参照
//! \param  platform_info 知りたい情報
//! \return なし.
inline void clPlatformClass::showPlatformInfo(const cl_platform_info platform_info) const
{
	std::string str="";

	switch(platform_info){
	case CL_PLATFORM_PROFILE:
		str = "profile   ";
		break;
	case CL_PLATFORM_VERSION:
		str = "version   ";
		break;
	case CL_PLATFORM_NAME:
		str = "name      ";
		break;
	case CL_PLATFORM_VENDOR:
		str = "vendor    ";
		break;
	case CL_PLATFORM_EXTENSIONS:
		str = "extensions";	
		break;
	default:
		break;
	}

	std::cout << "Platform " << str << ": " << this->getPlatformInfo(platform_info) << std::endl;
}

// -------------------------------------------------------
//! \brief  プラットフォームの情報をすべて表示する.
//! \param  platform_index 知りたいプラットフォームの参照
//! \return なし.
void clPlatformClass::showPlatformInfoAll() const
{
	for(unsigned int i=0; i < this->num_info; ++i){
		showPlatformInfo(this->platform_info[i]);
	}
}

// -------------------------------------------------------
//! \brief  プラットフォームの情報を返す.
/*! プラットフォームの情報の値が不正な値なら例外をスローする */
//! \param  platform_info 取得するプラットフォームの情報.
//! \return 文字列リテラルへのポインタを返却.
const __int8 *clPlatformClass::getPlatformInfo(const cl_platform_info platform_info) const
{
    unsigned int index=0;
    for(index=0; index<num_info; ++index){
        if(this->platform_info[index] == platform_info){
            goto LOOP_SUCCESS;
        }
    }
    std::cerr << __FUNCTION__  << std::endl <<  "Invalied value cl_platform_info."<< std::endl;
	index=0;
LOOP_SUCCESS:
    return this->any[index];
}

