| | 1 | | namespace Songhay.Extensions; |
| | 2 | |
|
| | 3 | | /// <summary> |
| | 4 | | /// Extensions of <see cref="string"/>. |
| | 5 | | /// </summary> |
| | 6 | | public static partial class StringExtensions |
| | 7 | | { |
| | 8 | | /// <summary> |
| | 9 | | /// Returns <c>true</c> when the strings are equal without regard to cultural locales |
| | 10 | | /// or casing. |
| | 11 | | /// </summary> |
| | 12 | | /// <param name="input">The input.</param> |
| | 13 | | /// <param name="otherString">The other <see cref="string"/>.</param> |
| | 14 | | public static bool EqualsInvariant(this string? input, string? otherString) => |
| 12 | 15 | | input.EqualsInvariant(otherString, ignoreCase: true); |
| | 16 | |
|
| | 17 | | /// <summary> |
| | 18 | | /// Returns <c>true</c> when the strings are equal without regard to cultural locales. |
| | 19 | | /// </summary> |
| | 20 | | /// <param name="input">The input.</param> |
| | 21 | | /// <param name="otherString">The other <see cref="string"/>.</param> |
| | 22 | | /// <param name="ignoreCase"></param> |
| | 23 | | public static bool EqualsInvariant(this string? input, string? otherString, bool ignoreCase) |
| 12 | 24 | | { |
| 12 | 25 | | return ignoreCase |
| 12 | 26 | | ? string.Equals(input, otherString, StringComparison.InvariantCultureIgnoreCase) |
| 12 | 27 | | : string.Equals(input, otherString, StringComparison.InvariantCulture); |
| 12 | 28 | | } |
| | 29 | |
|
| | 30 | | /// <summary> |
| | 31 | | /// Escapes the interpolation tokens of <see cref="string.Format(string, object[])"/>. |
| | 32 | | /// </summary> |
| | 33 | | /// <param name="input">The input.</param> |
| | 34 | | public static string? EscapeInterpolation(this string? input) => |
| 1 | 35 | | string.IsNullOrWhiteSpace(input) ? input : input.Replace("{", "{{").Replace("}", "}}"); |
| | 36 | |
|
| | 37 | | /// <summary> |
| | 38 | | /// Converts camel-case <see cref="string"/> to <see cref="IEnumerable{T}"/>. |
| | 39 | | /// </summary> |
| | 40 | | /// <param name="input">The input.</param> |
| | 41 | | public static IEnumerable<string> FromCamelCaseToEnumerable(this string? input) => |
| 1 | 42 | | new string(input.InsertSpacesBeforeCaps().ToArray()) |
| 7 | 43 | | .Split(' ').Where(i => !string.IsNullOrWhiteSpace(i)); |
| | 44 | |
|
| | 45 | | /// <summary> |
| | 46 | | /// Determines whether the specified input is in the comma-delimited values. |
| | 47 | | /// </summary> |
| | 48 | | /// <param name="input">The input.</param> |
| | 49 | | /// <param name="delimitedValues">The delimited values.</param> |
| 3 | 50 | | public static bool In(this string? input, string? delimitedValues) => input.In(delimitedValues, ','); |
| | 51 | |
|
| | 52 | | /// <summary> |
| | 53 | | /// Determines whether the specified input is in the delimited values. |
| | 54 | | /// </summary> |
| | 55 | | /// <param name="input">The input.</param> |
| | 56 | | /// <param name="delimitedValues">The delimited values.</param> |
| | 57 | | /// <param name="separator">The separator.</param> |
| | 58 | | public static bool In(this string? input, string? delimitedValues, char separator) |
| 3 | 59 | | { |
| 5 | 60 | | if (string.IsNullOrWhiteSpace(input)) return false; |
| 1 | 61 | | if (string.IsNullOrWhiteSpace(delimitedValues)) return false; |
| | 62 | |
|
| 1 | 63 | | var set = delimitedValues.Split(separator); |
| | 64 | |
|
| 1 | 65 | | return set.Contains(input); |
| 3 | 66 | | } |
| | 67 | |
|
| | 68 | | /// <summary> |
| | 69 | | /// Returns <see cref="string"/> in double quotes. |
| | 70 | | /// </summary> |
| | 71 | | /// <param name="input">The input.</param> |
| | 72 | | public static string? InDoubleQuotes(this string? input) |
| 1 | 73 | | { |
| 1 | 74 | | if (string.IsNullOrWhiteSpace(input)) return null; |
| | 75 | |
|
| 1 | 76 | | input = input.Replace("\"", "\"\""); |
| | 77 | |
|
| 1 | 78 | | return $"\"{input}\""; |
| 1 | 79 | | } |
| | 80 | |
|
| | 81 | | /// <summary> |
| | 82 | | /// Returns <see cref="string"/> in double quotes or default. |
| | 83 | | /// </summary> |
| | 84 | | /// <param name="input">The input.</param> |
| | 85 | | /// <param name="defaultValue">The default value.</param> |
| | 86 | | public static string? InDoubleQuotesOrDefault(this string? input, string defaultValue) => |
| 2 | 87 | | string.IsNullOrWhiteSpace(input) ? defaultValue : input.InDoubleQuotes(); |
| | 88 | |
|
| | 89 | | /// <summary> |
| | 90 | | /// Inserts the spaces before caps. |
| | 91 | | /// </summary> |
| | 92 | | /// <param name="input">The input.</param> |
| | 93 | | public static IEnumerable<char> InsertSpacesBeforeCaps(this string? input) |
| 2 | 94 | | { |
| 2 | 95 | | if (string.IsNullOrWhiteSpace(input)) yield return '\0'; |
| | 96 | |
|
| 78 | 97 | | foreach (char c in input!) |
| 36 | 98 | | { |
| 43 | 99 | | if (char.IsUpper(c)) yield return ' '; |
| 36 | 100 | | yield return c; |
| 36 | 101 | | } |
| 2 | 102 | | } |
| | 103 | |
|
| | 104 | | /// <summary> |
| | 105 | | /// Determines whether the specified input is byte. |
| | 106 | | /// </summary> |
| | 107 | | /// <param name="input">The input.</param> |
| | 108 | | /// <returns> |
| | 109 | | /// <c>true</c> if the specified input is byte; otherwise, <c>false</c>. |
| | 110 | | /// </returns> |
| 0 | 111 | | public static bool IsByte(this string? input) => input.IsByte(null); |
| | 112 | |
|
| | 113 | | /// <summary> |
| | 114 | | /// Determines whether the specified input is byte. |
| | 115 | | /// </summary> |
| | 116 | | /// <param name="input">The input.</param> |
| | 117 | | /// <param name="secondaryTest">The secondary test.</param> |
| | 118 | | /// <returns> |
| | 119 | | /// <c>true</c> if the specified input is byte; otherwise, <c>false</c>. |
| | 120 | | /// </returns> |
| | 121 | | public static bool IsByte(this string? input, Predicate<byte>? secondaryTest) |
| 0 | 122 | | { |
| 0 | 123 | | var isExpectedType = byte.TryParse(input, out var testValue); |
| | 124 | |
|
| 0 | 125 | | return isExpectedType ? secondaryTest?.Invoke(testValue) ?? isExpectedType : isExpectedType; |
| 0 | 126 | | } |
| | 127 | |
|
| | 128 | | /// <summary> |
| | 129 | | /// Determines whether the specified input is decimal. |
| | 130 | | /// </summary> |
| | 131 | | /// <param name="input">The input.</param> |
| | 132 | | /// <returns> |
| | 133 | | /// <c>true</c> if the specified input is decimal; otherwise, <c>false</c>. |
| | 134 | | /// </returns> |
| 0 | 135 | | public static bool IsDecimal(this string? input) => input.IsDecimal(null); |
| | 136 | |
|
| | 137 | | /// <summary> |
| | 138 | | /// Determines whether the specified input is decimal. |
| | 139 | | /// </summary> |
| | 140 | | /// <param name="input">The input.</param> |
| | 141 | | /// <param name="secondaryTest">The secondary test.</param> |
| | 142 | | /// <returns> |
| | 143 | | /// <c>true</c> if the specified input is decimal; otherwise, <c>false</c>. |
| | 144 | | /// </returns> |
| | 145 | | public static bool IsDecimal(this string? input, Predicate<decimal>? secondaryTest) |
| 0 | 146 | | { |
| 0 | 147 | | var isExpectedType = decimal.TryParse(input, out var testValue); |
| | 148 | |
|
| 0 | 149 | | return isExpectedType ? secondaryTest?.Invoke(testValue) ?? isExpectedType : isExpectedType; |
| 0 | 150 | | } |
| | 151 | |
|
| | 152 | | /// <summary> |
| | 153 | | /// Determines whether the specified input is integer. |
| | 154 | | /// </summary> |
| | 155 | | /// <param name="input">The input.</param> |
| | 156 | | /// <returns> |
| | 157 | | /// <c>true</c> if the specified input is integer; otherwise, <c>false</c>. |
| | 158 | | /// </returns> |
| 0 | 159 | | public static bool IsInteger(this string? input) => input.IsInteger(null); |
| | 160 | |
|
| | 161 | | /// <summary> |
| | 162 | | /// Determines whether the specified input is integer. |
| | 163 | | /// </summary> |
| | 164 | | /// <param name="input">The input.</param> |
| | 165 | | /// <param name="secondaryTest">The secondary test.</param> |
| | 166 | | /// <returns> |
| | 167 | | /// <c>true</c> if the specified input is integer; otherwise, <c>false</c>. |
| | 168 | | /// </returns> |
| | 169 | | public static bool IsInteger(this string? input, Predicate<int>? secondaryTest) |
| 0 | 170 | | { |
| 0 | 171 | | var isExpectedType = int.TryParse(input, out var testValue); |
| | 172 | |
|
| 0 | 173 | | return isExpectedType ? secondaryTest?.Invoke(testValue) ?? isExpectedType : isExpectedType; |
| 0 | 174 | | } |
| | 175 | |
|
| | 176 | | /// <summary> |
| | 177 | | /// Determines whether the specified input is long. |
| | 178 | | /// </summary> |
| | 179 | | /// <param name="input">The input.</param> |
| | 180 | | /// <returns> |
| | 181 | | /// <c>true</c> if the specified input is long; otherwise, <c>false</c>. |
| | 182 | | /// </returns> |
| 0 | 183 | | public static bool IsLong(this string? input) => input.IsLong(null); |
| | 184 | |
|
| | 185 | | /// <summary> |
| | 186 | | /// Determines whether the specified input is long. |
| | 187 | | /// </summary> |
| | 188 | | /// <param name="input">The input.</param> |
| | 189 | | /// <param name="secondaryTest">The secondary test.</param> |
| | 190 | | /// <returns> |
| | 191 | | /// <c>true</c> if the specified input is long; otherwise, <c>false</c>. |
| | 192 | | /// </returns> |
| | 193 | | public static bool IsLong(this string? input, Predicate<long>? secondaryTest) |
| 0 | 194 | | { |
| 0 | 195 | | var isExpectedType = long.TryParse(input, out var testValue); |
| | 196 | |
|
| 0 | 197 | | return isExpectedType ? secondaryTest?.Invoke(testValue) ?? isExpectedType : isExpectedType; |
| 0 | 198 | | } |
| | 199 | |
|
| | 200 | | /// <summary> |
| | 201 | | /// Determines whether the specified input is a telephone number. |
| | 202 | | /// </summary> |
| | 203 | | /// <param name="input">The input.</param> |
| | 204 | | /// <returns> |
| | 205 | | /// <c>true</c> if is telephone number; otherwise, <c>false</c>. |
| | 206 | | /// </returns> |
| | 207 | | public static bool IsTelephoneNumber(this string? input) => |
| 4 | 208 | | !string.IsNullOrWhiteSpace(input) && |
| 4 | 209 | | Regex.IsMatch(input, @"^\(?[0-9]\d{2}\)?([-., ])?[0-9]\d{2}([-., ])?\d{4}$"); |
| | 210 | |
|
| | 211 | | /// <summary> |
| | 212 | | /// Determines whether the specified input is a UNC. |
| | 213 | | /// </summary> |
| | 214 | | /// <param name="input">The input.</param> |
| | 215 | | /// <returns> |
| | 216 | | /// <c>true</c> if is a UNC; otherwise, <c>false</c>. |
| | 217 | | /// </returns> |
| | 218 | | /// <remarks> |
| | 219 | | /// 📚 https://stackoverflow.com/a/47531093/22944 |
| | 220 | | /// 📚 https://en.wikipedia.org/wiki/Path_(computing)#Uniform_Naming_Convention |
| | 221 | | /// </remarks> |
| | 222 | | public static bool IsUnc(this string? input) => |
| 4 | 223 | | !string.IsNullOrWhiteSpace(input) && |
| 4 | 224 | | Regex.IsMatch(input, @"^(\\(\\[^\s\\]+)+|([A-Za-z]:(\\)?|[A-z]:(\\[^\s\\]+)+))(\\)?$"); |
| | 225 | |
|
| | 226 | | /// <summary> |
| | 227 | | /// Determines whether the specified input looks like an email address. |
| | 228 | | /// </summary> |
| | 229 | | /// <param name="input">The input.</param> |
| | 230 | | /// <returns> |
| | 231 | | /// <c>true</c> if seems to be an email address; otherwise, <c>false</c>. |
| | 232 | | /// </returns> |
| | 233 | | /// <remarks> |
| | 234 | | /// “In short, don’t expect a single, usable regex to do a proper job. |
| | 235 | | /// And the best regex will validate the syntax, not the validity |
| | 236 | | /// of an e-mail (jhohn@example.com is correct but it will probably bounce…).” |
| | 237 | | /// [http://stackoverflow.com/questions/201323/how-to-use-a-regular-expression-to-validate-an-email-addresses] |
| | 238 | | /// </remarks> |
| | 239 | | public static bool LooksLikeEmailAddress(this string? input) => |
| 0 | 240 | | !string.IsNullOrWhiteSpace(input) && |
| 0 | 241 | | Regex.IsMatch(input, @"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"); |
| | 242 | |
|
| | 243 | | /// <summary> |
| | 244 | | /// Remove accent from strings |
| | 245 | | /// </summary> |
| | 246 | | /// <example> |
| | 247 | | /// input: "Příliš žluťoučký kůň úpěl ďábelské ódy." |
| | 248 | | /// result: "Prilis zlutoucky kun upel dabelske ody." |
| | 249 | | /// </example> |
| | 250 | | /// <param name="input">The input.</param> |
| | 251 | | /// <remarks> |
| | 252 | | /// From Tomas Kubes, http://www.codeproject.com/Articles/31050/String-Extension-Collection-for-C |
| | 253 | | /// Also, see http://stackoverflow.com/questions/249087/how-do-i-remove-diacritics-accents-from-a-string-in-net |
| | 254 | | /// </remarks> |
| | 255 | | /// <returns><see cref="string"/> without accents</returns> |
| | 256 | | public static string RemoveDiacritics(this string input) |
| 0 | 257 | | { |
| 0 | 258 | | string stFormD = input.Normalize(NormalizationForm.FormD); |
| 0 | 259 | | StringBuilder sb = new StringBuilder(); |
| | 260 | |
|
| 0 | 261 | | foreach (var t in stFormD) |
| 0 | 262 | | { |
| 0 | 263 | | UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(t); |
| 0 | 264 | | if (uc != UnicodeCategory.NonSpacingMark) |
| 0 | 265 | | { |
| 0 | 266 | | sb.Append(t); |
| 0 | 267 | | } |
| 0 | 268 | | } |
| | 269 | |
|
| 0 | 270 | | return sb.ToString().Normalize(NormalizationForm.FormC); |
| 0 | 271 | | } |
| | 272 | | } |