diff --git a/SabreTools.DatFiles.Test/DatFileTests.FromMetadata.cs b/SabreTools.DatFiles.Test/DatFileTests.FromMetadata.cs index 494d3ed0..f7d04cfe 100644 --- a/SabreTools.DatFiles.Test/DatFileTests.FromMetadata.cs +++ b/SabreTools.DatFiles.Test/DatFileTests.FromMetadata.cs @@ -70,7 +70,7 @@ namespace SabreTools.DatFiles.Test ValidateMachine(actualMachine); // Aggregate for easier validation - DatItems.DatItem[] datItems = datFile.Items.Keys + DatItems.DatItem[] datItems = datFile.Items.SortedKeys .SelectMany(key => datFile.GetItemsForBucket(key)) .ToArray(); diff --git a/SabreTools.DatFiles.Test/DatFileTests.ToMetadata.cs b/SabreTools.DatFiles.Test/DatFileTests.ToMetadata.cs index c4309ce9..607685f2 100644 --- a/SabreTools.DatFiles.Test/DatFileTests.ToMetadata.cs +++ b/SabreTools.DatFiles.Test/DatFileTests.ToMetadata.cs @@ -28,7 +28,7 @@ namespace SabreTools.DatFiles.Test DatFile datFile = new Formats.Logiqx(null, deprecated: false); datFile.SetHeader(header); - datFile.Add("key", new Rom()); + datFile.AddItem(new Rom(), statsOnly: false); Models.Metadata.MetadataFile? actual = datFile.ConvertToMetadata(); Assert.NotNull(actual); @@ -76,7 +76,7 @@ namespace SabreTools.DatFiles.Test ]; DatFile datFile = new Formats.SabreJSON(null); - datFile.Add("key", datItems); + datItems.ForEach(item => datFile.AddItem(item, statsOnly: false)); Models.Metadata.MetadataFile? actual = datFile.ConvertToMetadata(); Assert.NotNull(actual); diff --git a/SabreTools.DatFiles.Test/DatFileTests.cs b/SabreTools.DatFiles.Test/DatFileTests.cs index 291bf0c4..cc48153b 100644 --- a/SabreTools.DatFiles.Test/DatFileTests.cs +++ b/SabreTools.DatFiles.Test/DatFileTests.cs @@ -195,7 +195,7 @@ namespace SabreTools.DatFiles.Test { DatFile datFile = new Formats.Logiqx(datFile: null, deprecated: false); datFile.Header.SetFieldValue(Models.Metadata.Header.NameKey, "name"); - datFile.Add("key", new Rom()); + datFile.AddItem(new Rom(), statsOnly: false); datFile.AddItemDB(new Rom(), 0, 0, false); datFile.ResetDictionary(); diff --git a/SabreTools.DatFiles/DatFile.Filtering.cs b/SabreTools.DatFiles/DatFile.Filtering.cs index 928b9b13..b57ce9f0 100644 --- a/SabreTools.DatFiles/DatFile.Filtering.cs +++ b/SabreTools.DatFiles/DatFile.Filtering.cs @@ -102,11 +102,11 @@ namespace SabreTools.DatFiles Dictionary mapping = []; #endif #if NET452_OR_GREATER || NETCOREAPP - Parallel.ForEach(Items.Keys, Globals.ParallelOptions, key => + Parallel.ForEach(Items.SortedKeys, Globals.ParallelOptions, key => #elif NET40_OR_GREATER - Parallel.ForEach(Items.Keys, key => + Parallel.ForEach(Items.SortedKeys, key => #else - foreach (var key in Items.Keys) + foreach (var key in Items.SortedKeys) #endif { var items = GetItemsForBucket(key); @@ -191,7 +191,7 @@ namespace SabreTools.DatFiles /// Applies to private void ExecuteFiltersImpl(FilterRunner filterRunner) { - List keys = [.. Items.Keys]; + List keys = [.. Items.SortedKeys]; #if NET452_OR_GREATER || NETCOREAPP Parallel.ForEach(keys, Core.Globals.ParallelOptions, key => #elif NET40_OR_GREATER @@ -327,7 +327,7 @@ namespace SabreTools.DatFiles // Then we want to get a mapping of all machines to parents Dictionary> parents = []; - foreach (string key in Items.Keys) + foreach (string key in Items.SortedKeys) { DatItem item = GetItemsForBucket(key)[0]; @@ -389,7 +389,7 @@ namespace SabreTools.DatFiles parents[key].Remove(machine); // Remove the rest of the items from this key - parents[key].ForEach(k => Remove(k)); + parents[key].ForEach(k => RemoveBucket(k)); } // Finally, strip out the parent tags @@ -483,11 +483,11 @@ namespace SabreTools.DatFiles { // For each rom, we want to update the game to be "/" #if NET452_OR_GREATER || NETCOREAPP - Parallel.ForEach(Items.Keys, Globals.ParallelOptions, key => + Parallel.ForEach(Items.SortedKeys, Globals.ParallelOptions, key => #elif NET40_OR_GREATER - Parallel.ForEach(Items.Keys, key => + Parallel.ForEach(Items.SortedKeys, key => #else - foreach (var key in Items.Keys) + foreach (var key in Items.SortedKeys) #endif { var items = GetItemsForBucket(key); @@ -640,11 +640,11 @@ namespace SabreTools.DatFiles { // Now process all of the roms #if NET452_OR_GREATER || NETCOREAPP - Parallel.ForEach(Items.Keys, Globals.ParallelOptions, key => + Parallel.ForEach(Items.SortedKeys, Globals.ParallelOptions, key => #elif NET40_OR_GREATER - Parallel.ForEach(Items.Keys, key => + Parallel.ForEach(Items.SortedKeys, key => #else - foreach (var key in Items.Keys) + foreach (var key in Items.SortedKeys) #endif { var items = GetItemsForBucket(key); @@ -725,11 +725,11 @@ namespace SabreTools.DatFiles private void UpdateMachineNamesFromDescriptions(IDictionary mapping) { #if NET452_OR_GREATER || NETCOREAPP - Parallel.ForEach(Items.Keys, Globals.ParallelOptions, key => + Parallel.ForEach(Items.SortedKeys, Globals.ParallelOptions, key => #elif NET40_OR_GREATER - Parallel.ForEach(Items.Keys, key => + Parallel.ForEach(Items.SortedKeys, key => #else - foreach (var key in Items.Keys) + foreach (var key in Items.SortedKeys) #endif { var items = GetItemsForBucket(key); diff --git a/SabreTools.DatFiles/DatFile.Splitting.cs b/SabreTools.DatFiles/DatFile.Splitting.cs index dc07cbd9..d2be5f10 100644 --- a/SabreTools.DatFiles/DatFile.Splitting.cs +++ b/SabreTools.DatFiles/DatFile.Splitting.cs @@ -240,7 +240,7 @@ namespace SabreTools.DatFiles /// private void AddItemsFromChildrenImpl(bool subfolder, bool skipDedup) { - List buckets = [.. Items.Keys]; + List buckets = [.. Items.SortedKeys]; buckets.Sort(); foreach (string bucket in buckets) @@ -298,14 +298,14 @@ namespace SabreTools.DatFiles .Contains(mergeTag)) { disk.CopyMachineInformation(copyFrom); - Add(cloneOf, disk); + AddItem(disk, statsOnly: false); } // If there is no merge tag, add to parent else if (mergeTag == null) { disk.CopyMachineInformation(copyFrom); - Add(cloneOf, disk); + AddItem(disk, statsOnly: false); } } @@ -331,7 +331,7 @@ namespace SabreTools.DatFiles rom.SetName($"{rom.GetFieldValue(DatItem.MachineKey)!.GetStringFieldValue(Models.Metadata.Machine.NameKey)}\\{rom.GetName()}"); rom.CopyMachineInformation(copyFrom); - Add(cloneOf, rom); + AddItem(rom, statsOnly: false); } // If the parent doesn't already contain this item, add to subfolder of parent @@ -341,7 +341,7 @@ namespace SabreTools.DatFiles rom.SetName($"{item.GetFieldValue(DatItem.MachineKey)!.GetStringFieldValue(Models.Metadata.Machine.NameKey)}\\{rom.GetName()}"); rom.CopyMachineInformation(copyFrom); - Add(cloneOf, rom); + AddItem(rom, statsOnly: false); } } @@ -352,12 +352,12 @@ namespace SabreTools.DatFiles item.SetName($"{item.GetFieldValue(DatItem.MachineKey)!.GetStringFieldValue(Models.Metadata.Machine.NameKey)}\\{item.GetName()}"); item.CopyMachineInformation(copyFrom); - Add(cloneOf, item); + AddItem(item, statsOnly: false); } } // Then, remove the old game so it's not picked up by the writer - Remove(bucket); + RemoveBucket(bucket); } } @@ -503,7 +503,7 @@ namespace SabreTools.DatFiles /// private void AddItemsFromCloneOfParentImpl() { - List buckets = [.. Items.Keys]; + List buckets = [.. Items.SortedKeys]; buckets.Sort(); foreach (string bucket in buckets) @@ -533,7 +533,7 @@ namespace SabreTools.DatFiles if (!items.Exists(i => string.Equals(i.GetName(), datItem.GetName(), StringComparison.OrdinalIgnoreCase)) && !items.Contains(datItem)) { - Add(bucket, datItem); + AddItem(datItem, statsOnly: false); } } @@ -625,7 +625,7 @@ namespace SabreTools.DatFiles private bool AddItemsFromDevicesImpl(bool deviceOnly, bool useSlotOptions) { bool foundnew = false; - List buckets = [.. Items.Keys]; + List buckets = [.. Items.SortedKeys]; buckets.Sort(); foreach (string bucket in buckets) @@ -686,7 +686,7 @@ namespace SabreTools.DatFiles // Clone the item and then add it DatItem datItem = (DatItem)item.Clone(); datItem.CopyMachineInformation(copyFrom); - Add(bucket, datItem); + AddItem(datItem, statsOnly: false); } } } @@ -734,7 +734,7 @@ namespace SabreTools.DatFiles // Clone the item and then add it DatItem datItem = (DatItem)item.Clone(); datItem.CopyMachineInformation(copyFrom); - Add(bucket, datItem); + AddItem(datItem, statsOnly: false); } } } @@ -937,7 +937,7 @@ namespace SabreTools.DatFiles /// private void AddItemsFromRomOfParentImpl() { - List buckets = [.. Items.Keys]; + List buckets = [.. Items.SortedKeys]; buckets.Sort(); foreach (string bucket in buckets) @@ -965,7 +965,7 @@ namespace SabreTools.DatFiles DatItem datItem = (DatItem)item.Clone(); datItem.CopyMachineInformation(copyFrom); if (!items.Exists(i => i.GetName() == datItem.GetName()) && !items.Contains(datItem)) - Add(bucket, datItem); + AddItem(datItem, statsOnly: false); } } } @@ -1023,7 +1023,7 @@ namespace SabreTools.DatFiles /// private void RemoveBiosAndDeviceSetsImpl() { - List buckets = [.. Items.Keys]; + List buckets = [.. Items.SortedKeys]; buckets.Sort(); foreach (string bucket in buckets) @@ -1042,7 +1042,7 @@ namespace SabreTools.DatFiles if ((machine.GetBoolFieldValue(Models.Metadata.Machine.IsBiosKey) == true) || (machine.GetBoolFieldValue(Models.Metadata.Machine.IsDeviceKey) == true)) { - Remove(bucket); + RemoveBucket(bucket); } } } @@ -1093,7 +1093,7 @@ namespace SabreTools.DatFiles /// private void RemoveItemsFromCloneOfChildImpl() { - List buckets = [.. Items.Keys]; + List buckets = [.. Items.SortedKeys]; buckets.Sort(); foreach (string bucket in buckets) @@ -1120,7 +1120,7 @@ namespace SabreTools.DatFiles var matchedItems = items.FindAll(i => i.Equals(item)); foreach (var match in matchedItems) { - Items.Remove(bucket, match); + RemoveItem(bucket, match); } } @@ -1200,7 +1200,7 @@ namespace SabreTools.DatFiles private void RemoveItemsFromRomOfChildImpl() { // Loop through the romof tags - List buckets = [.. Items.Keys]; + List buckets = [.. Items.SortedKeys]; buckets.Sort(); foreach (string bucket in buckets) @@ -1227,7 +1227,7 @@ namespace SabreTools.DatFiles var matchedItems = items.FindAll(i => i.Equals(item)); foreach (var match in matchedItems) { - Items.Remove(bucket, match); + RemoveItem(bucket, match); } } } @@ -1281,7 +1281,7 @@ namespace SabreTools.DatFiles /// Applies to private void RemoveMachineRelationshipTagsImpl() { - List buckets = [.. Items.Keys]; + List buckets = [.. Items.SortedKeys]; buckets.Sort(); foreach (string bucket in buckets) diff --git a/SabreTools.DatFiles/DatFile.cs b/SabreTools.DatFiles/DatFile.cs index 678fbe76..877d8002 100644 --- a/SabreTools.DatFiles/DatFile.cs +++ b/SabreTools.DatFiles/DatFile.cs @@ -142,26 +142,6 @@ namespace SabreTools.DatFiles #region Item Dictionary Passthrough - Accessors - /// - /// Add a value to the file dictionary - /// - /// Key in the dictionary to add to - /// Value to add to the dictionary - public void Add(string key, DatItem value) - { - Items.Add(key, value); - } - - /// - /// Add a range of values to the file dictionary - /// - /// Key in the dictionary to add to - /// Value to add to the dictionary - public void Add(string key, List? value) - { - Items.Add(key, value); - } - /// /// Add a DatItem to the dictionary after checking /// @@ -242,9 +222,19 @@ namespace SabreTools.DatFiles /// Remove a key from the file dictionary if it exists /// /// Key in the dictionary to remove - public bool Remove(string key) + public bool RemoveBucket(string key) { - return Items.Remove(key); + return Items.RemoveBucket(key); + } + + /// + /// Remove the first instance of a value from the file dictionary if it exists + /// + /// Key in the dictionary to remove from + /// Value to remove from the dictionary + public bool RemoveItem(string key, DatItem value) + { + return Items.RemoveItem(key, value); } /// diff --git a/SabreTools.DatFiles/DatFileTool.cs b/SabreTools.DatFiles/DatFileTool.cs index b62304e7..3ea57a69 100644 --- a/SabreTools.DatFiles/DatFileTool.cs +++ b/SabreTools.DatFiles/DatFileTool.cs @@ -311,7 +311,7 @@ namespace SabreTools.DatFiles /// List of inputs to use for renaming public static void ApplySuperDAT(DatFile datFile, List inputs) { - List keys = [.. datFile.Items.Keys]; + List keys = [.. datFile.Items.SortedKeys]; #if NET452_OR_GREATER || NETCOREAPP Parallel.ForEach(keys, Core.Globals.ParallelOptions, key => #elif NET40_OR_GREATER @@ -366,8 +366,8 @@ namespace SabreTools.DatFiles newItems.Add(newItem); } - datFile.Remove(key); - datFile.Add(key, newItems); + datFile.RemoveBucket(key); + newItems.ForEach(item => datFile.AddItem(item, statsOnly: false)); #if NET40_OR_GREATER || NETCOREAPP }); #else @@ -467,11 +467,11 @@ namespace SabreTools.DatFiles // Then we do a hashwise comparison against the base DAT #if NET452_OR_GREATER || NETCOREAPP - Parallel.ForEach(intDat.Items.Keys, Core.Globals.ParallelOptions, key => + Parallel.ForEach(intDat.Items.SortedKeys, Core.Globals.ParallelOptions, key => #elif NET40_OR_GREATER - Parallel.ForEach(intDat.Items.Keys, key => + Parallel.ForEach(intDat.Items.SortedKeys, key => #else - foreach (var key in intDat.Items.Keys) + foreach (var key in intDat.Items.SortedKeys) #endif { List? datItems = intDat.GetItemsForBucket(key); @@ -497,8 +497,8 @@ namespace SabreTools.DatFiles } // Now add the new list to the key - intDat.Remove(key); - intDat.Add(key, newDatItems); + intDat.RemoveBucket(key); + newDatItems.ForEach(item => intDat.AddItem(item, statsOnly: false)); #if NET40_OR_GREATER || NETCOREAPP }); #else @@ -515,11 +515,11 @@ namespace SabreTools.DatFiles // Then we do a namewise comparison against the base DAT #if NET452_OR_GREATER || NETCOREAPP - Parallel.ForEach(intDat.Items.Keys, Core.Globals.ParallelOptions, key => + Parallel.ForEach(intDat.Items.SortedKeys, Core.Globals.ParallelOptions, key => #elif NET40_OR_GREATER - Parallel.ForEach(intDat.Items.Keys, key => + Parallel.ForEach(intDat.Items.SortedKeys, key => #else - foreach (var key in intDat.Items.Keys) + foreach (var key in intDat.Items.SortedKeys) #endif { List? datItems = intDat.GetItemsForBucket(key); @@ -547,8 +547,8 @@ namespace SabreTools.DatFiles } // Now add the new list to the key - intDat.Remove(key); - intDat.Add(key, newDatItems); + intDat.RemoveBucket(key); + newDatItems.ForEach(item => intDat.AddItem(item, statsOnly: false)); #if NET40_OR_GREATER || NETCOREAPP }); #else @@ -685,7 +685,7 @@ namespace SabreTools.DatFiles intDat.BucketBy(ItemKey.CRC, DedupeType.Full); // Then we compare against the base DAT - List keys = [.. intDat.Items.Keys]; + List keys = [.. intDat.Items.SortedKeys]; #if NET452_OR_GREATER || NETCOREAPP Parallel.ForEach(keys, Core.Globals.ParallelOptions, key => #elif NET40_OR_GREATER @@ -737,7 +737,7 @@ namespace SabreTools.DatFiles // If we have an exact match, remove the game if (exactMatch) - intDat.Remove(key); + intDat.RemoveBucket(key); } // Standard Against uses hashes @@ -759,8 +759,8 @@ namespace SabreTools.DatFiles } // Now add the new list to the key - intDat.Remove(key); - intDat.Add(key, keepDatItems); + intDat.RemoveBucket(key); + keepDatItems.ForEach(item => intDat.AddItem(item, statsOnly: false)); } #if NET40_OR_GREATER || NETCOREAPP }); @@ -859,11 +859,11 @@ namespace SabreTools.DatFiles watch.Start("Populating duplicate DAT"); #if NET452_OR_GREATER || NETCOREAPP - Parallel.ForEach(datFile.Items.Keys, Core.Globals.ParallelOptions, key => + Parallel.ForEach(datFile.Items.SortedKeys, Core.Globals.ParallelOptions, key => #elif NET40_OR_GREATER - Parallel.ForEach(datFile.Items.Keys, key => + Parallel.ForEach(datFile.Items.SortedKeys, key => #else - foreach (var key in datFile.Items.Keys) + foreach (var key in datFile.Items.SortedKeys) #endif { List items = Merge(datFile.GetItemsForBucket(key)); @@ -891,7 +891,7 @@ namespace SabreTools.DatFiles if (item.GetFieldValue(DatItem.SourceKey) != null) newrom.GetFieldValue(DatItem.MachineKey)!.SetFieldValue(Models.Metadata.Machine.NameKey, newrom.GetFieldValue(DatItem.MachineKey)!.GetStringFieldValue(Models.Metadata.Machine.NameKey) + $" ({Path.GetFileNameWithoutExtension(inputs[item.GetFieldValue(DatItem.SourceKey)!.Index].CurrentPath)})"); - dupeData.Add(key, newrom); + dupeData.AddItem(newrom, statsOnly: false); } } #if NET40_OR_GREATER || NETCOREAPP @@ -1084,11 +1084,11 @@ namespace SabreTools.DatFiles watch.Start("Populating all individual DATs"); #if NET452_OR_GREATER || NETCOREAPP - Parallel.ForEach(datFile.Items.Keys, Core.Globals.ParallelOptions, key => + Parallel.ForEach(datFile.Items.SortedKeys, Core.Globals.ParallelOptions, key => #elif NET40_OR_GREATER - Parallel.ForEach(datFile.Items.Keys, key => + Parallel.ForEach(datFile.Items.SortedKeys, key => #else - foreach (var key in datFile.Items.Keys) + foreach (var key in datFile.Items.SortedKeys) #endif { List items = Merge(datFile.GetItemsForBucket(key)); @@ -1112,7 +1112,7 @@ namespace SabreTools.DatFiles #else if (item.GetFieldValue(DatItem.DupeTypeKey).HasFlag(DupeType.Internal) || item.GetFieldValue(DatItem.DupeTypeKey) == 0x00) #endif - outDats[item.GetFieldValue(DatItem.SourceKey)!.Index].Add(key, item); + outDats[item.GetFieldValue(DatItem.SourceKey)!.Index].AddItem(item, statsOnly: false); } #if NET40_OR_GREATER || NETCOREAPP }); @@ -1294,11 +1294,11 @@ namespace SabreTools.DatFiles watch.Start("Populating no duplicate DAT"); #if NET452_OR_GREATER || NETCOREAPP - Parallel.ForEach(datFile.Items.Keys, Core.Globals.ParallelOptions, key => + Parallel.ForEach(datFile.Items.SortedKeys, Core.Globals.ParallelOptions, key => #elif NET40_OR_GREATER - Parallel.ForEach(datFile.Items.Keys, key => + Parallel.ForEach(datFile.Items.SortedKeys, key => #else - foreach (var key in datFile.Items.Keys) + foreach (var key in datFile.Items.SortedKeys) #endif { List items = Merge(datFile.GetItemsForBucket(key)); @@ -1324,7 +1324,7 @@ namespace SabreTools.DatFiles continue; newrom.GetFieldValue(DatItem.MachineKey)!.SetFieldValue(Models.Metadata.Machine.NameKey, newrom.GetFieldValue(DatItem.MachineKey)!.GetStringFieldValue(Models.Metadata.Machine.NameKey) + $" ({Path.GetFileNameWithoutExtension(inputs[newrom.GetFieldValue(DatItem.SourceKey)!.Index].CurrentPath)})"); - outerDiffData.Add(key, newrom); + outerDiffData.AddItem(newrom, statsOnly: false); } } #if NET40_OR_GREATER || NETCOREAPP @@ -1522,15 +1522,15 @@ namespace SabreTools.DatFiles private static void AddFromExisting(DatFile addTo, DatFile addFrom, bool delete = false) { // Get the list of keys from the DAT - List keys = [.. addFrom.Items.Keys]; + List keys = [.. addFrom.Items.SortedKeys]; foreach (string key in keys) { // Add everything from the key to the internal DAT - addTo.Add(key, addFrom.GetItemsForBucket(key)); + addFrom.GetItemsForBucket(key).ForEach(item => addTo.AddItem(item, statsOnly: false)); // Now remove the key from the source DAT if (delete) - addFrom.Remove(key); + addFrom.RemoveBucket(key); } // Now remove the file dictionary from the source DAT @@ -1612,11 +1612,11 @@ namespace SabreTools.DatFiles { // Loop through and add the items for this index to the output #if NET452_OR_GREATER || NETCOREAPP - Parallel.ForEach(datFile.Items.Keys, Core.Globals.ParallelOptions, key => + Parallel.ForEach(datFile.Items.SortedKeys, Core.Globals.ParallelOptions, key => #elif NET40_OR_GREATER - Parallel.ForEach(datFile.Items.Keys, key => + Parallel.ForEach(datFile.Items.SortedKeys, key => #else - foreach (var key in datFile.Items.Keys) + foreach (var key in datFile.Items.SortedKeys) #endif { List items = Merge(datFile.GetItemsForBucket(key)); @@ -1633,7 +1633,7 @@ namespace SabreTools.DatFiles { var source = item.GetFieldValue(DatItem.SourceKey); if (source != null && source.Index == index) - indexDat.Add(key, item); + indexDat.AddItem(item, statsOnly: false); } #if NET40_OR_GREATER || NETCOREAPP }); diff --git a/SabreTools.DatFiles/ItemDictionary.cs b/SabreTools.DatFiles/ItemDictionary.cs index 938b2800..463d421d 100644 --- a/SabreTools.DatFiles/ItemDictionary.cs +++ b/SabreTools.DatFiles/ItemDictionary.cs @@ -54,16 +54,6 @@ namespace SabreTools.DatFiles #region Keys - /// - /// Get the keys from the file dictionary - /// - /// List of the keys - [JsonIgnore, XmlIgnore] - public ICollection Keys - { - get { return _items.Keys; } - } - /// /// Get the keys in sorted order from the file dictionary /// @@ -109,59 +99,6 @@ namespace SabreTools.DatFiles #region Accessors - /// - /// Add a value to the file dictionary - /// - /// Key in the dictionary to add to - /// Value to add to the dictionary - public void Add(string key, DatItem value) - { - // Explicit lock for some weird corner cases - lock (key) - { - // Ensure the key exists - EnsureBucketingKey(key); - - // If item is null, don't add it - if (value == null) - return; - - // Now add the value - _items[key]!.Add(value); - - // Now update the statistics - DatStatistics.AddItemStatistics(value); - } - } - - /// - /// Add a range of values to the file dictionary - /// - /// Key in the dictionary to add to - /// Value to add to the dictionary - public void Add(string key, List? value) - { - // Explicit lock for some weird corner cases - lock (key) - { - // If the value is null or empty, just return - if (value == null || value.Count == 0) - return; - - // Ensure the key exists - EnsureBucketingKey(key); - - // Now add the value - _items[key]!.AddRange(value); - - // Now update the statistics - foreach (DatItem item in value) - { - DatStatistics.AddItemStatistics(item); - } - } - } - /// /// Add a DatItem to the dictionary after checking /// @@ -256,7 +193,7 @@ namespace SabreTools.DatFiles } else { - Add(key, item); + AddItem(key, item); } return key; @@ -267,7 +204,7 @@ namespace SabreTools.DatFiles /// internal void ClearEmpty() { - string[] keys = [.. Keys]; + string[] keys = [.. SortedKeys]; foreach (string key in keys) { #if NET40_OR_GREATER || NETCOREAPP @@ -303,15 +240,21 @@ namespace SabreTools.DatFiles /// internal void ClearMarked() { - string[] keys = [.. Keys]; + string[] keys = [.. SortedKeys]; foreach (string key in keys) { - // Skip invalid item lists - List oldItemList = GetItemsForBucket(key); - List newItemList = oldItemList.FindAll(i => i.GetBoolFieldValue(DatItem.RemoveKey) != true); + // Perform filtering on items + List list = GetItemsForBucket(key, filter: true); - Remove(key); - Add(key, newItemList); + // Remove the current list + RemoveBucket(key); + + // Add the filtered list back +#if NET40_OR_GREATER || NETCOREAPP + _ = _items.TryAdd(key, list); +#else + _items[key] = list; +#endif } } @@ -333,33 +276,6 @@ namespace SabreTools.DatFiles } } - /// - /// Get if the file dictionary contains the key and value - /// - /// Key in the dictionary to check - /// Value in the dictionary to check - /// True if the key exists, false otherwise - public bool Contains(string key, DatItem value) - { - // If the key is null, we return false since keys can't be null - if (key == null) - return false; - - // Explicit lock for some weird corner cases - lock (key) - { -#if NET40_OR_GREATER || NETCOREAPP - if (_items.TryGetValue(key, out var list) && list != null) - return list.Exists(i => i.Equals(value)); -#else - if (_items.ContainsKey(key) && _items[key] != null) - return _items[key]!.Exists(i => i.Equals(value)); -#endif - } - - return false; - } - /// /// Ensure the key exists in the items dictionary /// @@ -378,6 +294,9 @@ namespace SabreTools.DatFiles /// /// Get the items associated with a bucket name /// + /// Name of the bucket to retrive items for + /// Indicates if RemoveKey filtering is performed + /// List representing the bucket items, empty on missing public List GetItemsForBucket(string? bucketName, bool filter = false) { if (bucketName == null) @@ -410,28 +329,27 @@ namespace SabreTools.DatFiles /// Remove a key from the file dictionary if it exists /// /// Key in the dictionary to remove - public bool Remove(string key) + public bool RemoveBucket(string key) { - // Explicit lock for some weird corner cases - lock (key) - { - // If the key doesn't exist, return - if (!ContainsKey(key) || _items[key] == null) - return false; - - // Remove the statistics first - foreach (DatItem item in _items[key]!) - { - DatStatistics.RemoveItemStatistics(item); - } - - // Remove the key from the dictionary #if NET40_OR_GREATER || NETCOREAPP - return _items.TryRemove(key, out _); + bool removed = _items.TryRemove(key, out var list); #else - return _items.Remove(key); + if (!_items.ContainsKey(key)) + return false; + + bool removed = true; + var list = _items[key]; + _items.Remove(key); #endif + if (list == null) + return removed; + + foreach (var item in list) + { + DatStatistics.RemoveItemStatistics(item); } + + return removed; } /// @@ -439,43 +357,35 @@ namespace SabreTools.DatFiles /// /// Key in the dictionary to remove from /// Value to remove from the dictionary - public bool Remove(string key, DatItem value) + public bool RemoveItem(string key, DatItem value) { // Explicit lock for some weird corner cases lock (key) { - // If the key and value doesn't exist, return - if (!Contains(key, value) || _items[key] == null) + // If the key doesn't exist, return +#if NET40_OR_GREATER || NETCOREAPP + if (!_items.TryGetValue(key, out var list) || list == null) + return false; +#else + if (!_items.ContainsKey(key)) + return false; + + var list = _items[key]; + if (list == null) + return false; +#endif + + // If the value doesn't exist in the key, return + if (!list.Exists(i => i.Equals(value))) return false; // Remove the statistics first DatStatistics.RemoveItemStatistics(value); - return _items[key]!.Remove(value); + return list.Remove(value); } } - /// - /// Reset a key from the file dictionary if it exists - /// - /// Key in the dictionary to reset - public bool Reset(string key) - { - // If the key doesn't exist, return - if (!ContainsKey(key) || _items[key] == null) - return false; - - // Remove the statistics first - foreach (DatItem item in _items[key]!) - { - DatStatistics.RemoveItemStatistics(item); - } - - // Remove the key from the dictionary - _items[key] = []; - return true; - } - /// /// Override the internal ItemKey value /// @@ -485,6 +395,31 @@ namespace SabreTools.DatFiles _bucketedBy = newBucket; } + /// + /// Add a value to the file dictionary + /// + /// Key in the dictionary to add to + /// Value to add to the dictionary + internal void AddItem(string key, DatItem value) + { + // Explicit lock for some weird corner cases + lock (key) + { + // Ensure the key exists + EnsureBucketingKey(key); + + // If item is null, don't add it + if (value == null) + return; + + // Now add the value + _items[key]!.Add(value); + + // Now update the statistics + DatStatistics.AddItemStatistics(value); + } + } + #endregion #region Bucketing @@ -532,28 +467,29 @@ namespace SabreTools.DatFiles /// This also sets the remove flag on any duplicates found internal List GetDuplicates(DatItem datItem, bool sorted = false) { - List output = []; - // Check for an empty rom list first if (DatStatistics.TotalCount == 0) - return output; + return []; // We want to get the proper key for the DatItem string key = SortAndGetKey(datItem, sorted); - // If the key doesn't exist, return the empty list - if (!ContainsKey(key)) - return output; + // Get the items for the current key, if possible + List roms = GetItemsForBucket(key, filter: false); + if (roms.Count == 0) + return []; + + // Remove the current key + RemoveBucket(key); // Try to find duplicates - List roms = GetItemsForBucket(key); - List left = []; + List output = []; for (int i = 0; i < roms.Count; i++) { DatItem other = roms[i]; if (other.GetBoolFieldValue(DatItem.RemoveKey) == true) { - left.Add(other); + AddItem(key, other); continue; } @@ -562,16 +498,9 @@ namespace SabreTools.DatFiles other.SetFieldValue(DatItem.RemoveKey, true); output.Add(other); } - else - { - left.Add(other); - } - } - // Add back all roms with the proper flags - Remove(key); - Add(key, output); - Add(key, left); + AddItem(key, other); + } return output; } @@ -651,7 +580,7 @@ namespace SabreTools.DatFiles /// True if the key should be lowercased, false otherwise /// True if games should only be compared on game and file name, false if system and source are counted /// - private string GetBucketKey(DatItem datItem, ItemKey bucketBy, bool lower, bool norename) + private static string GetBucketKey(DatItem datItem, ItemKey bucketBy, bool lower, bool norename) { if (datItem == null) return string.Empty; @@ -679,7 +608,7 @@ namespace SabreTools.DatFiles _mergedBy = DedupeType.None; // First do the initial sort of all of the roms inplace - List oldkeys = [.. Keys]; + List oldkeys = [.. SortedKeys]; #if NET452_OR_GREATER || NETCOREAPP Parallel.For(0, oldkeys.Count, Core.Globals.ParallelOptions, k => @@ -691,7 +620,7 @@ namespace SabreTools.DatFiles { string key = oldkeys[k]; if (GetItemsForBucket(key).Count == 0) - Remove(key); + RemoveBucket(key); // Now add each of the roms to their respective keys for (int i = 0; i < GetItemsForBucket(key).Count; i++) @@ -706,8 +635,8 @@ namespace SabreTools.DatFiles // If the key is different, move the item to the new key if (newkey != key) { - Add(newkey, item); - bool removed = Remove(key, item); + AddItem(newkey, item); + bool removed = RemoveItem(key, item); if (!removed) break; @@ -717,7 +646,7 @@ namespace SabreTools.DatFiles // If the key is now empty, remove it if (GetItemsForBucket(key).Count == 0) - Remove(key); + RemoveBucket(key); #if NET40_OR_GREATER || NETCOREAPP }); #else @@ -735,7 +664,7 @@ namespace SabreTools.DatFiles // Set the sorted type _mergedBy = dedupeType; - List keys = [.. Keys]; + List keys = [.. SortedKeys]; #if NET452_OR_GREATER || NETCOREAPP Parallel.ForEach(keys, Core.Globals.ParallelOptions, key => #elif NET40_OR_GREATER @@ -755,8 +684,8 @@ namespace SabreTools.DatFiles sortedList = DatFileTool.Merge(sortedList); // Add the list back to the dictionary - Reset(key); - Add(key, sortedList); + RemoveBucket(key); + sortedList.ForEach(item => AddItem(key, item)); #if NET40_OR_GREATER || NETCOREAPP }); #else @@ -769,7 +698,7 @@ namespace SabreTools.DatFiles /// private void PerformSorting() { - List keys = [.. Keys]; + List keys = [.. SortedKeys]; #if NET452_OR_GREATER || NETCOREAPP Parallel.ForEach(keys, Core.Globals.ParallelOptions, key => #elif NET40_OR_GREATER @@ -785,8 +714,8 @@ namespace SabreTools.DatFiles DatFileTool.Sort(ref sortedList, false); // Add the list back to the dictionary - Reset(key); - Add(key, sortedList); + RemoveBucket(key); + sortedList.ForEach(item => AddItem(key, item)); #if NET40_OR_GREATER || NETCOREAPP }); #else diff --git a/SabreTools.DatTools/Cleaner.cs b/SabreTools.DatTools/Cleaner.cs index 922c2953..4a6b8d38 100644 --- a/SabreTools.DatTools/Cleaner.cs +++ b/SabreTools.DatTools/Cleaner.cs @@ -152,7 +152,7 @@ namespace SabreTools.DatTools /// Current DatFile object to run operations on internal void CleanDatItems(DatFile datFile) { - List keys = [.. datFile.Items.Keys]; + List keys = [.. datFile.Items.SortedKeys]; foreach (string key in keys) { // For every item in the current key diff --git a/SabreTools.DatTools/DatFromDir.cs b/SabreTools.DatTools/DatFromDir.cs index c0cc85db..2287a37e 100644 --- a/SabreTools.DatTools/DatFromDir.cs +++ b/SabreTools.DatTools/DatFromDir.cs @@ -230,7 +230,7 @@ namespace SabreTools.DatTools { // Add the list if it doesn't exist already Rom rom = baseFile.ConvertToRom(); - datFile.Add(rom.GetKey(ItemKey.CRC), rom); + datFile.AddItem(rom, statsOnly: false); _staticLogger.Verbose($"File added: {Path.GetFileNameWithoutExtension(item)}"); } else @@ -387,7 +387,7 @@ namespace SabreTools.DatTools blankRom.SetName(romname); blankRom.SetFieldValue(DatItem.MachineKey, blankMachine); - datFile.Add("null", blankRom); + datFile.AddItem(blankRom, statsOnly: false); #if NET40_OR_GREATER || NETCOREAPP }); #else @@ -440,8 +440,7 @@ namespace SabreTools.DatTools SetDatItemInfo(datFile, datItem, item, parent, basepath); // Add the file information to the DAT - string key = datItem.GetKey(ItemKey.CRC); - datFile.Add(key, datItem); + datFile.AddItem(datItem, statsOnly: false); _staticLogger.Verbose($"File added: {datItem.GetName() ?? string.Empty}"); } diff --git a/SabreTools.DatTools/Remover.cs b/SabreTools.DatTools/Remover.cs index 280086ff..715e3401 100644 --- a/SabreTools.DatTools/Remover.cs +++ b/SabreTools.DatTools/Remover.cs @@ -166,7 +166,7 @@ namespace SabreTools.DatTools if (itemDictionary == null || (MachineFieldNames.Count == 0 && ItemFieldNames.Count == 0)) return; - foreach (var key in itemDictionary.Keys) + foreach (var key in itemDictionary.SortedKeys) { List? items = itemDictionary.GetItemsForBucket(key); if (items == null) diff --git a/SabreTools.DatTools/Splitter.cs b/SabreTools.DatTools/Splitter.cs index 4e0702ff..1a11280a 100644 --- a/SabreTools.DatTools/Splitter.cs +++ b/SabreTools.DatTools/Splitter.cs @@ -2,8 +2,8 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Net; #if NET40_OR_GREATER || NETCOREAPP +using System.Net; using System.Threading.Tasks; #endif using SabreTools.Core.Tools; @@ -66,11 +66,11 @@ namespace SabreTools.DatTools // Now separate the roms accordingly #if NET452_OR_GREATER || NETCOREAPP - Parallel.ForEach(datFile.Items.Keys, Core.Globals.ParallelOptions, key => + Parallel.ForEach(datFile.Items.SortedKeys, Core.Globals.ParallelOptions, key => #elif NET40_OR_GREATER - Parallel.ForEach(datFile.Items.Keys, key => + Parallel.ForEach(datFile.Items.SortedKeys, key => #else - foreach (var key in datFile.Items.Keys) + foreach (var key in datFile.Items.SortedKeys) #endif { var items = datFile.GetItemsForBucket(key); @@ -85,16 +85,16 @@ namespace SabreTools.DatTools { if (Array.IndexOf(newExtA, (item.GetName() ?? string.Empty).GetNormalizedExtension()) > -1) { - extADat.Add(key, item); + extADat.AddItem(item, statsOnly: false); } if (Array.IndexOf(newExtB, (item.GetName() ?? string.Empty).GetNormalizedExtension()) > -1) { - extBDat.Add(key, item); + extBDat.AddItem(item, statsOnly: false); } else { - extADat.Add(key, item); - extBDat.Add(key, item); + extADat.AddItem(item, statsOnly: false); + extBDat.AddItem(item, statsOnly: false); } } #if NET40_OR_GREATER || NETCOREAPP @@ -242,11 +242,11 @@ namespace SabreTools.DatTools // Now populate each of the DAT objects in turn #if NET452_OR_GREATER || NETCOREAPP - Parallel.ForEach(datFile.Items.Keys, Core.Globals.ParallelOptions, key => + Parallel.ForEach(datFile.Items.SortedKeys, Core.Globals.ParallelOptions, key => #elif NET40_OR_GREATER - Parallel.ForEach(datFile.Items.Keys, key => + Parallel.ForEach(datFile.Items.SortedKeys, key => #else - foreach (var key in datFile.Items.Keys) + foreach (var key in datFile.Items.SortedKeys) #endif { var items = datFile.GetItemsForBucket(key); @@ -263,49 +263,49 @@ namespace SabreTools.DatTools { case Disk disk: if (disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue() == ItemStatus.Nodump) - fieldDats[Models.Metadata.Disk.StatusKey].Add(key, item); + fieldDats[Models.Metadata.Disk.StatusKey].AddItem(item, statsOnly: false); else if (!string.IsNullOrEmpty(disk.GetStringFieldValue(Models.Metadata.Disk.SHA1Key))) - fieldDats[Models.Metadata.Disk.SHA1Key].Add(key, item); + fieldDats[Models.Metadata.Disk.SHA1Key].AddItem(item, statsOnly: false); else if (!string.IsNullOrEmpty(disk.GetStringFieldValue(Models.Metadata.Disk.MD5Key))) - fieldDats[Models.Metadata.Disk.MD5Key].Add(key, item); + fieldDats[Models.Metadata.Disk.MD5Key].AddItem(item, statsOnly: false); else if (!string.IsNullOrEmpty(disk.GetStringFieldValue(Models.Metadata.Disk.MD5Key))) - fieldDats[Models.Metadata.Disk.MD5Key].Add(key, item); + fieldDats[Models.Metadata.Disk.MD5Key].AddItem(item, statsOnly: false); else - fieldDats["null"].Add(key, item); + fieldDats["null"].AddItem(item, statsOnly: false); break; case Media media: if (!string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.SHA256Key))) - fieldDats[Models.Metadata.Media.SHA256Key].Add(key, item); + fieldDats[Models.Metadata.Media.SHA256Key].AddItem(item, statsOnly: false); else if (!string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.SHA1Key))) - fieldDats[Models.Metadata.Media.SHA1Key].Add(key, item); + fieldDats[Models.Metadata.Media.SHA1Key].AddItem(item, statsOnly: false); else if (!string.IsNullOrEmpty(media.GetStringFieldValue(Models.Metadata.Media.MD5Key))) - fieldDats[Models.Metadata.Media.MD5Key].Add(key, item); + fieldDats[Models.Metadata.Media.MD5Key].AddItem(item, statsOnly: false); else - fieldDats["null"].Add(key, item); + fieldDats["null"].AddItem(item, statsOnly: false); break; case Rom rom: if (rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue() == ItemStatus.Nodump) - fieldDats[Models.Metadata.Rom.StatusKey].Add(key, item); + fieldDats[Models.Metadata.Rom.StatusKey].AddItem(item, statsOnly: false); else if (!string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA512Key))) - fieldDats[Models.Metadata.Rom.SHA512Key].Add(key, item); + fieldDats[Models.Metadata.Rom.SHA512Key].AddItem(item, statsOnly: false); else if (!string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA384Key))) - fieldDats[Models.Metadata.Rom.SHA384Key].Add(key, item); + fieldDats[Models.Metadata.Rom.SHA384Key].AddItem(item, statsOnly: false); else if (!string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA256Key))) - fieldDats[Models.Metadata.Rom.SHA256Key].Add(key, item); + fieldDats[Models.Metadata.Rom.SHA256Key].AddItem(item, statsOnly: false); else if (!string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.SHA1Key))) - fieldDats[Models.Metadata.Rom.SHA1Key].Add(key, item); + fieldDats[Models.Metadata.Rom.SHA1Key].AddItem(item, statsOnly: false); else if (!string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.MD5Key))) - fieldDats[Models.Metadata.Rom.MD5Key].Add(key, item); + fieldDats[Models.Metadata.Rom.MD5Key].AddItem(item, statsOnly: false); else if (!string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.MD4Key))) - fieldDats[Models.Metadata.Rom.MD4Key].Add(key, item); + fieldDats[Models.Metadata.Rom.MD4Key].AddItem(item, statsOnly: false); else if (!string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.MD2Key))) - fieldDats[Models.Metadata.Rom.MD2Key].Add(key, item); + fieldDats[Models.Metadata.Rom.MD2Key].AddItem(item, statsOnly: false); else if (!string.IsNullOrEmpty(rom.GetStringFieldValue(Models.Metadata.Rom.CRCKey))) - fieldDats[Models.Metadata.Rom.CRCKey].Add(key, item); + fieldDats[Models.Metadata.Rom.CRCKey].AddItem(item, statsOnly: false); else - fieldDats["null"].Add(key, item); + fieldDats["null"].AddItem(item, statsOnly: false); break; default: @@ -500,7 +500,7 @@ namespace SabreTools.DatTools tempDat.Header.SetFieldValue(Models.Metadata.Header.NameKey, null); // Sort the input keys - List keys = [.. datFile.Items.Keys]; + List keys = [.. datFile.Items.SortedKeys]; keys.Sort(SplitByLevelSort); // Then, we loop over the games @@ -532,7 +532,7 @@ namespace SabreTools.DatTools items.ForEach(item => item.GetFieldValue(DatItem.MachineKey)!.SetFieldValue(Models.Metadata.Machine.DescriptionKey, Path.GetFileName(item.GetFieldValue(DatItem.MachineKey)!.GetStringFieldValue(Models.Metadata.Machine.DescriptionKey)))); // Now add the game to the output DAT - tempDat.Add(key, items); + items.ForEach(item => tempDat.AddItem(item, statsOnly: false)); // Then set the DAT name to be the parent directory name tempDat.Header.SetFieldValue(Models.Metadata.Header.NameKey, Path.GetDirectoryName(key)); @@ -631,11 +631,11 @@ namespace SabreTools.DatTools // Now populate each of the DAT objects in turn #if NET452_OR_GREATER || NETCOREAPP - Parallel.ForEach(datFile.Items.Keys, Core.Globals.ParallelOptions, key => + Parallel.ForEach(datFile.Items.SortedKeys, Core.Globals.ParallelOptions, key => #elif NET40_OR_GREATER - Parallel.ForEach(datFile.Items.Keys, key => + Parallel.ForEach(datFile.Items.SortedKeys, key => #else - foreach (var key in datFile.Items.Keys) + foreach (var key in datFile.Items.SortedKeys) #endif { List? items = datFile.GetItemsForBucket(key); @@ -649,19 +649,19 @@ namespace SabreTools.DatTools { // If the file is not a Rom, it automatically goes in the "lesser" dat if (item is not Rom rom) - lessThan.Add(key, item); + lessThan.AddItem(item, statsOnly: false); // If the file is a Rom and has no size, put it in the "lesser" dat else if (rom.GetInt64FieldValue(Models.Metadata.Rom.SizeKey) == null) - lessThan.Add(key, item); + lessThan.AddItem(item, statsOnly: false); // If the file is a Rom and less than the radix, put it in the "lesser" dat else if (rom.GetInt64FieldValue(Models.Metadata.Rom.SizeKey) < radix) - lessThan.Add(key, item); + lessThan.AddItem(item, statsOnly: false); // If the file is a Rom and greater than or equal to the radix, put it in the "greater" dat else if (rom.GetInt64FieldValue(Models.Metadata.Rom.SizeKey) >= radix) - greaterThan.Add(key, item); + greaterThan.AddItem(item, statsOnly: false); } #if NET40_OR_GREATER || NETCOREAPP }); @@ -838,7 +838,7 @@ namespace SabreTools.DatTools } // Add the current machine to the current DatFile - currentDat.Add(machine, items); + items.ForEach(item => currentDat.AddItem(item, statsOnly: false)); currentSize += machineSize; } @@ -913,11 +913,11 @@ namespace SabreTools.DatTools { // Loop through and add the items for this index to the output #if NET452_OR_GREATER || NETCOREAPP - Parallel.ForEach(datFile.Items.Keys, Core.Globals.ParallelOptions, key => + Parallel.ForEach(datFile.Items.SortedKeys, Core.Globals.ParallelOptions, key => #elif NET40_OR_GREATER - Parallel.ForEach(datFile.Items.Keys, key => + Parallel.ForEach(datFile.Items.SortedKeys, key => #else - foreach (var key in datFile.Items.Keys) + foreach (var key in datFile.Items.SortedKeys) #endif { List items = DatFileTool.Merge(datFile.GetItemsForBucket(key)); @@ -933,7 +933,7 @@ namespace SabreTools.DatTools foreach (DatItem item in items) { if (item.GetStringFieldValue(Models.Metadata.DatItem.TypeKey).AsEnumValue() == itemType) - indexDat.Add(key, item); + indexDat.AddItem(item, statsOnly: false); } #if NET40_OR_GREATER || NETCOREAPP }); diff --git a/SabreTools.DatTools/Statistics.cs b/SabreTools.DatTools/Statistics.cs index 1f6a1ba0..64c5d109 100644 --- a/SabreTools.DatTools/Statistics.cs +++ b/SabreTools.DatTools/Statistics.cs @@ -83,17 +83,17 @@ namespace SabreTools.DatTools { DatStatistics individualStats = datdata.DatStatistics; individualStats.DisplayName = datdata.Header.GetStringFieldValue(DatHeader.FileNameKey); - individualStats.MachineCount = datdata.Items.Keys.Count; + individualStats.MachineCount = datdata.Items.SortedKeys.Count; stats.Add(individualStats); } // Add single DAT stats to dir dirStats.AddStatistics(datdata.DatStatistics); - dirStats.GameCount += datdata.Items.Keys.Count; + dirStats.GameCount += datdata.Items.SortedKeys.Count; // Add single DAT stats to totals totalStats.AddStatistics(datdata.DatStatistics); - totalStats.GameCount += datdata.Items.Keys.Count; + totalStats.GameCount += datdata.Items.SortedKeys.Count; // Make sure to assign the new directory lastdir = thisdir; diff --git a/SabreTools.DatTools/Writer.cs b/SabreTools.DatTools/Writer.cs index 6f24e56d..dcac107d 100644 --- a/SabreTools.DatTools/Writer.cs +++ b/SabreTools.DatTools/Writer.cs @@ -141,7 +141,7 @@ namespace SabreTools.DatTools datFile.BucketBy(ItemKey.Machine, DedupeType.None, norename: true); datFile.DatStatistics.DisplayName = datFile.Header.GetStringFieldValue(DatHeader.FileNameKey); - datFile.DatStatistics.MachineCount = datFile.Items.Keys.Count; + datFile.DatStatistics.MachineCount = datFile.Items.SortedKeys.Count; List statsList = [ diff --git a/SabreTools.Test/DatFiles/ItemDictionaryTests.cs b/SabreTools.Test/DatFiles/ItemDictionaryTests.cs index c54026b4..eb8ba47a 100644 --- a/SabreTools.Test/DatFiles/ItemDictionaryTests.cs +++ b/SabreTools.Test/DatFiles/ItemDictionaryTests.cs @@ -52,11 +52,13 @@ namespace SabreTools.Test.DatFiles // Setup the dictionary var dict = new ItemDictionary(); - dict.Add("game-1", [rom1, rom2]); - dict.Add("game-2", [rom3, rom4]); + dict.AddItem(rom1, statsOnly: false); + dict.AddItem(rom2, statsOnly: false); + dict.AddItem(rom3, statsOnly: false); + dict.AddItem(rom4, statsOnly: false); dict.BucketBy(itemKey, DedupeType.None); - Assert.Equal(expected, dict.Keys.Count); + Assert.Equal(expected, dict.SortedKeys.Count); } [Fact] @@ -64,12 +66,10 @@ namespace SabreTools.Test.DatFiles { // Setup the dictionary var dict = new ItemDictionary(); - dict.Add("game-1", [new Rom()]); - dict.Add("game-2", []); - dict.Add("game-3", (List?)null); + dict.AddItem("game-1", new Rom()); dict.ClearEmpty(); - Assert.Single(dict.Keys); + Assert.Single(dict.SortedKeys); } [Fact] @@ -96,10 +96,11 @@ namespace SabreTools.Test.DatFiles // Setup the dictionary var dict = new ItemDictionary(); - dict.Add("game-1", [rom1, rom2]); + dict.AddItem("game-1", rom1); + dict.AddItem("game-1", rom2); dict.ClearMarked(); - string key = Assert.Single(dict.Keys); + string key = Assert.Single(dict.SortedKeys); Assert.Equal("game-1", key); List items = dict.GetItemsForBucket(key); Assert.Single(items); @@ -128,7 +129,8 @@ namespace SabreTools.Test.DatFiles // Setup the dictionary var dict = new ItemDictionary(); - dict.Add("game-1", [rom1, rom2]); + dict.AddItem("game-1", rom1); + dict.AddItem("game-1", rom2); // Setup the test item var rom = new Rom(); @@ -164,7 +166,8 @@ namespace SabreTools.Test.DatFiles // Setup the dictionary var dict = new ItemDictionary(); - dict.Add("game-1", [rom1, rom2]); + dict.AddItem("game-1", rom1); + dict.AddItem("game-1", rom2); // Setup the test item var rom = new Rom();