using System.Text; namespace LehrerApp.Core.Importing; internal sealed record DelimitedRecord(int LineNumber, IReadOnlyList Fields); internal static class DelimitedTextParser { public static bool TryParse( string text, char delimiter, out List records, out string? error) { records = []; error = null; var fields = new List(); var field = new StringBuilder(); var inQuotes = false; var line = 1; var recordStartLine = 1; for (var index = 0; index < text.Length; index++) { var current = text[index]; if (current == '"') { if (inQuotes && index + 1 < text.Length && text[index + 1] == '"') { field.Append('"'); index++; } else { inQuotes = !inQuotes; } continue; } if (current == delimiter && !inQuotes) { fields.Add(field.ToString()); field.Clear(); continue; } if ((current == '\r' || current == '\n') && !inQuotes) { if (current == '\r' && index + 1 < text.Length && text[index + 1] == '\n') index++; fields.Add(field.ToString()); field.Clear(); records.Add(new DelimitedRecord(recordStartLine, fields.ToList())); fields.Clear(); line++; recordStartLine = line; continue; } if (current == '\n') line++; field.Append(current); } if (inQuotes) { error = $"Ein Textfeld ab Zeile {recordStartLine} besitzt kein schließendes Anführungszeichen."; return false; } if (field.Length > 0 || fields.Count > 0) { fields.Add(field.ToString()); records.Add(new DelimitedRecord(recordStartLine, fields.ToList())); } return true; } }