Add new path API for os2

This commit is contained in:
Feoramund
2025-03-21 19:14:15 -04:00
parent d1d86234aa
commit abe0c30837
4 changed files with 541 additions and 20 deletions
+94 -2
View File
@@ -1,8 +1,10 @@
#+private
package os2
import win32 "core:sys/windows"
import "base:intrinsics"
import "base:runtime"
import "core:strings"
import win32 "core:sys/windows"
_Path_Separator :: '\\'
_Path_Separator_String :: "\\"
@@ -217,7 +219,7 @@ _fix_long_path_internal :: proc(path: string) -> string {
return path
}
if !_is_abs(path) { // relative path
if !_is_absolute_path(path) { // relative path
return path
}
@@ -257,3 +259,93 @@ _fix_long_path_internal :: proc(path: string) -> string {
return string(path_buf[:w])
}
_are_paths_identical :: strings.equal_fold
_clean_path_handle_start :: proc(path: string, buffer: []u8) -> (rooted: bool, start: int) {
// Preserve rooted paths.
start = _volume_name_len(path)
if start > 0 {
rooted = true
if len(path) > start && _is_path_separator(path[start]) {
// Take `C:` to `C:\`.
start += 1
}
intrinsics.mem_copy_non_overlapping(raw_data(buffer), raw_data(path), start)
}
return
}
_is_absolute_path :: proc(path: string) -> bool {
if _is_reserved_name(path) {
return true
}
l := _volume_name_len(path)
if l == 0 {
return false
}
path := path
path = path[l:]
if path == "" {
return false
}
return _is_path_separator(path[0])
}
_get_absolute_path :: proc(path: string, allocator: runtime.Allocator) -> (absolute_path: string, err: Error) {
rel := path
if rel == "" {
rel = "."
}
TEMP_ALLOCATOR_GUARD()
rel_utf16 := win32.utf8_to_utf16(rel, temp_allocator())
n := win32.GetFullPathNameW(raw_data(rel_utf16), 0, nil, nil)
if n == 0 {
return "", Platform_Error(win32.GetLastError())
}
buf := make([]u16, n, temp_allocator()) or_return
n = win32.GetFullPathNameW(raw_data(rel_utf16), u32(n), raw_data(buf), nil)
if n == 0 {
return "", Platform_Error(win32.GetLastError())
}
return win32.utf16_to_utf8(buf, allocator)
}
_get_relative_path_handle_start :: proc(base, target: string) -> bool {
base_root := base[:_volume_name_len(base)]
target_root := target[:_volume_name_len(target)]
return strings.equal_fold(base_root, target_root)
}
_get_common_path_len :: proc(base, target: string) -> int {
i := 0
end := min(len(base), len(target))
for j in 0..=end {
if j == end || _is_path_separator(base[j]) {
if strings.equal_fold(base[i:j], target[i:j]) {
i = j
} else {
break
}
}
}
return i
}
_split_path :: proc(path: string) -> (dir, file: string) {
vol_len := _volume_name_len(path)
i := len(path) - 1
for i >= vol_len && !_is_path_separator(path[i]) {
i -= 1
}
if i == vol_len {
return path[:i+1], path[i+1:]
} else if i > vol_len {
return path[:i], path[i+1:]
}
return "", path
}