/**
  * flag.js
  * 
  * @auther		A.OG
  * @history		1.00	2007/08/22		create new
  * @description	
  * 
  */




/**
 * コンストラクタ。
 * フラグ処理クラス。
 *
 * @param	flagString	フラグ文字列。
 *			 			先頭１文字目で進数を判定する。
 *			 			d/D		10進数
 *			 			o/O		8進数
 *			 			x/X		16進数
 *			 			b/B		2進数
 *			 			なし	2進数（ディフォルト）
 */
function Flag( flagString ) {
	var		flag ;
	var		ii, type ;
	var		checkFlag=true ;


	this.value = 0 ;
	if ( flagString.charAt(0)=="x" || flagString.charAt(0)=="X" ) {
		flagString = flagString.slice( 1, flagString.length ) ;
		if( isNaN(flagString)!=NaN ) {
			this.value = parseInt( flagString, 16 ) ;
		}
	}
	else if ( flagString.charAt(0)=="d" || flagString.charAt(0)=="D" ) {
		flagString = flagString.slice( 1, flagString.length ) ;
		if( isNaN(flagString)!=NaN ) {
			this.value = parseInt( flagString, 10 ) ;
		//	this.string = flagString ;
		//	this.size = flagString.length ;
		}
	}
	else if ( flagString.charAt(0)=="o" || flagString.charAt(0)=="O" ) {
		flagString = flagString.slice( 1, flagString.length ) ;
		if( isNaN(flagString)!=NaN ) {
			this.value = parseInt( flagString, 8 ) ;
		}
	}
	else if( isNaN(flagString)!=NaN || flagString.charAt(0)=="b" || flagString.charAt(0)=="B" ) {
		if( flagString.charAt(0)=="b" || flagString.charAt(0)=="B" ) {
			flagString = flagString.slice( 1, flagString.length ) ;
		}

		if( isNaN(flagString)!=NaN ) {
			this.value = parseInt( flagString, 2 ) ;
		//	this.string = flagString ;
		//	this.size = flagString.length ;
		}
	}
	else {
		alert(	"属性フラグが有効な文字列でない\n[" + flagString + "]") ;
		checkFlag = false ;
	}
}



/**
 * 全体フラグ値を返す。
 *
 * @return	全体フラグ値。
 */
Flag.prototype.getValue = function () {
	return( this.value ) ;
}

/**
  * フラグを変更する（OR演算）。
  * 
  * @param	newFlag	。
  */
Flag.prototype.bitOrFlag = function ( newFlag ) {
	this.value |= parseInt(newFlag,2) ;
}



/**
 * 指定された桁のビットをセットする。
 *
 * @param	bit		セットするビットの桁位置。
 *					x x x x x x x x
 *					7 6 5 4 3 2 1 0
 */
Flag.prototype.setBit = function ( bit ) {
	var		setMask = 0 ;

	if( isNaN(bit) == NaN ) {
		alert( "指定桁位置(" + bit + ")が不正である" ) ;
		return( false ) ;
	}

	/*	ビットセット	*/
	setMask = Math.pow( 2, bit ) ;
	this.value |= setMask ;

	/*	ビットセット	*/
	if( this.size<bit ) {
		this.size = bit ;
	}
}



/**
 * 指定された桁のビットをリセットする。
 *
 * @param	bit		セットするビットの桁位置。
 *					x x x x x x x x
 *					7 6 5 4 3 2 1 0
 */
Flag.prototype.resetBit = function ( bit ) {
	var		mask = 0 ;
	var		ii ;
	var		value=0 ;
	var		msg="" ;

	if( isNaN(bit) == NaN ) {
		alert( "指定桁位置(" + bit + ")が不正である" ) ;
		return	false ;
	}

	for( ii=0; ii<this.size; ii++ ) {
		mask = ( this.getBitValue(ii)==0 || ii==bit ) ? 0 : Math.pow( 2, ii ) ;
		value |= mask ;
		msg += sprintf( "%2d  %d\n", ii, value ) ;
	}
	//alert( msg ) ;

	this.value = value ;
}



/**
 * 指定された桁のフラグ値を返す。
 *
 * @param	bit		フラグ値を取得する桁位置。
 *					x x x x x x x x
 *					7 6 5 4 3 2 1 0
 *
 * @return	指定された桁のフラグ値。
 *			以下の場合は、<code>false</code>を返す。
 *			・フラグサイズが０である。
 *			・指定桁位置がフラグサイズを超える。
 */
Flag.prototype.getBitValue = function ( bit ) {
	var		mask = 0 ;

	if( this.size<=0 ) {
		return	false ;
	}

	if( isNaN(bit) == NaN ) {
		alert( "指定桁位置(" + bit + ")が不正である" ) ;
		return	false ;
	}

	if( bit>this.size ) {
		alert( "指定桁位置(" + bit + ")がフラグサイズ[" + this.size + "]を超えている" ) ;
		return	0 ;
	}

	/*	ビットマスク生成	*/
	mask = Math.pow( 2, bit ) ;

	/*	ビットマスクと指定ビット位置のAND演算結果を返す	*/
	return( ((mask & this.getValue()) != 0) ? 1 : 0 ) ;
}



/**
 * 指定桁区間のフラグ値を返す。
 *
 * @param	startBit	フラグ値を取得する桁開始位置。
 *						開始位置は０（最終bit目を0とする）。
 *
 *			endBit		フラグ値を取得する桁終了位置。
 *						開始位置は０（1bit目は0とする）。
 *						省略時は開始位置と同じとして解釈される。
 *
 * @return	指定された桁のフラグ値。
 *			以下の場合は、<code>false</code>を返す。
 *			・フラグサイズが０である。
 *			・指定桁位置がフラグサイズを超える。
 */
Flag.prototype.getMultiBitValue = function ( endBit, startBit ) {
	var		result = 0 ;
	var		ii ;
	var		bit_start, bit_end, tmp ;

	if( this.size<=0 ) {
		return( false ) ;
	}

	if( isNaN( startBit ) == NaN ) {
		alert( "指定開始桁位置(" + startBit + ")が不正である" ) ;
		return( false ) ;
	}
	else {
		bit_start = parseInt( startBit, 10 ) ;
	}

	if( typeof(endBit) != "undefined" ) {
		if( isNaN( endBit ) == NaN ) {
			alert( "指定終了桁位置(" + endBit + ")が不正である" ) ;
			return( false ) ;
		}
		else {
			bit_end = parseInt( endBit, 10 ) ;
		}
	}
	else {
		bit_end = bit_start ;
	}

	/*	ビット指定の大小関係が逆の場合、入れ替える	*/
	if(  bit_start > bit_end ) {
		tmp = bit_start ;
		bit_start = bit_end ;
		bit_end = tmp ;
	}

	for( ii=bit_end; ii>=bit_start; ii-- ) {
		result += ( this.getBitValue(ii)!=0 ) ? Math.pow( 2, ii ) : 0 ;
	}
	result >>= bit_start ;

	return( result ) ;
}

