Format3DParser.cs 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. using System;
  2. using Emby.Naming.Common;
  3. namespace Emby.Naming.Video
  4. {
  5. /// <summary>
  6. /// Parse 3D format related flags.
  7. /// </summary>
  8. public static class Format3DParser
  9. {
  10. // Static default result to save on allocation costs.
  11. private static readonly Format3DResult _defaultResult = new(false, null);
  12. /// <summary>
  13. /// Parse 3D format related flags.
  14. /// </summary>
  15. /// <param name="path">Path to file.</param>
  16. /// <param name="namingOptions">The naming options.</param>
  17. /// <returns>Returns <see cref="Format3DResult"/> object.</returns>
  18. public static Format3DResult Parse(ReadOnlySpan<char> path, NamingOptions namingOptions)
  19. {
  20. int oldLen = namingOptions.VideoFlagDelimiters.Length;
  21. Span<char> delimiters = stackalloc char[oldLen + 1];
  22. namingOptions.VideoFlagDelimiters.AsSpan().CopyTo(delimiters);
  23. delimiters[oldLen] = ' ';
  24. return Parse(path, delimiters, namingOptions);
  25. }
  26. private static Format3DResult Parse(ReadOnlySpan<char> path, ReadOnlySpan<char> delimiters, NamingOptions namingOptions)
  27. {
  28. foreach (var rule in namingOptions.Format3DRules)
  29. {
  30. var result = Parse(path, rule, delimiters);
  31. if (result.Is3D)
  32. {
  33. return result;
  34. }
  35. }
  36. return _defaultResult;
  37. }
  38. private static Format3DResult Parse(ReadOnlySpan<char> path, Format3DRule rule, ReadOnlySpan<char> delimiters)
  39. {
  40. bool is3D = false;
  41. string? format3D = null;
  42. // If there's no preceding token we just consider it found
  43. var foundPrefix = string.IsNullOrEmpty(rule.PrecedingToken);
  44. while (path.Length > 0)
  45. {
  46. var index = path.IndexOfAny(delimiters);
  47. if (index == -1)
  48. {
  49. index = path.Length - 1;
  50. }
  51. var currentSlice = path[..index];
  52. path = path[(index + 1)..];
  53. if (!foundPrefix)
  54. {
  55. foundPrefix = currentSlice.Equals(rule.PrecedingToken, StringComparison.OrdinalIgnoreCase);
  56. continue;
  57. }
  58. is3D = foundPrefix && currentSlice.Equals(rule.Token, StringComparison.OrdinalIgnoreCase);
  59. if (is3D)
  60. {
  61. format3D = rule.Token;
  62. break;
  63. }
  64. }
  65. return is3D ? new Format3DResult(true, format3D) : _defaultResult;
  66. }
  67. }
  68. }