# 機能設計書: BinaryReader

## 1. 機能概要

### 1.1 機能名
BinaryReader（バイナリリーダー）

### 1.2 機能ID
No.30

### 1.3 機能分類
System.IO - 入出力

### 1.4 概要説明
BinaryReaderは、ストリームから型付きデータを読み取るためのメソッドセットを提供するクラスである。.NET FrameworkのBinaryReaderクラスをVB6で実装したもので、バイトストリームから各種データ型（整数、浮動小数点、文字列等）を読み取る機能を提供する。

### 1.5 主な用途
- バイナリファイルの読み取り
- ネットワークプロトコルのパース
- シリアライズされたデータの復元
- 構造化バイナリデータの解析
- .NETとの互換バイナリ形式の読み取り

---

## 2. 機能詳細

### 2.1 提供機能一覧

| No | 機能名 | 説明 |
|----|--------|------|
| 1 | Read | 汎用読み取り（文字/配列） |
| 2 | PeekChar | 次の文字をプレビュー |
| 3 | ReadByte | 1バイト読み取り |
| 4 | ReadChar | 1文字読み取り |
| 5 | ReadBytes | バイト配列読み取り |
| 6 | ReadChars | 文字配列読み取り |
| 7 | ReadBoolean | Boolean読み取り |
| 8 | ReadInt16 | 2バイト整数読み取り |
| 9 | ReadInt32 | 4バイト整数読み取り |
| 10 | ReadInt64 | 8バイト整数読み取り |
| 11 | ReadSingle | 4バイト浮動小数点読み取り |
| 12 | ReadDouble | 8バイト浮動小数点読み取り |
| 13 | ReadCurrency | Currency読み取り |
| 14 | ReadDate | Date読み取り |
| 15 | ReadDecimal | Decimal読み取り |
| 16 | ReadString | 長さプレフィックス付き文字列読み取り |
| 17 | CloseReader | リーダーを閉じる |

### 2.2 処理フロー

#### 2.2.1 型付き読み取りフロー（ReadInt32等）
```
1. FillBuffer（必要バイト数）
   ├── VerifyIsOpen
   ├── ストリームから読み取り
   └── EndOfStreamException（不足時）
   ↓
2. mBufferから型変換（AsLong等）
   ↓
3. 値を返却
```

#### 2.2.2 文字列読み取りフロー（ReadString）
```
1. VerifyIsOpen
   ↓
2. ReadStringLength（7ビットエンコード長）
   ├── 1バイトずつ読み取り
   └── &H80フラグで継続判定
   ↓
3. エンコードされたバイト数分読み取り
   ↓
4. デコーダで文字変換
   ↓
5. 文字列を返却
```

### 2.3 データ構造

#### 2.3.1 クラスメンバ変数
```vb
Private mStream         As Stream       ' 基底ストリーム
Private mLeaveOpen      As Boolean      ' ストリーム維持フラグ
Private mDecoder        As Decoder      ' デコーダ
Private mBuffer()       As Byte         ' 内部バッファ
Private mSingleChar(0)  As Integer      ' 1文字読み取り用
Private mCharBytes()    As Byte         ' 文字バイトバッファ
Private mIs2ByteChars   As Boolean      ' Unicode判定フラグ
```

#### 2.3.2 定数定義
```vb
Private Const DefaultCapacity   As Long = 16    ' デフォルトバッファ容量
Private Const NoChars           As Long = -1    ' 文字なし
```

### 2.4 7ビットエンコード長

文字列の長さは7ビット可変長整数でエンコードされている:
- 各バイトの下位7ビットが値
- 最上位ビット（&H80）が継続フラグ
- 最大5バイト（35ビット）まで

### 2.5 データ型とバイトレイアウト

| データ型 | バイト数 | 形式 |
|----------|----------|------|
| Boolean | 1 | 0=False, 非0=True |
| Byte | 1 | 符号なし |
| Int16 | 2 | リトルエンディアン |
| Int32 | 4 | リトルエンディアン |
| Int64 | 8 | リトルエンディアン |
| Single | 4 | IEEE 754 |
| Double | 8 | IEEE 754 |
| Currency | 8 | VB Currency形式 |
| Decimal | 16 | .NET形式（VBと異なる） |
| String | 可変 | 7ビット長 + UTF-8バイト |

### 2.6 実装インターフェース

| インターフェース | 説明 |
|------------------|------|
| IObject | 基本オブジェクト機能（Equals, GetHashCode, ToString） |

---

## 3. インターフェース仕様

### 3.1 パブリックAPI

#### 3.1.1 Read メソッド
```vb
Public Function Read(Optional ByRef Buffer As Variant, Optional ByRef Index As Variant, Optional ByRef Count As Variant) As Long
```
**パラメータ**:
- Buffer: Byte配列またはInteger配列（オプション）
- Index: 開始インデックス（オプション）
- Count: 読み取り数（オプション）

**戻り値**: 引数なしの場合は次の文字（-1で終端）、配列の場合は読み取り数

#### 3.1.2 PeekChar メソッド
```vb
Public Function PeekChar() As Long
```
**戻り値**: 次の文字（消費しない）、-1で終端またはシーク不可

#### 3.1.3 ReadByte メソッド
```vb
Public Function ReadByte() As Byte
```
**戻り値**: 1バイト値

#### 3.1.4 ReadChar メソッド
```vb
Public Function ReadChar() As Integer
```
**戻り値**: 1文字（UTF-16）

**備考**: 文字がない場合はEndOfStreamException

#### 3.1.5 ReadBytes メソッド
```vb
Public Function ReadBytes(ByVal Count As Long) As Byte()
```
**パラメータ**:
- Count: 読み取るバイト数

**戻り値**: バイト配列（ストリーム終端の場合は短くなる可能性あり）

#### 3.1.6 ReadChars メソッド
```vb
Public Function ReadChars(ByVal Count As Long) As Integer()
```
**パラメータ**:
- Count: 読み取る文字数

**戻り値**: 文字配列（エンコーディングに依存）

#### 3.1.7 ReadBoolean メソッド
```vb
Public Function ReadBoolean() As Boolean
```
**戻り値**: True（非ゼロ）またはFalse（ゼロ）

#### 3.1.8 ReadInt16 メソッド
```vb
Public Function ReadInt16() As Integer
```
**戻り値**: 2バイト符号付き整数

#### 3.1.9 ReadInt32 メソッド
```vb
Public Function ReadInt32() As Long
```
**戻り値**: 4バイト符号付き整数

#### 3.1.10 ReadInt64 メソッド
```vb
Public Function ReadInt64() As Int64
```
**戻り値**: 8バイト符号付き整数（Int64型）

#### 3.1.11 ReadDouble メソッド
```vb
Public Function ReadDouble() As Double
```
**戻り値**: 8バイト浮動小数点

#### 3.1.12 ReadSingle メソッド
```vb
Public Function ReadSingle() As Single
```
**戻り値**: 4バイト浮動小数点

#### 3.1.13 ReadCurrency メソッド
```vb
Public Function ReadCurrency() As Currency
```
**戻り値**: 8バイトCurrency型

#### 3.1.14 ReadDate メソッド
```vb
Public Function ReadDate() As Date
```
**戻り値**: Date型（.NETのTicks形式から変換）

**備考**: VBのDouble形式ではなく.NETのTicks形式

#### 3.1.15 ReadDecimal メソッド
```vb
Public Function ReadDecimal() As Variant
```
**戻り値**: 16バイトDecimal（.NET形式）

#### 3.1.16 ReadString メソッド
```vb
Public Function ReadString() As String
```
**戻り値**: 長さプレフィックス付き文字列

#### 3.1.17 CloseReader メソッド
```vb
Public Sub CloseReader()
```
**備考**: LeaveOpen=Trueの場合、基底ストリームは閉じない

---

## 4. 内部処理詳細

### 4.1 Init サブルーチン
ストリームからリーダーを初期化する。

**処理概要**（636-650行目）:
1. Stream引数の検証（Nothing、読み取り可能性）
2. エンコーディング設定（デフォルトはUTF-8）
3. UnicodeEncodingの場合、mIs2ByteCharsをTrue
4. デコーダ取得
5. LeaveOpen設定

### 4.2 FillBuffer サブルーチン
指定バイト数をバッファに読み込む。

**処理概要**（660-675行目）:
1. VerifyIsOpenでオープン確認
2. 1バイトの場合はReadByte使用
3. 複数バイトの場合はReadBlock使用
4. 読み取り不足の場合はEndOfStreamException

### 4.3 ReadCharBytes 関数
文字をバイトから読み取る。

**処理概要**（739-799行目）:
1. ストリーム位置を保存（シーク可能な場合）
2. 文字バイトバッファを初期化（128バイト）
3. ループで文字を読み取り
   - UnicodeEncodingの場合はバイト数を2倍
   - デコーダでバイトから文字に変換
4. エラー時はストリーム位置を復元

### 4.4 ReadStringLength 関数
7ビットエンコード長を読み取る。

**処理概要**（801-820行目）:
1. 最大35ビット（5バイト）まで読み取り
2. 各バイトの下位7ビットをシフトして加算
3. 最上位ビット（&H80）が0になるまで継続
4. 35ビット超過時はFormat例外

---

## 5. 関連コンポーネント

### 5.1 依存クラス/モジュール

| クラス名 | 用途 |
|----------|------|
| Stream | 基底ストリーム |
| Encoding | 文字エンコーディング |
| Decoder | 状態を持つデコーダ |
| UTF8Encoding | デフォルトエンコーディング |
| UnicodeEncoding | 2バイト文字判定 |
| BitConverter | Decimal変換 |
| CorDateTime | Date変換（GetOADate） |

---

## 6. エラー処理

### 6.1 例外一覧

| 例外 | 発生条件 |
|------|----------|
| ArgumentNullException | StreamがNothing |
| ArgumentException | Streamが読み取り不可、無効な配列型 |
| ArgumentOutOfRangeException | Countが負数、Decimal精度が28超過 |
| ObjectDisposedException | 閉じられたリーダーへの操作 |
| EndOfStreamException | ストリーム終端で読み取り試行 |
| FormatException | 7ビット長が35ビット超過 |
| IOException | I/Oエラー |
| OverflowException | Date値が無効 |

---

## 7. パフォーマンス考慮

### 7.1 バッファリング
- デフォルトバッファ容量: 16バイト
- 文字バイトバッファ: 128バイト
- mSingleCharは1要素配列（読み取り効率化）

### 7.2 推奨事項
- 大量読み取り時はReadBytes/ReadCharsを使用
- UnicodeEncodingは2倍のバイト読み取りが必要
- シーク不可ストリームではPeekCharは常に-1
- ReadDateは.NET形式であることに注意

---

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

### 8.1 推奨読解順序

1. **データ構造の理解**
   - `BinaryReader.cls` 54-63行目: メンバ変数定義
   - 54-55行目: 定数定義

2. **初期化処理**
   - `Class_Initialize` (632-634行目): バッファ初期化
   - `Init` (636-650行目): ストリーム設定

3. **基本読み取り**
   - `ReadByte` (154-157行目): 1バイト読み取り
   - `ReadInt32` (325-328行目): 4バイト読み取り
   - `ReadDouble` (379-382行目): 8バイト読み取り

4. **文字読み取り**
   - `ReadChar` (169-178行目): 1文字読み取り
   - `ReadChars` (225-249行目): 文字配列読み取り
   - `ReadCharBytes` (739-799行目): 文字バイト変換

5. **文字列読み取り**
   - `ReadString` (571-602行目): 文字列読み取り
   - `ReadStringLength` (801-820行目): 7ビット長デコード

6. **汎用読み取り**
   - `Read` (102-109行目): 汎用エントリポイント
   - `ReadToBuffer` (692-707行目): バッファ振り分け

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

```
BinaryReader.Init
  ├── Stream検証
  ├── Encoding.GetDecoder
  └── mIs2ByteChars判定（UnicodeEncoding）

BinaryReader.ReadInt32
  ├── FillBuffer(4)
  │     ├── VerifyIsOpen
  │     └── mStream.ReadBlock
  └── AsLong(mBuffer(0))

BinaryReader.ReadString
  ├── VerifyIsOpen
  ├── ReadStringLength
  │     └── mStream.ReadByte（ループ）
  ├── mStream.ReadBlock
  ├── mDecoder.GetCharCount
  └── mDecoder.GetChars

BinaryReader.Read
  ├── [引数なし] ReadOneChar
  │     └── ReadCharBytes
  └── [配列あり] ReadToBuffer
        ├── [Byte] ReadToByteBuffer
        │     └── mStream.ReadBlock
        └── [Integer] ReadToCharBuffer
              └── ReadCharBytes
```

### 8.3 データフロー図

```
[Stream]
    │
    ↓
[FillBuffer/ReadBlock]
    │
    ↓
[mBuffer]
    │
    ├── [数値型] ──→ [As関数（AsLong等）] ──→ [型付き値]
    │
    └── [文字列] ──→ [ReadStringLength] ──→ [長さ]
                          │
                          ↓
                    [ReadBlock]
                          │
                          ↓
                    [mDecoder.GetChars]
                          │
                          ↓
                      [String]
```

### 8.4 関連ファイル一覧

| パス | 種別 | 役割 |
|------|------|------|
| Source/CorLib/System.IO/BinaryReader.cls | クラス | メインクラス |
| Source/CorLib/System.IO/BinaryWriter.cls | クラス | 対となる書き込みクラス |
| Source/CorLib/System.IO/Stream.cls | インターフェース | ストリーム基底 |
| Source/CorLib/System.Text/Encoding.cls | クラス | エンコーディング |
| Source/CorLib/System.Text/Decoder.cls | クラス | デコーダ |
| Source/CorLib/System.Text/UTF8Encoding.cls | クラス | デフォルトエンコーディング |

### 8.5 読解のコツ
- AsLong, AsWord, AsDouble等はメモリ直接キャスト関数
- mSingleChar(0)は配列として渡すための1要素配列
- ReadDateは.NETのTicks形式（CorDateTime.GetOADate）で変換
- ReadDecimalは.NET形式のレイアウト（VBと異なる）
- mIs2ByteCharsはUnicodeEncodingの最適化フラグ
- FreeChars/AllocCharsはSAPtr操作によるメモリ管理

---

## 9. 変更履歴

| 日付 | バージョン | 変更内容 |
|------|------------|----------|
| 2014 | 1.0 | 初期実装（Kelly Ethridge） |

---

## 10. 備考

- .NET FrameworkのSystem.IO.BinaryReaderと互換性のあるAPI設計
- デフォルトエンコーディングはUTF-8
- ReadStringは.NETの7ビット可変長エンコーディングに対応
- Decimal, Date, Int64は.NET形式のバイトレイアウト
- BinaryWriterと対になるクラス
- IObjectのみ実装（特定のインターフェースは実装しない）
