//
//buffer.c
//
//Functions for manipulating buffers.
//
//
//-UserX 2001/12/10

#include "misc/compat.h"
#include <string.h>
#include "base/buffer.h"

//xor buffers
void bufferXor(uint8 *dstbuffer, uint8 *srcbuffer, size_t length) {
	size_t i;
	for(i = 0; i < length; i++) {
		dstbuffer[i] ^= srcbuffer[i];
	}
}

//swap buffers
void bufferSwap(uint8 *dstbuffer, uint8 *srcbuffer, size_t length) {
	bufferXor(dstbuffer, srcbuffer, length);
	bufferXor(srcbuffer, dstbuffer, length);
	bufferXor(dstbuffer, srcbuffer, length);
}

//swap buffers with a temporary space
void bufferSwap3(uint8 *dstbuffer, uint8 *srcbuffer, uint8 *tmpbuffer, size_t length) {
	memcpy(tmpbuffer, srcbuffer, length);
	memcpy(srcbuffer, dstbuffer, length);
	memcpy(dstbuffer, tmpbuffer, length);
}

//reverses order of bytes in a given array
void bufferReverse(uint8 *buffer, size_t length) {
	uint8 t;
	size_t i;
	for(i = 0; i < length / 2; i++) {
		t = buffer[length - i - 1];
		buffer[length - i - 1] = buffer[i];
		buffer[i] = t;
	}
}

//inc buffer (big endian)
void bufferInc(uint8 *dstbuffer, size_t length) {
	int i;
	for(i = length - 1; i >= 0; i++) {
		if(++dstbuffer[i] != 0) {
			break;
		}
	}
}
//dec buffer (big endian)
void bufferDec(uint8 *dstbuffer, size_t length) {
	int i;
	for(i = length - 1; i >= 0; i++) {
		if(dstbuffer[i]-- != 0) {
			break;
		}
	}
}

//write a big endian int
void bufferSetBEUInt(uint8 *dstbuffer, uint64 value, size_t length) {
	if(dstbuffer == NULL) {
		return;
	}

	for(dstbuffer += length - 1; length > 0; length--, dstbuffer--) {
		*dstbuffer = (uint8)value;
		value >>= 8;
	}
}

//read a big endian int
uint64 bufferGetBEUInt(uint8 *dstbuffer, size_t length) {
	int64 value = 0;
	if(dstbuffer == NULL) {
		return 0;
	}

	for(; length > 0; length--, dstbuffer++) {
		value <<= 8;
		value |= *dstbuffer;
	}
	return value;
}


//write a little endian int
void bufferSetLEUInt(uint8 *dstbuffer, uint64 value, size_t length) {
	if(dstbuffer == NULL) {
		return;
	}

	for(; length > 0; length--, dstbuffer++) {
		*dstbuffer = (uint8)value;
		value >>= 8;
	}
}

//read a little endian int
uint64 bufferGetLEUInt(uint8 *dstbuffer, size_t length) {
	uint64 value = 0;
	if(dstbuffer == NULL) {
		return 0;
	}

	for(dstbuffer += length - 1; length > 0; length--, dstbuffer--) {
		value <<= 8;
		value |= *dstbuffer;
	}
	return value;
}


//write a big endian int
void bufferSetBEInt(uint8 *dstbuffer, int64 value, size_t length) {
	if(dstbuffer == NULL) {
		return;
	}

	for(dstbuffer += length - 1; length > 0; length--, dstbuffer--) {
		*dstbuffer = (uint8)value;
		value >>= 8;
	}
}

//read a big endian int
int64 bufferGetBEInt(uint8 *dstbuffer, size_t length) {
	int64 value = 0;
	if(dstbuffer == NULL) {
		return 0;
	}
	if(length <= 0) {
		return 0;
	}

	if((dstbuffer[0] & 0x80) != 0) {
		value = -1;
	}
	for(; length > 0; length--, dstbuffer++) {
		value <<= 8;
		value |= *dstbuffer;
	}
	return value;
}


//write a little endian int
void bufferSetLEInt(uint8 *dstbuffer, int64 value, size_t length) {
	if(dstbuffer == NULL) {
		return;
	}

	for(; length > 0; length--, dstbuffer++) {
		*dstbuffer = (uint8)value;
		value >>= 8;
	}
}

//read a little endian int
int64 bufferGetLEInt(uint8 *dstbuffer, size_t length) {
	int64 value = 0;
	if(dstbuffer == NULL) {
		return 0;
	}
	if(length <= 0) {
		return 0;
	}

	if((dstbuffer[length - 1] & 0x80) != 0) {
		value = -1;
	}
	for(dstbuffer += length - 1; length > 0; length--, dstbuffer--) {
		value <<= 8;
		value |= *dstbuffer;
	}
	return value;
}


