# 機能設計書 44-UTF-8/UTF-16エンコーディング

## 概要

SQLiteにおけるUnicode文字列のエンコーディング変換機能の設計書。UTF-8、UTF-16LE（リトルエンディアン）、UTF-16BE（ビッグエンディアン）間の相互変換を提供する。

### 本機能の処理概要

SQLiteのエンコーディング機能は、データベース内部で使用される文字列表現と、アプリケーションや外部データソースで使用される表現との間の変換を担当する基盤機能である。

**業務上の目的・背景**：SQLiteは国際化対応のため、Unicodeを完全にサポートする必要がある。UTF-8はストレージ効率が良くASCII互換であるため、多くの場合に適している。一方、UTF-16はWindows APIやJava/C#など、一部のプラットフォームで標準的に使用される。これらのエンコーディング間の透過的な変換を提供することで、異なる環境でのシームレスなデータ交換を実現する。

**機能の利用シーン**：
- データベースオープン時のエンコーディング設定（PRAGMA encoding）
- 文字列リテラルの格納時の変換
- SQL関数（upper, lower, like等）での文字処理
- バインドパラメータの受け渡し
- 照合順序（COLLATE）の適用
- 外部アプリケーションとのデータ交換

**主要な処理内容**：
1. UTF-8読み取り（sqlite3Utf8Read）：UTF-8シーケンスから1文字分のUnicodeコードポイントを取得
2. UTF-8書き込み（WRITE_UTF8マクロ）：UnicodeコードポイントをUTF-8バイト列に変換
3. UTF-16読み取り：UTF-16LE/BEからUnicodeコードポイントを取得
4. UTF-16書き込み（WRITE_UTF16LE/BEマクロ）：UnicodeコードポイントをUTF-16に変換
5. エンコーディング変換（sqlite3VdbeMemTranslate）：Memオブジェクト内の文字列を別エンコーディングに変換
6. BOM処理（sqlite3VdbeMemHandleBom）：UTF-16のバイトオーダーマーク検出・除去
7. 文字数カウント（sqlite3Utf8CharLen）：UTF-8文字列のUnicode文字数を計算

**関連システム・外部連携**：
- VDBEサブシステム（Memオブジェクト経由）
- 文字列関数実装（func.c）
- 照合順序サブシステム
- パーサー（SQL文字列リテラル処理）

**権限による制御**：特になし（内部機能のためアプリケーションレベルの権限制御は不要）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | （内部機能） | - | 文字列操作を伴うすべてのSQL処理で使用 |

## 機能種別

文字エンコーディング変換 / Unicode処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| pMem | Mem* | Yes | 変換対象のメモリセル | MEM_Str フラグ必須 |
| desiredEnc | u8 | Yes | 変換先エンコーディング | SQLITE_UTF8/UTF16LE/UTF16BE |
| zIn | const char* / u8* | Yes | 入力文字列 | NULL終端またはバイト長指定 |
| nByte | int | No | 入力バイト長 | 負値なら終端文字まで |

### エンコーディング定数

| 定数 | 値 | 説明 |
|------|-----|------|
| SQLITE_UTF8 | 1 | UTF-8エンコーディング |
| SQLITE_UTF16LE | 2 | UTF-16リトルエンディアン |
| SQLITE_UTF16BE | 3 | UTF-16ビッグエンディアン |
| SQLITE_UTF16 | 4 | ネイティブバイトオーダーのUTF-16 |

### 入力データソース

- VDBEからのMemオブジェクト
- アプリケーションからバインドされた文字列
- SQLステートメント内の文字列リテラル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 変換結果 | int | SQLITE_OK（成功）またはSQLITE_NOMEM |
| Unicodeコードポイント | u32 | sqlite3Utf8Readの戻り値 |
| バイト数 | int | 文字のエンコードに要したバイト数 |
| 文字数 | int | sqlite3Utf8CharLenの戻り値 |

### 出力先

- 入力Memオブジェクトの更新（インプレース変換）
- 新規割り当てバッファ

## 処理フロー

### 処理シーケンス

```
1. UTF-8読み取り（sqlite3Utf8Read）
   ├─ 先頭バイト取得
   ├─ マルチバイト判定（0xC0以上）
   │   ├─ sqlite3Utf8Trans1テーブルで初期値取得
   │   └─ 継続バイト（0x80-0xBF）を連結
   ├─ 不正シーケンス検出
   │   ├─ オーバーロング（0x80未満の値をマルチバイトで表現）
   │   ├─ サロゲート範囲（0xD800-0xDFFF）
   │   └─ 非文字（0xFFFE, 0xFFFF）
   └─ 0xFFFD（置換文字）に変換

2. UTF-8書き込み（WRITE_UTF8マクロ）
   ├─ 1バイト（0x00-0x7F）：そのまま出力
   ├─ 2バイト（0x80-0x7FF）：0xC0 + 0x80形式
   ├─ 3バイト（0x800-0xFFFF）：0xE0 + 0x80 + 0x80形式
   └─ 4バイト（0x10000-0x10FFFF）：0xF0 + 0x80 + 0x80 + 0x80形式

3. エンコーディング変換（sqlite3VdbeMemTranslate）
   ├─ UTF-16間の変換（バイトスワップのみ）
   │   └─ 2バイトずつ入れ替え
   ├─ UTF-8 → UTF-16変換
   │   ├─ READ_UTF8で1文字読み取り
   │   └─ WRITE_UTF16LE/BEで書き込み
   └─ UTF-16 → UTF-8変換
       ├─ サロゲートペア処理
       │   └─ 上位・下位サロゲートを結合
       └─ WRITE_UTF8で書き込み

4. BOM処理（sqlite3VdbeMemHandleBom）
   ├─ 先頭2バイト確認
   │   ├─ 0xFE 0xFF → UTF-16BE
   │   └─ 0xFF 0xFE → UTF-16LE
   ├─ BOMを削除（memmove）
   └─ エンコーディングフラグ更新
```

### フローチャート

```mermaid
flowchart TD
    A[sqlite3VdbeMemTranslate] --> B{同一エンコーディング?}
    B -->|Yes| C[エラー:assert]
    B -->|No| D{UTF-16間の変換?}
    D -->|Yes| E[バイトスワップ]
    E --> F[完了]
    D -->|No| G[出力バッファ確保]
    G --> H{入力エンコーディング?}
    H -->|UTF-8| I[READ_UTF8ループ]
    I --> J{出力エンコーディング?}
    J -->|UTF16LE| K[WRITE_UTF16LE]
    J -->|UTF16BE| L[WRITE_UTF16BE]
    H -->|UTF-16| M[UTF-16読み取りループ]
    M --> N{サロゲートペア?}
    N -->|Yes| O[ペア結合]
    N -->|No| P[単一コードポイント]
    O --> Q[WRITE_UTF8]
    P --> Q
    K --> R[終端処理]
    L --> R
    Q --> R
    R --> F
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-44-01 | 不正UTF-8置換 | オーバーロング、サロゲート、非文字は0xFFFDに置換 | UTF-8読み取り時 |
| BR-44-02 | サロゲートペア処理 | UTF-16のサロゲートペアは単一コードポイントに結合 | UTF-16→UTF-8変換時 |
| BR-44-03 | BOM除去 | UTF-16のBOMは検出後に削除 | sqlite3VdbeMemHandleBom |
| BR-44-04 | バッファサイズ | UTF-8→UTF-16は最大2倍+2、UTF-16→UTF-8は最大2倍+1 | バッファ割り当て時 |

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

| バイト数 | 先頭バイト範囲 | コードポイント範囲 |
|---------|---------------|-------------------|
| 1 | 0x00-0x7F | U+0000 - U+007F |
| 2 | 0xC0-0xDF | U+0080 - U+07FF |
| 3 | 0xE0-0xEF | U+0800 - U+FFFF |
| 4 | 0xF0-0xF7 | U+10000 - U+10FFFF |

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

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

本機能はデータベーステーブルを直接操作しない（エンコーディング変換機能のため）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SQLITE_NOMEM | メモリ不足 | 変換バッファ割り当て失敗 | OOMフラグ設定 |
| 0xFFFD | 不正文字 | 無効なUTF-8/UTF-16シーケンス | 置換文字で代替 |

### リトライ仕様

エンコーディング変換はリトライ不要（同期処理）

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

エンコーディング変換はトランザクションの対象外（メモリ内処理のため）

## パフォーマンス要件

- sqlite3Utf8Trans1テーブルによる高速デコード
- UTF-16間変換は単純なバイトスワップで効率化
- SQLITE_SKIP_UTF8マクロで高速な文字スキップ

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

- オーバーロングUTF-8は0xFFFDに正規化（セキュリティホール回避）
- サロゲート範囲の単独出現は不正として処理

## 備考

- SQLITE_OMIT_UTF16でUTF-16サポートを無効化可能
- SQLITE_REPLACE_INVALID_UTFで不正サロゲートの厳格な処理

---

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

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

### 推奨読解順序

#### Step 1: エンコーディング規則を理解する

UTF-8とUTF-16のバイト表現を理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | utf.c | `src/utf.c` | コメント（15-34行目）：UTF-8/UTF-16のバイト構造 |
| 1-2 | utf.c | `src/utf.c` | sqlite3Utf8Trans1（52-61行目）：UTF-8デコードテーブル |

**読解のコツ**: UTF-8の先頭バイトは、上位ビットパターンでバイト数を示す。0xxxxxxx=1バイト、110xxxxx=2バイト、1110xxxx=3バイト、11110xxx=4バイト。

#### Step 2: UTF-8読み書きを理解する

UTF-8の読み取り・書き込みマクロと関数。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | utf.c | `src/utf.c` | WRITE_UTF8マクロ（64-82行目）：UTF-8書き込み |
| 2-2 | utf.c | `src/utf.c` | READ_UTF8マクロ（164-174行目）：UTF-8読み取り |
| 2-3 | utf.c | `src/utf.c` | sqlite3Utf8Read（175-194行目）：UTF-8読み取り関数 |

**主要処理フロー**:
1. **64-82行目**: WRITE_UTF8 - コードポイント値に応じて1-4バイト出力
2. **166-170行目**: 0xC0以上なら継続バイトを読み取り
3. **171-173行目**: 不正シーケンスを0xFFFDに置換

#### Step 3: UTF-16読み書きを理解する

UTF-16の書き込みマクロ。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | utf.c | `src/utf.c` | WRITE_UTF16LEマクロ（84-94行目）：リトルエンディアン書き込み |
| 3-2 | utf.c | `src/utf.c` | WRITE_UTF16BEマクロ（96-106行目）：ビッグエンディアン書き込み |

**主要処理フロー**:
- **85-87行目**: BMP範囲（0xFFFF以下）は2バイト直接出力
- **88-93行目**: サロゲートペアとして4バイト出力（U+10000以上）

#### Step 4: エンコーディング変換を理解する

Memオブジェクトのエンコーディング変換。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | utf.c | `src/utf.c` | sqlite3VdbeMemTranslate（242-424行目）：メイン変換関数 |
| 4-2 | utf.c | `src/utf.c` | バイトスワップ処理（270-288行目）：UTF-16間変換 |
| 4-3 | utf.c | `src/utf.c` | UTF-8→UTF-16変換（322-336行目） |
| 4-4 | utf.c | `src/utf.c` | UTF-16→UTF-8変換（341-399行目） |

**主要処理フロー**:
- **270-288行目**: UTF-16LE⇔UTF-16BEはバイトスワップのみ
- **297-298行目**: バッファサイズ計算（UTF-16→UTF-8は2倍+1）
- **346-366行目**: UTF-16LEでのサロゲートペア処理
- **375-395行目**: UTF-16BEでのサロゲートペア処理

#### Step 5: BOM処理と文字カウントを理解する

BOM検出・除去と文字数計算。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | utf.c | `src/utf.c` | sqlite3VdbeMemHandleBom（437-465行目）：BOM処理 |
| 5-2 | utf.c | `src/utf.c` | sqlite3Utf8CharLen（475-490行目）：UTF-8文字数カウント |
| 5-3 | utf.c | `src/utf.c` | sqlite3Utf16ByteLen（551-566行目）：UTF-16バイト長計算 |

**主要処理フロー**:
- **445-450行目**: 0xFE 0xFF=UTF-16BE、0xFF 0xFE=UTF-16LE
- **456-461行目**: BOM（2バイト）を削除してエンコーディング設定
- **485-488行目**: SQLITE_SKIP_UTF8マクロで高速カウント

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

```
sqlite3VdbeMemTranslate(pMem, desiredEnc)
    │
    ├─ [UTF-16間変換]
    │      └─ バイトスワップループ
    │
    ├─ [UTF-8 → UTF-16]
    │      ├─ READ_UTF8マクロ
    │      │      └─ sqlite3Utf8Trans1[]参照
    │      └─ WRITE_UTF16LE/BEマクロ
    │
    └─ [UTF-16 → UTF-8]
           ├─ サロゲートペア検出・結合
           └─ WRITE_UTF8マクロ

sqlite3Utf8Read(pz)
    │
    └─ sqlite3Utf8Trans1[]参照
           └─ 継続バイト処理

sqlite3Utf16to8(db, z, nByte, enc)
    │
    ├─ Memオブジェクト初期化
    ├─ sqlite3VdbeMemSetStr()
    ├─ sqlite3VdbeChangeEncoding()
    │      └─ sqlite3VdbeMemTranslate()
    └─ UTF-8文字列返却
```

### データフロー図

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

UTF-8文字列 ──────▶ sqlite3Utf8Read() ─────────────▶ Unicodeコードポイント
                         │
                         ▼
                  ┌─────────────────┐
                  │ sqlite3Utf8     │
                  │ Trans1[]テーブル│
                  └─────────────────┘


Mem (UTF-8) ─────▶ sqlite3VdbeMemTranslate() ──────▶ Mem (UTF-16)
                         │
                         ▼
                  ┌─────────────────┐
                  │ READ_UTF8       │
                  │ WRITE_UTF16LE/BE│
                  └─────────────────┘


UTF-16文字列 ────▶ sqlite3Utf16to8() ─────────────▶ UTF-8文字列
                         │
                         ▼
                  ┌─────────────────┐
                  │ Memオブジェクト  │
                  │ 経由で変換      │
                  └─────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| utf.c | `src/utf.c` | ソース | UTF-8/UTF-16変換の主要実装 |
| sqliteInt.h | `src/sqliteInt.h` | ヘッダ | エンコーディング定数、SQLITE_SKIP_UTF8マクロ |
| vdbeInt.h | `src/vdbeInt.h` | ヘッダ | Mem構造体定義 |
| vdbeaux.c | `src/vdbeaux.c` | ソース | sqlite3VdbeChangeEncoding実装 |
| vdbemem.c | `src/vdbemem.c` | ソース | Memオブジェクト操作関数 |
