# 機能設計書 44-UTF7Encoding

## 概要

本ドキュメントは、VBCorLibライブラリにおけるUTF-7エンコーディング機能「UTF7Encoding」クラスの機能設計について記述する。

### 本機能の処理概要

UTF7Encodingクラスは、Unicode文字をUTF-7形式のバイト配列に変換（エンコード）、およびUTF-7形式のバイト配列をUnicode文字に変換（デコード）する機能を提供する。UTF-7は7ビットASCII互換のエンコーディングであり、ASCII文字は直接エンコードされ、非ASCII文字は修正Base64でエンコードされる。

**業務上の目的・背景**：UTF-7は7ビットのみを使用するため、8ビット透過でないメールシステムやプロトコルでUnicode文字を安全に転送できる。主にSMTP/IMAPなどのレガシーメールシステムで使用されていた。

**機能の利用シーン**：
- レガシーメールシステムでの国際文字送受信
- 7ビット制限のあるプロトコルでのデータ転送
- 古いシステムとの互換性維持

**主要な処理内容**：
1. 直接エンコード可能文字（ASCII文字サブセット）はそのまま出力
2. 非ASCII文字は修正Base64でエンコード
3. "+"文字のエスケープ処理（"+-"で表現）
4. オプション文字の直接エンコード許可/禁止制御

**関連システム・外部連携**：EncodingStaticクラスを通じて取得可能。UTF7Encoder/UTF7Decoderクラスによるストリーム処理をサポート。

**権限による制御**：本機能には権限による制御は存在しない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能は画面からの直接操作を持たない |

## 機能種別

データ変換処理 / テキストエンコーディング

## 入力仕様

### 入力パラメータ（エンコード処理）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Chars | Integer() または String | Yes | エンコード対象の文字配列/文字列 | 初期化済み配列または有効な文字列 |
| Index | Long | No | 開始インデックス（0ベース） | 有効な配列範囲内 |
| Count | Long | No | 処理文字数 | 0以上、配列範囲内 |

### 入力パラメータ（デコード処理）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Bytes | Byte() | Yes | デコード対象のバイト配列 | 初期化済み配列 |
| Index | Long | No | 開始インデックス（0ベース） | 有効な配列範囲内 |
| Count | Long | No | 処理バイト数 | 0以上、配列範囲内 |

### コンストラクタパラメータ

| パラメータ名 | 型 | 必須 | 説明 | デフォルト値 |
|-------------|-----|-----|------|-------------|
| AllowOptionals | Boolean | No | オプション文字を直接エンコードするか | False |

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| GetBytes戻り値 | Byte() | UTF-7エンコードされたバイト配列 |
| GetChars戻り値 | Integer() | デコードされたUnicode文字配列 |
| GetString戻り値 | String | デコードされたUnicode文字列 |
| GetByteCount戻り値 | Long | エンコードに必要なバイト数 |
| GetCharCount戻り値 | Long | デコードで生成される文字数 |
| GetPreamble戻り値 | Byte() | 常に空配列（UTF-7にBOMはない） |

### UTF-7エンコーディング規則

```
直接エンコード可能文字:
  Tab, LF, CR, Space, '(),-./0-9:?A-Za-z

オプション文字（AllowOptionals=True時に直接エンコード）:
  !"#$%&*;<=>@[]^_`{|}

修正Base64エンコード:
  - "+"で開始、"-"で終了
  - Base64文字: A-Za-z0-9+/
  - 文字"+"は"+-"でエスケープ
```

## 処理フロー

### 処理シーケンス

```
1. インスタンス生成
   └─ 直接エンコード可能文字テーブルの初期化
   └─ AllowOptionals設定時はオプション文字も追加
2. エンコード処理 (GetBytes)
   └─ 直接エンコード可能文字: そのまま出力
   └─ "+"文字: "+-"で出力
   └─ その他: 修正Base64でエンコード
       ├─ "+"で開始
       ├─ 16ビット文字を6ビット単位でBase64変換
       └─ "-"で終了
3. デコード処理 (GetString/GetChars)
   └─ 通常文字: そのまま出力
   └─ "+"検出: 修正Base64デコード開始
       ├─ "-"検出: デコード終了
       ├─ "+-": "+"文字として出力
       └─ Base64文字: 6ビット単位で16ビット文字に復元
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{処理種別}
    B -->|エンコード| C[文字ループ開始]
    C --> D{直接エンコード可能?}
    D -->|Yes| E{Base64モード中?}
    E -->|Yes| F[Base64終了処理]
    F --> G[文字出力]
    E -->|No| G
    D -->|No| H{"+"文字?}
    H -->|Yes| I{Base64モード中?}
    I -->|Yes| J[Base64に追加]
    I -->|No| K["+-"出力]
    H -->|No| L{Base64モード中?}
    L -->|Yes| M[Base64に追加]
    L -->|No| N["+"出力しBase64開始]
    N --> M
    G --> O{次の文字?}
    J --> O
    K --> O
    M --> O
    O -->|Yes| C
    O -->|No| P[Base64終了処理]
    P --> Q[バイト配列返却]
    B -->|デコード| R[バイトループ開始]
    R --> S{Base64モード中?}
    S -->|No| T{"+"検出?}
    T -->|Yes| U[Base64モード開始]
    T -->|No| V[文字出力]
    S -->|Yes| W{"-"検出?}
    W -->|Yes| X{直前が"+"?}
    X -->|Yes| Y["+"文字出力]
    X -->|No| Z[Base64モード終了]
    W -->|No| AA{Base64文字?}
    AA -->|Yes| AB[6ビット蓄積]
    AA -->|No| AC[フォールバック]
    AB --> AD{16ビット蓄積?}
    AD -->|Yes| AE[文字出力]
    V --> AF{次のバイト?}
    U --> AF
    Y --> AF
    Z --> AF
    AE --> AF
    AC --> AF
    AF -->|Yes| R
    AF -->|No| AG[文字列返却]
    Q --> AH[終了]
    AG --> AH
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 直接エンコード | Tab/LF/CR/Space/'(),-./0-9:?A-Za-zはそのまま出力 | エンコード時 |
| BR-002 | オプション文字 | AllowOptionals=Trueで!"#$%&*;<=>@[]^_`{&#124;}も直接出力可能 | エンコード時 |
| BR-003 | Plus文字エスケープ | "+"文字は"+-"としてエスケープ | エンコード時 |
| BR-004 | 修正Base64 | 非直接エンコード文字は"+"で開始、"-"で終了するBase64でエンコード | エンコード時 |
| BR-005 | BOMなし | GetPreambleは常に空配列を返す | GetPreamble呼び出し時 |
| BR-006 | コードページ | CodePageは常に65000を返す | CodePage取得時 |

### 計算ロジック

```
GetMaxByteCount(CharCount) = CharCount * 3 + 2
GetMaxCharCount(ByteCount) = ByteCount (ByteCount > 0), 1 (ByteCount = 0)
```

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentNullException | Bytes/Chars配列が未初期化 | 配列を初期化してから呼び出し |
| - | ArgumentOutOfRangeException | Index/Countが配列範囲外 | 有効な範囲を指定 |
| - | ArgumentOutOfRangeException | CharCount/ByteCountが負の値 | 0以上の値を指定 |
| - | DecoderFallbackException | 不正バイト（ExceptionFallback設定時） | フォールバック設定変更またはデータ修正 |
| - | ArgumentException | 出力バッファが小さすぎる | 十分なサイズのバッファを確保 |
| - | InvalidOperationException | 読み取り専用インスタンスのフォールバック設定変更 | Cloneで書き込み可能なコピーを作成 |

### リトライ仕様

データ変換処理であるため、リトライは不要。

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

本機能はトランザクション処理を行わない。

## パフォーマンス要件

- ASCII文字のみのテキスト: 高速（直接エンコード）
- 非ASCII文字を含むテキスト: Base64変換のため比較的低速
- 数KB程度のテキスト変換: 数ミリ秒以内

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

- UTF-7はセキュリティ上の問題（XSS攻撃等）の原因となる可能性があるため、Webアプリケーションでの使用は非推奨
- 不正なUTF-7シーケンスはフォールバック処理で対応
- レガシーシステムとの互換性のみに使用を限定することを推奨

## 備考

- UTF-7はRFC 2152で定義されている
- 現代のシステムではUTF-8の使用が推奨される
- UTF-7には標準のBOMが存在しない
- メールのMIME Content-Transfer-Encodingとは異なる独自のBase64変種を使用

---

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

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

### 推奨読解順序

#### Step 1: データ構造とクラス定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | UTF7Encoding.cls | `Source/CorLib/System.Text/UTF7Encoding.cls` | クラス定義、プライベート変数（56-61行目） |

**読解のコツ**:
- 53行目: EncodableCharacters - 直接エンコード可能な文字セット
- 54行目: OptionalCharacters - オプションで直接エンコード可能な文字セット
- 57行目: mDirectlyEncodable(0 To 127) - 直接エンコード判定用のルックアップテーブル

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | UTF7Encoding.cls | `Source/CorLib/System.Text/UTF7Encoding.cls` | 公開メソッド（GetBytes、GetChars、GetString等） |

**主要処理フロー**:
1. **248-265行目**: GetByteCountメソッド - エンコードに必要なバイト数計算
2. **278-298行目**: GetBytesメソッド - 文字→バイト配列変換
3. **315-330行目**: GetBytesExメソッド - 既存バッファへのエンコード
4. **367-373行目**: GetCharCountメソッド - デコードで生成される文字数計算
5. **383-392行目**: GetCharsメソッド - バイト→文字配列変換
6. **340-357行目**: GetStringメソッド - バイト→文字列変換
7. **448-450行目**: GetPreambleメソッド - 空配列を返す（BOMなし）
8. **180-182行目**: CodePageプロパティ - 65000を返す

#### Step 3: コア処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | UTF7Encoding.cls | `Source/CorLib/System.Text/UTF7Encoding.cls` | GetBytesCore/GetCharsCore（内部処理） |

**主要処理フロー**:
- **564-688行目**: GetBytesCore - 文字→バイト変換の実装
  - 586-616行目: 直接エンコード可能文字の処理
  - 618-651行目: 非直接エンコード文字の修正Base64処理
  - 619-625行目: "+"文字の"+-"エスケープ
  - 639-647行目: 16ビット文字を6ビット単位でBase64変換
- **690-760行目**: GetByteCountCore - エンコードバイト数計算
- **762-815行目**: GetCharCountCore - デコード文字数計算
- **833-948行目**: GetCharsCore - バイト→文字変換の実装
  - 860-891行目: "+"/"-"文字の処理
  - 892-909行目: Base64文字の処理
  - 920-927行目: 6ビット蓄積→16ビット文字復元

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

```
UTF7Encoding
    │
    ├─ GetBytes(Chars)
    │      ├─ AsChars(): 文字配列変換
    │      ├─ ValidateGetBytes(): バリデーション
    │      ├─ GetByteCountCore(): バイト数計算
    │      │      ├─ 直接エンコード判定 (mDirectlyEncodable)
    │      │      └─ 修正Base64バイト数計算
    │      └─ GetBytesCore(): エンコード実行
    │             ├─ 直接エンコード文字: そのまま出力
    │             ├─ "+"文字: "+-"出力
    │             └─ 非直接文字: 修正Base64
    │                   ├─ Base64Bytes(): ビット→Base64文字
    │                   └─ Powers(): シフト演算
    │
    ├─ GetString(Bytes)
    │      ├─ ValidateGetChars(): バリデーション
    │      ├─ GetCharCountCore(): 文字数計算
    │      │      ├─ 直接文字カウント
    │      │      ├─ Base64文字カウント
    │      │      └─ GetFallbackCharCount(): フォールバック
    │      └─ GetCharsCore(): デコード実行
    │             ├─ 直接文字: そのまま出力
    │             ├─ "+"/"-"処理
    │             ├─ Base64CharToBits(): Base64→ビット変換
    │             └─ InsertFallbackChars(): フォールバック
    │
    ├─ GetEncoder()
    │      └─ UTF7Encoder.Init(Me)
    │
    └─ GetDecoder()
           └─ UTF7Decoder.Init(Me)
```

### データフロー図

```
[入力]                    [処理]                         [出力]

文字列 ──────────────────▶ GetBytes ──────────────────▶ UTF-7バイト配列
  │                           │
  ├─ 直接文字                 ├─ そのまま出力
  ├─ "+"文字                  ├─ "+-"出力
  └─ 非直接文字               └─ "+Base64文字列-"

UTF-7バイト配列 ──────────▶ GetString ─────────────────▶ 文字列
  │                           │
  ├─ 通常文字                 ├─ そのまま出力
  ├─ "+-"                     ├─ "+"文字出力
  └─ "+Base64-"               └─ Base64デコード→文字

AllowOptionals ───────────▶ Init ──────────────────────▶ mDirectlyEncodable更新
                              │
                              └─ オプション文字をルックアップテーブルに追加
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| UTF7Encoding.cls | `Source/CorLib/System.Text/UTF7Encoding.cls` | ソース | メインクラス定義（1161行） |
| UTF7Encoder.cls | `Source/CorLib/System.Text/UTF7Encoder.cls` | ソース | ストリーム用エンコーダ |
| UTF7Decoder.cls | `Source/CorLib/System.Text/UTF7Decoder.cls` | ソース | ストリーム用デコーダ |
| UTF7DecoderFallback.cls | `Source/CorLib/System.Text/UTF7DecoderFallback.cls` | ソース | UTF-7専用デコーダフォールバック |
| Encoding.cls | `Source/CorLib/System.Text/Encoding.cls` | ソース | インターフェース定義 |
| EncodingStatic.cls | `Source/CorLib/System.Text/EncodingStatic.cls` | ソース | UTF7プロパティ（132-138行目） |
| modTextGlobals.bas | `Source/CorLib/System.Text/modTextGlobals.bas` | ソース | Base64Bytes、Base64CharToBits等のヘルパー関数 |
