path +linux +x86_64

The path module provides utilities for working with filesystem paths.

Note that Hare expects paths to be valid UTF-8 strings. If you require the use of non-UTF-8 paths (ideally for only as long as it takes to delete or rename those files), see the low-level functions available from rt.

Use of the buffer type is recommended for efficient and consistent manipulation of filesystem paths.

let buf = path::init();
path::add(&buf, "/", "foo", "bar", "baz.txt");
fmt::println(path::string(&buf))!; // "/foo/bar/baz.txt"

path::add(&buf, "../.././hello.txt");
fmt::println(path::string(&buf))!; // "/foo/hello.txt"

The buffer object includes an array of length PATH_MAX, which can be somewhat large; on Linux it's 4096 bytes. You can allocate this on the stack in most cases, but you may prefer to allocate it elsewhere depending on your needs.

// Stack allocated
let buf = path::init();

// Statically allocated
static let buf = path::buffer { ... };
path::reset(&buf);

// Heap allocated
let buf = alloc(path::init());
defer free(buf);

Index

Types

// Undocumented types:
type buffer;
type iflags;
type iterator;

Constants

const PATHSEP: u8;
const PATH_MAX: size;

Functions

fn abs(str) bool;
fn add(*buffer, str...) (str | errors::overflow);
fn allocate(*buffer) str;
fn basename((str | *buffer)) const str;
fn dirname((str | *buffer)) const str;
fn extension((str | *buffer)) (str, str);
fn init() buffer;
fn iter((str | *buffer)) iterator;
fn join(str...) str;
fn next(*iterator) (str | void);
fn reset(*buffer) void;
fn set(*buffer, str...) (str | errors::overflow);
fn string(*buffer) str;

Types

type buffer[link]

Show undocumented member
type buffer = struct {
	buf: [PATH_MAX]u8,
	end: size,
};

type iflags[link]

Show undocumented member
type iflags = enum uint {
	NONE = 0,
	ABSOLUTE = 1 << 0,

};

type iterator[link]

Show undocumented member
type iterator = struct {
	tok: bytes::tokenizer,
	flags: iflags,
};

Constants

def PATHSEP[link]

def PATHSEP: u8;

Platform-specific path separator byte.

def PATH_MAX[link]

def PATH_MAX: size;

Maximum length of a file path for this platform.

Functions

fn abs[link]

fn abs(path: str) bool;

Returns true if a path is an absolute path.

fn add[link]

fn add(buf: *buffer, items: str...) (str | errors::overflow);

Joins several path elements together and copies them into a path buffer. Returns the new string value of the path.

fn allocate[link]

fn allocate(buf: *buffer) str;

Like string but the return value is copied to the heap and must be freed by the caller.

fn basename[link]

fn basename(path: (str | *buffer)) const str;

Returns the final component of a given path. For a path to a file name, this returns the file name. For a path to a directory, this returns the directory name. If the path consists solely of the target's path separator, a string of the path is returned unmodified. If the path is empty, "." is returned. The return value is either borrowed from the input or statically allocated; use strings::dup to extend its lifetime or modify it.

fn dirname[link]

fn dirname(path: (str | *buffer)) const str;

Returns the directory name for a given path. For a path to a file name, this returns the directory in which that file resides. For a path to a directory, this returns the path to its parent directory. If the path consists solely of the target's path separator, a string to the path is returned unmodified. If the path is empty, "." is returned. The return value is either borrowed from the input or statically allocated; use strings::dup to extend its lifetime or modify it.

fn extension[link]

fn extension(p: (str | *buffer)) (str, str);

Returns the file name and extension for a path. The return value is borrowed from the input, see strings::dup to extend its lifetime.

The extension includes the '.' character.

extension("foo/example") => ("example", "")
extension("foo/example.txt") => ("example", ".txt")
extension("foo/example.tar.gz") => ("example", ".tar.gz")

fn init[link]

fn init() buffer;

Initializes a new path buffer.

fn iter[link]

fn iter(path: (str | *buffer)) iterator;

Returns an iterator which yields each component of a path. If the path is absolute, the first component will be the root path (e.g. "/").

fn join[link]

fn join(items: str...) str;

Joins a list of path components together, normalizes it, and returns the resulting string. The caller must free the return value. If the resulting path would exceed PATH_MAX, the program aborts.

fn next[link]

fn next(iter: *iterator) (str | void);

Returns the next path component from an iterator, or void if none remain.

fn reset[link]

fn reset(buf: *buffer) void;

Resets a path buffer to its initial state.

fn set[link]

fn set(buf: *buffer, items: str...) (str | errors::overflow);

Sets the value of a path buffer to a list of components, overwriting any previous value. Returns the new string value of the path.

fn string[link]

fn string(buf: *buffer) str;

Returns the current path stored in this buffer. The path will always be normalized, which is to say that it will not include any of the following:

- Redundant ".." components - Redundant path separators - Any "." components, except in the case of "."

Assuming that PATHSEP is '/', "/usr//bin/../bin/./hare" becomes "/usr/bin/hare" and "../../foo/bar" is unchanged. The path will only end in a slash if the last item which was added ended in PATHSEP, like so:

let buf = path::init();
path::set(&buf, "foo", "bar")!;
assert(path::string(&buf) == "foo/bar");

path::set(&buf, "foo", "bar/")!;
assert(path::string(&buf) == "foo/bar/");

path::set(&buf, "foo", "bar", "/")!;
assert(path::string(&buf) == "foo/bar/");

The return value is borrowed from the buffer. Use allocate to extend the lifetime of the string.