# 機能設計書 123-CSV解析

## 概要

本ドキュメントは、KShootManiaにおけるCSVファイル解析処理機能の設計を記述する。CSVフォーマットの文字列を配列に分解する解析機能と、セル内のダブルクォーテーション処理・改行コード変換を行うユーティリティを提供する。

### 本機能の処理概要

本機能は、CSV(Comma-Separated Values)形式の文字列を解析し、各セルの値を配列に分解する処理を提供する。RFC 4180に準じたダブルクォーテーションによるエスケープ処理やセル内改行に対応しており、選曲画面のサブフォルダ名表示(foldername.csv)などで使用される。

**業務上の目的・背景**：KShootManiaでは楽曲のサブフォルダにfoldername.csvファイルを配置して、フォルダの表示名を多言語で管理している。CSV形式のデータを正確に解析するため、ダブルクォーテーションのエスケープ処理やセル区切りの正確な判定が必要である。

**機能の利用シーン**：
- 選曲画面でのサブフォルダ表示名の読み込み（select.hsp内のcsvstr2呼び出し）
- CSVファイルに格納されたフォルダ名の言語別テキストの取得

**主要な処理内容**：
1. cutwqt: ダブルクォーテーションで囲まれた文字列のアンエスケープ処理（ダブルクォート除去・連続ダブルクォートの単一化）
2. cell2str: CSVセル文字列を通常の文字列に変換（改行コード置換 + cutwqt呼び出し）
3. csvstr2: CSV形式の1行を配列に分解（ダブルクォーテーション囲み対応・カンマ区切り解析）
4. getstamp: ファイルのタイムスタンプ取得（付随機能）

**関連システム・外部連携**：Win32 API(FindFirstFile, FileTimeToSystemTime)をファイルタイムスタンプ取得で使用。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 3 | 曲選択画面 | 参照画面 | サブフォルダ名のCSV解析(select.hsp:2876) |

## 機能種別

データ変換処理（CSV文字列→配列分解）

## 入力仕様

### 入力パラメータ

#### csvstr2

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| _arrayout | array | Yes | 結果を格納する文字列型配列変数 | sdimで十分なサイズを事前確保 |
| _strin | str | Yes | CSV形式の1行文字列 | 有効なCSV文字列であること |

#### cutwqt

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| _strin | str | Yes | ダブルクォーテーション除去対象の文字列 | なし |

#### cell2str

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| _strin | str | Yes | CSVセル文字列 | なし |

### 入力データソース

CSVファイル(foldername.csv等)からnoteloadで読み込まれた文字列。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| _arrayout (csvstr2) | array(文字列型配列) | CSVの各セルを分解した配列 |
| stat (csvstr2) | int | 使用した配列要素の数 |
| 戻り値 (cutwqt) | str | ダブルクォーテーション除去後の文字列 |
| 戻り値 (cell2str) | str | 通常文字列に変換後のCSVセル文字列 |

### 出力先

呼び出し元モジュールの変数（引数で指定された配列・変数に格納）

## 処理フロー

### 処理シーケンス

```
1. csvstr2: CSV行解析
   ├─ 先頭文字がダブルクォーテーションかチェック
   │   ├─ Yes: ダブルクォーテーション囲みモード
   │   │   └─ 次のダブルクォーテーション+カンマまたは行末を検索
   │   └─ No: 通常モード
   │       └─ 次のカンマまたは行末を検索
   ├─ 区切り間の文字列を配列に格納
   └─ fcellend=1で行終了判定

2. cutwqt: ダブルクォーテーション除去
   ├─ 先頭が"で始まるか確認
   ├─ 先頭と末尾の"を除去
   └─ 連続する""を"に置換

3. cell2str: CSVセル→文字列変換
   ├─ 改行コード(LF)を"\n"に置換
   └─ cutwqtを呼び出しダブルクォーテーション処理
```

### フローチャート

```mermaid
flowchart TD
    A[csvstr2開始] --> B[cellcnt=0, flg=0]
    B --> C{先頭文字 == 引用符?}
    C -->|Yes| D[flg=1: 引用符囲みモード]
    C -->|No| E[flg=0: 通常モード]
    D --> F[閉じ引用符+カンマ/行末を検索]
    E --> G[次のカンマ/行末を検索]
    F --> H[区切り文字列を配列に格納]
    G --> H
    H --> I{行末到達?}
    I -->|No| C
    I -->|Yes| J[使用配列数をstatに返却]
    J --> K[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-123-01 | ダブルクォーテーション囲み | セルが"で始まる場合、",または"\nまでをセル範囲とする | csvstr2実行時 |
| BR-123-02 | ダブルクォーテーションエスケープ | セル内の""は単一の"に変換する | cutwqt実行時 |
| BR-123-03 | 改行コード変換 | LF(0x0A)を文字列"\n"に置換する | cell2str実行時 |
| BR-123-04 | 空文字列処理 | 空文字列の場合はそのまま返却 | cell2str実行時 |

### 計算ロジック

特になし。文字列解析のみ。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 配列不足 | _arrrayout配列のサイズが不足 | 呼び出し元でsdimにより十分なサイズを事前確保 |
| - | 不正CSV | 閉じダブルクォーテーションがない | 文字列末尾までをセル内容として扱う |

### リトライ仕様

リトライ処理なし。

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

該当なし。

## パフォーマンス要件

CSVの行解析にawait 0/await 1を含むため、1行あたりの処理にフレーム遅延が発生する。大量行の一括処理には不向きだが、本プロジェクトでの使用規模では問題ない。

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

- 外部CSVファイルの読み込みにおいて、入力バリデーションは最低限である
- バッファサイズの事前確保は呼び出し元の責任

## 備考

- mod_csv.hspにはgetstamp命令（ファイルのタイムスタンプ取得）とcharalen関数（文字数カウント）も含まれている
- csvstr2内でawait命令が使用されているため、処理中にウィンドウメッセージが処理される
- kshootmania.hsp 167行目で `#include "third_party/mod_csv.hsp"` としてインクルードされている

---

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

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

### 推奨読解順序

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

CSV解析で使用される変数と戻り値の構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | mod_csv.hsp | `third_party/mod_csv.hsp` | csvstr2の引数定義(59行目): array配列とstr文字列 |

**読解のコツ**: HSP3の`#defcfunc`は戻り値を持つ関数、`#deffunc`は命令(戻り値はstatで返す)として定義される。`array`型は配列の参照渡しを意味する。

#### Step 2: 低レベル関数を理解する

まずcutwqtとcell2strの下位関数を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | mod_csv.hsp | `third_party/mod_csv.hsp` | cutwqt関数(11-26行目): ダブルクォーテーション除去処理 |
| 2-2 | mod_csv.hsp | `third_party/mod_csv.hsp` | cell2str関数(34-44行目): 改行コード変換+cutwqt呼び出し |

**主要処理フロー**:
1. **11行目**: `#defcfunc cutwqt str _strin` - ダブルクォーテーション除去関数の定義
2. **13行目**: 先頭文字がダブルクォーテーションかチェック
3. **14行目**: 先頭と末尾の1文字ずつを除去（strmid）
4. **16-24行目**: repeatループで連続ダブルクォーテーション("")を検索し単一化
5. **39行目**: cell2str内でLF(0x0A)を"\n"に置換
6. **42行目**: cell2str内でcutwqtを呼び出し

#### Step 3: メイン解析関数を理解する

csvstr2のCSV行解析処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | mod_csv.hsp | `third_party/mod_csv.hsp` | csvstr2命令(59-116行目): CSV行解析メイン処理 |

**主要処理フロー**:
- **71行目**: 先頭文字がダブルクォーテーションかチェックし、flg変数にモード設定
- **80-98行目**: ダブルクォーテーション囲みモードの解析（閉じクォート検索）
- **99-108行目**: 通常モードの解析（getstrでカンマ/改行/EOF検索）
- **110行目**: `_arrayout.cnt = strmid(strin, cellcnt, scln)` で配列にセル値を格納
- **112行目**: `fcellend`フラグによる行終了判定

#### Step 4: 呼び出し元を理解する

実際の使用箇所を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | select.hsp | `src/scene/select.hsp` | csvstr2呼び出し(2876行目): サブフォルダ名CSV解析 |
| 4-2 | kshootmania.hsp | `kshootmania.hsp` | mod_csv.hspのインクルード(167行目) |

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

```
kshootmania.hsp (167行目: #include)
    |
    +-- select.hsp (2876行目)
            |
            +-- csvstr2 (mod_csv.hsp:59)
                    |
                    +-- strmid / getstr ... 文字列操作
                    +-- 配列への格納

            +-- strrep (select.hsp:2879)
                    |
                    +-- ダブルクォーテーション置換

cutwqt (mod_csv.hsp:11)
    |
    +-- strmid / instr ... 文字列検索・抽出

cell2str (mod_csv.hsp:34)
    |
    +-- strrep ... 改行コード置換
    +-- cutwqt ... ダブルクォーテーション処理
```

### データフロー図

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

CSVファイル ---------> noteload(ファイル読み込み)
(foldername.csv等)          |
                           v
CSV文字列(1行) -------> csvstr2 -----------------------> 文字列配列(_arrayout)
                           |                               + 要素数(stat)
                           +-- セル分割(カンマ区切り)
                           +-- ダブルクォーテーション処理

CSVセル文字列 --------> cell2str -----------------------> 通常文字列
                           |
                           +-- 改行コード変換
                           +-- cutwqt(ダブルクォーテーション除去)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| mod_csv.hsp | `third_party/mod_csv.hsp` | ソース | CSV解析モジュール本体(cutwqt/cell2str/csvstr2/getstamp) |
| kshootmania.hsp | `kshootmania.hsp` | ソース | mod_csv.hspのインクルード元(167行目) |
| select.hsp | `src/scene/select.hsp` | ソース | csvstr2の呼び出し元(サブフォルダ名解析、2876行目) |
