#include <stdlib.h>
#include "binary.h"
#include "string.h"
#include "stdio.h"
#include "algorithm.h"

CBinary::CBinary(void)
{
	m_pData=NULL;
	m_nSize=0;
}
void CBinary::Init(const void *pBuffer,uint16_t iLength)
{
	if(iLength==0){
		m_pData=NULL;
		m_nSize=0;
	}
	else{
		m_pData=new uint8_t[iLength];
		ASSERT_EX(m_pData!=NULL);
		m_nSize=iLength;
		if(pBuffer)
			memcpy(m_pData,pBuffer,iLength);
		else
			memset(m_pData,0,iLength);
	}
}
CBinary::CBinary(uint16_t iLength)
{
	Init(NULL,iLength);
}
CBinary::CBinary(const char *pBuffer, uint16_t iLength)
{
	Init((void*)pBuffer,iLength);
}
CBinary::CBinary(uint8_t *pBuffer, uint16_t iLength)
{
	Init(pBuffer,iLength);
}
CBinary::CBinary(const CBinary& binData)
{
	Init(binData.m_pData,binData.m_nSize);
}
CBinary::~CBinary(void)
{
	Empty();
}
void CBinary::operator = (const CBinary& binData)
{
	Empty();
	Append(binData.m_pData,binData.m_nSize);
}
CBinary CBinary::operator + (const CBinary& binData)
{	
	CBinary bin(m_pData,m_nSize);
	bin.Append(binData.m_pData,binData.m_nSize);
	return bin;
}
CBinary CBinary::operator + (uint8_t ucNewElement)
{	
	CBinary bin(m_pData,m_nSize);
	bin.Append(&ucNewElement,1);
	return bin;
}
CBinary& CBinary::operator += (const CBinary& binData)
{
	Append(binData.m_pData,binData.m_nSize);
	return *this;
}
CBinary& CBinary::operator += (uint8_t ucNewElement)
{
	uint8_t tmp=ucNewElement;
	Append(&tmp,1);
	return *this;
}
#ifndef _BOOT
bool CBinary::operator <= (const CBinary& binData)
{
	if(*this < binData)return true;
	if(*this == binData)return true;
	return false;
}
bool CBinary::operator >= (const CBinary& binData)
{
	if(*this < binData)return false;
	return true;
}
#endif

bool CBinary::operator > (const CBinary& binData)
{
	if(*this == binData)return false;
	if(*this < binData)return false;
	return true;
}
bool CBinary::operator < (const CBinary& binData)
{
	if(binData.m_pData == NULL)return false;
	else if(this->m_pData == NULL)return true;

	uint16_t nLength = MIN(this->m_nSize, binData.m_nSize);
	for(int i=0;i<nLength;i++){
		if(this->m_pData[i]<binData.m_pData[i])return true;
		if(this->m_pData[i]>binData.m_pData[i])return false;
	}
	return (this->m_nSize < binData.m_nSize)?true:false;
}
uint8_t CBinary::operator [] (uint16_t nIndex) const
{
	ASSERT_EX(this->m_pData != NULL);
	ASSERT_EX(nIndex <m_nSize) ;

	return (uint8_t)m_pData[nIndex];
}
uint8_t& CBinary::operator [] (uint16_t nIndex)
{
	ASSERT_EX(this->m_pData != NULL);
	ASSERT_EX(nIndex <m_nSize) ;

	return m_pData[nIndex];
}
bool CBinary::operator == (const CBinary& binData)
{
	if(this->m_pData == NULL || binData.m_pData == NULL){
		if(this->m_pData == NULL && binData.m_pData == NULL)return true;
		else return false;
	}
	if(this->m_nSize != binData.m_nSize)return false;
	for(int i=0;i<binData.m_nSize;i++){
		if(this->m_pData[i]!=binData.m_pData[i])return false;
	}
	return true;
}
#ifndef _BOOT
void CBinary::RemoveAt(uint16_t nIndex,uint16_t nCount)
{
	ASSERT_EX(nIndex + nCount <= m_nSize);
	if(nCount==0)return;
	int nMoveCount = m_nSize - (nIndex + nCount);
	if (nMoveCount)memmove(&m_pData[nIndex], &m_pData[nIndex + nCount],nMoveCount);
	m_nSize -= nCount;
}
void CBinary::InsertAt(uint16_t nIndex,uint8_t ucNewElement,uint16_t nCount)
{
	uint16_t nTemp=m_nSize+nCount;
	uint8_t *pTemp=new uint8_t[nTemp];
	ASSERT_EX(pTemp!=NULL);
	if(m_pData)memcpy(pTemp,m_pData,nIndex);	
	memset(pTemp+nIndex,ucNewElement,nCount);
	if(m_pData)memcpy(pTemp+nIndex+nCount,m_pData+nIndex,m_nSize-nIndex);	
	Empty();
	m_pData=pTemp;
	m_nSize=nTemp;
}
uint8_t CBinary::GetAt(uint16_t nIndex)
{
	ASSERT_EX(this->m_pData != NULL);
	ASSERT_EX(nIndex <m_nSize) ;
	return m_pData[nIndex];
}
void CBinary::SetAt(uint16_t nIndex,uint8_t ucNewElement)
{
	ASSERT_EX(this->m_pData != NULL);
	ASSERT_EX(nIndex <m_nSize) ;
	m_pData[nIndex]=ucNewElement;
}
#endif
void CBinary::Add(uint8_t ucNewElement)
{
	uint8_t tmp=ucNewElement;
	Append(&tmp,1);
}
uint16_t CBinary::GetSize(void)
{
	return m_nSize;
}
uint8_t *CBinary::GetBuffer()
{
	return m_pData;
}
const char *CBinary::AsString() const
{
	return (const char*)m_pData;
}

uint16_t CBinary::ReadBuffer(uint8_t *pBuffer, uint16_t iStart, uint16_t iLength)
{
	if(m_pData==NULL)return 0;
	if(iLength==0xffff)iLength=m_nSize-iStart;
	else if((iStart+iLength)>m_nSize)iLength=m_nSize-iStart;
	for(int i=iStart;i<iStart+iLength;i++)pBuffer[i-iStart]=m_pData[i];
	return iLength;
}
uint16_t CBinary::ReadBuffer(char *pBuffer, uint16_t iStart, uint16_t iLength)
{
	return ReadBuffer((uint8_t*)pBuffer,iStart,iLength);
}
uint16_t CBinary::WriteBuffer(uint8_t *pBuffer, uint16_t iLength)
{
   Empty();
   Append(pBuffer,iLength);
   return iLength;
}
uint16_t CBinary::WriteBuffer(const char *pBuffer, uint16_t iLength)
{
   return WriteBuffer((uint8_t*)pBuffer,iLength);
}
void CBinary::Append(uint8_t *pBuffer,uint16_t iLength)
{
	if(pBuffer==NULL||iLength<=0)return;
	uint16_t nTemp=m_nSize+iLength;
	uint8_t *pTemp=new uint8_t[nTemp];
	ASSERT_EX(pTemp!=NULL);
	if(m_pData)memcpy(pTemp,m_pData,m_nSize);	
	memcpy(pTemp+m_nSize,pBuffer,iLength);
	Empty();
	m_pData=pTemp;
	m_nSize=nTemp;
}
void CBinary::Append(const char *pBuffer,uint16_t iLength)
{
	Append((uint8_t*)pBuffer,iLength);
}
bool CBinary::IsEmpty(void)
{
	return (m_pData==NULL||m_nSize==0);
}
void CBinary::Empty(void)
{
	if(m_pData)delete [] m_pData;
	m_pData=NULL;
	m_nSize=0;
}

