備忘ぶ録-新犬小屋

ココログ「備忘ぶ録(https://kotatuinu.cocolog-nifty.com/blog/)」のコピー場所です。

覚書「サロゲートペア」について

サロゲートペア」とは、UNICODEの有る範囲の文字列群(U+100000 ~ U+10FFFF)をUTF-16では一文字分では表記できないため、二文字分を使用する、その範囲の文字列群のことを指す。
なので、UTF-8UTF-32には、サロゲートペアという概念はない。UTF-16サロゲートペアの範囲に当たるUNICODEの文字列群は当然UTF-8UTF-32で扱えるけど、それはサロゲートペアで扱っていない(そのような仕組みではない)。

簡単にサロゲートペアの範囲の文字をファイルに出力するプログラム(C++)を書いてみた。

#include <iostream>
#include <array>
#include <string>

std::wstring convertUicodeToUTF16(char32_t code)
{
	char16_t h = 0xd800;
	char16_t l = 0xdc00;

	code -= 0x10000;
	h += (code / 0x400) % 0xffff;
	l += code % 0x400;
	std::wstring result;
	result.push_back(h);
	result.push_back(l);

	return result;
}

int main()
{
	FILE* f = 0;
	errno_t eno = fopen_s(&f, "UTF16.txt", "wb");
	if (eno != 0) {
		fprintf_s(stderr, "ERR:fopen : eno=%d\r\n", eno);
		return -1;
	}

	// BOM UNICODE(BE)
	char bom[] = { 0xff, 0xfe };
	fwrite(bom, sizeof(bom), 1, f);

	uint16_t cnt = 0;
	//for (char32_t code = 0; code <= 0x10FFFF; code++) {
	for (char32_t code = 0x10000; code <= 0x10FFFF; code++) {

		if (cnt == 0) {
			fwprintf(f, L"%08x\t", code);
		}
		std::wstring result;
		if (code < 0x10000) {
			result.push_back((wchar_t)code);
		}
		else {
			result = convertUicodeToUTF16(code);
		}

		fwrite(result.c_str(), result.length() * sizeof(wchar_t), 1, f);

		cnt++;
		if (cnt == 0x40) {
			fwprintf(f, L"\r\n");
			cnt = 0;
		}
	}

	fclose(f);

	return 0;
}



・文字が割り振られていない範囲も出力している。
・0x40文字単位で改行を入れているのは、改行なしで出力したファイルをエディタで開くとスクロールできなくなっちゃうから。
↓出力される内容はこんな感じ(2行のみ出してみた)。


00010300 𐌀𐌁𐌂𐌃𐌄𐌅𐌆𐌇𐌈𐌉𐌊𐌋𐌌𐌍𐌎𐌏𐌐𐌑𐌒𐌓𐌔𐌕𐌖𐌗𐌘𐌙𐌚𐌛𐌜𐌝𐌞𐌟𐌠𐌡𐌢𐌣𐌤𐌥𐌦𐌧𐌨𐌩𐌪𐌫𐌬𐌭𐌮𐌯𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷𐌸𐌹𐌺𐌻𐌼𐌽𐌾𐌿
00010340 𐍀𐍁𐍂𐍃𐍄𐍅𐍆𐍇𐍈𐍉𐍊𐍋𐍌𐍍𐍎𐍏𐍐𐍑𐍒𐍓𐍔𐍕𐍖𐍗𐍘𐍙𐍚𐍛𐍜𐍝𐍞𐍟𐍠𐍡𐍢𐍣𐍤𐍥𐍦𐍧𐍨𐍩𐍪𐍫𐍬𐍭𐍮𐍯𐍰𐍱𐍲𐍳𐍴𐍵𐍶𐍷𐍸𐍹𐍺𐍻𐍼𐍽𐍾𐍿
・・・