| |
やはり 1 文字ずつ文字種でふるい分けする必要があるみたいですね。
当方でも Gemini 3 で JavaScript のサンプルコードを生成してみると、以下のようになりました。
/**
* UnicodeコードポイントからShift-JIS(CP932)のバイト数、
* またはサロゲートペアの有無を判定する
* * @param {number} cp - Unicodeコードポイント (例: 0x3042)
* @returns {number} 1, 2, 4, 8
*/
function getSjisByteType(cp) {
// 1. Shift-JIS (CP932) 1byte文字
// ASCII (00-7F) + 半角カタカナ (FF61-FF9F)
if ((cp >= 0x0000 && cp <= 0x007F) || (cp >= 0xFF61 && cp <= 0xFF9F)) {
return 1;
}
// 2. UTF-16 サロゲートペアに該当するか (U+10000 以上)
// CP932は基本多言語面(BMP)のみをサポートするため、これらは自動的に「含まれない」かつ「サロゲートペア」
if (cp >= 0x10000) {
return 8;
}
// 3. Shift-JIS (CP932) 2byte文字の判定
// CP932に含まれるBMP内の主要な範囲を網羅
const isSjis2Byte = (
(cp >= 0x4E00 && cp <= 0x9FFF) || // CJK統合漢字 (第1・第2水準)
(cp >= 0x3000 && cp <= 0x30FF) || // ひらがな・カタカナ・和文記号
(cp >= 0xFF01 && cp <= 0xFF60) || // 全角英数・記号 (一部)
(cp >= 0xFFE0 && cp <= 0xFFE6) || // 全角記号 (円記号・文字など)
(cp >= 0x2116 && cp <= 0x266F) || // NEC特殊文字・記号・罫線
(cp >= 0xF900 && cp <= 0xFAFF) || // CJK互換漢字 (IBM拡張)
(cp >= 0xE000 && cp <= 0xE757) || // 外字領域 (PUA)
// 個別の記号やギリシャ・ロシア文字など
(cp >= 0x0370 && cp <= 0x04FF) ||
(cp === 0x00A2 || cp === 0x00A3 || cp === 0x00A5 || cp === 0x00AC || cp === 0x00B0 ||
cp === 0x00B1 || cp === 0x00B4 || cp === 0x00B6 || cp === 0x00D7 || cp === 0x00F7)
);
if (isSjis2Byte) {
return 2;
}
// 4. BMP内(サロゲートペアではない)かつ CP932に含まれない文字
return 4;
}
ただ、この判定方法は完全なものではなく、漢字領域の U+4E00 〜 U+9FFF の範囲内に「虫食い」の
ように存在する
・第 3・第 4 水準漢字など BMP 内における、Unicode には存在するが CP932 には存在しない漢字。
は考慮されていません。
厳密な判定を行うためには、JavaScript のハッシュテーブルである Set オブジェクトに
・CP932 の全 2 バイト文字の Unicode コードポイント。
を登録して、has() メソッドで照合を行う、という手法を取らないといけません。一度生成した Set オブジェクトへの
照合は O(1) の計算量でオーバーヘッドは非常に小さいのですが、 Set オブジェクトに約 7500 文字ある 2 バイト文字の
コードポイントを登録することは、明らかに大きなオーバーヘッドとなります。
|
|