StackDir

A directory seamlessly working on a stack of multiple directories.

Directories can be mounted using the mount() method.

When looking for a file or directory in a StackDir, the last directory is searched first, then the second last, and so on. This means that directories mounted later override those mounted before.

Constructors

this
this(string name)

Construct a StackDir.

Members

Functions

mount
void mount(VFSDir dir)

Mount a directory.

Inherited Members

From VFSDir

name
string name [@property getter]

Get the name of this directory.

path
string path [@property getter]

Get full path of this directory in the VFS.

writable
bool writable [@property getter]

Is it possible to write to the directory?

exists
bool exists [@property getter]

Does the directory exist?

file
VFSFile file(string path)

Get file with specified _path in the directory.

dir
VFSDir dir(string path)

Get a subdirectory with specified _path in the directory.

files
VFSFiles files(Flag!"deep" deep = No.deep, string glob = null)

Get a range of files in the directory.

dirs
VFSDirs dirs(Flag!"deep" deep = No.deep, string glob = null)

Get a range of subdirectories.

create
void create()

Create the directory if it does not exist (otherwise do nothing).

remove
void remove()

Remove the directory if it exists (otherwise do nothing).

dirsRange
VFSDirs dirsRange(VFSDirs.Items dirs)

Construct a range from a set of directories.

filesRange
VFSFiles filesRange(VFSFiles.Items files)

Construct a range from a set of _files.

composePath
string composePath(const VFSDir child)

Compose path for a _child directory. Used e.g. to allow StackDir to set children's paths.

create_
void create_()

Implementation of create(). Caller contract guarantees that the directory is writable.

copyWithoutParent
VFSDir copyWithoutParent()

Return a copy of this VFSDir without a parent. Used for mounting.

getCopyWithoutParent
VFSDir getCopyWithoutParent(VFSDir dir)

Access for derived classes to call copyWithoutParent() of other instances.

Examples

We have a directory called data with the following contents:

1 shaders:
2    font.frag 
3    font.vert 
4 logs:
5    (empty)
6 main.cfg

and a directory called user_data with the following contents:

1 shaders: 
2     font.frag
3 logs:
4     (empty)
5 custom.cfg

the following code will work as specified in the comments:

1 VFSDir data, user_data; //initialized somewhere before
2 
3 auto stack = new StackDir("stack");
4 stack.mount(data);
5 stack.mount(user_data);
6 
7 //This will access user_data/shaders/font.frag
8 auto frag = stack.file("shaders/font.frag");
9 //This will access data/shaders/font.vert
10 auto vert = stack.file("shaders/font.vert");
11 //This will return a StackDir (as VFSDir) with "data/logs" and "user_data/logs"
12 //mounted, in that order:
13 auto logs = stack.dir("logs");

Accessing a file in a StackDir will actually return a StackFile, which decides which file to access on read, write and other operations. The StackFile is a stack of all files that map to the same path in the StackDir in the same order as StackDir's mounted directories.

For example, when reading or determining file size, the directories in the stack will be searched from newest to oldest and the first file found will be used.

When writing, the file in the newest writable directory will be written to.

In some cases, it might be required to access a particular directory in the stack. E.g. a game might have multiple packages stacked on top of each other, but sometimes default, non-overridden version of a file could be needed. This can be done using the :: separator.

In the context of the previous example:

//This will access data/shaders/font.frag even though user_data/shaders/font.frag exists
auto default_frag = stack.file("data::shaders/font.frag");

StackDir is considered writable when any directory in the stack is writable. Similarly, it exists when any directory in the stack exists.

When we have a StackDir that does not exist and we create() it, the newest directory that is writable will be created. (This can happen when getting a nonexistent subdirectory of a StackDir.)

Meta