// StreamSed.cpp : _xZkqqHx_iDfCiDjDiDfMiBfLiDiL_xHqqkZx_ _xZkqqHx_iDeBiDhGiDiKiDfAiBfLiDfGiDiHiDjDjHhAiCmMiDeHiDjDiDgHiDiK_xHqqkZx_ _xZkqqHx_iDhMiDeDiDjDiDgHiCmMjCoIiLgA_xHqqkZx_
//
// _xZkqqHx_jHoBiBeG_xHqqkZx_
// StreamSed.exe "^(\w+)(.*)" "$2$1" sample.txt
//

#include "stdafx.h"
#include <io.h>			// For _topen.etc.
#include <fcntl.h>		// For _O_BINARY.etc.
#include <sys/stat.h>	// For _S_IREAD.etc.
#include "FMTL.h"

char* LoadTextFile (const char* cpFile)
{
	// _xZkqqHx_iDhEiDeAiDeDiDiLiCmMiNfIjAfGiOjOiKnEiCpAiOoGjDlOiBeC_xHqqkZx_
	struct _stat buff;
	if (_stat(cpFile, &buff) != 0) return NULL;
	// _xZkqqHx_iDhEiDeAiDeDiDiLiCpA_xHqqkZx_Open_xZkqqHx_iBeC_xHqqkZx_
	int fh = _open(cpFile, _O_BINARY|_O_RDONLY);
	if (fh == -1) return NULL;
	// _xZkqqHx_iDgGiBfLiDfOiCpAiOoGjDlOiBeC_xHqqkZx_
	char* cpBuff = new char[buff.st_size + 10];
	// _xZkqqHx_iDhEiDeAiDeDiDiLiCkJiCoHiDgGiBfLiDfOjDmHiCnNiNjOiCnNiBeC_xHqqkZx_
	int iCount = _read(fh, cpBuff, buff.st_size + 9);
	if (iCount == -1 || _close(fh) == -1)
	{
		delete[] cpBuff;
		return NULL;
	}
	cpBuff[iCount] = '\0';
	return cpBuff;
} // LoadTextFile.

void ReleaseTextFileBuff (char* cpBuff)
{
	delete[] cpBuff;
} // ReleaseTextFileBuff.

void MStringToWString (wstring& wstr, const char* cpText)
{
	// UNICODE_xZkqqHx_iCmJjFmPiKlHiClHiCoJiBeC_xHqqkZx_
	int iBuffSz = strlen(cpText) + 1;
	wstr.resize(iBuffSz, L'\0');
	int iTextSz = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, cpText, -1, wstr.begin(), iBuffSz);
	wstr.resize(iTextSz);
}

void WStringToMString (string& str, const wchar_t* wcpText)
{
	// MBCS_xZkqqHx_iCmJjFmPiKlHiClHiCoJiBeC_xHqqkZx_
	int iBuffSz = (wcslen(wcpText) + 1) * sizeof(wchar_t);
	str.resize(iBuffSz, '\0');
	int iTextSz = WideCharToMultiByte(CP_ACP, 0, wcpText, -1, str.begin(), iBuffSz, NULL, NULL);
	str.resize(iTextSz);
}

int main (int argc, char* argv[])
{
	if (argc != 4) return 1;

	// _xZkqqHx_jAlDiLeLjFfMiMlLiDeJiDhFiDfHiDeGiDeOiDgHjAlGjAkMiBeC_xHqqkZx_
	FmRegExp regexp;
	// _xZkqqHx_iMjPiNpFiOkOiCpA_xHqqkZx_UNICODE_xZkqqHx_iCmJjFmPiKlHiBeC_xHqqkZx_
	wstring wstrExp;
	MStringToWString(wstrExp, argv[1]);
	// _xZkqqHx_jChFiKlHiOkOiCpA_xHqqkZx_UNICODE_xZkqqHx_iCmJjFmPiKlHiBeC_xHqqkZx_
	wstring wstrRep;
	MStringToWString(wstrRep, argv[2]);
	// _xZkqqHx_jChFiKlHiOkOiCpAjFmPiKlHiClFiCmEiCkIiCkNiBeC_xHqqkZx_
	wstring wstrRepForm;
	FmRegExp::ConvToReplaceForm(wstrRepForm, wstrRep.c_str());

	// _xZkqqHx_iDgFiDeMiDfIiDgHiCpAjDmHiCnNiNjOiCnOiBeC_xHqqkZx_
	char* cpText = LoadTextFile(argv[3]);
	// UNICODE_xZkqqHx_iCmJjFmPiKlHiBeC_xHqqkZx_
	wstring wstrText;
	MStringToWString(wstrText, cpText);
	// _xZkqqHx_jChFiKlHiMoDiDgFiDeMiDfIiDgHiDgPiDgCiDhEiDeAiBeC_xHqqkZx_
	wstring wstrNewText;

	WStringConst wscTextConst(wstrText.begin(), wstrText.end());
	for (;;)
	{
		const wchar_t* wcpBegin = wscTextConst.GetBegin();
		if (regexp.IsMatch(wscTextConst, wstrExp.c_str()))
		{
			wstring wstrRepText;
			regexp.GetReplaceText(wstrRepText, wstrRepForm.c_str());
			wstrNewText.insert(wstrNewText.end(), wcpBegin, wscTextConst.GetBegin());
			wstrNewText.insert(wstrNewText.end(), wstrRepText.begin(), wstrRepText.end());
			wscTextConst.SetBegin(wscTextConst.GetEnd());
			wscTextConst.SetEnd(wscTextConst.GetBufferEnd());
		} else
		{
			wstrNewText.insert(wstrNewText.end(), wscTextConst.GetBegin(), wscTextConst.GetEnd());
			break;
		}
	}
	wscTextConst.Clear();
	// MBCS_xZkqqHx_iCmJjFmPiKlHiBeC_xHqqkZx_
	string strText;
	WStringToMString(strText, wstrNewText.c_str());
	for (int iC = 0; iC != strText.length(); iC++)
		if (strText[iC] != '\r')
			putchar(strText[iC]);
	return 0;
}

