os: add windows_volume function (#14721)

Ben 2022-06-08 20:26:24 +02:00 committed by Chewing_Bever
parent 10b9dcb06e
commit d65fb03cab
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
3 changed files with 53 additions and 23 deletions

View File

@ -8,13 +8,14 @@ import strings.textscanner
// therefore results may be different for certain operating systems.
const (
fslash = `/`
bslash = `\\`
dot = `.`
qmark = `?`
dot_dot = '..'
empty_str = ''
dot_str = '.'
fslash = `/`
bslash = `\\`
dot = `.`
qmark = `?`
fslash_str = '/'
dot_dot = '..'
empty_str = ''
dot_str = '.'
)
// is_abs_path returns `true` if the given `path` is absolute.
@ -62,8 +63,13 @@ pub fn norm_path(path string) string {
return os.dot_str
}
rooted := is_abs_path(path)
volume := get_volume(path)
volume_len := volume.len
// get the volume name from the path
// if the current operating system is Windows
volume_len := win_volume_len(path)
mut volume := path[..volume_len]
if volume_len != 0 && volume.contains(os.fslash_str) {
volume = volume.replace(os.fslash_str, path_separator)
}
cpath := clean_path(path[volume_len..])
if cpath.len == 0 && volume_len == 0 {
return os.dot_str
@ -217,6 +223,9 @@ fn clean_path(path string) string {
// win_volume_len returns the length of the
// Windows volume/drive from the given `path`.
fn win_volume_len(path string) int {
$if !windows {
return 0
}
plen := path.len
if plen < 2 {
return 0
@ -244,20 +253,6 @@ fn win_volume_len(path string) int {
return 0
}
fn get_volume(path string) string {
$if !windows {
return os.empty_str
}
volume := path[..win_volume_len(path)]
if volume.len == 0 {
return os.empty_str
}
if volume[0] == os.fslash {
return volume.replace('/', '\\')
}
return volume
}
fn is_slash(b u8) bool {
$if windows {
return b == os.bslash || b == os.fslash

View File

@ -152,3 +152,20 @@ fn test_existing_path() {
assert existing_path('$wd//././/.//') or { '' } == '$wd//././/.//'
assert existing_path('$wd//././/.//oh') or { '' } == '$wd//././/.//'
}
fn test_windows_volume() {
$if windows {
assert windows_volume('C:/path\\to/file.v') == 'C:'
assert windows_volume('D:\\.\\') == 'D:'
assert windows_volume('G:') == 'G:'
assert windows_volume('G') == ''
assert windows_volume(r'\\Host\share\files\file.v') == r'\\Host\share'
assert windows_volume('\\\\Host\\') == ''
assert windows_volume(r'\\.\BootPartition2\\files\.\\') == r'\\.\BootPartition2'
assert windows_volume(r'\/.\BootPartition2\\files\.\\') == r'\/.\BootPartition2'
assert windows_volume(r'\\\.\BootPartition2\\files\.\\') == ''
assert windows_volume('') == ''
assert windows_volume('\\') == ''
assert windows_volume('/') == ''
}
}

View File

@ -0,0 +1,18 @@
module os
// windows_volume returns the volume name from the given `path` on a Windows system.
// An empty string is returned if no Windows volume is present.
// NOTE: An error is returned if the current operating system is not Windows.
// Examples (on a Windows system):
// ```v
// assert os.windows_volume(r'C:\path\to\file.v') == 'C:'
// assert os.windows_volume('D:') == 'D:'
// assert os.windows_volume(r'\\Host\share\files\file.v') == r'\\Host\share'
// ```
pub fn windows_volume(path string) string {
volume_len := win_volume_len(path)
if volume_len == 0 {
return empty_str
}
return path[..volume_len]
}