
#ifndef DKUTIL_BIT_HPP
#define DKUTIL_BIT_HPP


#include <dkutil/macro.hpp>

namespace dkutil{



/*!
@param buff [out] 文字列を格納するバッファ
@param buffsize [in] バッファのサイズ（バイト単位
@param dt [in] ビジュアル化したいビット
@param left[in] trueだと左からbitを文字列にする。
@return trueで成功
@todo & とか 配列とかビットシフトとかメチャクチャすれば高速化できそうな気もする。
*/
///ビットを文字列にしてビジュアル化する。
template<typename T>
inline bool BitIsVisualized( char *buff,size_t buffsize,T dt ,bool left=false)
{

	size_t len = sizeof(dt) * CHAR_BIT;;
	char *p=buff;
	if(len+1 > buffsize){//NULL文字分
		return false;
	}
 // int a=0;
	if(left==false){
		//for (size_t i=len-1; i >= 0; i-- ){
		for(int i=(int)(len - 1); i >= 0 ;i--){
				// ビットをぶち込む
				if(0 > _snprintf(p,buffsize,"%u",( dt>>i ) & 0x0001))
					return false;
				p++;
		}
	}else{
		for (size_t i=0; i < len; i++ ){
			// ビットをぶち込む
			if(0 > _snprintf(p,buffsize,"%u",( dt>>i ) & 0x0001))
				return false;
			p++;
		}
	}
	return true;
}

inline int bit_printf(ULONG ull,bool isReturn = true){
	char buff[64 + 1 + 1];
	BitIsVisualized(buff,sizeof(buff),ull,false);
	if(isReturn){
		strncat(buff,"\n",1);
	}
	return printf(buff);
}


///ビットの数を数える Hacker's Delight より
inline size_t NumOfBits(ULONG bits) {
  bits = (bits & 0x55555555) + (bits >> 1 & 0x55555555);
  bits = (bits & 0x33333333) + (bits >> 2 & 0x33333333);
  bits = (bits & 0x0f0f0f0f) + (bits >> 4 & 0x0f0f0f0f);
  bits = (bits & 0x00ff00ff) + (bits >> 8 & 0x00ff00ff);
  return (bits & 0x0000ffff) + (bits >>16 & 0x0000ffff);
}


///バイト単位をビット単位にする。
namespace detail{
template<class T>
class ByteToBit{
public:
	typedef T value_type;

	inline bool operator()(T byte,T *bit){
		if(byte > std::numeric_limits<T>::digits / 8){
			return false;
		}
		dkcmNOT_ASSERT(NULL==bit);
		*bit = byte * 8;
		return true;
	}
		
};//end of class


///スマン、これヨクワカラン
#define DKUTIL_MASK_BIT(bit,n) (bit &= (1 << n))

	//(bit &= ( (0xFFFFFFFF << min_ ) >> (32 - max_) ) ) 
	//( bit &= (	( 0xFFFFFFFF << ( max_ - min_ )  )	&	( 0xFFFFFFFF >> ( 32 - max_ ) )	) )

#define DKUTIL_MASK_BIT_RANGE(bit,min_,max_) \
	(bit &= ( 0xFFFFFFFF >> ( 32 - max_ - 1 )) & (0xFFFFFFFF << (min_)) )

template<class T>
class MaskBit{
public:
	typedef T value_type;

	inline void mask_(T *value,T mask){
		DKUTIL_MASK_BIT((*value),mask);
	}
	inline void mask_range_(T *value,T min_,T max_){
		DKUTIL_MASK_BIT_RANGE((*value),min_,max_);
	}
	inline T operator()(T value,T mask){
		mask_(&value,mask);
		return value;
	}
	inline T operator()(T value,T min_,T max_){
		mask_range_(&value,min_,max_);
		return value;
	}
};//end of class




}//end of detail namespace


inline bool ByteToBit(ULONGLONG byte,ULONGLONG *bit){
	static detail::ByteToBit<ULONGLONG> u;
	return u(byte,bit);
}

inline bool ByteToBit(ULONG byte,ULONG *bit){
	static detail::ByteToBit<ULONG> u;
	return u(byte,bit);
}

inline ULONGLONG MaskBit64(ULONGLONG target,ULONGLONG mask){
	static detail::MaskBit<ULONGLONG> m;
	return m(target,mask);
}

inline ULONGLONG MaskBit64(ULONG target,ULONGLONG min_,ULONGLONG max_){
	static detail::MaskBit<ULONGLONG> m;
	return m(target,min_,max_);
}
inline ULONG MaskBit(ULONG target,ULONG mask){
	static detail::MaskBit<ULONG> m;
	return m(target,mask);
}

inline ULONG MaskBit(ULONG target,ULONG min_,ULONG max_){
	static detail::MaskBit<ULONG> m;
	return m(target,min_,max_);
}

}//end of dkutil namespace



#endif