#include <stdio.h>
#include <string.h>

#include <new>

#define RESULT_OK			0

#define ERROR_PARAM			1
#define ERROR_MEMORY		2
#define ERROR_PARSE			3

#define ERROR_IN_OPEN		4
#define ERROR_IN_ACCESS		5

#define ERROR_OUT_OPEN		6
#define ERROR_OUT_ACCESS	7

#define ERROR_LAST			ERROR_OUT_ACCESS

const char* g_aErrorMessages[ERROR_LAST+1]=
{	"",
	"invalid parameter (should be: TARGET INFILE [OUTFILE])",
	"out of memory",
	"parsing error",
	"error opening input file (%s)",
	"error accessing input file (%s)",
	"error opening output file (%s)",
	"error accessing output file (%s)"
};


int ReadData(char** ppData,long* pLength,FILE* pFile,int AdditionalSpace)
{
	if(fseek(pFile,0,SEEK_END)!=0)
		return ERROR_IN_ACCESS;

	*pLength=ftell(pFile);
	if(*pLength<0)
		return ERROR_IN_ACCESS;

	if(fseek(pFile,0,SEEK_SET)!=0)
		return ERROR_IN_ACCESS;

	*ppData=new(std::nothrow) char[(*pLength)+AdditionalSpace+1];
	if(*ppData==NULL)
		return ERROR_MEMORY;

	if(fread(*ppData,1,*pLength,pFile)!=*pLength)
	{
		delete[] (*ppData);
		return ERROR_IN_ACCESS;
	}
	(*ppData)[*pLength]='\0';

	return RESULT_OK;
}

int ModifyData(char* sData,const char* sTarget)
{
	char* sColon;
	int nTargetLength=strlen(sTarget);

	//find colon;
	sColon=strchr(sData,':');
	if(sColon==0)
		return ERROR_PARSE;

	//insert target before it
	//make room
	memmove(sColon+nTargetLength+1,sColon,strlen(sColon)+1);
	//insert a space and the target
	sColon[0]=' ';
	memcpy(sColon+1,sTarget,nTargetLength);
	
	return RESULT_OK;
}

int DoIt(const char* sTarget,const char* sInFile,const char* sOutFile)
{
	char* sData;
	long nLength;
	FILE* pFile;
	int Result=RESULT_OK;
	int nAdditionalSpace=strlen(sTarget)+1;

	pFile=fopen(sInFile,"rb");
	if(pFile==NULL)
		Result=ERROR_IN_OPEN;
	else
	{
		Result=ReadData(&sData,&nLength,pFile,nAdditionalSpace);
		fclose(pFile);
	}

	if(Result==RESULT_OK)
	{
		Result=ModifyData(sData,sTarget);

		if(Result==RESULT_OK)
		{
			pFile=fopen(sOutFile,"wb");
			if(pFile==NULL)
				Result=ERROR_OUT_OPEN;
			else
			{
				if(fwrite(sData,1,nLength+nAdditionalSpace,pFile)!=nLength+nAdditionalSpace)
					Result=ERROR_OUT_ACCESS;
				fclose(pFile);
			}			
		}

		delete[] sData;
	}

	return Result;	
}

int main(int argc,char* argv[])
{
	int Result;
	const char* sInFile;
	const char* sOutFile;
	const char* sTarget;

	if(argc<3)
		Result=ERROR_PARAM;
	else
	{
		sTarget=argv[1];

		sInFile=argv[2];
		if(argc>3)
			sOutFile=argv[3];
		else
			sOutFile=sInFile;

		Result=DoIt(sTarget,sInFile,sOutFile);
	}

	if(Result!=0)
	{
		printf("\n");
		if(Result>=ERROR_IN_OPEN)
		{
			if(Result>=ERROR_OUT_OPEN)
				printf(g_aErrorMessages[Result],sOutFile);
			else
				printf(g_aErrorMessages[Result],sInFile);
		}
		else
			printf(g_aErrorMessages[Result]);
	}

	return Result;
}
