Skip to content

Commit 61c6730

Browse files
committed
Update example
1 parent d9f2d3b commit 61c6730

File tree

3 files changed

+48
-18
lines changed

3 files changed

+48
-18
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.txt

examples/singleapp/utf8-byte-count/Taskfile.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,12 @@ tasks:
1212
run-userune:
1313
cmds:
1414
- go run main.go -u
15+
diff:
16+
cmds:
17+
- go run main.go > manual.txt
18+
- go run main.go -u > userune.txt
19+
- diff manual.txt userune.txt
20+
ignore_error: true
21+
clean:
22+
cmds:
23+
- rm -f ./*.txt

examples/singleapp/utf8-byte-count/main.go

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,24 @@ func main() {
2121
func 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

6867
func 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

Comments
 (0)