Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

resolvePath

Similar to Dir.path.resolve, but converts to a cwd-relative path, or, if that would start with a relative up-dir (".."), an absolute path based on the cwd. Also, the cwd returns the empty string ("") instead of ".".

zig.resolvePath
pub fn resolvePath(
    gpa: Allocator,
    /// The return value of `getResolvedCwd`.
    /// Passed as an argument to avoid pointlessly repeating the call.
    cwd_resolved: []const u8,
    paths: []const []const u8,
) Allocator.Error![]u8

File

lib/std/zig.zig:1543

Code

pub fn resolvePath(
    gpa: Allocator,
    /// The return value of `getResolvedCwd`.
    /// Passed as an argument to avoid pointlessly repeating the call.
    cwd_resolved: []const u8,
    paths: []const []const u8,
) Allocator.Error![]u8 {
    if (builtin.target.os.tag == .wasi) {
        assert(mem.eql(u8, cwd_resolved, ""));
        const res = try Dir.path.resolve(gpa, paths);
        if (mem.eql(u8, res, ".")) {
            gpa.free(res);
            return "";
        }
        return res;
    }

    // Heuristic for a fast path: if no component is absolute and ".." never appears, we just need to resolve `paths`.
    for (paths) |p| {
        if (Dir.path.isAbsolute(p)) break; // absolute path
        if (mem.indexOf(u8, p, "..") != null) break; // may contain up-dir
    } else {
        // no absolute path, no "..".
        const res = try Dir.path.resolve(gpa, paths);
        if (mem.eql(u8, res, ".")) {
            gpa.free(res);
            return "";
        }
        assert(!Dir.path.isAbsolute(res));
        assert(!isUpDir(res));
        return res;
    }

    // The fast path failed; resolve the whole thing.
    // Optimization: `paths` often has just one element.
    const path_resolved = switch (paths.len) {
        0 => unreachable,
        1 => try Dir.path.resolve(gpa, &.{ cwd_resolved, paths[0] }),
        else => r: {
            const all_paths = try gpa.alloc([]const u8, paths.len + 1);
            defer gpa.free(all_paths);
            all_paths[0] = cwd_resolved;
            @memcpy(all_paths[1..], paths);
            break :r try Dir.path.resolve(gpa, all_paths);
        },
    };
    errdefer gpa.free(path_resolved);

    assert(Dir.path.isAbsolute(path_resolved));
    assert(Dir.path.isAbsolute(cwd_resolved));

    if (!mem.startsWith(u8, path_resolved, cwd_resolved)) return path_resolved; // not in cwd
    if (path_resolved.len == cwd_resolved.len) {
        // equal to cwd
        gpa.free(path_resolved);
        return "";
    }
    if (path_resolved[cwd_resolved.len] != Dir.path.sep) return path_resolved; // not in cwd (last component differs)

    // in cwd; extract sub path
    const sub_path = try gpa.dupe(u8, path_resolved[cwd_resolved.len + 1 ..]);
    gpa.free(path_resolved);
    return sub_path;
}