/*
 *	cliprinb.h
 *
 *	無駄を減らしたリングバッファ
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2015 Naoyuki Sawa
 *
 *	* Mon Nov 16 21:09:12 JST 2015 Naoyuki Sawa
 *	- 1st リリース。
 *	- 当モジュールは、リングバッファのアルゴリズムの覚え書きとして作成しました。
 *	  主な目的は、当モジュールを直接アプリケーションで利用する事よりも、当モジュールの実装を参照して個々のモジュールで独自にリングバッファを実装する事です。
 *	  2015/11/16現在、cliptaps.cモジュールが、当仕様に沿ったリングバッファを実装しています。
 *	- これまでは、リングバッファを作成する時は、次回読み出し位置(iGetPos)と要素格納数(iElmCnt)を管理するようにしていました。
 *	  そうしていた理由は、次回読み出し位置(iGetPos)と次回書き込み位置(iAddPos)を管理する方法だと、空とフルの状態が両方とも(iGetPos==iAddPos)で表され、区別出来ないからです。
 *	  区別するためには、iAddPosをiGetPosの一つ手前の要素までしか格納しないようにする必要が生じて、(バッファ容量-1)までしか利用出来ず、無駄が生じます。
 *	  次回読み出し位置(iGetPos)と要素格納数(iElmCnt)を管理する方法ならば、空の状態は(iElmCnt=0)、フルの状態は(iElmCnt=nElmCnt)で表され、区別出来ます。
 *	- しかし、次回読み出し位置(iGetPos)と要素格納数(iElmCnt)を管理する方法にも問題が有りました。
 *	  バッファ容量を(2^N)とする場合、iAddPosの最大値は(2^N-1)ですが、iElmCntの最大値は(2^N)を表現できなければいけません。
 *	  たとえば、バッファ容量を256とする場合、iAddPosは(uint8_t)で済みますが、iElmCntは(uint16_t)とする必要が有り、無駄が生じます。
 *	- 以上の問題の解決策として、次回読み出し位置(iGetPos)と次回書き込み位置(iAddPos)を管理する方法をとるが、残りの1要素も有効に活用する方法を考えました。
 *	  RinBuf_Get()は読み出した要素をコピーして返すのではなく、バッファ内の要素へのポインタを返す事にしました。
 *	  これが'残りの1要素'の用途となって、コピー回数を減らす効果が有り、有効に利用出来ます。
 *	- 当モジュールではiAddPosやiGetPosを(int)としているので、上記の改善はあまり意味が無いのですが、iAddPosやiGetPosを(uint8_t)とするモジュールには有効です。
 *	  今後、リングバッファを使用するモジュールでは、当モジュールの実装を参照して、個々にリングバッファを実装して下さい。
 *	  その際、上記の説明を参照して、iAddPosやiGetPosを最小限の変数サイズとして下さい。
 *	* Wed Nov 18 21:37:53 JST 2015 Naoyuki Sawa
 *	- 'extern "C" {'〜'}'で囲みました。.cppを含むWin32プロジェクトからもインクルード出来るようにするためです。
 */
#ifndef __CLIP_RINB_H__
#define __CLIP_RINB_H__
#ifdef  __cplusplus
extern "C" {
#endif//__cplusplus
/****************************************************************************
 *	
 ****************************************************************************/
//リングバッファ
typedef struct _ST_RinBuf {
	int	nElmSiz;				//+ 0, 4 要素のバイト数			1〜INT_MAX
	int	iMaxPos;				//+ 4, 4 iAddPos,及び,iGetPosの最大値	1〜INT_MAX	(=TBL_Buf[]の要素数-1)	少なくとも書き込み用に1要素と参照用に1要素の2要素が必要。従ってiMaxPosの下限は2-1=1である。
	int	iAddPos;				//+ 8, 4 要素を書き込む位置		0〜iMaxPos
	int	iGetPos;				//+12, 4 要素を読み出す位置		0〜iMaxPos
	int	nOvrCnt;				//+16, 4 オーバーランが発生した回数	0〜INT_MAX	オーバーランが発生した場合、既にバッファ内に有る要素は維持し、書き込もうとした要素が失われる。
#ifndef __RENESAS__
	char	TBL_Buf[0/*(nElmSiz*(iMaxPos+1))*/];	//+20,(nElmSiz*(iMaxPos+1))
#else //__RENESAS__
	char	TBL_Buf[1/*(nElmSiz*(iMaxPos+1))*/];	//+20,(nElmSiz*(iMaxPos+1))	//Hewは要素数[0]の配列に対応していないので、要素数[1]として調整しました。
#endif//__RENESAS__
} ST_RinBuf;						//=20+(nElmSiz*(iMaxPos+1))
/*---------------------------------------------------------------------------*/
ST_RinBuf* RinBuf_New(int nElmSiz/*1〜*/, int nElmCnt/*2〜*/);
void RinBuf_Init(ST_RinBuf* pRinBuf, int nElmSiz/*1〜*/, int nElmCnt/*2〜*/);
void RinBuf_Add(ST_RinBuf* pRinBuf, const void* pElm);
void* RinBuf_Get(ST_RinBuf* pRinBuf);
int RinBuf_Ovr(ST_RinBuf* pRinBuf);
#ifdef  __cplusplus
}//extern "C"
#endif//__cplusplus
#endif//__CLIP_RINB_H__
