#include <v_lib.h>

V_LOCAL void
translate_block(u8_t *buffer,u32_t len,u8_t *map)
{
#ifdef	USE_INTEL_ASM
	__asm
	{
		push ebx
		mov esi, buffer
		mov ebx, map
		mov edi, esi
		mov edx, esi
		add edx, len
		cld
main_loop:
		lodsb
		xlatb
		stosb
		cmp esi, edx
		jne main_loop
		pop ebx
	}
#else	/* !USE_INTEL_ASM */
	unsigned char *ptr, *endptr;
	for(ptr = buffer, endptr = buffer + len;ptr < endptr;ptr++)
		*ptr = map[*ptr];
#endif	/* !USE_INTEL_ASM */
}

void list(void)
{
	int i = 0;
	uc_charmap_desc_p cmap;
	for(;;i++)
	{
		cmap = ucGetCharmap(i);
		if(!cmap)
			break;
		conPrintf("\t%s\n",cmap->name);
	}
}

int main(int argc, char *argv[])
{
	vsize_t len;
	vhandle_t in, out;
	u8_t *buffer, tab[256];
	logStartConsoleLog();
	logUpperLevel(LOG_TRACE);
	if(argc != 4 && argc != 5)
	{
		conPuts("Usage: rconv <src_map> <dst_map> <input file name> [output file name]\n");
		conPuts("Known maps:\n");
		list();
		return -1;
	}
	if(!ucAscii2AsciiTable(argv[1],argv[2],tab))
	{
		conlPuts(LOG_ERROR,"ucAscii2AsciiTable() failed.\n");
		return -1;
	}
	in = fileOpenRead(argv[3]);
	if(in == LIBV_INVALID_HANDLE)
		return -1;
	len = fileSize(in);
	buffer = (u8_p)memAlloc(len);
	if(!buffer)
	{
		conlPuts(LOG_ERROR,error_out_of_memory);
		fileClose(in);
		return -1;
	}
	fileRead(in,buffer,len);
	fileClose(in);
	translate_block(buffer,len,tab);
	out = fileOpenSafeOverwrite(argv[(argc == 5) ? 4 : 3]);
	if(out == LIBV_INVALID_HANDLE)
		return -1;
	fileWrite(out,buffer,len);
	fileClose(out);
	memFree(buffer);
	memPrintStats();
	return 0;
}
