# 機能設計書 23-starts_with

## 概要

本ドキュメントは、Hack Standard Library（HSL）の `Str\starts_with` 関数の機能設計書です。文字列が指定されたプレフィックス（接頭辞）で始まるかどうかを判定する機能を提供します。

### 本機能の処理概要

`Str\starts_with` 関数は、与えられた文字列が特定のプレフィックスで始まるかどうかをブール値で返す関数です。大文字小文字を区別した比較を行います。

**業務上の目的・背景**：文字列処理において、URLスキームの判定、ファイルパスの検証、特定のプレフィックスを持つ識別子の検出など、文字列の先頭を検査する処理は頻繁に発生します。この関数は、そのような判定処理を簡潔かつ効率的に記述するために提供されています。PHPの `str_starts_with` 関数と同等の機能をHack言語で型安全に提供します。

**機能の利用シーン**：
- URLスキームの判定（例：`https://` で始まるかどうか）
- ファイルパスの検証（例：`/usr/local/` で始まるか）
- コメント行の検出（例：`#` や `//` で始まるか）
- 特定のプレフィックスを持つ変数名や識別子の検出
- コマンドライン引数の解析（例：`--` で始まるオプション）

**主要な処理内容**：
1. 入力文字列 `$string` とプレフィックス `$prefix` を受け取る
2. 内部実装関数 `_Str\starts_with_l` に処理を委譲
3. プレフィックスが空文字列の場合は常に `true` を返す
4. 文字列の先頭がプレフィックスと一致するかをバイト単位で比較
5. 一致する場合は `true`、しない場合は `false` を返す

**関連システム・外部連携**：外部システムとの連携はありません。純粋な文字列操作関数です。

**権限による制御**：特に権限による制御はありません。純粋関数（Pure function）として実装されており、副作用はありません。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 画面なし | - | 本プロジェクト（Hack Standard Library）はUIを持たないライブラリプロジェクトのため、画面機能マッピングは該当しません。 |

## 機能種別

バリデーション / 文字列判定処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| $string | string | Yes | 検査対象の文字列 | なし（空文字列も許可） |
| $prefix | string | Yes | 検索するプレフィックス（接頭辞） | なし（空文字列も許可） |

### 入力データソース

関数呼び出し時の引数として直接渡される文字列データ。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | bool | 文字列がプレフィックスで始まる場合は `true`、そうでない場合は `false` |

### 出力先

関数の戻り値として呼び出し元に返却。

## 処理フロー

### 処理シーケンス

```
1. 関数呼び出し
   └─ $string と $prefix を引数として受け取る
2. 内部実装への委譲
   └─ _Str\starts_with_l($string, $prefix) を呼び出し
3. 結果の返却
   └─ bool 値を返す
```

### フローチャート

```mermaid
flowchart TD
    A[開始: starts_with呼び出し] --> B{プレフィックスは空文字列?}
    B -->|Yes| C[true を返す]
    B -->|No| D{文字列長 >= プレフィックス長?}
    D -->|No| E[false を返す]
    D -->|Yes| F[文字列の先頭をプレフィックスと比較]
    F --> G{一致する?}
    G -->|Yes| C
    G -->|No| E
    C --> H[終了]
    E --> H
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 空プレフィックス | プレフィックスが空文字列の場合、常にtrueを返す | $prefix === '' |
| BR-02 | 大文字小文字区別 | 比較は大文字小文字を区別する | 常時 |
| BR-03 | バイト単位比較 | 文字列比較はバイト単位で行われる | 常時 |

### 計算ロジック

文字列の先頭 `length($prefix)` バイトが `$prefix` と一致するかを判定。

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

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

本機能はデータベース操作を行いません。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | - | 本関数は例外をスローしない | - |

### リトライ仕様

該当なし。

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

該当なし（データベース操作なし）。

## パフォーマンス要件

- 計算量: O(n) ここで n はプレフィックスの長さ
- 純粋関数として実装されており、キャッシュや状態を持たない
- コンテキスト係数 `[]:` が指定されており、副作用なしで実行可能

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

- 純粋関数のため、セキュリティ上の懸念は最小限
- パス検証に使用する場合は、正規化されたパスを使用すること
- 入力文字列のサニタイズは呼び出し元の責任

## 備考

- 大文字小文字を無視した比較が必要な場合は `Str\starts_with_ci()` を使用すること
- ロケールを考慮した比較が必要な場合は `Str\starts_with_l()` を使用すること

---

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

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

### 推奨読解順序

#### Step 1: 公開APIを理解する

まず、外部から呼び出される公開関数のインターフェースを理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | introspect.php | `src/str/introspect.php` | 公開関数 `starts_with` の定義とドキュメントコメント |

**主要処理フロー**:
- **260-266行目**: 関数のドキュメントコメント。機能説明と関連関数への参照を記載
- **267-272行目**: 関数シグネチャ。`string $string` と `string $prefix` を引数に取り、`bool` を返す
- **271行目**: 内部実装 `_Str\starts_with_l` への委譲

**読解のコツ**: Hackの `[]:` はコンテキスト係数を示し、この関数が純粋関数（副作用なし）であることを表します。

#### Step 2: 内部実装を理解する

内部実装の詳細を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | introspect_l.php | `src/str/introspect_l.php` | ロケール対応版の実装。デフォルトロケールでの動作を理解 |

**主要処理フロー**:
- **276-293行目**: ロケール対応版 `starts_with_l` の定義
- **292行目**: `_Str\starts_with_l($string, $prefix, $locale)` への委譲（ロケール指定あり）

#### Step 3: テストケースを理解する

テストコードから具体的な動作仕様を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | StrIntrospectTest.php | `tests/str/StrIntrospectTest.php` | テストケースから具体的な入出力パターンを理解 |

**主要処理フロー**:
- **346-379行目**: `provideStartsWith` メソッドでテストデータを定義
- **347-351行目**: 空文字列同士の比較は `true`
- **352-356行目**: プレフィックスが空文字列の場合は `true`
- **357-361行目**: 正常な接頭辞一致は `true`（"hello world" と "hello"）
- **362-366行目**: 文字列よりプレフィックスが長い場合は `false`
- **373-378行目**: 大文字小文字が異なる場合は `false`（"HELLO" != "hello"）
- **381-388行目**: テスト実行メソッド

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

```
Str\starts_with($string, $prefix)
    │
    └─ _Str\starts_with_l($string, $prefix)
           │
           └─ [HHVM内部実装]
                  └─ バイト単位での先頭比較
```

### データフロー図

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

$string (string) ───┬──▶ starts_with() ───▶ bool (true/false)
                    │         │
$prefix (string) ───┘         │
                              ▼
                    _Str\starts_with_l()
                              │
                              ▼
                    [バイト単位比較処理]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| introspect.php | `src/str/introspect.php` | ソース | 公開API定義 |
| introspect_l.php | `src/str/introspect_l.php` | ソース | ロケール対応実装 |
| StrIntrospectTest.php | `tests/str/StrIntrospectTest.php` | テスト | ユニットテスト |
