/* vim: ts=4 sw=4 sts=4 ff=unix fenc=utf-8 :
 * =====================================================================
 *  sc_stream_file.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_os.h>
#include <sc_error.h>
#include <sc_mmgr.h>
#include <sc_stream_file.h>

/* ---------------------------------------------------------------------
 *  プロトタイプ宣言
 * ---------------------------------------------------------------------
 */
static int  SC_Stream_stream_fileRead(SC_Stream* strm, void* buff, size_t size);
static int SC_Stream_stream_fileWrite(SC_Stream* strm, const void* buff, size_t size);
static bool SC_Stream_stream_fileClose(SC_Stream* strm);

/**
 * ファイルストリームを構築します。
 * 構築に失敗した場合、NULL を返します。
 *
 * @param fp       ファイルディスクリプタ
 * @param buffSize 読み取りバッファサイズ
 * @return ストリーム
 */
SC_Stream* SC_Stream_newFileStream(FILE* fp, size_t buffSize)
{
	SC_Stream* strm;
	strm = (SC_Stream*) malloc(sizeof(SC_Stream) + buffSize);
	if (strm == NULL)
	{	/* メモリ確保失敗	*/
		return NULL;
	}
	strm->_data.buff       = (char*) (strm + 1);
	strm->_data.buffSize   = buffSize;
	strm->_data.off        = 0;
	strm->_data.size       = 0;
	strm->_strmInfo        = fp;
	strm->readc            = SC_Stream_readc_;
	strm->read             = SC_Stream_read_;
	strm->readExact        = SC_Stream_readExact_;
	strm->readLine         = SC_Stream_readLine_;
	strm->limitedRead      = SC_Stream_limitedRead_;
	strm->writec           = SC_Stream_writec_;
	strm->write            = SC_Stream_write_;
	strm->writeExact       = SC_Stream_writeExact_;
	strm->_readCore        = SC_Stream_stream_fileRead;
	strm->_writeCore       = SC_Stream_stream_fileWrite;
	strm->close            = SC_Stream_stream_fileClose;
	return strm;
}


/**
 * ファイルを読み込みます。
 * ファイルの末尾に達した場合 0 を返します。
 * エラーが発生した場合 -1 を返します。
 *
 * @param strm ストリーム
 * @param buff バッファ
 * @param size サイズ
 * @return 読み取ったバッファサイズ
 */
static
int SC_Stream_stream_fileRead(SC_Stream* strm, void* buff, size_t size)
{
	int    ret;
	size_t readSize;
	readSize  = fread(buff, 1, size, strm->_strmInfo);

	ret = ferror((FILE*) strm->_strmInfo);
	if (ret != 0)
	{	/* エラーが発生している	*/
		return -1;
	}
	return readSize;
}


/**
 * ファイルに書き込みます。
 *
 * @param strm ストリーム
 * @param buff バッファ
 * @param size サイズ
 * @return 書き出したバッファサイズ
 */
static
int SC_Stream_stream_fileWrite(SC_Stream* strm, const void* buff, size_t size)
{
	int    ret;
	size_t writeSize;
	writeSize = fwrite(buff, 1, size, strm->_strmInfo);
	ret       = ferror((FILE*) strm->_strmInfo);
	if (ret != 0)
	{	/* エラーが発生している	*/
		return -1;
	}
	return writeSize;
}


/**
 * ストリームを close します。
 * close に失敗した場合、false を返します。
 *
 * @param strm ストリーム
 */
static
bool SC_Stream_stream_fileClose(SC_Stream* strm)
{
	int ret;
	if (strm->_strmInfo == NULL)
	{
		return false;
	}

	ret = fclose(strm->_strmInfo);
	strm->_strmInfo = NULL;
	if (ret == 0)
	{
		return true;
	}
	return false;
}


