/*
 *	dsjisutf8 - シフトJIS⇔UTF-8変換フィルタ
 *	Copyright (C) 2010 Naoyuki Sawa
 *
 *	* Mon Mar 08 23:22:14 JST 2010 Naoyuki Sawa
 *	- 1st リリース。
 *	- 標準入出力のテキストストリームを、シフトJIS⇔UTF-8に文字コード変換するツールです。
 *	  同等の既存ツールはたくさん有るのですが、シフトJIS⇔UTF-8変換ルーチンの備忘録として、本ツールを作成しておくことにしました。
 *	  もし今後、P/ECEアプリのデータ作成等にシフトJIS⇔UTF-8変換が必要になった場合は、Makefileの中で本ツールを使うことができます。
 */
#include <afx.h>

#define VERSION "20100308"

/*****************************************************************************
 *	シフトJIS⇔UTF-8変換ルーチン
 *****************************************************************************/

/* UTF-8文字列を、シフトJIS文字列に変換します。変換元の文字列が、空文字列でも大丈夫です。 */
CString utf8_to_sjis(const char* utf8_str) {
	/* UTF-8文字列のバイト数を取得します。 */
	int utf8_len/*バイト数*/ = strlen(utf8_str);

	/* UTF-8文字列を、Unicode文字列に変換します。 */
	CWordArray wide_str;
	int wide_len/*文字数*/ = MultiByteToWideChar(CP_UTF8, 0, utf8_str, utf8_len/*バイト数*/, NULL, 0);
	wide_str.SetSize(wide_len/*文字数*/);
	MultiByteToWideChar(CP_UTF8, 0, utf8_str, utf8_len/*バイト数*/, wide_str.GetData(), wide_len/*文字数*/);

	/* Unicode文字列を、シフトJIS文字列に変換します。 */
	CString sjis_str;
	int sjis_len/*バイト数*/ = WideCharToMultiByte(932/*CP_932*/, 0, wide_str.GetData(), wide_len/*文字数*/, NULL, 0, NULL, NULL);
	//                                                               ~~~~~~~~~~~~~~~~~~「&wide_str[0]」は不可。wide_len=0の場合に不正処理になる。
	WideCharToMultiByte(932/*CP_932*/, 0, wide_str.GetData(), wide_len/*文字数*/, sjis_str.GetBuffer(sjis_len/*バイト数*/), sjis_len/*バイト数*/, NULL, NULL);
	//                                    ~~~~~~~~~~~~~~~~~~「&wide_str[0]」は不可。wide_len=0の場合に不正処理になる。
	sjis_str.ReleaseBuffer(sjis_len);

	/* シフトJIS文字列を返します。 */
	return sjis_str;
}

/* シフトJIS文字列を、UTF-8文字列に変換します。変換元の文字列が、空文字列でも大丈夫です。 */
CString sjis_to_utf8(const char* sjis_str) {
	/* シフトJIS文字列のバイト数を取得します。 */
	int sjis_len/*バイト数*/ = strlen(sjis_str);

	/* シフトJIS文字列を、Unicode文字列に変換します。 */
	CWordArray wide_str;
	int wide_len/*文字数*/ = MultiByteToWideChar(932/*CP_932*/, 0, sjis_str, sjis_len/*バイト数*/, NULL, 0);
	wide_str.SetSize(wide_len/*文字数*/);
	MultiByteToWideChar(932/*CP_932*/, 0, sjis_str, sjis_len/*バイト数*/, wide_str.GetData(), wide_len/*文字数*/);

	/* Unicode文字列を、UTF-8文字列に変換します。 */
	CString utf8_str;
	int utf8_len/*バイト数*/ = WideCharToMultiByte(CP_UTF8, 0, wide_str.GetData(), wide_len/*文字数*/, NULL, 0, NULL, NULL);
	//                                                         ~~~~~~~~~~~~~~~~~~「&wide_str[0]」は不可。wide_len=0の場合に不正処理になる。
	WideCharToMultiByte(CP_UTF8, 0, wide_str.GetData(), wide_len/*文字数*/, utf8_str.GetBuffer(utf8_len/*バイト数*/), utf8_len/*バイト数*/, NULL, NULL);
	//                              ~~~~~~~~~~~~~~~~~~「&wide_str[0]」は不可。wide_len=0の場合に不正処理になる。
	utf8_str.ReleaseBuffer(utf8_len/*バイト数*/);

	/* UTF-8文字列を返します。 */
	return utf8_str;
}

/*****************************************************************************
 *	
 *****************************************************************************/

void
usage()
{
	fprintf(stderr, "dsjisutf8 - シフトJIS⇔UTF-8変換フィルタ (%s) Naoyuki Sawa\n", VERSION);
	fprintf(stderr, "Usage: dsjisutf8 -su [入力ファイル名(シフトJIS) [出力ファイル名(UTF-8)]]\n");
	fprintf(stderr, "       dsjisutf8 -us [入力ファイル名(UTF-8) [出力ファイル名(シフトJIS)]]\n");
	fprintf(stderr, "入出力ファイル名を省略するか、「-」を指定すると、標準入出力を使用します。\n");
	exit(1);
}

int
main(int argc, char* argv[])
{
	int mode; /* 0 = シフトJIS→UTF-8, 1 = UTF-8→シフトJIS */
	CStdioFile* in;  /* 入力ストリーム */
	CStdioFile* out; /* 出力ストリーム */
	CString str;

	if((argc < 1 + 1) || (argc > 1 + 3)) {
		usage();
	}

	/* 変換モードを取得します。 */
	if(!strcmp(argv[1], "-su")) {
		mode = 0; /* シフトJIS→UTF-8 */
	
	} else if(!strcmp(argv[1], "-us")) {
		mode = 1; /* UTF-8→シフトJIS */
	} else {
		usage();
	}

	/* 入力ストリームを開きます。 */
	if((argc < 1 + 2) || !strcmp(argv[2], "-")) { /* 入力ファイル名を省略するか、「-」を指定すると、標準入力を使用します。 */
		in = new CStdioFile(stdin);
	} else {
		TRY {
			in = new CStdioFile(argv[2], CFile::modeRead | CFile::shareDenyWrite | CFile::typeText);
		} CATCH(CFileException, e) {
			fprintf(stderr, "### %sが開けません。\n", argv[2]);
			exit(1);
		} END_CATCH
	}

	/* 出力ストリームを開きます。 */
	if((argc < 1 + 3) || !strcmp(argv[3], "-")) { /* 出力ファイル名を省略するか、「-」を指定すると、標準出力を使用します。 */
		out = new CStdioFile(stdout);
	} else {
		TRY {
			out = new CStdioFile(argv[3], CFile::modeCreate | CFile::modeWrite | CFile::shareExclusive | CFile::typeText);
		} CATCH(CFileException, e) {
			fprintf(stderr, "### %sが作成できません。\n", argv[3]);
			exit(1);
		} END_CATCH
	}

	/* 入力ストリームの終端に達するまで… */
	while(in->ReadString(str)) { /* CStringバージョンのこの関数は、'\n'があればをそれを取り除きます。 */
		/* 文字コードを変換します。 */
		if(mode == 0) {
			str = sjis_to_utf8(str); /* シフトJIS→UTF-8 */
		} else {
			str = utf8_to_sjis(str); /* UTF-8→シフトJIS */
		}
		/* 出力ストリームに書き出します。 */
		out->WriteString(str + '\n');
	}

	/* 入出力ストリームを閉じます。 */
	delete in;
	delete out;

	return 0;
}
