# 機能設計書 31-ユーティリティ関数

## 概要

本ドキュメントは、mrubyコアランタイムにおけるユーティリティ関数群（src/etc.c）の機能設計を記述する。RData構造体の割り当て・データ型チェック、オブジェクトID生成、値のボクシング/アンボクシング等の汎用機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：mrubyのC拡張（gem）開発者が、Rubyオブジェクトとネイティブのデータ構造を安全に橋渡しするための基盤機能を提供する。RData構造体を通じてCの構造体をRubyオブジェクトとしてラップし、型安全なデータアクセスを可能にする。また、ワードボクシング/NaNボクシング等の値表現方式に応じた変換処理を内部的に提供し、プラットフォーム間の互換性を確保する。

**機能の利用シーン**：C拡張でカスタムデータ型をRubyオブジェクトとして公開する場合（例: File, Socket等のリソースラッパー）、オブジェクトの一意識別が必要な場合（Object#object_id）、浮動小数点数や整数のボクシング処理時に内部的に利用される。

**主要な処理内容**：
1. RDataオブジェクトのメモリ割り当てとデータポインタ・型情報の設定（mrb_data_object_alloc）
2. RDataオブジェクトのデータ型チェックとポインタ取得（mrb_data_check_type, mrb_data_get_ptr, mrb_data_check_get_ptr）
3. オブジェクトからシンボルへの変換（mrb_obj_to_sym）
4. オブジェクトの一意識別子生成（mrb_obj_id）
5. ワードボクシングにおける浮動小数点数のボクシング/アンボクシング（mrb_word_boxing_float_value, mrb_word_boxing_value_float）
6. ワードボクシングにおけるCポインタのボクシング（mrb_word_boxing_cptr_value）
7. ワードボクシング/NaNボクシングにおける整数のボクシング（mrb_boxing_int_value）
8. MSVC互換のsnprintf/vsnprintf実装（mrb_msvc_vsnprintf, mrb_msvc_snprintf）

**関連システム・外部連携**：mrubyのGC（ガベージコレクション）サブシステムとのオブジェクト割り当て連携、シンボルテーブルとの連携。

**権限による制御**：なし（C API関数のため、直接的なRuby側の権限制御は存在しない）。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能はC APIであり画面は存在しない |

## 機能種別

ユーティリティ関数群 / データ変換処理 / 型チェック処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| mrb | mrb_state* | Yes | mrubyインタプリタ状態 | NULLでないこと |
| klass | struct RClass* | Yes(alloc) | 割り当て先のクラス | 有効なクラスポインタ |
| ptr | void* | Yes(alloc) | ネイティブデータポインタ | - |
| type | const mrb_data_type* | Yes | データ型記述子 | NULLでないこと |
| obj | mrb_value | Yes(check) | チェック対象オブジェクト | MRB_TT_CDATAであること |
| name | mrb_value | Yes(to_sym) | シンボルまたは文字列 | Symbol/Stringであること |

### 入力データソース

C API呼び出し元のパラメータ。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| RData* | struct RData* | 新規割り当てされたRDataオブジェクト |
| void* | void* | データポインタ（型チェック済み） |
| mrb_sym | mrb_sym | シンボルID |
| mrb_int | mrb_int | オブジェクトID |
| mrb_value | mrb_value | ボクシングされた値 |
| mrb_float | mrb_float | アンボクシングされた浮動小数点値 |

### 出力先

C API呼び出し元への戻り値。

## 処理フロー

### 処理シーケンス

```
1. mrb_data_object_alloc
   └─ MRB_OBJ_ALLOCでRData構造体を割り当て、data/typeフィールドを設定
2. mrb_data_check_type
   └─ MRB_TT_CDATA型チェック -> data_type一致チェック -> 不一致ならTypeError
3. mrb_data_get_ptr
   └─ mrb_data_check_type呼び出し -> DATA_PTRマクロでポインタ取得
4. mrb_data_check_get_ptr
   └─ 型チェック（エラーなし版）-> 不一致ならNULL返却
5. mrb_obj_to_sym
   └─ Symbol判定 -> String判定（intern） -> それ以外はTypeError
6. mrb_obj_id
   └─ ボクシング方式に応じた識別子生成
7. mrb_word_boxing_float_value
   └─ プラットフォーム/設定に応じた浮動小数点ボクシング
8. mrb_boxing_int_value
   └─ FIXABLE判定 -> fixnum値 or ヒープ割り当て
```

### フローチャート

```mermaid
flowchart TD
    A[mrb_data_object_alloc] --> B[MRB_OBJ_ALLOC]
    B --> C[data/typeフィールド設定]
    C --> D[RData*返却]

    E[mrb_data_check_type] --> F{mrb_data_p?}
    F -->|No| G[mrb_check_type で例外]
    F -->|Yes| H{DATA_TYPE一致?}
    H -->|No| I[TypeError]
    H -->|Yes| J[正常終了]

    K[mrb_obj_id] --> L{ボクシング方式}
    L -->|NaN Boxing| M[obj.uをハッシュ]
    L -->|Word Boxing| N[即値/型別処理]
    L -->|No Boxing| O[MakeIDマクロ]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | データ型一致チェック | RDataのdata_typeがリクエストされた型と一致しない場合はTypeErrorを発生 | mrb_data_check_type, mrb_data_get_ptr呼び出し時 |
| BR-02 | シンボル変換制限 | Symbol, String以外の値をシンボルに変換しようとした場合はTypeError | mrb_obj_to_sym呼び出し時 |
| BR-03 | 整数ボクシング閾値 | FIXABLE(n)がtrueの場合はfixnumタグ付き即値、falseの場合はヒープ割り当て | mrb_boxing_int_value呼び出し時 |
| BR-04 | 浮動小数点ボクシング | 指数範囲[-255, +256]内はインライン回転エンコーディング、範囲外はヒープ割り当て | 64bitワードボクシング時 |

### 計算ロジック

- **mrb_float_id**: 浮動小数点数のバイト列からmrb_byte_hashでハッシュ値を算出。-0.0は0.0に正規化。
- **MakeID(p,t)**: `(mrb_int)(((intptr_t)(p))^(t))` でポインタと型のXORで識別子生成。
- **Rotation encoding**: `rotl64(float64_bits - ADDEND, 3)` で下位2ビットがWORDBOX_FLOAT_FLAGとなるタグ付き値を生成。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし |

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | TypeError | mrb_data_check_typeで型不一致 | "wrong argument type X (expected Y)" メッセージ |
| - | TypeError | mrb_data_check_typeで未初期化 | "uninitialized X (expected Y)" メッセージ |
| - | TypeError | mrb_obj_to_symでSymbol/String以外 | "X is not a symbol nor a string" メッセージ |

### リトライ仕様

リトライ処理なし。

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

トランザクション処理なし。

## パフォーマンス要件

各関数は定数時間O(1)で処理される（mrb_obj_idのMRB_NO_BOXINGモードにおけるswitch文含む）。ヒープ割り当てが発生するケースではGCの影響を受ける。

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

- mrb_data_check_typeによる型安全性確保（不正なポインタキャストの防止）
- mrb_data_check_get_ptrは例外を発生させないため、NULLチェックが必須

## 備考

- ボクシング方式（NaN Boxing / Word Boxing / No Boxing）はビルド時のコンパイルオプションで決定される
- MSVC互換コード（mrb_msvc_vsnprintf等）はMSVC 2015未満のみ有効
- 64bit環境でのワードボクシングでは、浮動小数点数のロスレスインライン格納に回転エンコーディングを使用

---

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

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

### 推奨読解順序

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

RDataとmrb_data_typeの構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | data.h | `include/mruby/data.h` | RData構造体、mrb_data_type構造体、DATA_PTR/DATA_TYPEマクロの定義 |
| 1-2 | value.h | `include/mruby/value.h` | mrb_value共用体、ボクシング方式の条件分岐マクロ |

**読解のコツ**: `#ifdef MRB_NAN_BOXING` / `#ifdef MRB_WORD_BOXING` によるプリプロセッサ分岐が多用される。自分のターゲットプラットフォームの分岐のみ追えばよい。

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

etc.cの各関数は独立したC APIエントリーポイント。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | etc.c | `src/etc.c` | 全関数の実装。MRB_API修飾子が付いた関数が公開API |

**主要処理フロー**:
1. **18-27行目**: mrb_data_object_alloc - RData割り当て
2. **34-52行目**: mrb_data_check_type - 型チェックとエラー発生
3. **59-69行目**: mrb_data_check_get_ptr - 安全な型チェック（NULLリターン）
4. **77-81行目**: mrb_data_get_ptr - 型チェック付きポインタ取得
5. **89-96行目**: mrb_obj_to_sym - シンボル変換
6. **113-175行目**: mrb_obj_id - オブジェクト識別子生成（3分岐）
7. **243-295行目**: mrb_word_boxing_float_value - 浮動小数点ボクシング
8. **371-383行目**: mrb_boxing_int_value - 整数ボクシング

#### Step 3: ボクシング実装の詳細を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | etc.c | `src/etc.c` | 207-241行目: 回転エンコーディングのヘルパ関数群 |

**主要処理フロー**:
- **207-210行目**: WORDBOX_FLOAT_ROTATE等の定数定義
- **220-240行目**: wordbox_rotl64, wordbox_float64_to_u64, wordbox_u64_to_float64のビット操作ヘルパ
- **305-341行目**: mrb_word_boxing_value_float - アンボクシング（センチネル値判定 + 回転デコード）

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

```
[C拡張/gemからの呼び出し]
    |
    +-- mrb_data_object_alloc
    |       +-- MRB_OBJ_ALLOC (GC経由のメモリ割り当て)
    |
    +-- mrb_data_get_ptr
    |       +-- mrb_data_check_type
    |               +-- mrb_data_p (型判定マクロ)
    |               +-- mrb_check_type (汎用型チェック)
    |               +-- mrb_raisef (エラー発生)
    |
    +-- mrb_data_check_get_ptr
    |       +-- mrb_data_p / DATA_TYPE / DATA_PTR
    |
    +-- mrb_obj_to_sym
    |       +-- mrb_symbol_p / mrb_string_p
    |       +-- mrb_intern_str (シンボルテーブル登録)
    |
    +-- mrb_obj_id
    |       +-- mrb_float_id (浮動小数点ハッシュ)
    |               +-- mrb_byte_hash
    |
    +-- mrb_word_boxing_float_value
    |       +-- wordbox_float64_to_u64
    |       +-- wordbox_rotl64
    |       +-- mrb_obj_alloc (ヒープフォールバック)
    |
    +-- mrb_boxing_int_value
            +-- FIXABLE (即値判定)
            +-- mrb_obj_alloc (ヒープ割り当て)
```

### データフロー図

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

void* ptr          ──────▶ mrb_data_object_alloc ──────▶ struct RData*
mrb_data_type* type

mrb_value obj      ──────▶ mrb_data_check_type   ──────▶ (正常 or TypeError)
mrb_data_type* type

mrb_value name     ──────▶ mrb_obj_to_sym        ──────▶ mrb_sym

mrb_value obj      ──────▶ mrb_obj_id            ──────▶ mrb_int (ID)

mrb_float f        ──────▶ mrb_word_boxing_float_value ──▶ mrb_value (boxed)

mrb_int n          ──────▶ mrb_boxing_int_value   ──────▶ mrb_value (boxed)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| etc.c | `src/etc.c` | ソース | 本機能のメイン実装 |
| data.h | `include/mruby/data.h` | ヘッダ | RData構造体、mrb_data_type構造体の定義 |
| value.h | `include/mruby/value.h` | ヘッダ | mrb_value、ボクシングマクロの定義 |
| mruby.h | `include/mruby.h` | ヘッダ | mrb_state、主要API宣言 |
| string.h | `include/mruby/string.h` | ヘッダ | 文字列操作マクロ（mrb_intern_str等） |
| class.h | `include/mruby/class.h` | ヘッダ | クラス構造体 |
| numeric.h | `include/mruby/numeric.h` | ヘッダ | 数値関連マクロ（FIXABLE等） |
| internal.h | `include/mruby/internal.h` | ヘッダ | 内部API宣言 |
