# 機能設計書 184-UTF-16/WTF-8変換

## 概要

本ドキュメントは、UTF-16とWTF-8間の文字コード変換を行う4つのAPI（`uv_utf16_length_as_wtf8()`、`uv_utf16_to_wtf8()`、`uv_wtf8_length_as_utf16()`、`uv_wtf8_to_utf16()`）の機能設計について記述する。これらの関数は、主にWindows環境でのワイド文字列（UTF-16）とlibuv内部で使用するWTF-8文字列間の変換を提供する。

### 本機能の処理概要

**業務上の目的・背景**：Windows APIはUTF-16（ワイド文字列）を使用するが、libuvのAPIはUTF-8ベースの文字列を使用する。両者の間の変換が必要となるが、標準のUTF-8ではサロゲートペアの片側（孤立サロゲート）を表現できない。WTF-8（Wobbly Transformation Format - 8-bit）はUTF-8のスーパーセットであり、孤立サロゲートも表現可能な形式である。これにより、Windowsのファイルパスなど不正なUTF-16文字列をロスレスで変換・復元できる。

**機能の利用シーン**：
- Windowsファイルシステム操作でのパス名変換
- Windows DNS解決関数でのホスト名変換
- Windowsプロセス操作での引数・環境変数の変換
- WindowsTTY操作での文字列変換
- 動的ライブラリのパス名変換

**主要な処理内容**：
1. `uv_utf16_length_as_wtf8()`: UTF-16文字列をWTF-8に変換した場合の必要バイト数を計算
2. `uv_utf16_to_wtf8()`: UTF-16文字列をWTF-8文字列に変換（メモリ自動確保対応）
3. `uv_wtf8_length_as_utf16()`: WTF-8文字列をUTF-16に変換した場合の必要ワード数を計算
4. `uv_wtf8_to_utf16()`: WTF-8文字列をUTF-16文字列に変換

**関連システム・外部連携**：主にWindows API（ファイルシステム、DNS、プロセス、TTY関連）とlibuvの内部文字列処理の橋渡しとして使用される。

**権限による制御**：なし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 29 | その他ユーティリティ | 主機能 | uv_utf16_to_wtf8()/wtf8_to_utf16()等の文字コード変換のAPI定義 |

## 機能種別

データ変換処理（文字コード変換）

## 入力仕様

### 入力パラメータ

#### uv_utf16_length_as_wtf8()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| utf16 | const uint16_t* | Yes | UTF-16入力文字列 | NULLチェックなし |
| utf16_len | ssize_t | Yes | UTF-16文字列の長さ（負の値の場合はNUL終端まで読む） | なし |

#### uv_utf16_to_wtf8()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| utf16 | const uint16_t* | Yes | UTF-16入力文字列 | NULLチェックなし |
| utf16_len | ssize_t | Yes | UTF-16文字列の長さ（負の値の場合はNUL終端まで読む） | なし |
| wtf8_ptr | char** | No | WTF-8出力バッファのポインタへのポインタ | NULLの場合は長さ計算のみ |
| wtf8_len_ptr | size_t* | No | WTF-8出力バッファの長さへのポインタ | *wtf8_ptrがNULLの場合は計算結果の格納先 |

#### uv_wtf8_length_as_utf16()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| wtf8 | const char* | Yes | WTF-8入力文字列（NUL終端） | NULLチェックなし |

#### uv_wtf8_to_utf16()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| wtf8 | const char* | Yes | WTF-8入力文字列（NUL終端） | NULLチェックなし |
| utf16 | uint16_t* | Yes | UTF-16出力バッファ | NULLチェックなし |
| utf16_len | size_t | Yes | UTF-16出力バッファのワード数 | assertで0チェック |

### 入力データソース

呼び出し元プログラムが提供する文字列データ。主にWindows API経由で取得されたUTF-16文字列、またはlibuvの内部WTF-8文字列。

## 出力仕様

### 出力データ

#### uv_utf16_length_as_wtf8()

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | size_t | WTF-8変換後の必要バイト数（NUL終端を含まない） |

#### uv_utf16_to_wtf8()

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | int | 成功時は0、メモリ不足でUV_ENOMEM、バッファ不足でUV_ENOBUFS |
| *wtf8_ptr | char* | 変換されたWTF-8文字列（NUL終端付き） |
| *wtf8_len_ptr | size_t | WTF-8文字列の長さ（NUL終端を含まない） |

#### uv_wtf8_length_as_utf16()

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | ssize_t | UTF-16変換後の必要ワード数（NUL終端含む）、エラー時は-1 |

#### uv_wtf8_to_utf16()

| 項目名 | 型 | 説明 |
|--------|-----|------|
| （なし） | void | 出力はutf16バッファに直接書き込まれる |

### 出力先

呼び出し元に提供されたバッファ、または自動確保されたメモリ。

## 処理フロー

### 処理シーケンス

```
=== uv_utf16_length_as_wtf8() ===
1. 入力UTF-16文字列を走査
   └─ 各UTF-16コードユニットのサロゲートペア判定
2. WTF-8としてエンコードした場合のバイト数を計算
   └─ U+0000-U+007F: 1バイト
   └─ U+0080-U+07FF: 2バイト
   └─ U+0800-U+FFFF: 3バイト（サロゲート含む）
   └─ U+10000-U+10FFFF: 4バイト（サロゲートペア消費）
3. 合計バイト数を返却

=== uv_utf16_to_wtf8() ===
1. バッファ判定
   └─ target_ptrがNULLまたは*target_ptrがNULLの場合、必要長を計算
2. メモリ確保（必要な場合）
   └─ *target_ptrがNULLの場合、uv__mallocで確保
3. UTF-16からWTF-8へのコードポイント変換
   └─ サロゲートペアを処理し、WTF-8バイト列をターゲットバッファに書き込み
4. NUL終端の付加
5. バッファ不足チェック

=== uv_wtf8_length_as_utf16() ===
1. WTF-8文字列をデコード
   └─ uv__wtf8_decode1()で1コードポイントずつ読み取り
2. UTF-16としてエンコードした場合のワード数を計算
   └─ U+10000以上: 2ワード（サロゲートペア）
   └─ それ以外: 1ワード
3. NUL終端分を含めたワード数を返却

=== uv_wtf8_to_utf16() ===
1. WTF-8文字列を1コードポイントずつデコード
   └─ uv__wtf8_decode1()で読み取り
2. UTF-16にエンコードして出力バッファに書き込み
   └─ U+10000以上: サロゲートペアとして2ワード書き込み
   └─ それ以外: 1ワード書き込み
3. NUL終端の書き込み
```

### フローチャート

```mermaid
flowchart TD
    A[開始: uv_utf16_to_wtf8] --> B{target_ptr == NULL<br/>OR *target_ptr == NULL?}
    B -->|Yes| C[uv_utf16_length_as_wtf8で<br/>必要長を計算]
    B -->|No| D[target_len = *target_len_ptr]
    C --> E{target_ptr == NULL?}
    E -->|Yes| F[0を返す<br/>長さ計算のみ]
    E -->|No| G[uv__mallocでメモリ確保]
    G --> H{確保成功?}
    H -->|No| I[UV_ENOMEMを返す]
    H -->|Yes| J[変換処理実行]
    D --> J
    J --> K[UTF-16 -> WTF-8変換ループ]
    K --> L[NUL終端付加]
    L --> M{バッファ不足?}
    M -->|Yes| N[UV_ENOBUFSを返す]
    M -->|No| O[0を返す]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-184-1 | サロゲートペア処理 | 正しいサロゲートペア（High + Low）は単一のコードポイント（U+10000-U+10FFFF）に変換される | サロゲートペア検出時 |
| BR-184-2 | 孤立サロゲート許容 | WTF-8では孤立サロゲートも3バイトとしてエンコードされる（UTF-8との差異） | 孤立サロゲート検出時 |
| BR-184-3 | NUL終端文字列 | utf16_lenが負の場合はNUL終端までを入力とする | utf16_len < 0 |
| BR-184-4 | 自動メモリ確保 | uv_utf16_to_wtf8()でtarget_ptrのポイント先がNULLの場合、内部でメモリを確保する | *target_ptr == NULL |
| BR-184-5 | バッファ不足通知 | 提供されたバッファが不足する場合、必要サイズをtarget_len_ptrに設定してUV_ENOBUFSを返す | バッファ不足時 |

### 計算ロジック

**WTF-8エンコーディングのバイト数算出**:
- コードポイント 0x0000-0x007F: 1バイト
- コードポイント 0x0080-0x07FF: 2バイト
- コードポイント 0x0800-0xFFFF: 3バイト（孤立サロゲートを含む）
- コードポイント 0x10000-0x10FFFF: 4バイト

**サロゲートペアのデコード**:
- `code_point = 0x10000 + ((high_surrogate - 0xD800) << 10) + (low_surrogate - 0xDC00)`
- High surrogate: 0xD800-0xDBFF
- Low surrogate: 0xDC00-0xDFFF

## データベース操作仕様

### 操作別データベース影響一覧

該当なし（データベースを使用しない）。

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_ENOMEM | メモリ不足 | uv_utf16_to_wtf8()で自動メモリ確保に失敗 | メモリを解放してリトライ、または事前確保バッファを使用 |
| UV_ENOBUFS | バッファ不足 | uv_utf16_to_wtf8()で提供バッファが不足 | target_len_ptrの値を参照してバッファを再確保 |
| -1 | 不正入力 | uv_wtf8_length_as_utf16()で不正なWTF-8を検出 | 入力文字列の妥当性を確認 |

### リトライ仕様

UV_ENOBUFS発生時は`*target_len_ptr`に格納された必要サイズのバッファを用意して再呼び出しする。

## トランザクション仕様

該当なし。各関数はステートレスであり、スレッドセーフ（自動メモリ確保を除く）。

## パフォーマンス要件

各関数の処理時間は入力文字列の長さに線形（O(n)）。`uv_utf16_to_wtf8()`でtarget_ptrの指す先がNULLの場合、長さ計算と変換で入力を2回走査する。

## セキュリティ考慮事項

- WTF-8はUTF-8のスーパーセットであるため、WTF-8文字列を通常のUTF-8として解釈するライブラリに渡す場合は注意が必要
- サロゲートペアのバリデーション不備により、不正なコードポイントが生成される可能性がある（assertで検出）
- `uv_utf16_to_wtf8()`の自動メモリ確保はカスタムアロケータ経由（`uv__malloc`）で行われる

## 備考

- WTF-8（Wobbly Transformation Format - 8-bit）はUTF-8のスーパーセットで、孤立サロゲートもエンコード可能
- 主にWindows API連携で使用される（Windows API はUTF-16を使用するため）
- `uv__wtf8_decode1()`（src/idna.c:28-68）はWTF-8文字列から1コードポイントを読み取る内部関数
- `uv__get_surrogate_value()`（src/idna.c:412-424）はUTF-16のサロゲートペアを処理する内部関数
- 正しいUTF-16文字列の場合、WTF-8とUTF-8は同一の結果となる

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

UTF-16とWTF-8の文字コードエンコーディングの基本を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | 4つのAPI関数の宣言と引数・戻り値の型を理解する（1962-1971行目） |

**読解のコツ**: UTF-16はWindows APIで使用される16ビットエンコーディングで、Basic Multilingual Plane外のコードポイントはサロゲートペア（High: 0xD800-0xDBFF, Low: 0xDC00-0xDFFF）で表現される。WTF-8はUTF-8の拡張で、孤立サロゲート（ペアにならないサロゲート値）もエンコードできる点が特徴。

#### Step 2: 内部ヘルパー関数を理解する

変換処理の基盤となる内部関数を読み解く。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | idna.c | `src/idna.c` | uv__wtf8_decode1()によるWTF-8デコード処理（28-68行目） |
| 2-2 | idna.c | `src/idna.c` | uv__get_surrogate_value()によるサロゲートペア処理（412-424行目） |

**主要処理フロー**:
- **28-68行目**: `uv__wtf8_decode1()` - WTF-8バイト列から1コードポイントをデコード
  - **36-37行目**: ASCIIコードポイント（1バイト、0x00-0x7F）の処理
  - **38-39行目**: 無効な継続バイトの検出
  - **42-47行目**: 2バイト文字（0xC2-0xDF）の処理
  - **49-54行目**: 3バイト文字（0xE0-0xEF）の処理
  - **56-63行目**: 4バイト文字（0xF0-0xF4）の処理
- **412-424行目**: `uv__get_surrogate_value()` - UTF-16からサロゲートペアを検出し、コードポイントを計算
  - **418-419行目**: High surrogate (0xD800-0xDBFF)の検出
  - **420行目**: Low surrogate (0xDC00-0xDFFF)の検出
  - **421行目**: サロゲートペアからコードポイントの計算

#### Step 3: UTF-16 -> WTF-8 変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | idna.c | `src/idna.c` | uv_utf16_length_as_wtf8()の実装（427-457行目） |
| 3-2 | idna.c | `src/idna.c` | uv_utf16_to_wtf8()の実装（460-560行目） |

**主要処理フロー（uv_utf16_length_as_wtf8）**:
- **432行目**: target_len = 0 で初期化
- **433行目**: w_source_lenが0でない間ループ
- **434行目**: `uv__get_surrogate_value()`で次のコードポイントを取得
- **437-438行目**: NUL終端処理（w_source_len < 0 の場合）
- **439-453行目**: コードポイント範囲に基づくバイト数加算（1/2/3/4バイト）

**主要処理フロー（uv_utf16_to_wtf8）**:
- **473-479行目**: ターゲットバッファの判定（NULLなら長さを計算）
- **481-482行目**: target_ptrがNULLなら長さ計算のみで0を返す
- **484-489行目**: *target_ptrがNULLならuv__mallocでメモリ確保
- **496-539行目**: UTF-16 -> WTF-8 変換ループ（コードポイント範囲ごとのエンコーディング）
- **550行目**: NUL終端付加
- **553-557行目**: バッファ不足の場合、残りの長さを計算してUV_ENOBUFS返却

#### Step 4: WTF-8 -> UTF-16 変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | idna.c | `src/idna.c` | uv_wtf8_length_as_utf16()の実装（370-384行目） |
| 4-2 | idna.c | `src/idna.c` | uv_wtf8_to_utf16()の実装（387-409行目） |

**主要処理フロー（uv_wtf8_length_as_utf16）**:
- **374-381行目**: WTF-8デコードループ
  - **375行目**: `uv__wtf8_decode1()`で1コードポイントずつデコード
  - **376-377行目**: デコードエラーで-1を返す
  - **378-379行目**: U+10000以上は2ワード（サロゲートペア）
  - **380行目**: それ以外は1ワード

**主要処理フロー（uv_wtf8_to_utf16）**:
- **392-405行目**: WTF-8デコード＋UTF-16エンコードループ
  - **393行目**: `uv__wtf8_decode1()`でデコード
  - **396-400行目**: U+10000以上のコードポイントをサロゲートペアにエンコード
  - **402行目**: BMP内のコードポイントは直接書き込み
- **408行目**: assertで出力バッファが正確に消費されたことを確認

### プログラム呼び出し階層図

```
uv_utf16_length_as_wtf8()               [src/idna.c:427-457]
    +-- uv__get_surrogate_value()         [src/idna.c:412-424]

uv_utf16_to_wtf8()                      [src/idna.c:460-560]
    +-- uv_utf16_length_as_wtf8()         [src/idna.c:427-457] (長さ計算時)
    |      +-- uv__get_surrogate_value()
    +-- uv__malloc()                      [src/uv-common.c:75-79] (自動確保時)
    +-- uv__get_surrogate_value()         [src/idna.c:412-424] (変換時)

uv_wtf8_length_as_utf16()               [src/idna.c:370-384]
    +-- uv__wtf8_decode1()                [src/idna.c:28-68]

uv_wtf8_to_utf16()                      [src/idna.c:387-409]
    +-- uv__wtf8_decode1()                [src/idna.c:28-68]
```

### データフロー図

```
[UTF-16 -> WTF-8 変換]

UTF-16文字列        uv_utf16_length_as_wtf8()     WTF-8バイト数
(uint16_t[]) -----> uv__get_surrogate_value() --> (size_t)
                    コードポイント変換

UTF-16文字列        uv_utf16_to_wtf8()             WTF-8文字列
(uint16_t[]) -----> uv__get_surrogate_value() --> (char*)
   utf16_len        コードポイント -> WTF-8          + NUL終端
                    エンコード

[WTF-8 -> UTF-16 変換]

WTF-8文字列         uv_wtf8_length_as_utf16()     UTF-16ワード数
(const char*) ----> uv__wtf8_decode1()        --> (ssize_t)
                    コードポイントデコード

WTF-8文字列         uv_wtf8_to_utf16()             UTF-16文字列
(const char*) ----> uv__wtf8_decode1()        --> (uint16_t*)
                    コードポイント -> UTF-16         + NUL終端
                    エンコード（サロゲートペア生成）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダー | 4つのAPI関数の宣言（1962-1971行目） |
| idna.c | `src/idna.c` | ソース | 全4関数の実装およびヘルパー関数（28-560行目） |
| uv-common.c | `src/uv-common.c` | ソース | uv__malloc()（自動メモリ確保用、75-79行目） |
| dl.c | `src/win/dl.c` | ソース | Windows動的ライブラリでの利用箇所 |
| fs.c | `src/win/fs.c` | ソース | Windowsファイルシステムでの利用箇所 |
| getaddrinfo.c | `src/win/getaddrinfo.c` | ソース | Windows DNSでの利用箇所 |
| process.c | `src/win/process.c` | ソース | Windowsプロセス操作での利用箇所 |
| tty.c | `src/win/tty.c` | ソース | Windows TTY操作での利用箇所 |
| util.c | `src/win/util.c` | ソース | Windowsユーティリティでの利用箇所 |
