Radarr/src/NzbDrone.Common/Extensions/StringExtensions.cs

224 lines
6.8 KiB
C#
Raw Normal View History

2013-08-18 01:52:56 +00:00
using System;
2018-11-23 07:03:32 +00:00
using System.Collections.Generic;
2013-08-18 01:52:56 +00:00
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Sockets;
2013-07-24 05:35:32 +00:00
using System.Text;
using System.Text.RegularExpressions;
namespace NzbDrone.Common.Extensions
{
public static class StringExtensions
{
2018-11-23 07:03:32 +00:00
private static readonly Regex CamelCaseRegex = new Regex("(?<!^)[A-Z]", RegexOptions.Compiled);
2013-08-18 01:52:56 +00:00
public static string NullSafe(this string target)
{
2013-08-18 01:52:56 +00:00
return ((object)target).NullSafe().ToString();
}
2013-08-18 01:52:56 +00:00
public static object NullSafe(this object target)
{
2019-12-22 22:08:53 +00:00
if (target != null)
{
return target;
}
2013-08-18 01:52:56 +00:00
return "[NULL]";
}
public static string FirstCharToLower(this string input)
{
2019-06-29 22:33:49 +00:00
if (string.IsNullOrEmpty(input))
{
return string.Empty;
}
return char.ToLowerInvariant(input.First()) + input.Substring(1);
}
2013-08-18 01:52:56 +00:00
public static string FirstCharToUpper(this string input)
{
2019-06-29 22:33:49 +00:00
if (string.IsNullOrEmpty(input))
{
return string.Empty;
}
return char.ToUpperInvariant(input.First()) + input.Substring(1);
2013-08-18 01:52:56 +00:00
}
2013-08-18 01:52:56 +00:00
public static string Inject(this string format, params object[] formattingArgs)
{
return string.Format(format, formattingArgs);
}
2013-08-18 01:52:56 +00:00
private static readonly Regex CollapseSpace = new Regex(@"\s+", RegexOptions.Compiled);
public static string Replace(this string text, int index, int length, string replacement)
{
text = text.Remove(index, length);
text = text.Insert(index, replacement);
return text;
}
2013-08-18 01:52:56 +00:00
public static string RemoveAccent(this string text)
{
2013-08-18 01:52:56 +00:00
var normalizedString = text.Normalize(NormalizationForm.FormD);
var stringBuilder = new StringBuilder();
foreach (var c in normalizedString)
{
var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
if (unicodeCategory != UnicodeCategory.NonSpacingMark)
{
stringBuilder.Append(c);
}
}
return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
}
public static string TrimEnd(this string text, string postfix)
{
if (text.EndsWith(postfix))
2019-12-22 22:08:53 +00:00
{
text = text.Substring(0, text.Length - postfix.Length);
2019-12-22 22:08:53 +00:00
}
return text;
}
2018-11-23 07:03:32 +00:00
public static string Join(this IEnumerable<string> values, string separator)
{
return string.Join(separator, values);
}
2013-08-18 01:52:56 +00:00
public static string CleanSpaces(this string text)
{
2013-08-18 01:52:56 +00:00
return CollapseSpace.Replace(text, " ").Trim();
}
2014-02-26 05:40:47 +00:00
public static bool IsNullOrWhiteSpace(this string text)
{
return string.IsNullOrWhiteSpace(text);
2014-02-26 05:40:47 +00:00
}
2014-09-11 23:49:41 +00:00
public static bool IsNotNullOrWhiteSpace(this string text)
{
return !string.IsNullOrWhiteSpace(text);
2014-09-11 23:49:41 +00:00
}
New: Refactor MediaInfo tokens (fixes old tokens adds new stuff) (#3058) * Rename all 'episodeFile' variables to 'movieFile' * Improve media info extraction with more fields * Improve media info tokens extraction * Add missing fields to MediaInfoModel * Restore to previous implementation of null handling * Forgot to add MediaInfoFormatter to project * Add missing EqualsIgnoreCase extension method * Simplify Logger.Debug() invocations * Add missing StartsWithIgnoreCase extension method * This '.Value' shouldn't be required * Remove TODO comment * Upgrade MediaInfo from 17.10 to 18.08.1 * Use correct media info field for files listing * Replace media info "VideoCodec" (deprecated) with "VideoFormat" * Fix 'Formatiting' typos * Add support for media info Format_AdditionalFeatures' field * Add proper support for all DTS and TrueHD flavors * Add support for '3D' media info token * Remove deprecated media info video/audio profile fields * Add support for 'HDR' media info token * Add new video parameters to anime file name sample * Adapt tests for new media info fields * Revert "Remove deprecated media info video/audio profile fields" * Include missing test files in core test project * Fix small regression issue * Allow sample movie to be detected as HDR * Do not parse audio channel positions if there are no channels * Clean up extra blank line * Reuse already declared variable * Fix wrong audio channels detection on DTS:X streams * Fix all failing unit tests * Fix remaining failing unit tests
2018-10-30 20:44:59 +00:00
public static bool StartsWithIgnoreCase(this string text, string startsWith)
{
return text.StartsWith(startsWith, StringComparison.InvariantCultureIgnoreCase);
}
public static bool EndsWithIgnoreCase(this string text, string startsWith)
{
return text.EndsWith(startsWith, StringComparison.InvariantCultureIgnoreCase);
}
public static bool EqualsIgnoreCase(this string text, string equals)
{
return text.Equals(equals, StringComparison.InvariantCultureIgnoreCase);
}
public static bool ContainsIgnoreCase(this string text, string contains)
{
return text.IndexOf(contains, StringComparison.InvariantCultureIgnoreCase) > -1;
}
public static string WrapInQuotes(this string text)
{
if (!text.Contains(' '))
{
return text;
}
return "\"" + text + "\"";
}
public static byte[] HexToByteArray(this string input)
{
return Enumerable.Range(0, input.Length)
2019-12-22 22:08:53 +00:00
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(input.Substring(x, 2), 16))
.ToArray();
}
public static string ToHexString(this byte[] input)
{
return string.Concat(Array.ConvertAll(input, x => x.ToString("X2")));
}
public static string FromOctalString(this string octalValue)
{
octalValue = octalValue.TrimStart('\\');
var first = int.Parse(octalValue.Substring(0, 1));
var second = int.Parse(octalValue.Substring(1, 1));
var third = int.Parse(octalValue.Substring(2, 1));
2019-12-22 22:08:53 +00:00
var byteResult = (byte)((first << 6) | (second << 3) | third);
2019-12-22 22:08:53 +00:00
return Encoding.ASCII.GetString(new[] { byteResult });
}
2018-11-23 07:03:32 +00:00
public static string SplitCamelCase(this string input)
{
return CamelCaseRegex.Replace(input, match => " " + match.Value);
}
public static bool ContainsIgnoreCase(this IEnumerable<string> source, string value)
{
return source.Contains(value, StringComparer.InvariantCultureIgnoreCase);
}
public static string EncodeRFC3986(this string value)
{
// From Twitterizer http://www.twitterizer.net/
if (string.IsNullOrEmpty(value))
{
return string.Empty;
}
var encoded = Uri.EscapeDataString(value);
return Regex
.Replace(encoded, "(%[0-9a-f][0-9a-f])", c => c.Value.ToUpper())
.Replace("(", "%28")
.Replace(")", "%29")
.Replace("$", "%24")
.Replace("!", "%21")
.Replace("*", "%2A")
.Replace("'", "%27")
.Replace("%7E", "~");
}
public static bool IsValidIpAddress(this string value)
{
if (!IPAddress.TryParse(value, out var parsedAddress))
{
return false;
}
if (parsedAddress.Equals(IPAddress.Parse("255.255.255.255")))
{
return false;
}
if (parsedAddress.IsIPv6Multicast)
{
return false;
}
return parsedAddress.AddressFamily == AddressFamily.InterNetwork || parsedAddress.AddressFamily == AddressFamily.InterNetworkV6;
}
public static string ToUrlHost(this string input)
{
return input.Contains(':') ? $"[{input}]" : input;
}
}
New: Refactor MediaInfo tokens (fixes old tokens adds new stuff) (#3058) * Rename all 'episodeFile' variables to 'movieFile' * Improve media info extraction with more fields * Improve media info tokens extraction * Add missing fields to MediaInfoModel * Restore to previous implementation of null handling * Forgot to add MediaInfoFormatter to project * Add missing EqualsIgnoreCase extension method * Simplify Logger.Debug() invocations * Add missing StartsWithIgnoreCase extension method * This '.Value' shouldn't be required * Remove TODO comment * Upgrade MediaInfo from 17.10 to 18.08.1 * Use correct media info field for files listing * Replace media info "VideoCodec" (deprecated) with "VideoFormat" * Fix 'Formatiting' typos * Add support for media info Format_AdditionalFeatures' field * Add proper support for all DTS and TrueHD flavors * Add support for '3D' media info token * Remove deprecated media info video/audio profile fields * Add support for 'HDR' media info token * Add new video parameters to anime file name sample * Adapt tests for new media info fields * Revert "Remove deprecated media info video/audio profile fields" * Include missing test files in core test project * Fix small regression issue * Allow sample movie to be detected as HDR * Do not parse audio channel positions if there are no channels * Clean up extra blank line * Reuse already declared variable * Fix wrong audio channels detection on DTS:X streams * Fix all failing unit tests * Fix remaining failing unit tests
2018-10-30 20:44:59 +00:00
}