1. まえがき
UTF-8エンコーディングは、ユニバーサル符号化文字集合であるUnicodeの交換に最も適したエンコーディングです。そのため、新しいプロトコルやフォーマット、または新しいコンテキストで展開される既存のフォーマットにおいても、本仕様はUTF-8エンコーディングを要求し(また定義し)ます。
その他の(レガシー)エンコーディングは、過去にある程度定義されていました。しかし、ユーザーエージェントは必ずしもそれらを同じ方法で実装しておらず、同じラベルを使用しているわけでもなく、未定義や旧来の独自領域の扱いも異なっていました。本仕様はそれらのギャップを埋めることで、新しいユーザーエージェントがエンコーディングの実装をリバースエンジニアリングする必要がなくなり、既存のユーザーエージェントも収束できるようにしています。
特に、本仕様はすべてのエンコーディング、それらのバイトからスカラー値への変換アルゴリズムおよびその逆、そして正規名や識別ラベルを定義しています。また、エンコーディングアルゴリズムの一部をJavaScriptに公開するAPIも定義しています。
ユーザーエージェントは、IANA Character Setsレジストリに記載されているラベルからも大きく逸脱してきました。 レガシーエンコーディングのさらなる拡散を防ぐためにも、本仕様はこれらの詳細について網羅的に記述しており、レジストリを必要としません。特に、本仕様ではエンコーディングのあらゆる側面を拡張する仕組みを提供しません。
2. セキュリティの背景
プロデューサーとコンシューマーが使用中のエンコーディングやその実装方法について合意していない場合、エンコーディングに関するセキュリティ問題が発生します。例えば、2011年に報告された攻撃の一例では、Shift_JISのリーディングバイト0x82が、攻撃者が管理できるJSONリソースのフィールド内で0x22のトレイリングバイトを「マスク」するために使われました。 プロデューサーは、この組み合わせが不正なバイトであるにもかかわらず問題に気付かず、コンシューマーはそれを単一のU+FFFD(�)としてデコードし、U+0022(")が重要なデリミタであるため解釈全体が変わってしまいました。 スカラー値を表すのに複数バイトを使用するエンコーディングのデコーダーは、今では不正なバイトの組み合わせが発生した場合、U+0000からU+007Fまでの範囲のスカラー値が「マスク」されないことを要求しています。前述のシーケンスの場合、出力はU+FFFD U+0022となります。(ただし、gb18030デコーダーだけは、キューの終端で1バイトだけこのようなバイトを「マスク」します。)
リーディングバイトが存在しない場合、ASCIIバイトをASCIIコードポイント以外にマップするエンコーディングでは、より大きな問題になります。これらは「ASCII非互換」エンコーディングと呼ばれ、ISO-2022-JPやUTF-16BE/LEのように展開済みコンテンツのために必要なもの以外はサポートされていません。(その他のエンコーディングもより多くのラベルをreplacementエンコーディングにマッピングできないか調査中です。未知のエンコーディングフォールバックの代わりに。) 例えば、巧妙に作成されたコンテンツをリソースに挿入し、ユーザーにエンコーディングの上書きを促すことで、スクリプトの実行などを引き起こす攻撃があります。
HTMLやHTMLのフォーム機能で使われるURL用エンコーダーも、すべてのスカラー値を表現できないエンコーディングが使われた場合、若干の情報損失が発生することがあります。例えば、windows-1252エンコーディングを使用しているリソースでは、サーバーはエンドユーザーが「💩」と「💩」のどちらをフォームに入力したか区別できません。
ここで挙げられた問題は、UTF-8のみを排他的に使用することで解消されます。これが、すべてにおいてUTF-8を必須エンコーディングとした多くの理由の一つです。
詳細はブラウザーUIの章も参照してください。
3. 用語集
本仕様はInfra標準に依存しています。[INFRA]
16進数は"0x"で始まります。
数式では、すべての数値は整数であり、加算は「+」、減算は「−」、乗算は「×」、整数の除算は「/」(商を返す)、剰余は「%」(整数除算の余りを返す)、論理左シフトは「<<」、論理右シフトは「>>」、ビットごとのANDは「&」、ビットごとのORは「|」で表されます。
論理右シフトの被演算子は、少なくとも21ビットの精度を持っている必要があります。
I/Oキューは、特定の型(つまりバイトやスカラー値)のリストです。 キュー終端は、任意の型の要素としてI/Oキューに存在しうる特別な要素であり、キュー内にこれ以上要素が無いことを示します。
I/Oキューの利用方法は2つあります:即時モードではメモリ内のI/Oデータを表し、ストリーミングモードではネットワークから到着するデータを表します。即時キューは、最後の要素がキュー終端となりますが、ストリーミングキューは必ずしもそうとは限らず、そのため読み取り操作がブロックされることがあります。
ストリーミングI/Oキューは空で作成され、ネットワークからデータが到着するたびに新しい要素がプッシュされることが期待されます。基盤となるネットワークストリームが閉じられると、キュー終端要素がキューにプッシュされます。
ストリーミングI/Oキューからの読み取りはブロックされる可能性があるため、ストリーミングI/Oキューはイベントループからは使用しないでください。代わりに並列で使用してください。
復元のために、要素(ただしキュー終端を除く)をI/Oキューに復元するには、リストの前置操作を行ってください。復元によって、リスト(要素、キュー終端を除く)をI/Oキューに復元するには、指定された順序でキュー先頭に挿入します。
バイト « 0xF0, 0x9F » をI/Oキュー « 0x92 0xA9, キュー終端 » に挿入すると、I/Oキューは« 0xF0, 0x9F, 0x92 0xA9, キュー終端 » となります。次に読み取られる要素は0xF0です。
Infra標準で型変換に関するインフラが定義される予定です。 whatwg/infra issue #319も参照。[INFRA]
I/Oキューはリストとして定義されており、キューではありません。これは復元操作を持つためですが、この復元操作は本仕様のアルゴリズム内部の詳細であり、他の標準で使うものではありません。実装では、実装上の注意事項に記載の通り、こうしたアルゴリズムを別の方法で実装しても構いません。
サロゲートからスカラー値を得るには、リーディングサロゲートleadingとトレーリングサロゲートtrailingが与えられたとき、0x10000 + ((leading − 0xD800) << 10) + (trailing − 0xDC00) を返します。
Uint8Array
オブジェクトを作成するには、I/OキューioQueueとrealmrealmが与えられたとき:
-
変換でioQueueをバイト列に変換し、それをbytesとする。
-
作成で、
Uint8Array
オブジェクトをrealm内のbytesから作成し、それを返す。
4. エンコーディング
エンコーディングは、スカラー値列とバイト列との間の対応付け(およびその逆)を定義します。各エンコーディングには名前および1つ以上のラベルがあります。
本仕様は、Unicode標準で定義されているエンコーディングスキームと同じ名前を持つ3つのエンコーディング(UTF-8、UTF-16LE、UTF-16BE)を定義しています。エンコーディングは、バイト順マーク(BOM)の扱いがエンコーディング自体の一部ではなく、本仕様のラッパーアルゴリズムの一部である点で、Unicode標準のエンコーディングスキームと異なります。UTF-8とUTF-8デコードアルゴリズムを組み合わせることで、同名のエンコーディングスキームと一致します。 本仕様は、UTF-16LEおよびUTF-16BEを同様にラップするアルゴリズムは提供しません。[UNICODE]
4.1. エンコーダーとデコーダー
各エンコーディングには対応するデコーダーがあり、多くの場合は対応するエンコーダーもあります。デコーダーやエンコーダーのインスタンスは、ハンドラアルゴリズムを持ち、また状態を持つ場合もあります。ハンドラアルゴリズムは、入力のI/Oキューと要素を受け取り、終端、1個以上の要素、エラー(任意で符号位置付き)、または継続のいずれかを返します。
replacementおよびUTF-16BE/LEのエンコーディングには エンコーダーはありません。
以下で使われるエラーモードは、デコーダーの場合は"replacement
"または"fatal
"、エンコーダーの場合は"fatal
"または"html
"となります。
XMLプロセッサはエラーモードを"fatal
"に設定します。
[XML]
"html
"は、HTMLフォームが終了しないレガシーエンコーダーを必要とするため、エラーモードとして存在します。"html
"エラーモードは、正当な入力と区別できないシーケンスを出力し、サイレントなデータ損失につながる可能性があります。開発者はこれを防ぐため、UTF-8エンコーディングを使用することが強く推奨されます。
[HTML]
キューを処理するには、エンコーディングのデコーダーまたはエンコーダーインスタンスencoderDecoder、I/Oキューinput、I/Oキューoutput、エラーモードmodeが与えられたとき、次の手順を実行します:
要素を処理するには、要素item、エンコーディングのエンコーダーまたはデコーダーインスタンスencoderDecoder、I/Oキューinput、I/Oキューoutput、エラーモードmodeが与えられたとき、次の手順を実行します:
4.2. 名前とラベル
下表は、すべてのエンコーディングおよびユーザーエージェントがサポートしなければならないラベルを示します。ユーザーエージェントは、他のエンコーディングやラベルをサポートしてはなりません。
各エンコーディングについて、そのASCII小文字化した名前が、そのラベルの1つとなります。
著者はUTF-8 エンコーディングを使用し、その識別には(ASCII大文字小文字を区別しない)"utf-8
"ラベルを使用しなければなりません。
新しいプロトコルやフォーマット、ならびに新しいコンテキストで展開される既存のフォーマットは、UTF-8 エンコーディングのみを使用しなければなりません。これらのプロトコルやフォーマットがエンコーディングの名前やラベルを公開する必要がある場合、それは"utf-8
"として公開しなければなりません。
エンコーディングを取得する には、文字列labelが与えられたとき、次の手順を実行します:
-
labelの先頭および末尾からASCII空白をすべて除去する。
-
もしlabelが下表のいずれかのラベルとASCII大文字小文字を区別しない一致をする場合は、対応するエンコーディングを返す。そうでなければ失敗を返す。
これは、エンコーディングへのラベルのマッピングとして、 Unicode技術標準#22の1.4節が定めるものよりも基本的かつ制限の強いアルゴリズムです。これは現行コンテンツとの互換性のために必要です。
名前 | ラベル |
---|---|
エンコーディング | |
UTF-8 | "unicode-1-1-utf-8 "
|
"unicode11utf8 "
| |
"unicode20utf8 "
| |
"utf-8 "
| |
"utf8 "
| |
"x-unicode20utf8 "
| |
レガシー単一バイトエンコーディング | |
IBM866 | "866 "
|
"cp866 "
| |
"csibm866 "
| |
"ibm866 "
| |
ISO-8859-2 | "csisolatin2 "
|
"iso-8859-2 "
| |
"iso-ir-101 "
| |
"iso8859-2 "
| |
"iso88592 "
| |
"iso_8859-2 "
| |
"iso_8859-2:1987 "
| |
"l2 "
| |
"latin2 "
| |
ISO-8859-3 | "csisolatin3 "
|
"iso-8859-3 "
| |
"iso-ir-109 "
| |
"iso8859-3 "
| |
"iso88593 "
| |
"iso_8859-3 "
| |
"iso_8859-3:1988 "
| |
"l3 "
| |
"latin3 "
| |
ISO-8859-4 | "csisolatin4 "
|
"iso-8859-4 "
| |
"iso-ir-110 "
| |
"iso8859-4 "
| |
"iso88594 "
| |
"iso_8859-4 "
| |
"iso_8859-4:1988 "
| |
"l4 "
| |
"latin4 "
| |
ISO-8859-5 | "csisolatincyrillic "
|
"cyrillic "
| |
"iso-8859-5 "
| |
"iso-ir-144 "
| |
"iso8859-5 "
| |
"iso88595 "
| |
"iso_8859-5 "
| |
"iso_8859-5:1988 "
| |
ISO-8859-6 | "arabic "
|
"asmo-708 "
| |
"csiso88596e "
| |
"csiso88596i "
| |
"csisolatinarabic "
| |
"ecma-114 "
| |
"iso-8859-6 "
| |
"iso-8859-6-e "
| |
"iso-8859-6-i "
| |
"iso-ir-127 "
| |
"iso8859-6 "
| |
"iso88596 "
| |
"iso_8859-6 "
| |
"iso_8859-6:1987 "
| |
ISO-8859-7 | "csisolatingreek "
|
"ecma-118 "
| |
"elot_928 "
| |
"greek "
| |
"greek8 "
| |
"iso-8859-7 "
| |
"iso-ir-126 "
| |
"iso8859-7 "
| |
"iso88597 "
| |
"iso_8859-7 "
| |
"iso_8859-7:1987 "
| |
"sun_eu_greek "
| |
ISO-8859-8 | "csiso88598e "
|
"csisolatinhebrew "
| |
"hebrew "
| |
"iso-8859-8 "
| |
"iso-8859-8-e "
| |
"iso-ir-138 "
| |
"iso8859-8 "
| |
"iso88598 "
| |
"iso_8859-8 "
| |
"iso_8859-8:1988 "
| |
"visual "
| |
ISO-8859-8-I | "csiso88598i "
|
"iso-8859-8-i "
| |
"logical "
| |
ISO-8859-10 | "csisolatin6 "
|
"iso-8859-10 "
| |
"iso-ir-157 "
| |
"iso8859-10 "
| |
"iso885910 "
| |
"l6 "
| |
"latin6 "
| |
ISO-8859-13 | "iso-8859-13 "
|
"iso8859-13 "
| |
"iso885913 "
| |
ISO-8859-14 | "iso-8859-14 "
|
"iso8859-14 "
| |
"iso885914 "
| |
ISO-8859-15 | "csisolatin9 "
|
"iso-8859-15 "
| |
"iso8859-15 "
| |
"iso885915 "
| |
"iso_8859-15 "
| |
"l9 "
| |
ISO-8859-16 | "iso-8859-16 "
|
KOI8-R | "cskoi8r "
|
"koi "
| |
"koi8 "
| |
"koi8-r "
| |
"koi8_r "
| |
KOI8-U | "koi8-ru "
|
"koi8-u "
| |
macintosh | "csmacintosh "
|
"mac "
| |
"macintosh "
| |
"x-mac-roman "
| |
windows-874 | "dos-874 "
|
"iso-8859-11 "
| |
"iso8859-11 "
| |
"iso885911 "
| |
"tis-620 "
| |
"windows-874 "
| |
windows-1250 | "cp1250 "
|
"windows-1250 "
| |
"x-cp1250 "
| |
windows-1251 | "cp1251 "
|
"windows-1251 "
| |
"x-cp1251 "
| |
windows-1252
歴史的な「Latin1」や「ASCII」概念との関係については、下記を参照してください。 | "ansi_x3.4-1968 "
|
"ascii "
| |
"cp1252 "
| |
"cp819 "
| |
"csisolatin1 "
| |
"ibm819 "
| |
"iso-8859-1 "
| |
"iso-ir-100 "
| |
"iso8859-1 "
| |
"iso88591 "
| |
"iso_8859-1 "
| |
"iso_8859-1:1987 "
| |
"l1 "
| |
"latin1 "
| |
"us-ascii "
| |
"windows-1252 "
| |
"x-cp1252 "
| |
windows-1253 | "cp1253 "
|
"windows-1253 "
| |
"x-cp1253 "
| |
windows-1254 | "cp1254 "
|
"csisolatin5 "
| |
"iso-8859-9 "
| |
"iso-ir-148 "
| |
"iso8859-9 "
| |
"iso88599 "
| |
"iso_8859-9 "
| |
"iso_8859-9:1989 "
| |
"l5 "
| |
"latin5 "
| |
"windows-1254 "
| |
"x-cp1254 "
| |
windows-1255 | "cp1255 "
|
"windows-1255 "
| |
"x-cp1255 "
| |
windows-1256 | "cp1256 "
|
"windows-1256 "
| |
"x-cp1256 "
| |
windows-1257 | "cp1257 "
|
"windows-1257 "
| |
"x-cp1257 "
| |
windows-1258 | "cp1258 "
|
"windows-1258 "
| |
"x-cp1258 "
| |
x-mac-cyrillic | "x-mac-cyrillic "
|
"x-mac-ukrainian "
| |
レガシー多バイト中国語(簡体字)エンコーディング | |
GBK | "chinese "
|
"csgb2312 "
| |
"csiso58gb231280 "
| |
"gb2312 "
| |
"gb_2312 "
| |
"gb_2312-80 "
| |
"gbk "
| |
"iso-ir-58 "
| |
"x-gbk "
| |
gb18030 | "gb18030 "
|
レガシー多バイト中国語(繁体字)エンコーディング | |
Big5 | "big5 "
|
"big5-hkscs "
| |
"cn-big5 "
| |
"csbig5 "
| |
"x-x-big5 "
| |
レガシー多バイト日本語エンコーディング | |
EUC-JP | "cseucpkdfmtjapanese "
|
"euc-jp "
| |
"x-euc-jp "
| |
ISO-2022-JP | "csiso2022jp "
|
"iso-2022-jp "
| |
Shift_JIS | "csshiftjis "
|
"ms932 "
| |
"ms_kanji "
| |
"shift-jis "
| |
"shift_jis "
| |
"sjis "
| |
"windows-31j "
| |
"x-sjis "
| |
レガシー多バイト韓国語エンコーディング | |
EUC-KR | "cseuckr "
|
"csksc56011987 "
| |
"euc-kr "
| |
"iso-ir-149 "
| |
"korean "
| |
"ks_c_5601-1987 "
| |
"ks_c_5601-1989 "
| |
"ksc5601 "
| |
"ksc_5601 "
| |
"windows-949 "
| |
レガシーその他のエンコーディング | |
replacement | "csiso2022kr "
|
"hz-gb-2312 "
| |
"iso-2022-cn "
| |
"iso-2022-cn-ext "
| |
"iso-2022-kr "
| |
"replacement "
| |
UTF-16BE | "unicodefffe "
|
"utf-16be "
| |
UTF-16LE | "csunicode "
|
"iso-10646-ucs-2 "
| |
"ucs-2 "
| |
"unicode "
| |
"unicodefeff "
| |
"utf-16 "
| |
"utf-16le "
| |
x-user-defined | "x-user-defined "
|
すべてのエンコーディングとそのラベルは、非規範的リソースであるencodings.jsonとしても利用できます。
サポートされるエンコーディングのセットは、標準の策定開始時点で主要なブラウザーエンジンがサポートしていたセットの共通部分を主な根拠としつつ、正当な用途がほとんどないが攻撃に使われるおそれのあるエンコーディングを除外する形で構成されています。既存Webコンテンツでの利用状況に関する逸話的証拠を踏まえると、一部のエンコーディングの収録には疑問が残ります。つまり、ブラウザーで広くサポートされてきた一方で、Webコンテンツ側で広く使われているかは不明です。しかし、ブラウザーで広くサポートされていた、またはISO 8859シリーズの一部である単一バイトエンコーディングについて、積極的に除去する試みは行われていません。特に、既存コンテンツ対応としてIBM866、macintosh、x-mac-cyrillic、ISO-8859-3、ISO-8859-10、ISO-8859-14、ISO-8859-16の必要性は疑問視されているものの、これらを除去する計画はありません。
windows-1252 エンコーディングには、"latin1
"、"iso-8859-1
"、"ascii
"など、開発者を混乱させてきた様々なラベルがあります。Web上、および本仕様を実装してWeb互換を目指すソフトウェアにおいて、これらはすべて同義語です:"latin1
"や"ascii
"は単なるwindows-1252のラベルであり、本仕様に準拠したソフトウェアは、たとえば「Latin1」や「ASCII」デコードを要求されたとき、そのバイト0x80をU+20AC
(€)としてデコードします。
この仕様に従わないソフトウェアは、常に同じ動作をするとは限りません。その根本は、元々Latin1(ISO/IEC 8859-1)を規定した文書に、0x00~0x1Fや0x7F~0x9Fの範囲に関するマッピングがなかったこと、またASCII(ISO/IEC 646など)を規定した文書にも0x80~0xFFの範囲のマッピングがなかったことにあります。そのため、Latin1やASCIIエンコーディングを使うよう指示された場合、ソフトウェアごとにそれらバイトの符号位置割当が異なる場合があります。Webブラウザーやブラウザー互換ソフトウェアは、それらのバイトをwindows-1252に従って割り当てており、これは両者の上位互換であり、この選択が本仕様で規定されました。他のソフトウェアでは、エラーとしたり、等値復号など他のマッピングを使ったりします。[ISO8859-1] [ISO646]
このため、実装者や開発者は「Latin1」や「ASCII」といったAPIを公開するライブラリーを利用する際には注意が必要です。元仕様で未定義だったバイトに対して異なる動作を選択している場合、本仕様と一致しない結果になる可能性があります。
4.3. 出力エンコーディング
出力エンコーディングを取得するには、エンコーディングencodingが与えられたとき、次の手順を実行します:
-
もしencodingがreplacementまたはUTF-16BE/LEなら、UTF-8を返す。
-
encodingを返す。
出力エンコーディングを取得するアルゴリズムは、URL解析やHTMLフォーム送信のように、まさにこの処理が必要となる場面で役立ちます。
5. 索引
ほとんどのレガシーエンコーディングは、索引を使用します。索引とは、各エントリーがポインタと対応する符号位置から成る順序付きリストです。索引内ではポインタは一意で、符号位置は重複してもかまいません。
効率的な実装では、1つのエンコーディングごとに、デコーダー用とエンコーダー用の2つの索引を持つことが多いでしょう。
索引内のポインタと対応する符号位置を探すには、リソースの内容をU+000A LFで分割したものをlinesとする。その後、空文字列またはU+0023(#)で始まるlines内の各項目を削除する。各linesの項目をU+0009 TABで分割し、最初のサブ項目がポインタ(10進数)、2番目が対応する符号位置(16進数)となる。他のサブ項目は関係ありません。
変更を示すため、索引にはIdentifierとDateが含まれます。Identifierが変更されていれば、その索引も変更されています。
index内のpointerに対応する索引符号位置は、index内のpointerに対応する符号位置、またはpointerがindexにない場合はnullです。
index内のcodePointに対応する索引ポインタは、index内でcodePointに対応する最初のポインタ、またはcodePointがindexにない場合はnullです。
索引(gb18030範囲索引およびISO-2022-JPカタカナ索引を除く)ごとに、非規範的な可視化があります。jis0208索引には、別のShift_JIS可視化もあります。また、gb18030範囲索引やISO-2022-JPカタカナ索引以外の各索引について、基本多言語面カバレッジの可視化もあります。
可視化の凡例は以下の通りです:
- 未マップ
- UTF-8で2バイト
- UTF-8で2バイト、符号位置が直前のポインタの符号位置に連続
- UTF-8で3バイト(PUA以外)
- UTF-8で3バイト(PUA以外)、符号位置が直前のポインタの符号位置に連続
- 私用領域
- 私用領域、符号位置が直前のポインタの符号位置に連続
- UTF-8で4バイト
- UTF-8で4バイト、符号位置が直前のポインタの符号位置に連続
- 重複符号位置(以前の索引ですでにマップされている)
- CJK互換漢字
- CJK統合漢字拡張A
以下は、この仕様で定義されている索引(単一バイト索引を除く。そちらは別表)の一覧です。
索引 | 備考 | |||
---|---|---|---|---|
Big5索引 | index-big5.txt | Big5索引可視化 | Big5索引BMPカバレッジ | これはBig5標準と香港補助文字セットおよびその他の一般的な拡張を組み合わせたものに一致します。 |
EUC-KR索引 | index-euc-kr.txt | EUC-KR索引可視化 | EUC-KR索引BMPカバレッジ | これはKS X 1001標準およびUnified Hangul Code(通称Windowsコードページ949)に一致します。Unicodeのハングル音節ブロック全体をカバーします。ビジュアライゼーションで左上がポインタ9026のブロックはUnicode順です。それ以外のハングル音節もUnicode順です。 |
gb18030索引 | index-gb18030.txt | gb18030索引可視化 | gb18030索引BMPカバレッジ | 二バイトでエンコードされる符号位置について、GB18030-2022標準に一致します(ただし0xA3 0xA0は、実コンテンツとの互換性のためU+3000(IDEOGRAPHIC SPACE)へマップ)。この索引はUnicodeのCJK統合漢字ブロック全体をカバーします。そのブロックでビジュアライゼーション上U+3000より上または左にあるエントリはUnicode順です。 |
gb18030範囲索引 | index-gb18030-ranges.txt | この索引は他と動作が異なります。すべての符号位置を列挙すると100万件を超えるため、207範囲と単純な範囲チェックで表現しています。したがって、GB18030-2000標準の4バイト符号位置とは厳密に一致しません。GB18030-2005改訂の変更は、下記のgb18030範囲索引符号位置およびgb18030範囲索引ポインタアルゴリズムで扱います。2022年改訂の変更は、私用領域へのバイト列割当がこれ以上増えないよう別の方法で扱い、該当する私用領域符号位置はgb18030エンコーダーがサイドテーブルで直接処理します。 | ||
jis0208索引 | index-jis0208.txt | jis0208索引可視化, Shift_JIS可視化 | jis0208索引BMPカバレッジ | JIS X 0208標準にIBMとNECの旧独自拡張を含みます。 |
jis0212索引 | index-jis0212.txt | jis0212索引可視化 | jis0212索引BMPカバレッジ | JIS X 0212標準です。他で広くサポートされていないため、EUC-JPデコーダーでのみ使われます。 |
ISO-2022-JPカタカナ索引 | index-iso-2022-jp-katakana.txt | これはUnicode正規化形式KCに基づき、半角カタカナを全角カタカナにマップします。ただしU+FF9E(゙)、U+FF9F(゚)はU+309B(゛)、U+309C(゜)へ(U+3099, U+309Aではなく)マップされます。ISO-2022-JPエンコーダーでのみ使われます。[UNICODE] |
gb18030範囲索引符号位置(pointer用)は次の手順で求まります:
-
pointerが39419より大きくかつ189000未満、または1237575より大きい場合はnullを返す。
-
pointerが7457の場合、符号位置U+E7C7を返す。
-
offsetを、gb18030範囲索引でpointer以下の最後のポインタとし、codePointOffsetをその対応符号位置とする。
-
codePointOffset + pointer − offsetという値の符号位置を返す。
gb18030範囲索引ポインタ(codePoint用)は次の手順で求まります:
-
codePointがU+E7C7の場合、ポインタ7457を返す。
-
offsetを、gb18030範囲索引でcodePoint以下の最後の符号位置とし、pointerOffsetをその対応ポインタとする。
-
pointerOffset + codePoint − offsetという値のポインタを返す。
Shift_JIS索引ポインタ(codePoint用)は次の手順で求まります:
Big5索引ポインタ(codePoint用)は次の手順で求まります:
すべての索引は、非規範的リソースindexes.jsonとしても利用できます。(gb18030範囲索引は、範囲を表現するため少し異なるフォーマットです。)
6. 標準へのフック
以下で定義されるアルゴリズム(UTF-8デコード、BOMなしUTF-8デコード、 BOMなしエラー時失敗UTF-8デコード、UTF-8エンコード)は他の標準が利用することを意図しています。
デコードには、新しいフォーマットではUTF-8デコードを使用してください。フォーマットやプロトコル内の識別子やバイト列には、BOMなしUTF-8デコードやBOMなしエラー時失敗UTF-8デコードを使用してください。
エンコードには、UTF-8エンコードを使用してください。
標準は、UTF-8エンコード(およびレガシーエンコード)に渡す入力I/Oキューが実質的にスカラー値のI/Oキュー(すなわちサロゲートを含まない)であることを保証してください。
これらのフック(およびデコードやエンコード)は、入力I/Oキューがすべて消費されるまでブロックされます。ストリームに出力トークンがプッシュされるたびにそれを利用したい場合は、呼び出し元は空の出力I/Oキューでフックを呼び、並列でそれを読み取ってください。なおBOMなしエラー時失敗UTF-8デコードの利用時は注意が必要で、デコード中にエラーが発生した場合、出力I/Oキューに キュー終端要素がプッシュされなくなります。
UTF-8デコードを、バイトのI/OキューioQueueに対して(オプションでスカラー値のI/Oキューoutput(デフォルトは« »)付き)行うには、次の手順を実行します:
BOMなしUTF-8デコードを、バイトのI/OキューioQueueに対して(オプションでスカラー値のI/Oキューoutput(デフォルトは« »)付き)行うには、次の手順を実行します:
BOMなしエラー時失敗UTF-8デコードを、バイトのI/OキューioQueueに対して(オプションでスカラー値のI/Oキューoutput(デフォルトは« »)付き)行うには、次の手順を実行します:
UTF-8エンコードを、スカラー値のI/OキューioQueueに対して(オプションでバイトのI/Oキューoutput(デフォルトは« »)付き)行うには、エンコードでioQueueをエンコーディングUTF-8およびoutputでエンコードした結果を返します。
6.1. レガシー標準フック
標準では、互換性のため以外は、デコード、BOM判別、エンコードを使うことは強く推奨されません。これらレガシーフックが必要な標準は、(ラベルをエンコーディングに変換するための)エンコーディングを取得するや、(エンコーディングをエンコードに渡すのに適した別のエンコーディングに変換するための)出力エンコーディングを取得するも必要になるでしょう。
URLパーセントエンコーディングという極めてニッチなケースでは、カスタムエンコーダーのエラー処理が必要です。その場合はエンコーダー取得や失敗時エンコードアルゴリズムを使用してください。その他のアルゴリズムは直接使用しないでください。
デコードを、バイトのI/OキューioQueue、フォールバックエンコーディングencoding、(オプションでスカラー値のI/Oキューoutput(デフォルトは« »)付き)で行うには、次の手順を実行します:
BOM判別をバイトのI/OキューioQueueに対して行うには、次の手順を実行します:
-
BOMを、ピークでioQueueから3バイト取得し、バイト列に変換したものとする。
-
下表の各行について、最初の行から順に、BOMが最初の列に示すバイトで始まる場合、その行2列目のエンコーディングを返す。そうでなければnullを返す。
バイト順マーク エンコーディング 0xEF 0xBB 0xBF UTF-8 0xFE 0xFF UTF-16BE 0xFF 0xFE UTF-16LE
このフックは、デコードがバイト順マーク発見時に呼び出し元に伝達できない問題の回避策です。このフックはデコードの前に呼び出され、バイト順マークが見つかった場合は対応するエンコーディングを、そうでなければnullを返します。
エンコードを、スカラー値のI/OキューioQueue、エンコーディングencoding、(オプションでバイトのI/Oキューoutput(デフォルトは« »)付き)で行うには、次の手順を実行します:
これはHTMLフォーム用のレガシーフックです。UTF-8エンコードを重ねても安全で、エラーが発生することはありません。[HTML]
エンコーダー取得をエンコーディングencodingencodingから行うには:
-
アサート:encodingがreplacementまたはUTF-16BE/LEでないこと。
-
encodingのエンコーダーインスタンスを返す。
失敗時エンコードを、スカラー値のI/OキューioQueue、encoderインスタンスencoder、バイトのI/Oキューoutputで行うには、次の手順を実行します:
-
potentialErrorを、キューを処理する(encoder、ioQueue、output、"
fatal
")の結果とする。 -
nullを返す。
これはURLパーセントエンコーディング用のレガシーフックです。呼び出し元はエンコーダーインスタンスを保持する必要があります。ISO-2022-JPエンコーダーは、エラーを返す際に2つの異なる状態を取りうるためです。また、エラーをエンコードするバイトを出力する場合、それらは0x00~0x7Fの範囲(0x0E, 0x0F, 0x1B, 0x5C, 0x7Eを除く)でなければなりません。[URL]
特に、エラー時にISO-2022-JPエンコーダーがRoman状態にある場合、0x5C(\)は出力できません。これはU+005C(\)としてデコードされないためです。このため、失敗時エンコードを意図せず利用するアプリケーションは、U+005C(\)をリプレース構文(例:\u2603
)に使うJavaScriptやCSSのようなリプレース構文と組み合わせてISO-2022-JPエンコーダーを利用しないようにするか、リプレース構文をエンコーダーに通すようにしてください(URLパーセントエンコーディングとは対照的に)。
戻り値は、エンコードできなかった符号位置を表す数値、またはエラーがなければnullです。非nullの場合、呼び出し元は同じエンコーダーインスタンスと新しいoutput I/Oキューで再度呼び出す必要があります。
7. API
この節ではWeb IDLの用語を使用します。ブラウザーのユーザーエージェントは本APIをサポートしなければなりません。JavaScript実装も本APIをサポートすることが推奨されます。他のユーザーエージェントやプログラミング言語は、自身の要件に合ったAPIを使用することが推奨されますが、それが本APIと同一である必要はありません。[WEBIDL]
次の例は、TextEncoder
オブジェクトを使い、文字列配列をArrayBuffer
へエンコードするものです。結果はUint8Array
で、最初に文字列数(Uint32Array
として)が入り、それに続き1つ目の文字列の長さ(Uint32Array
として)、そのUTF-8エンコード文字列データ、2つ目の長さ(Uint32Array
として)、その文字列データ、…という順になります。
function encodeArrayOfStrings( strings) {
var encoder, encoded, len, bytes, view, offset;
encoder = new TextEncoder();
encoded = [];
len = Uint32Array. BYTES_PER_ELEMENT;
for ( var i = 0 ; i < strings. length; i++ ) {
len += Uint32Array. BYTES_PER_ELEMENT;
encoded[ i] = encoder. encode( strings[ i]);
len += encoded[ i]. byteLength;
}
bytes = new Uint8Array( len);
view = new DataView( bytes. buffer);
offset = 0 ;
view. setUint32( offset, strings. length);
offset += Uint32Array. BYTES_PER_ELEMENT;
for ( var i = 0 ; i < encoded. length; i += 1 ) {
len = encoded[ i]. byteLength;
view. setUint32( offset, len);
offset += Uint32Array. BYTES_PER_ELEMENT;
bytes. set( encoded[ i], offset);
offset += len;
}
return bytes. buffer;
}
次の例は、上記の形式でエンコードされたデータ(またはUTF-8以外の等価なアルゴリズムでエンコードされたデータ)を、ArrayBuffer
から配列の文字列にデコードします。
function decodeArrayOfStrings( buffer, encoding) {
var decoder, view, offset, num_strings, strings, len;
decoder = new TextDecoder( encoding);
view = new DataView( buffer);
offset = 0 ;
strings = [];
num_strings = view. getUint32( offset);
offset += Uint32Array. BYTES_PER_ELEMENT;
for ( var i = 0 ; i < num_strings; i++ ) {
len = view. getUint32( offset);
offset += Uint32Array. BYTES_PER_ELEMENT;
strings[ i] = decoder. decode(
new DataView( view. buffer, offset, len));
offset += len;
}
return strings;
}
7.1.
インターフェースミックスイン TextDecoderCommon
interface mixin {
TextDecoderCommon readonly attribute DOMString encoding ;readonly attribute boolean fatal ;readonly attribute boolean ignoreBOM ; };
TextDecoderCommon
インターフェースミックスインは、TextDecoder
およびTextDecoderStream
オブジェクト間で共有される共通のgetterを定義します。これらのオブジェクトは次のものを持ちます:
- encoding
- エンコーディング。
- decoder
- デコーダーインスタンス。
- I/Oキュー
- バイトのI/Oキュー。
- BOM無視
- 真偽値。初期値はfalse。
- BOM検出済み
- 真偽値。初期値はfalse。
- エラーモード
- エラーモード。初期値は"
replacement
"。
I/Oキューのシリアライズアルゴリズムは、TextDecoderCommon
decoderとスカラー値のI/Oキュー ioQueueが与えられたとき、次の手順を実行します:
-
outputを空文字列とする。
-
trueの間、以下を繰り返す:
このアルゴリズムは、BOMの扱いに関しては他のプラットフォームで使われているデコードアルゴリズムと意図的に異なり、API利用者により多くの制御を提供します。
7.2. インターフェース TextDecoder
dictionary {
TextDecoderOptions boolean =
fatal false ;boolean =
ignoreBOM false ; };dictionary {
TextDecodeOptions boolean =
stream false ; }; [Exposed=*]interface {
TextDecoder constructor (optional DOMString = "utf-8",
label optional TextDecoderOptions = {});
options USVString decode (optional AllowSharedBufferSource ,
input optional TextDecodeOptions = {}); };
options TextDecoder includes TextDecoderCommon ;
TextDecoder
オブジェクトには、do not flush(ブール値、初期値はfalse)が関連付けられています。
decoder = new TextDecoder([label = "utf-8" [, options]])
-
新しい
TextDecoder
オブジェクトを返します。labelがラベルでない場合、またはreplacementのラベルの場合、RangeError例外を投げます。
decoder . encoding
decoder . fatal
-
エラーモードが"
fatal
"の場合はtrue、それ以外はfalseを返します。 decoder . ignoreBOM
-
BOM無視の値を返します。
decoder . decode([input [, options]])
-
encodingのデコーダーを実行した結果を返します。optionsの
stream
がtrueでこのメソッドを0回以上呼び出し、その後optionsのstream
がfalse(または省略)で1回だけ呼び出すことで、断片化された入力を処理できます。optionsのstream
がfalse(または省略)かつinputも省略の場合は、両引数とも省略するのが最も明確です。var string= "" , decoder= new TextDecoder( encoding), buffer; while ( buffer= next_chunk()) { string+= decoder. decode( buffer, { stream: true }); } string+= decoder. decode(); // end-of-queue
new TextDecoder(label, options)
コンストラクタの手順は以下の通りです:
-
encodingをlabelからエンコーディングを取得するで得る。
-
encodingが失敗またはreplacementの場合、RangeError例外を投げる。
decode(input, options)
メソッドの手順は以下の通りです:
-
thisのdo not flushがfalseなら、thisのdecoderをencodingのデコーダーの新しいインスタンスに、thisのI/OキューをバイトのI/Oキュー « キュー終端 » に、thisのBOM検出済みをfalseに設定する。
-
thisのdo not flushをoptions["
stream
"]に設定する。 -
もしinputが与えられた場合、プッシュでinputのコピーをthisのI/Oキューに追加する。
実装ではこのコピーを避ける戦略が強く推奨されます。その場合もinputの変更が
decode()
の将来の呼び出しに影響しないように配慮してください。 -
trueの間、以下を繰り返す:
-
もしitemがキュー終端かつthisのdo not flushがtrueなら、I/Oキューのシリアライズをthisとoutputで実行した結果を返す。
ストリーミング動作は、キュー終端をここで処理せず、thisのdo not flushをfalseにしないことで実現します。これにより、次回呼び出し時にもthisのdecoderが新たにセットされず、状態が保持されます。
-
それ以外の場合:
7.3.
インターフェースミックスイン TextEncoderCommon
interface mixin {
TextEncoderCommon readonly attribute DOMString encoding ; };
TextEncoderCommon
インターフェースミックスインは、
TextEncoder
およびTextEncoderStream
オブジェクト間で共有される共通getterを定義します。
encoding
getterの手順は"utf-8
"を返すことです。
7.4. インターフェース TextEncoder
dictionary {
TextEncoderEncodeIntoResult unsigned long long ;
read unsigned long long ; }; [Exposed=*]
written interface {
TextEncoder constructor (); [NewObject ]Uint8Array encode (optional USVString = "");
input TextEncoderEncodeIntoResult encodeInto (USVString , [
source AllowShared ]Uint8Array ); };
destination TextEncoder includes TextEncoderCommon ;
TextEncoder
オブジェクトにはlabel引数はありません。これはUTF-8のみをサポートするためです。また、どのエンコーダーもスカラー値のバッファリングを必要としないため、stream
オプションもありません。
encoder = new TextEncoder()
-
新しい
TextEncoder
オブジェクトを返します。 encoder . encoding
-
"
utf-8
"を返します。 encoder . encode([input = ""])
encoder . encodeInto(source, destination)
-
sourceに対してUTF-8エンコーダーを実行し、その結果をdestinationに格納し、進捗状況を表すオブジェクトとして返します。そのオブジェクトでは
read
がsourceの変換されたコード単位数、written
がdestinationに書き込まれたバイト数です。
new TextEncoder()
コンストラクタの手順は何もしないことです。
encode(input)
メソッドの手順は以下の通りです:
-
trueの間、以下を繰り返す:
-
itemを読み取りでinputから取得する。
-
resultを、要素を処理する(item、UTF-8エンコーダーインスタンス、input、output、"
fatal
")の結果とする。 -
UTF-8エンコーダーはerrorを返しません。
-
もしresultが終端なら、Uint8Arrayオブジェクトの作成(outputとthisの関連レルムを与える)を返す。
-
encodeInto(source, destination)
メソッドの手順は以下の通りです:
-
readを0とする。
-
writtenを0とする。
-
encoderをUTF-8エンコーダーのインスタンスとする。
-
unusedをスカラー値のI/Oキュー « キュー終端 » とする。
この後で呼び出すハンドラアルゴリズムはこの引数を必要としますが、UTF-8エンコーダーでは使用しません。
-
trueの間、以下を繰り返す:
-
itemを読み取りでsourceから取得する。
-
resultをencoderのハンドラ(unusedとitemを与える)で実行した結果とする。
-
それ以外の場合:
-
もしdestinationのバイト長−writtenがresultのバイト数以上なら:
-
もしitemがU+FFFFより大きければ、readに2を加える。
-
それ以外はreadに1を加える。
-
resultのバイトをdestinationにstartingOffsetをwrittenにして書き込む。
上記
SharedArrayBuffer
オブジェクトの警告を参照してください。 -
writtenにresultのバイト数を加える。
-
-
そうでなければbreak。
-
-
encodeInto()メソッドは、既存のArrayBuffer
オブジェクトに文字列をエンコードするために使用できます。以下の詳細は読者への課題としますが、このメソッドの利用法の一例を示します:
function convertString( buffer, input, callback) {
let bufferSize = 256 ,
bufferStart = malloc( buffer, bufferSize),
writeOffset = 0 ,
readOffset = 0 ;
while ( true ) {
const view = new Uint8Array( buffer, bufferStart + writeOffset, bufferSize - writeOffset),
{ read, written} = cachedEncoder. encodeInto( input. substring( readOffset), view);
readOffset += read;
writeOffset += written;
if ( readOffset === input. length) {
callback( bufferStart, writeOffset);
free( buffer, bufferStart);
return ;
}
bufferSize *= 2 ;
bufferStart = realloc( buffer, bufferStart, bufferSize);
}
}
7.5.
インターフェース TextDecoderStream
[Exposed=*]interface {
TextDecoderStream constructor (optional DOMString = "utf-8",
label optional TextDecoderOptions = {}); };
options TextDecoderStream includes TextDecoderCommon ;TextDecoderStream includes GenericTransformStream ;
decoder = new TextDecoderStream([label = "utf-8" [, options]])
-
新しい
TextDecoderStream
オブジェクトを返します。もしlabelがラベルでないか、またはラベルであっても replacementのラベルである場合、RangeError例外をスローします。
decoder . encoding
decoder . fatal
-
エラーモードが"
fatal
"の場合true、それ以外はfalseを返します。 decoder . ignoreBOM
-
ignore BOMの値を返します。
decoder . readable
-
リーダブルストリームを返します。このストリームのチャンクは encodingのデコーダーを
writable
に書き込まれたチャンクに対して実行した結果の文字列です。 decoder . writable
-
ライト可能ストリームを返します。このストリームは
AllowSharedBufferSource
チャンクを受け付け、 それらをencodingのデコーダーに通してreadable
で利用可能にします。通常これは
pipeThrough()
メソッドをReadableStream
ソースに対して使って利用します。var decoder= new TextDecoderStream( encoding); byteReadable. pipeThrough( decoder) . pipeTo( textWritable); もしエラーモードが"
fatal
"で encodingのデコーダーがerrorを返した場合、readable
およびwritable
の両方がTypeError
でエラー状態になります。
new TextDecoderStream(label, options)
コンストラクタの手順は以下の通りです:
-
encodingをlabelからエンコーディングを取得するで得る。
-
encodingが失敗またはreplacementの場合、RangeError例外を投げる。
-
thisのdecoderをencodingのデコーダーの新しいインスタンスに、thisのI/Oキューを新しいI/Oキューに設定する。
-
transformAlgorithmを、chunk引数を受け取り、チャンクのデコードとエンキューアルゴリズムをthisとchunkで実行するアルゴリズムとする。
-
flushAlgorithmを、引数なしでフラッシュとエンキューアルゴリズムをthisで実行するアルゴリズムとする。
-
transformStreamを
TransformStream
の新しいインスタンスとする。 -
transformStreamをtransformAlgorithmをtransformAlgorithm、flushAlgorithmをflushAlgorithmにしてセットアップする。
チャンクのデコードとエンキューアルゴリズムは、TextDecoderStream
オブジェクトdecoderとchunkが与えられたとき、次の手順を実行します:
-
bufferSourceをchunkを
AllowSharedBufferSource
に変換した結果とする。 -
プッシュでbufferSourceのコピーをdecoderのI/Oキューに追加する。
上記
SharedArrayBuffer
オブジェクトの警告を参照してください。 -
trueの間、以下を繰り返す:
フラッシュとエンキューアルゴリズムは、入力ReadableStream
オブジェクトからデータの終端を処理します。TextDecoderStream
オブジェクトdecoderが与えられたとき、次の手順を実行します:
-
trueの間、以下を繰り返す:
7.6.
インターフェース TextEncoderStream
[Exposed=*]interface {
TextEncoderStream constructor (); };TextEncoderStream includes TextEncoderCommon ;TextEncoderStream includes GenericTransformStream ;
TextEncoderStream
オブジェクトには次のものが関連付けられています:
- エンコーダー
- エンコーダーインスタンス。
- リーディングサロゲート
- nullまたはリーディングサロゲート。初期値はnull。
TextEncoderStream
オブジェクトにはlabel引数はありません。これはUTF-8のみをサポートするためです。
encoder = new TextEncoderStream()
-
新しい
TextEncoderStream
オブジェクトを返します。 encoder . encoding
-
"
utf-8
"を返します。 encoder . readable
-
リーダブルストリームを返します。このストリームのチャンクは
Uint8Array
であり、 UTF-8のエンコーダーをwritable
に書き込まれたチャンクに対して実行した結果です。 encoder . writable
-
ライト可能ストリームを返します。このストリームは文字列チャンクを受け取り、 UTF-8のエンコーダーを通して
readable
で利用可能にします。これは通常、
pipeThrough()
メソッドをReadableStream
ソースに対して利用します。textReadable
. pipeThrough( new TextEncoderStream()) . pipeTo( byteWritable);
new TextEncoderStream()
コンストラクタの手順は以下の通りです:
-
thisのエンコーダーをUTF-8エンコーダーのインスタンスに設定する。
-
transformAlgorithmをchunk引数を受け取り、チャンクのエンコードとエンキューアルゴリズムをthisとchunkで実行するアルゴリズムとする。
-
flushAlgorithmを、エンコードとフラッシュアルゴリズムをthisで実行するアルゴリズムとする。
-
transformStreamを
TransformStream
の新しいインスタンスとする。 -
transformStreamをtransformAlgorithmをtransformAlgorithm、flushAlgorithmをflushAlgorithmにしてセットアップする。
チャンクのエンコードとエンキューアルゴリズムは、TextEncoderStream
オブジェクトencoderとchunkが与えられたとき、次の手順を実行します:
-
inputをコード単位のI/Oキューに変換する。
DOMString
やコード単位のI/Oキューを使うことで、チャンク間で分割されたサロゲートペアも適切なスカラー値に再構成できます。その他の動作はUSVString
と同じです。特に、孤立したサロゲートはU+FFFD(�)に置き換えられます。 -
trueの間、以下を繰り返す:
コード単位からスカラー値への変換アルゴリズムは、TextEncoderStream
オブジェクトencoder、コード単位item、コード単位のI/Oキューinputが与えられたとき、次の手順を実行します:
-
もしencoderのリーディングサロゲートがnullでなければ:
-
leadingSurrogateをencoderのリーディングサロゲートとする。
-
encoderのリーディングサロゲートをnullに設定する。
-
もしitemがトレーリングサロゲートなら、サロゲートからスカラー値(leadingSurrogate、item)を返す。
-
itemをinputに復元する。
-
U+FFFD(�)を返す。
-
-
もしitemがリーディングサロゲートなら、encoderのリーディングサロゲートをitemに設定し、continueを返す。
-
もしitemがトレーリングサロゲートなら、U+FFFD(�)を返す。
-
itemを返す。
これはInfra標準の「文字列をスカラー値文字列に変換する」アルゴリズムと等価ですが、文字列間でサロゲートペアが分割されても対応できるようになっています。[INFRA]
エンコードとフラッシュアルゴリズムは、TextEncoderStream
オブジェクトencoderが与えられたとき、次の手順を実行します:
-
もしencoderのリーディングサロゲートがnullでなければ:
-
chunkをUint8Arrayオブジェクトの作成(« 0xEF, 0xBF, 0xBD » と encoderの関連レルムを与える)で得る。
これはUTF-8バイトでのU+FFFD(�)です。
-
8. エンコーディング
8.1. UTF-8
8.1.1. UTF-8デコーダー
バイト順マークはラベルよりも優先されます。これは実際のコンテンツでより正確であることが判明しているためです。したがって、これはUTF-8デコーダーアルゴリズムの一部ではなく、デコードやUTF-8デコードアルゴリズムで扱われます。
- UTF-8コードポイント
- UTF-8受信済みバイト数
- UTF-8必要バイト数
- UTF-8受信済みバイト数
- いずれも数値。初期値は0。
- UTF-8下限値
- バイト。初期値は0x80。
- UTF-8上限値
- バイト。初期値は0xBF。
UTF-8のデコーダーのハンドラはioQueueおよびbyteを受け取り、次の手順を実行します:
-
もしbyteがキュー終端であり、UTF-8必要バイト数が0でなければ、 UTF-8必要バイト数を0に設定し、errorを返す。
-
UTF-8必要バイト数が0なら、byteに基づき:
- 0x00 〜 0x7F
-
byte値のコードポイントを返す。
- 0xC2 〜 0xDF
-
-
UTF-8必要バイト数を1に設定する。
-
UTF-8コードポイントにbyte & 0x1Fを設定する。
byteの下位5ビット。
-
- 0xE0 〜 0xEF
-
-
もしbyteが0xE0なら、UTF-8下限値を0xA0に設定する。
-
もしbyteが0xEDなら、UTF-8上限値を0x9Fに設定する。
-
UTF-8必要バイト数を2に設定する。
-
UTF-8コードポイントにbyte & 0xFを設定する。
byteの下位4ビット。
-
- 0xF0 〜 0xF4
-
-
もしbyteが0xF0なら、UTF-8下限値を0x90に設定する。
-
もしbyteが0xF4なら、UTF-8上限値を0x8Fに設定する。
-
UTF-8必要バイト数を3に設定する。
-
UTF-8コードポイントにbyte & 0x7を設定する。
byteの下位3ビット。
-
- それ以外
-
errorを返す。
continueを返す。
-
もしbyteがUTF-8下限値〜UTF-8上限値の範囲外なら:
-
UTF-8コードポイント、UTF-8必要バイト数、UTF-8受信済みバイト数を0にし、UTF-8下限値を0x80、UTF-8上限値を0xBFに設定する。
-
byteをioQueueに復元する。
-
errorを返す。
-
-
UTF-8コードポイントを(UTF-8コードポイント << 6) | (byte & 0x3F)に設定する。
UTF-8コードポイントの既存ビット列を6ビット左シフトし、下位6ビットをbyteの下位6ビットで埋める。
-
UTF-8受信済みバイト数を1増やす。
-
UTF-8受信済みバイト数がUTF-8必要バイト数と等しくなければ、continueを返す。
-
codePointをUTF-8コードポイントとする。
-
値がcodePointのコードポイントを返す。
上記UTF-8デコーダーの制約は、Unicode標準の「U+FFFDのベストプラクティス」に一致します。エンコーディング標準では他の挙動は許可されません(同じ結果を得る他のアルゴリズムは可、むしろ推奨)。[UNICODE]
8.1.2. UTF-8エンコーダー
UTF-8のエンコーダーのハンドラはunusedおよびcodePointを受け取り、次の手順を実行します:
-
もしcodePointがASCIIコードポイントなら、その値のバイトを返す。
-
codePointの範囲に応じてcountとoffsetを設定する:
- U+0080〜U+07FF(含む)
- 1および0xC0
- U+0800〜U+FFFF(含む)
- 2および0xE0
- U+10000〜U+10FFFF(含む)
- 3および0xF0
-
bytesを、最初のバイトが(codePoint >> (6 × count)) + offsetであるバイト列とする。
-
countが0より大きい間:
-
tempをcodePoint >> (6 × (count − 1))とする。
-
bytesに0x80 | (temp & 0x3F)を追加する。
-
countを1減らす。
-
-
バイト列bytesを順に返す。
このアルゴリズムはUnicode標準に記載のものと同じ結果になります。ここでは完全性のため記載しています。[UNICODE]
9. レガシー単一バイトエンコーディング
各バイトが単一の符号位置か何も表さないエンコーディングは、単一バイトエンコーディングです。 単一バイトエンコーディングは共通の デコーダーおよびエンコーダーを持ちます。単一バイト索引は、単一バイトデコーダーおよび 単一バイトエンコーダーで参照され、以下の表で定義されており、使用する単一バイトエンコーディングに依存します。ほとんどの単一バイトエンコーディングは、固有の索引を持ちます(2つを除く)。
ISO-8859-8 と ISO-8859-8-I は 別々のエンコーディング名です。なぜならISO-8859-8はレイアウト方向に影響するためです。また、かつてはISO-8859-6と"ISO-8859-6-I"についても同様でしたが、現在はそうではありません。
9.1. 単一バイトデコーダー
単一バイトエンコーディングのデコーダーのハンドラはunusedとbyteを受け取り、次の手順を実行します:
9.2. 単一バイトエンコーダー
単一バイトエンコーディングのエンコーダーのハンドラはunusedとcodePointを受け取り、次の手順を実行します:
-
もしcodePointがASCIIコードポイントなら、その値のバイトを返す。
-
もしpointerがnullなら、error(codePoint付き)を返す。
-
pointer+0x80の値のバイトを返す。
10. レガシー多バイト中国語(簡体字)エンコーディング
10.1. GBK
10.1.1. GBKデコーダー
10.1.2. GBKエンコーダー
GBKのエンコーダーはgb18030のエンコーダーで、is GBKをtrueに設定したものです。
GBKをgb18030と完全に同一視しないのは、レガシーサーバーやGBKのエンコーダーで生成されたコンテンツの他の利用者を壊すリスクを減らすための慎重な対応です。
10.2. gb18030
10.2.1. gb18030デコーダー
- gb18030 first
- gb18030 second
- gb18030 third
- gb18030 second
- いずれもバイト。初期値は0x00。
gb18030のデコーダーのハンドラはioQueueとbyteを受け取り、次の手順を実行します:
-
もしbyteがキュー終端であり、gb18030 first、gb18030 second、gb18030 thirdがすべて0x00なら、終端を返す。
-
もしbyteがキュー終端であり、gb18030 first、gb18030 second、またはgb18030 thirdが0x00でないなら、それらを0x00に設定し、errorを返す。
-
もしgb18030 thirdが0x00でなければ:
-
もしbyteが0x30〜0x39の範囲外なら:
-
« gb18030 second, gb18030 third, byte » をioQueueに復元する。
-
gb18030 first、gb18030 second、gb18030 thirdを0x00に設定する。
-
errorを返す。
-
-
codePointを次の式でindex gb18030 ranges code pointとする:((gb18030 first − 0x81) × (10 × 126 × 10)) + ((gb18030 second − 0x30) × (10 × 126)) + ((gb18030 third − 0x81) × 10) + byte − 0x30。
-
gb18030 first、gb18030 second、gb18030 thirdを0x00に設定する。
-
もしcodePointがnullなら、errorを返す。
-
値がcodePointのコードポイントを返す。
-
-
もしgb18030 secondが0x00でなければ:
-
もしbyteが0x81〜0xFEの範囲なら、gb18030 thirdにbyteを設定し、continueを返す。
-
« gb18030 second, byte » をioQueueに復元し、gb18030 firstおよびgb18030 secondを0x00に設定し、errorを返す。
-
-
もしgb18030 firstが0x00でなければ:
-
もしbyteが0x30〜0x39の範囲なら、gb18030 secondにbyteを設定し、continueを返す。
-
leadingをgb18030 firstとする。
-
gb18030 firstを0x00に設定する。
-
pointerをnullに設定する。
-
offsetをbyteが0x7F未満なら0x40、そうでなければ0x41とする。
-
もしbyteが0x40〜0x7E、または0x80〜0xFEの範囲なら、pointerを(leading − 0x81) × 190 + (byte − offset)に設定する。
-
codePointをpointerがnullならnull、そうでなければindex code point(pointer、index gb18030)とする。
-
もしcodePointがnullでなければ、その値のコードポイントを返す。
-
errorを返す。
-
-
もしbyteがASCIIバイトなら、その値のコードポイントを返す。
-
もしbyteが0x80なら、コードポイントU+20AC (€)を返す。
-
もしbyteが0x81〜0xFEの範囲なら、gb18030 firstにbyteを設定し、continueを返す。
-
errorを返す。
10.2.2. gb18030エンコーダー
gb18030のエンコーダーには、is GBK(真偽値、初期値はfalse)が関連付けられています。
gb18030のエンコーダーのハンドラはunusedとcodePointを受け取り、次の手順を実行します:
-
もしcodePointがASCIIコードポイントなら、その値のバイトを返す。
-
もしcodePointがU+E5E5なら、error(codePoint付き)を返す。
index gb18030は0xA3 0xA0をU+E5E5ではなくU+3000(全角空白)にマッピングします。これは現行コンテンツとの互換性のためであり、往復変換はできません。
-
もしis GBKがtrueかつcodePointがU+20AC(€)なら、バイト0x80を返す。
-
もし下表の1列目がcodePointである行があれば、2列目の2バイトを返す:
コードポイント バイト U+E78D 0xA6 0xD9 U+E78E 0xA6 0xDA U+E78F 0xA6 0xDB U+E790 0xA6 0xDC U+E791 0xA6 0xDD U+E792 0xA6 0xDE U+E793 0xA6 0xDF U+E794 0xA6 0xEC U+E795 0xA6 0xED U+E796 0xA6 0xF3 U+E81E 0xFE 0x59 U+E826 0xFE 0x61 U+E82B 0xFE 0x66 U+E82C 0xFE 0x67 U+E832 0xFE 0x6D U+E843 0xFE 0x7E U+E854 0xFE 0x90 U+E864 0xFE 0xA0 この非対称なエンコーダーテーブルはGB18030-2005標準との互換性維持のためです。詳細はindex gb18030 rangesの説明も参照。
-
pointerをindex pointer(codePoint、index gb18030)とする。
-
もしpointerがnullでなければ:
-
leadingをpointer/190+0x81とする。
-
trailingをpointer%190とする。
-
offsetをtrailing<0x3Fなら0x40、そうでなければ0x41とする。
-
2バイト:leading、trailing+offsetを返す。
-
-
pointerをindex gb18030 ranges pointer(codePoint)に設定する。
-
byte1をpointer/(10×126×10)とする。
-
pointerをpointer%(10×126×10)に設定する。
-
byte2をpointer/(10×126)とする。
-
pointerをpointer%(10×126)に設定する。
-
byte3をpointer/10とする。
-
byte4をpointer%10とする。
-
4バイト:byte1+0x81、byte2+0x30、byte3+0x81、byte4+0x30を返す。
11. レガシー多バイト中国語(繁体字)エンコーディング
11.1. Big5
11.1.1. Big5デコーダー
Big5のデコーダーにはBig5リードバイトが関連付けられており、バイトで初期値は0x00です。
Big5のデコーダーのハンドラはioQueueとbyteを受け取り、次の手順を実行します:
-
もしbyteがキュー終端かつBig5リードバイトが0x00でなければ、Big5リードバイトを0x00にしてerrorを返す。
-
もしbyteがキュー終端かつBig5リードバイトが0x00なら、終端を返す。
-
もしBig5リードバイトが0x00でなければ:
-
leadingをBig5リードバイトとする。
-
Big5リードバイトを0x00にする。
-
pointerをnullとする。
-
offsetをbyteが0x7F未満なら0x40、そうでなければ0x62とする。
-
もしbyteが0x40〜0x7Eまたは0xA1〜0xFEの範囲なら、pointerを(leading−0x81)×157 + (byte−offset)とする。
-
下表の1列目がpointerである行があれば、その2列目の2つのコードポイントを返す(3列目は無視):
ポインタ コードポイント 備考 1133 U+00CA U+0304 Ê̄ (LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND MACRON) 1135 U+00CA U+030C Ê̌ (LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND CARON) 1164 U+00EA U+0304 ê̄ (LATIN SMALL LETTER E WITH CIRCUMFLEX AND MACRON) 1166 U+00EA U+030C ê̌ (LATIN SMALL LETTER E WITH CIRCUMFLEX AND CARON) 索引(indexes)は単一コードポイントに限定されるため、これらのポインタはこの表で扱われます。
-
codePointをpointerがnullならnull、それ以外はindex code point(pointer、index Big5)とする。
-
codePointがnullでなければ、その値のコードポイントを返す。
-
errorを返す。
-
-
もしbyteがASCIIバイトなら、その値のコードポイントを返す。
-
もしbyteが0x81〜0xFEの範囲なら、Big5リードバイトにbyteを設定し、continueを返す。
-
errorを返す。
11.1.2. Big5エンコーダー
Big5のエンコーダーのハンドラはunusedとcodePointを受け取り、次の手順を実行します:
-
もしcodePointがASCIIコードポイントなら、その値のバイトを返す。
-
pointerをcodePointのindex Big5 pointerとする。
-
もしpointerがnullなら、error(codePoint付き)を返す。
-
leadingをpointer/157+0x81とする。
-
trailingをpointer%157とする。
-
offsetをtrailing<0x3Fなら0x40、そうでなければ0x62とする。
-
2バイト:leading、trailing+offsetを返す。
12. レガシー多バイト日本語エンコーディング
12.1. EUC-JP
12.1.1. EUC-JPデコーダー
- EUC-JP jis0212
- 真偽値(初期値false)。
- EUC-JPリードバイト
- バイト(初期値0x00)。
EUC-JPのデコーダーのハンドラはioQueueとbyteを受け取り、次の手順を実行します:
-
もしbyteがキュー終端かつEUC-JPリードバイトが0x00でなければ、EUC-JPリードバイトを0x00にしてerrorを返す。
-
もしbyteがキュー終端かつEUC-JPリードバイトが0x00なら、終端を返す。
-
もしEUC-JPリードバイトが0x8Eかつbyteが0xA1〜0xDFの範囲なら、EUC-JPリードバイトを0x00にして、値0xFF61−0xA1+byteのコードポイントを返す。
-
もしEUC-JPリードバイトが0x8Fかつbyteが0xA1〜0xFEの範囲なら、EUC-JP jis0212をtrueに、EUC-JPリードバイトをbyteにし、continueを返す。
-
もしEUC-JPリードバイトが0x00でなければ:
-
leadingをEUC-JPリードバイトとする。
-
EUC-JPリードバイトを0x00にする。
-
codePointをnullとする。
-
もしleadingおよびbyteがともに0xA1〜0xFEの範囲なら、codePointを、EUC-JP jis0212がfalseなら(leading−0xA1)×94+byte−0xA1をindex jis0208で、trueなら同じ計算式でindex jis0212での値とする。
-
EUC-JP jis0212をfalseにする。
-
もしcodePointがnullでなければ、その値のコードポイントを返す。
-
errorを返す。
-
-
もしbyteがASCIIバイトなら、その値のコードポイントを返す。
-
もしbyteが0x8E、0x8F、または0xA1〜0xFEの範囲なら、EUC-JPリードバイトにbyteを設定し、continueを返す。
-
errorを返す。
12.1.2. EUC-JPエンコーダー
EUC-JPのエンコーダーのハンドラはunusedとcodePointを受け取り、次の手順を実行します:
-
もしcodePointがASCIIコードポイントなら、その値のバイトを返す。
-
もしcodePointがU+00A5(¥)なら、バイト0x5Cを返す。
-
もしcodePointがU+203E(‾)なら、バイト0x7Eを返す。
-
もしcodePointがU+FF61(。)〜U+FF9F(゚)の範囲なら、2バイト0x8EとcodePoint−0xFF61+0xA1を返す。
-
もしcodePointがU+2212(−)なら、U+FF0D(-)に設定する。
-
pointerをcodePointのindex pointer(index jis0208)とする。
pointerがnullでなければ、index jis0208の性質とindex pointer操作により8836未満となる。
-
もしpointerがnullなら、error(codePoint付き)を返す。
-
leadingをpointer/94+0xA1とする。
-
trailingをpointer%94+0xA1とする。
-
2バイト:leading、trailingを返す。
12.2. ISO-2022-JP
12.2.1. ISO-2022-JPデコーダー
ISO-2022-JPのデコーダーには次が関連付けられています:
- ISO-2022-JPデコーダー状態
- 状態(初期値はASCII)。
- ISO-2022-JPデコーダー出力状態
- 状態(初期値もASCII)。
- ISO-2022-JPリードバイト
- バイト(初期値0x00)。
- ISO-2022-JP出力
- 真偽値(初期値false)。
ISO-2022-JPのデコーダーのハンドラはioQueueとbyteを受け取り、ISO-2022-JPデコーダー状態によって分岐しながら次の手順を実行します:
- ASCII
-
byteに基づく:
- 0x1B
-
ISO-2022-JPデコーダー状態を エスケープ開始に設定し、continueを返す。
- 0x00〜0x7F(ただし0x0E, 0x0F, 0x1Bを除く)
-
ISO-2022-JP出力をfalseにし、値がbyteのコードポイントを返す。
- キュー終端
-
終端を返す。
- それ以外
-
ISO-2022-JP出力をfalseにし、errorを返す。
- Roman
-
byteに基づく:
- 0x1B
-
ISO-2022-JPデコーダー状態を エスケープ開始に設定し、continueを返す。
- 0x5C
-
ISO-2022-JP出力をfalseにし、コードポイントU+00A5(¥)を返す。
- 0x7E
-
ISO-2022-JP出力をfalseにし、コードポイントU+203E(‾)を返す。
- 0x00〜0x7F(ただし0x0E, 0x0F, 0x1B, 0x5C, 0x7Eを除く)
-
ISO-2022-JP出力をfalseにし、値がbyteのコードポイントを返す。
- キュー終端
-
終端を返す。
- それ以外
-
ISO-2022-JP出力をfalseにし、errorを返す。
- カタカナ
-
byteに基づく:
- 0x1B
-
ISO-2022-JPデコーダー状態を エスケープ開始に設定し、continueを返す。
- 0x21〜0x5F
-
ISO-2022-JP出力をfalseにし、値0xFF61−0x21+byteのコードポイントを返す。
- キュー終端
-
終端を返す。
- それ以外
-
ISO-2022-JP出力をfalseにし、errorを返す。
- リードバイト
-
byteに基づく:
- 0x1B
-
ISO-2022-JPデコーダー状態を エスケープ開始に設定し、continueを返す。
- 0x21〜0x7E
-
ISO-2022-JP出力をfalseにし、ISO-2022-JPリードバイトをbyteに、 ISO-2022-JPデコーダー状態をトレイルバイトに設定し、continueを返す。
- キュー終端
-
終端を返す。
- それ以外
-
ISO-2022-JP出力をfalseにし、errorを返す。
- トレイルバイト
-
byteに基づく:
- 0x1B
-
ISO-2022-JPデコーダー状態を エスケープ開始に設定し、errorを返す。
- 0x21〜0x7E
-
-
ISO-2022-JPデコーダー状態を リードバイトに設定する。
-
pointerを(ISO-2022-JPリードバイト−0x21)×94+byte−0x21とする。
-
codePointをindex code point(pointer、index jis0208)とする。
-
もしcodePointがnullなら、errorを返す。
-
値がcodePointのコードポイントを返す。
-
- キュー終端
-
ISO-2022-JPデコーダー状態を リードバイトに設定し、errorを返す。
- それ以外
-
ISO-2022-JPデコーダー状態を リードバイトに設定し、errorを返す。
- エスケープ開始
-
-
もしbyteが0x24または0x28なら、ISO-2022-JPリードバイトをbyteに、ISO-2022-JPデコーダー状態を エスケープにし、continueを返す。
-
ISO-2022-JP出力をfalse、ISO-2022-JPデコーダー状態を ISO-2022-JPデコーダー出力状態にし、errorを返す。
-
- エスケープ
-
-
leadingをISO-2022-JPリードバイトとし、ISO-2022-JPリードバイトを0x00にする。
-
stateをnullとする。
-
もしleadingが0x28かつbyteが0x42なら、stateをASCIIにする。
-
もしleadingが0x28かつbyteが0x4Aなら、stateをRomanにする。
-
もしleadingが0x28かつbyteが0x49なら、stateをカタカナにする。
-
もしleadingが0x24かつbyteが0x40または0x42なら、stateをリードバイトにする。
-
もしstateがnullでなければ:
-
ISO-2022-JPデコーダー状態と ISO-2022-JPデコーダー出力状態をstateに設定する。
-
outputをISO-2022-JP出力の値とする。
-
ISO-2022-JP出力をtrueにする。
-
-
もしbyteがキュー終端なら、leadingをioQueueに復元する。そうでなければ、« leading, byte »をioQueueに復元する。
-
ISO-2022-JP出力をfalse、ISO-2022-JPデコーダー状態をISO-2022-JPデコーダー出力状態にし、errorを返す。
-
12.2.2. ISO-2022-JPエンコーダー
ISO-2022-JPエンコーダーは、複数回の出力を連結したものを対応するデコーダーで実行した場合にerrorになることがある唯一のエンコーダーです。
U+00A5(¥)をエンコードすると0x1B 0x28 0x4A 0x5C 0x1B 0x28 0x42となります。これを2回繰り返して連結し、デコードするとU+00A5 U+FFFD U+00A5になります。
ISO-2022-JPのエンコーダーには ISO-2022-JPエンコーダー状態があり、 ASCII、 Roman、 jis0208のいずれかで、初期値は ASCIIです。
ISO-2022-JPのエンコーダーのハンドラはioQueueとcodePointを受け取り、次の手順を実行します:
-
もしcodePointがキュー終端で、ISO-2022-JPエンコーダー状態が ASCIIでなければ、ISO-2022-JPエンコーダー状態を ASCIIにし、3バイト0x1B 0x28 0x42を返す。
-
もしcodePointがキュー終端かつISO-2022-JPエンコーダー状態が ASCIIなら、終端を返す。
-
もしISO-2022-JPエンコーダー状態が ASCIIまたは RomanかつcodePointがU+000E,U+000F,U+001Bなら、U+FFFD(�)でerrorを返す。
攻撃防止のため、codePoint自身ではなくU+FFFD(�)を返します。
-
もしISO-2022-JPエンコーダー状態が ASCIIかつcodePointがASCIIコードポイントなら、その値のバイトを返す。
-
もしISO-2022-JPエンコーダー状態が RomanかつcodePointがASCIIコードポイント(U+005C(\)とU+007E(~)を除く)またはU+00A5(¥)またはU+203E(‾)なら:
-
もしcodePointがASCIIコードポイントなら、その値のバイトを返す。
-
もしcodePointがU+00A5(¥)なら、バイト0x5Cを返す。
-
もしcodePointがU+203E(‾)なら、バイト0x7Eを返す。
-
-
もしcodePointがASCIIコードポイントで、ISO-2022-JPエンコーダー状態が ASCIIでないなら、codePointをioQueueに復元し、ISO-2022-JPエンコーダー状態を ASCIIにし、3バイト0x1B 0x28 0x42を返す。
-
もしcodePointがU+00A5(¥)またはU+203E(‾)で、ISO-2022-JPエンコーダー状態が Romanでないなら、codePointをioQueueに復元し、ISO-2022-JPエンコーダー状態を Romanにし、3バイト0x1B 0x28 0x4Aを返す。
-
もしcodePointがU+2212(−)なら、U+FF0D(-)に設定する。
-
もしcodePointがU+FF61(。)〜U+FF9F(゚)の範囲なら、codePoint−0xFF61をindex ISO-2022-JP katakanaでindex code pointとする。
-
pointerをcodePointのindex pointer(index jis0208)とする。
pointerがnullでなければ、index jis0208とindex pointer操作の性質から8836未満となる。
-
もしpointerがnullなら:
-
もしISO-2022-JPエンコーダー状態が jis0208なら、codePointをioQueueに復元し、ISO-2022-JPエンコーダー状態を ASCIIにし、3バイト0x1B 0x28 0x42を返す。
-
error(codePoint付き)を返す。
-
-
もしISO-2022-JPエンコーダー状態が jis0208でないなら、codePointをioQueueに復元し、ISO-2022-JPエンコーダー状態を jis0208にし、3バイト0x1B 0x24 0x42を返す。
-
leadingをpointer/94+0x21とする。
-
trailingをpointer%94+0x21とする。
-
2バイト:leading、trailingを返す。
12.3. Shift_JIS
12.3.1. Shift_JISデコーダー
Shift_JISのデコーダーには Shift_JISリードバイト (バイト、初期値0x00)が関連付けられています。
Shift_JISのデコーダーのハンドラはioQueueと byteを受け取り、次の手順を実行します:
-
もしbyteがキュー終端かつShift_JISリードバイトが0x00でなければ、Shift_JISリードバイトを0x00にしてerrorを返す。
-
もしbyteがキュー終端かつShift_JISリードバイトが0x00なら、終端を返す。
-
もしShift_JISリードバイトが0x00でなければ:
-
leadingをShift_JISリードバイトとする。
-
Shift_JISリードバイトを0x00にする。
-
pointerをnullとする。
-
offsetをbyteが0x7F未満なら0x40、そうでなければ0x41とする。
-
leadingOffsetをleadingが0xA0未満なら0x81、そうでなければ0xC1とする。
-
もしbyteが0x40〜0x7Eまたは0x80〜0xFCの範囲なら、pointerを(leading−leadingOffset)×188+byte−offsetとする。
-
もしpointerが8836〜10715の範囲なら、値0xE000−8836+pointerのコードポイントを返す。
これはWindows由来のEUDCの互換的レガシーです。
-
codePointをpointerがnullならnull、そうでなければindex code point(pointer、index jis0208)とする。
-
もしcodePointがnullでなければ、その値のコードポイントを返す。
-
errorを返す。
-
-
もしbyteがASCIIバイトまたは0x80なら、その値のコードポイントを返す。
-
もしbyteが0xA1〜0xDFの範囲なら、値0xFF61−0xA1+byteのコードポイントを返す。
-
もしbyteが0x81〜0x9Fまたは0xE0〜0xFCの範囲なら、Shift_JISリードバイトにbyteを設定し、continueを返す。
-
errorを返す。
12.3.2. Shift_JISエンコーダー
Shift_JISのエンコーダーのハンドラはunusedと codePointを受け取り、次の手順を実行します:
-
もしcodePointがASCIIコードポイントまたはU+0080なら、その値のバイトを返す。
-
もしcodePointがU+00A5(¥)なら、バイト0x5Cを返す。
-
もしcodePointがU+203E(‾)なら、バイト0x7Eを返す。
-
もしcodePointがU+FF61(。)〜U+FF9F(゚)の範囲なら、値codePoint−0xFF61+0xA1のバイトを返す。
-
もしcodePointがU+2212(−)なら、U+FF0D(-)に設定する。
-
pointerをcodePointのindex Shift_JIS pointerとする。
-
もしpointerがnullなら、error(codePoint付き)を返す。
-
leadingをpointer/188とする。
-
leadingOffsetをleadingが0x1F未満なら0x81、そうでなければ0xC1とする。
-
trailingをpointer%188とする。
-
offsetをtrailingが0x3F未満なら0x40、そうでなければ0x41とする。
-
2バイト:leading+leadingOffset、trailing+offsetを返す。
13. レガシー多バイト韓国語エンコーディング
13.1. EUC-KR
13.1.1. EUC-KRデコーダー
EUC-KRのデコーダーにはEUC-KRリードバイト (バイト、初期値0x00)が関連付けられています。
EUC-KRのデコーダーのハンドラはioQueueと byteを受け取り、次の手順を実行します:
-
もしbyteがキュー終端かつEUC-KRリードバイトが0x00でなければ、EUC-KRリードバイトを0x00にしてerrorを返す。
-
もしbyteがキュー終端かつEUC-KRリードバイトが0x00なら、終端を返す。
-
もしEUC-KRリードバイトが0x00でなければ:
-
leadingをEUC-KRリードバイトとする。
-
EUC-KRリードバイトを0x00にする。
-
pointerをnullとする。
-
もしbyteが0x41〜0xFEの範囲なら、pointerを(leading−0x81)×190+(byte−0x41)とする。
-
codePointをpointerがnullならnull、そうでなければindex code point(pointer、index EUC-KR)とする。
-
もしcodePointがnullでなければ、その値のコードポイントを返す。
-
errorを返す。
-
-
もしbyteがASCIIバイトなら、その値のコードポイントを返す。
-
もしbyteが0x81〜0xFEの範囲なら、EUC-KRリードバイトにbyteを設定し、continueを返す。
-
errorを返す。
13.1.2. EUC-KRエンコーダー
EUC-KRのエンコーダーのハンドラはunusedと codePointを受け取り、次の手順を実行します:
-
もしcodePointがASCIIコードポイントなら、その値のバイトを返す。
-
pointerをcodePointのindex pointer(index EUC-KR)とする。
-
もしpointerがnullなら、error(codePoint付き)を返す。
-
leadingをpointer/190+0x81とする。
-
trailingをpointer%190+0x41とする。
-
2バイト:leading、trailingを返す。
14. レガシーその他エンコーディング
14.1. replacement
replacement エンコーディングは、サーバーとクライアントでサポートされるエンコーディングの不一致を悪用する攻撃を防ぐために存在します。
14.1.1. replacementデコーダー
replacementのデコーダーにはreplacement error returned(真偽値、初期値false)が関連付けられています。
replacementのデコーダーのハンドラはunusedと byteを受け取り、次の手順を実行します:
-
もしreplacement error returnedがfalseなら、それをtrueに設定し、errorを返す。
-
終端を返す。
14.2. UTF-16BE/LE共通インフラストラクチャ
UTF-16BE/LEはUTF-16BEまたはUTF-16LEです。
14.2.1. 共通UTF-16デコーダー
バイトオーダーマークはラベルよりも優先されます。これは実際のコンテンツでより正確であることが確認されているためです。したがってこれは共通UTF-16デコーダーアルゴリズムの一部ではなく、decodeアルゴリズムの一部です。
共通UTF-16デコーダーには次が関連付けられています:
- UTF-16リードバイト
- nullまたはバイト(初期値null)。
- UTF-16リードサロゲート
- nullまたはリードサロゲート(初期値null)。
- is UTF-16BEデコーダー
- 真偽値(初期値false)。
共通UTF-16デコーダーのハンドラはioQueueとbyteを受け取り、次の手順を実行します:
-
もしbyteがキュー終端かつUTF-16リードバイトまたはUTF-16リードサロゲートがnullでなければ、両方をnullにし、errorを返す。
-
もしbyteがキュー終端かつUTF-16リードバイトとUTF-16リードサロゲートがnullなら、終端を返す。
-
もしUTF-16リードバイトがnullなら、UTF-16リードバイトにbyteを設定し、continueを返す。
-
codeUnitを次の結果とする:
- is UTF-16BEデコーダーがtrue
-
(UTF-16リードバイト << 8) + byte。
- is UTF-16BEデコーダーがfalse
-
(byte << 8) + UTF-16リードバイト。
-
UTF-16リードバイトをnullにする。
-
もしUTF-16リードサロゲートがnullでなければ:
-
leadingSurrogateをUTF-16リードサロゲートとする。
-
UTF-16リードサロゲートをnullにする。
-
もしcodeUnitがトレイルサロゲートなら、surrogatesからスカラ値をleadingSurrogateとcodeUnitで返す。
-
byte1をcodeUnit>>8とする。
-
byte2をcodeUnit&0x00FFとする。
-
bytesを、is UTF-16BEデコーダーがtrueならbyte1とbyte2、そうでなければbyte2とbyte1の2バイトのリストとする。
-
-
もしcodeUnitがリードサロゲートなら、UTF-16リードサロゲートにcodeUnitを設定し、continueを返す。
-
コードポイントcodeUnitを返す。
14.3. UTF-16BE
14.3.1. UTF-16BEデコーダー
UTF-16BEのデコーダーは共通UTF-16デコーダーであり、is UTF-16BEデコーダーをtrueに設定します。
14.4. UTF-16LE
"utf-16
"は、現行コンテンツに対応するためUTF-16LEのラベルです。
14.4.1. UTF-16LEデコーダー
UTF-16LEのデコーダーは共通UTF-16デコーダーです。
14.5. x-user-defined
これは技術的には単一バイトエンコーディングですが、アルゴリズム的に実装できるため個別に定義されています。
14.5.1. x-user-definedデコーダー
x-user-definedのデコーダーのハンドラはunusedと byteを受け取り、次の手順を実行します:
14.5.2. x-user-definedエンコーダー
x-user-definedのエンコーダーのハンドラはunusedと codePointを受け取り、次の手順を実行します:
-
もしcodePointがASCIIコードポイントなら、その値のバイトを返す。
-
もしcodePointがU+F780〜U+F7FFの範囲なら、値codePoint−0xF780+0x80のバイトを返す。
-
error(codePoint付き)を返す。
15. ブラウザーUI
ブラウザーは、リソースのエンコーディングを上書きする機能を有効にしないことが推奨されます。もしこの機能が存在する場合でも、前述のセキュリティ上の問題から、UTF-16BE/LEを選択肢として提供すべきではありません。また、リソースがUTF-16BE/LEでデコードされた場合はこの機能自体を無効にするべきです。
実装上の考慮事項
この標準のエンコーディングのデコーダーは、I/Oキューや復元を任意にサポートする代わりに、以下のように実装できます:
-
現在のバイトを未読に戻す機能。
-
gb18030(ASCIIバイト)およびISO-2022-JP(0x24または0x28)のための1バイトバッファ。
gb18030でgb18030 thirdが0x00でない状態で不正なバイトに遭遇した場合、gb18030 secondを1バイトバッファに移し次に返されるようにし、gb18030 thirdを新たなgb18030 firstとし、1バイトバッファが返されて空になった後で0x00でないことを確認します。gb18030のfirstおよびthirdバイトの範囲が同じであるため、これは可能です。
ISO-2022-JPエンコーダーは追加状態としてISO-2022-JPエンコーダー状態が必要ですが、それ以外のこの標準のエンコーダーは追加の状態やバッファを必要としません。
謝辞
長年にわたりエンコーディングの相互運用性向上に貢献し、本標準の目標の推進に寄与してくださった多くの方々に感謝します。同様に、この標準を現行の形にするために多くの方々がご協力くださいました。
以下の方々に深く感謝します(敬称略): Adam Rice, Alan Chaney, Alexander Shtuchkin, Allen Wirfs-Brock, Andreu Botella, Aneesh Agrawal, Arkadiusz Michalski, Asmus Freytag, Ben Noordhuis, Bnaya Peretz, Boris Zbarsky, Bruno Haible, Cameron McCormack, Charles McCathieNeville, Christopher Foo, CodifierNL, David Carlisle, Domenic Denicola, Dominique Hazaël-Massieux, Doug Ewell, Erik van der Poel, 譚永鋒(Frank Yung-Fong Tang), Glenn Maynard, Gordon P. Hemsley, Henri Sivonen, Ian Hickson, J. King, James Graham, Jeffrey Yasskin, John Tamplin, Joshua Bell, 村井純(Jun Murai), 신정식(Jungshik Shin), Jxck, 강 성훈(Kang Seonghoon), 川幡太一(Kawabata Taichi), Ken Lunde, Ken Whistler, Kenneth Russell, 田村健人(Kent Tamura), Leif Halvard Silli, Luke Wagner, Maciej Hirsz, Makoto Kato, Mark Callow, Mark Crispin, Mark Davis, Martin Dürst, Masatoshi Kimura, Mattias Buelens, Ms2ger, Nigel Megitt, Nigel Tao, Norbert Lindenberg, Øistein E. Andersen, Peter Krefting, Philip Jägenstedt, Philip Taylor, Richard Ishida, Robbert Broersma, Robert Mustacchi, Ryan Dahl, Sam Sneddon, Shawn Steele, Simon Montagu, Simon Pieters, Simon Sapin, Stephen Checkoway, 寺田健(Takeshi Terada), Vyacheslav Matva, Wolf Lammen, 成瀬ゆい(Yui Naruse) ほか、皆さんのご支援に感謝します。
本標準はAnne van Kesteren(Apple, annevk@annevk.nl)が執筆しました。API章は当初、Joshua Bell(Google)によって執筆されました。
知的財産権
Copyright © WHATWG(Apple, Google, Mozilla, Microsoft)。本作業はCreative Commons Attribution 4.0 International Licenseの下でライセンスされています。一部がソースコードに組み込まれる場合、該当部分はBSD 3-Clause Licenseの下でライセンスされます。
これは現行標準です。特許審査版に関心がある方は、現行標準レビュー草稿をご覧ください。