From 43d16473d8bd7a5d6e6d99c565fa7f1c5dea061d Mon Sep 17 00:00:00 2001 From: YoshiRulz Date: Wed, 3 Jul 2024 19:27:47 +1000 Subject: [PATCH] Backport `string.Contains(char)` and `string.EndsWith(char)` --- src/BizHawk.BizInvoke/BizInvoker.cs | 3 ++- src/BizHawk.Client.EmuHawk/EmuHawkUtil.cs | 3 ++- .../RetroAchievements/RCheevos.Debug.cs | 5 +++-- .../MultiDiskBundler/MultiDiskBundler.cs | 2 +- src/BizHawk.Common/DeepEquality.cs | 5 +++-- .../Extensions/StringExtensions.cs | 22 +++++++++++++++++++ src/BizHawk.Common/FFmpegService.cs | 5 ++--- .../Arcades/MAME/MAME.IInputPollable.cs | 5 ++--- .../Arcades/MAME/MAME.ISettable.cs | 2 +- .../Arcades/MAME/MAMEMachineDB.cs | 4 ++-- .../CPUs/FairchildF8/F3850.Disassembler.cs | 11 +++++----- .../CPUs/Z80A/NewDisassembler.cs | 9 ++++---- .../Consoles/Nintendo/3DS/Encore.cs | 3 ++- 13 files changed, 53 insertions(+), 26 deletions(-) diff --git a/src/BizHawk.BizInvoke/BizInvoker.cs b/src/BizHawk.BizInvoke/BizInvoker.cs index 5f6c6b5dd7..2c9bad7997 100644 --- a/src/BizHawk.BizInvoke/BizInvoker.cs +++ b/src/BizHawk.BizInvoke/BizInvoker.cs @@ -8,6 +8,7 @@ using System.Text; using BizHawk.Common; using BizHawk.Common.CollectionExtensions; +using BizHawk.Common.StringExtensions; namespace BizHawk.BizInvoke { @@ -534,7 +535,7 @@ namespace BizHawk.BizInvoke throw new NotImplementedException("Multidimensional arrays are not supported!"); } - if (type.Name.Contains('*')) + if (type.Name.ContainsOrdinal('*')) { throw new NotImplementedException("Only 0-based 1-dimensional arrays are supported!"); } diff --git a/src/BizHawk.Client.EmuHawk/EmuHawkUtil.cs b/src/BizHawk.Client.EmuHawk/EmuHawkUtil.cs index bf792836f8..c203977a42 100644 --- a/src/BizHawk.Client.EmuHawk/EmuHawkUtil.cs +++ b/src/BizHawk.Client.EmuHawk/EmuHawkUtil.cs @@ -3,6 +3,7 @@ using System.IO; using System.Security.Principal; using BizHawk.Common; +using BizHawk.Common.StringExtensions; namespace BizHawk.Client.EmuHawk { @@ -15,7 +16,7 @@ namespace BizHawk.Client.EmuHawk /// http://stackoverflow.com/questions/139010/how-to-resolve-a-lnk-in-c-sharp public static string ResolveShortcut(string filename) { - if (OSTailoredCode.IsUnixHost || filename.Contains("|") + if (OSTailoredCode.IsUnixHost || filename.ContainsOrdinal('|') || !".lnk".Equals(Path.GetExtension(filename), StringComparison.OrdinalIgnoreCase)) { return filename; // archive internal files are never shortcuts (and choke when analyzing any further) diff --git a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Debug.cs b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Debug.cs index a1054211ea..330339a622 100644 --- a/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Debug.cs +++ b/src/BizHawk.Client.EmuHawk/RetroAchievements/RCheevos.Debug.cs @@ -8,6 +8,7 @@ using System.Windows.Forms; using BizHawk.Client.Common; using BizHawk.Common; using BizHawk.Common.PathExtensions; +using BizHawk.Common.StringExtensions; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Arcades.MAME; using BizHawk.Emulation.DiscSystem; @@ -310,7 +311,7 @@ namespace BizHawk.Client.EmuHawk { static string ResolvePath(string path) { - if (path.IndexOf('|') == -1 && Disc.IsValidExtension(Path.GetExtension(path))) + if (!path.ContainsOrdinal('|') && Disc.IsValidExtension(Path.GetExtension(path))) { return path; // nothing to do in this case } @@ -342,7 +343,7 @@ namespace BizHawk.Client.EmuHawk static ConsoleID IdentifyConsole(string path) { - if (path.IndexOf('|') == -1 && Disc.IsValidExtension(Path.GetExtension(path))) + if (!path.ContainsOrdinal('|') && Disc.IsValidExtension(Path.GetExtension(path))) { using var disc = DiscExtensions.CreateAnyType(path, Console.WriteLine); if (disc is null) diff --git a/src/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.cs b/src/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.cs index 68eb4f5754..5e943793c8 100644 --- a/src/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.cs +++ b/src/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskBundler.cs @@ -61,7 +61,7 @@ namespace BizHawk.Client.EmuHawk if (!Game.IsNullInstance()) { - if (MainForm.CurrentlyOpenRom.Contains("|")) + if (MainForm.CurrentlyOpenRom.ContainsOrdinal('|')) { var pieces = MainForm.CurrentlyOpenRom.Split('|'); diff --git a/src/BizHawk.Common/DeepEquality.cs b/src/BizHawk.Common/DeepEquality.cs index c02de6f381..d675b87fa9 100644 --- a/src/BizHawk.Common/DeepEquality.cs +++ b/src/BizHawk.Common/DeepEquality.cs @@ -1,8 +1,9 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Reflection; +using BizHawk.Common.StringExtensions; + namespace BizHawk.Common { /// Annotated fields will not be used by for comparison. @@ -24,7 +25,7 @@ namespace BizHawk.Common } // is there a better way to do this? i couldn't find any documentation... - return t.ToString().Contains('*'); + return t.ToString().ContainsOrdinal('*'); } /// diff --git a/src/BizHawk.Common/Extensions/StringExtensions.cs b/src/BizHawk.Common/Extensions/StringExtensions.cs index 4a15b1b6a2..f6bb8a614a 100644 --- a/src/BizHawk.Common/Extensions/StringExtensions.cs +++ b/src/BizHawk.Common/Extensions/StringExtensions.cs @@ -13,9 +13,31 @@ namespace BizHawk.Common.StringExtensions return new(a); } +#if !(NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER) + public static bool Contains(this string haystack, char needle) + => haystack.IndexOf(needle) >= 0; +#endif + public static bool Contains(this string haystack, string needle, StringComparison comparisonType) => haystack.IndexOf(needle, comparisonType) != -1; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsOrdinal(this string haystack, char needle) + => haystack.Contains(needle); // already ordinal + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool ContainsOrdinal(this string haystack, string needle) + => haystack.Contains(needle); // already ordinal + +#if !(NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER) + public static bool EndsWith(this string haystack, char needle) + => haystack.Length >= 1 && haystack[^1] == needle; +#endif + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool EndsWithOrdinal(this string haystack, char needle) + => haystack.EndsWith(needle); // already ordinal + /// /// if appears in (case-insensitive) /// diff --git a/src/BizHawk.Common/FFmpegService.cs b/src/BizHawk.Common/FFmpegService.cs index 87e0568e65..71d3bbeb75 100644 --- a/src/BizHawk.Common/FFmpegService.cs +++ b/src/BizHawk.Common/FFmpegService.cs @@ -8,6 +8,7 @@ using System.Text.RegularExpressions; using System.IO; using System.Threading.Tasks; using BizHawk.Common.PathExtensions; +using BizHawk.Common.StringExtensions; namespace BizHawk.Common { @@ -29,9 +30,7 @@ namespace BizHawk.Common } private static string[] Escape(IEnumerable args) - { - return args.Select(s => s.Contains(" ") ? $"\"{s}\"" : s).ToArray(); - } + => args.Select(static s => s.ContainsOrdinal(' ') ? $"\"{s}\"" : s).ToArray(); //note: accepts . or : in the stream stream/substream separator in the stream ID format, since that changed at some point in FFMPEG history //if someone has a better idea how to make the determination of whether an audio stream is available, I'm all ears diff --git a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.IInputPollable.cs b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.IInputPollable.cs index 1b5b8ee87d..27f2751ef1 100644 --- a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.IInputPollable.cs +++ b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.IInputPollable.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using BizHawk.Common; using BizHawk.Common.StringExtensions; @@ -47,7 +46,7 @@ namespace BizHawk.Emulation.Cores.Arcades.MAME foreach (var buttonField in buttonFields) { - if (buttonField != string.Empty && !buttonField.Contains('%')) + if (buttonField.Length is not 0 && !buttonField.ContainsOrdinal('%')) { var tag = buttonField.SubstringBefore(','); var field = buttonField.SubstringAfterLast(','); @@ -66,7 +65,7 @@ namespace BizHawk.Emulation.Cores.Arcades.MAME foreach (var analogField in analogFields) { - if (analogField != string.Empty && !analogField.Contains('%')) + if (analogField.Length is not 0 && !analogField.ContainsOrdinal('%')) { var keys = analogField.Split(','); var tag = keys[0]; diff --git a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISettable.cs b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISettable.cs index 65fa861e02..d2c066f1b4 100644 --- a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISettable.cs +++ b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAME.ISettable.cs @@ -166,7 +166,7 @@ namespace BizHawk.Emulation.Cores.Arcades.MAME } else { - if (hashdata.Contains("^")) + if (hashdata.EndsWithOrdinal('^')) { hashdata = hashdata.RemoveSuffix("^"); name += " (BAD DUMP)"; diff --git a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAMEMachineDB.cs b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAMEMachineDB.cs index dae31e314d..55c9946605 100644 --- a/src/BizHawk.Emulation.Cores/Arcades/MAME/MAMEMachineDB.cs +++ b/src/BizHawk.Emulation.Cores/Arcades/MAME/MAMEMachineDB.cs @@ -2,10 +2,10 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Linq; using System.Threading; using BizHawk.Common; +using BizHawk.Common.StringExtensions; namespace BizHawk.Emulation.Cores.Arcades.MAME { @@ -54,7 +54,7 @@ namespace BizHawk.Emulation.Cores.Arcades.MAME public static bool IsMAMEMachine(string path) { if (_acquire == null) throw new InvalidOperationException("MAME Machine DB not initialized. It's a client responsibility because only a client knows where the database is located."); - if (path.Contains('|')) return false; // binded archive, can't be a mame zip (note | is not a legal filesystem char, at least on windows) + if (path.ContainsOrdinal('|')) return false; // binded archive, can't be a mame zip (note | is not a legal filesystem char, at least on windows) if (Path.GetExtension(path).ToLowerInvariant() is not ".zip" and not ".7z") return false; _acquire.WaitOne(); return Instance.MachineDB.Contains(Path.GetFileNameWithoutExtension(path).ToLowerInvariant()); diff --git a/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Disassembler.cs b/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Disassembler.cs index 8b4ad69ed7..d49878aa9c 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Disassembler.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/FairchildF8/F3850.Disassembler.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; + +using BizHawk.Common.StringExtensions; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Components.FairchildF8 @@ -15,17 +17,16 @@ namespace BizHawk.Emulation.Cores.Components.FairchildF8 //n immediate succeeds the opcode and the displacement (if present) //nn immediately succeeds the opcode and the displacement (if present) - if (format.IndexOf("nn", StringComparison.Ordinal) != -1) + if (format.ContainsOrdinal("nn")) { format = format.Replace("nn", read(addr++) .ToString("X2") + read(addr++) .ToString("X2") + "h"); // MSB is read first } + if (format.ContainsOrdinal('n')) format = format.Replace("n", $"{read(addr++):X2}h"); - if (format.IndexOf("n", StringComparison.Ordinal) != -1) format = format.Replace("n", $"{read(addr++):X2}h"); - - if (format.IndexOf("+d", StringComparison.Ordinal) != -1) format = format.Replace("+d", "d"); - if (format.IndexOf("d", StringComparison.Ordinal) != -1) + format = format.Replace("+d", "d"); + if (format.ContainsOrdinal('d')) { var b = unchecked((sbyte)read(addr++)); format = format.Replace("d", $"{(b < 0 ? '-' : '+')}{(b < 0 ? -b : b):X2}h"); diff --git a/src/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs b/src/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs index 56b9416026..2c6848d1a4 100644 --- a/src/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs +++ b/src/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; +using BizHawk.Common.StringExtensions; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Components.Z80A @@ -13,11 +14,11 @@ namespace BizHawk.Emulation.Cores.Components.Z80A //n immediate succeeds the opcode and the displacement (if present) //nn immediately succeeds the opcode and the displacement (if present) - if (format.IndexOf("nn", StringComparison.Ordinal) != -1) format = format.Replace("nn", $"{read(addr++) + (read(addr++) << 8):X4}h"); // LSB is read first - if (format.IndexOf("n", StringComparison.Ordinal) != -1) format = format.Replace("n", $"{read(addr++):X2}h"); + if (format.ContainsOrdinal("nn")) format = format.Replace("nn", $"{read(addr++) + (read(addr++) << 8):X4}h"); // LSB is read first + if (format.ContainsOrdinal('n')) format = format.Replace("n", $"{read(addr++):X2}h"); - if (format.IndexOf("+d", StringComparison.Ordinal) != -1) format = format.Replace("+d", "d"); - if (format.IndexOf("d", StringComparison.Ordinal) != -1) + format = format.Replace("+d", "d"); + if (format.ContainsOrdinal('d')) { var b = unchecked ((sbyte) read(addr++)); format = format.Replace("d", $"{(b < 0 ? '-' : '+')}{(b < 0 ? -b : b):X2}h"); diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.cs index 1b4c176ad4..fa3d892f2e 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/3DS/Encore.cs @@ -7,6 +7,7 @@ using System.Text; using BizHawk.BizInvoke; using BizHawk.Common; +using BizHawk.Common.StringExtensions; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Consoles.Nintendo.N3DS @@ -46,7 +47,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.N3DS [CoreConstructor(VSystemID.Raw.N3DS)] public Encore(CoreLoadParameters lp) { - if (lp.Roms.Exists(r => r.RomPath.Contains("|"))) + if (lp.Roms.Exists(static r => r.RomPath.ContainsOrdinal('|'))) { throw new InvalidOperationException("3DS does not support compressed ROMs"); }