인코딩

현행 표준 — 마지막 갱신

참여하기:
GitHub whatwg/encoding (새 이슈, 오픈 이슈)
Matrix에서 채팅하기
커밋:
GitHub whatwg/encoding/commits
이 커밋 기준 스냅샷
@encodings
테스트:
web-platform-tests encoding/ (진행 중인 작업)
번역 (비공식):
日本語
简体中文
한국어

개요

인코딩 표준은 인코딩과 그에 대한 JavaScript API를 정의합니다.

1. 서문

UTF-8 인코딩은 유니코드(범용 문자 집합) 교환에 가장 적합한 인코딩입니다. 따라서, 새로운 프로토콜과 포맷뿐만 아니라, 새로운 맥락에서 사용되는 기존 포맷의 경우에도, 본 명세서는 UTF-8 인코딩을 요구(및 정의)합니다.

기타(레거시) 인코딩은 과거에 어느 정도 정의되어 있었습니다. 하지만, 사용자 에이전트마다 항상 동일하게 구현한 것은 아니었고, 동일한 레이블을 사용하지 않았으며, 인코딩의 미정의 영역이나 과거의 독자 영역 처리에서도 차이가 많았습니다. 본 명세서는 이러한 격차를 해결하여, 새로운 사용자 에이전트가 인코딩 구현을 리버스 엔지니어링할 필요가 없도록 하고, 기존 사용자 에이전트는 일치할 수 있도록 합니다.

특히, 본 명세서는 모든 인코딩, 바이트에서 스칼라 값으로(또는 그 반대) 변환하는 알고리즘, 그리고 표준 이름 및 식별 레이블을 정의합니다. 또한, 인코딩 알고리즘의 일부를 JavaScript에 노출하는 API도 정의합니다.

사용자 에이전트는 IANA 문자 집합 레지스트리에 명시된 레이블과도 많이 달라졌습니다. 레거시 인코딩이 더 이상 확산되지 않도록, 본 명세서는 위의 세부사항을 빠짐없이 기술하며, 따라서 별도의 레지스트리가 필요하지 않습니다. 특히, 본 명세서는 인코딩의 어떤 측면도 확장할 수 있는 메커니즘을 제공하지 않습니다.

2. 보안 배경

생산자와 소비자가 사용 중인 인코딩이나 특정 인코딩의 구현 방식에 합의하지 않을 때 인코딩 보안 문제가 발생할 수 있습니다. 예를 들어, 2011년에 보고된 공격에서는 Shift_JIS 선행 바이트 0x82가 JSON 리소스의 0x22 후행 바이트를 “마스킹”하는 데 사용되었습니다. 공격자가 일부 필드를 제어할 수 있었던 상황에서, 생산자는 이 조합이 불법 바이트 조합임에도 문제를 인식하지 못했습니다. 소비자는 이를 하나의 U+FFFD(�)로 디코딩했고, 이로 인해 전체 해석이 변경되었습니다. (U+0022(")는 중요한 구분자입니다.) 이제 여러 바이트로 스칼라 값을 표현하는 인코딩의 디코더는 불법 바이트 조합이 발생할 때, U+0000~U+007F 범위의 스칼라 값이 “마스킹”되지 않도록 해야 합니다. 위와 같은 시퀀스의 출력은 U+FFFD U+0022가 됩니다. (예외적으로, gb18030 디코더end-of-queue에서 최대 한 바이트까지 마스킹할 수 있습니다.)

선행 바이트 없이 ASCII 바이트ASCII 코드 포인트가 아닌 것으로 매핑하는 인코딩(“ASCII-비호환” 인코딩)은 이 문제가 더 심각합니다. ISO-2022-JPUTF-16BE/LE는 배포된 콘텐츠로 인해 부득이하게 지원되지만, 그 외 인코딩은 지원하지 않습니다. (다른 인코딩의 더 많은 레이블을 대체(replacement) 인코딩으로 매핑할 수 있는지에 대한 조사가 진행 중입니다. 그렇지 않을 경우 미지정 인코딩 폴백이 사용됩니다.) 예를 들면, 악의적으로 제작된 콘텐츠를 리소스에 주입한 뒤 인코딩을 덮어쓰도록 유도하여 스크립트 실행이 일어날 수 있습니다.

HTML 및 HTML의 폼 기능에서 사용되는 URL의 인코더는 인코딩이 모든 스칼라 값을 표현할 수 없을 때 약간의 정보 손실을 초래할 수 있습니다. 예를 들어, windows-1252 인코딩을 사용하는 리소스에서는 서버가 “💩”과 “💩”을 구분할 수 없습니다.

여기서 설명한 문제는 UTF-8만을 사용할 경우 사라집니다. 이것이 모든 곳에서 UTF-8을 필수 인코딩으로 지정한 많은 이유 중 하나입니다.

자세한 내용은 브라우저 UI 장을 참고하세요.

3. 용어

이 명세서는 Infra Standard에 의존합니다. [INFRA]

16진수 숫자는 "0x"로 시작합니다.

수식에서는 모든 숫자가 정수이며, 덧셈은 "+", 뺄셈은 "−", 곱셈은 "×", 정수 나눗셈은 "/"(몫 반환), 나머지는 "%"(정수 나눗셈의 나머지 반환), 논리적 왼쪽 시프트는 "<<", 논리적 오른쪽 시프트는 ">>", 비트 AND는 "&", 비트 OR는 "|"로 나타냅니다.

논리적 오른쪽 시프트 연산의 피연산자는 최소 21비트 이상의 정밀도를 가져야 합니다.


I/O 큐는 특정 타입(바이트 또는 스칼라 값 등)의 항목으로 이루어진 리스트의 일종입니다. end-of-queue는 모든 타입의 I/O 큐에 존재할 수 있는 특수한 항목으로, 큐에 더 이상 항목이 없음을 나타냅니다.

I/O 큐를 사용하는 방법에는 두 가지가 있습니다: 즉시 모드에서는 메모리에 저장된 I/O 데이터를 나타내고, 스트리밍 모드에서는 네트워크에서 들어오는 데이터를 나타냅니다. 즉시 큐는 마지막 항목으로 end-of-queue를 가지지만, 스트리밍 큐는 그렇지 않을 수 있으므로 read 연산이 블록될 수 있습니다.

스트리밍 I/O 큐는 빈 상태에서 생성되고, 네트워크에서 데이터가 들어올 때마다 새로운 항목push됩니다. 네트워크 스트림이 닫히면, end-of-queue 항목이 큐에 push되어야 합니다.

스트리밍 I/O 큐에서 읽는 작업은 블록될 수 있으므로, 스트리밍 I/O 큐이벤트 루프에서 사용해서는 안 됩니다. 대신 병렬로 사용해야 합니다.

읽기항목I/O 큐 ioQueue에서 읽는 절차입니다:

  1. 만약 ioQueue비어있다면, 크기가 1 이상이 될 때까지 대기합니다.

  2. ioQueue[0]이 end-of-queue라면, end-of-queue를 반환합니다.

  3. 제거 ioQueue[0]을(를) 제거하고 반환합니다.

읽기number개의 항목ioQueue에서 읽는 절차입니다:

  1. readItems를 « »로 둡니다.

  2. 아래 단계를 number번 반복합니다:

    1. append readItems읽기 결과를 추가합니다.

  3. 제거 end-of-queuereadItems에서 제거합니다.

  4. readItems를 반환합니다.

peek이란 number개의 항목I/O 큐 ioQueue에서 미리 보는 절차입니다:

  1. 다음 두 조건 중 하나가 만족될 때까지 대기합니다: ioQueue크기number 이상이 되거나, ioQueueend-of-queue를 포함하는 경우.

  2. prefix를 « »로 둡니다.

  3. 각각 n에 대해 범위 1~number에 대해:

    1. 만약 ioQueue[n]이 end-of-queue라면, break합니다.

    2. 그 외에는 appendioQueue[n]을 prefix에 추가합니다.

  4. prefix를 반환합니다.

push항목 itemI/O 큐 ioQueue에 추가하는 절차입니다:

  1. ioQueue의 마지막 항목end-of-queue라면:

    1. itemend-of-queue라면 아무것도 하지 않습니다.

    2. 그 외에는 insertitem을 마지막 항목 앞에 삽입합니다.

  2. 그 외에는 appenditemioQueue에 추가합니다.

push란 시퀀스의 항목들을 주어진 순서대로 I/O 큐 ioQueue에 차례로 push하는 절차입니다.

restore항목end-of-queue가 아닌 경우 I/O 큐prepend하는 작업입니다. restore리스트항목들 중 end-of-queue가 아닌 항목을 주어진 순서대로 큐 맨 앞에 삽입하는 작업입니다.

바이트 « 0xF0, 0x9F »를 I/O 큐 « 0x92 0xA9, end-of-queue »에 삽입하면, 결과는 I/O 큐 « 0xF0, 0x9F, 0x92 0xA9, end-of-queue »가 됩니다. 다음에 읽을 항목은 0xF0입니다.

변환이란 I/O 큐 ioQueue리스트, 문자열, 또는 바이트 시퀀스로 변환하는 작업이며, 읽기를 무한히 반복하여 항목을 모두 가져와 반환합니다.

변환이란 리스트, 문자열 또는 바이트 시퀀스 inputI/O 큐로 변환하는 절차입니다:

  1. Assert: input리스트가 아니거나, 또는 end-of-queue를 포함하지 않아야 합니다.

  2. I/O 큐를 반환하는데, input항목을 순서대로 포함하고, 마지막에 end-of-queue를 추가합니다.

Infra 표준에서는 타입 변환 관련 인프라를 정의할 예정입니다. whatwg/infra issue #319를 참고하세요. [INFRA]

I/O 큐리스트로 정의되며, 로 정의되지 않습니다. 이는 restore 연산 때문입니다. 하지만 이 restore 연산은 본 명세서의 알고리즘 내부 구현 세부사항일 뿐이며, 다른 표준에서 사용해서는 안 됩니다. 구현체는 구현 고려사항에 따라 이러한 알고리즘을 다른 방법으로 구현할 수도 있습니다.


대리쌍으로부터 스칼라 값 얻기선행 대리쌍 leading후행 대리쌍 trailing이 주어졌을 때, 0x10000 + ((leading − 0xD800) << 10) + (trailing − 0xDC00)을 반환합니다.


Uint8Array 객체 생성이란 I/O 큐 ioQueuerealm realm이 주어졌을 때:

  1. 변환을 통해 ioQueue를 바이트 시퀀스로 변환한 결과를 bytes로 둡니다.

  2. 생성을 통해 Uint8Array 객체를 bytesrealm으로부터 생성하여 반환합니다.

4. 인코딩

인코딩스칼라 값 시퀀스를 바이트 시퀀스로(그리고 그 반대로) 매핑하는 규칙을 정의합니다. 각 인코딩이름과 하나 이상의 레이블을 가집니다.

본 명세서는 유니코드 표준에서 정의된 인코딩 방식과 동일한 이름을 가진 세 가지 인코딩을 정의합니다: UTF-8, UTF-16LE, UTF-16BE. 인코딩인코딩 방식과 다르게 바이트 순서 표시(BOM) 처리가 인코딩 자체에 포함되지 않고, 본 명세서의 래퍼 알고리즘 일부로 처리됩니다. 반면 유니코드 표준의 인코딩 방식 정의에는 BOM 처리가 포함되어 있습니다. UTF-8UTF-8 디코드 알고리즘을 함께 사용할 경우, 동일 이름의 인코딩 방식과 일치합니다. 본 명세서는 UTF-16LEUTF-16BE에 대해 인코딩 방식과 일치하는 래퍼 알고리즘을 제공하지 않습니다. [UNICODE]

4.1. 인코더와 디코더

인코딩에는 연관된 디코더가 있고, 대부분에는 연관된 인코더도 있습니다. 디코더인코더의 인스턴스는 핸들러 알고리즘을 가지며 상태를 가질 수도 있습니다. 핸들러 알고리즘은 입력 I/O 큐항목을 받아, finished 또는 하나 이상의 항목, error(선택적으로 코드 포인트 포함), 또는 continue를 반환합니다.

대체(replacement)UTF-16BE/LE 인코딩에는 인코더가 없습니다.

오류 모드(error mode)는 아래에서 사용되며, 디코더의 경우 "replacement" 또는 "fatal", 인코더의 경우 "fatal" 또는 "html"입니다.

XML 프로세서는 오류 모드를 "fatal"로 설정합니다. [XML]

"html"은 HTML 폼에서 종료되지 않는 레거시 인코더가 필요하기 때문에 오류 모드로 존재합니다. "html" 오류 모드는 정상 입력과 구분할 수 없는 시퀀스를 출력하므로, 조용한 데이터 손실을 초래할 수 있습니다. 개발자들은 이러한 상황을 방지하기 위해 UTF-8 인코딩 사용을 강력히 권장합니다. [HTML]


큐 처리인코딩디코더 또는 인코더 인스턴스 encoderDecoder, I/O 큐 input, I/O 큐 output, 오류 모드 mode가 주어졌을 때 다음과 같이 동작합니다:

  1. 다음이 참인 동안 반복합니다:

    1. result항목 처리의 결과로 둡니다. 이때 입력값은 input에서 읽기의 결과, encoderDecoder, input, output, mode입니다.

    2. resultcontinue가 아니면 result를 반환합니다.

항목 처리항목 item, 인코딩인코더 또는 디코더 인스턴스 encoderDecoder, I/O 큐 input, I/O 큐 output, 오류 모드 mode가 주어졌을 때 다음과 같이 동작합니다:

  1. Assert: encoderDecoder인코더 인스턴스가 아니거나, mode가 "replacement"가 아님.

  2. Assert: encoderDecoder디코더 인스턴스가 아니거나, mode가 "html"가 아님.

  3. Assert: encoderDecoder인코더 인스턴스가 아니거나, item대리쌍이 아님.

  4. resultencoderDecoder핸들러inputitem에 적용한 결과로 둡니다.

  5. resultfinished라면:

    1. Push end-of-queueoutput에 추가합니다.

    2. result를 반환합니다.

  6. 그 외에 result가 하나 이상의 항목이라면:

    1. Assert: encoderDecoder디코더 인스턴스가 아니거나 result대리쌍이 포함되어 있지 않음.

    2. Push resultoutput에 추가합니다.

  7. 그 외에 resulterror라면, mode에 따라 다음 단계를 실행합니다:

    "replacement"
    Push U+FFFD (�)를 output에 추가합니다.
    "html"
    Push 0x26 (&), 0x23 (#), 이어서 result코드 포인트을 10진수로 나타낸 가장 짧은 0x30(0)~0x39(9) 시퀀스, 그리고 0x3B(;)를 output에 추가합니다.
    "fatal"
    result를 반환합니다.
  8. continue를 반환합니다.

4.2. 이름과 레이블

아래 표에는 모든 인코딩과 사용자 에이전트가 반드시 지원해야 하는 레이블이 나와 있습니다. 사용자 에이전트는 이외의 인코딩이나 레이블을 지원해서는 안 됩니다.

각 인코딩에 대해, ASCII 소문자화이름이 해당 인코딩의 레이블 중 하나가 됩니다.

작성자는 반드시 UTF-8 인코딩을 사용해야 하며, 이를 식별할 때는 (ASCII 대소문자 구분하지 않음) "utf-8" 레이블을 사용해야 합니다.

새 프로토콜과 포맷, 그리고 새로운 맥락에서 사용되는 기존 포맷은 반드시 UTF-8 인코딩만 사용해야 합니다. 이러한 프로토콜과 포맷이 인코딩이름이나 레이블을 노출해야 한다면, "utf-8"로 노출해야 합니다.

문자열 label에서 인코딩 얻기 절차는 다음과 같습니다:

  1. label에서 앞뒤의 ASCII 공백을 제거합니다.

  2. 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 리소스에서도 제공됩니다.

지원되는 인코딩의 집합은, 이 표준 개발이 시작될 당시 주요 브라우저 엔진이 지원하던 집합의 교집합을 기반으로 하며, 합법적으로 거의 사용되지 않았으나 공격에 사용될 수 있는 인코딩은 제외되었습니다. 일부 인코딩의 포함은 기존 웹 콘텐츠에서의 사용 빈도에 대한 일화적 증거를 고려할 때 의문이 있지만, 브라우저에서 널리 지원되었으나 웹 콘텐츠에서 실제로 널리 사용되는지는 불분명합니다. 그러나 브라우저에서 널리 지원되었거나 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" 등 다양한 레이블을 가집니다. 이들은 역사적으로 개발자들에게 혼란을 주었습니다. 웹, 그리고 이 표준을 구현하여 웹 호환성을 추구하는 모든 소프트웨어에서는, 이들은 동의어입니다: "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 인코딩을 사용할 때 해당 바이트에 대해 서로 다른 코드 포인트 매핑을 선택하게 만듭니다. 웹 브라우저와 브라우저 호환 소프트웨어는 이 바이트들을 windows-1252에 따라 매핑하는데, 이는 두 가지 모두의 상위 집합이며, 이 선택은 본 표준에 명문화되었습니다. 다른 소프트웨어는 에러를 발생시키거나, 동형 디코딩이나 기타 매핑을 사용하기도 합니다. [ISO8859-1] [ISO646]

따라서 구현자와 개발자는 "Latin1" 또는 "ASCII" 관련 API를 제공하는 라이브러리를 사용할 때 주의해야 합니다. 이러한 라이브러리들이 원본 명세에서 정의하지 않은 바이트에 대해 다른 동작을 선택했다면, 이 표준과 일치하지 않는 결과를 반환할 수 있습니다.

4.3. 출력 인코딩

출력 인코딩 얻기인코딩 encoding이 주어졌을 때 다음 절차를 따릅니다:

  1. encoding대체(replacement) 또는 UTF-16BE/LE라면, UTF-8을 반환합니다.

  2. encoding을 반환합니다.

출력 인코딩 얻기 알고리즘은 URL 파싱과 HTML 폼 제출에 유용합니다. 이 둘 모두 정확히 이 동작이 필요합니다.

5. 인덱스

대부분의 레거시 인코딩인덱스를 사용합니다. 인덱스란, 각 항목이 포인터와 해당 코드 포인트로 이루어진 순서 있는 목록입니다. 하나의 인덱스 내에서 포인터는 고유하며, 코드 포인트는 중복될 수 있습니다.

효율적인 구현에서는 인덱스인코딩마다 두 개씩 존재할 수 있습니다. 하나는 디코더에 최적화되고, 다른 하나는 인코더에 최적화됩니다.

인덱스에서 포인터와 해당 코드 포인트를 찾으려면, lines를 리소스의 내용을 U+000A LF로 분할한 결과로 둡니다. 그리고 lines의 각 항목 중 빈 문자열이거나 U+0023(#)로 시작하는 항목은 제거합니다. 그런 다음 lines의 각 항목을 U+0009 TAB으로 분할해서 얻은 첫 번째 서브항목이 포인터(10진수), 두 번째가 해당 코드 포인트(16진수)입니다. 그 외의 서브항목은 무시합니다.

변경 사항을 표시하기 위해 인덱스에는 IdentifierDate가 포함됩니다. Identifier가 변경되었다면, 인덱스도 변경된 것입니다.

index에서 pointer인덱스 코드 포인트index에서 pointer에 해당하는 코드 포인트이며, pointerindex에 없으면 null입니다.

index에서 codePoint인덱스 포인터index에서 codePoint에 처음으로 매핑되는 포인터이며, codePoint가 없으면 null입니다.

인덱스마다(단, index gb18030 rangesindex ISO-2022-JP katakana는 제외) 비권고 시각화 자료가 있습니다. index jis0208에는 Shift_JIS 시각화도 있습니다. 또한, index gb18030 rangesindex ISO-2022-JP katakana를 제외한 각 인덱스에 대해 BMP(기본 다국어 평면) 커버리지 시각화도 존재합니다.

시각화 범례는 다음과 같습니다:

다음은 본 명세서에서 정의한 인덱스 목록입니다. index single-byte는 별도의 표를 가집니다:

인덱스 비고
index Big5 index-big5.txt index Big5 시각화 index Big5 BMP 커버리지 이는 Big5 표준과 홍콩 보조 문자 집합, 기타 일반 확장과 결합되어 일치합니다.
index EUC-KR index-euc-kr.txt index EUC-KR 시각화 index EUC-KR BMP 커버리지 이는 KS X 1001 표준과 Unified Hangul Code(Windows Codepage 949로 더 잘 알려짐)에 일치합니다. 유니코드의 한글 음절 블록 전체를 커버합니다. 시각화에서 좌상단이 포인터 9026인 한글 블록은 유니코드 순서로 되어 있습니다. 별도로 보면, 이 인덱스의 나머지 한글 음절도 유니코드 순서로 되어 있습니다.
index gb18030 index-gb18030.txt index gb18030 시각화 index gb18030 BMP 커버리지 이는 2바이트로 인코딩된 코드 포인트에 대해 GB18030-2022 표준에 일치합니다(단, 0xA3 0xA0은 배포된 콘텐츠와의 호환성을 위해 U+3000 IDEOGRAPHIC SPACE로 매핑됨). 이 인덱스는 유니코드의 CJK 통합 한자 블록 전체를 커버합니다. 시각화에서 (첫 번째) U+3000 위나 왼쪽에 있는 해당 블록의 항목들은 유니코드 순서입니다.
index gb18030 ranges index-gb18030-ranges.txt 인덱스는 다른 모든 인덱스와 동작이 다릅니다. 모든 코드 포인트를 나열하면 100만 개가 넘지만, 207개 구간과 단순한 범위 체크로 표현할 수 있습니다. 따라서 4바이트로 인코딩된 코드 포인트에 대해 GB18030-2000 표준과는 표면적으로만 일치합니다. GB18030-2005 개정의 변경 사항은 아래의 index gb18030 ranges code pointindex gb18030 ranges pointer 알고리즘에서 처리됩니다. GB18030-2022 개정에 대한 변경 사항은 사적 사용 영역 코드 포인트로 매핑되는 바이트 시퀀스 수를 더 늘리지 않기 위해 다르게 처리됩니다. 관련 사적 사용 영역 코드 포인트는 gb18030 인코더에서 별도의 테이블을 통해 직접 매핑되어 이전 매핑과의 호환성을 보장합니다.
index jis0208 index-jis0208.txt index jis0208 시각화, Shift_JIS 시각화 index jis0208 BMP 커버리지 이는 IBM과 NEC의 과거 독자 확장을 포함한 JIS X 0208 표준입니다.
index jis0212 index-jis0212.txt index jis0212 시각화 index jis0212 BMP 커버리지 이는 JIS X 0212 표준입니다. EUC-JP 디코더에서만 사용됩니다(다른 곳에서는 널리 지원되지 않음).
index ISO-2022-JP katakana index-iso-2022-jp-katakana.txt 유니코드 정규화 형식 KC에 따라 반각 가타카나를 전각 가타카나로 매핑합니다. 단, U+FF9E(゙)와 U+FF9F(゚)는 U+3099(◌゙), U+309A(◌゚)가 아니라 U+309B(゛), U+309C(゜)로 매핑됩니다. ISO-2022-JP 인코더에서만 사용됩니다. [UNICODE]

index gb18030 ranges code pointpointer에 대해 다음 절차로 값을 반환합니다:

  1. pointer가 39419보다 크고 189000보다 작거나, pointer가 1237575보다 크면 null을 반환합니다.

  2. pointer가 7457이면 코드 포인트 U+E7C7을 반환합니다.

  3. offsetindex gb18030 ranges에서 pointer 이하인 마지막 포인터로, codePointOffset을 해당 코드 포인트로 둡니다.

  4. codePointOffset + pointeroffset 값의 코드 포인트를 반환합니다.

index gb18030 ranges pointercodePoint에 대해 다음 절차로 값을 반환합니다:

  1. codePoint가 U+E7C7이면 포인터 7457을 반환합니다.

  2. offsetindex gb18030 ranges에서 codePoint 이하인 마지막 코드 포인트로, pointerOffset을 해당 포인터로 둡니다.

  3. pointerOffset + codePointoffset 값의 포인터를 반환합니다.

index Shift_JIS pointercodePoint에 대해 다음 절차로 값을 반환합니다:

  1. indexindex jis0208에서 포인터가 8272~8835(포함) 구간의 항목을 제외한 것으로 둡니다.

    index jis0208에는 중복 코드 포인트가 있으므로 해당 항목을 제외하면 이후 코드 포인트가 사용됩니다.

  2. index에서 codePoint인덱스 포인터를 반환합니다.

index Big5 pointercodePoint에 대해 다음 절차로 값을 반환합니다:

  1. indexindex Big5에서 포인터가 (0xA1 - 0x81) × 157 미만인 항목을 제외한 것으로 둡니다.

    홍콩 보조 문자 집합 확장 반환을 피하기 위함입니다.

  2. codePoint가 U+2550(═), U+255E(╞), U+2561(╡), U+256A(╪), U+5341(十), U+5345(卅) 중 하나라면, index에서 codePoint에 해당하는 마지막 포인터를 반환합니다.

    다른 중복 코드 포인트도 있으나, 이 경우는 첫 번째 포인터를 사용합니다.

  3. index에서 codePoint인덱스 포인터를 반환합니다.


모든 인덱스는 비권고 indexes.json 리소스에서도 제공됩니다. (index gb18030 ranges는 범위 표현을 위해 형식이 약간 다릅니다.)

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 큐가 완전히 소모될 때까지 블로킹됩니다. 스트림에 토큰이 push될 때마다 바로 출력을 사용하려면, 호출자는 빈 출력 I/O 큐로 훅을 실행하고 이를 병렬로 읽어야 합니다. BOM 없는 UTF-8 디코드(실패 가능) 사용 시에는 디코딩 중 오류가 발생하면 출력 I/O 큐에 end-of-queue 항목이 push되지 않음을 주의해야 합니다.

UTF-8 디코드란 바이트 I/O 큐 ioQueue와 선택적 스칼라 값 I/O 큐 output(기본값 « »)에 대해 다음을 수행합니다:

  1. bufferpeek으로 ioQueue에서 3바이트를 가져와 바이트 시퀀스로 변환한 값으로 둡니다.

  2. buffer가 0xEF 0xBB 0xBF이면, readioQueue에서 3바이트를 읽습니다. (해당 바이트는 아무 처리도 하지 않음)

  3. 큐 처리UTF-8디코더 인스턴스, ioQueue, output, "replacement"로 실행합니다.

  4. output을 반환합니다.

BOM 없는 UTF-8 디코드란 바이트 I/O 큐 ioQueue와 선택적 스칼라 값 I/O 큐 output(기본값 « »)에 대해 다음을 수행합니다:

  1. 큐 처리UTF-8디코더 인스턴스, ioQueue, output, "replacement"로 실행합니다.

  2. output을 반환합니다.

BOM 없는 UTF-8 디코드(실패 가능)란 바이트 I/O 큐 ioQueue와 선택적 스칼라 값 I/O 큐 output(기본값 « »)에 대해 다음을 수행합니다:

  1. potentialError큐 처리UTF-8디코더 인스턴스, ioQueue, output, "fatal"로 실행한 결과로 둡니다.

  2. potentialError에러라면, 실패를 반환합니다.

  3. output을 반환합니다.


UTF-8 인코드란 스칼라 값 I/O 큐 ioQueue와 선택적 바이트 I/O 큐 output(기본값 « »)에 대해, 인코딩 ioQueue를 인코딩 UTF-8output으로 실행한 결과를 반환합니다.

6.1. 레거시 표준 훅

표준에서는 디코드, BOM 감지, 인코드 사용을 호환성 외에는 강력히 권장하지 않습니다. 이러한 레거시 훅이 필요한 표준은 보통 인코딩 얻기(레이블을 인코딩으로 변환)와 출력 인코딩 얻기(인코딩인코드에 적합한 인코딩으로 변환)에 의존하게 됩니다.

URL 퍼센트 인코딩처럼 극히 드문 경우에는 커스텀 인코더 오류 처리가 필요합니다. 이럴 땐 인코더 얻기인코딩 또는 실패 알고리즘을 사용해야 하며, 다른 알고리즘은 직접 사용하지 않아야 합니다.

디코드란 바이트 I/O 큐 ioQueue, 폴백 인코딩 encoding, 선택적 스칼라 값 I/O 큐 output(기본값 « »)에 대해 다음을 수행합니다:

  1. BOMEncodingBOM 감지ioQueue에 대해 얻습니다.

  2. BOMEncoding이 null이 아니라면:

    1. encodingBOMEncoding으로 설정합니다.

    2. BOMEncodingUTF-8이면 readioQueue에서 3바이트, 그 외에는 read로 2바이트를 읽습니다. (해당 바이트는 아무 처리도 하지 않음)

    배포된 콘텐츠와의 호환성을 위해 바이트 순서 표시는 그 어떤 것보다 우선합니다. HTTP가 사용되는 맥락에서는 이는 `Content-Type` 헤더 의미와 상충합니다.

  3. 큐 처리encoding디코더 인스턴스, ioQueue, output, "replacement"로 실행합니다.

  4. output을 반환합니다.

BOM 감지란 바이트 I/O 큐 ioQueue에 대해 다음을 수행합니다:

  1. BOMpeek으로 ioQueue에서 3바이트를 가져와 바이트 시퀀스로 변환한 값으로 둡니다.

  2. 아래 표의 각 행에 대해 위에서 아래로 순서대로, BOM이 첫 번째 열의 바이트로 시작하면, 해당 행의 두 번째 열에 있는 인코딩을 반환합니다. 그렇지 않으면 null을 반환합니다.

    바이트 순서 표시 인코딩
    0xEF 0xBB 0xBF UTF-8
    0xFE 0xFF UTF-16BE
    0xFF 0xFE UTF-16LE

이 훅은 디코드가 바이트 순서 표시를 발견했음을 호출자에게 알릴 방법이 없다는 점을 보완하기 위한 것입니다. 이 훅은 디코드 전에 호출해야 하며, 발견된 바이트 순서 표시에 해당하는 인코딩을 반환하거나, 없으면 null을 반환합니다.


인코드란 스칼라 값 I/O 큐 ioQueue, 인코딩 encoding, 선택적 바이트 I/O 큐 output(기본값 « »)에 대해 다음을 수행합니다:

  1. encoder인코더 얻기encoding에서 구한 값으로 둡니다.

  2. 큐 처리encoder, ioQueue, output, "html"로 실행합니다.

  3. output을 반환합니다.

이것은 HTML 폼을 위한 레거시 훅입니다. UTF-8 인코드를 위에 겹쳐 사용하는 것은 안전합니다. 에러가 발생하지 않기 때문입니다. [HTML]


인코더 얻기인코딩 encoding에서 다음을 수행합니다:

  1. Assert: encoding대체(replacement)UTF-16BE/LE가 아님.

  2. encoding인코더 인스턴스를 반환합니다.

인코딩 또는 실패란 스칼라 값 I/O 큐 ioQueue, 인코더 인스턴스 encoder, 바이트 I/O 큐 output에 대해 다음을 수행합니다:

  1. potentialError큐 처리encoder, ioQueue, output, "fatal"로 실행한 결과로 둡니다.

  2. Push end-of-queueoutput에 추가합니다.

  3. potentialError에러라면, 에러코드 포인트을 반환합니다.

  4. null을 반환합니다.

이것은 URL 퍼센트 인코딩을 위한 레거시 훅입니다. 호출자는 ISO-2022-JP 인코더에러를 반환할 때 두 가지 상태를 가질 수 있으므로 인코더 인스턴스를 유지해야 합니다. 또한, 에러를 인코딩할 때 바이트는 0x00~0x7F 범위(단, 0x0E, 0x0F, 0x1B, 0x5C, 0x7E 제외)이어야 합니다. [URL]

특히, 에러를 반환할 때 ISO-2022-JP 인코더Roman 상태라면 0x5C(\)를 출력할 수 없습니다. 이는 U+005C(\)로 디코드되지 않기 때문입니다. 따라서 인코딩 또는 실패를 의도와 다르게 사용하는 응용 프로그램은 대체 구문(예: JavaScript, CSS 등 U+005C(\)를 사용하는 대체 구문)을 사용하는 경우 ISO-2022-JP 인코더 사용을 방지하거나, 반드시 대체 구문을 인코더를 거치도록 해야 합니다(URL 퍼센트 인코딩과는 대조적임).

반환 값은 인코딩할 수 없었던 코드 포인트를 나타내는 숫자이거나, 에러가 없으면 null입니다. non-null이 반환되면 호출자는 동일한 인코더 인스턴스와 새로운 output I/O 큐로 다시 호출해야 합니다.

7. API

이 절에서는 Web IDL의 용어를 사용합니다. 브라우저 사용자 에이전트는 이 API를 지원해야 합니다. JavaScript 구현도 이 API를 지원하는 것이 좋습니다. 그 외의 사용자 에이전트나 프로그래밍 언어는 필요에 맞는 API를 사용하는 것이 권장되며, 반드시 이 API일 필요는 없습니다. [WEBIDL]

다음 예제는 TextEncoder 객체를 사용하여 문자열 배열을 ArrayBuffer로 인코딩합니다. 결과는 Uint8Array 로, 문자열 개수(Uint32Array), 첫 번째 문자열의 길이(Uint32Array), UTF-8로 인코딩된 문자열 데이터, 두 번째 문자열의 길이(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 인터페이스 믹스인은 TextDecoderTextDecoderStream 객체가 공유하는 공통 getter를 정의합니다. 이 객체들은 다음과 같은 연관 항목을 가집니다:

encoding
인코딩.
decoder
디코더 인스턴스.
I/O queue
바이트 I/O 큐.
ignore BOM
불리언, 초기값은 false.
BOM seen
불리언, 초기값은 false.
error mode
오류 모드, 초기값은 "replacement".

I/O 큐 직렬화 알고리즘은 TextDecoderCommon decoder와 스칼라 값 I/O 큐 ioQueue가 주어졌을 때 다음을 수행합니다:

  1. output을 빈 문자열로 둡니다.

  2. 다음이 참인 동안 반복합니다:

    1. item읽기ioQueue에서 가져옵니다.

    2. itemend-of-queue이면 output을 반환합니다.

    3. decoderencodingUTF-8 또는 UTF-16BE/LE이고, decoderignore BOMBOM seen이 false라면:

      1. decoderBOM seen을 true로 설정합니다.

      2. item이 U+FEFF BOM이면 continue합니다.

    4. itemoutput에 추가합니다.

이 알고리즘은 BOM 처리에 있어서 플랫폼의 디코드 알고리즘과 다르게 동작합니다. API 사용자가 더 많은 제어권을 가지도록 의도적으로 다르게 설계되었습니다.


encoding getter의 동작은 thisencoding이름ASCII 소문자로 반환합니다.

fatal getter의 동작은 thiserror mode가 "fatal"이면 true, 아니면 false를 반환합니다.

ignoreBOM getter의 동작은 thisignore BOM을 반환합니다.

7.2. 인터페이스 TextDecoder

dictionary TextDecoderOptions {
  boolean fatal = false;
  boolean ignoreBOM = false;
};

dictionary TextDecodeOptions {
  boolean stream = false;
};

[Exposed=*]
interface TextDecoder {
  constructor(optional DOMString label = "utf-8", 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

encoding이름의 소문자를 반환합니다.

decoder . fatal

error mode가 "fatal"이면 true, 아니면 false를 반환합니다.

decoder . ignoreBOM

ignore BOM 값을 반환합니다.

decoder . decode([input [, options]])

encoding디코더를 실행한 결과를 반환합니다. 이 메서드는 optionsstream이 true로 여러 번 호출된 후, optionsstream이 없는(또는 false인) 한 번의 호출로 조각난 입력을 처리할 수 있습니다. optionsstream이 없는(또는 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

error mode가 "fatal"이고 encoding디코더error를 반환하면, TypeError 예외를 발생시킵니다.

new TextDecoder(label, options) 생성자 동작은 다음과 같습니다:

  1. encoding인코딩 얻기에서 label로 구합니다.

  2. encoding이 실패이거나 replacement이면 RangeError 예외를 발생시킵니다.

  3. thisencodingencoding으로 설정합니다.

  4. options["fatal"] 이 true이면 thiserror mode를 "fatal"로 설정합니다.

  5. thisignore BOMoptions["ignoreBOM"]로 설정합니다.

decode(input, options) 메서드 동작은 다음과 같습니다:

  1. thisdo not flush가 false이면, thisdecoderencoding디코더의 새 인스턴스로, thisI/O 큐를 바이트 I/O 큐 « end-of-queue »로, thisBOM seen을 false로 설정합니다.

  2. thisdo not flushoptions["stream"]로 설정합니다.

  3. input이 주어졌다면, push복사본 inputthisI/O 큐에 추가합니다.

    구현에서는 이 복사를 피하는 전략을 권장합니다. 그렇게 할 경우 input 변경이 이후 decode() 호출에 영향을 주지 않도록 해야 합니다.

    SharedArrayBuffer 객체가 노출하는 메모리는 일반적으로 구현에 사용되는 프로그래밍 언어의 메모리 모델에서 요구하는 데이터 경합 자유 특성을 보장하지 않습니다. 구현 시 SharedArrayBuffer가 노출하는 메모리 접근 시 적절한 방법을 사용해야 합니다.

  4. output을 스칼라 값 I/O 큐 « end-of-queue »로 둡니다.

  5. 다음이 참인 동안 반복합니다:

    1. item읽기thisI/O 큐에서 가져옵니다.

    2. itemend-of-queue이고 thisdo not flush가 true이면, I/O 큐 직렬화thisoutput에 실행한 결과를 반환합니다.

      스트리밍 동작은 end-of-queue를 여기서 처리하지 않고, thisdo not flush를 false로 설정하지 않는 방식으로 동작합니다. 이렇게 하면 이후 호출에서 thisdecoder가 새로 설정되지 않아 상태가 보존됩니다.

    3. 그 외의 경우:

      1. result항목 처리item, thisdecoder, thisI/O 큐, output, thiserror mode로 실행한 결과로 둡니다.

      2. resultfinished이면, I/O 큐 직렬화thisoutput에 실행한 결과를 반환합니다.

      3. 그 외에 resulterror라면 TypeError 예외를 발생시킵니다.

7.3. 인터페이스 믹스인 TextEncoderCommon

interface mixin TextEncoderCommon {
  readonly attribute DOMString encoding;
};

TextEncoderCommon 인터페이스 믹스인은 TextEncoderTextEncoderStream 객체가 공유하는 공통 getter를 정의합니다.

encoding getter의 동작은 "utf-8"을 반환하는 것입니다.

7.4. 인터페이스 TextEncoder

dictionary TextEncoderEncodeIntoResult {
  unsigned long long read;
  unsigned long long written;
};

[Exposed=*]
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 = ""])

UTF-8인코더를 실행한 결과를 반환합니다.

encoder . encodeInto(source, destination)

source에 대해 UTF-8 인코더를 실행하고, 그 결과를 destination에 저장하며, 변환 진행 상황을 객체로 반환합니다. 여기서 readsource에서 변환된 코드 유닛의 개수, writtendestination에서 변환된 바이트 개수입니다.

new TextEncoder() 생성자는 아무 동작도 하지 않습니다.

encode(input) 메서드 동작은 다음과 같습니다:

  1. input을 스칼라 값 I/O 큐로 변환합니다.

  2. output을 바이트 I/O 큐 « end-of-queue »로 둡니다.

  3. 다음이 참인 동안 반복합니다:

    1. item읽기input에서 가져옵니다.

    2. result항목 처리item, UTF-8 인코더 인스턴스, input, output, "fatal"로 실행한 결과로 둡니다.

    3. Assert: resulterror가 아님.

      UTF-8 인코더error를 반환하지 않습니다.

    4. resultfinished이면, Uint8Array 객체 생성outputthis관련 realm으로 실행한 결과를 반환합니다.

encodeInto(source, destination) 메서드 동작은 다음과 같습니다:

  1. read를 0으로 둡니다.

  2. written을 0으로 둡니다.

  3. encoderUTF-8 인코더의 인스턴스로 둡니다.

  4. unused를 스칼라 값 I/O 큐 « end-of-queue »로 둡니다.

    아래에서 호출되는 handler 알고리즘은 이 인자를 필요로 하지만, UTF-8 인코더에서는 사용하지 않습니다.

  5. source를 스칼라 값 I/O 큐로 변환합니다.

  6. 다음이 참인 동안 반복합니다:

    1. item읽기source에서 가져옵니다.

    2. resultencoderhandlerunuseditem에 실행한 결과로 둡니다.

    3. resultfinished이면 break합니다.

    4. 그 외의 경우:

      1. destinationbyte lengthwrittenresult의 바이트 수 이상이면:

        1. item이 U+FFFF보다 크면 read를 2 증가시킵니다.

        2. 그 외에는 read를 1 증가시킵니다.

        3. result의 바이트를 destinationstartingOffsetwritten인 상태로 씁니다.

          위의 SharedArrayBuffer 경고 참고.

        4. writtenresult의 바이트 수만큼 증가시킵니다.

      2. 그 외에는 break합니다.

  7. «[ "read" → read, "written" → written ]»을 반환합니다.

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 label = "utf-8", optional TextDecoderOptions options = {});
};
TextDecoderStream includes TextDecoderCommon;
TextDecoderStream includes GenericTransformStream;
decoder = new TextDecoderStream([label = "utf-8" [, options]])

TextDecoderStream 객체를 반환합니다.

label이 레이블이 아니거나 replacement레이블이라면 RangeError 예외를 발생시킵니다.

decoder . encoding

encoding이름의 소문자를 반환합니다.

decoder . fatal

error mode가 "fatal"이면 true, 아니면 false를 반환합니다.

decoder . ignoreBOM

ignore BOM 값을 반환합니다.

decoder . readable

readable stream을 반환합니다. 이 스트림의 청크encoding디코더writable에 기록된 청크에 대해 실행한 결과입니다.

decoder . writable

writable stream을 반환합니다. 이 스트림은 AllowSharedBufferSource 청크를 받아 encoding디코더를 실행한 뒤, readable에서 사용할 수 있도록 합니다.

일반적으로 ReadableStream 소스의 pipeThrough() 메서드로 사용합니다.

var decoder = new TextDecoderStream(encoding);
byteReadable
  .pipeThrough(decoder)
  .pipeTo(textWritable);

error mode가 "fatal"이고 encoding디코더error를 반환하면, readablewritable 모두 TypeError로 에러 처리됩니다.

new TextDecoderStream(label, options) 생성자 동작은 다음과 같습니다:

  1. encoding인코딩 얻기에서 label로 구합니다.

  2. encoding이 실패이거나 replacement라면 RangeError 예외를 발생시킵니다.

  3. thisencodingencoding으로 설정합니다.

  4. options["fatal"] 이 true이면 thiserror mode를 "fatal"로 설정합니다.

  5. thisignore BOMoptions["ignoreBOM"]로 설정합니다.

  6. thisdecoderthisencoding디코더의 새 인스턴스로, thisI/O 큐를 새 I/O 큐로 설정합니다.

  7. transformAlgorithmchunk 인자를 받아 청크 디코드 및 enqueue 알고리즘을 thischunk로 실행하는 알고리즘으로 둡니다.

  8. flushAlgorithm을 인자 없이 flush and enqueue 알고리즘을 this로 실행하는 알고리즘으로 둡니다.

  9. transformStream TransformStream으로 둡니다.

  10. transformStreamtransformAlgorithmflushAlgorithm으로 설정합니다.

  11. thistransformtransformStream으로 설정합니다.

청크 디코드 및 enqueue 알고리즘은 TextDecoderStream 객체 decoderchunk가 주어졌을 때 다음을 수행합니다:

  1. bufferSourcechunk를 AllowSharedBufferSource로 변환한 값으로 둡니다.

  2. PushbufferSource의 복사본decoderI/O 큐에 추가합니다.

    위의 SharedArrayBuffer 경고 참고.

  3. output을 스칼라 값 I/O 큐 « end-of-queue »로 둡니다.

  4. 다음이 참인 동안 반복합니다:

    1. item읽기decoderI/O 큐에서 가져옵니다.

    2. itemend-of-queue라면:

      1. outputChunkI/O 큐 직렬화decoderoutput에 실행한 결과로 둡니다.

      2. outputChunk가 빈 문자열이 아니라면 enqueueoutputChunkdecodertransform에 추가합니다.

      3. 반환합니다.

    3. result항목 처리item, decoderdecoder, decoderI/O 큐, output, decodererror mode로 실행한 결과로 둡니다.

    4. resulterror라면 TypeError 예외를 발생시킵니다.

flush and enqueue 알고리즘은 입력 ReadableStream 객체의 데이터가 끝났을 때, TextDecoderStream 객체 decoder에 대해 다음을 수행합니다:

  1. output을 스칼라 값 I/O 큐 « end-of-queue »로 둡니다.

  2. 다음이 참인 동안 반복합니다:

    1. item읽기decoderI/O 큐에서 가져옵니다.

    2. result항목 처리item, decoderdecoder, decoderI/O 큐, output, decodererror mode로 실행한 결과로 둡니다.

    3. resultfinished라면:

      1. outputChunkI/O 큐 직렬화decoderoutput에 실행한 결과로 둡니다.

      2. outputChunk가 빈 문자열이 아니라면 enqueueoutputChunkdecodertransform에 추가합니다.

      3. 반환합니다.

    4. 그 외에 resulterror라면 TypeError 예외를 발생시킵니다.

7.6. 인터페이스 TextEncoderStream

[Exposed=*]
interface TextEncoderStream {
  constructor();
};
TextEncoderStream includes TextEncoderCommon;
TextEncoderStream includes GenericTransformStream;

TextEncoderStream 객체는 다음과 연관된 값을 가집니다:

encoder
인코더 인스턴스.
선행 서러게이트
null 또는 선행 서러게이트, 초기값은 null.

TextEncoderStream 객체는 label 인자를 지원하지 않습니다. 오직 UTF-8만 지원합니다.

encoder = new TextEncoderStream()

TextEncoderStream 객체를 반환합니다.

encoder . encoding

"utf-8"을 반환합니다.

encoder . readable

readable stream을 반환합니다. 이 스트림의 청크Uint8Array 이며, UTF-8인코더writable에 기록된 청크에 대해 실행한 결과입니다.

encoder . writable

writable stream을 반환합니다. 이 스트림은 문자열 청크를 받아 UTF-8인코더를 실행한 뒤, readable에서 사용할 수 있도록 합니다.

일반적으로 ReadableStream 소스의 pipeThrough() 메서드로 사용합니다.

textReadable
  .pipeThrough(new TextEncoderStream())
  .pipeTo(byteWritable);

new TextEncoderStream() 생성자 동작은 다음과 같습니다:

  1. thisencoderUTF-8 인코더의 인스턴스로 설정합니다.

  2. transformAlgorithmchunk 인자를 받아 청크 인코딩 및 enqueue 알고리즘을 thischunk로 실행하는 알고리즘으로 둡니다.

  3. flushAlgorithm인코딩 및 플러시 알고리즘을 this로 실행하는 알고리즘으로 둡니다.

  4. transformStream TransformStream으로 둡니다.

  5. transformStreamtransformAlgorithmflushAlgorithm으로 설정합니다.

  6. thistransformtransformStream으로 설정합니다.


청크 인코딩 및 enqueue 알고리즘은 TextEncoderStream 객체 encoderchunk가 주어졌을 때 다음을 수행합니다:

  1. inputchunk를 DOMString으로 변환한 값으로 둡니다.

  2. input코드 유닛 I/O 큐로 변환합니다.

    DOMString과 코드 유닛 I/O 큐를 사용하는 이유는, 청크 사이에 분리된 서러게이트 쌍을 재조립할 수 있도록 하기 위함입니다. 동작 자체는 USVString과 동일합니다. 특히, 단독 서러게이트는 U+FFFD(�)로 대체됩니다.

  3. output을 바이트 I/O 큐 « end-of-queue »로 둡니다.

  4. 다음이 참인 동안 반복합니다:

    1. item읽기input에서 가져옵니다.

    2. itemend-of-queue라면:

      1. output을 바이트 시퀀스로 변환합니다.

      2. output이 비어 있지 않으면:

        1. chunkUint8Array 객체 생성outputencoderrelevant realm으로 실행한 결과로 둡니다.

        2. enqueuechunkencodertransform에 추가합니다.

      3. 반환합니다.

    3. result코드 유닛을 스칼라 값으로 변환 알고리즘을 encoder, item, input에 실행한 결과로 둡니다.

    4. resultcontinue가 아니면, 항목 처리result, encoderencoder, input, output, "fatal"로 실행합니다.

코드 유닛을 스칼라 값으로 변환 알고리즘은 TextEncoderStream 객체 encoder, 코드 유닛 item, 코드 유닛 I/O 큐 input이 주어졌을 때 다음을 수행합니다:

  1. encoder선행 서러게이트가 null이 아니면:

    1. leadingSurrogateencoder선행 서러게이트로 둡니다.

    2. encoder선행 서러게이트를 null로 설정합니다.

    3. item후행 서러게이트라면, 서러게이트로부터 스칼라 값leadingSurrogate, item으로 실행한 결과를 반환합니다.

    4. iteminput에 복원합니다.

    5. U+FFFD(�)를 반환합니다.

  2. item선행 서러게이트라면 encoder선행 서러게이트item으로 설정하고 continue를 반환합니다.

  3. item후행 서러게이트라면 U+FFFD(�)를 반환합니다.

  4. item을 반환합니다.

이 알고리즘은 Infra 표준의 "문자열을 스칼라 값 문자열로 변환" 알고리즘과 동등하지만, 문자열 사이에 분리된 서러게이트 쌍도 허용합니다. [INFRA]

인코딩 및 플러시 알고리즘은 TextEncoderStream 객체 encoder가 주어졌을 때 다음을 수행합니다:

  1. encoder선행 서러게이트가 null이 아니면:

    1. chunkUint8Array 객체 생성을 « 0xEF, 0xBF, 0xBD »와 encoderrelevant realm으로 실행한 결과로 둡니다.

      이는 UTF-8 바이트로 U+FFFD(�)입니다.

    2. enqueuechunkencodertransform에 추가합니다.

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디코더handlerioQueuebyte가 주어졌을 때 다음을 수행합니다:

  1. byteend-of-queue이고 UTF-8 필요한 바이트 수가 0이 아니라면, UTF-8 필요한 바이트 수를 0으로 설정하고 에러를 반환합니다.

  2. byteend-of-queue라면, finished를 반환합니다.

  3. UTF-8 필요한 바이트 수가 0이면, byte에 따라:

    0x00 ~ 0x7F

    byte 값을 가진 코드 포인트를 반환합니다.

    0xC2 ~ 0xDF
    1. UTF-8 필요한 바이트 수를 1로 설정합니다.

    2. UTF-8 코드 포인트byte & 0x1F로 설정합니다.

      byte의 하위 5비트입니다.

    0xE0 ~ 0xEF
    1. byte가 0xE0이면, UTF-8 하한값을 0xA0으로 설정합니다.

    2. byte가 0xED이면, UTF-8 상한값을 0x9F로 설정합니다.

    3. UTF-8 필요한 바이트 수를 2로 설정합니다.

    4. UTF-8 코드 포인트byte & 0xF로 설정합니다.

      byte의 하위 4비트입니다.

    0xF0 ~ 0xF4
    1. byte가 0xF0이면, UTF-8 하한값을 0x90으로 설정합니다.

    2. byte가 0xF4이면, UTF-8 상한값을 0x8F로 설정합니다.

    3. UTF-8 필요한 바이트 수를 3으로 설정합니다.

    4. UTF-8 코드 포인트byte & 0x7로 설정합니다.

      byte의 하위 3비트입니다.

    그 외

    에러 반환

    continue를 반환합니다.

  4. byteUTF-8 하한값부터 UTF-8 상한값 범위에 없으면:

    1. UTF-8 코드 포인트, UTF-8 필요한 바이트 수, UTF-8 읽은 바이트 수를 0으로, UTF-8 하한값을 0x80으로, UTF-8 상한값을 0xBF로 설정합니다.

    2. byteioQueue에 복원합니다.

    3. 에러 반환

  5. UTF-8 하한값을 0x80, UTF-8 상한값을 0xBF로 설정합니다.

  6. UTF-8 코드 포인트를 (UTF-8 코드 포인트 << 6) | (byte & 0x3F)로 설정합니다.

    UTF-8 코드 포인트의 기존 비트들을 6비트 왼쪽으로 이동시키고, 새로 생긴 하위 6비트를 byte의 하위 6비트로 설정합니다.

  7. UTF-8 읽은 바이트 수를 1 증가시킵니다.

  8. UTF-8 읽은 바이트 수UTF-8 필요한 바이트 수와 같지 않다면 continue를 반환합니다.

  9. codePointUTF-8 코드 포인트로 둡니다.

  10. UTF-8 코드 포인트, UTF-8 필요한 바이트 수, UTF-8 읽은 바이트 수를 0으로 설정합니다.

  11. 값이 codePoint인 코드 포인트를 반환합니다.

UTF-8 디코더의 제약사항은 Unicode 표준의 “Best Practices for Using U+FFFD”와 일치합니다. 현행 표준(Encoding Standard)에서는 이 외의 동작이 허용되지 않습니다(동일한 결과를 내는 다른 알고리즘은 허용, 오히려 장려됨). [UNICODE]

8.1.2. UTF-8 인코더

UTF-8인코더handlerunusedcodePoint가 주어졌을 때 다음을 수행합니다:

  1. codePointend-of-queue라면, finished를 반환합니다.

  2. codePointASCII 코드 포인트라면, 값이 codePoint인 바이트를 반환합니다.

  3. codePoint가 속한 범위에 따라 countoffset을 설정합니다:

    U+0080 ~ U+07FF (포함)
    1 및 0xC0
    U+0800 ~ U+FFFF (포함)
    2 및 0xE0
    U+10000 ~ U+10FFFF (포함)
    3 및 0xF0
  4. bytes를 바이트 시퀀스(첫 번째 바이트는 (codePoint >> (6 × count)) + offset)로 둡니다.

  5. count가 0보다 큰 동안 반복합니다:

    1. tempcodePoint >> (6 × (count − 1))로 설정합니다.

    2. bytes에 0x80 | (temp & 0x3F)를 추가합니다.

    3. count를 1 감소시킵니다.

  6. 바이트 시퀀스 bytes를 순서대로 반환합니다.

이 알고리즘은 Unicode 표준에 기술된 것과 동일한 결과를 가집니다. 완전성을 위해 여기에 포함되어 있습니다. [UNICODE]

9. 레거시 단일 바이트 인코딩

각 바이트가 하나의 코드 포인트이거나 아무것도 아닌 인코딩단일 바이트 인코딩이라고 합니다. 단일 바이트 인코딩디코더인코더를 공유합니다. index single-byte단일 바이트 디코더단일 바이트 인코더에서 참조되며, 아래 표로 정의되고, 사용하는 단일 바이트 인코딩에 따라 다릅니다. 두 개를 제외한 모든 단일 바이트 인코딩은 고유한 index를 가집니다.

IBM866 index-ibm866.txt index IBM866 시각화 index IBM866 BMP 커버리지
ISO-8859-2 index-iso-8859-2.txt index ISO-8859-2 시각화 index ISO-8859-2 BMP 커버리지
ISO-8859-3 index-iso-8859-3.txt index ISO-8859-3 시각화 index ISO-8859-3 BMP 커버리지
ISO-8859-4 index-iso-8859-4.txt index ISO-8859-4 시각화 index ISO-8859-4 BMP 커버리지
ISO-8859-5 index-iso-8859-5.txt index ISO-8859-5 시각화 index ISO-8859-5 BMP 커버리지
ISO-8859-6 index-iso-8859-6.txt index ISO-8859-6 시각화 index ISO-8859-6 BMP 커버리지
ISO-8859-7 index-iso-8859-7.txt index ISO-8859-7 시각화 index ISO-8859-7 BMP 커버리지
ISO-8859-8 index-iso-8859-8.txt index ISO-8859-8 시각화 index ISO-8859-8 BMP 커버리지
ISO-8859-8-I
ISO-8859-10 index-iso-8859-10.txt index ISO-8859-10 시각화 index ISO-8859-10 BMP 커버리지
ISO-8859-13 index-iso-8859-13.txt index ISO-8859-13 시각화 index ISO-8859-13 BMP 커버리지
ISO-8859-14 index-iso-8859-14.txt index ISO-8859-14 시각화 index ISO-8859-14 BMP 커버리지
ISO-8859-15 index-iso-8859-15.txt index ISO-8859-15 시각화 index ISO-8859-15 BMP 커버리지
ISO-8859-16 index-iso-8859-16.txt index ISO-8859-16 시각화 index ISO-8859-16 BMP 커버리지
KOI8-R index-koi8-r.txt index KOI8-R 시각화 index KOI8-R BMP 커버리지
KOI8-U index-koi8-u.txt index KOI8-U 시각화 index KOI8-U BMP 커버리지
macintosh index-macintosh.txt index macintosh 시각화 index macintosh BMP 커버리지
windows-874 index-windows-874.txt index windows-874 시각화 index windows-874 BMP 커버리지
windows-1250 index-windows-1250.txt index windows-1250 시각화 index windows-1250 BMP 커버리지
windows-1251 index-windows-1251.txt index windows-1251 시각화 index windows-1251 BMP 커버리지
windows-1252 index-windows-1252.txt index windows-1252 시각화 index windows-1252 BMP 커버리지
windows-1253 index-windows-1253.txt index windows-1253 시각화 index windows-1253 BMP 커버리지
windows-1254 index-windows-1254.txt index windows-1254 시각화 index windows-1254 BMP 커버리지
windows-1255 index-windows-1255.txt index windows-1255 시각화 index windows-1255 BMP 커버리지
windows-1256 index-windows-1256.txt index windows-1256 시각화 index windows-1256 BMP 커버리지
windows-1257 index-windows-1257.txt index windows-1257 시각화 index windows-1257 BMP 커버리지
windows-1258 index-windows-1258.txt index windows-1258 시각화 index windows-1258 BMP 커버리지
x-mac-cyrillic index-x-mac-cyrillic.txt index x-mac-cyrillic 시각화 index x-mac-cyrillic BMP 커버리지

ISO-8859-8ISO-8859-8-I는 별도의 인코딩 이름입니다. ISO-8859-8은 레이아웃 방향에 영향을 주기 때문입니다. 과거에는 ISO-8859-6과 "ISO-8859-6-I"도 그랬던 적이 있으나, 현행 표준에서는 더 이상 그렇지 않습니다.

9.1. 단일 바이트 디코더

단일 바이트 인코딩디코더handlerunusedbyte가 주어졌을 때 다음을 수행합니다:

  1. byteend-of-queue라면, finished를 반환합니다.

  2. byteASCII 바이트라면, 값이 byte인 코드 포인트를 반환합니다.

  3. codePointindex code pointbyte − 0x80에 해당하는 값을 index single-byte에서 찾은 값으로 둡니다.

  4. codePoint가 null이면 에러를 반환합니다.

  5. 값이 codePoint인 코드 포인트를 반환합니다.

9.2. 단일 바이트 인코더

단일 바이트 인코딩인코더handlerunusedcodePoint가 주어졌을 때 다음을 수행합니다:

  1. codePointend-of-queue라면, finished를 반환합니다.

  2. codePointASCII 코드 포인트라면, 값이 codePoint인 바이트를 반환합니다.

  3. pointerindex pointercodePoint에 해당하는 값을 index single-byte에서 찾은 값으로 둡니다.

  4. pointer가 null이면 에러codePoint와 함께 반환합니다.

  5. 값이 pointer + 0x80인 바이트를 반환합니다.

10. 레거시 다중 바이트 중국어(간체) 인코딩

10.1. GBK

10.1.1. GBK 디코더

GBK디코더gb18030디코더입니다.

10.1.2. GBK 인코더

GBK인코더gb18030인코더이며, is GBK가 true로 설정되어 있습니다.

GBKgb18030와 완전히 동일하게 alias하지 않는 것은, 현행 서버 및 GBK 인코더로 생성된 콘텐츠를 사용하는 레거시 소비자에서의 호환성 문제를 줄이기 위한 보수적인 선택입니다.

10.2. gb18030

10.2.1. gb18030 디코더

gb18030디코더는 다음과 연관된 값을 가집니다:

gb18030 first
gb18030 second
gb18030 third
각각 바이트이며, 초기값은 0x00입니다.

gb18030디코더handlerioQueuebyte가 주어졌을 때 다음을 수행합니다:

  1. byteend-of-queue이고 gb18030 first, gb18030 second, gb18030 third 모두 0x00이면 finished를 반환합니다.

  2. byteend-of-queue이고, gb18030 first, gb18030 second, 또는 gb18030 third가 0x00이 아니라면 gb18030 first, gb18030 second, gb18030 third를 0x00으로 설정하고 에러를 반환합니다.

  3. gb18030 third가 0x00이 아니라면:

    1. byte가 0x30~0x39 범위가 아니라면:

      1. 복원 « gb18030 second, gb18030 third, byte »를 ioQueue에 복원합니다.

      2. gb18030 first, gb18030 second, gb18030 third를 0x00으로 설정합니다.

      3. 에러 반환

    2. codePointindex gb18030 ranges code point에서 ((gb18030 first − 0x81) × (10 × 126 × 10)) + ((gb18030 second − 0x30) × (10 × 126)) + ((gb18030 third − 0x81) × 10) + byte − 0x30의 값으로 둡니다.

    3. gb18030 first, gb18030 second, gb18030 third를 0x00으로 설정합니다.

    4. codePoint가 null이면 에러를 반환합니다.

    5. 값이 codePoint인 코드 포인트를 반환합니다.

  4. gb18030 second가 0x00이 아니라면:

    1. byte가 0x81~0xFE 범위라면, gb18030 thirdbyte를 설정하고 continue를 반환합니다.

    2. 복원 « gb18030 second, byte »를 ioQueue에 복원하고, gb18030 firstgb18030 second를 0x00으로 설정한 뒤, 에러를 반환합니다.

  5. gb18030 first가 0x00이 아니라면:

    1. byte가 0x30~0x39 범위라면 gb18030 secondbyte를 설정하고 continue를 반환합니다.

    2. leadinggb18030 first로 둡니다.

    3. gb18030 first를 0x00으로 설정합니다.

    4. pointer를 null로 둡니다.

    5. offsetbyte가 0x7F 미만이면 0x40, 그 외에는 0x41로 둡니다.

    6. byte가 0x40~0x7E 또는 0x80~0xFE 범위라면 pointer를 (leading − 0x81) × 190 + (byteoffset)로 설정합니다.

    7. codePointpointer가 null이면 null, 아니면 index code pointpointer에 해당하는 index gb18030의 값으로 둡니다.

    8. codePoint가 null이 아니라면 값이 codePoint인 코드 포인트를 반환합니다.

    9. byteASCII 바이트라면 byteioQueue에 복원합니다.

    10. 에러 반환

  6. byteASCII 바이트라면, 값이 byte인 코드 포인트를 반환합니다.

  7. byte가 0x80이면, 코드 포인트 U+20AC(€)를 반환합니다.

  8. byte가 0x81~0xFE 범위라면, gb18030 firstbyte를 설정하고 continue를 반환합니다.

  9. 에러 반환

10.2.2. gb18030 인코더

gb18030인코더is GBK라는 불리언 값을 가지며, 초기값은 false입니다.

gb18030인코더handlerunusedcodePoint가 주어졌을 때 다음을 수행합니다:

  1. codePointend-of-queue라면, finished를 반환합니다.

  2. codePointASCII 코드 포인트라면, 값이 codePoint인 바이트를 반환합니다.

  3. codePoint가 U+E5E5라면, 에러codePoint와 함께 반환합니다.

    index gb18030은 호환성 때문에 0xA3 0xA0을 U+E5E5가 아니라 U+3000 IDEOGRAPHIC SPACE로 매핑합니다. 따라서 역변환(roundtrip)이 불가능합니다.

  4. is GBK가 true이고 codePoint가 U+20AC(€)라면, 바이트 0x80을 반환합니다.

  5. 아래 표의 첫 번째 열이 codePoint인 행이 있다면, 해당 행의 두 번째 열에 있는 두 바이트를 반환합니다:

    코드 포인트 바이트
    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 참고.

  6. pointerindex pointer에서 codePoint에 해당하는 값으로 index gb18030에서 찾습니다.

  7. pointer가 null이 아니라면:

    1. leadingpointer / 190 + 0x81로 둡니다.

    2. trailingpointer % 190로 둡니다.

    3. offsettrailing이 0x3F 미만이면 0x40, 그 외에는 0x41로 둡니다.

    4. leadingtrailing + offset 값을 가지는 두 바이트를 반환합니다.

  8. is GBK가 true이면, 에러codePoint와 함께 반환합니다.

  9. pointerindex gb18030 ranges pointer에서 codePoint에 해당하는 값으로 둡니다.

  10. byte1pointer / (10 × 126 × 10)로 둡니다.

  11. pointerpointer % (10 × 126 × 10)으로 설정합니다.

  12. byte2pointer / (10 × 126)로 둡니다.

  13. pointerpointer % (10 × 126)으로 설정합니다.

  14. byte3pointer / 10으로 둡니다.

  15. byte4pointer % 10으로 둡니다.

  16. 값이 byte1 + 0x81, byte2 + 0x30, byte3 + 0x81, byte4 + 0x30인 네 바이트를 반환합니다.

11. 레거시 다중 바이트 중국어(번체) 인코딩

11.1. Big5

11.1.1. Big5 디코더

Big5디코더Big5 lead라는 바이트 값을 가지며, 초기값은 0x00입니다.

Big5디코더handlerioQueuebyte가 주어졌을 때 다음을 수행합니다:

  1. byteend-of-queue이고 Big5 lead가 0x00이 아니면, Big5 lead를 0x00으로 설정하고 에러를 반환합니다.

  2. byteend-of-queue이고 Big5 lead가 0x00이면, finished를 반환합니다.

  3. Big5 lead가 0x00이 아니면:

    1. leadingBig5 lead로 둡니다.

    2. Big5 lead를 0x00으로 설정합니다.

    3. pointer를 null로 둡니다.

    4. offsetbyte가 0x7F 미만이면 0x40, 그 외에는 0x62로 둡니다.

    5. byte가 0x40~0x7E 또는 0xA1~0xFE 범위라면 pointer를 (leading − 0x81) × 157 + (byteoffset)로 설정합니다.

    6. 아래 표의 첫 번째 열이 pointer인 행이 있다면, 두 번째 열에 있는 두 개 코드 포인트를 반환합니다(세 번째 열은 무시):

      포인터 코드 포인트 비고
      1133 U+00CA U+0304 Ê̄ (라틴 대문자 E 위에 곡절표 및 장음표)
      1135 U+00CA U+030C Ê̌ (라틴 대문자 E 위에 곡절표 및 캐런 부호)
      1164 U+00EA U+0304 ê̄ (라틴 소문자 e 위에 곡절표 및 장음표)
      1166 U+00EA U+030C ê̌ (라틴 소문자 e 위에 곡절표 및 캐런 부호)

      인덱스는 하나의 코드 포인트만 허용하므로, 이 표는 이러한 포인터에 사용됩니다.

    7. codePointpointer가 null이면 null, 아니면 index code pointpointer에 해당하는 index Big5의 값으로 둡니다.

    8. codePoint가 null이 아니면, 값이 codePoint인 코드 포인트를 반환합니다.

    9. byteASCII 바이트라면, byteioQueue에 복원합니다.

    10. 에러 반환

  4. byteASCII 바이트라면, 값이 byte인 코드 포인트를 반환합니다.

  5. byte가 0x81~0xFE 범위라면, Big5 leadbyte를 설정하고 continue를 반환합니다.

  6. 에러 반환

11.1.2. Big5 인코더

Big5인코더handlerunusedcodePoint가 주어졌을 때 다음을 수행합니다:

  1. codePointend-of-queue라면, finished를 반환합니다.

  2. codePointASCII 코드 포인트라면, 값이 codePoint인 바이트를 반환합니다.

  3. pointerindex Big5 pointer에서 codePoint에 해당하는 값으로 둡니다.

  4. pointer가 null이면 에러codePoint와 함께 반환합니다.

  5. leadingpointer / 157 + 0x81로 둡니다.

  6. trailingpointer % 157로 둡니다.

  7. offsettrailing이 0x3F 미만이면 0x40, 그 외에는 0x62로 둡니다.

  8. 값이 leadingtrailing + offset인 두 바이트를 반환합니다.

12. 레거시 다중 바이트 일본어 인코딩

12.1. EUC-JP

12.1.1. EUC-JP 디코더

EUC-JP디코더는 다음과 연관된 값을 가집니다:

EUC-JP jis0212
불리언, 초기값은 false.
EUC-JP lead
바이트, 초기값은 0x00.

EUC-JP디코더handlerioQueuebyte가 주어졌을 때 다음을 수행합니다:

  1. byteend-of-queue이고 EUC-JP lead가 0x00이 아니면, EUC-JP lead를 0x00으로 설정하고 에러를 반환합니다.

  2. byteend-of-queue이고 EUC-JP lead가 0x00이면, finished를 반환합니다.

  3. EUC-JP lead가 0x8E이고 byte가 0xA1~0xDF 범위라면, EUC-JP lead를 0x00으로 설정하고 값이 0xFF61 − 0xA1 + byte인 코드 포인트를 반환합니다.

  4. EUC-JP lead가 0x8F이고 byte가 0xA1~0xFE 범위라면, EUC-JP jis0212를 true로, EUC-JP leadbyte로 설정하고 continue를 반환합니다.

  5. EUC-JP lead가 0x00이 아니면:

    1. leadingEUC-JP lead로 둡니다.

    2. EUC-JP lead를 0x00으로 설정합니다.

    3. codePoint를 null로 둡니다.

    4. leadingbyte가 모두 0xA1~0xFE 범위라면, EUC-JP jis0212가 false일 때는 index code point 중 (leading − 0xA1) × 94 + byte − 0xA1에 해당하는 값을 index jis0208에서, true일 때는 index jis0212에서 codePoint로 설정합니다.

    5. EUC-JP jis0212를 false로 설정합니다.

    6. codePoint가 null이 아니면, 값이 codePoint인 코드 포인트를 반환합니다.

    7. byteASCII 바이트라면, byteioQueue에 복원합니다.

    8. 에러 반환

  6. byteASCII 바이트라면, 값이 byte인 코드 포인트를 반환합니다.

  7. byte가 0x8E, 0x8F 또는 0xA1~0xFE 범위라면 EUC-JP leadbyte를 설정하고 continue를 반환합니다.

  8. 에러 반환

12.1.2. EUC-JP 인코더

EUC-JP인코더handlerunusedcodePoint가 주어졌을 때 다음을 수행합니다:

  1. codePointend-of-queue라면, finished를 반환합니다.

  2. codePointASCII 코드 포인트라면, 값이 codePoint인 바이트를 반환합니다.

  3. codePoint가 U+00A5(¥)라면, 바이트 0x5C을 반환합니다.

  4. codePoint가 U+203E(‾)라면, 바이트 0x7E을 반환합니다.

  5. codePoint가 U+FF61(。) ~ U+FF9F(゚) 범위라면, 값이 0x8E와 codePoint − 0xFF61 + 0xA1인 두 바이트를 반환합니다.

  6. codePoint가 U+2212(−)라면, U+FF0D(-)로 설정합니다.

  7. pointerindex pointer에서 codePoint에 해당하는 값으로 index jis0208에서 찾습니다.

    pointer가 null이 아니면 index jis0208의 특성상 8836 미만입니다.

  8. pointer가 null이면 에러codePoint와 함께 반환합니다.

  9. leadingpointer / 94 + 0xA1로 둡니다.

  10. trailingpointer % 94 + 0xA1로 둡니다.

  11. 값이 leadingtrailing인 두 바이트를 반환합니다.

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 lead
바이트, 초기값은 0x00.
ISO-2022-JP output
불리언, 초기값은 false.

ISO-2022-JP디코더handlerioQueuebyte가 주어졌을 때, ISO-2022-JP 디코더 상태를 기준으로 동작합니다:

ASCII

byte에 따라:

0x1B

ISO-2022-JP 디코더 상태escape start로 설정하고 continue를 반환합니다.

0x00 ~ 0x7F (0x0E, 0x0F, 0x1B 제외)

ISO-2022-JP output을 false로 설정하고, 값이 byte인 코드 포인트를 반환합니다.

end-of-queue

finished를 반환합니다.

그 외

ISO-2022-JP output을 false로 설정하고 에러를 반환합니다.

Roman

byte에 따라:

0x1B

ISO-2022-JP 디코더 상태escape start로 설정하고 continue를 반환합니다.

0x5C

ISO-2022-JP output을 false로 설정하고 코드 포인트 U+00A5(¥) 반환.

0x7E

ISO-2022-JP output을 false로 설정하고 코드 포인트 U+203E(‾) 반환.

0x00 ~ 0x7F (0x0E, 0x0F, 0x1B, 0x5C, 0x7E 제외)

ISO-2022-JP output을 false로 설정하고, 값이 byte인 코드 포인트를 반환합니다.

end-of-queue

finished를 반환합니다.

그 외

ISO-2022-JP output을 false로 설정하고 에러를 반환합니다.

katakana

byte에 따라:

0x1B

ISO-2022-JP 디코더 상태escape start로 설정하고 continue를 반환합니다.

0x21 ~ 0x5F

ISO-2022-JP output을 false로 설정하고 값이 0xFF61 − 0x21 + byte인 코드 포인트를 반환합니다.

end-of-queue

finished를 반환합니다.

그 외

ISO-2022-JP output을 false로 설정하고 에러를 반환합니다.

Leading byte

byte에 따라:

0x1B

ISO-2022-JP 디코더 상태escape start로 설정하고 continue를 반환합니다.

0x21 ~ 0x7E

ISO-2022-JP output을 false로, ISO-2022-JP leadbyte로, ISO-2022-JP 디코더 상태trailing byte로 설정하고 continue를 반환합니다.

end-of-queue

finished를 반환합니다.

그 외

ISO-2022-JP output을 false로 설정하고 에러를 반환합니다.

Trailing byte

byte에 따라:

0x1B

ISO-2022-JP 디코더 상태escape start로 설정하고 에러를 반환합니다.

0x21 ~ 0x7E
  1. ISO-2022-JP 디코더 상태leading byte로 설정합니다.

  2. pointer를 (ISO-2022-JP lead − 0x21) × 94 + byte − 0x21로 둡니다.

  3. codePointindex code pointpointer에 해당하는 index jis0208의 값으로 둡니다.

  4. codePoint가 null이면 에러를 반환합니다.

  5. 값이 codePoint인 코드 포인트를 반환합니다.

end-of-queue

ISO-2022-JP 디코더 상태leading byte로 설정하고 에러를 반환합니다.

그 외

ISO-2022-JP 디코더 상태leading byte로 설정하고 에러를 반환합니다.

Escape start
  1. byte가 0x24 또는 0x28이면 ISO-2022-JP leadbyte로, ISO-2022-JP 디코더 상태escape로 설정하고 continue를 반환합니다.

  2. byteend-of-queue가 아니면, byteioQueue에 복원합니다.

  3. ISO-2022-JP output을 false로, ISO-2022-JP 디코더 상태ISO-2022-JP 디코더 출력 상태로 설정하고 에러를 반환합니다.

Escape
  1. leadingISO-2022-JP lead로 두고, ISO-2022-JP lead를 0x00으로 설정합니다.

  2. state를 null로 둡니다.

  3. leading이 0x28이고 byte가 0x42이면 stateASCII로 설정합니다.

  4. leading이 0x28이고 byte가 0x4A이면 stateRoman으로 설정합니다.

  5. leading이 0x28이고 byte가 0x49이면 statekatakana로 설정합니다.

  6. leading이 0x24이고 byte가 0x40 또는 0x42이면, stateleading byte로 설정합니다.

  7. state가 null이 아니면:

    1. ISO-2022-JP 디코더 상태ISO-2022-JP 디코더 출력 상태state로 설정합니다.

    2. outputISO-2022-JP output의 값으로 둡니다.

    3. ISO-2022-JP output을 true로 설정합니다.

    4. output이 false면 continue를 반환하고, 아니라면 에러를 반환합니다.

  8. byteend-of-queue이면 leadingioQueue에 복원하고, 아니면 « leading, byte »ioQueue에 복원합니다.

  9. ISO-2022-JP output을 false로, ISO-2022-JP 디코더 상태ISO-2022-JP 디코더 출력 상태로 설정하고 에러 반환.

12.2.2. ISO-2022-JP 인코더

ISO-2022-JP 인코더는 여러 번 출력 결과를 이어붙였을 때 해당 디코더에서 에러가 발생할 수 있는 유일한 인코더입니다.

U+00A5(¥)를 인코딩하면 0x1B 0x28 0x4A 0x5C 0x1B 0x28 0x42가 됩니다. 두 번 인코딩해서 결과를 이어붙이고 디코딩하면 U+00A5 U+FFFD U+00A5가 나옵니다.

ISO-2022-JP인코더ISO-2022-JP 인코더 상태를 가지며, ASCII, Roman, jis0208 중 하나이며, 초기값은 ASCII입니다.

ISO-2022-JP인코더handlerioQueuecodePoint가 주어졌을 때 다음을 수행합니다:

  1. codePointend-of-queue이고 ISO-2022-JP 인코더 상태ASCII가 아니라면, ISO-2022-JP 인코더 상태ASCII로 설정하고, 세 바이트 0x1B 0x28 0x42를 반환합니다.

  2. codePointend-of-queue이고 ISO-2022-JP 인코더 상태ASCII라면, finished를 반환합니다.

  3. ISO-2022-JP 인코더 상태ASCII 또는 Roman이고, codePoint가 U+000E, U+000F, U+001B 중 하나라면, U+FFFD(�)와 함께 에러를 반환합니다.

    공격 방지를 위해 해당 codePoint 대신 U+FFFD(�)를 반환합니다.

  4. ISO-2022-JP 인코더 상태ASCII이고, codePointASCII 코드 포인트라면, 값이 codePoint인 바이트를 반환합니다.

  5. ISO-2022-JP 인코더 상태Roman이고, codePointASCII 코드 포인트(U+005C(\), U+007E(~) 제외)이거나 U+00A5(¥), U+203E(‾)라면:

    1. codePointASCII 코드 포인트라면, 값이 codePoint인 바이트를 반환합니다.

    2. codePoint가 U+00A5(¥)라면, 바이트 0x5C을 반환합니다.

    3. codePoint가 U+203E(‾)라면, 바이트 0x7E을 반환합니다.

  6. codePointASCII 코드 포인트이고 ISO-2022-JP 인코더 상태ASCII가 아니라면, codePointioQueue에 복원하고, ISO-2022-JP 인코더 상태ASCII로 설정한 뒤, 세 바이트 0x1B 0x28 0x42를 반환합니다.

  7. codePoint가 U+00A5(¥), U+203E(‾)이고, ISO-2022-JP 인코더 상태Roman이 아니라면, codePointioQueue에 복원하고, ISO-2022-JP 인코더 상태Roman으로 설정한 뒤, 세 바이트 0x1B 0x28 0x4A를 반환합니다.

  8. codePoint가 U+2212(−)라면, U+FF0D(-)로 설정합니다.

  9. codePoint가 U+FF61(。)~U+FF9F(゚) 범위라면, codePoint − 0xFF61에 해당하는 index code pointindex ISO-2022-JP katakana에서 찾아서 codePoint로 설정합니다.

  10. pointerindex pointer에서 codePoint에 해당하는 값으로 index jis0208에서 찾습니다.

    pointer가 null이 아니면 index jis0208의 특성상 8836 미만입니다.

  11. pointer가 null이면:

    1. ISO-2022-JP 인코더 상태jis0208이면, codePointioQueue에 복원하고, ISO-2022-JP 인코더 상태ASCII로 설정한 뒤, 세 바이트 0x1B 0x28 0x42를 반환합니다.

    2. 에러codePoint와 함께 반환합니다.

  12. ISO-2022-JP 인코더 상태jis0208이 아니라면, codePointioQueue에 복원하고, ISO-2022-JP 인코더 상태jis0208으로 설정한 뒤, 세 바이트 0x1B 0x24 0x42를 반환합니다.

  13. leadingpointer / 94 + 0x21로 둡니다.

  14. trailingpointer % 94 + 0x21로 둡니다.

  15. 값이 leadingtrailing인 두 바이트를 반환합니다.

12.3. Shift_JIS

12.3.1. Shift_JIS 디코더

Shift_JIS디코더Shift_JIS lead라는 바이트 값을 가지며, 초기값은 0x00입니다.

Shift_JIS디코더handlerioQueuebyte가 주어졌을 때 다음을 수행합니다:

  1. byteend-of-queue이고 Shift_JIS lead가 0x00이 아니면, Shift_JIS lead를 0x00으로 설정하고 에러를 반환합니다.

  2. byteend-of-queue이고 Shift_JIS lead가 0x00이면, finished를 반환합니다.

  3. Shift_JIS lead가 0x00이 아니면:

    1. leadingShift_JIS lead로 둡니다.

    2. Shift_JIS lead를 0x00으로 설정합니다.

    3. pointer를 null로 둡니다.

    4. offsetbyte가 0x7F 미만이면 0x40, 그 외에는 0x41로 둡니다.

    5. leadingOffsetleading이 0xA0 미만이면 0x81, 그렇지 않으면 0xC1로 둡니다.

    6. byte가 0x40~0x7E 또는 0x80~0xFC 범위라면, pointer를 (leadingleadingOffset) × 188 + byteoffset으로 설정합니다.

    7. pointer가 8836~10715 범위라면, 값이 0xE000 − 8836 + pointer인 코드 포인트를 반환합니다.

      이 값은 Windows의 EUDC와 연동되는 레거시 값입니다.

    8. codePointpointer가 null이면 null, 아니면 index code pointpointer에 해당하는 index jis0208의 값으로 둡니다.

    9. codePoint가 null이 아니면, 값이 codePoint인 코드 포인트를 반환합니다.

    10. byteASCII 바이트라면, byteioQueue에 복원합니다.

    11. 에러 반환

  4. byteASCII 바이트이거나 0x80이면, 값이 byte인 코드 포인트를 반환합니다.

  5. byte가 0xA1~0xDF 범위라면, 값이 0xFF61 − 0xA1 + byte인 코드 포인트를 반환합니다.

  6. byte가 0x81~0x9F 또는 0xE0~0xFC 범위라면, Shift_JIS leadbyte를 설정하고 continue를 반환합니다.

  7. 에러 반환

12.3.2. Shift_JIS 인코더

Shift_JIS인코더handlerunusedcodePoint가 주어졌을 때 다음을 수행합니다:

  1. codePointend-of-queue라면, finished를 반환합니다.

  2. codePointASCII 코드 포인트이거나 U+0080이면, 값이 codePoint인 바이트를 반환합니다.

  3. codePoint가 U+00A5(¥)라면, 바이트 0x5C을 반환합니다.

  4. codePoint가 U+203E(‾)라면, 바이트 0x7E을 반환합니다.

  5. codePoint가 U+FF61(。)~U+FF9F(゚) 범위라면, 값이 codePoint − 0xFF61 + 0xA1인 바이트를 반환합니다.

  6. codePoint가 U+2212(−)라면, U+FF0D(-)로 설정합니다.

  7. pointerindex Shift_JIS pointer에서 codePoint에 해당하는 값으로 둡니다.

  8. pointer가 null이면, 에러codePoint와 함께 반환합니다.

  9. leadingpointer / 188로 둡니다.

  10. leadingOffsetleading이 0x1F 미만이면 0x81, 그렇지 않으면 0xC1로 둡니다.

  11. trailingpointer % 188로 둡니다.

  12. offsettrailing이 0x3F 미만이면 0x40, 그 외에는 0x41로 둡니다.

  13. 값이 leading + leadingOffsettrailing + offset인 두 바이트를 반환합니다.

13. 레거시 다중 바이트 한글 인코딩

13.1. EUC-KR

13.1.1. EUC-KR 디코더

EUC-KR디코더EUC-KR lead라는 바이트 값을 가지며, 초기값은 0x00입니다.

EUC-KR디코더handlerioQueuebyte가 주어졌을 때 다음을 수행합니다:

  1. byteend-of-queue이고 EUC-KR lead가 0x00이 아니면, EUC-KR lead를 0x00으로 설정하고 에러를 반환합니다.

  2. byteend-of-queue이고 EUC-KR lead가 0x00이면, finished를 반환합니다.

  3. EUC-KR lead가 0x00이 아니면:

    1. leadingEUC-KR lead로 둡니다.

    2. EUC-KR lead를 0x00으로 설정합니다.

    3. pointer를 null로 둡니다.

    4. byte가 0x41~0xFE 범위라면 pointer를 (leading − 0x81) × 190 + (byte − 0x41)로 설정합니다.

    5. codePointpointer가 null이면 null, 아니면 index code pointpointer에 해당하는 index EUC-KR의 값으로 둡니다.

    6. codePoint가 null이 아니면, 값이 codePoint인 코드 포인트를 반환합니다.

    7. byteASCII 바이트라면, byteioQueue에 복원합니다.

    8. 에러 반환

  4. byteASCII 바이트라면, 값이 byte인 코드 포인트를 반환합니다.

  5. byte가 0x81~0xFE 범위라면, EUC-KR leadbyte를 설정하고 continue를 반환합니다.

  6. 에러 반환

13.1.2. EUC-KR 인코더

EUC-KR인코더handlerunusedcodePoint가 주어졌을 때 다음을 수행합니다:

  1. codePointend-of-queue라면, finished를 반환합니다.

  2. codePointASCII 코드 포인트라면, 값이 codePoint인 바이트를 반환합니다.

  3. pointerindex pointer에서 codePoint에 해당하는 값으로 index EUC-KR에서 찾습니다.

  4. pointer가 null이면, 에러codePoint와 함께 반환합니다.

  5. leadingpointer / 190 + 0x81로 둡니다.

  6. trailingpointer % 190 + 0x41로 둡니다.

  7. 값이 leadingtrailing인 두 바이트를 반환합니다.

14. 레거시 기타 인코딩

14.1. replacement

replacement 인코딩은 서버와 클라이언트에서 지원되는 인코딩이 불일치할 때 발생하는 특정 공격을 방지하기 위해 존재합니다.

14.1.1. replacement 디코더

replacement디코더replacement error returned라는 불리언 값을 가지며, 초기값은 false입니다.

replacement디코더handlerunusedbyte가 주어졌을 때 다음을 수행합니다:

  1. byteend-of-queue라면, finished를 반환합니다.

  2. replacement error returned가 false라면, replacement error returned를 true로 설정하고 에러를 반환합니다.

  3. finished를 반환합니다.

14.2. UTF-16BE/LE 공통 구조

UTF-16BE/LEUTF-16BE 또는 UTF-16LE입니다.

14.2.1. 공용 UTF-16 디코더

바이트 오더 마크는 레이블보다 우선하며, 실제 배포된 콘텐츠에서 더 정확한 것으로 나타났습니다. 따라서 공용 UTF-16 디코더 알고리즘의 일부가 아니라 decode 알고리즘의 일부입니다.

공용 UTF-16 디코더는 다음과 연관된 값을 가집니다:

UTF-16 lead 바이트
null 또는 바이트, 초기값은 null.
UTF-16 lead 서러게이트
null 또는 leading surrogate, 초기값은 null.
is UTF-16BE 디코더
불리언, 초기값은 false.

공용 UTF-16 디코더handlerioQueuebyte가 주어졌을 때 다음을 수행합니다:

  1. byteend-of-queue이고 UTF-16 lead 바이트 또는 UTF-16 lead 서러게이트가 null이 아니면, UTF-16 lead 바이트UTF-16 lead 서러게이트를 null로 설정하고 에러를 반환합니다.

  2. byteend-of-queue이고 UTF-16 lead 바이트UTF-16 lead 서러게이트가 모두 null이면, finished를 반환합니다.

  3. UTF-16 lead 바이트가 null이면, UTF-16 lead 바이트byte로 설정하고 continue를 반환합니다.

  4. codeUnit을 다음과 같이 둡니다:

    is UTF-16BE 디코더가 true

    (UTF-16 lead 바이트 << 8) + byte.

    is UTF-16BE 디코더가 false

    (byte << 8) + UTF-16 lead 바이트.

  5. UTF-16 lead 바이트를 null로 설정합니다.

  6. UTF-16 lead 서러게이트가 null이 아니면:

    1. leadingSurrogateUTF-16 lead 서러게이트로 둡니다.

    2. UTF-16 lead 서러게이트를 null로 설정합니다.

    3. codeUnittrailing surrogate라면, scalar value from surrogatesleadingSurrogatecodeUnit을 인수로 하여 반환합니다.

    4. byte1codeUnit >> 8로 둡니다.

    5. byte2codeUnit & 0x00FF로 둡니다.

    6. bytes리스트로, is UTF-16BE 디코더가 true면 byte1, byte2, 아니면 byte2, byte1 두 개의 바이트로 둡니다.

    7. bytesioQueue에 복원하고 에러를 반환합니다.

  7. codeUnitleading surrogate라면, UTF-16 lead 서러게이트codeUnit으로 설정하고 continue를 반환합니다.

  8. codeUnittrailing surrogate라면, 에러를 반환합니다.

  9. 코드 포인트 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-16LElabel입니다.

14.4.1. UTF-16LE 디코더

UTF-16LE디코더공용 UTF-16 디코더입니다.

14.5. x-user-defined

기술적으로는 단일 바이트 인코딩이지만, 알고리즘적으로 구현이 가능하므로 별도로 정의됩니다.

14.5.1. x-user-defined 디코더

x-user-defined디코더handlerunusedbyte가 주어졌을 때 다음을 수행합니다:

  1. byteend-of-queue라면, finished를 반환합니다.

  2. byteASCII 바이트라면, 값이 byte인 코드 포인트를 반환합니다.

  3. 값이 0xF780 + byte − 0x80인 코드 포인트를 반환합니다.

14.5.2. x-user-defined 인코더

x-user-defined인코더handlerunusedcodePoint가 주어졌을 때 다음을 수행합니다:

  1. codePointend-of-queue라면, finished를 반환합니다.

  2. codePointASCII 코드 포인트라면, 값이 codePoint인 바이트를 반환합니다.

  3. codePoint가 U+F780~U+F7FF 범위에 있다면, 값이 codePoint − 0xF780 + 0x80인 바이트를 반환합니다.

  4. 에러codePoint와 함께 반환합니다.

15. 브라우저 UI

브라우저는 리소스의 인코딩을 재정의하는 기능을 활성화하지 않도록 권장됩니다. 만약 이러한 기능이 존재한다면, 위에서 언급한 보안상의 이유로 UTF-16BE/LE을 옵션으로 제공하지 않아야 합니다. 또한 리소스가 UTF-16BE/LE로 디코딩된 경우에는 이 기능을 비활성화해야 합니다.

구현 관련 고려사항

이 표준의 인코딩에 대한 디코더는 임의의 I/O 큐복원 기능을 지원하는 대신 다음과 같이 구현할 수 있습니다:

  1. 현재 바이트를 읽지 않은 상태로 되돌리는 기능.

  2. gb18030(ASCII 바이트)와 ISO-2022-JP(0x24 또는 0x28)를 위한 단일 바이트 버퍼.

    gb18030에서 gb18030 third가 0x00이 아닐 때 잘못된 바이트를 만난 경우, gb18030 second를 단일 바이트 버퍼로 옮겨 다음에 반환하고, gb18030 third가 새 gb18030 first가 되며, 단일 바이트 버퍼가 반환되어 비워진 후 0x00이 아님을 체크할 수 있습니다. gb18030에서 첫 번째와 세 번째 바이트의 범위가 동일하기 때문에 가능합니다.

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가 적용됩니다.

이 문서는 현행 표준입니다. 특허 검토 버전을 원하는 경우 현행 표준 검토 초안을 참고하세요.

색인

이 명세에서 정의된 용어

참조로 정의된 용어

참고 문헌

규범적 참고 문헌

[ECMASCRIPT]
ECMAScript Language Specification. URL: https://tc39.es/ecma262/multipage/
[HTML]
Anne van Kesteren; et al. HTML Standard. 현행 표준. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. 현행 표준. URL: https://infra.spec.whatwg.org/
[STREAMS]
Adam Rice; et al. Streams Standard. 현행 표준. URL: https://streams.spec.whatwg.org/
[UNICODE]
The Unicode Standard. URL: https://www.unicode.org/versions/latest/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. 현행 표준. URL: https://webidl.spec.whatwg.org/

비규범적 참고 문헌

[ISO646]
Information technology — ISO 7-bit coded character set for information interchange. 1991년 12월. 발행됨. URL: https://www.iso.org/standard/4777.html
[ISO8859-1]
Information technology — 8-bit single-byte coded graphic character sets — Part 1: Latin alphabet No. 1. 1998년 4월. 발행됨. URL: https://www.iso.org/standard/28245.html
[URL]
Anne van Kesteren. URL Standard. 현행 표준. URL: https://url.spec.whatwg.org/
[XML]
Tim Bray; et al. Extensible Markup Language (XML) 1.0 (Fifth Edition). 2008년 11월 26일. REC. URL: https://www.w3.org/TR/xml/

IDL 색인

interface mixin TextDecoderCommon {
  readonly attribute DOMString encoding;
  readonly attribute boolean fatal;
  readonly attribute boolean ignoreBOM;
};

dictionary TextDecoderOptions {
  boolean fatal = false;
  boolean ignoreBOM = false;
};

dictionary TextDecodeOptions {
  boolean stream = false;
};

[Exposed=*]
interface TextDecoder {
  constructor(optional DOMString label = "utf-8", optional TextDecoderOptions options = {});

  USVString decode(optional AllowSharedBufferSource input, optional TextDecodeOptions options = {});
};
TextDecoder includes TextDecoderCommon;

interface mixin TextEncoderCommon {
  readonly attribute DOMString encoding;
};

dictionary TextEncoderEncodeIntoResult {
  unsigned long long read;
  unsigned long long written;
};

[Exposed=*]
interface TextEncoder {
  constructor();

  [NewObject] Uint8Array encode(optional USVString input = "");
  TextEncoderEncodeIntoResult encodeInto(USVString source, [AllowShared] Uint8Array destination);
};
TextEncoder includes TextEncoderCommon;

[Exposed=*]
interface TextDecoderStream {
  constructor(optional DOMString label = "utf-8", optional TextDecoderOptions options = {});
};
TextDecoderStream includes TextDecoderCommon;
TextDecoderStream includes GenericTransformStream;

[Exposed=*]
interface TextEncoderStream {
  constructor();
};
TextEncoderStream includes TextEncoderCommon;
TextEncoderStream includes GenericTransformStream;

MDN

TextDecoder/TextDecoder

In all current engines.

Firefox19+Safari10.1+Chrome38+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js11.0.0+
MDN

TextDecoder/decode

In all current engines.

Firefox19+Safari10.1+Chrome38+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js11.0.0+
MDN

TextDecoder/encoding

In all current engines.

Firefox19+Safari10.1+Chrome38+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js8.3.0+
MDN

TextDecoder/fatal

In all current engines.

Firefox36+Safari10.1+Chrome38+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js8.3.0+
MDN

TextDecoder/ignoreBOM

In all current engines.

Firefox63+Safari10.1+Chrome38+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js8.3.0+
MDN

TextDecoder

In all current engines.

Firefox19+Safari10.1+Chrome38+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js11.0.0+
MDN

TextDecoderStream/TextDecoderStream

In all current engines.

Firefox105+Safari14.1+Chrome71+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js16.6.0+
MDN

TextDecoderStream/encoding

In all current engines.

Firefox105+Safari14.1+Chrome71+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js16.6.0+
MDN

TextDecoderStream/fatal

In all current engines.

Firefox105+Safari14.1+Chrome71+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js16.6.0+
MDN

TextDecoderStream/ignoreBOM

In all current engines.

Firefox105+Safari14.1+Chrome71+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js16.6.0+
MDN

TextDecoderStream

In all current engines.

Firefox105+Safari14.1+Chrome71+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js18.0.0+
MDN

TextEncoder/TextEncoder

In all current engines.

Firefox18+Safari10.1+Chrome38+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js11.0.0+
MDN

TextEncoder/encode

In all current engines.

Firefox18+Safari10.1+Chrome38+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js8.3.0+
MDN

TextEncoder/encodeInto

In all current engines.

Firefox66+Safari14.1+Chrome74+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile50+
Node.js12.11.0+
MDN

TextEncoder/encoding

In all current engines.

Firefox18+Safari10.1+Chrome38+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js8.3.0+

TextEncoderStream/encoding

In all current engines.

Firefox105+Safari14.1+Chrome71+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js16.6.0+
MDN

TextEncoder

In all current engines.

Firefox18+Safari10.1+Chrome38+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js11.0.0+
MDN

TextEncoderStream/TextEncoderStream

In all current engines.

Firefox105+Safari14.1+Chrome71+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js16.6.0+
MDN

TextEncoderStream

In all current engines.

Firefox105+Safari14.1+Chrome71+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js18.0.0+