Function resolveWindows [src]
This function is like a series of cd statements executed one after another.
It resolves "." and "..", but will not convert relative path to absolute path, use std.fs.Dir.realpath instead.
The result does not have a trailing path separator.
Each drive has its own current working directory.
Path separators are canonicalized to '\' and drives are canonicalized to capital letters.
Note: all usage of this function should be audited due to the existence of symlinks.
Without performing actual syscalls, resolving .. could be incorrect.
This API may break in the future: https://github.com/ziglang/zig/issues/13613
  Prototype
 pub fn resolveWindows(allocator: Allocator, paths: []const []const u8) ![]u8  Parameters
allocator: Allocatorpaths: []const []const u8 Example
 test resolveWindows {
    try testResolveWindows(
        &[_][]const u8{ "Z:\\", "/usr/local", "lib\\zig\\std\\array_list.zig" },
        "Z:\\usr\\local\\lib\\zig\\std\\array_list.zig",
    );
    try testResolveWindows(
        &[_][]const u8{ "z:\\", "usr/local", "lib\\zig" },
        "Z:\\usr\\local\\lib\\zig",
    );
    try testResolveWindows(&[_][]const u8{ "c:\\a\\b\\c", "/hi", "ok" }, "C:\\hi\\ok");
    try testResolveWindows(&[_][]const u8{ "c:/blah\\blah", "d:/games", "c:../a" }, "C:\\blah\\a");
    try testResolveWindows(&[_][]const u8{ "c:/blah\\blah", "d:/games", "C:../a" }, "C:\\blah\\a");
    try testResolveWindows(&[_][]const u8{ "c:/ignore", "d:\\a/b\\c/d", "\\e.exe" }, "D:\\e.exe");
    try testResolveWindows(&[_][]const u8{ "c:/ignore", "c:/some/file" }, "C:\\some\\file");
    try testResolveWindows(&[_][]const u8{ "d:/ignore", "d:some/dir//" }, "D:\\ignore\\some\\dir");
    try testResolveWindows(&[_][]const u8{ "//server/share", "..", "relative\\" }, "\\\\server\\share\\relative");
    try testResolveWindows(&[_][]const u8{ "c:/", "//" }, "C:\\");
    try testResolveWindows(&[_][]const u8{ "c:/", "//dir" }, "C:\\dir");
    try testResolveWindows(&[_][]const u8{ "c:/", "//server/share" }, "\\\\server\\share\\");
    try testResolveWindows(&[_][]const u8{ "c:/", "//server//share" }, "\\\\server\\share\\");
    try testResolveWindows(&[_][]const u8{ "c:/", "///some//dir" }, "C:\\some\\dir");
    try testResolveWindows(&[_][]const u8{ "C:\\foo\\tmp.3\\", "..\\tmp.3\\cycles\\root.js" }, "C:\\foo\\tmp.3\\cycles\\root.js");
    // Keep relative paths relative.
    try testResolveWindows(&[_][]const u8{"a/b"}, "a\\b");
}  Source
 pub fn resolveWindows(allocator: Allocator, paths: []const []const u8) ![]u8 {
    assert(paths.len > 0);
    // determine which disk designator we will result with, if any
    var result_drive_buf = "_:".*;
    var disk_designator: []const u8 = "";
    var drive_kind = WindowsPath.Kind.None;
    var have_abs_path = false;
    var first_index: usize = 0;
    for (paths, 0..) |p, i| {
        const parsed = windowsParsePath(p);
        if (parsed.is_abs) {
            have_abs_path = true;
            first_index = i;
        }
        switch (parsed.kind) {
            .Drive => {
                result_drive_buf[0] = ascii.toUpper(parsed.disk_designator[0]);
                disk_designator = result_drive_buf[0..];
                drive_kind = WindowsPath.Kind.Drive;
            },
            .NetworkShare => {
                disk_designator = parsed.disk_designator;
                drive_kind = WindowsPath.Kind.NetworkShare;
            },
            .None => {},
        }
    }
    // if we will result with a disk designator, loop again to determine
    // which is the last time the disk designator is absolutely specified, if any
    // and count up the max bytes for paths related to this disk designator
    if (drive_kind != WindowsPath.Kind.None) {
        have_abs_path = false;
        first_index = 0;
        var correct_disk_designator = false;
        for (paths, 0..) |p, i| {
            const parsed = windowsParsePath(p);
            if (parsed.kind != WindowsPath.Kind.None) {
                if (parsed.kind == drive_kind) {
                    correct_disk_designator = compareDiskDesignators(drive_kind, disk_designator, parsed.disk_designator);
                } else {
                    continue;
                }
            }
            if (!correct_disk_designator) {
                continue;
            }
            if (parsed.is_abs) {
                first_index = i;
                have_abs_path = true;
            }
        }
    }
    // Allocate result and fill in the disk designator.
    var result = std.array_list.Managed(u8).init(allocator);
    defer result.deinit();
    const disk_designator_len: usize = l: {
        if (!have_abs_path) break :l 0;
        switch (drive_kind) {
            .Drive => {
                try result.appendSlice(disk_designator);
                break :l disk_designator.len;
            },
            .NetworkShare => {
                var it = mem.tokenizeAny(u8, paths[first_index], "/\\");
                const server_name = it.next().?;
                const other_name = it.next().?;
                try result.ensureUnusedCapacity(2 + 1 + server_name.len + other_name.len);
                result.appendSliceAssumeCapacity("\\\\");
                result.appendSliceAssumeCapacity(server_name);
                result.appendAssumeCapacity('\\');
                result.appendSliceAssumeCapacity(other_name);
                break :l result.items.len;
            },
            .None => {
                break :l 1;
            },
        }
    };
    var correct_disk_designator = true;
    var negative_count: usize = 0;
    for (paths[first_index..]) |p| {
        const parsed = windowsParsePath(p);
        if (parsed.kind != .None) {
            if (parsed.kind == drive_kind) {
                const dd = result.items[0..disk_designator_len];
                correct_disk_designator = compareDiskDesignators(drive_kind, dd, parsed.disk_designator);
            } else {
                continue;
            }
        }
        if (!correct_disk_designator) {
            continue;
        }
        var it = mem.tokenizeAny(u8, p[parsed.disk_designator.len..], "/\\");
        while (it.next()) |component| {
            if (mem.eql(u8, component, ".")) {
                continue;
            } else if (mem.eql(u8, component, "..")) {
                if (result.items.len == 0) {
                    negative_count += 1;
                    continue;
                }
                while (true) {
                    if (result.items.len == disk_designator_len) {
                        break;
                    }
                    const end_with_sep = switch (result.items[result.items.len - 1]) {
                        '\\', '/' => true,
                        else => false,
                    };
                    result.items.len -= 1;
                    if (end_with_sep or result.items.len == 0) break;
                }
            } else if (!have_abs_path and result.items.len == 0) {
                try result.appendSlice(component);
            } else {
                try result.ensureUnusedCapacity(1 + component.len);
                result.appendAssumeCapacity('\\');
                result.appendSliceAssumeCapacity(component);
            }
        }
    }
    if (disk_designator_len != 0 and result.items.len == disk_designator_len) {
        try result.append('\\');
        return result.toOwnedSlice();
    }
    if (result.items.len == 0) {
        if (negative_count == 0) {
            return allocator.dupe(u8, ".");
        } else {
            const real_result = try allocator.alloc(u8, 3 * negative_count - 1);
            var count = negative_count - 1;
            var i: usize = 0;
            while (count > 0) : (count -= 1) {
                real_result[i..][0..3].* = "..\\".*;
                i += 3;
            }
            real_result[i..][0..2].* = "..".*;
            return real_result;
        }
    }
    if (negative_count == 0) {
        return result.toOwnedSlice();
    } else {
        const real_result = try allocator.alloc(u8, 3 * negative_count + result.items.len);
        var count = negative_count;
        var i: usize = 0;
        while (count > 0) : (count -= 1) {
            real_result[i..][0..3].* = "..\\".*;
            i += 3;
        }
        @memcpy(real_result[i..][0..result.items.len], result.items);
        return real_result;
    }
}