/* vim: ts=4 sw=4 sts=4 ff=unix fenc=utf-8 :
 * =====================================================================
 *  sc_error.c
 *  Copyright (c)  2003 - 2011  sys0tem
 *  LICENSE :
 *	LGPL (GNU Lesser General Public License - Version 3,29 June 2007)
 *	http://www.gnu.org/copyleft/lesser.html
 *	or
 *	EPL (Eclipse Public License - v1.0)
 *	http://www.eclipse.org/legal/epl-v10.html
 * =====================================================================
 */
#include <string.h>
#include <sc_error.h>


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


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


/**
 * 指定された errnum に対応するエラーメッセージを buf に格納します.
 * メッセージの獲得に成功した場合、true を返します.
 *
 * @param errnum エラー番号
 * @param buf    メッセージ格納用バッファ
 * @param buflen バッファサイズ
 * @return true/false (成功/失敗)
 */
bool SC_getErrorMessage(int errnum, char* buf, size_t buflen)
{
#if (SC_isWindows)
	int ret = FormatMessage(
			FORMAT_MESSAGE_FROM_SYSTEM,		/* 動作フラグ			*/
			NULL,							/* メッセージ定義位置	*/
			errnum,							/* エラーコード			*/
			0,								/* 言語ID				*/
			buf,							/* バッファアドレス		*/
			buflen,							/* バッファサイズ		*/
			NULL							/* 挿入句				*/
			);
	if (ret == 0)
	{	/* メッセージ取得失敗	*/
		return false;
	}
	return true;

#elif ((_POSIX_C_SOURCE >= 200112L || __XOPEN_SOURCE >= 600) && ! _GNU_SOURCE)
	/* XSI準拠 strerror_r が提供されている場合	*/
	int ret = strerror_r(errnum, buf, buflen);
	if (ret == 0)
	{	/* メッセージ取得成功	*/
		return true;
	}
	return false;

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


