DOCUMENTATION

File System
(ply-system.h)

Plywood provides a portable file system API that works consistently across Windows and POSIX platforms. All paths arguments are treated as UTF-8 strings.

FileSystem

The FileSystem class contains static methods for file and directory operations.

static FSResult FileSystem::lastResult()

Returns the result code from the most recent file system operation.

static Array<DirectoryEntry> FileSystem::listDir(StringView path)

Returns an array of directory entries for the given path. Each entry contains the name, size, and type of a file or subdirectory.

static FSResult FileSystem::makeDir(StringView path)

Creates a single directory. The parent directory must already exist.

static Path_t FileSystem::pathFormat()

Returns the native path format for the current platform (Windows or POSIX).

static String FileSystem::getWorkingDirectory()

Returns the current working directory as an absolute path.

static FSResult FileSystem::setWorkingDirectory(StringView path)

Changes the current working directory.

static ExistsResult FileSystem::exists(StringView path)

Checks if a file or directory exists at the given path.

static Owned<Pipe> FileSystem::openPipeForRead(StringView path)

Opens a file for reading and returns a pipe. Returns null if the file doesn't exist.

static Owned<Pipe> FileSystem::openPipeForWrite(StringView path)

Opens a file for writing and returns a pipe. Creates the file if it doesn't exist.

static FSResult FileSystem::moveFile(StringView srcPath, StringView dstPath)

Moves or renames a file.

static FSResult FileSystem::deleteFile(StringView path)

Deletes a file. Does not delete directories.

static FSResult FileSystem::removeDirTree(StringView dirPath)

Recursively deletes a directory and all its contents.

static DirectoryEntry FileSystem::getFileInfo(StringView path)

Returns information about a file or directory.

static FSResult FileSystem::copyFile(StringView srcPath, StringView dstPath)

Copies a file to a new location.

static bool FileSystem::isDir(StringView path)

Returns true if the path is a directory.

static DirectoryWalker FileSystem::walk(StringView top)

Returns an iterator for recursively walking a directory tree.

static FSResult FileSystem::makeDirs(StringView path)

Creates a directory and all necessary parent directories.

static Stream FileSystem::openBinaryForRead(StringView path)

Opens a file for binary reading and returns a buffered stream.

static Stream FileSystem::openBinaryForWrite(StringView path)

Opens a file for binary writing and returns a buffered stream.

static Stream FileSystem::openTextForRead(StringView path, const TextFormat& format)

Opens a file for text reading with the specified encoding.

static Stream FileSystem::openTextForReadAutodetect(StringView path, TextFormat* outFormat)

Opens a file for text reading, automatically detecting the encoding from byte-order marks.

static Stream FileSystem::openTextForWrite(StringView path, const TextFormat& format)

Opens a file for text writing with the specified encoding.

static String FileSystem::loadBinary(StringView path)

Loads an entire file into memory as raw bytes.

static String FileSystem::loadText(StringView path, const TextFormat& format)

Loads an entire text file into memory, converting to UTF-8.

static String FileSystem::loadTextAutodetect(StringView path, TextFormat* outFormat)

Loads an entire text file, auto-detecting the encoding.

static FSResult FileSystem::saveBinary(StringView path, StringView contents)

Writes raw bytes to a file, replacing any existing contents.

static FSResult FileSystem::saveText(StringView path, StringView strContents, const TextFormat& format)

Writes text to a file with the specified encoding.

TextFormat

TextFormat describes the encoding and line-ending style of a text file. Common formats include UTF-8, UTF-16 (big and little endian), and various legacy encodings.

Manipulating Paths

These functions help you parse and construct file paths in a platform-independent way.

char getPathSeparator()

Returns the native path separator character: '/' on POSIX, '\\' on Windows.

bool isPathSeparator(char c)

Returns true if c is '/'. Also matches '\' on Windows.

StringView getDriveLetter(StringView path)

Returns the drive letter prefix (e.g., "C:") from a Windows path, or an empty view on POSIX.

bool isAbsolutePath(StringView path)

Returns true if the path is absolute (starts with / on POSIX or a drive letter on Windows).

bool isRelativePath(StringView path)

Returns true if the path is relative.

String makeAbsolutePath(StringView path)

Converts a relative path to an absolute path using the current working directory.

String makeRelativePath(StringView ancestor, StringView descendant)

Returns descendant as a path relative to ancestor.

SplitPath splitPath(StringView path)

Splits a path into directory and filename components.

SplitExtension splitFileExtension(StringView path)

Splits a filename into base name and extension.

Array<StringView> splitPathFull(StringView path)

Splits a path into all of its individual components.

String joinPath(StringViews&& pathComponentArgs)

Joins path components with the native separator.

bool matchGlobPattern(StringView str, StringView pattern, GlobOptions options)

Returns true if str is matched by a single-component glob pattern. Recognizes *, ?, bracket expressions such as [abc], ranges such as [a-z], inverted bracket expressions such as [!abc], POSIX character classes such as [[:digit:]], and backslash escapes.

bool matchGitIgnorePattern(StringView relativePath, bool isDir, StringView pattern)

Returns true if relativePath is ignored by one .gitignore-style pattern.

String fullPath = Path::joinPath("home", "user", "documents", "file.txt");
// On POSIX: "home/user/documents/file.txt"
// On Windows: "home\\user\\documents\\file.txt"

auto [dir, file] = Path::splitPath("/home/user/test.cpp");
// The directory is "/home/user" and the file is "test.cpp".

bool ignored = matchGitIgnorePattern("build/output.o", false, "build/");
// The path is ignored.

DirectoryWatcher

DirectoryWatcher monitors a directory tree for file and directory changes, invoking a callback whenever modifications are detected. This is useful for applications that need to react to file changes in real-time, such as live-reload servers or file synchronization tools.

When mustRecurse is false, the path refers to a specific file that changed.

DirectoryWatcher is only supported on Windows and macOS and is not enabled by default. To enable it, define PLY_WITH_DIRECTORY_WATCHER in your project settings. If enabled on macOS, you must also link with the CoreServices framework.

DirectoryWatcher::DirectoryWatcher()

Default constructor. Creates an inactive watcher. Call start() to begin watching.

DirectoryWatcher::DirectoryWatcher(StringView root, Functor<void(StringView path, bool mustRecurse)>&& callback)

Constructs and immediately starts watching the directory at root.

void DirectoryWatcher::start(StringView root, Functor<void(StringView path, bool mustRecurse)>&& callback)

Begins watching the directory tree rooted at root. The callback will be invoked from a background thread whenever changes are detected. The watcher must not already be running.

void DirectoryWatcher::stop()

Stops the background watcher thread and waits for it to finish. After calling stop(), you may call start() again with a new root and callback. The destructor calls stop() automatically.

// Watch a directory and log changes.
DirectoryWatcher watcher;
watcher.start("/path/to/watch", [](StringView path, bool mustRecurse) {
    if (mustRecurse) {
        // Too many changes or directory modified; rescan this path.
        puts(String::format("Rescan needed: {}", path).bytes);
    } else {
        // Single file changed.
        puts(String::format("File changed: {}", path).bytes);
    }
});

// ... do other work ...

// Stop watching (also happens automatically in destructor).
watcher.stop();