using System; using System.Collections.Generic; using System.IO; #if NET40_OR_GREATER || NETCOREAPP using System.Threading.Tasks; #endif using SabreTools.Core.Tools; using SabreTools.DatFiles; using SabreTools.DatItems; using SabreTools.IO; using SabreTools.IO.Logging; namespace SabreTools.DatTools { public class MergeSplit { #region Fields /// /// Splitting mode to apply /// public MergingFlag SplitType { get; set; } #endregion #region Logging /// /// Logging object /// private static readonly Logger _staticLogger = new(); #endregion #region Running /// /// Apply splitting on the DatFile /// /// Current DatFile object to run operations on /// True if DatFile tags override splitting, false otherwise /// True if the error that is thrown should be thrown back to the caller, false otherwise /// True if the DatFile was split, false on error public bool ApplySplitting(DatFile datFile, bool useTags, bool throwOnError = false) { InternalStopwatch watch = new("Applying splitting to DAT"); try { // If we are using tags from the DAT, set the proper input for split type unless overridden if (useTags && SplitType == MergingFlag.None) SplitType = datFile.Header.GetStringFieldValue(Models.Metadata.Header.ForceMergingKey).AsEnumValue(); // Run internal splitting switch (SplitType) { // Standard case MergingFlag.None: // No-op break; case MergingFlag.Split: datFile.ApplySplit(); break; case MergingFlag.Merged: datFile.ApplyMerged(); break; case MergingFlag.NonMerged: datFile.ApplyNonMerged(); break; // Nonstandard case MergingFlag.FullMerged: datFile.ApplyFullyMerged(); break; case MergingFlag.DeviceNonMerged: datFile.ApplyDeviceNonMerged(); break; case MergingFlag.FullNonMerged: datFile.ApplyFullyNonMerged(); break; } } catch (Exception ex) when (!throwOnError) { _staticLogger.Error(ex); return false; } finally { watch.Stop(); } return true; } /// /// Apply SuperDAT naming logic to a merged DatFile /// /// Current DatFile object to run operations on /// List of inputs to use for renaming public static void ApplySuperDAT(DatFile datFile, List inputs) { #if NET452_OR_GREATER || NETCOREAPP Parallel.ForEach(datFile.Items.SortedKeys, Core.Globals.ParallelOptions, key => #elif NET40_OR_GREATER Parallel.ForEach(datFile.Items.SortedKeys, key => #else foreach (var key in datFile.Items.SortedKeys) #endif { List? items = datFile.GetItemsForBucket(key); if (items == null) #if NET40_OR_GREATER || NETCOREAPP return; #else continue; #endif List newItems = []; foreach (DatItem item in items) { DatItem newItem = item; var source = newItem.GetFieldValue(DatItem.SourceKey); if (source == null) continue; string filename = inputs[source.Index].CurrentPath; string rootpath = inputs[source.Index].ParentPath ?? string.Empty; if (rootpath.Length > 0 #if NETFRAMEWORK && !rootpath.EndsWith(Path.DirectorySeparatorChar.ToString()) && !rootpath.EndsWith(Path.AltDirectorySeparatorChar.ToString())) #else && !rootpath.EndsWith(Path.DirectorySeparatorChar) && !rootpath.EndsWith(Path.AltDirectorySeparatorChar)) #endif { rootpath += Path.DirectorySeparatorChar.ToString(); } filename = filename.Remove(0, rootpath.Length); var machine = newItem.GetFieldValue(DatItem.MachineKey); if (machine == null) continue; string machineName = Path.GetDirectoryName(filename) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(filename) + Path.DirectorySeparatorChar + machine.GetName(); if (machineName.Length == 0) machineName = "Default"; machine.SetName(machineName); newItems.Add(newItem); } datFile.RemoveBucket(key); newItems.ForEach(item => datFile.AddItem(item, statsOnly: false)); #if NET40_OR_GREATER || NETCOREAPP }); #else } #endif } /// /// Apply SuperDAT naming logic to a merged DatFile /// /// Current DatFile object to run operations on /// List of inputs to use for renaming public static void ApplySuperDATDB(DatFile datFile, List inputs) { List keys = [.. datFile.ItemsDB.SortedKeys]; #if NET452_OR_GREATER || NETCOREAPP Parallel.ForEach(keys, Core.Globals.ParallelOptions, key => #elif NET40_OR_GREATER Parallel.ForEach(keys, key => #else foreach (var key in keys) #endif { var items = datFile.GetItemsForBucketDB(key); if (items == null) #if NET40_OR_GREATER || NETCOREAPP return; #else continue; #endif foreach (var item in items) { var source = datFile.GetSourceForItemDB(item.Key); if (source.Value == null) continue; var machine = datFile.GetMachineForItemDB(item.Key); if (machine.Value == null) continue; string filename = inputs[source.Value.Index].CurrentPath; string rootpath = inputs[source.Value.Index].ParentPath ?? string.Empty; if (rootpath.Length > 0 #if NETFRAMEWORK && !rootpath!.EndsWith(Path.DirectorySeparatorChar.ToString()) && !rootpath!.EndsWith(Path.AltDirectorySeparatorChar.ToString())) #else && !rootpath.EndsWith(Path.DirectorySeparatorChar) && !rootpath.EndsWith(Path.AltDirectorySeparatorChar)) #endif { rootpath += Path.DirectorySeparatorChar.ToString(); } filename = filename.Remove(0, rootpath.Length); string machineName = Path.GetDirectoryName(filename) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(filename) + Path.DirectorySeparatorChar + machine.Value.GetName(); if (machineName.Length == 0) machineName = "Default"; machine.Value.SetName(machineName); } #if NET40_OR_GREATER || NETCOREAPP }); #else } #endif } #endregion } }