211 lines
8.3 KiB
C#
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
|
|
}
|
|
}
|