Skip to content

Commit

Permalink
feat: Added PathHelper.MakeRelative() and PathHelper.IsSubPathOf() me…
Browse files Browse the repository at this point in the history
…thods
  • Loading branch information
SolidAlloy committed Jun 20, 2021
1 parent 4973a2e commit 7f9803f
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 7 deletions.
6 changes: 3 additions & 3 deletions Runtime/Extensions/RectExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ [PublicAPI] public static void RoundUpCoordinates(this ref Rect rect)
/// <param name="cutDistance">
/// The distance from the left or right border of the rect where to place vertical cut.
/// </param>
/// <param name="fromRightBorder">Whether to count the distance from left or right border.</param>
/// <param name="fromRightSide">Whether to count the distance from left or right border.</param>
/// <returns>Left and right rects that appeared after the cut.</returns>
/// <example><code>
/// (Rect searchFieldArea, Rect buttonArea) = innerToolbarArea.CutVertically(DropdownStyle.IconSize, true);
/// </code></example>
[PublicAPI] public static (Rect leftRect, Rect rightRect) CutVertically(this Rect originalRect, float cutDistance,
bool fromRightBorder = false)
bool fromRightSide = false)
{
Rect leftRect, rightRect;

Expand All @@ -40,7 +40,7 @@ [PublicAPI] public static (Rect leftRect, Rect rightRect) CutVertically(this Rec
var cutDistanceSize = new Vector2(cutDistance, originalRect.height);
var leftoverSize = new Vector2(originalRect.width - cutDistance, originalRect.height);

if (fromRightBorder)
if (fromRightSide)
{
leftRect = new Rect(leftRectPos, leftoverSize);
rightRect = new Rect(RightRectPos(), cutDistanceSize);
Expand Down
99 changes: 99 additions & 0 deletions Runtime/Helpers/PathHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
namespace SolidUtilities.Helpers
{
using System;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using JetBrains.Annotations;

public static class PathHelper
{
/// <summary>
/// Rebases file with path fromPath to folder with baseDir.
/// </summary>
/// <param name="fromPath">Full file path (absolute).</param>
/// <param name="baseDir">Full base directory path (absolute).</param>
/// <returns>Relative path to file in respect of baseDir.</returns>
[PublicAPI]
public static string MakeRelative(string fromPath, string baseDir)
{
const string pathSep = "\\";
string fullFromPath = Path.GetFullPath(fromPath);
string fullBaseDir = Path.GetFullPath(baseDir); // If folder contains upper folder references, they gets lost here. "c:\test\..\test2" => "c:\test2"

string[] p1 = Regex.Split(fullFromPath, "[\\\\/]").Where(x => x.Length != 0).ToArray();
string[] p2 = Regex.Split(fullBaseDir, "[\\\\/]").Where(x => x.Length != 0).ToArray();
int i = 0;

for (; i < p1.Length && i < p2.Length; i++)
if (string.Compare(p1[i], p2[i], StringComparison.OrdinalIgnoreCase) != 0)
break;

if (i == 0) // Cannot make relative path, for example if resides on different drive
return fullFromPath;

string r = string.Join(pathSep, Enumerable.Repeat("..", p2.Length - i).Concat(p1.Skip(i).Take(p1.Length - i)));
return r;
}

/// <summary>
/// Returns true if <paramref name="path"/> starts with the path <paramref name="baseDirPath"/>.
/// The comparison is case-insensitive, handles / and \ slashes as folder separators and
/// only matches if the base dir folder name is matched exactly ("c:\foobar\file.txt" is not a sub path of "c:\foo").
/// </summary>
[PublicAPI]
public static bool IsSubPathOf(string path, string baseDirPath)
{
string normalizedPath = Path.GetFullPath(path.Replace('/', '\\')
.WithEnding("\\"));

string normalizedBaseDirPath = Path.GetFullPath(baseDirPath.Replace('/', '\\')
.WithEnding("\\"));

return normalizedPath.StartsWith(normalizedBaseDirPath, StringComparison.OrdinalIgnoreCase);
}

/// <summary>
/// Returns <paramref name="str"/> with the minimal concatenation of <paramref name="ending"/> (starting from end) that
/// results in satisfying .EndsWith(ending).
/// </summary>
/// <example>"hel".WithEnding("llo") returns "hello", which is the result of "hel" + "lo".</example>
private static string WithEnding([CanBeNull] this string str, string ending)
{
if (str == null)
return ending;

string result = str;

// Right() is 1-indexed, so include these cases
// * Append no characters
// * Append up to N characters, where N is ending length
for (int i = 0; i <= ending.Length; i++)
{
string tmp = result + ending.GetEnding(i);
if (tmp.EndsWith(ending))
return tmp;
}

return result;
}

/// <summary>Gets the rightmost <paramref name="length" /> characters from a string.</summary>
/// <param name="value">The string to retrieve the substring from.</param>
/// <param name="length">The number of characters to retrieve.</param>
/// <returns>The substring.</returns>
private static string GetEnding([NotNull] this string value, int length)
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
if (length < 0)
{
throw new ArgumentOutOfRangeException(nameof(length), length, "Length is less than zero");
}

return (length < value.Length) ? value.Substring(value.Length - length) : value;
}
}
}
3 changes: 3 additions & 0 deletions Runtime/Helpers/PathHelper.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,15 @@
<Reference Include="System.Core" />
<Reference Include="System.Xml" />
<Reference Include="UnityEngine.CoreModule">
<HintPath>C:\Program Files\Unity Editors\2021.1.3f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll</HintPath>
<HintPath>C:\Program Files\Unity Editors\2021.1.9f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.IMGUIModule">
<HintPath>C:\Program Files\Unity Editors\2021.1.3f1\Editor\Data\Managed\UnityEngine\UnityEngine.IMGUIModule.dll</HintPath>
<HintPath>C:\Program Files\Unity Editors\2021.1.9f1\Editor\Data\Managed\UnityEngine\UnityEngine.IMGUIModule.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup Condition=" '$(Platform)' == 'Unity2020'">
<Reference Include="UnityEditor.CoreModule">
<HintPath>C:\Program Files\Unity Editors\2021.1.3f1\Editor\Data\Managed\UnityEngine\UnityEditor.CoreModule.dll</HintPath>
<HintPath>C:\Program Files\Unity Editors\2021.1.9f1\Editor\Data\Managed\UnityEngine\UnityEditor.CoreModule.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup Condition=" '$(Platform)' == 'Unity2019'">
Expand All @@ -76,13 +76,13 @@
<Compile Include="DrawerReplacer.cs" />
<Compile Include="EditorGUIHelper.cs" />
<Compile Include="EditorGUILayoutHelper.cs" />
<Compile Include="EditorGUISlider.cs" />
<Compile Include="EditorGUIUtilityProxy.cs" />
<Compile Include="IDelayable.cs" />
<Compile Include="LogEntries.cs" />
<Compile Include="LogEntry.cs" />
<Compile Include="MonoScriptExtensions.cs" />
<Compile Include="MonoImporterProxy.cs" />
<Compile Include="ProjectWindowUtilProxy.cs" />
<Compile Include="PropertyDrawerExtensions.cs" />
<Compile Include="SerializedPropertyExtensions.cs" />
</ItemGroup>
Expand Down

0 comments on commit 7f9803f

Please sign in to comment.