/* =============================================================================
 *  scpp_errno.cpp
 *  Copyright (c)  2003 - 2011  Nomura Kei
 *  LICENSE :
 *  LGPL (GNU Lesser General General Public License - Version 3,29 June 2007)
 *  http://www.gnu.org/copyleft/lesser.html
 * =============================================================================
 *
 * エラーモジュール
 * エラー番号, エラーメッセージを扱います.
 *
 */
#include <cstring>
#include <scpp_errno.hpp>

#ifndef MAXMSG
#define MAXMSG (256)
#endif

namespace scpp
{
namespace Errno
{


/**
 * 最後に発生したエラー番号を取得します.
 *
 * @return エラー番号
 */
int getError()
{
#if (SCPP_IS_WINDOWS)
	return GetLastError();
#else
	return errno;
#endif
}


/**
 * エラー番号を設定します.
 *
 * @param errnum 設定するエラー番号
 */
void setError(int errnum)
{
#if (SCPP_IS_WINDOWS)
	SetLastError(errnum);
#else
	errno = errnum;
#endif
}


/**
 * 指定された errnum に対応するエラーメッセージを取得します.
 *
 * @param errnum エラー番号
 * @param errStr エラー文字列格納用
 * @return true/false (エラーメッセージ取得成功/失敗)
 */
bool getErrorMessage(std::string* errStr, int errnum)
{
	bool result = true;
#if (SCPP_IS_WINDOWS)
	LPVOID lpMsgBuf;
	int ret = FormatMessage(
			FORMAT_MESSAGE_ALLOCATE_BUFFER				// 動作フラグ
			| FORMAT_MESSAGE_FROM_SYSTEM
			| FORMAT_MESSAGE_IGNORE_INSERTS,
			0,											// メッセージ定義位置
			errnum,										// エラーコード
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),	// 言語ID
			(LPSTR) &lpMsgBuf,							// バッファアドレス
			0,											// バッファサイズ
			0);											// 挿入句
	*errStr = (char*) lpMsgBuf;
	LocalFree(lpMsgBuf);
	result = (ret != 0);

#elif ((_POSIX_C_SOURCE >= 200112L || __XOPEN_SOURCE >= 600) && ! _GNU_SOURCE)
	// XSI準拠 strerror_r が提供されている場合
	char buf[MAXMSG];
	int ret = stderror_r(errnum, buf, sizeof(buf));
	*errStr = buf;
	result = (ret == 0);

#else
	// 上記以外の場合, ANSI 準拠 strerror(errnum) を使用する
	char* tmpMsg = strerror(errnum);
	*errStr = tmpMsg;
	result = true;

#endif

	return result;
}


}	// namespace errno
}	// namespace scpp


