diff --git a/.gitattributes b/.gitattributes index 76e22e2..279b318 100644 --- a/.gitattributes +++ b/.gitattributes @@ -28,6 +28,7 @@ *.uxml text eol=lf *.uss text eol=lf *.sh text eol=lf +*.ps1 text eol=lf # Exclude TextMesh Pro files from language statistics "Assets/TextMesh Pro/**" linguist-generated=true linguist-vendored=true diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..065fdae --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,71 @@ +name: Docs + +on: + pull_request: + paths: + - "Assets/Plugins/CSVLoader/Runtime/**/*.cs" + - "docs/**" + - ".github/workflows/docs.yml" + push: + branches: [main] + paths: + - "Assets/Plugins/CSVLoader/Runtime/**/*.cs" + - "docs/**" + - ".github/workflows/docs.yml" + release: + types: [published] + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: docs + cancel-in-progress: true + +jobs: + build: + name: Build API site + runs-on: ubuntu-latest + container: + image: unityci/editor:ubuntu-6000.0.73f1-base-3 + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + + - name: Setup .NET + uses: actions/setup-dotnet@26b0ec14cb23fa6904739307f278c14f94c95bf1 # v5.4.0 + with: + dotnet-version: "8.0.x" + + - name: Install DocFX + run: dotnet tool install docfx --tool-path .tools --version 2.78.5 + + - name: Build documentation + env: + UnityEditorContents: /opt/unity/Editor/Data + run: | + dotnet restore docs/CSV4Unity.Docs.csproj + cd docs + ../.tools/docfx metadata docfx.json + ../.tools/docfx build docfx.json + + - name: Upload Pages artifact + uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 + with: + path: docs/_site + + deploy: + name: Deploy to GitHub Pages + needs: build + if: github.event_name != 'pull_request' + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy + id: deployment + uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0 diff --git a/.gitignore b/.gitignore index 5bfd11f..ca1bf88 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,7 @@ ExportedObj/ .consulo/ *.csproj +!/docs/CSV4Unity.Docs.csproj *.unityproj *.sln *.slnx @@ -116,6 +117,12 @@ CaseSensitiveTest *.coverage *.coveragexml +# DocFX generated files +/docs/api/ +/docs/_site/ +/docs/bin/ +/docs/obj/ + # OS generated files .DS_Store Thumbs.db diff --git a/Assets/Plugins/CSVLoader/Runtime/CSVLoader.cs b/Assets/Plugins/CSVLoader/Runtime/CSVLoader.cs index dafbe2e..916be89 100644 --- a/Assets/Plugins/CSVLoader/Runtime/CSVLoader.cs +++ b/Assets/Plugins/CSVLoader/Runtime/CSVLoader.cs @@ -4,13 +4,20 @@ namespace CSV4Unity { /// - /// UnityのTextAssetとPure C#のCSVコアを接続します。 + /// UnityのとPure C#のCSVコアを接続します。 /// public static class CSVLoader { /// /// TextAssetを解析し、ヘッダー名または列番号で参照できるドキュメントを返します。 /// + /// 解析するCSVを保持したTextAsset。 + /// 解析方法。の場合は既定値を使用します。 + /// ドキュメントの識別名。の場合はTextAsset名を使用します。 + /// 解析された読み取り専用ドキュメント。 + /// です。 + /// 区切り文字にダブルクォートまたは改行文字が指定されています。 + /// CSVの構文またはレコードの列数が不正です。 public static CsvDocument LoadDocument( TextAsset csvFile, CsvParseOptions options = null, @@ -23,6 +30,13 @@ public static CsvDocument LoadDocument( /// /// CSV文字列を解析し、ヘッダー名または列番号で参照できるドキュメントを返します。 /// + /// 解析するCSV文字列。 + /// 解析方法。の場合は既定値を使用します。 + /// ドキュメントの識別名。の場合は空文字列を使用します。 + /// 解析された読み取り専用ドキュメント。 + /// です。 + /// 区切り文字にダブルクォートまたは改行文字が指定されています。 + /// CSVの構文またはレコードの列数が不正です。 public static CsvDocument LoadDocument( string csvText, CsvParseOptions options = null, @@ -34,6 +48,15 @@ public static CsvDocument LoadDocument( /// /// TextAssetを解析し、Enumで列を指定できるテーブルを返します。 /// + /// CSVヘッダーと同名のフィールドを持つEnum型。 + /// 解析するCSVを保持したTextAsset。 + /// 解析方法。の場合は既定値を使用します。 + /// ドキュメントの識別名。の場合はTextAsset名を使用します。 + /// Enumで列を指定できるテーブル。 + /// です。 + /// 区切り文字にダブルクォートまたは改行文字が指定されています。 + /// CSVの構文またはレコードの列数が不正です。 + /// ヘッダーとEnumを一意に対応付けられません。 public static CsvTable LoadTable( TextAsset csvFile, CsvParseOptions options = null, @@ -46,6 +69,15 @@ public static CsvTable LoadTable( /// /// CSV文字列を解析し、Enumで列を指定できるテーブルを返します。 /// + /// CSVヘッダーと同名のフィールドを持つEnum型。 + /// 解析するCSV文字列。 + /// 解析方法。の場合は既定値を使用します。 + /// ドキュメントの識別名。の場合は空文字列を使用します。 + /// Enumで列を指定できるテーブル。 + /// です。 + /// 区切り文字にダブルクォートまたは改行文字が指定されています。 + /// CSVの構文またはレコードの列数が不正です。 + /// ヘッダーとEnumを一意に対応付けられません。 public static CsvTable LoadTable( string csvText, CsvParseOptions options = null, diff --git a/Assets/Plugins/CSVLoader/Runtime/Conversion/CsvConversionException.cs b/Assets/Plugins/CSVLoader/Runtime/Conversion/CsvConversionException.cs index 8971d35..b3c5ee2 100644 --- a/Assets/Plugins/CSVLoader/Runtime/Conversion/CsvConversionException.cs +++ b/Assets/Plugins/CSVLoader/Runtime/Conversion/CsvConversionException.cs @@ -2,8 +2,15 @@ namespace CSV4Unity { + /// + /// CSVセルの文字列を要求された型へ変換できない場合に送出される例外です。 + /// public sealed class CsvConversionException : FormatException { + /// 変換できなかった値と変換先型を指定して例外を生成します。 + /// 変換できなかったCSVセルの文字列。 + /// 要求された変換先型。 + /// です。 public CsvConversionException(string value, Type targetType) : base($"CSV value '{value}' cannot be converted to {targetType.Name}.") { @@ -11,7 +18,10 @@ public CsvConversionException(string value, Type targetType) TargetType = targetType; } + /// 変換できなかったCSVセルの文字列を取得します。 public string Value { get; } + + /// 要求された変換先型を取得します。 public Type TargetType { get; } } } diff --git a/Assets/Plugins/CSVLoader/Runtime/Conversion/CsvValueConverter.cs b/Assets/Plugins/CSVLoader/Runtime/Conversion/CsvValueConverter.cs index f8e0d37..82ba3ca 100644 --- a/Assets/Plugins/CSVLoader/Runtime/Conversion/CsvValueConverter.cs +++ b/Assets/Plugins/CSVLoader/Runtime/Conversion/CsvValueConverter.cs @@ -8,11 +8,22 @@ namespace CSV4Unity /// public static class CsvValueConverter { + /// 文字列をBoolean値へ変換します。 + /// 変換する文字列。 + /// 変換に成功した場合の値。 + /// 変換に成功した場合は、それ以外は + /// と同じ文字列表現を受け付けます。 public static bool TryConvertBoolean(ReadOnlySpan value, out bool result) { return bool.TryParse(value, out result); } + /// 文字列を32ビット符号付き整数へ変換します。 + /// 変換する文字列。 + /// 変換に成功した場合の値。 + /// 数値形式。の場合はを使用します。 + /// 変換に成功した場合は、それ以外は + /// として解析します。 public static bool TryConvertInt32( ReadOnlySpan value, out int result, @@ -21,6 +32,12 @@ public static bool TryConvertInt32( return int.TryParse(value, NumberStyles.Integer, formatProvider ?? CultureInfo.InvariantCulture, out result); } + /// 文字列を64ビット符号付き整数へ変換します。 + /// 変換する文字列。 + /// 変換に成功した場合の値。 + /// 数値形式。の場合はを使用します。 + /// 変換に成功した場合は、それ以外は + /// として解析します。 public static bool TryConvertInt64( ReadOnlySpan value, out long result, @@ -29,6 +46,12 @@ public static bool TryConvertInt64( return long.TryParse(value, NumberStyles.Integer, formatProvider ?? CultureInfo.InvariantCulture, out result); } + /// 文字列を単精度浮動小数点数へ変換します。 + /// 変換する文字列。 + /// 変換に成功した場合の値。 + /// 数値形式。の場合はを使用します。 + /// 変換に成功した場合は、それ以外は + /// として解析します。 public static bool TryConvertSingle( ReadOnlySpan value, out float result, @@ -37,6 +60,12 @@ public static bool TryConvertSingle( return float.TryParse(value, NumberStyles.Float, formatProvider ?? CultureInfo.InvariantCulture, out result); } + /// 文字列を倍精度浮動小数点数へ変換します。 + /// 変換する文字列。 + /// 変換に成功した場合の値。 + /// 数値形式。の場合はを使用します。 + /// 変換に成功した場合は、それ以外は + /// として解析します。 public static bool TryConvertDouble( ReadOnlySpan value, out double result, @@ -45,12 +74,29 @@ public static bool TryConvertDouble( return double.TryParse(value, NumberStyles.Float, formatProvider ?? CultureInfo.InvariantCulture, out result); } + /// 文字列を指定型へ変換します。 + /// 変換先型。 + /// 変換する文字列。 + /// 数値および日時形式。の場合はを使用します。 + /// 変換された値。 + /// へ変換できません。 + /// + /// string、bool、short、int、uint、long、ulong、float、double、decimal、 + /// 、Enum、およびこれらのNullable型をサポートします。 + /// Enum名は大文字小文字を区別します。空文字列はNullable型のへ変換されます。 + /// public static T Convert(ReadOnlySpan value, IFormatProvider formatProvider = null) { if (TryConvert(value, out T result, formatProvider)) return result; throw new CsvConversionException(value.ToString(), typeof(T)); } + /// 文字列を指定型へ変換できるか確認します。 + /// 確認する文字列。 + /// 変換先型。 + /// 数値および日時形式。の場合はを使用します。 + /// 変換可能な場合は、それ以外は + /// です。 public static bool CanConvert( ReadOnlySpan value, Type targetType, @@ -73,6 +119,16 @@ public static bool CanConvert( out _); } + /// 文字列を指定型へ変換します。 + /// 変換先型。 + /// 変換する文字列。 + /// 変換に成功した場合の値。失敗した場合は。 + /// 数値および日時形式。の場合はを使用します。 + /// 変換に成功した場合は、それ以外は + /// + /// 対応型とEnumの比較規則はと同じです。 + /// 変換先型ごとの変換処理はジェネリックキャッシュへ保存されます。 + /// public static bool TryConvert( ReadOnlySpan value, out T result, diff --git a/Assets/Plugins/CSVLoader/Runtime/CsvValidation/CsvValidationAttributes.cs b/Assets/Plugins/CSVLoader/Runtime/CsvValidation/CsvValidationAttributes.cs index ae1ca3f..d028459 100644 --- a/Assets/Plugins/CSVLoader/Runtime/CsvValidation/CsvValidationAttributes.cs +++ b/Assets/Plugins/CSVLoader/Runtime/CsvValidation/CsvValidationAttributes.cs @@ -3,33 +3,36 @@ namespace CSV4Unity.Validation { /// - /// 主キー制約 - 値が一意である必要があります + /// 列の各値が空でなく、一意であることを要求します。 /// + /// 値はデコード済み文字列として、大文字小文字を区別して比較されます。 [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] public class PrimaryKeyAttribute : Attribute { } /// - /// NOT NULL制約 - 値が必須です + /// セルが空でないことを要求します。 /// + /// 空文字列を未入力として扱います。空白だけの文字列は空とはみなしません。 [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] public class NotNullAttribute : Attribute { } /// - /// 型制約 - 指定された型に変換可能である必要があります + /// セルを指定型へ変換できることを要求します。 /// [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] public class TypeConstraintAttribute : Attribute { + /// 要求する変換先型を取得します。 public Type ExpectedType { get; } /// - /// 型制約を設定します + /// 型制約を設定します。 /// - /// 期待される型(int, float, string, boolなど) + /// 要求する変換先型。 public TypeConstraintAttribute(Type expectedType) { ExpectedType = expectedType; @@ -37,19 +40,23 @@ public TypeConstraintAttribute(Type expectedType) } /// - /// 範囲制約 - 数値が指定範囲内である必要があります + /// 数値が指定範囲内にあることを要求します。 /// + /// 最小値と最大値を含む範囲として、検証時の形式プロバイダーを使ってdoubleへ変換します。 [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] public class RangeAttribute : Attribute { + /// 許可する最小値を取得します。 public double Min { get; } + + /// 許可する最大値を取得します。 public double Max { get; } /// - /// 数値の範囲制約を設定します + /// 数値の範囲制約を設定します。 /// - /// 最小値 - /// 最大値 + /// 許可する最小値。 + /// 許可する最大値。 public RangeAttribute(double min, double max) { Min = min; @@ -58,25 +65,28 @@ public RangeAttribute(double min, double max) } /// - /// ユニーク制約 - 値が重複してはいけません(NULLは許可) + /// 空でないセルの値が一意であることを要求します。 /// + /// 空セルは検証対象から除外します。値は大文字小文字を区別して比較されます。 [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] public class UniqueAttribute : Attribute { } /// - /// 正規表現制約 - 指定されたパターンに一致する必要があります + /// セル文字列が指定した正規表現に一致することを要求します。 /// + /// 正規表現はで生成されます。 [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] public class RegexAttribute : Attribute { + /// 正規表現パターンを取得します。 public string Pattern { get; } /// - /// 正規表現パターンを設定します + /// 正規表現パターンを設定します。 /// - /// 正規表現パターン + /// 検証に使用する正規表現パターン。 public RegexAttribute(string pattern) { Pattern = pattern; @@ -84,17 +94,19 @@ public RegexAttribute(string pattern) } /// - /// 列挙値制約 - 指定された値のいずれかである必要があります + /// セル文字列が許可値のいずれかと一致することを要求します。 /// + /// 許可値はInvariantCultureで文字列化し、大文字小文字を区別して比較されます。 [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] public class AllowedValuesAttribute : Attribute { + /// 指定された許可値を取得します。 public object[] AllowedValues { get; } /// - /// 許可される値を設定します + /// 許可される値を設定します。 /// - /// 許可される値の配列 + /// 許可する値。 public AllowedValuesAttribute(params object[] allowedValues) { AllowedValues = allowedValues; @@ -102,19 +114,26 @@ public AllowedValuesAttribute(params object[] allowedValues) } /// - /// 外部キー制約 - 他のCSVの指定列に存在する値である必要があります + /// セル文字列が参照先テーブルの指定列に存在することを要求します。 /// + /// + /// 同じEnum型を指定した場合は検証対象テーブル内を参照します。別のEnum型を指定する場合は、 + /// で参照先を登録します。 + /// [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] public class ForeignKeyAttribute : Attribute { + /// 参照先テーブルを識別するEnum型を取得します。 public Type ReferenceEnumType { get; } + + /// 参照先のヘッダー名を取得します。 public string ReferenceField { get; } /// - /// 外部キー制約を設定します + /// 外部キー制約を設定します。 /// - /// 参照先のEnum型 - /// 参照先のフィールド名 + /// 参照先テーブルを識別するEnum型。 + /// 参照先のヘッダー名。 public ForeignKeyAttribute(Type referenceEnumType, string referenceField) { ReferenceEnumType = referenceEnumType; @@ -123,13 +142,16 @@ public ForeignKeyAttribute(Type referenceEnumType, string referenceField) } /// - /// 最小長制約 - 文字列の最小長を指定します + /// セル文字列が指定した最小長以上であることを要求します。 /// [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] public class MinLengthAttribute : Attribute { + /// で判定する最小長を取得します。 public int MinLength { get; } + /// 文字列の最小長を設定します。 + /// で判定する最小長。 public MinLengthAttribute(int minLength) { MinLength = minLength; @@ -137,13 +159,16 @@ public MinLengthAttribute(int minLength) } /// - /// 最大長制約 - 文字列の最大長を指定します + /// セル文字列が指定した最大長以下であることを要求します。 /// [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] public class MaxLengthAttribute : Attribute { + /// で判定する最大長を取得します。 public int MaxLength { get; } + /// 文字列の最大長を設定します。 + /// で判定する最大長。 public MaxLengthAttribute(int maxLength) { MaxLength = maxLength; diff --git a/Assets/Plugins/CSVLoader/Runtime/CsvValidation/CsvValidationContext.cs b/Assets/Plugins/CSVLoader/Runtime/CsvValidation/CsvValidationContext.cs index 9b0a8dc..1683ea0 100644 --- a/Assets/Plugins/CSVLoader/Runtime/CsvValidation/CsvValidationContext.cs +++ b/Assets/Plugins/CSVLoader/Runtime/CsvValidation/CsvValidationContext.cs @@ -6,11 +6,16 @@ namespace CSV4Unity.Validation /// /// ForeignKey検証で参照する別CSVテーブルを保持します。 /// + /// 参照先はEnum型をキーとして保持し、同じ型を再登録した場合は後のテーブルで置き換えます。 public sealed class CsvValidationContext { private readonly Dictionary _documents = new Dictionary(); /// Enum型を識別子として参照先テーブルを登録します。 + /// 参照先テーブルの列を表すEnum型。 + /// 登録する参照先テーブル。 + /// 連続して登録できるよう、このContext自身を返します。 + /// です。 public CsvValidationContext Register(CsvTable table) where TField : struct, Enum { if (table == null) throw new ArgumentNullException(nameof(table)); diff --git a/Assets/Plugins/CSVLoader/Runtime/CsvValidation/CsvValidationResult.cs b/Assets/Plugins/CSVLoader/Runtime/CsvValidation/CsvValidationResult.cs index 28afc7f..a722658 100644 --- a/Assets/Plugins/CSVLoader/Runtime/CsvValidation/CsvValidationResult.cs +++ b/Assets/Plugins/CSVLoader/Runtime/CsvValidation/CsvValidationResult.cs @@ -4,14 +4,24 @@ namespace CSV4Unity.Validation { /// - /// バリデーション結果 + /// CSVテーブルのValidation結果を保持します。 /// public class CsvValidationResult { + /// エラーがなく、Validationに成功したかを取得します。 + /// Warningの有無はこの値に影響しません。 public bool IsValid => Errors.Count == 0; + + /// 検出されたエラーの変更可能なリストを取得します。 public List Errors { get; } = new List(); + + /// 検出されたWarningの変更可能なリストを取得します。 public List Warnings { get; } = new List(); + /// エラーを追加します。 + /// ヘッダーを除くゼロ始まり行番号。列全体のエラーには負数を指定します。 + /// 対象の列名。 + /// エラー内容。 public void AddError(int row, string column, string message) { Errors.Add(new ValidationError @@ -22,6 +32,10 @@ public void AddError(int row, string column, string message) }); } + /// Warningを追加します。 + /// ヘッダーを除くゼロ始まり行番号。列全体のWarningには負数を指定します。 + /// 対象の列名。 + /// Warning内容。 public void AddWarning(int row, string column, string message) { Warnings.Add(new ValidationWarning @@ -32,6 +46,8 @@ public void AddWarning(int row, string column, string message) }); } + /// エラー数とWarning数を含む短い英語の概要を生成します。 + /// Validation結果の概要。末尾に改行を含む場合があります。 public string GetSummary() { if (IsValid && Warnings.Count == 0) @@ -51,11 +67,15 @@ public string GetSummary() return summary; } + /// すべてのエラーを表示用文字列へ変換します。 + /// エラーリストを遅延列挙する文字列シーケンス。 public IEnumerable GetErrorMessages() { return Errors.Select(e => e.ToString()); } + /// すべてのWarningを表示用文字列へ変換します。 + /// Warningリストを遅延列挙する文字列シーケンス。 public IEnumerable GetWarningMessages() { return Warnings.Select(w => w.ToString()); @@ -63,14 +83,22 @@ public IEnumerable GetWarningMessages() } /// - /// バリデーションエラー情報 + /// 1件のValidationエラーを表します。 /// public class ValidationError { + /// ヘッダーを除くゼロ始まり行番号を取得または設定します。 + /// 列全体のエラーの場合は負数。 public int Row { get; set; } + + /// 対象の列名を取得または設定します。 public string Column { get; set; } + + /// エラー内容を取得または設定します。 public string Message { get; set; } + /// 行番号、列名、エラー内容を表示用文字列へ変換します。 + /// 行番号を1始まりで表記したエラー文字列。行番号が負数の場合は列名だけを含みます。 public override string ToString() { if (Row < 0) return $"[Column '{Column}'] {Message}"; @@ -79,14 +107,22 @@ public override string ToString() } /// - /// バリデーション警告情報 + /// 1件のValidation Warningを表します。 /// public class ValidationWarning { + /// ヘッダーを除くゼロ始まり行番号を取得または設定します。 + /// 列全体のWarningの場合は負数。 public int Row { get; set; } + + /// 対象の列名を取得または設定します。 public string Column { get; set; } + + /// Warning内容を取得または設定します。 public string Message { get; set; } + /// 行番号、列名、Warning内容を表示用文字列へ変換します。 + /// 行番号を1始まりで表記したWarning文字列。行番号が負数の場合は列名だけを含みます。 public override string ToString() { if (Row < 0) return $"[Column '{Column}'] {Message}"; diff --git a/Assets/Plugins/CSVLoader/Runtime/CsvValidation/CsvValidationSchema.cs b/Assets/Plugins/CSVLoader/Runtime/CsvValidation/CsvValidationSchema.cs index 585d57c..23985f7 100644 --- a/Assets/Plugins/CSVLoader/Runtime/CsvValidation/CsvValidationSchema.cs +++ b/Assets/Plugins/CSVLoader/Runtime/CsvValidation/CsvValidationSchema.cs @@ -9,6 +9,8 @@ namespace CSV4Unity.Validation /// /// Enumフィールドの制約属性を、再利用可能な検証規則へ変換します。 /// + /// 制約属性を定義したEnum型。 + /// 生成後の規則は変更されず、複数ののValidationに再利用できます。 public sealed class CsvValidationSchema where TField : struct, Enum { private readonly CsvFieldValidationRule[] _rules; @@ -18,10 +20,19 @@ private CsvValidationSchema(CsvFieldValidationRule[] rules) _rules = rules; } + /// Enum型ごとに一度生成される既定スキーマを取得します。 public static CsvValidationSchema Default { get; } = Create(); + + /// 1つ以上の制約属性を持つEnumフィールド数を取得します。 public int RuleCount => _rules.Length; /// Enumに定義された制約属性からスキーマを作成します。 + /// 属性をコンパイルした新しいValidationスキーマ。 + /// 定義された正規表現パターンが不正です。 + /// + /// Reflectionによる属性読み取りと正規表現の生成を行います。繰り返し検証する場合はを再利用してください。 + /// 制約属性を持たないEnumフィールドは規則に含まれません。 + /// public static CsvValidationSchema Create() { FieldInfo[] fields = typeof(TField).GetFields(BindingFlags.Public | BindingFlags.Static); diff --git a/Assets/Plugins/CSVLoader/Runtime/CsvValidation/CsvValidator.cs b/Assets/Plugins/CSVLoader/Runtime/CsvValidation/CsvValidator.cs index 6a1e442..36e9348 100644 --- a/Assets/Plugins/CSVLoader/Runtime/CsvValidation/CsvValidator.cs +++ b/Assets/Plugins/CSVLoader/Runtime/CsvValidation/CsvValidator.cs @@ -7,11 +7,26 @@ namespace CSV4Unity.Validation /// /// Enumに定義された制約属性を使ってCSVテーブルを検証します。 /// + /// Validationは入力テーブルを変更せず、検出内容を新しいへ格納します。 public static class CsvValidator { /// /// Enumの制約属性に従ってテーブルを検証します。読み込んだデータ自体は変更しません。 /// + /// 列と制約属性を定義したEnum型。 + /// 検証するEnum対応テーブル。 + /// + /// 使用するValidationスキーマ。の場合はを使用します。 + /// + /// ForeignKeyの参照先テーブル。参照先が同じテーブルだけの場合はにできます。 + /// 型変換と数値範囲検証に使用する形式。の場合はを使用します。 + /// すべてのエラーとWarningを格納したValidation結果。 + /// です。 + /// + /// PrimaryKeyは空でなく一意、Uniqueは空セルを除いて一意であることを大文字小文字を区別して検証します。 + /// ForeignKeyの参照テーブルまたは列を解決できない場合、その制約を実行せずWarningを追加します。 + /// 空セルはPrimaryKeyとNotNullを除くセル単位制約の対象外です。 + /// public static CsvValidationResult Validate( CsvTable table, CsvValidationSchema validationSchema = null, diff --git a/Assets/Plugins/CSVLoader/Runtime/Data/CsvCell.cs b/Assets/Plugins/CSVLoader/Runtime/Data/CsvCell.cs index 0655e77..82233b8 100644 --- a/Assets/Plugins/CSVLoader/Runtime/Data/CsvCell.cs +++ b/Assets/Plugins/CSVLoader/Runtime/Data/CsvCell.cs @@ -17,25 +17,44 @@ internal CsvCell(string source, CsvCellRange range) _range = range; } + /// セルの内容が空かを取得します。 + /// 空フィールドまたは空のクォートフィールドの場合は public bool IsEmpty => _range.Length == 0; + + /// 入力CSVでセルがダブルクォートに囲まれていたかを取得します。 public bool IsQuoted => (_range.Flags & CsvCellFlags.Quoted) != 0; + + /// セル内に二重化されたダブルクォートが含まれているかを取得します。 public bool HasEscapedQuotes => (_range.Flags & CsvCellFlags.EscapedQuotes) != 0; + + /// 元CSV文字列内のセル内容を割り当てなしで参照します。 + /// 外側のダブルクォートを除き、二重化されたダブルクォートを解除していない文字列範囲。 public ReadOnlySpan RawSpan => _source.AsSpan(_range.Start, _range.Length); - /// CSVのエスケープを解除した文字列を返します。 + /// CSVのダブルクォートエスケープを解除した文字列を返します。 + /// セルのデコード済み文字列。 + /// 戻り値として新しい文字列を生成します。 public string GetString() { return Decode(_source, _range); } - /// セルを指定型へ変換し、失敗時はCsvConversionExceptionを送出します。 + /// セルを指定型へ変換します。 + /// 変換先型。 + /// 数値および日時形式。の場合はInvariantCultureを使用します。 + /// 変換された値。 + /// へ変換できません。 public T Get(IFormatProvider formatProvider = null) { if (TryGet(out T value, formatProvider)) return value; throw new CsvConversionException(GetString(), typeof(T)); } - /// セルを指定型へ変換できる場合に値を返します。 + /// セルを指定型へ変換します。 + /// 変換先型。 + /// 変換に成功した場合の値。失敗した場合は。 + /// 数値および日時形式。の場合はInvariantCultureを使用します。 + /// 変換に成功した場合は、それ以外は public bool TryGet(out T value, IFormatProvider formatProvider = null) { if (typeof(T) == typeof(string)) @@ -54,6 +73,10 @@ public bool TryGet(out T value, IFormatProvider formatProvider = null) } /// 例外を送出せず、指定型へ変換可能かを確認します。 + /// 変換先型。 + /// 数値および日時形式。の場合はInvariantCultureを使用します。 + /// 変換可能な場合は、それ以外は + /// です。 public bool CanGet(Type targetType, IFormatProvider formatProvider = null) { if (!HasEscapedQuotes) @@ -65,6 +88,10 @@ public bool CanGet(Type targetType, IFormatProvider formatProvider = null) return CsvValueConverter.CanConvert(decoded.AsSpan(), targetType, formatProvider); } + /// セルを32ビット符号付き整数へ変換します。 + /// 変換に成功した場合の値。 + /// 変換に成功した場合は、それ以外は + /// InvariantCultureを使用します。 public bool TryGetInt32(out int value) { if (!HasEscapedQuotes) @@ -76,12 +103,19 @@ public bool TryGetInt32(out int value) return false; } + /// セルを32ビット符号付き整数として取得します。 + /// 変換された値。 + /// 32ビット符号付き整数へ変換できません。 public int GetInt32() { if (TryGetInt32(out int value)) return value; throw new CsvConversionException(GetString(), typeof(int)); } + /// セルを64ビット符号付き整数へ変換します。 + /// 変換に成功した場合の値。 + /// 変換に成功した場合は、それ以外は + /// InvariantCultureを使用します。 public bool TryGetInt64(out long value) { if (!HasEscapedQuotes) @@ -93,12 +127,19 @@ public bool TryGetInt64(out long value) return false; } + /// セルを64ビット符号付き整数として取得します。 + /// 変換された値。 + /// 64ビット符号付き整数へ変換できません。 public long GetInt64() { if (TryGetInt64(out long value)) return value; throw new CsvConversionException(GetString(), typeof(long)); } + /// セルを単精度浮動小数点数へ変換します。 + /// 変換に成功した場合の値。 + /// 変換に成功した場合は、それ以外は + /// InvariantCultureを使用します。 public bool TryGetSingle(out float value) { if (!HasEscapedQuotes) @@ -110,12 +151,19 @@ public bool TryGetSingle(out float value) return false; } + /// セルを単精度浮動小数点数として取得します。 + /// 変換された値。 + /// 単精度浮動小数点数へ変換できません。 public float GetSingle() { if (TryGetSingle(out float value)) return value; throw new CsvConversionException(GetString(), typeof(float)); } + /// セルを倍精度浮動小数点数へ変換します。 + /// 変換に成功した場合の値。 + /// 変換に成功した場合は、それ以外は + /// InvariantCultureを使用します。 public bool TryGetDouble(out double value) { if (!HasEscapedQuotes) @@ -127,12 +175,18 @@ public bool TryGetDouble(out double value) return false; } + /// セルを倍精度浮動小数点数として取得します。 + /// 変換された値。 + /// 倍精度浮動小数点数へ変換できません。 public double GetDouble() { if (TryGetDouble(out double value)) return value; throw new CsvConversionException(GetString(), typeof(double)); } + /// セルをBoolean値へ変換します。 + /// 変換に成功した場合の値。 + /// 変換に成功した場合は、それ以外は public bool TryGetBoolean(out bool value) { if (!HasEscapedQuotes) @@ -144,12 +198,17 @@ public bool TryGetBoolean(out bool value) return false; } + /// セルをBoolean値として取得します。 + /// 変換された値。 + /// Boolean値へ変換できません。 public bool GetBoolean() { if (TryGetBoolean(out bool value)) return value; throw new CsvConversionException(GetString(), typeof(bool)); } + /// CSVのエスケープを解除したセル文字列を返します。 + /// と同じ文字列。 public override string ToString() { return GetString(); diff --git a/Assets/Plugins/CSVLoader/Runtime/Data/CsvColumn.cs b/Assets/Plugins/CSVLoader/Runtime/Data/CsvColumn.cs index 090a5ba..40cb7a5 100644 --- a/Assets/Plugins/CSVLoader/Runtime/Data/CsvColumn.cs +++ b/Assets/Plugins/CSVLoader/Runtime/Data/CsvColumn.cs @@ -3,6 +3,7 @@ namespace CSV4Unity /// /// CsvDocument内の1列を参照する軽量なビューです。 /// + /// この型はセルを所有せず、生成元のを参照します。 public readonly struct CsvColumn { private readonly CsvDocument _document; @@ -13,9 +14,20 @@ internal CsvColumn(CsvDocument document, int index) Index = index; } + /// ゼロ始まりの列番号を取得します。 public int Index { get; } + + /// ヘッダー名を取得します。 + /// ヘッダーなしで解析した場合は空文字列。 public string Name => _document.GetHeader(Index); + + /// ヘッダーを除くデータ行数を取得します。 public int Count => _document.RowCount; + + /// 行番号からセルを取得します。 + /// ヘッダーを除くゼロ始まりの行番号。 + /// 指定行のセル。 + /// が範囲外です。 public CsvCell this[int rowIndex] => _document.Cell(rowIndex, Index); internal CsvDocument Document => _document; } diff --git a/Assets/Plugins/CSVLoader/Runtime/Data/CsvDocument.cs b/Assets/Plugins/CSVLoader/Runtime/Data/CsvDocument.cs index f494e36..c3ce090 100644 --- a/Assets/Plugins/CSVLoader/Runtime/Data/CsvDocument.cs +++ b/Assets/Plugins/CSVLoader/Runtime/Data/CsvDocument.cs @@ -6,6 +6,10 @@ namespace CSV4Unity /// /// 元のCSV文字列とセル位置を所有する、読み取り専用のCSVドキュメントです。 /// + /// + /// 行番号と列番号はゼロ始まりです。ヘッダーを使用する場合、ヘッダーレコードはと行番号に含まれません。 + /// この型が元CSV文字列とセル位置を所有し、はその内容を参照します。 + /// public sealed class CsvDocument { private readonly string _source; @@ -29,13 +33,26 @@ internal CsvDocument(string name, string source, string[] headers, CsvCellRange[ } } + /// ログやValidation結果で使用できるドキュメントの識別名を取得します。 public string Name { get; } + + /// ヘッダーを除いたデータ行数を取得します。 public int RowCount { get; } + + /// 各レコードの列数を取得します。 public int ColumnCount { get; } + + /// 宣言順のヘッダー名を取得します。 + /// ヘッダーなしで解析した場合は空のリスト。 public IReadOnlyList Headers => _headers; + + /// CSVをヘッダー付きとして解析したかを取得します。 public bool HasHeader => _headers.Length > 0; /// 指定した行を参照するビューを返します。 + /// ヘッダーを除くゼロ始まりの行番号。 + /// 指定行を参照する軽量なビュー。 + /// が範囲外です。 public CsvRow Row(int rowIndex) { ValidateRowIndex(rowIndex); @@ -43,6 +60,9 @@ public CsvRow Row(int rowIndex) } /// 列番号から列ビューを返します。 + /// ゼロ始まりの列番号。 + /// 指定列を参照する軽量なビュー。 + /// が範囲外です。 public CsvColumn Column(int columnIndex) { ValidateColumnIndex(columnIndex); @@ -50,12 +70,20 @@ public CsvColumn Column(int columnIndex) } /// ヘッダー名から列ビューを返します。 + /// 検索するヘッダー名。大文字小文字を区別します。 + /// 指定列を参照する軽量なビュー。 + /// です。 + /// 指定したヘッダーが存在しません。 public CsvColumn Column(string header) { return Column(GetColumnIndex(header)); } /// 行番号と列番号からセルを返します。 + /// ヘッダーを除くゼロ始まりの行番号。 + /// ゼロ始まりの列番号。 + /// 指定位置のセル。 + /// またはが範囲外です。 public CsvCell Cell(int rowIndex, int columnIndex) { ValidateRowIndex(rowIndex); @@ -64,17 +92,31 @@ public CsvCell Cell(int rowIndex, int columnIndex) } /// 行番号とヘッダー名からセルを返します。 + /// ヘッダーを除くゼロ始まりの行番号。 + /// 検索するヘッダー名。大文字小文字を区別します。 + /// 指定位置のセル。 + /// が範囲外です。 + /// です。 + /// 指定したヘッダーが存在しません。 public CsvCell Cell(int rowIndex, string header) { return Cell(rowIndex, GetColumnIndex(header)); } /// Enumとヘッダーを対応付けたテーブルを生成します。 + /// CSVヘッダーと同名のフィールドを持つEnum型。 + /// Enumで列を指定できるテーブル。 + /// ヘッダーがないか、Enumの各フィールドをヘッダーへ一意に対応付けられません。 public CsvTable WithFields() where TField : struct, Enum { return new CsvTable(this); } + /// ヘッダー名に対応する列番号を取得します。 + /// 検索するヘッダー名。大文字小文字を区別します。 + /// ゼロ始まりの列番号。 + /// です。 + /// 指定したヘッダーが存在しません。 public int GetColumnIndex(string header) { if (header == null) throw new ArgumentNullException(nameof(header)); diff --git a/Assets/Plugins/CSVLoader/Runtime/Data/CsvRow.cs b/Assets/Plugins/CSVLoader/Runtime/Data/CsvRow.cs index f275cea..08d473f 100644 --- a/Assets/Plugins/CSVLoader/Runtime/Data/CsvRow.cs +++ b/Assets/Plugins/CSVLoader/Runtime/Data/CsvRow.cs @@ -3,6 +3,7 @@ namespace CSV4Unity /// /// CsvDocument内の1行を参照する軽量なビューです。 /// + /// この型はセルを所有せず、生成元のを参照します。 public readonly struct CsvRow { private readonly CsvDocument _document; @@ -13,9 +14,23 @@ internal CsvRow(CsvDocument document, int index) Index = index; } + /// ヘッダーを除くゼロ始まりの行番号を取得します。 public int Index { get; } + + /// 行に含まれる列数を取得します。 public int Count => _document.ColumnCount; + + /// 列番号からセルを取得します。 + /// ゼロ始まりの列番号。 + /// 指定列のセル。 + /// が範囲外です。 public CsvCell this[int columnIndex] => _document.Cell(Index, columnIndex); + + /// ヘッダー名からセルを取得します。 + /// 検索するヘッダー名。大文字小文字を区別します。 + /// 指定列のセル。 + /// です。 + /// 指定したヘッダーが存在しません。 public CsvCell this[string header] => _document.Cell(Index, header); } } diff --git a/Assets/Plugins/CSVLoader/Runtime/Data/CsvTable.cs b/Assets/Plugins/CSVLoader/Runtime/Data/CsvTable.cs index 7253c64..9f29c7a 100644 --- a/Assets/Plugins/CSVLoader/Runtime/Data/CsvTable.cs +++ b/Assets/Plugins/CSVLoader/Runtime/Data/CsvTable.cs @@ -5,6 +5,7 @@ namespace CSV4Unity /// /// CsvDocumentとEnumスキーマを組み合わせ、Enumによる列アクセスを提供します。 /// + /// CSVヘッダーと同名のフィールドを持つEnum型。 public sealed class CsvTable where TField : struct, Enum { internal CsvTable(CsvDocument document) @@ -12,6 +13,11 @@ internal CsvTable(CsvDocument document) { } + /// ドキュメントと対応済みスキーマを組み合わせてテーブルを生成します。 + /// セルデータを所有するドキュメント。 + /// 同じドキュメントへ対応付けられたEnumスキーマ。 + /// またはです。 + /// が別のドキュメントへ対応付けられています。 public CsvTable(CsvDocument document, CsvEnumSchema schema) { Document = document ?? throw new ArgumentNullException(nameof(document)); @@ -22,22 +28,43 @@ public CsvTable(CsvDocument document, CsvEnumSchema schema) } } + /// セルデータを所有するドキュメントを取得します。 public CsvDocument Document { get; } + + /// Enumフィールドと列番号の対応を取得します。 public CsvEnumSchema Schema { get; } + + /// ヘッダーを除くデータ行数を取得します。 public int RowCount => Document.RowCount; + + /// ドキュメント全体の列数を取得します。 + /// Enumフィールド数が必要な場合はを使用します。 public int ColumnCount => Document.ColumnCount; + /// 指定した行を参照するEnum対応ビューを返します。 + /// ヘッダーを除くゼロ始まりの行番号。 + /// 指定行を参照する軽量なビュー。 + /// が範囲外です。 public CsvRow Row(int rowIndex) { Document.Row(rowIndex); return new CsvRow(this, rowIndex); } + /// Enumフィールドから列ビューを返します。 + /// 検索するEnumフィールド。 + /// 指定列を参照する軽量なビュー。 + /// がスキーマに含まれません。 public CsvColumn Column(TField field) { return new CsvColumn(this, field, GetColumnIndex(field)); } + /// 行番号とEnumフィールドからセルを返します。 + /// ヘッダーを除くゼロ始まりの行番号。 + /// 検索するEnumフィールド。 + /// 指定位置のセル。 + /// が範囲外、またはがスキーマに含まれません。 public CsvCell Cell(int rowIndex, TField field) { return Document.Cell(rowIndex, GetColumnIndex(field)); @@ -50,6 +77,8 @@ internal int GetColumnIndex(TField field) } /// Enumで列を指定できる行ビューです。 + /// 列を指定するEnum型。 + /// この型はセルを所有せず、生成元のを参照します。 public readonly struct CsvRow where TField : struct, Enum { private readonly CsvTable _table; @@ -60,12 +89,22 @@ internal CsvRow(CsvTable table, int index) Index = index; } + /// ヘッダーを除くゼロ始まりの行番号を取得します。 public int Index { get; } + + /// ドキュメント全体の列数を取得します。 public int Count => _table.ColumnCount; + + /// Enumフィールドからセルを取得します。 + /// 検索するEnumフィールド。 + /// 指定列のセル。 + /// がスキーマに含まれません。 public CsvCell this[TField field] => _table.Cell(Index, field); } /// Enumで選択された列を参照するビューです。 + /// 列を指定するEnum型。 + /// この型はセルを所有せず、生成元のを参照します。 public readonly struct CsvColumn where TField : struct, Enum { private readonly CsvTable _table; @@ -77,9 +116,19 @@ internal CsvColumn(CsvTable table, TField field, int index) Index = index; } + /// この列に対応するEnumフィールドを取得します。 public TField Field { get; } + + /// ゼロ始まりの列番号を取得します。 public int Index { get; } + + /// ヘッダーを除くデータ行数を取得します。 public int Count => _table.RowCount; + + /// 行番号からセルを取得します。 + /// ヘッダーを除くゼロ始まりの行番号。 + /// 指定行のセル。 + /// が範囲外です。 public CsvCell this[int rowIndex] => _table.Document.Cell(rowIndex, Index); internal CsvDocument Document => _table.Document; } diff --git a/Assets/Plugins/CSVLoader/Runtime/Indexing/CsvIndex.cs b/Assets/Plugins/CSVLoader/Runtime/Indexing/CsvIndex.cs index 5d0924b..95c1c0b 100644 --- a/Assets/Plugins/CSVLoader/Runtime/Indexing/CsvIndex.cs +++ b/Assets/Plugins/CSVLoader/Runtime/Indexing/CsvIndex.cs @@ -6,6 +6,11 @@ namespace CSV4Unity /// /// 指定列の値から行番号を検索する、明示生成型のインデックスです。 /// + /// 検索キーへ変換する型。 + /// + /// 生成時に指定列の全データ行を走査し、同じキーに一致する複数の行番号を入力順で保持します。 + /// 元のは読み取り専用のため、生成後にIndexを同期する処理はありません。 + /// public sealed class CsvIndex { private readonly Dictionary _firstRows; @@ -17,9 +22,17 @@ private CsvIndex(Dictionary firstRows, Dictionary> ad _additionalRows = additionalRows; } + /// 重複を除いたキー数を取得します。 public int KeyCount => _firstRows.Count; /// 非ジェネリック列からインデックスを作成します。 + /// 検索対象の列。 + /// 空セルをIndexへ含めない場合は。 + /// キー変換に使用する形式。の場合はInvariantCultureを使用します。 + /// キーの等価比較。の場合はを使用します。 + /// 指定列から生成されたIndex。 + /// セルをへ変換できません。 + /// で、変換結果がです。 public static CsvIndex Create( CsvColumn column, bool skipEmpty = true, @@ -30,6 +43,14 @@ public static CsvIndex Create( } /// Enumで選択された列からインデックスを作成します。 + /// 列を指定するEnum型。 + /// 検索対象のEnum対応列。 + /// 空セルをIndexへ含めない場合は。 + /// キー変換に使用する形式。の場合はInvariantCultureを使用します。 + /// キーの等価比較。の場合はを使用します。 + /// 指定列から生成されたIndex。 + /// セルをへ変換できません。 + /// で、変換結果がです。 public static CsvIndex Create( CsvColumn column, bool skipEmpty = true, @@ -85,11 +106,20 @@ private static CsvIndex Build( return new CsvIndex(firstRows, additionalRows); } + /// キーに最初に一致する行番号を検索します。 + /// 検索キー。 + /// 一致した最初のゼロ始まり行番号。 + /// 一致する行が存在する場合は、それ以外は + /// で、基になるDictionaryがnullキーを許可しません。 public bool TryFindFirst(TKey key, out int rowIndex) { return _firstRows.TryGetValue(key, out rowIndex); } + /// キーに一致するすべての行番号を検索します。 + /// 検索キー。 + /// 入力順の行番号を参照する検索結果。一致しない場合は空の結果。 + /// で、基になるDictionaryがnullキーを許可しません。 public CsvIndexMatches FindAll(TKey key) { if (!_firstRows.TryGetValue(key, out int firstRow)) return CsvIndexMatches.Empty; @@ -99,6 +129,7 @@ public CsvIndexMatches FindAll(TKey key) } /// インデックス検索に一致した行番号を参照します。 + /// 行番号はゼロ始まりで、元CSVの入力順に並びます。 public readonly struct CsvIndexMatches { private readonly int _firstRow; @@ -110,9 +141,16 @@ internal CsvIndexMatches(int firstRow, IReadOnlyList additionalRows) _additionalRows = additionalRows; } + /// 一致する行がない検索結果を取得します。 public static CsvIndexMatches Empty => new CsvIndexMatches(-1, null); + + /// 一致した行数を取得します。 public int Count => _firstRow < 0 ? 0 : 1 + (_additionalRows?.Count ?? 0); + /// 入力順の行番号を取得します。 + /// 検索結果内のゼロ始まり位置。 + /// 元ドキュメント内のゼロ始まり行番号。 + /// が範囲外です。 public int this[int index] { get diff --git a/Assets/Plugins/CSVLoader/Runtime/Parsing/CsvParseException.cs b/Assets/Plugins/CSVLoader/Runtime/Parsing/CsvParseException.cs index f3eb592..dd0bffd 100644 --- a/Assets/Plugins/CSVLoader/Runtime/Parsing/CsvParseException.cs +++ b/Assets/Plugins/CSVLoader/Runtime/Parsing/CsvParseException.cs @@ -2,10 +2,19 @@ namespace CSV4Unity { + /// + /// CSVの構文またはレコード構造を解析できない場合に送出される例外です。 + /// public sealed class CsvParseException : FormatException { + /// エラーが検出されたレコードのゼロ始まり番号を取得します。 + /// ヘッダーを含む入力上のレコード番号。 public int RecordIndex { get; } + + /// エラーが検出されたフィールドのゼロ始まり番号を取得します。 public int FieldIndex { get; } + + /// 入力文字列内でエラーが検出されたゼロ始まり位置を取得します。 public int CharacterIndex { get; } internal CsvParseException(string message, int recordIndex, int fieldIndex, int characterIndex) diff --git a/Assets/Plugins/CSVLoader/Runtime/Parsing/CsvParseOptions.cs b/Assets/Plugins/CSVLoader/Runtime/Parsing/CsvParseOptions.cs index 8c58c44..7fd7712 100644 --- a/Assets/Plugins/CSVLoader/Runtime/Parsing/CsvParseOptions.cs +++ b/Assets/Plugins/CSVLoader/Runtime/Parsing/CsvParseOptions.cs @@ -6,15 +6,22 @@ namespace CSV4Unity public sealed class CsvParseOptions { /// 先頭レコードをヘッダーとして扱うかを指定します。 + /// ヘッダーとして扱う場合は。既定値はです。 public bool HasHeader { get; set; } = true; /// フィールドの区切り文字を指定します。 + /// 1文字の区切り文字。既定値はカンマです。 + /// ダブルクォート、CR、LFは指定できません。 public char Delimiter { get; set; } = ','; /// 空レコードを読み飛ばすかを指定します。 + /// 空レコードを結果に含めない場合は。既定値はです。 + /// 区切り文字を含まず、単一の空フィールドだけで構成されるレコードを空レコードとして扱います。 public bool IgnoreEmptyRecords { get; set; } /// クォートされていないフィールドの前後空白を除去するかを指定します。 + /// 前後空白を除去する場合は。既定値はです。 + /// クォートされたフィールド内の空白は除去しません。 public bool TrimUnquotedFields { get; set; } } } diff --git a/Assets/Plugins/CSVLoader/Runtime/Parsing/CsvParser.cs b/Assets/Plugins/CSVLoader/Runtime/Parsing/CsvParser.cs index 4c75c38..8c2403e 100644 --- a/Assets/Plugins/CSVLoader/Runtime/Parsing/CsvParser.cs +++ b/Assets/Plugins/CSVLoader/Runtime/Parsing/CsvParser.cs @@ -11,6 +11,17 @@ public static class CsvParser /// /// CSV文字列を解析します。セル値の型推測やValidationは行いません。 /// + /// 解析するCSV文字列。先頭のUTF-8 BOM文字は読み飛ばします。 + /// 解析方法。の場合は既定値を使用します。 + /// 生成するドキュメントの識別名。の場合は空文字列を使用します。 + /// 元文字列とセル位置を保持する読み取り専用ドキュメント。 + /// です。 + /// 区切り文字にダブルクォートまたは改行文字が指定されています。 + /// クォート構文、レコード終端、列数、またはヘッダーが不正です。 + /// + /// CRLF、CR、LFをレコード終端として認識し、クォートされたフィールド内の改行はセル値として保持します。 + /// ヘッダー名は大文字小文字を区別し、重複を許可しません。 + /// public static CsvDocument Parse(string source, CsvParseOptions options = null, string name = null) { if (source == null) throw new ArgumentNullException(nameof(source)); diff --git a/Assets/Plugins/CSVLoader/Runtime/Schema/CsvEnumSchema.cs b/Assets/Plugins/CSVLoader/Runtime/Schema/CsvEnumSchema.cs index adafc4a..dc8ee13 100644 --- a/Assets/Plugins/CSVLoader/Runtime/Schema/CsvEnumSchema.cs +++ b/Assets/Plugins/CSVLoader/Runtime/Schema/CsvEnumSchema.cs @@ -6,6 +6,8 @@ namespace CSV4Unity /// /// Enum値とCSVの列番号を対応付けた不変スキーマです。 /// + /// CSVヘッダーと同名のフィールドを持つEnum型。 + /// Enum名とヘッダー名は相当で比較し、大文字小文字を区別します。 public sealed class CsvEnumSchema where TField : struct, Enum { private static readonly TField[] DeclaredFields = (TField[])Enum.GetValues(typeof(TField)); @@ -19,11 +21,22 @@ private CsvEnumSchema(CsvDocument document, Dictionary columnIndice _columnIndices = columnIndices; } + /// このスキーマを対応付けたドキュメントを取得します。 public CsvDocument Document { get; } + + /// 対応付けられたEnumフィールド数を取得します。 public int FieldCount => _columnIndices.Count; + + /// 宣言順のEnumフィールドを割り当てなしで参照します。 public ReadOnlySpan Fields => DeclaredFields; /// Enum名とCSVヘッダー名を対応付けます。 + /// ヘッダー付きで解析されたドキュメント。 + /// 指定ドキュメントに対応付けられた不変スキーマ。 + /// です。 + /// + /// ヘッダーがない、必要なヘッダーが存在しない、またはEnumに同じ値を持つ別名フィールドがあります。 + /// public static CsvEnumSchema Bind(CsvDocument document) { if (document == null) throw new ArgumentNullException(nameof(document)); @@ -59,12 +72,20 @@ public static CsvEnumSchema Bind(CsvDocument document) return new CsvEnumSchema(document, columnIndices); } + /// Enumフィールドに対応する列番号を取得します。 + /// 検索するEnumフィールド。 + /// ゼロ始まりの列番号。 + /// がスキーマに含まれません。 public int GetColumnIndex(TField field) { if (_columnIndices.TryGetValue(field, out int columnIndex)) return columnIndex; throw new ArgumentOutOfRangeException(nameof(field), field, "The enum value is not part of this CSV schema."); } + /// Enumフィールドに対応する列番号を取得します。 + /// 検索するEnumフィールド。 + /// 対応付けが存在する場合のゼロ始まり列番号。 + /// 対応付けが存在する場合は、それ以外は public bool TryGetColumnIndex(TField field, out int columnIndex) { return _columnIndices.TryGetValue(field, out columnIndex); diff --git a/Assets/Plugins/CSVLoader/Runtime/Schema/CsvSchemaException.cs b/Assets/Plugins/CSVLoader/Runtime/Schema/CsvSchemaException.cs index 1cf85de..a40ad56 100644 --- a/Assets/Plugins/CSVLoader/Runtime/Schema/CsvSchemaException.cs +++ b/Assets/Plugins/CSVLoader/Runtime/Schema/CsvSchemaException.cs @@ -2,13 +2,21 @@ namespace CSV4Unity { + /// + /// CSVヘッダーとEnumスキーマを対応付けられない場合に送出される例外です。 + /// public sealed class CsvSchemaException : InvalidOperationException { + /// エラー内容を指定して例外を生成します。 + /// エラー内容。 public CsvSchemaException(string message) : base(message) { } + /// エラー内容と原因となった例外を指定して例外を生成します。 + /// エラー内容。 + /// この例外の原因となった例外。 public CsvSchemaException(string message, Exception innerException) : base(message, innerException) { diff --git a/README.md b/README.md index 4355270..64e899b 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,12 @@ CSVをクラスへ一括変換せず、セルを必要なときに指定した > [!IMPORTANT] > 現在は1.0未満の再設計中です。APIは今後も変更される可能性があります。利用時はGitのタグまたはコミットを固定してください。 +## ドキュメント + +- [APIリファレンス](https://cotore-game.github.io/CSV4Unity/) +- [コア設計(日本語)](./docs/ja/architecture.md) +- [Core architecture (English)](./docs/en/architecture.md) + ## 主な機能 - RFC 4180形式のクォート、カンマ、二重引用符、クォート内改行を解析 diff --git a/README_EN.md b/README_EN.md index dd84ab9..75720fe 100644 --- a/README_EN.md +++ b/README_EN.md @@ -7,6 +7,12 @@ CSV4Unity reads CSV text into row, column, and cell views for Unity. Values rema > [!IMPORTANT] > The library is currently being redesigned before 1.0. Pin a release tag or commit when using the Git package URL. +## Documentation + +- [API reference](https://cotore-game.github.io/CSV4Unity/) +- [Core architecture (Japanese)](./docs/ja/architecture.md) +- [Core architecture (English)](./docs/en/architecture.md) + ## Features - RFC 4180 quoted fields, escaped quotes, commas, and embedded line breaks diff --git a/docs/CSV4Unity.Docs.csproj b/docs/CSV4Unity.Docs.csproj new file mode 100644 index 0000000..8da83de --- /dev/null +++ b/docs/CSV4Unity.Docs.csproj @@ -0,0 +1,29 @@ + + + + + netstandard2.1 + latest + false + true + $(NoWarn);CS0436 + $(WarningsAsErrors);CS0419;CS1570;CS1572;CS1573;CS1584;CS1587;CS1591;CS1658 + + /opt/unity/Editor/Data + $(UnityEditorContents)/Resources/Scripting/Managed + $(UnityEditorContents)/Managed + $(MSBuildThisFileDirectory)../Assets/Plugins/CSVLoader/Runtime + + + + + + + + + + + diff --git a/docs/README.md b/docs/README.md index 97aa897..4020ae2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,3 +6,41 @@ CSV4Unityを開発・保守する人向けの資料です。 - [English: Core architecture](en/architecture.md) 現時点では日本語版を正本として更新します。英語版は設計が安定した段階で追従させます。 + +## 言語方針 + +- 公開APIの識別子は英語で命名します。 +- 公開APIのXMLドキュメントコメントは日本語を正本とします。 +- 実装意図を補足する通常コメントも、必要な場所に日本語で記載します。 +- 英語版APIドキュメントは、仕様が安定してから別のDocFXサイトまたは翻訳用ファイルとして整備します。 +- 長い使用例はXMLコメントへ重複させず、READMEや手書きガイドへ記載します。 + +DocFX専用ビルドでは、公開APIのXMLコメント欠落、引数タグの不一致、不正なXMLおよび`cref`をコンパイルエラーとして扱います。 + +## APIリファレンス + +公開APIのリファレンスは、RuntimeコードのXMLドキュメントコメントからDocFXで生成します。 + +- 設定: `docs/docfx.json` +- 解析用プロジェクト: `docs/CSV4Unity.Docs.csproj` +- GitHub Actions: `.github/workflows/docs.yml` +- 公開先: + +GitHubではPR時にビルドだけを検証し、`main`へのpush、Release公開、手動実行時にGitHub Pagesへデプロイします。リポジトリのSettingsから、PagesのSourceを `GitHub Actions` に設定する必要があります。 + +### ローカル生成 + +.NET SDK 8.0以降とDocFX 2.78.5を用意し、Unity 6000.0.73f1のインストール先を指定して実行します。 + +```powershell +dotnet tool install --global docfx --version 2.78.5 +./docs/build.ps1 +``` + +Unityを標準以外の場所へインストールしている場合は、`Editor/Data`を指定します。 + +```powershell +./docs/build.ps1 -UnityEditorContents "D:\Unity\6000.0.73f1\Editor\Data" +``` + +生成物は `docs/_site/` に出力され、Git管理対象には含まれません。 diff --git a/docs/build.ps1 b/docs/build.ps1 new file mode 100644 index 0000000..bb5983d --- /dev/null +++ b/docs/build.ps1 @@ -0,0 +1,17 @@ +param( + [string]$UnityEditorContents = "C:\Program Files\Unity\Hub\Editor\6000.0.73f1\Editor\Data" +) + +$ErrorActionPreference = "Stop" +$env:UnityEditorContents = $UnityEditorContents + +Push-Location $PSScriptRoot +try { + dotnet restore CSV4Unity.Docs.csproj + docfx metadata docfx.json + docfx build docfx.json + Write-Host "CSV4Unity API site generated at: $PSScriptRoot\_site\index.html" +} +finally { + Pop-Location +} diff --git a/docs/docfx.json b/docs/docfx.json new file mode 100644 index 0000000..67eff93 --- /dev/null +++ b/docs/docfx.json @@ -0,0 +1,32 @@ +{ + "metadata": [ + { + "src": [ + { + "files": ["CSV4Unity.Docs.csproj"], + "src": "." + } + ], + "dest": "api", + "outputFormat": "mref", + "namespaceLayout": "nested", + "memberLayout": "separatePages", + "filter": "filterConfig.yml" + } + ], + "build": { + "content": [ + { "files": ["api/**.yml", "api/index.md"] }, + { "files": ["index.md", "toc.yml", "ja/**.md", "en/**.md"] } + ], + "output": "_site", + "template": ["default", "modern"], + "globalMetadata": { + "_appName": "CSV4Unity", + "_appTitle": "CSV4Unity API Reference", + "_appFooter": "CSV4Unity - RFC 4180 CSV reader for Unity. MIT License.", + "_enableSearch": true, + "_disableContribution": false + } + } +} diff --git a/docs/filterConfig.yml b/docs/filterConfig.yml new file mode 100644 index 0000000..801c1e0 --- /dev/null +++ b/docs/filterConfig.yml @@ -0,0 +1,15 @@ +# CSV4Unity自身の公開APIだけをリファレンスへ掲載します。 +apiRules: + - exclude: + uidRegex: ^System\. + - exclude: + uidRegex: ^Unity\. + - exclude: + uidRegex: ^UnityEngine\. + - exclude: + uidRegex: ^UnityEditor\. + - exclude: + hasAttribute: + uid: System.ComponentModel.EditorBrowsableAttribute + ctorArguments: + - System.ComponentModel.EditorBrowsableState.Never diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..336170f --- /dev/null +++ b/docs/index.md @@ -0,0 +1,10 @@ +# CSV4Unity + +CSV4Unityは、RFC 4180形式のCSVをUnityで扱うためのライブラリです。 + +- [APIリファレンス](api/index.md) +- [コア設計(日本語)](ja/architecture.md) +- [Core architecture (English)](en/architecture.md) +- [GitHubリポジトリ](https://github.com/cotore-game/CSV4Unity) + +APIリファレンスは、RuntimeコードのXMLドキュメントコメントから自動生成されます。 diff --git a/docs/toc.yml b/docs/toc.yml new file mode 100644 index 0000000..e67cc19 --- /dev/null +++ b/docs/toc.yml @@ -0,0 +1,8 @@ +- name: Home + href: index.md +- name: APIリファレンス + href: api/ +- name: コア設計(日本語) + href: ja/architecture.md +- name: Core architecture (English) + href: en/architecture.md