using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Text.RegularExpressions; namespace Emby.Naming.Video { /// /// . /// public static class CleanStringParser { /// /// Attempts to extract clean name with regular expressions. /// /// Name of file. /// List of regex to parse name and year from. /// Parsing result string. /// True if parsing was successful. public static bool TryClean([NotNullWhen(true)] string? name, IReadOnlyList expressions, out ReadOnlySpan newName) { if (string.IsNullOrEmpty(name)) { newName = ReadOnlySpan.Empty; return false; } // Iteratively remove extra cruft until we're left with the string // we want. newName = ReadOnlySpan.Empty; const int maxTries = 100; // This is just a precautionary // measure. Should not be neccesary. var loopCounter = 0; for (; loopCounter < maxTries; loopCounter++) { bool cleaned = false; var len = expressions.Count; for (int i = 0; i < len; i++) { if (TryClean(name, expressions[i], out newName)) { cleaned = true; name = newName.ToString(); break; } } if (!cleaned) { break; } } if (loopCounter > 0) { newName = name.AsSpan(); } return newName != ReadOnlySpan.Empty; } private static bool TryClean(string name, Regex expression, out ReadOnlySpan newName) { var match = expression.Match(name); int index = match.Index; if (match.Success) { var found = match.Groups.TryGetValue("cleaned", out var cleaned); if (!found || cleaned == null) { newName = ReadOnlySpan.Empty; return false; } newName = name.AsSpan().Slice(cleaned.Index, cleaned.Length); return true; } newName = ReadOnlySpan.Empty; return false; } } }