Feature idea: Directory functions

Not sure if these things are in the scope of what SDL is meant to be for, but here are some file I/O related features I think would be quite useful.

(1) Structure representing the names of files/subdirectories, and a function to produce the structure from a path representing a directory. Or, perhaps a few functions for traversing the names in a directory without actually loading them all at once.

// all names loaded at once style
SDL_Directory* directory = SDL_ExploreDirectory("/folder");
if (!directory) /* error */;
for (int i = 0; i < directory->n_names; i++)
{
    char* path = directory->names[i];
    /* 'path' points to a string in memory SDL allocated for you */
}
SDL_FreeDirectory(directory);

// piece by piece style
SDL_Directory* directory = SDL_ExploreDirectory("/folder"); 
if (!directory) /* error */; 
char* path;
while (SDL_NextFileName(directory,&path))
{
    /* 'path' has been set to point to some string, maybe with the provision you're not supposed to free it */
}
// Maybe no 'FreeDirectory' sort of thing here, NextFileName can clean up the SDL_Directory* automatically right before it returns NULL itself

(2) A few new event types, something like SDL_FILEADD, SDL_FILEREMOVE, SDL_FILEMODIFY, which would convey the file path at which a file has been added, removed, modified. And alongside these new events, a function to tell SDL to “listen” to a directory, maybe recursively, to the directory at a path (or perhaps a single file at a path), so that the events are generated.

SDL_WatchDirectory("/folder",SDL_FALSE/*recursive*/);

// event loop:
SDL_Event event;
while (SDL_PollEvent(&event))
{
    if (event.type == SDL_FILEADD)
    {
        printf("%s was added to %s and is a %s\n",event.change_path,event.watch_path,event.is_file ? "file" : "directory");
        // the watch_path is the path supplied to WatchDirectory, and the change_path is relative to the watch_path such that the path to the changed item can be obtained from concatenating these two pieces
    }
}

When something changes in a directory that is watched by multiple SDL_WatchDirectory, I think it’s best to just produce an event for each ‘watcher’.

// suppose the directory /folder1/folder2 exists and is accessible
SDL_WatchDirectory("/folder1",SDL_TRUE);
SDL_WatchDirectory("/folder1/folder2",SDL_FALSE);
// Suppose the file /folder1/folder2/filename.txt is modified
// Two of SDL_Event with type SDL_FILEMODIFY are generated, for the one change. 
// One for each listener, so one has change_path="folder2/filename.txt" and watch_path="/folder1/", and the other has change_path="filename.txt" and watch_path="/folder1/folder2/"

In order to be able to stop watching directories, it may make sense for SDL_WatchDirectory to return something, perhaps SDL_DirectoryWatcher*, that can be passed to a function named something like SDL_ForgetDirectory(SDL_DirectoryWatcher*). Or, maybe it would suffice for the ‘cancelling’ function to just take the path to stop generating events for, though this might cause issues if two parts of an application are watching the same thing, and only one of them wishes to stop seeing events.
Considering that, it may even make sense to supply a userdata pointer to SDL_WatchDirectory that is accessible in the SDL_Event later.

These directory exploring & watching features would be quite handy. The former would help a lot in making custom file saving/loading GUIs for games with built-in level editors, and for games that want to do something with all files in a certain directory, for example "when my game starts, I want to run every script file ending in .lua that resides in the local path ‘content/scripts’ ". The latter is a little bit harder to find justification for in the context of just games, as the use case I personally have in mind is for server software (I want to be able to listen to changes in files that the server has cached, and update the cache accordingly to not serve stale files), and for a developer-oriented level editor (to detect and show new image assets that can be used, or to recalculate things when a file describing object information is changed, without having to reload the editor).

1 Like