# 帳票設計書 5-INI設定メモリ出力

## 概要

本ドキュメントは、Dear ImGuiライブラリのINI設定メモリ出力機能に関する帳票設計書である。ウィンドウ位置やサイズなどの設定をメモリ上の文字列として出力し、任意の保存方法に対応する機能について記述する。

### 本帳票の処理概要

INI設定メモリ出力機能は、ImGuiアプリケーションの状態（ウィンドウの位置、サイズ、折りたたみ状態など）をINI形式の文字列としてメモリ上に出力する機能である。ファイルシステムを経由せずに設定データを取得できる。

**業務上の目的・背景**：アプリケーションによっては、標準的なファイルシステムへの保存ではなく、独自のストレージシステム（クラウドストレージ、暗号化ファイル、データベースなど）を使用したい場合がある。INI設定メモリ出力機能により、設定データを文字列として取得し、アプリケーション側で任意の方法で保存・管理できる。これにより、プラットフォーム固有の制約やセキュリティ要件にも柔軟に対応可能となる。

**帳票の利用シーン**：io.WantSaveIniSettingsフラグがtrueになった時点で、アプリケーションがSaveIniSettingsToMemory関数を呼び出し、返された文字列を独自の方法で保存する。例えば、ゲームのセーブデータに含めたり、リモートサーバーに送信したりするユースケースがある。Metricsウィンドウからも「Save to memory」ボタンで手動実行できる。

**主要な出力内容**：
1. ウィンドウの位置情報（Pos）
2. ウィンドウのサイズ情報（Size）
3. ウィンドウの折りたたみ状態（Collapsed）
4. カスタム設定ハンドラーによる追加データ

**帳票の出力タイミング**：io.WantSaveIniSettingsがtrueの場合、アプリケーションがSaveIniSettingsToMemory関数を明示的に呼び出す。io.IniFilenameがNULLに設定されている場合、自動保存タイマー満了時にもWantSaveIniSettingsがtrueになる。

**帳票の利用者**：アプリケーション開発者

## 帳票種別

設定データ出力（メモリ上の文字列形式）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | 任意のImGuiウィンドウ | - | SaveIniSettingsToMemory()関数呼び出し |
| - | Metrics/Debuggerウィンドウ | - | Settings > Save to memoryボタン |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | INI形式文字列（メモリ上） |
| 用紙サイズ | N/A（メモリ出力） |
| 向き | N/A |
| ファイル名 | N/A（メモリ上の文字列） |
| 出力方法 | 関数戻り値として文字列ポインタを返す |
| 文字コード | UTF-8（NULL終端文字列） |

### メモリ出力固有設定

| 項目 | 内容 |
|-----|------|
| バッファ | g.SettingsIniData |
| サイズ取得 | out_ini_sizeパラメータ |
| 寿命 | 次回SaveIniSettingsToMemory呼び出しまで有効 |

## 帳票レイアウト

### レイアウト概要

INI形式のセクション構造で、各ウィンドウごとにセクションが作成される。ディスク保存と同一フォーマット。

```
[Window][ウィンドウ名]
Pos=x,y
Size=width,height
Collapsed=0

[Window][別のウィンドウ]
Pos=x,y
Size=width,height
```

### 出力項目

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | セクションヘッダー | ウィンドウの識別情報 | [Window][名前] | INIセクション形式 |
| 2 | Pos | ウィンドウ位置 | ImGuiWindowSettings | Pos=x,y |
| 3 | Size | ウィンドウサイズ | ImGuiWindowSettings | Size=w,h |
| 4 | Collapsed | 折りたたみ状態 | ImGuiWindowSettings | Collapsed=0/1 |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| なし | いつでも呼び出し可能 | - |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | SettingsHandler登録順 | 登録順 |

### 改ページ条件

N/A（メモリ出力のため改ページ概念なし）

## データベース参照仕様

### 参照テーブル一覧

N/A（データベースは使用しない）

### 内部データ構造参照

| データ構造 | 用途 | アクセス方法 |
|-----------|------|-------------|
| ImGuiContext.SettingsWindows | ウィンドウ設定のリスト | g.SettingsWindows |
| ImGuiContext.SettingsHandlers | 設定ハンドラーのリスト | g.SettingsHandlers |
| ImGuiContext.SettingsIniData | 出力用テキストバッファ | g.SettingsIniData |
| ImGuiIO.WantSaveIniSettings | 保存要求フラグ | g.IO.WantSaveIniSettings |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| 出力サイズ | g.SettingsIniData.size() | なし | バイト数 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[SaveIniSettingsToMemory呼び出し] --> B[SettingsDirtyTimer = 0]
    B --> C[SettingsIniData.Buf.resize(0)]
    C --> D[空のNULL文字をpush]
    D --> E[SettingsHandlers.WriteAllFn実行]
    E --> F{out_size指定あり?}
    F -->|Yes| G[*out_size = SettingsIniData.size()]
    F -->|No| H[サイズ出力スキップ]
    G --> I[SettingsIniData.c_str()を返す]
    H --> I
    I --> Z[終了]
```

### WantSaveIniSettingsフロー

```mermaid
flowchart TD
    A[設定変更検知] --> B[MarkIniSettingsDirty呼び出し]
    B --> C[SettingsDirtyTimer = IniSavingRate]
    C --> D[毎フレーム UpdateSettings]
    D --> E{SettingsDirtyTimer <= 0?}
    E -->|No| D
    E -->|Yes| F{IniFilename設定あり?}
    F -->|Yes| G[SaveIniSettingsToDisk]
    F -->|No| H[WantSaveIniSettings = true]
    H --> I[アプリがSaveIniSettingsToMemory呼び出し]
    I --> J[アプリ側で保存処理]
    J --> K[WantSaveIniSettings = false をクリア]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| なし | この関数はエラーを返さない | - | - |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数十〜数百ウィンドウ |
| 目標出力時間 | 即時（メモリ操作） |
| メモリ使用量 | SettingsIniDataのサイズに依存 |

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

- 返される文字列ポインタはImGuiコンテキストが管理するメモリを指す
- 次回SaveIniSettingsToMemory呼び出しで内容が上書きされるため、必要に応じてコピーを取ること
- カスタムSettingsHandlerで機密情報を出力しないよう注意

## 備考

- 返される文字列はNULL終端されている
- 文字列の寿命は次回SaveIniSettingsToMemory呼び出しまたはコンテキスト破棄まで
- io.WantSaveIniSettingsはアプリケーション側でクリアする必要がある
- SaveIniSettingsToDisk関数の内部でもこの関数が呼び出される

---

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

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

### 推奨読解順序

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

まず、設定保存で使用されるデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui.h | `imgui.h` | 1131行目: SaveIniSettingsToMemory関数の宣言を確認 |
| 1-2 | imgui.h | `imgui.h` | 1126行目: io.WantSaveIniSettingsの説明コメントを確認 |
| 1-3 | imgui_internal.h | `imgui_internal.h` | ImGuiContext.SettingsIniDataを確認 |

**読解のコツ**: imgui.hのコメントでWantSaveIniSettingsの使い方を理解し、アプリケーション側での使用パターンを把握する。

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

処理の起点となる関数を特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui.cpp | `imgui.cpp` | 15488-15499行目: SaveIniSettingsToMemory関数の実装 |

**主要処理フロー**:
1. **15490行目**: SettingsDirtyTimer = 0.0fでタイマーリセット
2. **15491行目**: SettingsIniData.Buf.resize(0)でバッファクリア
3. **15492行目**: SettingsIniData.Buf.push_back(0)で空のNULL文字をpush
4. **15493-15494行目**: 各SettingsHandlerのWriteAllFnを呼び出し
5. **15495-15496行目**: out_sizeが指定されていればサイズを設定
6. **15497行目**: SettingsIniData.c_str()を返す

#### Step 3: WantSaveIniSettingsの使用パターンを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui.cpp | `imgui.cpp` | 15332-15333行目: WantSaveIniSettingsがtrueに設定される箇所 |
| 3-2 | imgui.h | `imgui.h` | 1126行目: WantSaveIniSettingsの説明 |

**主要処理フロー**:
- **15332-15333行目**: IniFilenameがNULLの場合、WantSaveIniSettings = true

#### Step 4: 実際の使用例を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | imgui.cpp | `imgui.cpp` | 16727-16728行目: Metricsウィンドウでの使用例 |
| 4-2 | imgui.cpp | `imgui.cpp` | 15479行目: SaveIniSettingsToDiskからの呼び出し |

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

```
SaveIniSettingsToMemory(out_ini_size)
    │
    ├─ g.SettingsDirtyTimer = 0.0f
    │
    ├─ g.SettingsIniData.Buf.resize(0)
    │
    ├─ g.SettingsIniData.Buf.push_back(0)
    │
    ├─ for (handler : g.SettingsHandlers)
    │      └─ handler.WriteAllFn(&g, &handler, &g.SettingsIniData)
    │
    ├─ if (out_size)
    │      └─ *out_size = (size_t)g.SettingsIniData.size()
    │
    └─ return g.SettingsIniData.c_str()

[呼び出し元]
SaveIniSettingsToDisk(ini_filename)
    └─ SaveIniSettingsToMemory(&ini_data_size)

[WantSaveIniSettingsパターン]
UpdateSettings()
    └─ [IniFilename == NULL && タイマー満了]
           └─ g.IO.WantSaveIniSettings = true
                  │
                  └─ [アプリケーション側]
                         ├─ SaveIniSettingsToMemory()
                         └─ g.IO.WantSaveIniSettings = false
```

### データフロー図

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

ウィンドウ設定 ──────▶ SettingsHandlers
                              │
                              ▼
                        WriteAllFn()
                              │
                              ▼
                        SettingsIniData ◀───── [データ蓄積]
                              │
                              ▼
SaveIniSettingsToMemory ▶ c_str() ────────────▶ const char* 文字列
                              │
                              ▼
                        [アプリケーション側で保存]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | 公開API宣言（SaveIniSettingsToMemory等） |
| imgui.cpp | `imgui.cpp` | ソース | 設定メモリ出力機能の実装 |
| imgui_internal.h | `imgui_internal.h` | ヘッダー | ImGuiSettingsHandler, SettingsIniData定義 |
