# 機能設計書 50-printf実装

## 概要

SQLiteにおける独自printf実装の設計書。標準Cライブラリのprintf()に加え、SQLite固有の拡張フォーマット（%q, %Q, %w, %T, %S）を提供する。

### 本機能の処理概要

SQLiteのprintf実装は、文字列フォーマット機能の基盤である。

**業務上の目的・背景**：SQLiteは移植性を重視し、様々なプラットフォームで一貫した動作を必要とする。標準ライブラリのprintf()は実装によって挙動が異なる場合があるため、独自実装を使用する。また、SQLリテラルのエスケープ（%q, %Q）やトークン出力（%T）など、SQLite固有のフォーマット機能を追加している。

**機能の利用シーン**：
- エラーメッセージの生成
- SQL文字列の構築
- デバッグ出力
- ログメッセージの生成
- sqlite3_mprintf(), sqlite3_snprintf() API

**主要な処理内容**：
1. フォーマット解析：フラグ、幅、精度、型指定子の解析
2. 整数変換：%d, %u, %x, %o, %p
3. 浮動小数点変換：%f, %e, %g（FpDecodeを使用）
4. 文字列変換：%s, %z（動的文字列）
5. SQL拡張：%q, %Q（シングルクォートエスケープ）, %w（ダブルクォート）
6. 内部拡張：%T（Token）, %S（SrcItem）
7. StrAccum：動的成長可能な文字列バッファ

**関連システム・外部連携**：
- メモリアロケータ（sqlite3Malloc, sqlite3DbMalloc）
- エラー処理サブシステム
- SQL関数（printf SQL関数）

**権限による制御**：SQLITE_PRINTF_INTERNALフラグで内部拡張を制限

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | （API機能） | - | sqlite3_mprintf(), sqlite3_snprintf()で呼び出し |

## 機能種別

文字列フォーマット / ユーティリティ

## 入力仕様

### 入力パラメータ（sqlite3_str_vappendf）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| pAccum | sqlite3_str* | Yes | 出力バッファ | - |
| fmt | const char* | Yes | フォーマット文字列 | - |
| ap | va_list | Yes | 可変引数リスト | - |

### 入力データソース

- SQLite内部からの呼び出し
- アプリケーションからのsqlite3_mprintf()等

## 出力仕様

### 出力データ

| 関数 | 戻り値型 | 説明 |
|------|---------|------|
| sqlite3_mprintf | char* | 新規確保された文字列 / NULL（エラー） |
| sqlite3_snprintf | char* | 入力バッファへのポインタ |
| sqlite3StrAccumFinish | char* | 完成した文字列 / NULL（エラー） |

### 出力先

- 呼び出し元のStrAccumバッファ
- 新規mallocされたメモリ

## 処理フロー

### 処理シーケンス

```
1. sqlite3_str_vappendf(pAccum, fmt, ap)
   ├─ フォーマット文字列を1文字ずつ走査
   ├─ %以外: 直接出力
   └─ %発見時:
       ├─ フラグ解析: -, +, 空白, #, !, 0, ,
       ├─ 幅解析: 数値または*
       ├─ 精度解析: .数値または.*
       ├─ 長さ修飾子: l, ll
       ├─ 型指定子をハッシュテーブルで検索
       └─ 型別変換処理:
           ├─ etDECIMAL/etRADIX: 整数変換
           ├─ etFLOAT/etEXP/etGENERIC: 浮動小数点
           ├─ etSTRING/etDYNSTRING: 文字列
           ├─ etESCAPE_q/Q/w: SQLエスケープ
           ├─ etTOKEN: Token出力
           ├─ etSRCITEM: SrcItem出力
           └─ その他

2. StrAccum管理
   ├─ sqlite3StrAccumInit(): 初期化
   ├─ sqlite3_str_append(): 追加
   ├─ sqlite3StrAccumEnlarge(): 拡張
   ├─ sqlite3StrAccumFinish(): 完了
   └─ sqlite3_str_reset(): リセット
```

### フローチャート

```mermaid
flowchart TD
    A[sqlite3_str_vappendf] --> B{文字='%'?}
    B -->|No| C[直接出力]
    C --> D{終端?}
    D -->|No| B
    B -->|Yes| E[フラグ解析]
    E --> F[幅解析]
    F --> G[精度解析]
    G --> H[型指定子検索]
    H --> I{型は?}
    I -->|整数| J[etDECIMAL/RADIX]
    I -->|浮動小数点| K[etFLOAT/EXP/GENERIC]
    I -->|文字列| L[etSTRING]
    I -->|SQLエスケープ| M[etESCAPE_q/Q/w]
    I -->|その他| N[その他処理]
    J --> O[幅調整・出力]
    K --> O
    L --> O
    M --> O
    N --> O
    O --> D
    D -->|Yes| P[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-50-01 | ハッシュ検索 | 型指定子をc%23でハッシュ検索 | ASCIIモード時 |
| BR-50-02 | 精度制限 | SQLITE_PRINTF_PRECISION_LIMITで制限可能 | コンパイル時 |
| BR-50-03 | 内部拡張制限 | %T, %SはSQLITE_PRINTF_INTERNAL時のみ | 常時 |
| BR-50-04 | %z最適化 | 既存malloc文字列の拡張を再利用 | %z先頭時 |

### フォーマット指定子一覧

| 指定子 | 型 | 説明 |
|--------|-----|------|
| %d, %i | etDECIMAL | 符号付き10進数 |
| %u | etDECIMAL | 符号なし10進数 |
| %x, %X | etRADIX | 16進数（小文字/大文字） |
| %o | etRADIX | 8進数 |
| %f | etFLOAT | 固定小数点 |
| %e, %E | etEXP | 指数表記 |
| %g, %G | etGENERIC | 自動選択 |
| %s | etSTRING | 文字列 |
| %z | etDYNSTRING | 動的文字列（解放される） |
| %c | etCHARX | 文字 |
| %p | etPOINTER | ポインタ |
| %q | etESCAPE_q | シングルクォートを''に |
| %Q | etESCAPE_Q | %qに加えて'...'で囲む、NULLはNULL |
| %w | etESCAPE_w | ダブルクォートを""に |
| %T | etTOKEN | Token構造体（内部用） |
| %S | etSRCITEM | SrcItem構造体（内部用） |
| %r | etORDINAL | 序数（1st, 2nd等） |
| %n | etSIZE | 出力文字数 |
| %% | etPERCENT | リテラル% |

### フラグ一覧

| フラグ | 意味 |
|--------|------|
| - | 左寄せ |
| + | 正数に+を付ける |
| (空白) | 正数に空白を付ける |
| # | 代替形式（0x, 0等） |
| ! | UTF-8文字幅 / 後置ゼロ保持 |
| 0 | ゼロ埋め |
| , | 千区切りカンマ |

### StrAccum構造体

| フィールド | 型 | 説明 |
|-----------|-----|------|
| zText | char* | 文字列バッファ |
| db | sqlite3* | データベース接続（NULL可） |
| nAlloc | int | 確保サイズ |
| mxAlloc | int | 最大確保サイズ |
| nChar | u32 | 現在の文字数 |
| accError | u8 | エラー状態 |
| printfFlags | u8 | 内部フラグ |

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

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

本機能はデータベーステーブルを直接操作しない（文字列フォーマット機能）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SQLITE_NOMEM | メモリ不足 | バッファ拡張失敗 | accError設定、NULL返却 |
| SQLITE_TOOBIG | サイズ超過 | mxAlloc超過 | accError設定、NULL返却 |

### リトライ仕様

printf操作はリトライ不要（同期処理）

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

printf機能はトランザクションの対象外

## パフォーマンス要件

- 初期バッファ（SQLITE_PRINT_BUF_SIZE=70）で小規模出力を最適化
- 指数バッファ成長で再確保回数を削減
- ハッシュテーブルで高速な型指定子検索

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

- 精度・幅の制限でメモリ枯渇攻撃を防止
- %T, %Sは内部専用（SQLITE_PRINTF_INTERNAL必須）

## 備考

- 1980年代からのパブリックドメインコード
- ロケール非依存（小数点は常に"."）
- SQLITE_EBCDICでEBCDIC対応

---

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

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

### 推奨読解順序

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

フォーマット情報の構造を理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | printf.c | `src/printf.c` | et*定数（18-38行目）：変換タイプ |
| 1-2 | printf.c | `src/printf.c` | et_info構造体（50-58行目）：フォーマット情報 |
| 1-3 | printf.c | `src/printf.c` | fmtinfo配列（94-118行目）：フォーマットテーブル |

**読解のコツ**: fmtinfo[]はハッシュテーブル。iNxtでチェーン。ASCIIコード%23でハッシュ。

#### Step 2: StrAccumを理解する

文字列蓄積バッファの管理。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | printf.c | `src/printf.c` | sqlite3StrAccumInit（1284-1292行目）：初期化 |
| 2-2 | printf.c | `src/printf.c` | sqlite3StrAccumEnlarge（1054-1099行目）：拡張 |
| 2-3 | printf.c | `src/printf.c` | sqlite3_str_append（1132-1144行目）：追加 |
| 2-4 | printf.c | `src/printf.c` | sqlite3StrAccumFinish（1172-1180行目）：完了 |

**主要処理フロー**:
- **1068-1072行目**: 指数バッファ成長
- **1087行目**: 非malloc時のコピー
- **1090行目**: SQLITE_PRINTF_MALLOCEDフラグ設定

#### Step 3: メインループを理解する

フォーマット解析とメイン処理ループ。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | printf.c | `src/printf.c` | sqlite3_str_vappendf（194-1006行目）：メイン関数 |
| 3-2 | printf.c | `src/printf.c` | フラグ解析ループ（266-361行目） |
| 3-3 | printf.c | `src/printf.c` | ハッシュ検索（376-389行目） |

**主要処理フロー**:
- **241行目**: '%'以外は直接出力
- **266-275行目**: フラグ文字の解析
- **286-304行目**: 幅の解析
- **327-358行目**: 精度の解析
- **379行目**: c%23でハッシュ計算

#### Step 4: 変換処理を理解する

型別の変換処理。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | printf.c | `src/printf.c` | etDECIMAL処理（419-525行目）：整数変換 |
| 4-2 | printf.c | `src/printf.c` | etFLOAT/EXP処理（526-708行目）：浮動小数点 |
| 4-3 | printf.c | `src/printf.c` | etSTRING処理（764-815行目）：文字列 |
| 4-4 | printf.c | `src/printf.c` | etESCAPE処理（816-923行目）：SQLエスケープ |

**主要処理フロー**:
- **493-496行目**: 基数変換ループ
- **552行目**: sqlite3FpDecode呼び出し
- **830-831行目**: NULL時の"NULL"/"(NULL)"処理
- **853-876行目**: #フラグでのunistr()エスケープ

#### Step 5: 公開APIを理解する

ユーザー向けprintf関数。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | printf.c | `src/printf.c` | sqlite3_mprintf（1367-1377行目）：公開API |
| 5-2 | printf.c | `src/printf.c` | sqlite3_snprintf（1407-1424行目）：公開API |
| 5-3 | printf.c | `src/printf.c` | sqlite3VMPrintf（1310-1324行目）：内部用 |

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

```
sqlite3_mprintf(zFormat, ...)
    └─ sqlite3_vmprintf(zFormat, ap)
           ├─ sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH)
           ├─ sqlite3_str_vappendf(&acc, zFormat, ap)
           │      ├─ [フォーマット解析]
           │      ├─ [型別変換]
           │      │      ├─ etDECIMAL: 整数変換
           │      │      ├─ etFLOAT: sqlite3FpDecode()
           │      │      ├─ etSTRING: 文字列コピー
           │      │      └─ etESCAPE_q/Q/w: エスケープ処理
           │      └─ sqlite3_str_append()
           │             └─ [必要時] enlargeAndAppend()
           │                    └─ sqlite3StrAccumEnlarge()
           └─ sqlite3StrAccumFinish(&acc)

sqlite3MPrintf(db, zFormat, ...)  [内部用]
    └─ sqlite3VMPrintf(db, zFormat, ap)
           ├─ acc.printfFlags = SQLITE_PRINTF_INTERNAL
           └─ [%T, %Sが使用可能]
```

### データフロー図

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

フォーマット文字列 ────▶ sqlite3_str_vappendf() ─────▶ フォーマット済み文字列
可変引数            │
                    ├─ フラグ/幅/精度解析
                    ├─ 型指定子ハッシュ検索
                    └─ 型別変換
                           │
                           ▼
                    ┌─────────────────┐
                    │ StrAccum         │
                    │ ・zText         │──▶ 出力バッファ
                    │ ・nChar         │──▶ 現在文字数
                    │ ・nAlloc        │──▶ 確保サイズ
                    │ ・mxAlloc       │──▶ 最大サイズ
                    └─────────────────┘
                           │
                           ▼
                    ┌─────────────────┐
                    │ 自動拡張         │
                    │ sqlite3StrAccumEnlarge │
                    │ 指数成長          │
                    └─────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| printf.c | `src/printf.c` | ソース | printf実装 |
| sqliteInt.h | `src/sqliteInt.h` | ヘッダ | StrAccum構造体、PrintfArguments |
| util.c | `src/util.c` | ソース | sqlite3FpDecode（浮動小数点デコード） |
| malloc.c | `src/malloc.c` | ソース | sqlite3DbMallocRaw等 |
