using System; using System.Collections.Generic; using System.Text; namespace PKHeX.Core; /// /// Processes input of strings into a list of valid Filters and Instructions. /// public sealed class StringInstructionSet { /// /// Filters to check if the object should be modified. /// public readonly IReadOnlyList Filters; /// /// Instructions to modify the object. /// public readonly IReadOnlyList Instructions; private const char SetSeparatorChar = ';'; public StringInstructionSet(IReadOnlyList filters, IReadOnlyList instructions) { Filters = filters; Instructions = instructions; } public StringInstructionSet(ReadOnlySpan text) { var set = text.EnumerateLines(); Filters = StringInstruction.GetFilters(set); Instructions = StringInstruction.GetInstructions(set); } public StringInstructionSet(SpanLineEnumerator set) { Filters = StringInstruction.GetFilters(set); Instructions = StringInstruction.GetInstructions(set); } public StringInstructionSet(ReadOnlySpan set) { Filters = StringInstruction.GetFilters(set); Instructions = StringInstruction.GetInstructions(set); } /// /// Checks if the input is potentially formatted incorrectly. /// /// Normally, no blank lines should be present in the input. /// True if a blank line is found in the input. public static bool HasEmptyLine(ReadOnlySpan text) => HasEmptyLine(text.EnumerateLines()); /// public static bool HasEmptyLine(SpanLineEnumerator lines) { foreach (var line in lines) { if (line.IsEmpty || line.IsWhiteSpace()) return true; } return false; } /// /// Gets a list of s from the input . /// public static StringInstructionSet[] GetBatchSets(ReadOnlySpan lines) { int ctr = 0; int start = 0; while (start < lines.Length) { var slice = lines[start..]; var count = GetInstructionSetLength(slice); ctr++; start += count + 1; } var result = new StringInstructionSet[ctr]; ctr = 0; start = 0; while (start < lines.Length) { var slice = lines[start..]; var count = GetInstructionSetLength(slice); var set = slice[..count]; result[ctr++] = new StringInstructionSet(set); start += count + 1; } return result; } /// /// Gets a list of s from the input . /// public static StringInstructionSet[] GetBatchSets(ReadOnlySpan text) { int ctr = 0; int start = 0; while (start < text.Length) { var slice = text[start..]; var count = GetInstructionSetLength(slice); ctr++; start += count + 1; } var result = new StringInstructionSet[ctr]; ctr = 0; start = 0; while (start < text.Length) { var slice = text[start..]; var count = GetInstructionSetLength(slice); var set = slice[..count]; result[ctr++] = new StringInstructionSet(set); start += count + 1; } return result; } /// /// Scans through the to count the amount of characters to consume. /// /// Multi line string /// Amount of characters comprising a set of instructions public static int GetInstructionSetLength(ReadOnlySpan text) { int start = 0; while (start < text.Length) { var line = text[start..]; if (line.Length != 0 && line[0] == SetSeparatorChar) return start; var next = line.IndexOf('\n'); if (next == -1) return text.Length; start += next + 1; } return start; } /// /// Scans through the to count the amount of valid lines to consume. /// /// Amount of lines comprising a set of instructions. public static int GetInstructionSetLength(ReadOnlySpan lines) { int start = 0; while (start < lines.Length) { var line = lines[start++]; if (line.StartsWith(SetSeparatorChar)) return start; } return start; } }