/
895.txt
620 lines (466 loc) · 30.5 KB
/
895.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
[34] [DFN[[[UTF-8]]]] は、世界中で広く用いられており、 [[Linux]] や [[Web]]
では原則として用いられている標準的な[[文字コード]]です。
* 仕様書
[REFS[
- [116] '''[CITE@en-US[Encoding Standard]] ([TIME[2016-07-29 16:12:31 +09:00]]) <https://encoding.spec.whatwg.org/#utf-8>'''
- [85] [CITE@en-US[Encoding Standard]] ([TIME[2016-07-29 16:12:31 +09:00]]) <https://encoding.spec.whatwg.org/#specification-hooks>
- [53] [CITE@en[RFC 7617 - The 'Basic' HTTP Authentication Scheme]] ([TIME[2015-10-01 09:47:40 +09:00]] 版) <https://tools.ietf.org/html/rfc7617#section-2.1>
- [58] [CITE@en[RFC 7616 - HTTP Digest Access Authentication]] ([TIME[2015-11-10 07:05:08 +09:00]] 版) <https://tools.ietf.org/html/rfc7616#section-3.3>
- [69] [CITE@en[RFC 7616 - HTTP Digest Access Authentication]] ([TIME[2015-11-10 07:05:08 +09:00]] 版) <https://tools.ietf.org/html/rfc7616#section-4>
]REFS]
* Unicode と UTF-8
[44] [[Unicode]] は、色々な[[文字]]に[[符号]]を与えています。
その[[符号]]をどのように表現するかは選択の余地があり、
歴史的に幾つかの方法が用いられました。その中で現在最も広く用いられているのが
[[UTF-8]] です。 [[UTF-8]] は[[文字]]の[[符号]]を一定の規則で求められる1-4個の[[バイト]]の列として表すものです。
[EG[
[45] [[文字]]「[CODE(char)[a]]」 ([CODE(charname)@en[[[LATIN SMALL LETTER A]]]]) は
[[Unicode]] で [CODE(char)[[[U+0061]]]] という[[符号位置]]が割り当てられています。
これは [[UTF-8]] では[[バイト列]] [CODE(char)[0x61]] によって表されます。
]EG]
[EG[
[46] [[文字]]「[CODE(char)[字]]」 ([CODE(charname)@en[[[CJK UNIFIED IDEOGRAPH-5B57]]]]) は
[[Unicode]] で [CODE(char)[[[U+5B57]]]] という[[符号位置]]が割り当てられています。
これは [[UTF-8]] では[[バイト列]] [CODE(char)[0xE5 0xAD 0x97]] によって表されます。
]EG]
* 定義
@@
* 性質
[38] [[ASCII互換符号化]]です。
[39] [CODE(char)[[[0x00]]]]-[CODE(char)[[[0x7F]]]] は常に
[CODE(char)[[[U+0000]]]]-[CODE(char)[[[U+007F]]]] を表します。
[40] [CODE(char)[[[U+0000]]]]-[CODE(char)[[[U+10FFFF]]]] のすべての[[符号位置]]を[[符号化]]できます。
[48] すべての[[符号位置]]に対応する[[バイト列]]が一意に定まります。
[49] [[文字列]]の[[部分一致]]と[[文字列]]に対応する[[バイト列]]の[[部分一致]]の結果が等しくなります。
[50] [[文字列]]の[[符号位置]]による[[整列]]と[[文字列]]に対応する[[バイト列]]の[[整列]]の結果が等しくなります。
[51] 任意の[[バイト列]]が妥当な[[文字列]]を表すとは限りません。
[52] [[BOM]] を使わない限りは、[[文字列]]を表す[[バイト列]]の単純な連結が[[文字列]]の連結となります。
* BOM との関係
[2] ''[CODE(charset)[UTF-8]] の [[BOM]] は必須ではありません''。
詳しくは [[BOM]>>9] を参照して下さい。 BOM
必須説は、そういうことにしたい人達が勝手に流した風説です。
[8] [[BOM]] を使うと [[UTF-8]] の重要な性質の1つである [[ASCII]] 互換性が失われます。
多くの場合 [[BOM]] を使うのは適切ではないと考えられています。
* 非文字との関係
- [3] [[Unicode]] 3.0 以降では S-area の符号位置 (の UTF-8 表現) は禁止されています。他方、 [CODE[U+FFFF]] のような non-character (の UTF-8 表現) は禁止されていません。 non character は情報交換を目的としたものではありませんから情報交換用で紛れ込んでいたなら間違いですが、内部処理に使うことが出来るものですから、 [[UTF]] で禁止したら使う意味が無くなるということらしいです。
* Charset 名
[13] [[IANA]] に登録された [[charset]] 名は [DFN[[CODE(charset)@en[[[utf-8]]]]]] です。
[14] [[HTTP]] では、たまに誤って [[charset]] 名として [CODE(charset)@en[[[utf8]]]]
が用いられることがあります。
** Unicode の版との関係
@@ [15] [CODE(charset)@en[[[unicode-1-1-utf-8]]]] は・・・
* HTML における UTF-8
[42] [[XML文書]]が [CODE(HTML)@en[[[<meta charset>]]]] を含む場合、その値は
[CODE(charset)@en[[[UTF-8]]]] ([[ASCII大文字・小文字不区別]]) でなければなりません。
従って当該[[文書]]の[[文字符号化]]は、 [[UTF-8]] でなければなりません。
;; [CODE(HTML)@en[[[<meta charset>]]]] 参照。
;; [43] [[HTML文書]]や [CODE(HTML)@en[[[<meta charset>]]]] を含まない[[XML文書]]にはこの制約は適用されません。
* 符号化
[108] [DFN[[RUBYB[UTF-8符号化]@en[UTF-8 encode]]]]は、
[[符号位置ストリーム]][VAR[ストリーム]]について、次のようにします [SRC[>>85]]。
[FIG(steps)[
= [109] [[符号化][符号化 (動詞)]]した結果を返します。
[FIG(list members)[
: [VAR[ストリーム]] : [VAR[ストリーム]]
: [VAR[符号化]] : [[UTF-8]]
]FIG]
]FIG]
[113] 次の場面で使われます。
[FIG(list middle)[ [132] [[UTF-8符号化]]が使われる場面
- [[UTF-8パーセント符号化]]
- [[ホスト構文解析器]]
- [CODE[Response.redirect]]
- [[fetch]] [CODE(HTTP)@en[Origin:]], [CODE(HTTP)@en[Referer:]], [CODE(HTTP)@en[Content-Length:]]
- [[fetch]] [CODE(DOMi)@en[BodyInit]] [CODE(DOMi)@en[USVString]]
- [[CORS check]]
- [CODE(JS)@en[document.cookie]]
- [CODE(HTML)@en[<meta http-equiv=Set-Cookie>]]
- [[Web Transport Processing]]
- [CODE(DOMi)@en[Blob]] [[コンストラクター]]
- [CODE(DOMi)@en[File]] [[コンストラクター]]
]FIG]
[111] [CODE(DOMi)@en[TextEncoder]] の [CODE(DOMm)@en[encode][TextEncoder]]
[[メソッド]]は、[[UTF-8符号化]]を使っていませんが、実質的に等価です。
[110] 他に、[[符号化][符号化 (動詞)]]操作が [[UTF-8]] について実行されることもあります。
-*-*-
[95] [[BOM]] は生成されません。[[文字列]]の先頭に [CODE[ZWNBSP]] がある場合、
[[復号][復号 (符号化)]]や[[UTF-8復号]]は [[BOM]] とみなすので、
[[文字列]]に戻した時に [CODE[ZWNBSP]] が失われてしまいます。
* 復号
[86] [DFN[[RUBYB[UTF-8復号]@en[UTF-8 decode]]]]は、
[[バイトストリーム]][VAR[ストリーム]]を次のようにします [SRC[>>85]]。
[FIG(steps)[
= [87] [VAR[バッファー]]を、空の[[バイト列]]に設定します。
= [88] [VAR[ストリーム]]から3バイトを[VAR[バッファー]]に[[読み][読む (ストリーム)]]ます。
= [89] [VAR[バッファー]]が [CODE[0xEF 0xBB 0xBF]] ''以外''なら、
== [90] [VAR[ストリーム]]に[VAR[バッファー]]を [[prepend][prepend (ストリーム)]]します。
= [91] [VAR[出力]]を、[[符号位置ストリーム]]に設定します。
= [92] [[UTF-8]] の[F[復号器]]を[[走らせ][走らせる]]ます。
[VAR[入力]]を[VAR[ストリーム]]、[VAR[出力]]を[VAR[出力]]とします。
= [93] [VAR[出力]]を返します。
]FIG]
;; [94] つまりこの操作は先頭の [CODE(charname)@en[BOM]] を無視します。
[96] [DFN[[RUBYB[BOMなしUTF-8復号]@en[UTF-8 decode without BOM]]]]は、
[[バイトストリーム]][VAR[ストリーム]]を次のようにします [SRC[>>85]]。
[FIG(steps)[
= [97] [VAR[出力]]を、[[符号位置ストリーム]]に設定します。
= [98] [[UTF-8]] の[F[復号器]]を[[走らせ][走らせる]]ます。
[VAR[入力]]を[VAR[ストリーム]]、[VAR[出力]]を[VAR[出力]]とします。
= [99] [VAR[出力]]を返します。
]FIG]
;; [100] 先頭に [CODE(charname)@en[BOM]] があったとしても、
[CODE(charname)@en[BOM]] ではなく [CODE(charname)@en[ZWNBSP]] とみなします。
[101] [DFN[[RUBYB[BOMなしUTF-8復号または失敗]@en[UTF-8 decode without BOM or fail]]]]は、
[[バイトストリーム]][VAR[ストリーム]]を次のようにします [SRC[>>85]]。
[FIG(steps)[
= [102] [VAR[出力]]を、[[符号位置ストリーム]]に設定します。
= [103] [VAR[結果]]を、 [[UTF-8]] の[F[復号器]]を[[走らせ][走らせる]]た結果に設定します。
[VAR[入力]]を[VAR[ストリーム]]、[VAR[出力]]を[VAR[出力]]、
[VAR[[[誤りモード]]]]を [CODE[fatal][fatal (符号化)]] とします。
= [105] [VAR[結果]]が[[誤り][誤り (符号化)]]なら、
== [106] [[失敗]]を返します。
= [107] それ以外なら、
== [104] [VAR[出力]]を返します。
]FIG]
[112] これらの操作は同期的に処理される[[手続き]]のような形で[[仕様書]]では記述されていますが、
実際には、呼び出される文脈次第で、入力ストリームを読みながら、読んだところから順に[[復号器]]に与え、
出力ストリームに書き込んでいくことが想定されているようです。
[114] これらの操作の呼び出される場面については、[[復号][復号 (符号化)]]を参照。
-*-*-
[117] [[UTF-8]] の[[復号器オブジェクト]]は、次の状態を持ちます
[SRC[>>116]]。
[FIG(list members)[
: [DFN[[F[[RUBYB[[[UTF-8符号位置]]]@en[UTF-8 code point]]]]]] :
初期値は [N[0]]。
: [DFN[[F[[RUBYB[[[UTF-8見たバイト数]]]@en[UTF-8 bytes seen]]]]]] :
初期値は [N[0]]。
: [DFN[[F[[RUBYB[[[UTF-8必要バイト数]]]@en[UTF-8 bytes needed]]]]]] :
初期値は [N[0]]。
: [DFN[[F[[RUBYB[[[UTF-8下境界]]]@en[UTF-8 lower boundary]]]]]] :
初期値は [N[0x80]]。
: [DFN[[F[[RUBYB[[[UTF-8上境界]]]@en[UTF-8 upper boundary]]]]]] :
初期値は [N[0xBF]]。
]FIG]
[118] [[UTF-8]] [[復号器オブジェクト]][VAR[復号器]]の[F[取扱器]]は、
[VAR[ストリーム]]と[VAR[字句]]について、次のようにします [SRC[>>116]]。
[FIG(steps)[
= [119] [VAR[字句]]が [[end-of-stream]] なら、
== [122] [VAR[復号器]]の[F[UTF-8必要バイト数]]が [N[0]] 以外なら、
=== [120] [VAR[復号器]]の[F[UTF-8必要バイト数]]を [N[0]] に設定します。
=== [121] [[誤り][誤り (符号化)]]を返します。
== [123] それ以外なら、
=== [124] [[終了済み][終了済み (符号化)]]を返します。
= [125] それ以外で、[VAR[復号器]]の[F[UTF-8必要バイト数]]が [N[0]] なら、
== [126] [VAR[バイト]]により、次表に従い、
[VAR[復号器]]の[F[UTF-8必要バイト数]]、[F[UTF-8符号位置]]、[F[UTF-8上境界]]、
[F[UTF-8下境界]]が指定されていればそれぞれ設定し、
[VAR[返し値]]を返します。
[FIG(table)[
:バイト: [VAR[バイト]]
:必要: [F[UTF-8必要バイト数]]
:符号位置: [F[UTF-8符号位置]]
:上界: [F[UTF-8上境界]]
:下界: [F[UTF-8下境界]]
:返す: [VAR[返し値]]
:バイト: [ [N[0x00]], [N[0x7F]] ]
:返す: [VAR[バイト]]と同じ値の[[符号位置]]
:バイト: [ [N[0xC2]], [N[0xDF]] ]
:必要: [N[1]]
:符号位置: [VAR[バイト]] [[&]] [N[0x1F]]
:返す: [[継続][継続 (符号化)]]
:バイト: [N[0xE0]]
:必要: [N[2]]
:下界: [N[0xA0]]
:符号位置: [VAR[バイト]] [[&]] [N[0xF]]
:返す: [[継続][継続 (符号化)]]
:バイト: [ [N[0xE1]], [N[0xEC]] ], [N[0xEE]], [N[0xEF]]
:必要: [N[2]]
:符号位置: [VAR[バイト]] [[&]] [N[0xF]]
:返す: [[継続][継続 (符号化)]]
:バイト: [N[0xED]]
:必要: [N[2]]
:上界: [N[0x9F]]
:符号位置: [VAR[バイト]] [[&]] [N[0xF]]
:返す: [[継続][継続 (符号化)]]
:バイト: [N[0xF0]]
:必要: [N[3]]
:符号位置: [VAR[バイト]] [[&]] [N[0x7]]
:下界: [N[0x90]]
:返す: [[継続][継続 (符号化)]]
:バイト: [ [N[0xF1]], [N[0xF3]] ]
:必要: [N[3]]
:符号位置: [VAR[バイト]] [[&]] [N[0x7]]
:返す: [[継続][継続 (符号化)]]
:バイト: [N[0xF4]]
:必要: [N[3]]
:符号位置: [VAR[バイト]] [[&]] [N[0x7]]
:上界: [N[0x8F]]
:返す: [[継続][継続 (符号化)]]
:バイト: それ以外
:返す: [[誤り][誤り (符号化)]]
]FIG]
= [146] それ以外で、[VAR[バイト]]が [ [VAR[復号器]]の[F[UTF-8下境界]], [VAR[復号器]]の[F[UTF-8上境界]] ] の範囲内に''ない''なら、
== [147] [VAR[復号器]]の[F[UTF-8必要バイト数]]を、 [N[0]] に設定します。
== [150] [VAR[復号器]]の[F[UTF-8見たバイト数]]を、 [N[0]] に設定します。
== [148] [VAR[復号器]]の[F[UTF-8符号位置]]を、 [N[0]] に設定します。
== [149] [VAR[復号器]]の[F[UTF-8下境界]]を、[N[0x80]] に設定します。
== [151] [VAR[復号器]]の[F[UTF-8上境界]]を、[N[0xBF]] に設定します。
== [152] [VAR[バイト]]を[VAR[ストリーム]]に[[prepend][prepend (ストリーム)]]します。
== [153] [[誤り][誤り (符号化)]]を返します。
= [154] それ以外なら、
== [156] [VAR[復号器]]の[F[UTF-8見たバイト数]]を[[インクリメント]]します。
== [157] [VAR[復号器]]の[F[UTF-8符号位置]]を、
([VAR[復号器]]の[F[UTF-8符号位置]] [[<<]] 6) [[|]] ([VAR[バイト]] [[&]] [N[0x3F]])
に設定します。
== [158] [VAR[復号器]]の[F[UTF-8下境界]]を、[N[0x80]] に設定します。
== [159] [VAR[復号器]]の[F[UTF-8上境界]]を、[N[0xBF]] に設定します。
== [155] [VAR[復号器]]の[F[UTF-8必要バイト数]]と[VAR[復号器]]の[F[UTF-8見たバイト数]]が等しくなければ、
=== [160] [[継続][継続 (符号化)]]を返します。
== [161] それ以外なら、
=== [162] [VAR[符号位置]]を、値が[VAR[復号器]]の[F[UTF-8符号位置]]の[[符号位置]]に設定します。
=== [163] [VAR[復号器]]の[F[UTF-8符号位置]]を、 [N[0]] に設定します。
=== [164] [VAR[復号器]]の[F[UTF-8見たバイト数]]を、 [N[0]] に設定します。
=== [165] [VAR[復号器]]の[F[UTF-8必要バイト数]]を、 [N[0]] に設定します。
=== [166] [VAR[符号位置]]を返します。
]FIG]
[127] これより、不正なバイト列、[CODE(char)[U-00110000]] [[以上]]、
[[サロゲート]]は、構成する各[[バイト]]が [CODE(char)[U+FFFD]] に置き換えられます。
* HTTP 認証の [CODE(charset)@en[UTF-8]]
[54] [[基本認証]]や[[ダイジェスト認証]]の [CODE(HTTP)@en[[[charset=""]]]] [[引数]]には値
[DFN[[CODE(charset)@en[[[UTF-8]]]]]] を指定できます [SRC[>>53, >>58, >>69]]。
[55] これは、[[文字列]]を [[NFC]] で[[正規化]]してから、
[[RFC 3629]] [[UTF-8]] で[[バイト列]]に変換することをいいます [SRC[>>53, >>69]]。
[56] [[受信者]]は、[[利用者識別子]]においては、
[[RFC 7613]] [CODE[[[UsernameCasePreserved]]]] プロファイルから
[CODE[[[:]]]] を除くすべての[[文字]]に対応しなければ[['''なりません''']] [SRC[>>53, >>69]]。
[REFS[
- [74] [CITE@en[Character set "UTF-8 username character"]] ([TIME[2016-01-04 23:18:56 +09:00]] 版) <https://chars.suikawiki.org/set/%24rfc7616%3AUTF-8%3Ausername-char>
- [75] [CITE@en[Character set "UTF-8 user-id character"]] ([TIME[2016-01-04 23:19:15 +09:00]] 版) <https://chars.suikawiki.org/set/%24rfc7617%3AUTF-8%3Auser-id-char>
]REFS]
;; [70] [[基本認証]]では [[credentials]] で、
[[ダイジェスト認証]]では [VAR[[[A1]]]] で [CODE[[[:]]]]
が区切り文字として使われているため、
[CODE[[[:]]]] は除外されているようです。
[57] [[受信者]]は、[[合言葉]]においては、
[[RFC 7613]] [CODE[[[OpaqueString]]]] プロファイルからすべての[[文字]]に対応しなければ[['''なりません''']] [SRC[>>53, >>69]]。
[REFS[
- [72] [CITE@en[Character set "UTF-8 password character"]] ([TIME[2016-01-04 23:18:02 +09:00]] 版) <https://chars.suikawiki.org/set/%24rfc7616%3AUTF-8%3Apassword-char>
- [73] [CITE@en[Character set "UTF-8 password character"]] ([TIME[2016-01-04 23:18:37 +09:00]] 版) <https://chars.suikawiki.org/set/%24rfc7617%3AUTF-8%3Apassword-char>
]REFS]
;; [71] [[プロファイル]]の[[文字]]への対応は要求していますが、
[[プロファイル]]自体を適用することは要求されていないようです。
また、[[プロファイル]]で禁止されている[[文字]]を使うことを禁止はしていないようです。
;; [76] 「対応」というのが何を意味しているのか不明です。
[[利用者名]]や[[合言葉]]に使える[[文字]]については[[HTTP]]としての制約以外に、
[[アプリケーション]]や[[組織]]などの制約もありそうです。
[[IETF]] が[[組織]]の[[セキュリティーポリシー]]や[[アプリケーション]]の[[データベース]]設計などに介入しようとしているとは考えにくいですから、
[[プロファイル]]に含まれる[[文字]]であっても使えないことはありそうです。
普通[[サーバー]]は[[利用者名]]や[[合言葉]]が本来のものと一致しなければすべて
[CODE(HTTP)[[[401]]]] エラーにしますから、
[[サーバー]]が [[HTTP]] レベルでこれらの[[プロファイル]]の[[文字]]に対応しているかどうかは、
外部から観測できないように思えます。
[[プロファイル]]に従い[[写像]]や[[正規化]]を適用することを指しているのだとしたら観測可能ですが、
そんな実装はあるのでしょうか。。。
* 歴史
** ISO/IEC 10646 の定義
[36] [[ISO/IEC 10646]] では[[符号位置]]が [CODE(char)[[[U-7FFFFFFF]]]]
まであり、そのすべてが [[UTF-8]] でも表現できます。[[UTF-8]]
における1[[文字]]は最大6[[バイト]]で表現されます。
;; [37] [CODE(char)[[[U-00110000]]]] 以上の[[符号位置]]には[[文字]]は割り当てられていませんが
([[私用域]]が以前はありましたが削除されました。)、
[[UTF-8]] としては現在も存在しているはずです。
** RFC による定義
- [6] [WEAK[2003-11-10 23:49:29 +00:00]] ''[[名無しさん]]'': ついに IETF Full Standard の [[RFC3629]] (= [[STD63]]) がでました。
[41] [[Net-Unicode]] はそれに[[制御文字]]の用法や[[正規化]]に関する規定を加えた[[プロファイル]]です。
** CESU-8
[7] [[CESU-8]] は [CODE(char)[[[U+10000]]]] 以上の[[符号位置]]を [[UTF-16]]
同様の[[サロゲートペア]]によって表現するものです。
;; [[CESU-8]] を参照。
** Web UTF-8
[19] [[Web Applications 1.0]] は、「[DFN[[RUBYB[バイト列をUTF-8として誤り取り扱い付きで復号]@en[decode a byte string as UTF-8, with error handling]]]]」することについて規定しています。
これは、 [[UTF-8]] [[バイト列]]を[[文字列]]に[[復号]]するにあたって不正な[[バイト列]]を適宜
[CODE(char)[[[U+FFFD]]]] に置き換える方法を定めたものです。
[REFS[
- [18] [[Web Applications 1.0]]
<http://www.whatwg.org/specs/web-apps/current-work/complete.html#decoded-as-utf-8,-with-error-handling>
]REFS]
[17] [CITE@en[Web Applications 1.0 r5530 Tighten up UTF-8 error handling definitions Fixing http://www.w3.org/Bugs/Public/show_bug.cgi?id=9663]]
( ([TIME[2010-09-29 04:16:00 +09:00]] 版))
<http://html5.org/tools/web-apps-tracker?from=5529&to=5530>
[47] これは後の [[Encoding Standard]] の定義につながりました。現在の [[HTML Standard]]
は [[Encoding Standard]] を参照しています。
* 実装
** Emacs で UTF-8
[11] [[Emacs]] で [[UTF-8]] な[[ファイル]]を開くとなぜか[[漢字]]だけ全部化ける ([[仮名]]とかは化けない)
という時は [[.emacs]] とかにこう書くと直るかもよ:
[PRE(example code)[
(prefer-coding-system 'utf-8-unix)
]PRE]
** Perl の UTF-8
[12] [[Perl]] の [CODE(perl)@en[[[Encode]]]] [[モジュール]]には「[[utf8]]」と「[[utf-8]]」
があります。「[[utf8]]」は [[UTF-8]] っぽい[[符号化方式]]を使った [[Perl]]
の[[内部コード]]、「[[utf-8]]」は [[Unicode]] の [[UTF-8]] です。
*** utf8 旗と utf8 文字列
@@ ・・・
*** [CODE(perl)@en[use utf8]]
@@ ・・・
**** [CODE(perl)@en[use encoding]] との関係
@@ ・・・
*** [CODE(perl)@en[utf8]] 符号化
[66] [[Perl]] の [CODE(perl)@en[[[Encode]]]] [[モジュール]]は[[文字符号化]]の名前として
「[CODE(perl)@en[[[utf8]]]]」 と 「[CODE(perl)@en[[[utf-8]]]]」に対応しています。
前者は [[Perl]] の[[文字列]]の[[内部符号化]]方式としての [[UTF-8]]
(の[[バイト文字列]]としての表現)、
後者は [[Unicode]] の[[文字符号化方式]]である [[UTF-8]] を表しています。
*** [CODE(perl)@en[:utf8]] PerlIO 層
[67] [KBD@en[[[perldoc]] [[PerlIO]]]] にもちゃんと書いてありましたが、
[[PerlIO]] [[層]] [CODE(perl)@en[:[[utf8]]]] を使った入力は不正な入力も黙って受け入れます。
読み込むファイルが [[UTF-8]] として不正な[[バイト列]]であったとしても、警告も何も無しで、
黙って [[utf8]] [[旗]]を立てた SV にするみたいです。なので、入力が不正なバイト列である可能性がある場合、
[CODE(perl)@en[:[[encoding]]([[utf8]])]] を使う必要があります。
こちらは不正なバイト列を [CODE(example)[\x[VAR[HH]]]] に置き換えるようです。
おそらく [CODE(perl)@en[:[[utf8]]]] の方が早いのでしょうが、もし不正なバイト列が混入していた場合、
読み込みの時点では何も起こらず、その後読み込んだ文字列に対して何らかの操作を行おうとした時点で
[Q@en[Malformed UTF-8 character (fatal)]]
というエラーが出ますので、デバッグが難しくなるかもしれません。
*** EBCDIC 環境との関係
@@ ・・・
*** メモ
[68] [CITE[Perl, utf8 フラグ, ハッシュ, リテラル, => - 冬通りに消え行く制服ガールは、夢物語にリアルを求めない。 - subtech]]
([TIME[2010-03-25 09:56:06 +09:00]] 版)
<https://subtech.g.hatena.ne.jp/cho45/20100323/1269329227>
** Java の UTF
[1] [[Java]] が実装している UTF-8 の変種は、 U+0000 を表現するために
0xC0 0x80 を (0x00 の代わりに) 使います。 (0x00 は Java
では文字列の終端を表し、文字列内には入れられません。)
- [4] このような、「長さが最小ではない表現」は、 UTF-8 では禁止されています。[WEAK[もっとも、各規格は当初そのことを忘れていました。設計者は最初からそのことに注意していたらしいですが、気が抜けていたとかなんとか。]]
- [5] 実際には巷の UTF-8 の decoder は最短じゃない表現を「意図どおりに」解読してしまうことがありますが、それは禁止されています。
[9]
[Q[Java [RUBYB[修正] [modified]] UTF-8]] (昔は Java の世界で [Q[UTF-8]] と呼ばれていたもの。) は >>1 に加えて [[CESU-8]] らしいです。
''Supplementary Characters in the Java Platform'' <http://java.sun.com/developer/technicalArticles/Intl/Supplementary/>
[10]
''JNI Types and Data Structures'' <http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/types.html>
** MySQL の UTF8
[25] [[MySQL]] では元々の [CODE[[[utf8]]]] は3バイトまでしか表せませんでした。
のちにこれは [CODE[[[utf8mb3]]]] という別名が付けられ、それとは別に、
4バイトまで表せる [CODE[[[utf8mb4]]]] が追加されています。
[61] [[MySQL]] の [CODE[[[CHARSET]]]] [DFN[[CODE[utf8]]]]、[DFN[[CODE[utf8mb3]]]] は、1文字が3バイト以下で表せる範囲の
[[UTF-8]] です。
[62] [[Unicode]] の範囲をすべて表せるためには [CODE[[[utf8mb4]]]] を使う必要があります。
[REFS[
-[63] [CITE@ja[MySQL :: MySQL 5.1 リファレンスマニュアル :: 9.7 Unicodeのサポート]]
([TIME[2009-09-28 15:58:25 +09:00]] 版)
<http://dev.mysql.com/doc/refman/5.1/ja/charset-unicode.html>
-[64] [CITE@en[MySQL :: MySQL 5.5 Reference Manual :: 10.1.10.4 The utf8 Character Set (3-Byte UTF-8 Unicode Encoding)]]
( ([TIME[2012-12-15 08:37:37 +09:00]] 版))
<http://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8.html>
-[65] [CITE@en[MySQL :: MySQL 5.5 Reference Manual :: 10.1.10.5 The utf8mb3 “Character Set” (Alias for utf8)]]
( ([TIME[2012-12-15 08:38:03 +09:00]] 版))
<http://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb3.html>
]REFS]
* 関連
[59]
[FIG(short list)[
- [[CESU-8]]
- [[WTF-8]]
- [[WTF-8 (Windows Transformation Format)]]
- [[UTF-EBCDIC]]
- [[UTF-8-MAC]]
]FIG]
* メモ
[16] [CITE[Official Google Blog: Unicode nearing 50% of the web]]
([TIME[2010-01-29 05:36:25 +09:00]] 版)
<http://googleblog.blogspot.com/2010/01/unicode-nearing-50-of-web.html>
[20] [CITE@en[Web Applications 1.0 r5940 typo in the allowed UTF-8 ranges]]
( ([TIME[2011-03-04 11:06:00 +09:00]] 版))
<http://html5.org/tools/web-apps-tracker?from=5939&to=5940>
[21] [CITE@en[Web Applications 1.0 r5942 Fix the UTF-8 decoder error handling to handle a few errors I'd missed, including in particular surrogate halves. This may be a mistake; if I'm forgetting something please let me know so I can fix it. (e.g. did we decide not to catch surrogates or something?)]]
( ([TIME[2011-03-04 11:56:00 +09:00]] 版))
<http://html5.org/tools/web-apps-tracker?from=5941&to=5942>
[22] [CITE@en[RFC 6120 - Extensible Messaging and Presence Protocol (XMPP): Core]]
( ([TIME[2011-03-31 08:23:45 +09:00]] 版))
<http://tools.ietf.org/html/rfc6120#section-11.6>
[23] [CITE[「私のために争わないで」文字コードのUTF8さん、自殺 : bogusnews]]
( ([TIME[2012-04-01 10:06:51 +09:00]] 版))
<http://bogusne.ws/article/41580267.html>
[24] [CITE[IRC logs: freenode / #whatwg / 20120419]]
( ([TIME[2012-04-24 21:49:36 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20120419>
[26] [CITE@en[Web Applications 1.0 r7647 Embrace the Encodings specification.]]
( ([TIME[2013-01-24 10:38:00 +09:00]] 版))
<http://html5.org/tools/web-apps-tracker?from=7646&to=7647>
[27] [CITE[Provide better encoding label guidance. (Basically require utf-8 all ove... · a454d2e · whatwg/encoding]]
( ([TIME[2013-02-16 12:48:30 +09:00]] 版))
<https://github.com/whatwg/encoding/commit/a454d2e543964b8d5432778ff917324e8032b78c>
[28] [CITE@en[Web Applications 1.0 r7782 Strip a leading BOM from scripts in workers, if any. Also, use more of the encoding spec.]]
( ([TIME[2013-03-30 03:45:00 +09:00]] 版))
<http://html5.org/tools/web-apps-tracker?from=7781&to=7782>
[29] [CITE[ 3 - JNI Types and Data Structures ]]
( ([TIME[2011-09-07 21:57:56 +09:00]] 版))
<http://docs.oracle.com/javase/1.3/docs/guide/jni/spec/types.doc.html#16542>
[30] [CITE[jwerle/libutf8]]
( ([TIME[2013-12-16 00:12:32 +09:00]] 版))
<https://github.com/jwerle/libutf8>
[31] [CITE@en[Web Applications 1.0 r8405 Various editorial tweaks.]]
( ([TIME[2014-01-17 17:12:00 +09:00]] 版))
<http://html5.org/tools/web-apps-tracker?from=8404&to=8405>
[32] [[Gmail]] の (日本語での?) デフォルト設定が2014年4月中頃に [[ISO-2022-JP]] から [[UTF-8]]
に変わったようです。 (13-17 の間?)
[33] [CITE@en-US[JNI Types and Data Structures]]
( ([TIME[2014-05-08 13:10:38 +09:00]] 版))
<http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html#wp16542>
[35] [CITE@en[Web Applications 1.0 r8722 Adjust notes on encoding detection]]
( ([TIME[2014-08-28 08:12:00 +09:00]] 版))
<http://html5.org/r/8722>
[60] [CITE@en[Fix #19: reword utf-8 decoder step to avoid extra parenthesis · whatwg/encoding@05d9649]]
([TIME[2015-12-16 12:30:40 +09:00]] 版)
<https://github.com/whatwg/encoding/commit/05d96490cba5e800e40b76bfd4acc7e7ff2981ae>
[FIG(quote)[
[FIGCAPTION[
[77] [CITE@ja[【開発】.net C#でRSS/Atom feedとか読んでみる | 鍋風呂]]
([TIME[2016-01-07 17:51:33 +09:00]] 版)
<http://blog.ahh.jp/?p=1007>
]FIGCAPTION]
> <?xml encode=”***”>が適当。結構多かった。”utf-8”となるべきところ、”utf8”となっている。
]FIG]
[78] [CITE@en[Add utf-8 decode without BOM or fail for HTML · whatwg/encoding@4b20911]]
([TIME[2016-02-10 21:42:33 +09:00]] 版)
<https://github.com/whatwg/encoding/commit/4b209111f7ab450eb1935551159b98413b5c23e0>
[79] [CITE@en[Use utf-8 decode without BOM rather than UTF-8 decoder · whatwg/html@39a2e6c]]
([TIME[2016-02-10 21:44:11 +09:00]] 版)
<https://github.com/whatwg/html/commit/39a2e6cde3b4820db56fabe1859de0dc0e6ed8d9>
[80] [CITE@en[Drop dependencies on Encoding Standard's decoder concept · whatwg/url@37f9329]]
([TIME[2016-02-11 12:00:57 +09:00]] 版)
<https://github.com/whatwg/url/commit/37f932928378c0df521034cfd223f4ba603ef476>
[81] [CITE@en[Update integration with Encoding Standard · whatwg/html@6a31c26]]
([TIME[2016-02-14 18:47:22 +09:00]] 版)
<https://github.com/whatwg/html/commit/6a31c26cf12e39dab1a488e75dd56c03d6786d39>
[FIG(quote)[
[FIGCAPTION[
[82] [CITE@en[RFC 4194 - The S Hexdump Format]]
([TIME[2015-12-13 15:30:39 +09:00]] 版)
<https://tools.ietf.org/html/rfc4194#section-9>
]FIGCAPTION]
> Required parameters: charset
> This parameter must exist and must be set to "UTF-8". No other
> character sets are allowed for transporting SHF data. The character
> set designator MUST be uppercase.
]FIG]
[83] [CITE@en[Editorial: avoid teaching bad UTF-8 math · whatwg/encoding@19a25b5]]
([TIME[2016-04-07 11:08:35 +09:00]] 版)
<https://github.com/whatwg/encoding/commit/19a25b5fcae895853d964b7ee6afa2fe9b6070a8>
[84] [CITE[UTF-8 processing using SIMD (SSE4)]]
([TIME[2016-05-25 18:28:34 +09:00]])
<https://woboq.com/blog/utf-8-processing-using-simd.html>
[128] [CITE@en[Parse application/x-www-form-urlencoded using UTF-8 only]]
([[annevk]]著, [TIME[2017-01-17 19:11:02 +09:00]])
<https://github.com/whatwg/url/commit/3fe969679f78c92c353047661b0c4b6797f099f6>
[129] [CITE@en[Thunderbird/SeaMonkey の既定のテキストエンコーディングを UTF-8 に変更する · Issue #63 · mozilla-japan/gecko-l10n]]
([TIME[2017-02-04 13:50:20 +09:00]])
<https://github.com/mozilla-japan/gecko-l10n/issues/63>
[130] [CITE@en[Use Encoding's "UTF-8 encode" hook.]]
([[mkruisselbrink]]著, [TIME[2017-02-04 09:05:21 +09:00]])
<https://github.com/w3c/FileAPI/commit/64c346deb9132a8cefc1ce79050256cfc64fcc72>
[131] [CITE@en[RFC 8160 - IUTF8 Terminal Mode in Secure Shell (SSH)]]
([TIME[2017-04-20 17:11:00 +09:00]])
<https://tools.ietf.org/html/rfc8160>