Skip to content

Commit

Permalink
identify root file as file:///.; link top-level directory to root
Browse files Browse the repository at this point in the history
  • Loading branch information
IS4Code committed Jun 4, 2023
1 parent 97912c8 commit 9c41353
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 9 deletions.
17 changes: 10 additions & 7 deletions SFI/Analyzers/PathObjectAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ public async override ValueTask<AnalysisResult> Analyze(PathObject path, Analysi
{
if(context.Node is not ILinkedNode node)
{
if(path.IsRootDirectory)
if(path.IsRoot)
{
node = context.NodeFactory.Create(RootDirectoryUri.Instance, default);
node = context.NodeFactory.Create(RootFileUri.Instance, default);
}else if(path.IsRootDirectory)
{
node = context.NodeFactory.Create(Vocabularies.File, "");
}else{
var local = UriTools.EscapePathString(path.Value.Value ?? "");
node = context.NodeFactory.Create(Vocabularies.File, local);
Expand All @@ -47,15 +50,15 @@ public async override ValueTask<AnalysisResult> Analyze(PathObject path, Analysi

/// <summary>
/// This class is used to provide a fake URI with the value of
/// <see cref="RootDirectoryUri.Value"/> when .NET would like to change it.
/// <see cref="RootFileUri.Value"/> when .NET would like to change it.
/// </summary>
class RootDirectoryUri : Uri, IIndividualUriFormatter<ValueTuple>
class RootFileUri : Uri, IIndividualUriFormatter<ValueTuple>
{
public const string Value = "file:///./";
public const string Value = "file:///.";

public static readonly RootDirectoryUri Instance = new();
public static readonly RootFileUri Instance = new();

private RootDirectoryUri() : base(Value, UriKind.Absolute)
private RootFileUri() : base(Value, UriKind.Absolute)
{

}
Expand Down
54 changes: 52 additions & 2 deletions SFI/Services/PathObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,61 @@

namespace IS4.SFI.Services
{
/// <summary>
/// Represents a path in any file system.
/// </summary>
/// <param name="Value">The textual value of the path.</param>
public readonly record struct PathObject(StringSegment Value) : IIdentityKey
{
/// <summary>
/// The less specific path contained within this path, if existing.
/// </summary>
/// <remarks>
/// The path is obtained by splitting the value at the first <c>/</c>
/// and retrieving the second segment.
/// </remarks>
public PathObject? Broader {
get {
var slash = Value.IndexOf('/');
if(slash != -1 && slash != Value.Length - 1)
if(slash != -1 && !(slash == 0 && Value.Length == 1))
{
return new(Value.Subsegment(slash + 1));
if(slash == Value.Length - 1)
{
return new(Value.Subsegment(slash));
}else{
return new(Value.Subsegment(slash + 1));
}
}
return null;
}
}

/// <summary>
/// The parent path, as a directory containing this path.
/// </summary>
/// <remarks>
/// The path is obtained by splitting the value at the last <c>/</c>
/// and retrieving the first segment.
/// </remarks>
public PathObject? Parent {
get {
var slash = Value.LastIndexOf('/');
if(slash != -1)
{
if(slash == Value.Length - 1)
{
return new(Value.Subsegment(0, slash));
}else{
return new(Value.Subsegment(0, slash + 1));
}
}
return null;
}
}

/// <summary>
/// The extension indicated by the path, if any.
/// </summary>
public ExtensionObject? Extension {
get {
var dot = Value.LastIndexOf('.');
Expand All @@ -30,8 +72,16 @@ public ExtensionObject? Extension {
}
}

/// <summary>
/// Whether the path is equal to <c>/</c>, indicating the root directory.
/// </summary>
public bool IsRootDirectory => Value.Length == 1 && Value[0] == '/';

/// <summary>
/// Whether the path is equal to the empty string, indicating the root.
/// </summary>
public bool IsRoot => Value.Length == 0;

/// <inheritdoc/>
public override string ToString() => $"/{Value}";

Expand Down

0 comments on commit 9c41353

Please sign in to comment.