Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 40 additions & 27 deletions src/path.cr
Original file line number Diff line number Diff line change
Expand Up @@ -1122,7 +1122,10 @@ struct Path
#
# NOTE: Drives are only available for Windows paths. It can either be a drive letter (`C:`) or a UNC share (`\\host\share`).
def drive : Path?
if drive = drive_and_root[0]
drive_end, _ = drive_and_root_indices

if drive_end
drive = @name.byte_slice(0, drive_end)
new_instance drive
end
end
Expand All @@ -1138,7 +1141,11 @@ struct Path
# Path.windows("\\\\host\\share\\folder").root # => Path.windows("\\")
# ```
def root : Path?
if root = drive_and_root[1]
drive_end, root_end = drive_and_root_indices

if root_end
root_start = drive_end || 0
root = @name.byte_slice(root_start, root_end - root_start)
new_instance root
end
end
Expand All @@ -1152,47 +1159,49 @@ struct Path
# Path.windows("\\\\host\\share\\folder").anchor # => Path.windows("\\\\host\\share\\")
# ```
def anchor : Path?
drive, root = drive_and_root
drive_end, root_end = drive_and_root_indices
anchor_end = root_end || drive_end

if root
if drive
new_instance({drive, root}.join)
else
new_instance(root)
end
elsif drive
new_instance drive
if anchor_end
new_instance(@name.byte_slice(0, anchor_end))
end
end

# Returns a tuple of `#drive` and `#root` as strings.
def drive_and_root : {String?, String?}
drive_end, root_end = drive_and_root_indices

if drive_end
drive = @name.byte_slice(0, drive_end)
end

if root_end
root_start = drive_end || 0
root = @name.byte_slice(root_start, root_end - root_start)
end

{drive, root}
end

private def drive_and_root_indices : {Int32?, Int32?}
if windows?
if windows_drive?
drive = @name.byte_slice(0, 2)
if separators.includes?(@name.byte_at?(2).try(&.chr))
return drive, @name.byte_slice(2, 1)
{2, 3}
else
return drive, nil
{2, nil}
end
elsif unc_share = unc_share?
share_end, root_end = unc_share
if share_end == root_end
root = nil
else
root = @name.byte_slice(share_end, root_end - share_end)
end

return @name.byte_slice(0, share_end), root
unc_share
elsif starts_with_separator?
return nil, @name.byte_slice(0, 1)
{nil, 1}
else
return nil, nil
{nil, nil}
end
elsif absolute? # posix
return nil, "/"
{nil, 1}
else
return nil, nil
{nil, nil}
end
end

Expand Down Expand Up @@ -1261,7 +1270,11 @@ struct Path
break unless separators.includes?(char)
end

return share_end, reader.pos
unless reader.pos == share_end
root_end = reader.pos
end

return share_end, root_end
end

# Returns `true` if this path is absolute.
Expand Down
Loading