JD2022-TU1/main/tools/framework/JD.Kernel/StaticHelpers/StringExtensions.cs

211 lines
8.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace JD.Kernel.StaticHelpers
{
/// <summary>
/// Provides additional utility manipulations over the string.
/// </summary>
public static class StringExtensions
{
#region Contains
/// <summary>
/// Returns a value indicating whether the specified System.String object occurs within this string.
/// </summary>
/// <param name="theString"></param>
/// <param name="value"></param>
/// <param name="comparisonType"></param>
/// <returns></returns>
public static bool Contains(this string theString, string value, StringComparison comparisonType)
{
return theString.IndexOf(value, comparisonType) >= 0;
}
#endregion
#region Extract
/// <summary>
/// Extracts a string between the two bounds (searching from the end of the string).
/// </summary>
/// <param name="value">Value to search in.</param>
/// <param name="begin">First tag to search</param>
/// <param name="end">Second tag to search</param>
/// <returns>The extracted string if found, empty string otherwise.</returns>
/// <example>"My [string] [value]".ExtractLast("[", "]") -> "value"</example>
public static string ExtractLast(this string value, string begin, string end)
{
string dummy1, dummy2;
return ExtractLast(value, begin, end, out dummy1, out dummy2);
}
/// <summary>
/// Extracts a string between the two bounds (searching from the end of the string).
/// </summary>
/// <param name="value">Value to search in.</param>
/// <param name="begin">First tag to search</param>
/// <param name="end">Second tag to search</param>
/// <param name="textBefore">Text before the extracted part (excluding the tag).</param>
/// <param name="textAfter">Text after the extracted part (excluding the tag).</param>
/// <returns>The extracted string if found, empty string otherwise.</returns>
/// <example>"My [string] [value]".ExtractLast("[", "]") -> "value"</example>
public static string ExtractLast(this string value, string begin, string end, out string textBefore, out string textAfter)
{
Throw.IfEmpty(begin, "begin");
Throw.IfEmpty(end, "end");
textBefore = string.Empty;
textAfter = string.Empty;
if (!string.IsNullOrEmpty(value))
{
int indexOfEnd = value.LastIndexOf(end);
if (indexOfEnd > 0)
{
int indexOfStart = value.LastIndexOf(begin, indexOfEnd - 1);
if (indexOfStart != -1)
{
textBefore = value.Substring(0, indexOfStart);
textAfter = value.Substring(indexOfEnd + end.Length);
return value.Substring(indexOfStart + begin.Length, indexOfEnd - indexOfStart - begin.Length);
}
}
}
return string.Empty;
}
#endregion
#region MakeUnique
/// <summary>
/// Returns a new string from the current one that is unique in the given <paramref name="collection"/>
/// </summary>
/// <remarks>
/// If the string is already unique, it is returned "as is".
/// </remarks>
public static string MakeUnique(this string suggestedName, ICollection<string> collection)
{
return MakeUnique(suggestedName, collection.Contains, collection.Count);
}
/// <summary>
/// Returns a new string from the current one that is unique in the given <paramref name="collection"/>
/// </summary>
/// <remarks>
/// If the string is already unique, it is returned "as is".
/// </remarks>
public static string MakeUnique<T>(this string suggestedName, IEnumerable<T> collection, Func<T, string> getName)
{
return MakeUnique(suggestedName, collection, getName, EqualityComparer<string>.Default);
}
/// <summary>
/// Returns a new string from the current one that is unique in the given <paramref name="collection"/>
/// </summary>
/// <remarks>
/// If the string is already unique, it is returned "as is".
/// </remarks>
public static string MakeUnique<T>(this string suggestedName, IEnumerable<T> collection, Func<T, string> getName, IEqualityComparer<string> comparer)
{
var strings = new HashSet<string>(collection.Select(getName), comparer);
return MakeUnique(suggestedName, strings);
}
/// <summary>
/// Returns a new string from the current one that is unique in the given <paramref name="collection"/>
/// </summary>
/// <remarks>
/// If the string is already unique, it is returned "as is".
/// </remarks>
/// <param name="suggestedName"></param>
/// <param name="collection"></param>
/// <param name="item">The item to ignore. Its current name is ignored in the computation.</param>
/// <param name="getName"></param>
/// <returns></returns>
public static string MakeUnique<T>(this string suggestedName, IEnumerable<T> collection, T item, Func<T, string> getName)
{
return MakeUnique(suggestedName, collection, item, getName, EqualityComparer<string>.Default);
}
/// <summary>
/// Returns a new string from the current one that is unique in the given <paramref name="collection"/>
/// </summary>
/// <remarks>
/// If the string is already unique, it is returned "as is".
/// </remarks>
/// <param name="suggestedName"></param>
/// <param name="collection"></param>
/// <param name="item">The item to ignore. Its current name is ignored in the computation.</param>
/// <param name="getName"></param>
/// <param name="comparer"></param>
/// <returns></returns>
public static string MakeUnique<T>(this string suggestedName, IEnumerable<T> collection, T item, Func<T, string> getName, IEqualityComparer<string> comparer)
{
var collectionExceptItem = collection.Where(x => !Equals(x, item));
return MakeUnique(suggestedName, collectionExceptItem, getName, comparer);
}
/// <summary>
/// Makes the string unique by incrementing a number at the end.
/// </summary>
/// <param name="name"></param>
/// <param name="exists">A predicate that determines if the name is unique.</param>
/// <param name="maxClashCount">Maximum number of times we can encounter a clash (mainly to validate the predicate)</param>
/// <returns></returns>
public static string MakeUnique(this string name, Predicate<string> exists, int maxClashCount)
{
Debug.Assert(exists != null);
if (exists(name))
{
name = name ?? string.Empty;
string baseValue = name;
if (name.EndsWith(")"))
{
string number = name.ExtractLast(" (", ")");
int dummy;
if (!string.IsNullOrEmpty(number) && int.TryParse(number, out dummy))
{
baseValue = name.Substring(0, name.LastIndexOf(" ("));
}
}
int index = 0;
string result;
do
{
index++;
result = $"{baseValue} ({index})";
Throw.InvalidArgumentIf(index > maxClashCount + 1, "The predicate is invalid, it should have found a unique name.", "predicate");
}
while (exists(result));
return result;
}
return name;
}
#endregion
#region NonEmpty
/// <summary>
/// Replaces null or empty string by <paramref name="fallback"/>
/// </summary>
public static string NonEmpty(this string original, string fallback)
{
return string.IsNullOrEmpty(original) ? fallback : original;
}
#endregion
}
}