有効な修正UTF-8ですか?


9

UTF-8は、Unicodeに対応していないコードを簡単に混同しないように、可変幅フォーマットでUnicodeコードポイントをエンコードする比較的単純な方法です。

UTF-8の概要

  • 通常、1から0x7Fの範囲のバイトが有効です。
  • ビットパターンの10XX XXXXあるバイトは継続バイトと見なされ、最下位6ビットがコードポイントの一部のエンコードに使用されます。これらは、先行するバイトで予期されていない限り、表示されないようにする必要があります。
  • パターンを持つバイトは、110X XXXXその後に1つの継続バイトを期待します
  • パターンのあるバイトは、1110 XXXXその後2つの継続バイトを予期します
  • パターンのあるバイトは、1111 0XXXその後に3つの継続バイトを期待します
  • 他のすべてのバイトは無効であり、UTF-8ストリームのどこにも表示されるべきではありません。5、6、および7バイトのクラスターは理論的には可能ですが、この課題では許可されません。

長すぎるエンコーディング

UTF-8では、コードポイントを最小バイト数で表す必要もあります。より少ないバイトで表現できるバイトシーケンスは無効です。変更されたUTF-8は、これに1つの例外を追加し、ヌル文字(U + 0000)をC0 80(16進表記)として表す必要があります)代わりに、ストリーム内のどこかにヌルバイトを表示できません。(これにより、ヌル終了文字列と互換性があります)

チャレンジ

バイトの文字列が与えられたときに、その文字列が有効なModified UTF-8を表すかどうかを判断し、有効な場合は真の値を、それ以外の場合は偽の値を返すプログラムを作成します。長すぎるエンコーディングとnullバイトをチェックする必要があることに注意してください(これはModified UTF-8であるため)。UTF-8値をデコードする必要はありません。

41 42 43  ==> yes (all bytes are in the 0-0x7F range)
00 01 02  ==> no (there is a null byte in the stream)
80 7F 41  ==> no (there is a continuation byte without a starter byte)
D9 84 10  ==> yes (the correct number of continuation bytes follow a starter byte)
F0 81 82 41  ==> no (there are not enough continuation bytes after F0)
EF 8A A7 91  ==> no (too many continuation bytes)
E1 E1 01  ==> no (starter byte where a continuation byte is expected)
E0 80 87  ==> no (overlong encoding)
41 C0 80  ==> yes (null byte encoded with the only legal overlong encoding)
F8 42 43  ==> no (invalid byte 'F8')

ルール

  • 標準のルールと抜け穴が適用されます
  • 符号なしバイト範囲(0〜255)のすべての値を読み取ることができる限り、入出力は任意の便利な形式にすることができます。
    • nullで終了する文字列ではなく、配列またはファイルを使用する必要がある場合があります。nullバイトを読み取ることができる必要があります。
  • 最短のコードが勝ちます!
  • ビルトインを使用してUTF-8をデコードしても、ここに記載されている要件に準拠しているとは限りません。それを回避し、特別なケースを作成する必要があるかもしれません。

編集:UTF-8をデコードするビルトインを使用しないことのボーナスを追加しました

EDIT2:Rustの回答のみが適格であり、定義するのが面倒なので、ボーナスを削除しました。


私はこれを待っていました。
アダム・

0xF8-0xFFの範囲の無効なバイトのテストケースを追加することができます。
アーノールド

2
「現代の」UTF-8仕様とは異なり、サロゲート(0xD800-0xDFFF)および0x10FFFFを超えるコードポイントが許可されているようです。これは明確にすべきであり、理想的には追加のテストケースが必要です。
nwellnhof

より多くの例が参考になります
明るく明るい

「0〜0x7Fの範囲のバイトは通常、有効です」というのは、1〜0x7fであるはずです。
明るいドン

回答:



1

APL(Dyalog Unicode)41 39 バイトSBCS

匿名の暗黙のプレフィックス関数。Unicode文字列を引数として取り、文字のコードポイントは入力バイトを表します。

{0::0⋄×⌊/'UTF-8'UCS2UCS⍵}'À\x80'RA

オンラインでお試しください!

'À\x80'⎕R⎕AR eplace C0 80S大文字とAの lphabet

{} 引数が次の無名関数を適用します

0:: エラーが発生した場合:

  0 ゼロを返す

 試してください:

  ⎕UCS⍵ 文字列をコードポイントに変換する

  'UTF-8'⎕UCS⍣2 UTF-8バイトとして解釈し、結果のテキストをバイトに変換します

  ⌊/ 最下位バイト(nullバイトが存在する場合はゼロ、存在しない場合は正、空の文字列の場合は「無限大」)

  × 符号(nullバイトが存在する場合はゼロ、存在しない場合は1)


これは真実に戻りませんD9 C0 80 84 C0 80 10か?
Neil

@ニールそれは確かにありません。削除C0 80すると無関係なバイトが有効な方法で隣接するようになるため、それは間違っていますか?編集:バイトコストなしでそれを修正するために更新されました。
アダム、

一部の文字が長方形またはボックスとして画面に表示されますが、それは正常ですか?LinuxのFirefoxでのIM。APLは非常に興味深い言語です。
明るく

@donbright私の経験では、APL文字は常に美しくなくても正しくレンダリングされるため、これらのボックスはおそらくクワッドであり、メインコードに4つあるはずです。このように表示されるはずです。そして、はい、APLは素晴らしいですし、とても楽しいです。あなたも簡単かつ迅速にそれを学ぶことができます— APL Orchardに参加してください
アダム

はい、彼らはクワッドです。ありがとう。
明るい明るい


0

-191バイト 313バイト

以下のコメントごとに、オリジナルは適切に機能しませんでした。新しく改良されたバージョン。Mighty Rustにはユーザーやライブラリが必要ないため、ライブラリは使用されません。このコードは、ステートマシンとのパターンマッチングを使用します。臆面もなくUTF8の仕様をオフにリッピングを経由して、それを発見した後、ジョンスキートによる参照や議論、我々はさびマッチパターンマッチブロックに文字のため、ほとんどの文字スペックをコピーすることができます。最後に、C0 80を有効と見なすためのBeefsterの特別なMutf8要件を追加します。非ゴルフ:

/* http://www.unicode.org/versions/corrigendum1.html
 Code Points        1st Byte    2nd Byte    3rd Byte    4th Byte
U+0000..U+007F      00..7F           
U+0080..U+07FF      C2..DF      80..BF           
U+0800..U+0FFF      E0          A0..BF      80..BF       
U+1000..U+FFFF      E1..EF      80..BF      80..BF       
U+10000..U+3FFFF    F0          90..BF      80..BF      80..BF
U+40000..U+FFFFF    F1..F3      80..BF      80..BF      80..BF
U+100000..U+10FFFF  F4          80..8F      80..BF      80..BF
*/

let m=|v:&Vec<u8>|v.iter().fold(0, |s, b| match (s, b) {
        (0, 0x01..=0x7F) => 0,
        (0, 0xc2..=0xdf) => 1,
        (0, 0xe0) => 2,
        (0, 0xe1..=0xef) => 4,
        (0, 0xf0) => 5,
        (0, 0xf1..=0xf3) => 6,
        (0, 0xf4) => 7,
        (1, 0x80..=0xbf) => 0,
        (2, 0xa0..=0xbf) => 1,
        (4, 0x80..=0xbf) => 1,
        (5, 0x90..=0xbf) => 4,
        (6, 0x80..=0xbf) => 4,
        (7, 0x80..=0x8f) => 4,
        (0, 0xc0) => 8, // beefster mutf8 null
        (8, 0x80) => 0, // beefster mutf8 null
        _ => -1,
    })==0;

さびた遊び場で試してみてください


手動で行うことの小道具ですが、あなたの長いチェックは正しくないと思います。
Beefster

あなたの挑戦、親愛なる、模倣に私を誘発し、私はもっと露骨に(あなたの質問を公開します男に応じ修正するには、私の番で、あなたに挑戦することで、この手紙を締結bit.ly/2T8tXhO
明るいドン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.