/* =============================================================================
 *  sc_errno.c
 *  Copyright (c) 2003 - 2013  Nomura Kei
 * =============================================================================
 */
#include <string.h>
#include <sc_compiler.h>
#include <sc_errno.h>



/**
 * エラー番号を取得します.
 *
 * @param エラー番号
 */
sc_errno_t getError(void)
{
#if (isWindows)
	return GetLastError();
#else
	return errno;
#endif
}


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


/**
 * 指定された errnum に対応するエラーメッセージを buf に格納します.
 * メッセージの獲得に成功した場合、true を返します.
 *
 * @param errnum エラー番号
 * @param buf    メッセージ格納用バッファ
 * @param buflen バッファサイズ
 * @return true/false (成功/失敗)
 */
bool getErrorMessage(const sc_errno_t errnum, char* const buf, const size_t buflen)
{
	bool result = true;

#if (isWindows)
	const DWORD ret = FormatMessage(
			(DWORD) FORMAT_MESSAGE_FROM_SYSTEM,		/* 動作フラグ			*/
			NULL,									/* メッセージ定義位置	*/
			errnum,									/* エラーコード			*/
			0UL,									/* 言語ID				*/
			buf,									/* バッファアドレス		*/
			(DWORD)  buflen,						/* バッファサイズ		*/
			NULL									/* 挿入句				*/
	);
	result = (ret != 0UL);

#elif ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !defined(_GNU_SOURCE))
	/* XSI準拠 strerror_r が提供されている場合	*/
	int ret = strerror_r(errnum, buf, buflen);
	result = (ret == 0);

#else
	/* 上記以外の場合, ANSI 準拠 strerror(errnum) を使用する	*/
	char*  tmpMsg = strerror(errnum);
	size_t size   = strlen(tmpMsg) + 1;
	if (size > buflen)
	{	/* バッファサイズが足りない	*/
		setError(SC_ERANGE);
		result = false;
	}
	else
	{
		strncpy(buf, tmpMsg, size);
		result = true;
	}
#endif	/* SC_isWindows */

	return result;
}


