#ifndef __GFL_EXCEPTION_H__
#define __GFL_EXCEPTION_H__

#pragma once

#include <nn.h>
#include <exception>


namespace gfl{
namespace err{

/*!
 * @brief  全ての例外クラスの基本クラス
 */
class Exception : public ::std::exception
{
protected:
  static const u32 MESSAGE_BUFFER_SIZE  = 256;
  static const u32 MESSAGE_TEMP_SIZE    = 256;
  static const u32 FILENAME_BUFFER_SIZE = 128;
  static const u32 FUNCNAME_BUFFER_SIZE = 64;
  //
  char      m_message[MESSAGE_BUFFER_SIZE];      // 内部メッセージ用バッファ
  char      m_fileName[FILENAME_BUFFER_SIZE];    // エラー発生ファイル名用バッファ
  char      m_funcName[FUNCNAME_BUFFER_SIZE];    // エラー発生関数名用バッファ
  u32       m_line;                              // エラー発生ライン数

public:
  /** ---------------------------------------------------------------------
  * @brief  コンストラクタ
  * @param  message エラーメッセージを追加したい際の文字列(省略可能)
  *         NULLの指定も可能。
  * @param  fileName エラーが発生したファイル名(省略可能)
  *         NULLの指定も可能。
  * @param  line     エラーが発生したファイル行番号(省略可能)
  * @param  funcName エラーが発生した関数名(省略可能)
  *         NULLの指定も可能。
  * @return 無し
  **/
  // -----------------------------------------------------------------------
            Exception( const char * message = NULL, const char *fileName = NULL, u32 line = 0, const char* funcName = NULL );

public:

  /** ---------------------------------------------------------------------
  * @brief  トレース情報を追加する
  * @param  fileName エラーが発生したファイル名(省略可能)
  *         NULLの指定も可能。
  * @param  line     エラーが発生したファイル行番号(省略可能)
  * @param  funcName エラーが発生した関数名(省略可能)
  *         NULLの指定も可能。
  * @return 無し
  **/
  // -----------------------------------------------------------------------
  void      Push( const char *fileName = NULL, u32 line = 0, const char* funcName = NULL );

  /** ---------------------------------------------------------------------
  * @brief  トレース情報をコンソールへ出力する
  * @param  無し
  * @return 無し
  **/
  // -----------------------------------------------------------------------
  void      PrintStackTrace( void ) const;

  /** ---------------------------------------------------------------------
  * @brief  例外が発行されたファイル名を取得
  * @param  無し
  * @return 例外が発行されたファイル名
  **/
  // -----------------------------------------------------------------------
  const char*  GetThrowsFileName( void ) const;

  /** ---------------------------------------------------------------------
  * @brief  例外が発行された関数名を取得
  * @param  無し
  * @return 例外が発行された関数名
  **/
  // -----------------------------------------------------------------------
  const char*  GetThrowsFunctionName( void ) const;

  /** ---------------------------------------------------------------------
  * @brief  例外が発行されたファイルの行数を取得
  * @param  無し
  * @return 例外が発行されたファイルの行数
  **/
  // -----------------------------------------------------------------------
  u32       GetThrowsFileLine( void ) const;

protected:
  void      SetMessage( const char *classHeader, const char* message );

private:
  void      SetName( char *dst, const char* src, u32 size );

};

} // err
} // gfl

#endif  // __GFL_EXCEPTION_H__
