////////////////////////////////////////////////////////////////////////////
// SelRange.h
// 選択範囲を示すクラス
//

// 文字列の選択範囲の表現は常に半開空間で表現される
// 選択範囲は開始位置目の文字から、終了位置−１文字目までとする。

#if !defined( SELRANGE_H_423CE64F_021B_4b59_A597_A58C4D52D0DA_ICLUDED_ )
#define SELRANGE_H_423CE64F_021B_4b59_A597_A58C4D52D0DA_ICLUDED_

#include <assert.h>

/*
// CSelRange型の変数を、終了位置で比較するための関数オブジェクト
class CSelRange_EPosPR
{
public:
	CSelRange_EPosPR(){};
	~CSelRange_EPosPR(){};
	template < class _T >
	bool operator ()( const _T& r1, const _T& r2 ) {
		return r1.GetEPos() < r2.GetEPos();
	};
};
*/

template < class _T >
class CSelRange
{
public:

	// コンストラクタ
	CSelRange() : SPos( 0 ), EPos( 0 ) {};

	CSelRange( _T s, _T e ){
		SetPosEx( s, e );
	};

	// デストラクタ
	~CSelRange(){
	};

	// 開始位置取得
	inline _T GetSPos() const
	{ return SPos; };

	// 終了位置取得
	inline _T GetEPos() const 
	{ return EPos; };

	// 選択範囲長を取得
	inline _T GetLength() const
	{ return EPos - SPos; };

	// 開始位置設定
	inline void SetSPos( _T s ){
		assert( !( EPos < s ) );
		SPos = s;
	};

	// 終了位置設定
	inline void SetEPos( _T e ){
		assert( !( SPos > e ) );
		EPos = e;
	};

	// 範囲の設定
	inline void SetPos( _T s, _T e ){
		assert( !( s > e ) );
		SPos = s;
		EPos = e;
	};
	// 順番が不正な場合は入れ替えてから値を設定する
	inline void SetPosEx( _T s, _T e ){
		if ( s > e ) {
			_T w = s;
			s = e;
			e = w;
		}
		SPos = s;
		EPos = e;
	};

	// 代入
	const CSelRange& operator =( const CSelRange& r )
	{
		SPos = r.GetSPos();
		EPos = r.GetEPos();
		return *this;
	};

	// 等号
	bool operator ==( const CSelRange& r ) const {
		return r.GetSPos() == SPos && r.GetEPos() == EPos;
	};

	// 不等号
	// 開始地点により比較する
	bool operator <( const CSelRange& r ) const {
		return SPos < r.SPos;
	};

	bool operator !=( const CSelRange& r ) const {
		return !( this->operator ==( r ) );
	};

	// 共通部分の算出
	CSelRange And( const CSelRange &r ) const {
		if ( r == (*this) )
			return r;	// 一致する場合

		if ( SPos < r.SPos ) {
			if ( EPos <= r.SPos )
				return CSelRange< _T >( 0, 0 );	// 一致する部分がない
			return CSelRange< _T >( r.SPos, EPos < r.EPos ? EPos : r.EPos );
		}
		else {
			if ( r.EPos <= SPos )
				return CSelRange< _T >( 0, 0 );	// 一致する部分がない
			return CSelRange< _T >( SPos, EPos < r.EPos ? EPos : r.EPos );
		}
	};

	// 和演算
	// (*this)とrとを内包する範囲を求める
	CSelRange Add( const CSelRange &r ) const {
		_T t1;
		_T t2;
		if ( SPos < r.SPos )
			t1 = SPos;
		else
			t1 = r.SPos;
		if ( EPos > r.EPos )
			t2 = EPos;
		else
			t2 = r.EPos;
		return CSelRange< _T >( t1, t2 );
	};
protected:
	_T SPos;	// 開始位置
	_T EPos;	// 終了位置
};


#endif // SELRANGE_H_423CE64F_021B_4b59_A597_A58C4D52D0DA_ICLUDED_

