You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

90 lines
3.5 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. using System;
  2. using System.IO;
  3. #if NET3
  4. using Path = Net3_Proxy.Path;
  5. #endif
  6. namespace IPA.Utilities
  7. {
  8. /// <summary>
  9. /// A class providing various extension methods.
  10. /// </summary>
  11. public static class Extensions
  12. {
  13. /// <summary>
  14. /// Gets the default value for a given <see cref="Type"/>.
  15. /// </summary>
  16. /// <param name="type">the <see cref="Type"/> to get the default value for</param>
  17. /// <returns>the default value of <paramref name="type"/></returns>
  18. public static object GetDefault(this Type type)
  19. {
  20. return type.IsValueType ? Activator.CreateInstance(type) : null;
  21. }
  22. /// <summary>
  23. /// Unwraps a <see cref="Nullable{T}"/> where T is <see cref="bool"/> such that if the value is null, it gives <see langword="false"/>.
  24. /// </summary>
  25. /// <param name="self">the bool? to unwrap</param>
  26. /// <returns>the unwrapped value, or <see langword="false"/> if it was <see langword="null"/></returns>
  27. public static bool Unwrap(this bool? self) => self != null && self.Value;
  28. /// <summary>
  29. /// Returns true if <paramref name="path"/> starts with the path <paramref name="baseDirPath"/>.
  30. /// The comparison is case-insensitive, handles / and \ slashes as folder separators and
  31. /// only matches if the base dir folder name is matched exactly ("c:\foobar\file.txt" is not a sub path of "c:\foo").
  32. /// </summary>
  33. public static bool IsSubPathOf(this string path, string baseDirPath)
  34. {
  35. string normalizedPath = Path.GetFullPath(path.Replace('/', '\\')
  36. .WithEnding("\\"));
  37. string normalizedBaseDirPath = Path.GetFullPath(baseDirPath.Replace('/', '\\')
  38. .WithEnding("\\"));
  39. return normalizedPath.StartsWith(normalizedBaseDirPath, StringComparison.OrdinalIgnoreCase);
  40. }
  41. /// <summary>
  42. /// Returns <paramref name="str"/> with the minimal concatenation of <paramref name="ending"/> (starting from end) that
  43. /// results in satisfying .EndsWith(ending).
  44. /// </summary>
  45. /// <example>"hel".WithEnding("llo") returns "hello", which is the result of "hel" + "lo".</example>
  46. public static string WithEnding(this string str, string ending)
  47. {
  48. if (str == null)
  49. return ending;
  50. string result = str;
  51. // Right() is 1-indexed, so include these cases
  52. // * Append no characters
  53. // * Append up to N characters, where N is ending length
  54. for (int i = 0; i <= ending.Length; i++)
  55. {
  56. string tmp = result + ending.Right(i);
  57. if (tmp.EndsWith(ending))
  58. return tmp;
  59. }
  60. return result;
  61. }
  62. /// <summary>Gets the rightmost <paramref name="length" /> characters from a string.</summary>
  63. /// <param name="value">The string to retrieve the substring from.</param>
  64. /// <param name="length">The number of characters to retrieve.</param>
  65. /// <returns>The substring.</returns>
  66. public static string Right(this string value, int length)
  67. {
  68. if (value == null)
  69. {
  70. throw new ArgumentNullException("value");
  71. }
  72. if (length < 0)
  73. {
  74. throw new ArgumentOutOfRangeException("length", length, "Length is less than zero");
  75. }
  76. return (length < value.Length) ? value.Substring(value.Length - length) : value;
  77. }
  78. }
  79. }