# 通知設計書 4-CallbackSorter

## 概要

本ドキュメントは、VBCorLibライブラリにおけるCallbackSorterコールバック通知の設計を定義する。CallbackSorterクラスは配列ソート時にカスタム比較関数をコールバックとして呼び出す機能を提供する。

### 本通知の処理概要

CallbackSorterは、CorArray.Sortメソッドで配列をソートする際に、ユーザー定義の比較関数をコールバックとして呼び出す通知機構である。QuickSortアルゴリズムの各比較ステップで比較関数が呼び出され、戻り値に基づいてソート順序が決定される。

**業務上の目的・背景**：VB6では配列のソートに標準的な機能がなく、カスタム比較ロジックを使用したソートは困難であった。CallbackSorterは、ユーザーが任意の比較ロジックを定義できる仕組みを提供し、複雑なオブジェクトのソートやカスタム順序でのソートを可能にする。これにより、.NET FrameworkのArray.Sort(IComparer)に相当する機能をVB6で実現できる。

**通知の送信タイミング**：ソートアルゴリズム（QuickSort）の実行中、2つの要素を比較するたびにコールバック関数が呼び出される。配列サイズやデータの初期状態により、呼び出し回数は異なる（平均O(n log n)回）。

**通知の受信者**：CorArray.Sortメソッドに渡された比較関数（AddressOfで指定）。標準モジュール内のPublic Functionとして定義する必要がある。

**通知内容の概要**：比較関数には2つの配列要素がByVal引数として渡される。関数は比較結果を整数（負値、0、正値）で返す必要がある。

**期待されるアクション**：比較関数は2つの引数を比較し、第1引数が小さい場合は負の値、等しい場合は0、大きい場合は正の値を返す。この戻り値に基づいてソート順序が決定される。

## 通知種別

コールバック通知（関数ポインタによるコールバック）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（ソート処理中に繰り返し呼び出し） |
| 優先度 | 高（ソートアルゴリズムの一部として即時処理） |
| リトライ | 無 |

### 送信先決定ロジック

1. CorArray.SortメソッドにAddressOfで比較関数アドレスを渡す
2. CallbackSorter.Init()でNewDelegateを使用してデリゲートを作成
3. mComparer.Invokeで各比較時にコールバック呼び出し

## 通知テンプレート

### コールバック関数シグネチャ

| 項目 | 内容 |
|-----|------|
| 関数名 | 任意（AddressOfで指定） |
| 引数1 | ByVal x As T（比較対象1） |
| 引数2 | ByVal y As T（比較対象2） |
| 戻り値 | Long（負値: x < y, 0: x = y, 正値: x > y） |

### コールバック関数テンプレート

```vb
' 標準モジュール（.bas）内
' 昇順ソート用比較関数
Public Function CompareInt(ByVal x As Long, ByVal y As Long) As Long
    If x < y Then
        CompareInt = -1
    ElseIf x > y Then
        CompareInt = 1
    Else
        CompareInt = 0
    End If
End Function

' 降順ソート用比較関数
Public Function CompareIntDesc(ByVal x As Long, ByVal y As Long) As Long
    CompareIntDesc = -CompareInt(x, y)
End Function
```

### 使用例

```vb
' 標準モジュール内
Sub Main()
    Dim arr() As Long
    arr = Array(5, 2, 8, 1, 9, 3)

    ' カスタム比較関数を使用してソート
    CorArray.Sort arr, AddressOf CompareInt

    ' 結果: 1, 2, 3, 5, 8, 9
End Sub

Public Function CompareInt(ByVal x As Long, ByVal y As Long) As Long
    CompareInt = x - y
End Function
```

### 添付ファイル

該当なし（プログラム内部コールバック）

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| x | 比較対象の第1要素 | 配列要素 | Yes |
| y | 比較対象の第2要素 | 配列要素 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ソート処理 | QuickSort比較ステップ | ソート対象配列が2要素以上 | 各比較時にコールバック |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 配列が空または1要素 | ソート処理自体が不要 |
| IComparer指定 | IComparerインターフェースを使用した場合はCallbackSorterは使用されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[CorArray.Sort呼び出し] --> B{比較関数アドレス指定?}
    B -->|Yes| C[CallbackSorter作成]
    B -->|No| D[デフォルトソーター使用]
    C --> E[CallbackSorter.Init]
    E --> F[NewDelegate mComparer 作成]
    F --> G[CallbackSorter.Sort開始]
    G --> H[QuickSortアルゴリズム]
    H --> I{比較が必要?}
    I -->|Yes| J[mComparer.Invoke x, y]
    J --> K[比較関数実行]
    K --> L[結果に基づき要素入れ替え]
    L --> I
    I -->|No| M[ソート完了]
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（メモリ内処理のみ）

### 更新テーブル一覧

該当なし（メモリ内処理のみ）

#### 内部データ構造

| メンバ変数 | 型 | 用途 |
|-----------|---|------|
| mComparer | Func_T_T_Long | 比較コールバック用デリゲート |
| mHasSortItems | Boolean | Items配列の有無フラグ |
| mSortItems | SortItems | Items配列用バッファ |
| mKeyItems | SortItems | Keys配列用バッファ |
| mInt8() - mInt128() | 各型配列 | ソート対象配列への参照 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 不正な戻り値 | 比較関数が数値以外を返した | 比較関数で必ずLong型を返す |
| シグネチャ不一致 | 比較関数の引数型が配列要素型と不一致 | 適切な型の比較関数を定義 |
| OutOfMemory | 大きな配列のソート時 | メモリを確保してから再試行 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（自動リトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 呼び出し回数 | 平均O(n log n)回、最悪O(n^2)回 |

### 配信時間帯

制限なし

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

- AddressOf演算子で指定された関数のみコールバック対象
- ソート処理中はアプリケーションがブロックされる

## 備考

- 要素サイズに応じて内部処理が分岐（1, 2, 4, 8, 16バイト、それ以外）
- Keys配列とItems配列の同時ソートに対応
- IComparerインターフェースとは別の軽量コールバック方式

---

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

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

### 推奨読解順序

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

比較コールバックに関連するデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | CallbackSorter.cls | `Source/CorLib/System/CallbackSorter.cls` | mComparerメンバ変数（48行目） |
| 1-2 | Delegation.bas | `Source/CorLib/System/Delegation.bas` | Delegate構造体とNewDelegate関数 |

**読解のコツ**: mComparerはFunc_T_T_Long型で、2引数を取りLongを返すデリゲート。

#### Step 2: 初期化処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | CallbackSorter.cls | `Source/CorLib/System/CallbackSorter.cls` | Init Sub（85-87行目） |

**主要処理フロー**:
- **86行目**: Set mComparer = NewDelegate(Callback) でデリゲート作成

#### Step 3: ソート処理と比較コールバックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | CallbackSorter.cls | `Source/CorLib/System/CallbackSorter.cls` | Sort Sub（65-79行目） |
| 3-2 | CallbackSorter.cls | `Source/CorLib/System/CallbackSorter.cls` | SortInt32 Sub（216-241行目）を例として |

**主要処理フロー**:
- **71-77行目**: 要素サイズに応じたソート関数呼び出し
- **222-223行目**: mComparer.Invoke(mInt32(i), x) で比較コールバック呼び出し
- **226-228行目**: 比較結果に基づく要素入れ替え

#### Step 4: クリーンアップ処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | CallbackSorter.cls | `Source/CorLib/System/CallbackSorter.cls` | Class_Terminate（89-99行目） |

**主要処理フロー**:
- **90-94行目**: 各配列ポインタをvbNullPtrに設定
- **96-98行目**: CoTaskMemFreeでバッファ解放

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

```
[ユーザーコード]
    │
    └─ CorArray.Sort(arr, AddressOf CompareFunc)
           │
           └─ CallbackSorter作成
                  │
                  └─ CallbackSorter.Init(Callback)
                         │
                         └─ Set mComparer = NewDelegate(Callback)
                                │
                                ▼
                         CallbackSorter.Sort(Keys, Items, Left, Right)
                                │
                                ├─ 要素サイズ判定
                                │
                                └─ SortInt32 / SortInt64 / 等
                                       │
                                       ├─ mComparer.Invoke(arr(i), x) ... 比較
                                       │      │
                                       │      └─ [ユーザー定義比較関数]
                                       │             │
                                       │             └─ 戻り値: -1, 0, 1
                                       │
                                       └─ 比較結果に基づき要素入れ替え
```

### データフロー図

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

Keys配列        ───▶ CallbackSorter.Sort   ───▶ ソート済み配列
(ソート対象)

AddressOf       ───▶ NewDelegate          ───▶ mComparer
CompareFunc           (Delegation.bas)          (Func_T_T_Long)

arr(i), arr(j)  ───▶ mComparer.Invoke     ───▶ 比較結果
(2要素)               │                         (Long: -1, 0, 1)
                      │
                      ▼
                CompareFunc(x, y)
                      │
                      └─ 比較ロジック実行
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CallbackSorter.cls | `Source/CorLib/System/CallbackSorter.cls` | ソース | コールバック比較によるソート実装 |
| Delegation.bas | `Source/CorLib/System/Delegation.bas` | ソース | デリゲート作成機能 |
| CorArray.cls | `Source/CorLib/System/CorArray.cls` | ソース | 配列操作クラス、Sortメソッド |
| SortItems.bas | `Source/CorLib/System/SortItems.bas` | ソース | ソート用ヘルパー構造体 |
