# 機能設計書 40-Symbol拡張

## 概要

本ドキュメントは、mrubyのSymbolクラスにall_symbols, length/size, capitalize, downcase, upcase, casecmp, casecmp?, empty?等の拡張メソッドを追加し、Comparableモジュールをincludeするgem（mruby-symbol-ext）の機能設計を記述する。

### 本機能の処理概要

**業務上の目的・背景**：CRuby互換のSymbol操作メソッドを提供し、シンボルの文字列操作（大文字小文字変換、比較）、長さ取得、シンボルテーブルの参照等を可能にする。Comparableのincludeにより<=>ベースの比較演算子も利用可能になる。

**機能の利用シーン**：シンボル名の大文字小文字変換（capitalize, downcase, upcase）、大文字小文字を無視した比較（casecmp, casecmp?）、シンボルの空判定（empty?）、シンボル名の長さ取得（length/size）、デバッグ時のシンボルテーブル確認（all_symbols）等。

**主要な処理内容**：
1. シンボルテーブル: all_symbols（全シンボルの配列取得、MRB_USE_ALL_SYMBOLS時のみ）
2. 長さ取得: length/size（シンボル名の文字数、UTF-8対応）
3. 大文字小文字変換: capitalize, downcase, upcase（to_s経由で変換後to_sym）
4. 比較: casecmp（大文字小文字無視の<=>）、casecmp?（大文字小文字無視の等値判定）
5. 判定: empty?（空シンボル判定）
6. エイリアス: intern（to_symのエイリアス）
7. Comparable: includeによる比較演算子の利用

**関連システム・外部連携**：なし。

**権限による制御**：なし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面なし |

## 機能種別

シンボル操作 / 文字列変換処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| other | Symbol | Yes(casecmp/casecmp?) | 比較対象シンボル | - |

### 入力データソース

メソッド呼び出し時の引数。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Array | Array | all_symbolsの結果（Symbol配列） |
| Integer | Integer | length/sizeの結果 |
| Symbol | Symbol | capitalize, downcase, upcaseの結果 |
| Integer/nil | -1, 0, +1, nil | casecmpの結果 |
| Boolean/nil | true, false, nil | casecmp?の結果 |
| Boolean | true/false | empty?の結果 |

### 出力先

メソッドの戻り値。

## 処理フロー

### 処理シーケンス

```
1. all_symbols: presymbolテーブルとランタイムシンボルテーブルを走査して配列構築
2. length/size: mrb_sym_name_lenで名前取得後、UTF-8文字数をカウント
3. capitalize/downcase/upcase: to_s→文字列変換→to_symの3段階
4. casecmp: 両方upcase後に<=>で比較
5. casecmp?: casecmpの結果が0かどうかで判定
6. empty?: length == 0 で判定
```

### フローチャート

```mermaid
flowchart TD
    A[capitalize 呼び出し] --> B[self.to_s]
    B --> C[capitalize!]
    C --> D{変更あり?}
    D -->|Yes| E[変更後文字列.to_sym]
    D -->|No| F[self.to_sym]
    E --> G[結果返却]
    F --> G
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | all_symbolsの条件コンパイル | MRB_USE_ALL_SYMBOLS定義時のみ利用可能 | all_symbols呼び出し時 |
| BR-02 | presymbolとランタイムシンボルの分離 | all_symbolsはpresymbol（1〜MRB_PRESYM_MAX）とランタイムシンボル（MRB_PRESYM_MAX+1〜）を別ループで収集 | all_symbols呼び出し時 |
| BR-03 | UTF-8文字数カウント | MRB_UTF8_STRING定義時はmrb_utf8_strlenでUTF-8文字数を返す | length/size呼び出し時 |
| BR-04 | casecmpの非Symbol引数 | 引数がSymbolでない場合はnilを返す | casecmp呼び出し時 |
| BR-05 | casecmp?のnil伝搬 | casecmpがnilを返した場合はcasecmp?もnilを返す | casecmp?呼び出し時 |
| BR-06 | Comparable include | SymbolクラスにComparableをincludeし、<=>ベースの比較演算子を利用可能にする | クラス定義時 |

### 計算ロジック

- **capitalize/downcase/upcase**: `(self.to_s.capitalize! || self).to_sym` - bang!メソッドで変更なしならnilが返るため、selfを使用
- **casecmp**: `lhs = self.to_s; lhs.upcase!; rhs = other.to_s.upcase; lhs <=> rhs`
- **casecmp?**: `c = self.casecmp(sym); c.nil? ? nil : c == 0`
- **empty?**: `self.length == 0`

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | - | - | 本機能は例外を発生させない。casecmp/casecmp?は非Symbol引数に対してnilを返す |

### リトライ仕様

なし。

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

なし。

## パフォーマンス要件

- all_symbols: O(全シンボル数)
- length/size: O(文字列長)（UTF-8カウント時）、O(1)（非UTF-8時は名前取得のみ）
- capitalize/downcase/upcase: O(文字列長)（to_s + 変換 + to_sym）
- casecmp: O(文字列長)（upcase + <=>）
- empty?: O(1)（length呼び出し）

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

- all_symbolsはシンボルテーブル全体を公開するため、セキュリティ上の考慮が必要な場合はMRB_USE_ALL_SYMBOLSを無効にすることが推奨される

## 備考

- CとRubyのハイブリッド実装
- all_symbols, length/sizeがC実装、capitalize, downcase, upcase, casecmp, casecmp?, empty?がRuby実装
- all_symbolsはMRB_USE_ALL_SYMBOLS条件コンパイルフラグに依存
- length/sizeはMRB_UTF8_STRING条件コンパイルフラグでUTF-8対応
- Comparable includeによりSymbol同士の比較演算（<, <=, >, >=, between?, clamp）が利用可能
- intern（to_symのエイリアス）も定義される

---

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

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

### 推奨読解順序

#### Step 1: C実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | symbol.c | `mrbgems/mruby-symbol-ext/src/symbol.c` | 各メソッドのC実装 |

**主要処理フロー**:
- **24-38行目**: mrb_sym_all_symbols - presymbol（1〜MRB_PRESYM_MAX）とランタイムシンボル（MRB_PRESYM_MAX+1〜symidx+MRB_PRESYM_MAX）を2ループで収集
- **47-59行目**: mrb_sym_length - mrb_sym_name_lenで名前取得後、MRB_UTF8_STRING時はmrb_utf8_strlenでUTF-8文字数カウント
- **61-64行目**: ROMメソッドテーブル（length, size）
- **67-74行目**: gem_init - all_symbolsのクラスメソッド定義（MRB_USE_ALL_SYMBOLS時のみ）、ROMメソッド初期化

**読解のコツ**: `mrb->symidx`はランタイムで追加されたシンボルの数。presymbolはコンパイル時に確定したシンボルで`MRB_PRESYM_MAX`までの範囲。ランタイムシンボルは`MRB_PRESYM_MAX + 1`から始まる。

#### Step 2: Ruby実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | symbol.rb | `mrbgems/mruby-symbol-ext/mrblib/symbol.rb` | Ruby実装メソッド群 |

**主要処理フロー**:
- **2行目**: `include Comparable` - 比較演算子の利用可能化
- **4行目**: `alias intern to_sym` - エイリアス定義
- **12-14行目**: capitalize - `(self.to_s.capitalize! || self).to_sym`
- **22-24行目**: downcase - `(self.to_s.downcase! || self).to_sym`
- **32-34行目**: upcase - `(self.to_s.upcase! || self).to_sym`
- **42-47行目**: casecmp - 両方upcaseして<=>比較、非Symbol時nil
- **56-60行目**: casecmp? - casecmpの結果が0かで判定
- **68-70行目**: empty? - length == 0

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

```
Symbol.all_symbols
    +-- mrb_sym_all_symbols (C実装)
            +-- [presymbol] 1..MRB_PRESYM_MAX
            +-- [runtime] 1..mrb->symidx (+MRB_PRESYM_MAX)

Symbol#length / Symbol#size
    +-- mrb_sym_length (C実装)
            +-- mrb_sym_name_len
            +-- [UTF-8] mrb_utf8_strlen

Symbol#capitalize
    +-- [Ruby実装]
            +-- self.to_s
            +-- String#capitalize!
            +-- to_sym

Symbol#casecmp
    +-- [Ruby実装]
            +-- kind_of?(Symbol) チェック
            +-- self.to_s.upcase!
            +-- other.to_s.upcase
            +-- String#<=>
```

### データフロー図

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

Symbol (self)   ──────▶ C/Ruby処理関数 ──────▶ Array/Integer/Symbol/Boolean
other引数               文字列変換/比較          結果

[capitalize詳細フロー]
Symbol ──▶ to_s ──▶ String ──▶ capitalize! ──▶ to_sym ──▶ Symbol
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| symbol.c | `mrbgems/mruby-symbol-ext/src/symbol.c` | ソース(C) | C実装メソッド群（all_symbols, length/size） |
| symbol.rb | `mrbgems/mruby-symbol-ext/mrblib/symbol.rb` | ソース(Ruby) | Ruby実装メソッド群（capitalize, downcase, upcase, casecmp, casecmp?, empty?） |
| mrbgem.rake | `mrbgems/mruby-symbol-ext/mrbgem.rake` | 設定 | gem定義 |
| symbol.rb | `mrbgems/mruby-symbol-ext/test/symbol.rb` | テスト | テストケース |
