Sfoglia il codice sorgente

UI: Create a ColumnIndices struct and pass it by reference to the row ctor instead of recomputing the column index for every column on every row

Evan Husted 1 anno fa
parent
commit
606e149bd3

+ 47 - 26
src/Ryujinx/Utilities/Compat/CompatibilityCsv.cs

@@ -1,50 +1,71 @@
 using Gommon;
 using nietras.SeparatedValues;
 using Ryujinx.Ava.Common.Locale;
+using Ryujinx.Common.Logging;
 using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
+using System.Reflection;
 using System.Text;
 
 namespace Ryujinx.Ava.Utilities.Compat
 {
-    public class CompatibilityCsv
+    public struct ColumnIndices(SepReaderHeader header)
     {
-        public static CompatibilityCsv Shared { get; set; }
+        public const string TitleIdCol = "\"title_id\"";
+        public const string GameNameCol = "\"game_name\"";
+        public const string LabelsCol = "\"labels\"";
+        public const string StatusCol = "\"status\"";
+        public const string LastUpdatedCol = "\"last_updated\"";
         
-        public CompatibilityCsv(SepReader reader)
+        public readonly int TitleId = header.IndexOf(TitleIdCol);
+        public readonly int GameName = header.IndexOf(GameNameCol);
+        public readonly int Labels = header.IndexOf(LabelsCol);
+        public readonly int Status = header.IndexOf(StatusCol);
+        public readonly int LastUpdated = header.IndexOf(LastUpdatedCol);
+    }
+    
+    public class CompatibilityCsv
+    {
+        static CompatibilityCsv()
         {
-            var entries = new List<CompatibilityEntry>();
+            using Stream csvStream = Assembly.GetExecutingAssembly()
+                .GetManifestResourceStream("RyujinxGameCompatibilityList")!;
+            csvStream.Position = 0;
 
-            foreach (var row in reader)
-            {
-                entries.Add(new CompatibilityEntry(reader.Header, row));
-            }
+            LoadFromStream(csvStream);
+        }
+        
+        public static void LoadFromStream(Stream stream)
+        {
+            var reader = Sep.Reader().From(stream);
+            var columnIndices = new ColumnIndices(reader.Header); 
 
-            Entries = entries.Where(x => x.Status != null)
-                .OrderBy(it => it.GameName).ToArray();
+            Entries = reader
+                .Enumerate(row => new CompatibilityEntry(ref columnIndices, row))
+                .OrderBy(it => it.GameName)
+                .ToArray();
+            
+            Logger.Debug?.Print(LogClass.UI, "Compatibility CSV loaded.");
         }
 
-        public CompatibilityEntry[] Entries { get; }
+        public static CompatibilityEntry[] Entries { get; private set; }
     }
 
     public class CompatibilityEntry
     {
-        public CompatibilityEntry(SepReaderHeader header, SepReader.Row row)
+        public CompatibilityEntry(ref ColumnIndices indices, SepReader.Row row)
         {
-            if (row.ColCount != header.ColNames.Count)
-                throw new InvalidDataException($"CSV row {row.RowIndex} ({row.ToString()}) has mismatched column count");
-            
-            var titleIdRow = ColStr(row[header.IndexOf("\"title_id\"")]);
+            var titleIdRow = ColStr(row[indices.TitleId]);
             TitleId = !string.IsNullOrEmpty(titleIdRow) 
                 ? titleIdRow 
                 : default(Optional<string>);
             
-            GameName = ColStr(row[header.IndexOf("\"game_name\"")]).Trim().Trim('"');
+            GameName = ColStr(row[indices.GameName]).Trim().Trim('"');
 
-            IssueLabels = ColStr(row[header.IndexOf("\"labels\"")]).Split(';');
-            Status = ColStr(row[header.IndexOf("\"status\"")]).ToLower() switch
+            Labels = ColStr(row[indices.Labels]).Split(';');
+            Status = ColStr(row[indices.Status]).ToLower() switch
             {
                 "playable" => LocaleKeys.CompatibilityListPlayable,
                 "ingame" => LocaleKeys.CompatibilityListIngame,
@@ -54,8 +75,8 @@ namespace Ryujinx.Ava.Utilities.Compat
                 _ => null
             };
 
-            if (DateTime.TryParse(ColStr(row[header.IndexOf("\"last_updated\"")]), out var dt))
-                LastEvent = dt;
+            if (DateTime.TryParse(ColStr(row[indices.LastUpdated]), out var dt))
+                LastUpdated = dt;
 
             return;
             
@@ -64,15 +85,15 @@ namespace Ryujinx.Ava.Utilities.Compat
         
         public string GameName { get; }
         public Optional<string> TitleId { get; }
-        public string[] IssueLabels { get; }
+        public string[] Labels { get; }
         public LocaleKeys? Status { get; }
-        public DateTime LastEvent { get; }
+        public DateTime LastUpdated { get; }
 
         public string LocalizedStatus => LocaleManager.Instance[Status!.Value];
         public string FormattedTitleId => TitleId
             .OrElse(new string(' ', 16));
 
-        public string FormattedIssueLabels => IssueLabels
+        public string FormattedIssueLabels => Labels
             .Where(it => !it.StartsWithIgnoreCase("status"))
             .Select(FormatLabelName)
             .JoinToString(", ");
@@ -82,9 +103,9 @@ namespace Ryujinx.Ava.Utilities.Compat
             var sb = new StringBuilder("CompatibilityEntry: {");
             sb.Append($"{nameof(GameName)}=\"{GameName}\", ");
             sb.Append($"{nameof(TitleId)}={TitleId}, ");
-            sb.Append($"{nameof(IssueLabels)}=\"{IssueLabels}\", ");
+            sb.Append($"{nameof(Labels)}=\"{Labels}\", ");
             sb.Append($"{nameof(Status)}=\"{Status}\", ");
-            sb.Append($"{nameof(LastEvent)}=\"{LastEvent}\"");
+            sb.Append($"{nameof(LastUpdated)}=\"{LastUpdated}\"");
             sb.Append('}');
 
             return sb.ToString();

+ 0 - 9
src/Ryujinx/Utilities/Compat/CompatibilityList.axaml.cs

@@ -14,15 +14,6 @@ namespace Ryujinx.Ava.Utilities.Compat
     {
         public static async Task Show()
         {
-            if (CompatibilityCsv.Shared is null)
-            {
-                await using Stream csvStream = Assembly.GetExecutingAssembly()
-                    .GetManifestResourceStream("RyujinxGameCompatibilityList")!;
-                csvStream.Position = 0;
-
-                CompatibilityCsv.Shared = new CompatibilityCsv(Sep.Reader().From(csvStream));
-            }
-            
             ContentDialog contentDialog = new()
             {
                 PrimaryButtonText = string.Empty,

+ 4 - 5
src/Ryujinx/Utilities/Compat/CompatibilityViewModel.cs

@@ -11,14 +11,13 @@ namespace Ryujinx.Ava.Utilities.Compat
     {
         [ObservableProperty] private bool _onlyShowOwnedGames = true;
 
-        private IEnumerable<CompatibilityEntry> _currentEntries = CompatibilityCsv.Shared.Entries;
+        private IEnumerable<CompatibilityEntry> _currentEntries = CompatibilityCsv.Entries;
         private readonly string[] _ownedGameTitleIds = [];
         private readonly ApplicationLibrary _appLibrary;
 
         public IEnumerable<CompatibilityEntry> CurrentEntries => OnlyShowOwnedGames
             ? _currentEntries.Where(x =>
-                x.TitleId.Check(tid => _ownedGameTitleIds.ContainsIgnoreCase(tid))
-                || _appLibrary.Applications.Items.Any(a => a.Name.EqualsIgnoreCase(x.GameName)))
+                x.TitleId.Check(tid => _ownedGameTitleIds.ContainsIgnoreCase(tid)))
             : _currentEntries;
 
         public CompatibilityViewModel() {}
@@ -39,11 +38,11 @@ namespace Ryujinx.Ava.Utilities.Compat
         {
             if (string.IsNullOrEmpty(searchTerm))
             {
-                SetEntries(CompatibilityCsv.Shared.Entries);
+                SetEntries(CompatibilityCsv.Entries);
                 return;
             }
 
-            SetEntries(CompatibilityCsv.Shared.Entries.Where(x =>
+            SetEntries(CompatibilityCsv.Entries.Where(x =>
                 x.GameName.ContainsIgnoreCase(searchTerm)
                 || x.TitleId.Check(tid => tid.ContainsIgnoreCase(searchTerm))));
         }