投稿者 魔界の仮面弁士  (社会人) 投稿日時 2021/10/5 14:29:43
るきおさん:
> If cp1 <= 65535 Then
>   Debug.WriteLine("鯖はUnicode第1面にあります。")
第1面ではなく、第0面ですよね。


snowmansnowさん:
> Cells(3, 4).VALUE = uni2(55405, 57158)
> Cells(6, 4).VALUE = uni5(9977, 65039, 8205, 9792, 65039)

この部分、中身は ChrW を呼んでいるだけのようですが、
uni2~uni5 と分けるのではなく、ParamArray を使った方がスマートかと思います。
Function Uni(ParamArray charCode() As VariantAs String
    Uni = ""
    Dim v As Variant
    For Each v In charCode
        Uni = Uni & ChrW(v)
    Next
End Function


結果はこれで良いのですよね。


𫝆
葛󠄀
𠮟󠄀
⛹️‍♀️
𩸽󠄁
𩸽󠄊

Cells(2, 4).Value = ChrW(&H6298)
Cells(3, 4).Value = ChrW(&HD86D) & ChrW(&HDF46)
Cells(4, 4).Value = ChrW(&H845B) & ChrW(&HDB40) & ChrW(&HDD00)
Cells(5, 4).Value = ChrW(&HD842) & ChrW(&HDF9F) & ChrW(&HDB40) & ChrW(&HDD00)
Cells(6, 4).Value = ChrW(&H26F9) & ChrW(&HFE0F) & ChrW(&H200D) & ChrW(&H2640) & ChrW(&HFE0F)
Cells(7, 4).Value = ChrW(&HD867) & ChrW(&HDE3D) & ChrW(&HDB40) & ChrW(&HDD01)
Cells(8, 4).Value = ChrW(&HD867) & ChrW(&HDE3D) & ChrW(&HDB40) & ChrW(&HDD0A)



> UTF-16のHEX?列で表現される文字は
> ①UTF-16が1個 通常の文字
> ②UTF-16が2個 サロゲートペア
> ③UTF-16が3個 異体字
> ④UTF-16が4個 サロゲートペア異体字
> ⑤UTF-16が4個以上 結合文字
> と、思っております。
> ②~④(か、⑤も)
> について、知りたいです

質問の意味が良く分かりませんが:

たとえば「á」であれば
U+0061 (アルファベットの小文字エー) に
U+0301 (合成用アキュート・アクセント記号)を組み合わせたものであり、
UTF-8 では 3 バイト(61 CC 81)
UTF-16では 4 バイト(0061 0301) で表現されます。

一方で「á」の場合には
U+00E1 (アキュート・アクセント付き小文字エー)であり、
UTF-8 では 2 バイト(C3 A1)
UTF-16では 2 バイト(00E1) で表現されます。
JIS X 0212 では 2 バイト(2B 21) [11区1点] で、
EUC-JPだと 3 バイト(8F AB A1) [11区1点] です。

そして「á」と「á」のいずれも BMP であり、サロゲート領域は必要としません。

あるいは家族絵文字「👩🏻‍👩🏿‍👧🏼‍👧🏾」。これは 1 書記素として描画されますが、
その表現には 11 個のコードポイントが用いられており、
UTF-8 では 41バイト、UTF-16 では 38バイトとなります。
https://j.mp/3a7n8Hy


> 1面のintしか受け付けないのかと勘違いして、2面以降はどうすればいいのか質問した感じでした。

UTF-16 のことですよね。0 面(0000~FFFF)は無加工なので良いとして、
1~16面(10000~10FFFF)で、サロゲートペアの使い方は変わりません。
異体字だろうと結合文字であろうと同じこと。

通常はビットシフトで処理されることが多いですが、
ここでは説明のため、2 進数文字列として処理してみます。

Public Function ToUTF16(codePage As IntegerAs UShort()
    If codePage < 0 OrElse &H10FFFF < codePage Then
        Throw New ArgumentOutOfRangeException(NameOf(codePage))
    End If
    If codePage <= &HFFFF Then
        'BMP の場合は無加工 
        Return New UShort() {CUShort(codePage)}
    Else
        '①元の値から 0x10000 を引くことで、U+010000~U+10FFFF を 00000~FFFFF にする 
        Dim u = CUShort(codePage - &H10000UI)
        '②それを 20ビットの2進数として表現 
        Dim b = Convert.ToString(u, 2).PadLeft(20, "0"c)
        '③上位サロゲートは、上位10ビットの前に"110110"を添えた値 
        Dim us = CUShort(Convert.ToInt32("110110" & b.Substring(0, 10), 2))
        '④下位サロゲートは、下位10ビットの前に"110111"を添えた値 
        Dim ls = CUShort(Convert.ToInt32("110111" & b.Substring(10, 10), 2))
        Return {us, ls}
    End If
End Function



・ベースとなるのは、31ビットの符号化文字集合である UCS-4 (ISO/IEC 10646) という規格です。
 "UCS" の由来は、Universal Character Set です。

・UCS-4では、符号位置として 0~7FFFFFFF の 4 バイトで表現されており、
 それを上位から「群:0~127」「面:0~255」「区:0~255」「点:0~255」で区切って管理しています。

・Unicode は、それらのうち、0~10FFFF にあたる第0群 第0~16面 のみを扱います。
 このため Unicode の符号空間には「群」が無く、「面・区・点」でのみ管理されます。

・UTF-32 は、その 0~10FFFF の文字集合をそのまま符号化するもので、
 UCS-4 の部分集合にあたります。
 "UTF" の由来は、Unicode (または UCS) Transformation Format だそうです。

・UCS-2 ではその内、0000~FFFF の範囲(第 0 群第 0 面)のみを扱います。
 この範囲は特に、BMP(基本多言語面) と呼ばれます。
 VB4 (32bit) が扱える Unicode バージョンは 3.0 であり、実質的にはこの範囲に相当します。
 ※厳密に言えば、VB4 は OS 既定のコードページも扱える仕様なので、たとえば
  Shift_JIS では区別されるが、Unicode では同一視される文字なども扱えます。

・BMP は、UCS-2 が扱える唯一の面であり、UCS-4 および Unicode の最初の面です。
 BMP の符号位置は、UTF-8 では 1~3 バイト、UTF-16 では 2 バイトで表現されます。

・UTF-16 では BMP(第 0 面) に加えて、サロゲートペアを使うことで、
 第 1 面~第 16 面の文字を扱えます。符号空間としては 0~10FFFF の範囲です。
 VB.NET が扱う文字列は、内部的にはこの符号化方式で保持されています。
 ※0000~FFFF で 65,536、10000~10FFFF で 1,048,576、そしてそこから
  サロゲート領域の 2,048 文字を引いて、合計 111万2,064文字分の空間)

・サロゲートペアを使うのは UTF-16 のみです。
 UTF-8 や UTF-32 は、0~10FFFF の範囲をそのまま符号化できます。