/** * @file * リングバッファクラスを記述する。 */ #pragma once //----------------------------------------------------------- #include #include //----------------------------------------------------------- namespace apcl { namespace container { using ::apcl::util::u32; /// リングバッファのクラス template< typename T > class Ring { public: typedef T ValType; ///< テンプレートの型 /// UnitTest static void unitTest() { const int aSize = 30; Ring ring( aSize ); apclAssert( ring.size() == 1 ); apclAssert( ring.sizeMax() == aSize ); for ( int i = 0; i < aSize; ++i ) { apclAssert( ring.index() == i+1 ); apclAssert( ring.size() == i+2 ); ring.at(0) = i; ring.next(); } apclAssert( ring.index() == 0 ); apclAssert( ring.size() == ring.sizeMax() ); Ring ring2( ring ); for ( int i = 0; i < aSize; ++i ) apclAssert( ring.at(i) == ring2.at(i) ); Ring ring3( 1 ); ring3 = ring; for ( int i = 0; i < aSize; ++i ) apclAssert( ring.at(i) == ring3.at(i) ); apclAssert( ring3.at(0) == 0 ); } //================================================= /// @name 生成・破棄 //@{ /// バッファサイズを指定して作成 explicit Ring( const u32 aSizeMax ): size_( aSizeMax ), index_( 0 ), loopedFlg_( false ) { apclAssert( aSizeMax > 0 ); buff_ = new T[size_]; } /// コピーコンストラクタ explicit Ring( const Ring& aRing ): size_( aRing.sizeMax() ), index_( 0 ), loopedFlg_( false ) { apclAssert( size_ > 0 ); buff_ = new T[size_]; copy( aRing ); } /// デストラクタ virtual ~Ring() { delete[] buff_; } //@} //================================================= /// @name 複製 //@{ /// 引数の内容をコピーする。 void copy( const Ring& aRing ) { // 解放 delete[] buff_; // 初期化 size_ = aRing.sizeMax(); index_ = aRing.index(); loopedFlg_ = aRing.size() == aRing.sizeMax(); buff_ = new T[size_]; // コピー const u32 max = aRing.size(); for ( u32 i = 0; i < max; ++i ) { const u32 index = index_ >= i ? index_-i : size_-(i-index_); buff_[index] = aRing.at(i); } } //@} //================================================= /// @name サイズ //@{ /// 現在のサイズを取得する。 u32 size()const { return loopedFlg_ ? size_ : index_+1; } /// 最大サイズを取得する。 u32 sizeMax()const { return size_; } //@} //================================================= /// @name インデックス //@{ /// 現在指してるバッファのインデックス値を取得する。 u32 index()const { return index_; } /// 現在指しているバッファのインデックスを1つ移動する。 void next() { if ( index_ == size_ -1 ) { loopedFlg_ = true; index_ = 0; } else ++index_; apclAssert( index_ >=0 && index_ < size_ ); } //@} //================================================= /** * @name 参照取得 *
    * index = 0が,現在指してるバッファのインデックス。
    * インデックス値が増えるほど,過去にさかのぼる。
    * また,インデックス値は0以上,size()未満である必要がある。
    * 
*/ //@{ /// 要素の参照を取得する。 T& at( const u32 aIndex ) { apclAssert( aIndex >= 0 && aIndex < size() ); u32 index; if ( aIndex <= index_ ) index = index_ - aIndex; else { const u32 subMemo = aIndex - index_; index = size_ - subMemo; } apclAssert( index < size_ ); return buff_[index]; } /// at(aIndex)のconst版 const T& at( const u32 aIndex )const { apclAssert( aIndex >= 0 && aIndex < size() ); u32 index; if ( aIndex <= index_ ) index = index_ - aIndex; else { const u32 subMemo = aIndex - index_; index = size_ - subMemo; } apclAssert( index < size_ ); return buff_[index]; } //@} //================================================= /// @name 演算子 //@{ /// at()のカバー T& operator[]( const u32 aIndex ){ return at(aIndex); } /// at()のカバー const T& operator[]( const u32 aIndex )const{ return at(aIndex); } /// copy()のカバー const Ring& operator=( const Ring& aRing ) { copy( aRing ); return *this; } //@} private: T* buff_; u32 size_; u32 index_; bool loopedFlg_; }; }} // end of namespace ::apcl::container //----------------------------------------------------------- // EOF