@@ -21,25 +21,24 @@ func main() {
2121func run (runeMode bool ) error {
2222 var (
2323 strs = []string {
24- // 全角かな
24+ // 全角かな (3bytes)
2525 "こんにちは" ,
26- // 全角カタカナ
26+ // 全角カタカナ (3bytes)
2727 "コンニチハ" ,
28- // 半角カタカナ
29- "コンニチワ " ,
30- // 英数字
28+ // 半角カタカナ (3bytes)
29+ "コンニチハ " ,
30+ // 英数字記号 (1byte)
3131 "golang->60l4n6" ,
32- // ©¼½¾
32+ // ©¼½¾ (2bytes)
3333 "\U000000A9 \U000000BC \U000000BD \U000000BE " ,
34- // 🍺🍻🍷🍜
34+ // 🍺🍻🍷🍜 (4bytes)
3535 "\U0001F37A \U0001F37B \U0001F377 \U0001F35C " ,
3636 }
3737 fn = manual
3838 )
3939
4040 if runeMode {
4141 fn = userune
42- output .Stdoutl ("[MODE]" , "Use Rune" )
4342 }
4443
4544 for _ , v := range strs {
@@ -61,20 +60,38 @@ func userune(s string) {
6160 continue
6261 }
6362
64- output .Stdoutl ("[byte-count]" , utf8 .RuneLen (r ))
63+ output .Stdoutf ("[byte-count]" , "%c (%d) \n " , r , utf8 .RuneLen (r ))
6564 }
6665}
6766
6867func manual (s string ) {
6968 for i := 0 ; i < len (s ); {
70- //
71- // UTF-8の先頭バイトを判定し、バイトサイズ算出
72- //
7369 var (
7470 b = s [i ]
7571 l = 0
7672 )
7773
74+ //
75+ // UTF-8の先頭バイトを判定し、バイトサイズ算出
76+ //
77+ // UTF-8エンコーディングでは、各文字は1バイトから4バイトまでの可変長でエンコードされる。
78+ // 先頭バイト(最初のバイト)を見ることで、その文字が何バイトでエンコードされているかを判定できる。
79+ //
80+ // - 0xxxxxxx: 1バイト(ASCIIと互換性あり)
81+ // - 110xxxxx: 続く1バイトと合わせて2バイト
82+ // - 1110xxxx: 続く2バイトと合わせて3バイト
83+ // - 11110xxx: 続く3バイトと合わせて4バイト
84+ //
85+ // 以下の case は上記を判定している.
86+ //
87+ // - (b & 0x80) == 0: 最上位ビットが0なら、この文字は1バイト
88+ // - (b & 0xE0) == 0xC0: 最上位2ビットが110なら、この文字は2バイト
89+ // - (b & 0xF0) == 0xE0: 最上位3ビットが1110なら、この文字は3バイト
90+ // - (b & 0xF8) == 0xF0: 最上位4ビットが11110なら、この文字は4バイト
91+ //
92+ // REFERENCES:
93+ // - https://ja.wikipedia.org/wiki/UTF-8
94+ //
7895 switch {
7996 case (b & 0x80 ) == 0 :
8097 l = 1
@@ -86,12 +103,15 @@ func manual(s string) {
86103 l = 4
87104 }
88105
89- i += l
90- if b == ' ' {
91- output .StdoutHr ()
92- continue
93- }
106+ func () {
107+ defer func () { i += l }()
108+
109+ if b == ' ' {
110+ output .StdoutHr ()
111+ return
112+ }
94113
95- output .Stdoutl ("[byte-count]" , l )
114+ output .Stdoutf ("[byte-count]" , "%s (%d)\n " , s [i :i + l ], l )
115+ }()
96116 }
97117}
0 commit comments