void IntelHexImage::write(unsigned char *buffer, size_t bufSize)
{
	size_t address, offset, current;
	string str;
	CIntelHexRec record;
	for (offset = 0; offset < bufSize; offset += current)
	{
		address = _writeAddr + offset;
		if ((_linAddr & 0xFFFFU) || ((_linAddr & 0xFFFF0000U) != (_writeAddr & 0xFFFF0000U)) || ((address != 0) && (address%0x10000 == 0)))
		{
			record.InitExtAddr(HIWORD(address));
			str = record.GetString();
#ifdef NEED_CRLF_TRANSLATION
/* NOTE: Because in most cases HEX files created on Windows with MPLAB we need CRLF */
			if ((str[str.size() - 1] == '\n') && (str[str.size() - 2] != '\r'))
				str.insert(str.size() - 1, "\r");
#endif
			int tmp = fputs(str.c_str(), _file);
			if (tmp < 0)
			{
				eTrace1("tmp = %d", tmp);
				throw DEFileWriteFailed();
			}
			_linAddr = _writeAddr & 0xFFFF0000U;
		}
		if (offset + 0x10 > bufSize)
			current = bufSize - offset;
		else
			current = 0x10;

		if (address/0x10000 != (address + current)/0x10000)
			current = 0x10000 - (address%0x10000);
		if (current != 0)
		{
			record.InitData((unsigned char)current, LOWORD(address),buffer+offset);
			str = record.GetString();
#ifdef NEED_CRLF_TRANSLATION
/* NOTE: Because in most cases HEX files created on Windows with MPLAB we need CRLF */
			if ((str[str.size() - 1] == '\n') && (str[str.size() - 2] != '\r'))
				str.insert(str.size() - 1, "\r");
#endif
			int tmp = fputs(str.c_str(), _file);
			if (tmp < 0)
			{
				eTrace1("tmp = %d", tmp);
				throw DEFileWriteFailed();
			}
		}
		else
			eTrace0("current = 0");
	}
	_writeAddr += bufSize;
}
size_t IntelHexImage::read(unsigned char *buffer, size_t bufSize, size_t *addr)
{
	const size_t buffer_size = 500;
	char f_buffer[buffer_size];
	char* fgets_rc;
	size_t pc;
	size_t address;

	while (_readCurrent >= _record.m_Size)
	{	// read from file
		fgets_rc = fgets(f_buffer, buffer_size, _file);
		if (fgets_rc == NULL)
		{
			if (feof(_file))
				return 0;
			else
				throw DEFileReadFailed();
		}
#ifdef NEED_CRLF_TRANSLATION
/* NOTE: Because fopen() do nothing with "t" mode on non-Windows we need to translate CRLF -> LF manually */
		size_t len = strlen(f_buffer);
		if ((f_buffer[len - 2] == '\r') && (f_buffer[len - 1] == '\n'))
		{
			f_buffer[len - 2] = '\n';
			f_buffer[len - 1] = 0;
		}
#endif
		_record.InitFromString(f_buffer);
		switch(_record.m_Type)
		{
		case cHexTypeData:
			_readCurrent = 0;
			break;
		case cHexTypeExtLinearAddr:
		case cHexTypeExtSegmentAddr:
			_readAddr = _record.GetExtAddr();
			_record.clear();
			break;
		case cHexTypeEndOfData:
			_record.clear();
			break;
		default:
			eTrace1("_record.m_Type = %d", _record.m_Type);
			throw DEFileReadFailed();
		}
	}
	if (bufSize > _record.m_Size - _readCurrent)
		pc = _record.m_Size - _readCurrent;
	else
		pc = bufSize;
	memcpy(buffer, &_record.m_Data[_readCurrent], pc);

	address = _readAddr & 0xFFFF0000;
	address |= _record.m_Addr;
	address += _readCurrent;
	*addr = address;

	_readCurrent += pc;
	return pc;
}
unsigned long CIntelHexRec::GetExtAddr()
{
	eAssert(m_Size == 2);
	unsigned long pc = 0;
	switch(m_Type)
	{
	case cHexTypeExtLinearAddr:
		pc |= m_Data[0] << 24;
		pc |= m_Data[1] << 16;
		return pc;
	case cHexTypeExtSegmentAddr:
		pc |= m_Data[0] << 12;
		pc |= m_Data[1] << 4;
		return pc;
	default:
		eTrace1("m_Type = %d", m_Type);
		throw DEFileInvalidHexFormat();
	}
}
void IntelHexImage::close()
{
	if (!_read)
	{
		_record.InitEndOfData();
		string str = _record.GetString();
#ifdef NEED_CRLF_TRANSLATION
/* NOTE: Because in most cases HEX files created on Windows with MPLAB we need CRLF */
			if ((str[str.size() - 1] == '\n') && (str[str.size() - 2] != '\r'))
				str.insert(str.size() - 1, "\r");
#endif
		int tmp = fputs(str.c_str(), _file);
		if (tmp < 0)
		{
			eTrace1("tmp = %d", tmp);
			throw DEFileWriteFailed();
		}
	}
	if (fclose(_file) != 0)
		throw DEFileCloseFailed(_name);
	_file = NULL;
}