From c6b1c8d07a3f47a49c5d155544578be03fda9088 Mon Sep 17 00:00:00 2001 From: Ben <89769190+benwalksaway@users.noreply.github.com> Date: Wed, 8 Jun 2022 20:26:24 +0200 Subject: [PATCH] os: add windows_volume function (#14721) --- vlib/os/filepath.v | 41 +++++++++++++++++--------------------- vlib/os/filepath_test.v | 17 ++++++++++++++++ vlib/os/filepath_windows.v | 18 +++++++++++++++++ 3 files changed, 53 insertions(+), 23 deletions(-) create mode 100644 vlib/os/filepath_windows.v diff --git a/vlib/os/filepath.v b/vlib/os/filepath.v index 6111e7f798..abb4205293 100644 --- a/vlib/os/filepath.v +++ b/vlib/os/filepath.v @@ -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 diff --git a/vlib/os/filepath_test.v b/vlib/os/filepath_test.v index bd5c832185..8ef370a31a 100644 --- a/vlib/os/filepath_test.v +++ b/vlib/os/filepath_test.v @@ -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('/') == '' + } +} diff --git a/vlib/os/filepath_windows.v b/vlib/os/filepath_windows.v new file mode 100644 index 0000000000..35f32123cd --- /dev/null +++ b/vlib/os/filepath_windows.v @@ -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] +}