// Common, group Encoding
// Copyright Alexander Liss

#include <stdlib.h>
#include <string.h>
#include "ascicoder.h"


const char del = ',';
const int double_digits=14;


	// ASCICoder


int ASCICoder::put(void* data, int size)
{
	if(start_put()) return 1;

	return write_buffer->append((unsigned char*)data, size);
}

int ASCICoder::get(void* data, int size)
{
	if(start_get()) return 1;

	if((int)strlen(buf)!=size) return 2;

	memcpy(data,buf,size);

	return 0;
}



int ASCICoder::put(int data)
{
	if(start_put()) return 1;

	_itoa(data,buf,10);
	
	return write_buffer->append(buf);
}

int ASCICoder::get(int& data)
{
	if(start_get()) return 1;

	data=atoi(buf);

	return 0;
}

int ASCICoder::put(unsigned int data)
{
	if(start_put()) return 1;

	_ultoa((unsigned long)data,buf,10);
		
	return write_buffer->append(buf);

	return 0;
}

int ASCICoder::get(unsigned int& data)
{
	if(start_get()) return 1;

	char *z=0;

	data=(unsigned int)strtoul(buf,&z,10);

	return 0;
}


int ASCICoder::put(long data)
{
	if(start_put()) return 1;

	_ltoa(data,buf,10);
	
	return write_buffer->append(buf);
}

int ASCICoder::get(long& data)
{
	if(start_get()) return 1;

	data=atol(buf);

	return 0;
}


int ASCICoder::put(unsigned long data)
{
	if(start_put()) return 1;
	
	_ultoa(data,buf,10);
		
	return write_buffer->append(buf);
}

int ASCICoder::get(unsigned long& data)
{
	if(start_get()) return 1;

	char *z=0;

	data=(unsigned int)strtoul(buf,&z,10);

	return 0;
}

int ASCICoder::put(short data)
{
	if(start_put()) return 1;	

	_itoa((int)data,buf,10);
	
	return write_buffer->append(buf);
}

int ASCICoder::get(short& data)
{
	if(start_get()) return 1;

	data=(short)atoi(buf);

	return 0;
}


int ASCICoder::put(unsigned short data)
{
	if(start_put()) return 1;
		
	_ultoa((unsigned long)data,buf,10);
	
	return write_buffer->append(buf);
}

int ASCICoder::get(unsigned short& data)
{
	if(start_get()) return 1;

	data=(unsigned short)atoi(buf);

	return 0;
}

int ASCICoder::put(char data)
{
	if(start_put()) return 1;

	return write_buffer->append(1,data);
}

int ASCICoder::get(char& data)
{
	if(start_get()) return 1;

	if(strlen(buf)>1) return 2;

	data=*buf;

	return 0;
}


int ASCICoder::put(unsigned char data)
{
	if(start_put()) return 1;

	return write_buffer->append(1,data);
}

int ASCICoder::get(unsigned char& data)
{
	if(start_get()) return 1;

	if(strlen(buf)>1) return 2;

	data=*((unsigned char *)buf);

	return 0;
}


int ASCICoder::put(float data)
{
	if(start_put()) return 1;

	_gcvt((double)data,double_digits,buf);
	
	return write_buffer->append(buf);
}

int ASCICoder::get(float& data)
{
	if(start_get()) return 1;

	data=(float)atof(buf);

	return 0;
}


int ASCICoder::put(double data)
{
	if(start_put()) return 1;

	_gcvt(data,double_digits,buf);
	
	return write_buffer->append(buf);
}

int ASCICoder::get(double& data)
{
	if(start_get()) return 1;

	data=atof(buf);

	return 0;
}

int ASCICoder::start_put()
{
	if(!write_buffer) return 1;

	int g=0;

	memset(buf,0,100);

	if(write_buffer->data_size>0)
		g=write_buffer->append(1,del);

	return g;
}

int ASCICoder::start_get()
{
	if(!read_buffer || !read_control) return 1;

	if(read_control->offset>=read_buffer->data_size-2) return 2;

	if(read_control->offset != 0)
	{
		// no delimeter
		if(*(read_buffer->data+read_control->offset) != del) return 3;

		// two elimiters
		if(*(read_buffer->data+read_control->offset + 1) == del) return 4;

		++read_control->offset;
	}

	memset(buf,0,100);

	int left=read_buffer->data_size - read_control->offset;
	if (left>99) left=99;

	for(int i=0,count=0;i<left;++i)
	{
		buf[i]= *(read_buffer->data + read_control->offset + i);
		if(buf[i]==del)
		{
			buf[i]=0;
			count=i-1;
			break;
		}
	}

	if(count==0)
	{
		if( left==99)
			return 5; // no delimiter

		count=left;	// end of buffer
	}

	read_control->offset += count;

	return 0;
}