use an ArrayList in uri.pathRelative

This commit is contained in:
Techatrix 2022-09-22 20:06:31 +02:00
parent adb012001f
commit 87bfa683bd

View File

@ -51,43 +51,37 @@ pub fn fromPath(allocator: std.mem.Allocator, path: []const u8) ![]const u8 {
/// Move along `rel` from `base` with a single allocation. /// Move along `rel` from `base` with a single allocation.
/// `base` is a URI of a folder, `rel` is a raw relative path. /// `base` is a URI of a folder, `rel` is a raw relative path.
pub fn pathRelative(allocator: std.mem.Allocator, base: []const u8, rel: []const u8) ![]const u8 { pub fn pathRelative(allocator: std.mem.Allocator, base: []const u8, rel: []const u8) error{ OutOfMemory, UriBadScheme }![]const u8 {
const max_size = base.len + rel.len * 3 + 1; const max_size = base.len + rel.len * 3 + 1;
var result = try allocator.alloc(u8, max_size); var result = try std.ArrayListUnmanaged(u8).initCapacity(allocator, max_size);
errdefer allocator.free(result); errdefer result.deinit(allocator);
result.appendSliceAssumeCapacity(base);
std.mem.copy(u8, result, base);
var result_index: usize = base.len;
var it = std.mem.tokenize(u8, rel, "/"); var it = std.mem.tokenize(u8, rel, "/");
while (it.next()) |component| { while (it.next()) |component| {
if (std.mem.eql(u8, component, ".")) { if (std.mem.eql(u8, component, ".")) {
continue; continue;
} else if (std.mem.eql(u8, component, "..")) { } else if (std.mem.eql(u8, component, "..")) {
while (true) { while (true) {
if (result_index == 0) const char = result.popOrNull() orelse return error.UriBadScheme;
return error.UriBadScheme; if (char == '/') break;
result_index -= 1;
if (result[result_index] == '/')
break;
} }
} else { } else {
result[result_index] = '/'; result.appendAssumeCapacity('/');
result_index += 1;
for (component) |char| { for (component) |char| {
if (std.mem.indexOfScalar(u8, reserved_chars, char)) |reserved| { if (std.mem.indexOfScalar(u8, reserved_chars, char)) |reserved| {
const escape = &reserved_escapes[reserved]; const escape = &reserved_escapes[reserved];
std.mem.copy(u8, result[result_index..], escape); result.appendSliceAssumeCapacity(escape);
result_index += escape.len;
} else { } else {
result[result_index] = char; result.appendAssumeCapacity(char);
result_index += 1;
} }
} }
} }
} }
return allocator.resize(result, result_index) orelse error.FailedResize; return result.toOwnedSlice(allocator);
} }
// Original code: https://github.com/andersfr/zig-lsp/blob/master/uri.zig // Original code: https://github.com/andersfr/zig-lsp/blob/master/uri.zig