# 機能設計書 74-正規表現

## 概要

本ドキュメントは、Godotエンジンにおける正規表現機能の設計を記述する。PCRE2ライブラリをベースにした強力なパターンマッチングと文字列置換機能を提供する。

### 本機能の処理概要

正規表現機能は、文字列のパターンマッチング、検索、置換を行うための標準的なRegex実装を提供する。PCRE2（Perl Compatible Regular Expressions 2）ライブラリを内部で使用し、UTF-32対応の高機能な正規表現処理を実現する。

**業務上の目的・背景**：ゲーム開発においては、ユーザー入力のバリデーション、テキストのパース、ファイル名やパスの処理など、様々な場面でパターンマッチングが必要となる。正規表現機能は、こうした複雑な文字列処理を効率的に実装するための基盤を提供する。

**機能の利用シーン**：
- ユーザー入力（メールアドレス、電話番号など）の検証
- ゲーム内チャットのフィルタリング
- ログファイルやデータファイルのパース
- テンプレート文字列の変数置換
- MODシステムでのカスタムコマンド解析

**主要な処理内容**：
1. 正規表現パターンのコンパイル（compile）
2. 文字列内のパターン検索（search）
3. すべてのマッチを検索（search_all）
4. パターンに基づく文字列置換（sub）
5. 名前付きキャプチャグループのサポート
6. マッチ結果の詳細情報取得（RegExMatch）

**関連システム・外部連携**：PCRE2ライブラリ、Godotメモリ管理

**権限による制御**：特になし（すべてのスクリプトから利用可能）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 該当画面なし | - | 正規表現は特定画面に限定されない汎用機能 |

## 機能種別

ユーティリティ / 文字列処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| pattern | String | Yes | 正規表現パターン | PCRE2互換形式 |
| subject | String | Yes | 検索対象の文字列 | - |
| offset | int | No | 検索開始位置（デフォルト: 0） | 0以上 |
| end | int | No | 検索終了位置（デフォルト: -1=末尾） | - |
| replacement | String | Yes(sub) | 置換文字列 | - |
| all | bool | No | 全マッチを置換（デフォルト: false） | - |

### 入力データソース

- スクリプトからの文字列引数
- compile()時のパターン文字列

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| RegExMatch | Ref<RegExMatch> | マッチ結果オブジェクト |
| search_all結果 | TypedArray<RegExMatch> | 全マッチ結果配列 |
| sub結果 | String | 置換後の文字列 |
| is_valid | bool | パターンが有効かどうか |
| pattern | String | コンパイル済みパターン |
| group_count | int | キャプチャグループ数 |
| names | PackedStringArray | 名前付きグループ名一覧 |

### 出力先

- スクリプトへの結果返却

## 処理フロー

### 処理シーケンス

```
1. RegExインスタンス生成
   └─ PCRE2コンテキスト初期化
2. パターンコンパイル
   └─ pcre2_compile_32()でパターンを内部表現に変換
3. 検索/置換実行
   └─ pcre2_match_32()/pcre2_substitute_32()を呼び出し
4. 結果取得
   └─ RegExMatchオブジェクトに結果を格納
5. リソース解放
   └─ マッチデータ/コンテキストの解放
```

### フローチャート

```mermaid
flowchart TD
    A[RegEx生成] --> B[compile]
    B --> C{コンパイル成功?}
    C -->|No| D[エラー表示]
    C -->|Yes| E{search/sub?}
    E -->|search| F[pcre2_match_32]
    E -->|sub| G[pcre2_substitute_32]
    F --> H{マッチあり?}
    H -->|Yes| I[RegExMatch生成]
    H -->|No| J[null返却]
    I --> K[結果返却]
    G --> L[置換後文字列返却]
    D --> M[終了]
    J --> M
    K --> M
    L --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-74-01 | オフセット検証 | offsetは0以上である必要がある | search/sub呼び出し時 |
| BR-74-02 | パターン有効性 | 無効なパターンでsearch/subを呼ぶとエラー | is_valid()がfalseの場合 |
| BR-74-03 | 重複グループ名許可 | 同じ名前の複数キャプチャグループを許可 | PCRE2_DUPNAMES設定 |
| BR-74-04 | メモリ再割り当て | 置換結果がバッファを超えた場合は再割り当て | sub実行時 |

### PCRE2フラグ

- `PCRE2_DUPNAMES`: 重複グループ名許可
- `PCRE2_SUBSTITUTE_OVERFLOW_LENGTH`: バッファ不足時に必要サイズを返す
- `PCRE2_SUBSTITUTE_UNSET_EMPTY`: 未設定グループを空文字列に
- `PCRE2_SUBSTITUTE_GLOBAL`: 全マッチを置換

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

本機能はデータベース操作を行わない（インメモリ処理）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ERR_FAIL_COND_V | パラメータエラー | offset < 0 | 0以上の値を指定 |
| ERR_FAIL_COND_V | 状態エラー | is_valid() == false | compile()を先に呼ぶ |
| PCRE2_ERROR_* | PCRE2エラー | パターン構文エラー等 | パターンを修正 |
| PCRE2_ERROR_NOMEMORY | メモリエラー | バッファ不足 | 自動再割り当て |
| PCRE2_ERROR_NOSUBSTRING | 置換エラー | 存在しないグループ参照 | UNKNOWN_UNSETフラグで再試行 |

### リトライ仕様

sub()でPCRE2_ERROR_NOMEMORYが発生した場合、必要サイズを再計算して自動リトライする。

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

該当なし（インメモリ処理）

## パフォーマンス要件

- コンパイル済みパターンは再利用可能（一度コンパイルして複数回検索）
- PCRE2のJITコンパイルには非対応（将来の拡張候補）
- 大きな文字列の処理時はsearch_allよりもsearchのループが効率的な場合あり

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

- ReDoS（正規表現DoS）攻撃への考慮が必要
- ユーザー入力をパターンとして使用する場合は注意
- PCRE2のデフォルトセキュリティ設定を使用

## 備考

- PCRE2のUTF-32モードを使用（GodotのString内部表現に対応）
- Godot独自のメモリアロケータを使用（_regex_malloc/_regex_free）
- 名前付きキャプチャグループをサポート（`(?<name>pattern)`）

---

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

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

### 推奨読解順序

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

RegExとRegExMatchクラスの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | regex.h | `modules/regex/regex.h` | RegEx/RegExMatchクラス定義 |
| 1-2 | regex.cpp | `modules/regex/regex.cpp` | メソッド実装 |

**読解のコツ**: RegExがパターンを保持し、RegExMatchが個々のマッチ結果を保持する。

#### Step 2: コンパイル処理を理解する

パターンのコンパイル処理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | regex.cpp | `modules/regex/regex.cpp` | compile()の実装 |

**主要処理フロー**:
1. **179-205行目**: compile()でパターンをPCRE2内部表現に変換
2. **172-177行目**: clear()で既存コードを解放
3. **195-203行目**: コンパイルエラー時のメッセージ出力

#### Step 3: 検索・置換処理を理解する

search/subメソッドの処理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | regex.cpp | `modules/regex/regex.cpp` | search(), sub()の実装 |

**主要処理フロー**:
1. **207-271行目**: search()でパターンマッチ
2. **273-290行目**: search_all()で全マッチ取得
3. **292-360行目**: sub()で文字列置換

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

```
RegEx::compile()
    │
    └─ pcre2_compile_32()
           └─ code = [PCRE2内部表現]

RegEx::search()
    │
    ├─ pcre2_match_context_create_32()
    ├─ pcre2_match_data_create_from_pattern_32()
    ├─ pcre2_match_32()
    │      └─ [マッチング実行]
    ├─ pcre2_get_ovector_*()
    │      └─ [結果取得]
    └─ RegExMatch生成
           └─ [data, names設定]

RegEx::sub()
    │
    ├─ pcre2_substitute_32()
    │      └─ [置換実行]
    └─ 置換後文字列返却
```

### データフロー図

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

pattern ───────────▶ pcre2_compile_32 ─────▶ code (内部表現)
     │                                             │
subject ───────────▶ pcre2_match_32 ───────▶ ovector (マッチ位置)
     │                    │                        │
offset/end ─────────────────────────────────▶ RegExMatch
                                                   │
replacement ───────▶ pcre2_substitute_32 ──▶ 置換後文字列
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| regex.cpp | `modules/regex/regex.cpp` | ソース | RegEx/RegExMatch実装 |
| regex.h | `modules/regex/regex.h` | ヘッダー | RegEx/RegExMatch定義 |
| pcre2.h | 外部ライブラリ | ヘッダー | PCRE2 API定義 |
| register_types.cpp | `modules/regex/register_types.cpp` | ソース | モジュール登録 |
