diff --git a/BizHawk.Client.DiscoHawk/MainDiscoForm.cs b/BizHawk.Client.DiscoHawk/MainDiscoForm.cs index 269f64d93f..2e527401e8 100644 --- a/BizHawk.Client.DiscoHawk/MainDiscoForm.cs +++ b/BizHawk.Client.DiscoHawk/MainDiscoForm.cs @@ -105,7 +105,7 @@ namespace BizHawk.Client.DiscoHawk if (files == null) return new List(); foreach (string str in files) { - string ext = Path.GetExtension(str)?.ToUpper(); + var ext = Path.GetExtension(str) ?? string.Empty; if(!ext.In(".CUE", ".ISO", ".CCD", ".MDS")) { return new List(); diff --git a/BizHawk.Common/Extensions/StringExtensions.cs b/BizHawk.Common/Extensions/StringExtensions.cs index 2e96c3f7e9..bfa8149f7b 100644 --- a/BizHawk.Common/Extensions/StringExtensions.cs +++ b/BizHawk.Common/Extensions/StringExtensions.cs @@ -1,376 +1,205 @@ -#nullable disable - -using System; -using System.Collections.Generic; +using System; using System.Linq; using System.Text; namespace BizHawk.Common.StringExtensions { + /// TODO how many of these Is*/Only* methods' callers can use int.TryParse or similar instead? --yoshi public static class StringExtensions { - public static string GetPrecedingString(this string str, string value) +#pragma warning disable CS8602 // no idea --yoshi + + /// the substring of before the first occurrence of , or if not found + public static string? GetPrecedingString(this string str, string value) { var index = str.IndexOf(value); - - if (index < 0) - { - return null; - } - - if (index == 0) - { - return ""; - } - - return str.Substring(0, index); + return index < 0 ? null : str.Substring(0, index); } - public static bool In(this string str, params string[] options) - { - return options.Any(opt => opt.Equals(str, StringComparison.CurrentCultureIgnoreCase)); - } + /// iff appears in (case-insensitive) + public static bool In(this string str, params string[] options) => options.Any(opt => string.Equals(opt, str, StringComparison.InvariantCultureIgnoreCase)); - public static bool NotIn(this string str, params string[] options) - { - return options.All(opt => opt.ToLower() != str.ToLower()); - } + /// how many times appears in , or 0 if is null + public static int HowMany(this string? str, char c) => string.IsNullOrEmpty(str) ? 0 : str.Count(t => t == c); - public static bool NotIn(this string str, IEnumerable options) + /// how many times appears in , or 0 if is null + /// + /// occurrences may overlap, for example "AAA".HowMany("AA") returns 2
+ /// TODO except it doesn't, but "AAAB".HowMany("AA") does. I left this bug in so as to not break anything. --yoshi + ///
+ public static int HowMany(this string? str, string sub) { - return options.All(opt => opt.ToLower() != str.ToLower()); - } - - public static int HowMany(this string str, char c) - { - return !string.IsNullOrEmpty(str) ? str.Count(t => t == c) : 0; - } - - public static int HowMany(this string str, string s) - { - if (str == null) - { - return 0; - } + if (string.IsNullOrEmpty(str)) return 0; var count = 0; - for (var i = 0; i < (str.Length - s.Length); i++) + var substrLength = sub.Length; + for (int i = 0, l = str.Length - substrLength; i < l; i++) { - if (str.Substring(i, s.Length) == s) - { - count++; - } + if (string.Equals(str.Substring(i, substrLength), sub, StringComparison.InvariantCulture)) count++; } - return count; } - #region String and Char validation extensions + /// iff is not and all chars of are digits + public static bool IsUnsigned(this string? str) => !string.IsNullOrWhiteSpace(str) && str.All(IsUnsigned); - /// - /// Validates all chars are 0-9 - /// - public static bool IsUnsigned(this string str) + /// iff is a digit + public static bool IsUnsigned(this char c) => char.IsDigit(c); + + /// + /// iff is not , + /// the first char of is '-' or a digit, and + /// all subsequent chars of are digits + /// + public static bool IsSigned(this string? str) => !string.IsNullOrWhiteSpace(str) && str[0].IsSigned() && str.Substring(1).All(IsUnsigned); + + /// iff is '-' or a digit + public static bool IsSigned(this char c) => IsUnsigned(c) || c == '-'; + + /// iff is not and all chars of are hex digits ([0-9A-Fa-f]) + /// should exclude the prefix 0x + public static bool IsHex(this string? str) => !string.IsNullOrWhiteSpace(str) && str.All(IsHex); + + /// iff is a hex digit ([0-9A-Fa-f]) + public static bool IsHex(this char c) => IsUnsigned(c) || 'A' <= char.ToUpperInvariant(c) && char.ToUpperInvariant(c) <= 'F'; + + /// iff is not and all chars of are either '0' or '1' + /// should exclude the prefix 0b + public static bool IsBinary(this string? str) => !string.IsNullOrWhiteSpace(str) && str.All(IsBinary); + + /// iff is either '0' or '1' + public static bool IsBinary(this char c) => c == '0' || c == '1'; + + /// + /// iff is not ,
+ /// all chars of are '.' or a digit, and
+ /// contains at most 1 decimal separator '.' + ///
+ /// + /// should exclude the suffix M.
+ /// This method returning for some does not imply that float.TryParse will also return .
+ /// Also this has nothing to do with fixed- vs. floating-point numbers, a better name would be IsUnsignedDecimal. + ///
+ public static bool IsFixedPoint(this string? str) => !string.IsNullOrWhiteSpace(str) && str.HowMany('.') <= 1 && str.All(IsFixedPoint); + + /// iff is '.' or a digit + /// Also this has nothing to do with fixed- vs. floating-point numbers, a better name would be IsUnsignedDecimal. + public static bool IsFixedPoint(this char c) => IsUnsigned(c) || c == '.'; + + /// + /// iff is not ,
+ /// the first char of is '-', '.', or a digit,
+ /// all subsequent chars of are '.' or a digit, and
+ /// contains at most 1 decimal separator '.' + ///
+ /// + /// should exclude the suffix f.
+ /// This method returning for some does not imply that float.TryParse will also return .
+ /// Also this has nothing to do with fixed- vs. floating-point numbers, a better name would be IsSignedDecimal. + ///
+ public static bool IsFloat(this string? str) => !string.IsNullOrWhiteSpace(str) && str.HowMany('.') <= 1 && str[0].IsFloat() && str.Substring(1).All(IsFixedPoint); + + /// iff is '-', '.', or a digit + /// Also this has nothing to do with fixed- vs. floating-point numbers, a better name would be IsSignedDecimal. + public static bool IsFloat(this char c) => c.IsFixedPoint() || c == '-'; + + /// + /// A copy of with characters removed so that the whole thing passes IsBinary.
+ /// That is, all chars of the copy will be either '0' or '1'. + ///
+ public static string OnlyBinary(this string? raw) => string.IsNullOrWhiteSpace(raw) ? string.Empty : string.Concat(raw.Where(IsBinary)); + + /// + /// A copy of with characters removed so that the whole thing passes IsUnsigned.
+ /// That is, all chars of the copy will be digits. + ///
+ public static string OnlyUnsigned(this string? raw) => string.IsNullOrWhiteSpace(raw) ? string.Empty : string.Concat(raw.Where(IsUnsigned)); + + /// + /// A copy of with characters removed so that the whole thing passes IsSigned.
+ /// That is, the first char of the copy will be '-' or a digit, and all subsequent chars of the copy will be digits. + ///
+ /// If contains a serialized negative integer, it must be at the start ([0] == '-') or the sign will be dropped. + public static string OnlySigned(this string? raw) { - if (string.IsNullOrWhiteSpace(str)) - { - return false; - } - - return str.All(IsUnsigned); + if (string.IsNullOrWhiteSpace(raw)) return string.Empty; + return raw[0].IsSigned() + ? raw[0] + string.Concat(raw.Skip(1).Where(IsUnsigned)) + : string.Concat(raw.Skip(1).Where(IsUnsigned)); } - /// - /// Validates the char is 0-9 - /// - public static bool IsUnsigned(this char c) + /// + /// A copy of with characters removed so that the whole thing passes IsHex.
+ /// That is, all chars of the copy will be hex digits ([0-9A-F]). + ///
+ public static string OnlyHex(this string? raw) => string.IsNullOrWhiteSpace(raw) ? string.Empty : string.Concat(raw.Where(IsHex)).ToUpperInvariant(); + + /// + /// A copy of with characters removed so that the whole thing passes IsFixedPoint.
+ /// That is, the all chars of the copy will be '.' or a digit and the copy will contain at most 1 decimal separator '.'. + ///
+ /// + /// The returned value may not be parseable by float.TryParse.
+ /// Also this has nothing to do with fixed- vs. floating-point numbers, a better name would be IsUnsignedDecimal. + ///
+ public static string OnlyFixedPoint(this string? raw) { - return char.IsDigit(c); - } - - /// - /// Validates all chars are 0-9, or a dash as the first value - /// - public static bool IsSigned(this string str) - { - if (string.IsNullOrWhiteSpace(str)) - { - return false; - } - - return str[0].IsSigned() && str.Substring(1).All(IsUnsigned); - } - - /// - /// Validates the char is 0-9 or a dash - /// - public static bool IsSigned(this char c) - { - return char.IsDigit(c) || c == '-'; - } - - /// - /// Validates all chars are 0-9, A-F or a-f - /// - public static bool IsHex(this string str) - { - return !string.IsNullOrWhiteSpace(str) && str.All(IsHex); - } - - /// - /// Validates the char is 0-9, A-F or a-f - /// - public static bool IsHex(this char c) - { - if (char.IsDigit(c)) - { - return true; - } - - return char.ToUpperInvariant(c) >= 'A' && char.ToUpperInvariant(c) <= 'F'; - } - - /// - /// Validates all chars are 0 or 1 - /// - public static bool IsBinary(this string str) - { - return !string.IsNullOrWhiteSpace(str) && str.All(IsBinary); - } - - /// - /// Validates the char is 0 or 1 - /// - public static bool IsBinary(this char c) - { - return c == '0' || c == '1'; - } - - /// - /// Validates all chars are 0-9, a decimal point, and that there is no more than 1 decimal point, can not be signed - /// - public static bool IsFixedPoint(this string str) - { - if (string.IsNullOrWhiteSpace(str)) - { - return false; - } - - return str.HowMany('.') <= 1 - && str.All(IsFixedPoint); - } - - /// - /// Validates the char is 0-9, a dash, or a decimal - /// - public static bool IsFixedPoint(this char c) - { - return c.IsUnsigned() || c == '.'; - } - - /// - /// Validates all chars are 0-9 or decimal, and that there is no more than 1 decimal point, a dash can be the first character - /// - public static bool IsFloat(this string str) - { - if (string.IsNullOrWhiteSpace(str)) - { - return false; - } - - return str.HowMany('.') <= 1 - && str[0].IsFloat() - && str.Substring(1).All(IsFixedPoint); - } - - /// - /// Validates that the char is 0-9, a dash, or a decimal point - /// - public static bool IsFloat(this char c) - { - return c.IsFixedPoint() || c == '-'; - } - - /// - /// Takes any string and removes any value that is not a valid binary value (0 or 1) - /// - public static string OnlyBinary(this string raw) - { - if (string.IsNullOrWhiteSpace(raw)) - { - return ""; - } - + if (string.IsNullOrWhiteSpace(raw)) return string.Empty; var output = new StringBuilder(); - - foreach (var chr in raw) - { - if (IsBinary(chr)) - { - output.Append(chr); - } - } - - return output.ToString(); - } - - /// - /// Takes any string and removes any value that is not a valid unsigned integer value (0-9) - /// - public static string OnlyUnsigned(this string raw) - { - if (string.IsNullOrWhiteSpace(raw)) - { - return ""; - } - - var output = new StringBuilder(); - - foreach (var chr in raw) - { - if (IsUnsigned(chr)) - { - output.Append(chr); - } - } - - return output.ToString(); - } - - /// - /// Takes any string and removes any value that is not a valid unsigned integer value (0-9 or -) - /// Note: a "-" will only be kept if it is the first digit - /// - public static string OnlySigned(this string raw) - { - if (string.IsNullOrWhiteSpace(raw)) - { - return ""; - } - - var output = new StringBuilder(); - - int count = 0; - foreach (var chr in raw) - { - if (count == 0 && chr == '-') - { - output.Append(chr); - } - else if (IsUnsigned(chr)) - { - output.Append(chr); - } - - count++; - } - - return output.ToString(); - } - - /// - /// Takes any string and removes any value that is not a valid hex value (0-9, a-f, A-F), returns the remaining characters in uppercase - /// - public static string OnlyHex(this string raw) - { - if (string.IsNullOrWhiteSpace(raw)) - { - return ""; - } - - var output = new StringBuilder(raw.Length); - - foreach (var chr in raw) - { - if (IsHex(chr)) - { - output.Append(char.ToUpper(chr)); - } - } - - return output.ToString(); - } - - /// - /// Takes any string and removes any value that is not a fixed point value (0-9 or .) - /// Note: only the first occurrence of a . will be kept - /// - public static string OnlyFixedPoint(this string raw) - { - if (string.IsNullOrWhiteSpace(raw)) - { - return ""; - } - - var output = new StringBuilder(); - var usedDot = false; foreach (var chr in raw) { if (chr == '.') { - if (usedDot) - { - continue; - } - + if (usedDot) continue; + output.Append(chr); usedDot = true; } - - if (IsFixedPoint(chr)) - { - output.Append(chr); - } + else if (chr.IsUnsigned()) output.Append(chr); } - return output.ToString(); } - /// - /// Takes any string and removes any value that is not a float point value (0-9, -, or .) - /// Note: - is only valid as the first character, and only the first occurrence of a . will be kept - /// - public static string OnlyFloat(this string raw) + /// + /// A copy of with characters removed so that the whole thing passes IsFloat.
+ /// That is, the first char of the copy will be '-', '.', or a digit,
+ /// all subsequent chars of the copy will be '.' or a digit, and
+ /// the copy will contain at most 1 decimal separator '.'. + ///
+ /// + /// If contains a serialized negative decimal, it must be at the start ([0] == '-') or the sign will be dropped.
+ /// The returned value may not be parseable by float.TryParse.
+ /// Also this has nothing to do with fixed- vs. floating-point numbers, a better name would be IsSignedDecimal. + ///
+ public static string OnlyFloat(this string? raw) { - if (string.IsNullOrWhiteSpace(raw)) - { - return ""; - } + if (string.IsNullOrWhiteSpace(raw)) return string.Empty; var output = new StringBuilder(); - var usedDot = false; - var count = 0; - foreach (var chr in raw) + + var first = raw[0]; + if (first.IsFloat()) { - if (count == 0 && chr == '-') + output.Append(first); + if (first == '.') usedDot = true; + } + + for (int i = 1, l = raw.Length; i < l; i++) + { + var chr = raw[i]; + if (chr == '.') { + if (usedDot) continue; output.Append(chr); + usedDot = true; } - else - { - if (chr == '.') - { - if (usedDot) - { - continue; - } - - usedDot = true; - } - - if (IsFixedPoint(chr)) - { - output.Append(chr); - } - } - - count++; + else if (chr.IsUnsigned()) output.Append(chr); } return output.ToString(); } - #endregion +#pragma warning restore CS8602 } } diff --git a/BizHawk.Emulation.Cores/CPUs/68000/OpcodeTable.cs b/BizHawk.Emulation.Cores/CPUs/68000/OpcodeTable.cs index ac94bfae87..8cdbbf1c68 100644 --- a/BizHawk.Emulation.Cores/CPUs/68000/OpcodeTable.cs +++ b/BizHawk.Emulation.Cores/CPUs/68000/OpcodeTable.cs @@ -121,7 +121,7 @@ namespace BizHawk.Emulation.Cores.Components.M68000 foreach (var opcode in opList) { int opc = Convert.ToInt32(opcode, 2); - if (Opcodes[opc] != null && instr.NotIn("movea", "andi2sr", "eori2sr", "ori2sr", "ext", "dbcc", "swap", "cmpm")) + if (Opcodes[opc] != null && !instr.In("movea", "andi2sr", "eori2sr", "ori2sr", "ext", "dbcc", "swap", "cmpm")) Console.WriteLine("Setting opcode for {0}, a handler is already set. overwriting. {1:X4}", instr, opc); Opcodes[opc] = exec; }