using System.Collections.Generic;
using System.Globalization;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using JetBrains.Annotations;
using Volo.Abp;
namespace System;
///
/// Extension methods for String class.
///
public static class AbpStringExtensions
{
///
/// Adds a char to end of given string if it does not ends with the char.
///
public static string EnsureEndsWith(this string str, char c, StringComparison comparisonType = StringComparison.Ordinal)
{
Check.NotNull(str, nameof(str));
if (str.EndsWith(c.ToString(), comparisonType))
{
return str;
}
return str + c;
}
///
/// Adds a char to beginning of given string if it does not starts with the char.
///
public static string EnsureStartsWith(this string str, char c, StringComparison comparisonType = StringComparison.Ordinal)
{
Check.NotNull(str, nameof(str));
if (str.StartsWith(c.ToString(), comparisonType))
{
return str;
}
return c + str;
}
///
/// Indicates whether this string is null or an System.String.Empty string.
///
[ContractAnnotation("str:null => true")]
public static bool IsNullOrEmpty([System.Diagnostics.CodeAnalysis.NotNullWhen(false)]this string? str)
{
return string.IsNullOrEmpty(str);
}
///
/// indicates whether this string is null, empty, or consists only of white-space characters.
///
[ContractAnnotation("str:null => true")]
public static bool IsNullOrWhiteSpace([System.Diagnostics.CodeAnalysis.NotNullWhen(false)]this string? str)
{
return string.IsNullOrWhiteSpace(str);
}
///
/// Gets a substring of a string from beginning of the string.
///
/// Thrown if is null
/// Thrown if is bigger that string's length
public static string Left(this string str, int len)
{
Check.NotNull(str, nameof(str));
if (str.Length < len)
{
throw new ArgumentException("len argument can not be bigger than given string's length!");
}
return str.Substring(0, len);
}
///
/// Converts line endings in the string to .
///
public static string NormalizeLineEndings(this string str)
{
return str.Replace("\r\n", "\n").Replace("\r", "\n").Replace("\n", Environment.NewLine);
}
///
/// Gets index of nth occurrence of a char in a string.
///
/// source string to be searched
/// Char to search in
/// Count of the occurrence
public static int NthIndexOf(this string str, char c, int n)
{
Check.NotNull(str, nameof(str));
var count = 0;
for (var i = 0; i < str.Length; i++)
{
if (str[i] != c)
{
continue;
}
if ((++count) == n)
{
return i;
}
}
return -1;
}
///
/// Removes first occurrence of the given postfixes from end of the given string.
///
/// The string.
/// one or more postfix.
/// Modified string or the same string if it has not any of given postfixes
[ContractAnnotation("null <= str:null")]
public static string RemovePostFix(this string str, params string[] postFixes)
{
return str.RemovePostFix(StringComparison.Ordinal, postFixes);
}
///
/// Removes first occurrence of the given postfixes from end of the given string.
///
/// The string.
/// String comparison type
/// one or more postfix.
/// Modified string or the same string if it has not any of given postfixes
[ContractAnnotation("null <= str:null")]
public static string RemovePostFix(this string str, StringComparison comparisonType, params string[] postFixes)
{
if (str.IsNullOrEmpty())
{
return str;
}
if (postFixes.IsNullOrEmpty())
{
return str;
}
foreach (var postFix in postFixes)
{
if (str.EndsWith(postFix, comparisonType))
{
return str.Left(str.Length - postFix.Length);
}
}
return str;
}
///
/// Removes first occurrence of the given prefixes from beginning of the given string.
///
/// The string.
/// one or more prefix.
/// Modified string or the same string if it has not any of given prefixes
[ContractAnnotation("null <= str:null")]
public static string RemovePreFix(this string str, params string[] preFixes)
{
return str.RemovePreFix(StringComparison.Ordinal, preFixes);
}
///
/// Removes first occurrence of the given prefixes from beginning of the given string.
///
/// The string.
/// String comparison type
/// one or more prefix.
/// Modified string or the same string if it has not any of given prefixes
[ContractAnnotation("null <= str:null")]
public static string RemovePreFix(this string str, StringComparison comparisonType, params string[] preFixes)
{
if (str.IsNullOrEmpty())
{
return str;
}
if (preFixes.IsNullOrEmpty())
{
return str;
}
foreach (var preFix in preFixes)
{
if (str.StartsWith(preFix, comparisonType))
{
return str.Right(str.Length - preFix.Length);
}
}
return str;
}
public static string ReplaceFirst(this string str, string search, string replace, StringComparison comparisonType = StringComparison.Ordinal)
{
Check.NotNull(str, nameof(str));
var pos = str.IndexOf(search, comparisonType);
if (pos < 0)
{
return str;
}
var searchLength = search.Length;
var replaceLength = replace.Length;
var newLength = str.Length - searchLength + replaceLength;
Span buffer = newLength <= 1024 ? stackalloc char[newLength] : new char[newLength];
// Copy the part of the original string before the search term
str.AsSpan(0, pos).CopyTo(buffer);
// Copy the replacement text
replace.AsSpan().CopyTo(buffer.Slice(pos));
// Copy the remainder of the original string
str.AsSpan(pos + searchLength).CopyTo(buffer.Slice(pos + replaceLength));
return buffer.ToString();
}
///
/// Gets a substring of a string from end of the string.
///
/// Thrown if is null
/// Thrown if is bigger that string's length
public static string Right(this string str, int len)
{
Check.NotNull(str, nameof(str));
if (str.Length < len)
{
throw new ArgumentException("len argument can not be bigger than given string's length!");
}
return str.Substring(str.Length - len, len);
}
///
/// Uses string.Split method to split given string by given separator.
///
public static string[] Split(this string str, string separator)
{
return str.Split(new[] { separator }, StringSplitOptions.None);
}
///
/// Uses string.Split method to split given string by given separator.
///
public static string[] Split(this string str, string separator, StringSplitOptions options)
{
return str.Split(new[] { separator }, options);
}
///
/// Uses string.Split method to split given string by .
///
public static string[] SplitToLines(this string str)
{
return str.Split(Environment.NewLine);
}
///
/// Uses string.Split method to split given string by .
///
public static string[] SplitToLines(this string str, StringSplitOptions options)
{
return str.Split(Environment.NewLine, options);
}
///
/// Converts PascalCase string to camelCase string.
///
/// String to convert
/// set true to use current culture. Otherwise, invariant culture will be used.
/// set true to if you want to convert 'XYZ' to 'xyz'.
/// camelCase of the string
[ContractAnnotation("null <= str:null")]
public static string ToCamelCase(this string str, bool useCurrentCulture = false, bool handleAbbreviations = false)
{
if (string.IsNullOrWhiteSpace(str))
{
return str;
}
if (str.Length == 1)
{
return useCurrentCulture ? str.ToLower() : str.ToLowerInvariant();
}
if (handleAbbreviations && IsAllUpperCase(str))
{
return useCurrentCulture ? str.ToLower() : str.ToLowerInvariant();
}
return (useCurrentCulture ? char.ToLower(str[0]) : char.ToLowerInvariant(str[0])) + str.Substring(1);
}
///
/// Converts given PascalCase/camelCase string to sentence (by splitting words by space).
/// Example: "ThisIsSampleSentence" is converted to "This is a sample sentence".
///
/// String to convert.
/// set true to use current culture. Otherwise, invariant culture will be used.
[ContractAnnotation("null <= str:null")]
public static string ToSentenceCase(this string str, bool useCurrentCulture = false)
{
if (string.IsNullOrWhiteSpace(str))
{
return str;
}
return useCurrentCulture
? Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + " " + char.ToLower(m.Value[1]))
: Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + " " + char.ToLowerInvariant(m.Value[1]));
}
///
/// Converts given PascalCase/camelCase string to kebab-case.
///
/// String to convert.
/// set true to use current culture. Otherwise, invariant culture will be used.
[ContractAnnotation("null <= str:null")]
public static string ToKebabCase(this string str, bool useCurrentCulture = false)
{
if (string.IsNullOrWhiteSpace(str))
{
return str;
}
str = str.ToCamelCase();
return useCurrentCulture
? Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + "-" + char.ToLower(m.Value[1]))
: Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + "-" + char.ToLowerInvariant(m.Value[1]));
}
///
/// Converts given PascalCase/camelCase string to snake case.
/// Example: "ThisIsSampleSentence" is converted to "this_is_a_sample_sentence".
/// https://github.com/npgsql/npgsql/blob/dev/src/Npgsql/NameTranslation/NpgsqlSnakeCaseNameTranslator.cs#L51
///
/// String to convert.
///
public static string ToSnakeCase(this string str)
{
return str.IsNullOrWhiteSpace() ? str : JsonNamingPolicy.SnakeCaseLower.ConvertName(str);
}
///
/// Converts string to enum value.
///
/// Type of enum
/// String value to convert
/// Returns enum object
public static T ToEnum(this string value)
where T : struct
{
Check.NotNull(value, nameof(value));
return (T)Enum.Parse(typeof(T), value);
}
///
/// Converts string to enum value.
///
/// Type of enum
/// String value to convert
/// Ignore case
/// Returns enum object
public static T ToEnum(this string value, bool ignoreCase)
where T : struct
{
Check.NotNull(value, nameof(value));
return (T)Enum.Parse(typeof(T), value, ignoreCase);
}
public static string ToMd5(this string str)
{
using (var md5 = MD5.Create())
{
var inputBytes = Encoding.UTF8.GetBytes(str);
var hashBytes = md5.ComputeHash(inputBytes);
var sb = new StringBuilder();
foreach (var hashByte in hashBytes)
{
sb.Append(hashByte.ToString("X2"));
}
return sb.ToString();
}
}
///
/// Converts camelCase string to PascalCase string.
///
/// String to convert
/// set true to use current culture. Otherwise, invariant culture will be used.
/// PascalCase of the string
[ContractAnnotation("null <= str:null")]
public static string ToPascalCase(this string str, bool useCurrentCulture = false)
{
if (string.IsNullOrWhiteSpace(str))
{
return str;
}
if (str.Length == 1)
{
return useCurrentCulture ? str.ToUpper() : str.ToUpperInvariant();
}
return (useCurrentCulture ? char.ToUpper(str[0]) : char.ToUpperInvariant(str[0])) + str.Substring(1);
}
///
/// Gets a substring of a string from beginning of the string if it exceeds maximum length.
///
[ContractAnnotation("null <= str:null")]
public static string? Truncate(this string? str, int maxLength)
{
if (str == null)
{
return null;
}
if (str.Length <= maxLength)
{
return str;
}
return str.Left(maxLength);
}
///
/// Gets a substring of a string from Ending of the string if it exceeds maximum length.
///
[ContractAnnotation("null <= str:null")]
public static string? TruncateFromBeginning(this string? str, int maxLength)
{
if (str == null)
{
return null;
}
if (str.Length <= maxLength)
{
return str;
}
return str.Right(maxLength);
}
///
/// Gets a substring of a string from beginning of the string if it exceeds maximum length.
/// It adds a "..." postfix to end of the string if it's truncated.
/// Returning string can not be longer than maxLength.
///
/// Thrown if is null
public static string? TruncateWithPostfix(this string? str, int maxLength)
{
return TruncateWithPostfix(str, maxLength, "...");
}
///
/// Gets a substring of a string from beginning of the string if it exceeds maximum length.
/// It adds given to end of the string if it's truncated.
/// Returning string can not be longer than maxLength.
///
/// Thrown if is null
[ContractAnnotation("null <= str:null")]
public static string? TruncateWithPostfix(this string? str, int maxLength, string postfix)
{
if (str == null)
{
return null;
}
if (str == string.Empty || maxLength == 0)
{
return string.Empty;
}
if (str.Length <= maxLength)
{
return str;
}
if (maxLength <= postfix.Length)
{
return postfix.Left(maxLength);
}
return str.Left(maxLength - postfix.Length) + postfix;
}
///
/// Converts given string to a byte array using encoding.
///
public static byte[] GetBytes(this string str)
{
return str.GetBytes(Encoding.UTF8);
}
///
/// Converts given string to a byte array using the given
///
public static byte[] GetBytes([NotNull] this string str, [NotNull] Encoding encoding)
{
Check.NotNull(str, nameof(str));
Check.NotNull(encoding, nameof(encoding));
return encoding.GetBytes(str);
}
private static bool IsAllUpperCase(string input)
{
for (int i = 0; i < input.Length; i++)
{
if (Char.IsLetter(input[i]) && !Char.IsUpper(input[i]))
{
return false;
}
}
return true;
}
}