mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-06 06:38:20 +00:00
Fix #6279
If the replacement rune was multi-byte, `os.replace_path_separators` would silently fail to replace anything. Now it properly handles non-ASCII separator. Additionally added a fast path for when all runes in the input path as well as the replacement separator are simple ASCII. Test added.
This commit is contained in:
@@ -29,22 +29,39 @@ with the `new_sep` rune.
|
||||
*Allocates Using Provided Allocator*
|
||||
*/
|
||||
replace_path_separators :: proc(path: string, new_sep: rune, allocator: runtime.Allocator) -> (new_path: string, err: Error) {
|
||||
buf := make([]u8, len(path), allocator) or_return
|
||||
length := len(path)
|
||||
rep_b, rep_w := utf8.encode_rune(new_sep)
|
||||
|
||||
byte_oriented := rep_w == 1
|
||||
|
||||
i: int
|
||||
for r in path {
|
||||
replacement := r
|
||||
if r == '/' || r == '\\' {
|
||||
replacement = new_sep
|
||||
length += rep_w - 1
|
||||
}
|
||||
if r > rune(0x7f) {
|
||||
byte_oriented = false
|
||||
}
|
||||
}
|
||||
|
||||
if replacement <= rune(0x7F) {
|
||||
buf[i] = u8(replacement)
|
||||
i += 1
|
||||
} else {
|
||||
b, w := utf8.encode_rune(r)
|
||||
copy(buf[i:], b[:w])
|
||||
i += w
|
||||
buf := make([]u8, length, allocator) or_return
|
||||
|
||||
if byte_oriented {
|
||||
// Neither replacement rune or any other rune in the path takes up more than 1 byte
|
||||
str := transmute([]byte)path
|
||||
#no_bounds_check for b, i in str {
|
||||
buf[i] = u8(new_sep) if b == '/' || b == '\\' else b
|
||||
}
|
||||
} else {
|
||||
i: int
|
||||
for r in path {
|
||||
if r == '/' || r == '\\' {
|
||||
copy(buf[i:], rep_b[:rep_w])
|
||||
i += rep_w
|
||||
} else {
|
||||
r_b, r_w := utf8.encode_rune(r)
|
||||
copy(buf[i:], r_b[:r_w])
|
||||
i += r_w
|
||||
}
|
||||
}
|
||||
}
|
||||
return string(buf), nil
|
||||
|
||||
@@ -99,6 +99,17 @@ test_clean_path :: proc(t: ^testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
replace_path_separators :: proc(t: ^testing.T) {
|
||||
P :: "W:/Odin/core/os/path.odin"
|
||||
|
||||
p1, _ := os.replace_path_separators(P, '😀', context.temp_allocator)
|
||||
testing.expect_value(t, p1, "W:😀Odin😀core😀os😀path.odin")
|
||||
|
||||
p2, _ := os.replace_path_separators(P, '|', context.temp_allocator)
|
||||
testing.expect_value(t, p2, "W:|Odin|core|os|path.odin")
|
||||
}
|
||||
|
||||
@(test)
|
||||
test_is_absolute_path :: proc(t: ^testing.T) {
|
||||
when ODIN_OS == .Windows {
|
||||
|
||||
Reference in New Issue
Block a user