AngelScript:Shift JISで文字列リテラルUTF16対応

このページは常に新しいバージョンの修正箇所書きます。

下記の設定は、スクリプトファイルはShiftJISコードで、文字列リテラルもShiftJISで扱う設定だ。
r = engine->SetEngineProperty(asEP_SCRIPT_SCANNER, 0); assert( r < 0 );
r = engine->SetEngineProperty(asEP_STRING_ENCODING, 0); assert( r < 0 );


下記では、ShiftJISコードで、文字列リテラルはUTF16を扱う設定
r = engine->SetEngineProperty(asEP_SCRIPT_SCANNER, 0); assert( r < 0 );
r = engine->SetEngineProperty(asEP_STRING_ENCODING, 1); assert( r < 0 );


はぃ~みごとにAngelScript側でコンパイルエラー出てしまいます。

おいおい、どうせならここまで対応してないと気持ち悪いだろ?

ってなわけで、かなり強引に修正した、どんなバグが潜んでいるかわからない サンプルを作ってみた。主な修正箇所は、ソースを比較できるWinMergeなどのソフトを使って違いを確かめてくれ!

ダウンロード


sample 新(2.32.0 専用) << 怖がらずダウンロードしてみな


ファイルの中身

as_compiler.cppas_kaoken.has_tokenizer.cppsjis_tbl.cpp の4つのファイルだ。

こいつは、AngelScriptのsourceディレクトリ内に上書きしてくださいな。こいつが原因でとんでもない障害が起きても一切責任は持たないので、予めよろしく(-.☆

修正したと言っても、ただ単にShiftJISからUTF16へ変換するテーブルを使っただけだ。
いゃ~ 文字コード関連のプログラミング数年ぶりなので全く覚えていなかったよ。慣れないことをするもんではないなw

as_compiler.cpp 内での修正箇所、※as_kaoken.hをインクルード済み
#ifdef AS_DOUBLEBYTE_CHARSET
		// ▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼
		// ▼ 修正
		// 全角文字はSJISのみ対応
		// 全角文字セットのみSJIS、ASCIIと非UTF16でエンコードされた文字列に対して許可
		if (engine->ep.scanner == 0)
		{
			asBYTE c = (asBYTE)cstr[n];
			if (engine->ep.stringEncoding == 1 && (c >= 0xa1 && c <= 0xdf))
			{// 半角カタカナなど
#ifndef AS_BIG_ENDIAN
				str.PushLast(g_aUTF16_SJIS_ANK[ c ][1]);
				str.PushLast(g_aUTF16_SJIS_ANK[ c ][0]);
#else
				str.PushLast(g_aUTF16_SJIS_ANK[ c ][0]);
				str.PushLast(g_aUTF16_SJIS_ANK[ c ][1]);
#endif
				continue;
			}
			else if (n + 1 < cstr.GetLength())
			{
				if (IsFirstByteSJIS(c))
				{
					// 第1バイトがSJISの範囲であり第2バイトもSJISの範囲か?
					if (IsSecondByteSJIS((asBYTE)cstr[n + 1]))
					{
						if (engine->ep.stringEncoding == 1)
						{
							char encodedValue[5] = { '\0' };
							int len = asStringEncodeUTF16FromSJSI(c, (asBYTE)cstr[n + 1], encodedValue);
							if (len == 0)
							{
								// 無効コード ポイントに関する警告を与える
								// TODO:警告のコード位置が必要
								Warning(TXT_INVALID_UNICODE_VALUE, node);
							}
							else
							{
								// 最終的な文字列にエンコードされた値を追加
								str.Concatenate(encodedValue, len);
							}
							++n;
						}
						else
						{
							str.PushLast(cstr[n++]);
							str.PushLast(cstr[n]);
						}
						continue;
					}
				}
			}
		}
		//// Double-byte charset is only allowed for ASCII and not UTF16 encoded strings
		//if ((cstr[n] & 0x80) && engine->ep.scanner == 0 && engine->ep.stringEncoding != 1)
		//{
		//	// This is the lead character of a double byte character
		//	// include the trail character without checking it's value.
		//	str.PushLast(cstr[n]);
		//	n++;
		//	str.PushLast(cstr[n]);
		//	continue;
		//}
		// ▲ 修正
		// ▲▲▲▲▲▲▲▲▲▲▲▲▲▲
#endif


as_tokenizer.cpp内での修正箇所、※as_kaoken.hをインクルード済み
#ifdef AS_DOUBLEBYTE_CHARSET
				// ▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼
				// ▼ 修正
				// 全角文字はSJISのみ対応
				if (IsFirstByteSJIS(source[n]) && (n + 1) < sourceLength && engine->ep.scanner == 0)
				{
					// 第1バイトがSJISの範囲であり第2バイトもSJISの範囲か?
					if (IsSecondByteSJIS(source[n + 1]))
					{
						n++; continue;
					}
				}
				//// Double-byte characters are only allowed for ASCII
				//if ((source[n] & 0x80) && engine->ep.scanner == 0)
				//{
				//	// This is a leading character in a double byte character, 
				//	// include both in the string and continue processing.
				//	n++;
				//	continue;
				//}
				// ▲ 修正
				// ▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲
#endif
as_compiler.cppは、前回より多く修正してます。そりゃUTF16文字列リテラル対応させたからね。

sjis_tbl.cppは、単なるShiftJIS→UTF16変換テーブル。

as_kaoken.hは、ShiftJIS変換に関するプログラムが書かれている。

もちろん今回もプロセッサ定義AS_DOUBLEBYTE_CHARSETを忘れるなよ。

r = engine->SetEngineProperty(asEP_SCRIPT_SCANNER, 1); assert( r < 0 );
r = engine->SetEngineProperty(asEP_STRING_ENCODING, 1); assert( r < 0 );

まぁ、なんというか、普通に上記設定のUTF8で文字リテラルUTF16でいいんじゃね?と思ってしまったのは内緒。

コメント 

コメントを残す