バイナリデータを扱う上で必ず必要になる情報はバイナリデータの長さである。
これらをまとめて、かつ参照カウンタで寿命を管理する簡単便利なクラスを作ってみた。
参照カウンタの加減算にロックはかけていないので、スレッドには未対応である。



////////////////////////////////////////////////////////////////////////////////////////////////

// bin_ = 参照カウンタ(DWORD)+長さ(DWORD)+バイナリデータ(bi_length byte)

class Binary
{
public :
Binary():bin_(0){}
Binary( const BYTE* bi, DWORD bi_length )
{
DWORD alclen = 4 + bi_length;
bin_ = new BYTE[ alclen+sizeof(DWORD)*2];

DWORD cnt = 1;
memcpy( bin_, &cnt, sizeof(DWORD) );
memcpy( bin_+sizeof(DWORD), &bi_length, sizeof(DWORD) );

if ( bi )
memcpy( bin_+sizeof(DWORD)*2, bi, bi_length );
else
memset( bin_+sizeof(DWORD)*2 , 0, bi_length );// fill zero.
}
Binary( const Binary& s ):bin_(0)
{
this->operator=(s);
}

~Binary(){ clear(); }

// バイナリデータ
BYTE* get() const
{
return bin_ + sizeof(DWORD)*2;
}
// 長さ
DWORD length() const{ return *(DWORD*)(bin_ + sizeof(DWORD)); }

void clear()
{
if ( bin_ )
{
DWORD& cnt = *(DWORD*)bin_;
cnt--;

if ( cnt == 0 )
delete [] bin_;

bin_ = NULL;
}
}

Binary& operator=(const Binary& src)
{
if ( this == &src ) return *this;

clear();

DWORD& cnt = *(DWORD*)src.bin_;
cnt++;

bin_ = src.bin_;

return *this;
}

Binary clone() const
{
return Binary(get(), len());
}

Binary cut(DWORD pos, DWORD xlen) const
{
_ASSERT( pos + xlen <= len());
_ASSERT( 0 < xlen );
return Binary(get()+pos, xlen);
}
Binary& shrink(DWORD xlen )
{
_ASSERT( xlen < length());
memcpy( bin_+sizeof(DWORD), &xlen, sizeof(DWORD) );
return *this;
}
bool isnull() const { return (bin_ == nullptr); }
private :
BYTE* bin_;
};