diff --git a/src/CatLib.Core.Tests/Support/TestsStr.cs b/src/CatLib.Core.Tests/Support/TestsStr.cs index af01bd3..dd6f2a1 100644 --- a/src/CatLib.Core.Tests/Support/TestsStr.cs +++ b/src/CatLib.Core.Tests/Support/TestsStr.cs @@ -66,6 +66,8 @@ public void TestSplitEmpty() public void TestRepeat() { Assert.AreEqual("foofoo", Str.Repeat("foo", 2)); + Assert.AreEqual("foo", Str.Repeat("foo", 1)); + Assert.AreEqual(string.Empty, Str.Repeat("foo", 0)); } [TestMethod] diff --git a/src/CatLib.Core/Support/Str.cs b/src/CatLib.Core/Support/Str.cs index 4e6b144..fe603fb 100644 --- a/src/CatLib.Core/Support/Str.cs +++ b/src/CatLib.Core/Support/Str.cs @@ -47,9 +47,9 @@ public enum PadType } /// - /// Get the function name expressed by the string. + /// Get the method name expressed by the string. /// - /// The string. + /// The string will extract method name. /// The method name. public static string Method(string pattern) { @@ -91,7 +91,6 @@ public static string Method(string pattern) Array.Resize(ref chars, count); Array.Reverse(chars); - return new string(chars); } @@ -99,8 +98,8 @@ public static string Method(string pattern) /// Translate the specified string into an asterisk match expression and test. /// /// The match pattern. - /// The. - /// True if matches. + /// The match value. + /// True if value is matched. public static bool Is(string pattern, string value) { return pattern == value || Regex.IsMatch(value, "^" + AsteriskWildcard(pattern) + "$"); @@ -112,16 +111,18 @@ public static bool Is(string pattern, string value) /// /// The type of source array. /// The match pattern. - /// The source array. + /// The match value. /// True if matches. - public static bool Is(string[] patterns, T source) + public static bool Is(string[] patterns, T value) { - Guard.Requires(source != null); - Guard.Requires(patterns != null); + if (patterns == null || value == null) + { + return false; + } foreach (var pattern in patterns) { - if (Is(pattern, source.ToString())) + if (Is(pattern, value.ToString())) { return true; } @@ -138,9 +139,7 @@ public static bool Is(string[] patterns, T source) public static string AsteriskWildcard(string pattern) { pattern = Regex.Escape(pattern); - pattern = pattern.Replace(@"\*", ".*?"); - - return pattern; + return pattern.Replace(@"\*", ".*?"); } /// @@ -151,16 +150,19 @@ public static string AsteriskWildcard(string pattern) /// Returns an array of the string. public static string[] Split(string str, int length = 1) { - Guard.Requires(str != null); - Guard.Requires(length > 0); - var requested = new string[(str.Length / length) + (str.Length % length == 0 ? 0 : 1)]; + if (string.IsNullOrEmpty(str)) + { + return Array.Empty(); + } + length = Math.Max(1, length); + var ret = new string[(str.Length / length) + (str.Length % length == 0 ? 0 : 1)]; for (var i = 0; i < str.Length; i += length) { - requested[i / length] = str.Substring(i, Math.Min(str.Length - i, length)); + ret[i / length] = str.Substring(i, Math.Min(str.Length - i, length)); } - return requested; + return ret; } /// @@ -171,21 +173,20 @@ public static string[] Split(string str, int length = 1) /// Return the repeated string. public static string Repeat(string str, int num) { - Guard.Requires(str != null); - Guard.Requires(num >= 0); + num = Math.Max(0, num); - if (num == 0) + if (string.IsNullOrEmpty(str) || num == 0) { - return str; + return string.Empty; } - var requested = new StringBuilder(); + var ret = new StringBuilder(); for (var i = 0; i < num; i++) { - requested.Append(str); + ret.Append(str); } - return requested.ToString(); + return ret.ToString(); } /// @@ -196,16 +197,19 @@ public static string Repeat(string str, int num) /// Returns disrupted string. public static string Shuffle(string str, int? seed = null) { - Guard.Requires(str != null); - var random = Helper.MakeRandom(seed); + if (string.IsNullOrEmpty(str)) + { + return string.Empty; + } - var requested = new string[str.Length]; + var random = Helper.MakeRandom(seed); + var ret = new string[str.Length]; for (var i = 0; i < str.Length; i++) { var index = random.Next(0, str.Length - 1); - requested[i] = requested[i] ?? str.Substring(i, 1); - requested[index] = requested[index] ?? str.Substring(index, 1); + ret[i] = ret[i] ?? str.Substring(i, 1); + ret[index] = ret[index] ?? str.Substring(index, 1); if (index == i) { @@ -213,13 +217,13 @@ public static string Shuffle(string str, int? seed = null) } #pragma warning disable S4143 - var temp = requested[i]; - requested[i] = requested[index]; - requested[index] = temp; + var temporary = ret[i]; + ret[i] = ret[index]; + ret[index] = temporary; #pragma warning restore S4143 } - return Arr.Reduce(requested, (v1, v2) => v1 + v2, string.Empty); + return Arr.Reduce(ret, (a, b) => a + b, string.Empty); } /// @@ -227,15 +231,17 @@ public static string Shuffle(string str, int? seed = null) /// This function does not count overlapping substrings. /// /// The specified string. - /// The substring. + /// The substring. /// The starting position. /// The length to calculate. /// The string comparison. - /// Returns the number of times a substring appears. - public static int SubstringCount(string str, string subStr, int start = 0, int? length = null, StringComparison comparison = StringComparison.CurrentCultureIgnoreCase) + /// Returns the number of times a substring appears. -1 means unable to calculate. + public static int SubstringCount(string str, string substr, int start = 0, int? length = null, StringComparison comparison = StringComparison.CurrentCultureIgnoreCase) { - Guard.Requires(str != null); - Guard.Requires(subStr != null); + if (string.IsNullOrEmpty(str) || string.IsNullOrEmpty(substr)) + { + return 0; + } Helper.NormalizationPosition(str.Length, ref start, ref length); @@ -243,14 +249,14 @@ public static int SubstringCount(string str, string subStr, int start = 0, int? while (length.Value > 0) { int index; - if ((index = str.IndexOf(subStr, start, length.Value, comparison)) < 0) + if ((index = str.IndexOf(substr, start, length.Value, comparison)) < 0) { break; } count++; - length -= index + subStr.Length - start; - start = index + subStr.Length; + length -= index + substr.Length - start; + start = index + substr.Length; } return count; @@ -265,7 +271,6 @@ public static string Reverse(string str) { var chars = str.ToCharArray(); Array.Reverse(chars); - return new string(chars); } @@ -286,8 +291,8 @@ public static string Pad(int length, string str = null, string padStr = null, Pa { str = str ?? string.Empty; - var needPadding = length - str.Length; - if (needPadding <= 0) + var needlePadding = length - str.Length; + if (needlePadding <= 0) { return str; } @@ -297,16 +302,16 @@ public static string Pad(int length, string str = null, string padStr = null, Pa if (type == PadType.Both) { - leftPadding = needPadding >> 1; - rightPadding = (needPadding >> 1) + (needPadding % 2 == 0 ? 0 : 1); + leftPadding = needlePadding >> 1; + rightPadding = (needlePadding >> 1) + (needlePadding % 2 == 0 ? 0 : 1); } else if (type == PadType.Right) { - rightPadding = needPadding; + rightPadding = needlePadding; } else { - leftPadding = needPadding; + leftPadding = needlePadding; } padStr = padStr ?? Space; @@ -328,8 +333,15 @@ public static string Pad(int length, string str = null, string padStr = null, Pa /// The remaining part. public static string After(string str, string search) { - Guard.Requires(str != null); - Guard.Requires(search != null); + if (string.IsNullOrEmpty(str)) + { + return string.Empty; + } + + if (string.IsNullOrEmpty(search)) + { + return str ?? string.Empty; + } var index = str.IndexOf(search, StringComparison.Ordinal); return index < 0 ? str : str.Substring(index + search.Length, str.Length - index - search.Length); @@ -345,12 +357,11 @@ public static string After(string str, string search) /// True if contains substring. public static bool Contains(string str, params string[] needles) { - Guard.Requires(str != null); - Guard.Requires(needles != null); + needles = needles ?? Array.Empty(); foreach (var needle in needles) { - if (str.Contains(needle)) + if (str == needle || str.Contains(needle)) { return true; } @@ -368,12 +379,21 @@ public static bool Contains(string str, params string[] needles) /// Returns the replacement string. public static string Replace(string[] matches, string replace, string str) { - Guard.Requires(matches != null); - Guard.Requires(replace != null); - Guard.Requires(str != null); + matches = matches ?? Array.Empty(); + replace = replace ?? string.Empty; + + if (string.IsNullOrEmpty(str)) + { + return string.Empty; + } foreach (var match in matches) { + if (match == null) + { + continue; + } + str = str.Replace(match, replace); } @@ -390,10 +410,12 @@ public static string Replace(string[] matches, string replace, string str) /// Returns the replacement string. public static string ReplaceFirst(string match, string replace, string str) { - Guard.Requires(match != null); - Guard.Requires(replace != null); - Guard.Requires(str != null); + if (string.IsNullOrEmpty(match) || string.IsNullOrEmpty(str)) + { + return str ?? string.Empty; + } + replace = replace ?? string.Empty; var index = str.IndexOf(match, StringComparison.Ordinal); return index < 0 ? str : str.Remove(index, match.Length).Insert(index, replace); } @@ -408,10 +430,12 @@ public static string ReplaceFirst(string match, string replace, string str) /// Returns the replacement string. public static string ReplaceLast(string match, string replace, string str) { - Guard.Requires(match != null); - Guard.Requires(replace != null); - Guard.Requires(str != null); + if (string.IsNullOrEmpty(match) || string.IsNullOrEmpty(str)) + { + return str ?? string.Empty; + } + replace = replace ?? string.Empty; var index = str.LastIndexOf(match, StringComparison.Ordinal); return index < 0 ? str : str.Remove(index, match.Length).Insert(index, replace); } @@ -424,21 +448,21 @@ public static string ReplaceLast(string match, string replace, string str) /// The random string. public static string Random(int length = 16, int? seed = null) { - Guard.Requires(length > 0); + length = Math.Max(1, length); - var requested = new StringBuilder(); + var ret = new StringBuilder(); var random = Helper.MakeRandom(seed); - for (int len; (len = requested.Length) < length;) + for (int len; (len = ret.Length) < length;) { var size = length - len; var bytes = new byte[size]; random.NextBytes(bytes); var code = Replace(new[] { "/", "+", "=" }, string.Empty, Convert.ToBase64String(bytes)); - requested.Append(code.Substring(0, Math.Min(size, code.Length))); + ret.Append(code.Substring(0, Math.Min(size, code.Length))); } - return requested.ToString(); + return ret.ToString(); } /// @@ -466,69 +490,69 @@ public static string Truncate(string str, int length, object separator = null, s return mission; } - var result = str.Substring(0, end); + var ret = str.Substring(0, end); if (separator == null) { - return result + mission; + return ret + mission; } var separatorStr = separator.ToString(); var index = -1; if (separator is Regex separatorRegex) { - if (separatorRegex.IsMatch(result)) + if (separatorRegex.IsMatch(ret)) { index = (separatorRegex.RightToLeft - ? separatorRegex.Match(result) - : Regex.Match(result, separatorRegex.ToString(), + ? separatorRegex.Match(ret) + : Regex.Match(ret, separatorRegex.ToString(), separatorRegex.Options | RegexOptions.RightToLeft)).Index; } } else if (!string.IsNullOrEmpty(separatorStr) && str.IndexOf(separatorStr, StringComparison.Ordinal) != end) { - index = result.LastIndexOf(separatorStr, StringComparison.Ordinal); + index = ret.LastIndexOf(separatorStr, StringComparison.Ordinal); } if (index > -1) { - result = result.Substring(0, index); + ret = ret.Substring(0, index); } - return result + mission; + return ret + mission; } /// /// Calculate Levenshtein distance between two strings. /// - /// The string 1. - /// The string 2. + /// The string 1. + /// The string 2. /// /// This function returns the Levenshtein-Distance between the two argument /// strings or -1, if one of the argument strings is longer than the limit /// of 255 characters. /// - public static int Levenshtein(string str1, string str2) + public static int Levenshtein(string a, string b) { - if (str1 == null || str2 == null) + if (a == null || b == null) { return -1; } - var length1 = str1.Length; - var length2 = str2.Length; + var lengthA = a.Length; + var lengthB = b.Length; - if (length1 > 255 || length2 > 255) + if (lengthA > 255 || lengthB > 255) { return -1; } - var p1 = new int[length2 + 1]; - var p2 = new int[length2 + 1]; + var pA = new int[lengthB + 1]; + var pB = new int[lengthB + 1]; - for (var i = 0; i <= length2; i++) + for (var i = 0; i <= lengthB; i++) { - p1[i] = i; + pA[i] = i; } int Min(int num1, int num2, int num3) @@ -547,23 +571,23 @@ int Min(int num1, int num2, int num3) return min; } - for (var i = 0; i < length1; i++) + for (var i = 0; i < lengthA; i++) { - p2[0] = p1[0] + 1; - for (var n = 0; n < length2; n++) + pB[0] = pA[0] + 1; + for (var n = 0; n < lengthB; n++) { - var distance = str1[i] == str2[n] - ? Min(p1[n], p1[n + 1] + 1, p2[n] + 1) - : Min(p1[n] + 1, p1[n + 1] + 1, p2[n] + 1); - p2[n + 1] = distance; + var distance = a[i] == b[n] + ? Min(pA[n], pA[n + 1] + 1, pB[n] + 1) + : Min(pA[n] + 1, pA[n + 1] + 1, pB[n] + 1); + pB[n + 1] = distance; } - var temp = p1; - p1 = p2; - p2 = temp; + var temp = pA; + pA = pB; + pB = temp; } - return p1[length2]; + return pA[lengthB]; } /// @@ -576,27 +600,27 @@ int Min(int num1, int num2, int num3) /// result[0] == "hello"; /// result[1] == "hello/world";. /// - /// The source array. + /// The source array. /// The separator. /// The sequential combination array. - public static string[] JoinList(string[] source, string separator = null) + public static string[] JoinList(string[] sources, string separator = null) { - Guard.Requires(source != null); - var builder = new StringBuilder(); - for (var index = 1; index < source.Length; index++) + sources = sources ?? Array.Empty(); + var ret = new StringBuilder(); + for (var index = 1; index < sources.Length; index++) { - builder.Append(source[index - 1]); + ret.Append(sources[index - 1]); if (!string.IsNullOrEmpty(separator)) { - builder.Append(separator); + ret.Append(separator); } - builder.Append(source[index]); - source[index] = builder.ToString(); - builder.Remove(0, source[index].Length); + ret.Append(sources[index]); + sources[index] = ret.ToString(); + ret.Remove(0, sources[index].Length); } - return source; + return sources; } ///