# 機能設計書 96-MemoryMappedViewAccessor

## 概要

本ドキュメントは、VBCorLibライブラリにおけるMemoryMappedViewAccessor機能の設計を記述するものである。MemoryMappedViewAccessorは、メモリマップトファイルへのランダムアクセスビューを提供するクラスである。

### 本機能の処理概要

MemoryMappedViewAccessorクラスは、メモリマップトファイルの特定領域に対してランダムアクセス（任意の位置への読み書き）を提供する。様々なデータ型の読み書きメソッドを持ち、構造体の直接読み書きもサポートする。

**業務上の目的・背景**：メモリマップトファイルの特定部分に対して、位置を指定した直接アクセスが必要な場合に使用する。ファイル全体をメモリに読み込むことなく、必要な部分のみにアクセスできる。

**機能の利用シーン**：バイナリファイルの構造体読み込み、ランダムアクセスデータベース、固定長レコードファイルの処理、プロセス間共有メモリへのアクセスに使用される。

**主要な処理内容**：
1. 各種型の読み取り（ReadByte/ReadInt16/ReadInt32/ReadInt64/ReadSingle/ReadDouble等）
2. 各種型の書き込み（WriteValue/WriteArray）
3. 構造体の読み書き（Read/ReadArray/WriteArray）
4. バッファのフラッシュ（Flush）
5. アクセス権の確認（CanRead/CanWrite）

**関連システム・外部連携**：Windows API（MapViewOfFile、FlushViewOfFile、UnmapViewOfFile）を使用。

**権限による制御**：CanRead/CanWriteプロパティでアクセス権を確認。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | Simply VB Unit Runner | 参照画面 | MemoryMappedViewAccessor関連テストの実行 |

## 機能種別

メモリアクセス / データ変換

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Position | Long | Yes | 読み書き開始位置 | 0以上かつCapacity未満 |
| Value | Variant | Yes（Write系） | 書き込む値 | 型に応じた検証 |
| Arr | Variant | Yes（Array系） | 配列 | Null禁止 |
| Offset | Long | Yes（Array系） | 配列内のオフセット | 有効範囲内 |
| Count | Long | Yes（Array系） | 要素数 | 0以上 |
| Structure | Variant | Yes（Read構造体） | 読み込む構造体の参照 | UDTまたはプリミティブ型 |

### 入力データソース

- メモリマップトファイルのビュー領域

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ReadByte | Byte | 1バイト値 |
| ReadBoolean | Boolean | ブール値（1バイト） |
| ReadChar | Integer | 文字（2バイト） |
| ReadInt16 | Integer | 16ビット整数 |
| ReadInt32 | Long | 32ビット整数 |
| ReadInt64 | Int64 | 64ビット整数 |
| ReadSingle | Single | 単精度浮動小数点 |
| ReadDouble | Double | 倍精度浮動小数点 |
| ReadCurrency | Currency | 通貨型（64ビット） |
| ReadDate | Date | 日付型 |
| ReadDecimal | Variant | Decimal型 |
| Capacity | Long | ビューの容量 |
| CanRead | Boolean | 読み取り可能か |
| CanWrite | Boolean | 書き込み可能か |
| PointerOffset | Currency | ファイル先頭からのオフセット |

### 出力先

- 呼び出し元への戻り値

## 処理フロー

### 処理シーケンス

```
1. Init呼び出し（MemoryMappedFile.CreateViewAccessor経由）
   └─ ページ境界調整を計算
   └─ MapViewOfFileでビューをマップ
   └─ 内部バイト配列（mViewData）をセットアップ

2. Read系メソッド呼び出し
   └─ CanReadを確認
   └─ GetSafeIndexで位置を検証
   └─ mViewDataから値を読み取り
   └─ 必要に応じて型変換

3. Write系メソッド呼び出し
   └─ CanWriteを確認
   └─ GetSafeIndexで位置を検証
   └─ mViewDataに値を書き込み

4. Flush呼び出し
   └─ FlushViewOfFileでディスクに書き込み

5. Class_Terminate
   └─ UnmapViewOfFileでビューを解除
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{操作種別}
    B -->|Read| C{CanRead?}
    C -->|No| D[NotSupportedException]
    C -->|Yes| E[GetSafeIndex]
    E --> F{位置有効?}
    F -->|No| G[ArgumentOutOfRangeException]
    F -->|Yes| H[mViewDataから読み取り]
    H --> I[型変換]
    I --> J[値返却]
    B -->|Write| K{CanWrite?}
    K -->|No| D
    K -->|Yes| L[GetSafeIndex]
    L --> M{位置有効?}
    M -->|No| G
    M -->|Yes| N[mViewDataに書き込み]
    N --> O[終了]
    D --> O
    G --> O
    J --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-96-01 | 読み取り権限チェック | CanReadがFalseの場合、Read操作は失敗 | Read系メソッド呼び出し時 |
| BR-96-02 | 書き込み権限チェック | CanWriteがFalseの場合、Write操作は失敗 | Write系メソッド呼び出し時 |
| BR-96-03 | 位置検証 | Positionは0以上かつCapacity未満 | 全Read/Write操作時 |
| BR-96-04 | サイズ検証 | Position + データサイズ <= Capacity | 全Read/Write操作時 |
| BR-96-05 | Boolean表現 | Booleanは1バイトで0または1 | ReadBoolean/WriteBoolean時 |
| BR-96-06 | Date表現 | DateはTicks（64ビット整数）として保存 | ReadDate/WriteDate時 |

### 計算ロジック

```
位置調整:
AdjustedPosition = mStartIndex + Position
（mStartIndexはページ境界調整によるオフセット）

サイズチェック:
If AdjustedPosition > mCapacity - SizeOfType Then Error
```

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

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

該当なし

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| NotSupported_Reading | NotSupportedException | CanRead=Falseで読み取り | ReadWrite/ReadOnlyアクセスで作成 |
| NotSupported_Writing | NotSupportedException | CanWrite=Falseで書き込み | ReadWrite/WriteOnlyアクセスで作成 |
| ArgumentOutOfRange_NeedNonNegNum | ArgumentOutOfRangeException | 負のPosition | 0以上の値を指定 |
| ArgumentOutOfRange_PositionLessThanCapacityRequired | ArgumentOutOfRangeException | Capacity以上のPosition | 有効範囲内の値を指定 |
| Argument_NotEnoughBytesToRead | ArgumentException | 読み取りサイズ不足 | 十分なサイズのビューを作成 |
| Argument_InvalidStructure | ArgumentException | 無効な構造体型 | サポートされる型を使用 |

### リトライ仕様

特になし

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

該当なし

## パフォーマンス要件

- 直接メモリアクセスのため高速
- Flushを頻繁に呼ぶとパフォーマンスが低下
- 配列操作はCopyMemoryで一括処理

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

- 書き込みアクセスがない場合でもメモリ内容は読み取り可能
- 機密データは適切な権限で保護すること

## 備考

- .NET FrameworkのSystem.IO.MemoryMappedFiles.MemoryMappedViewAccessorクラスに対応
- VB6のBooleanは2バイトだが、.NET互換性のため1バイトで読み書き
- VB6のDateはDouble形式だが、.NET互換性のためTicks形式で保存

---

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

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

### 推奨読解順序

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

MemoryMappedViewAccessorの内部状態を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | MemoryMappedViewAccessor.cls | `Source/CorLib/System.IO.MemoryMappedFiles/MemoryMappedViewAccessor.cls` | プライベート変数（45-53行目）：mViewData、mCapacity、mStartIndex、mCanRead、mCanWrite |

**読解のコツ**: mViewDataはバイト配列だが、SafeArray1dを使用して直接メモリマップ領域を参照している。

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

Initメソッドでビューがどのように作成されるかを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | MemoryMappedViewAccessor.cls | `Source/CorLib/System.IO.MemoryMappedFiles/MemoryMappedViewAccessor.cls` | Init（810-842行目）でビュー作成 |

**主要処理フロー**:
- **814-831行目**: ページ境界調整 - アロケーショングラニュラリティに合わせてオフセットを調整
- **833-834行目**: MapViewOfFileでビューをマップ
- **840-841行目**: SetCapacityとInitViewDataで内部状態を初期化

#### Step 3: Read系メソッドを理解する

各種データ型の読み取り処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | MemoryMappedViewAccessor.cls | `Source/CorLib/System.IO.MemoryMappedFiles/MemoryMappedViewAccessor.cls` | ReadByte（109-115行目）で基本読み取り |
| 3-2 | MemoryMappedViewAccessor.cls | `Source/CorLib/System.IO.MemoryMappedFiles/MemoryMappedViewAccessor.cls` | ReadInt32（225-231行目）で32ビット整数読み取り |
| 3-3 | MemoryMappedViewAccessor.cls | `Source/CorLib/System.IO.MemoryMappedFiles/MemoryMappedViewAccessor.cls` | Read（440-468行目）で構造体読み取り |

**主要処理フロー**:
- **109-115行目**: ReadByte - CanReadチェック後、GetSafeIndexで位置を取得し、mViewDataから1バイト読み取り
- **225-231行目**: ReadInt32 - AsLong関数で4バイトをLong型に変換
- **440-468行目**: Read - VarTypeでデータ型を判定し、適切なRead関数を呼び出し

#### Step 4: Write系メソッドを理解する

値の書き込み処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | MemoryMappedViewAccessor.cls | `Source/CorLib/System.IO.MemoryMappedFiles/MemoryMappedViewAccessor.cls` | WriteValue（605-643行目）で値書き込み |
| 4-2 | MemoryMappedViewAccessor.cls | `Source/CorLib/System.IO.MemoryMappedFiles/MemoryMappedViewAccessor.cls` | WriteArray（690-726行目）で配列書き込み |

**主要処理フロー**:
- **605-643行目**: WriteValue - VarTypeでデータ型を判定し、適切な変換を行ってmViewDataに書き込み
- **690-726行目**: WriteArray - SizeOfTypeを計算し、WriteDataで一括書き込み

#### Step 5: ヘルパーメソッドを理解する

位置検証とアクセス権管理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | MemoryMappedViewAccessor.cls | `Source/CorLib/System.IO.MemoryMappedFiles/MemoryMappedViewAccessor.cls` | GetSafeIndex（915-931行目）で位置検証 |
| 5-2 | MemoryMappedViewAccessor.cls | `Source/CorLib/System.IO.MemoryMappedFiles/MemoryMappedViewAccessor.cls` | GetDesiredAccess（887-913行目）でアクセス権設定 |

**主要処理フロー**:
- **915-931行目**: GetSafeIndex - 負の位置チェック、mStartIndex調整、容量チェックを実施
- **887-913行目**: GetDesiredAccess - MemoryMappedFileAccessからFILE_MAP_*フラグに変換

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

```
MemoryMappedFile.CreateViewAccessor
    │
    └─ MemoryMappedViewAccessor.Init
           │
           ├─ GetSystemInfo（Windows API）
           │
           ├─ MapViewOfFile（Windows API）
           │
           ├─ SetCapacity
           │      └─ VirtualQuery（必要時）
           │
           └─ InitViewData
                  └─ SAPtr（バイト配列をマップ）

MemoryMappedViewAccessor.ReadXxx
    │
    ├─ CanRead チェック
    │
    ├─ GetSafeIndex
    │      └─ 位置バリデーション
    │
    └─ mViewData から読み取り
           └─ AsXxx 変換関数

MemoryMappedViewAccessor.WriteValue
    │
    ├─ CanWrite チェック
    │
    ├─ GetSafeIndex
    │
    └─ mViewData へ書き込み
           └─ AsXxx 逆変換
```

### データフロー図

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

Position ─────────────▶ GetSafeIndex ──────────────────▶ AdjustedPosition
                              │
                              ▼
                        バリデーション
                              │
Position ─────────────▶ ReadXxx ───────────────────────▶ 型付き値
                              │
                              ▼
                        mViewData[AdjustedPosition]
                              │
                              ▼
                        型変換（AsXxx）

Value ────────────────▶ WriteValue ────────────────────▶ mViewData更新
Position ─────────────┘      │
                              ▼
                        型判定（VarType）
                              │
                              ▼
                        mViewData[AdjustedPosition] = Value
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| MemoryMappedViewAccessor.cls | `Source/CorLib/System.IO.MemoryMappedFiles/MemoryMappedViewAccessor.cls` | ソース | ランダムアクセスビューの実装 |
| MemoryMappedFile.cls | `Source/CorLib/System.IO.MemoryMappedFiles/MemoryMappedFile.cls` | ソース | 親クラス（CreateViewAccessor） |
