Final Platform Layer 0.9.8-beta
Loading...
Searching...
No Matches
Working with Paths/Files

Path constants

FPL provides a couple of path constants you can use, if needed:

Name Description
FPL_MAX_PATH_LENGTH Defines the maximum length of any path
FPL_MAX_FILENAME_LENGTH Defines the maximum length of a single filename without path
FPL_PATH_SEPARATOR Defines the path separator character
FPL_FILE_EXT_SEPARATOR Defines the file extension separator character
Note
All length constants include the null-terminator character as well, so you don't have to add one to the length when using!

Utilities

Combining paths

Use fplPathCombine() to combine multiple parts of a path to build one single path from it.
Unfortunately, this function requires you to pass the number of parts you want to combine :-(
If you know how to get the count of the variadic arguments (va_list) in C99, please contact me or write a GitHub issue! Thanks.

Example:

const char *assetsRootPath = ...
char textureAssetFilePath[FPL_MAX_PATH_LENGTH];
if (fplPathCombine(textureAssetFilePath, fplArrayCount(textureAssetFilePath), 3, assetsRootPath, "textures", "mytexture.png") != fpl_null) {
// ... Do something with the textureAssetFilePath
}
char tempPath[1024];
fplPathCombine(tempPath, fplArrayCount(tempPath), 3, "One", "Another", "Last");
// POSIX tempPath = One/Another/Last
// Win32 tempPath = One\Another\Last
#define fpl_null
Null.
#define FPL_MAX_PATH_LENGTH
Maximum length of a path.
#define fplArrayCount(arr)
Returns the element count from a static array. This should ideally produce a compile error when passi...
fpl_common_api size_t fplPathCombine(char *destPath, const size_t maxDestPathLen, const size_t pathCount,...)
Combines all given paths by the platforms path separator for a fixed number of arguments.
Note
This is the recommended way to construct any kind of path because it will handle path separators correctly.
This function is designed to be compatible with .NET Path.Combine().
Warning
Do not pass the wrong number of maximum arguments as a third-argument, otherwise, your application may end crashing horribly.

Extracting the file path

Use fplExtractFilePath() to extract the directory from the given path.

Using this on a path with a file will extract the path where the file is stored.
Using this on a directory path will extract the path of the parent directory.

Example:

const char *inputPath = ...
char newPath[FPL_MAX_PATH_LENGTH];
if (fplExtractFilePath(inputPath, &newPath, fplArrayCount(newPath)) != fpl_null) {
// ... Do something with the newPath
}
fpl_common_api size_t fplExtractFilePath(const char *sourcePath, char *destPath, const size_t maxDestLen)
Extracts the directory path from the given file path.
Note
This function is designed to be compatible with .NET Path.GetDirectoryName() or ExtractFilePath() on Delphi/FreePascal.
The original path is not altered in any way, therefore the source argument is defined as const.
Warning
Do not use manually constructed source paths with fixed path separators such as / or \, otherwise you will lose platform independence! Use fplPathCombine() to build new paths from multiple paths if needed.
The return value of fplExtractFilePath returns the pointer to the last-written character and NOT the pointer to the first character!

Extracting the file name

Use fplExtractFileName() to extract the filename from any path.
Using this on a full or relative file-path will extract the name of the file.
Using this on a directory path will extract the name of the last directory in the path.

Example:

const char *inputFilePath = ...
const char *fileName = fplExtractFileName(inputFilePath);
// ... Do something with the fileName
// Results:
// /my/path/to/the/file.ico -> file.ico
// /my/path/to/the/starting.file.ico -> starting.file.ico
// c:\Program Files (x86)\Xenorate\Xenorate.exe -> Xenorate.exe
// myAwesomeFilename.executable -> myAwesomeFilename.executable
// passthrough -> passthrough
// /my/path/to/the/ ->
fpl_common_api const char * fplExtractFileName(const char *sourcePath)
Extracts the file name including the file extension from the given source path.
Note
This function is designed to be compatible with .NET Path.GetFileName() or ExtractFileName() on Delphi/FreePascal.
The original path is not altered in any way, therefore the source argument is defined as const.
Warning
Do not use manually constructed source paths with fixed path separators such as / or \, otherwise you will lose platform independence! Use fplPathCombine() to build new paths from multiple paths if needed.

Extracting the file extension

Use fplExtractFileExtension() to extract the file extension from a path.
This will return anything starting from the last found file extension separator FPL_FILE_EXT_SEPARATOR to the very end of the path - containing the starting dot.
Using this on a path or filename will get you just the file extension if there is any.

Example:

const char *inputFilePath = ...
const char *fileExt = fplExtractFileExtension(inputFilePath);
// ... Do something with the fileExt
// Results:
// /my/path/to/the/file.ico -> .ico
// /my/path/to/the/starting.file.ico -> .file.ico
// c:\Program Files (x86)\Xenorate\Xenorate.exe -> .exe
// myAwesomeFilename.executable -> .executable
// /my/path/what.ever/libMyAwesome.so -> .so
// i_dont_have_any_dots_in_the_name ->
fpl_common_api const char * fplExtractFileExtension(const char *sourcePath)
Extracts the file extension from the given source path.
Note
This function is designed to be compatible with .NET Path.GetExtension() or ExtractFileExt() on Delphi/FreePascal.
The original path is not altered in any way, therefore the source argument is defined as const.
Warning
Do not use manually constructed source paths with fixed path separators such as / or \, otherwise you will lose platform independence! Use fplPathCombine() to build new paths from multiple paths if needed.

Changing the file extension

Use fplChangeFileExtension() to change/add a file extensions on a file path.

Example:

const char *inputFilePath = ...
char changedFileExt[FPL_MAX_PATH_LENGTH];
if (fplChangeFileExtension(inputFilePath, ".log", changedFileExt, fplArrayCount(changedFileExt)) != fpl_null) {
// ... Do something with the changedFileExt
}
fpl_common_api size_t fplChangeFileExtension(const char *filePath, const char *newFileExtension, char *destPath, const size_t maxDestLen)
Changes the file extension on the given source path and writes the result into a destination buffer.
Note
This function is designed to be compatible with .NET Path.ChangeFileExtension().
The original path is not altered in any way, therefore the source arguments are defined as const.
Warning
Do not use manually constructed source paths with fixed path separators such as / or \, otherwise you will lose platform independence! Use fplPathCombine() to build new paths from multiple paths if needed.

Retrievement of paths

Getting the home directory path

Use fplGetHomePath() to retrieve the home directory path for the current user.

On a POSIX based system this will most likely return something like "/usr/home/the_username_in_question"
On a Win32 based system this will most likely return something like "c:\Users\TheUsernameInQuestion"

Example:

char homePath[FPL_MAX_PATH_LENGTH];
fplGetHomePath(&homePath, fplArrayCount(homePath));
// ... Do something with the homePath
fpl_platform_api size_t fplGetHomePath(char *destPath, const size_t maxDestLen)
Gets the full path to your home directory.
Note
There is no guarantee that this path ends with a trailing path separator, such as / on POSIX or \ on Win32! If needed use fplEnforcePathSeparator to force a path separator on always.
Warning
The return value of fplGetHomePath returns the pointer to the last-written character and NOT the pointer to the first character!

Get executable file path

Use fplGetExecutableFilePath() to retrieve the full-path to your current executable.

On a POSIX based system this will most likely return something like "/some/path/../my_application"
On a Win32 based system this will most likely return something like "c:\Some\Path\..\MyApplication.exe"

Example:

// Get executable file path
char exeFilePath[FPL_MAX_PATH_LENGTH];
fplGetExecutableFilePath(&exeFilePath, fplArrayCount(exeFilePath));
// Get executable directory path
char appPath[FPL_MAX_PATH_LENGTH];
if (fplExtractFilePath(exeFilePath, &appPath, fplArrayCount(appPath)) != fpl_null) {
// ... Do something with appPath
}
fpl_platform_api size_t fplGetExecutableFilePath(char *destPath, const size_t maxDestLen)
Gets the full path to this executable, including the executable file name.
Note
There is no guarantee that this path ends with a trailing path separator, such as / on POSIX or \ on Win32! If needed use fplEnforcePathSeparator to force a path separator on always.
The name of the executable is always included in the path and will contain the file extension if there is one.
Warning
The return value of fplExtractFilePath returns the pointer to the last-written character and NOT the pointer to the first character!

Directory Traversing

FPL provides a powerful and easy directory traversal API, to find either files, directories, or both using a wildcard matching system.

Finding files by wildcard

Use fplDirectoryListBegin() to start finding files in a path.
If this function succeeds, the result for the first match is written into the fplFileEntry structure.

After this you repeatly call fplDirectoryListNext(), to get the next match into fplFileEntry structure - until the function returns false.

Example:

const char *sourcePath = ...
fplFileEntry fileEntry;
size_t fileCount = 0;
// Find all .so files (For-loop style)
fileCount = 0;
for(bool hasEntry = fplDirectoryListBegin(sourcePath, "*.so", &entry); hasEntry; hasEntry = fplDirectoryListNext(&entry)) {
// ... do something with entry.name
++fileCount;
}
// Find all .so files (While style)
fileCount = 0;
if (fplDirectoryListBegin(sourcePath, "*.so", &entry)) {
// The first file was found
// ... do something with entry.name
++fileCount;
// Loop until no file is found
while (fplDirectoryListNext(&entry)) {
// ... do something with entry.name
++fileCount;
}
}
// Find all .so files (For-loop style, break out after reaching a limit of maximum allowed files)
size_t maxFileCount = ...
fileCount = 0;
for(bool hasEntry = fplDirectoryListBegin(sourcePath, "*.so", &entry); hasEntry; hasEntry = fplDirectoryListNext(&entry)) {
if (fileCount < maxFileCount) {
// ... do something with entry.name
} else {
// Release resources, when we exit out the iteration
break;
}
++fileCount;
}
fpl_platform_api bool fplDirectoryListNext(fplFileEntry *entry)
Gets the next file entry from iterating through files/directories.
fpl_platform_api bool fplDirectoryListBegin(const char *path, const char *filter, fplFileEntry *entry)
Iterates through files/directories in the given directory.
fpl_platform_api void fplDirectoryListEnd(fplFileEntry *entry)
Releases opened resources from iterating through files/directories.
Note
When fplDirectoryListBegin() or fplDirectoryListNext() does not find any match, the internal resources are released automatically.
Warning
If you manually stop the iteration, please call fplDirectoryListEnd() to release its internal resources - otherwise you may leak memory!

Recursively get all files in a directory

There is no recursion support built-in in FPL, but you can easily make one using fplDirectoryListBegin() .
Just iterate through the file entries, which are already explained here: Finding files by wildcard
You can check fplFileEntry::type ,to check for either a fplFileEntryType_Directory or a fplFileEntryType_File type to start a recursion or not.

Example:

// Some existing awesome file-list container api
typedef struct file_list_t {
size_t capacity;
size_t count;
char **items;
} file_list_t;
void init_file_list(file_list_t *outList);
void free_file_list(file_list_t *outList);
void push_file_list_item(file_list_t *outList, const char *item);
static void GetFilesFromDirectory(const char *rootPath, const bool recursive, file_list_t *outList) {
fplEntry entry;
for(bool hasEntry = fplDirectoryListBegin(rootPath, "*", &entry); hasEntry; hasEntry = fplDirectoryListNext(&entry)) {
char path[FPL_MAX_PATH_LENGTH];
fplPathCombine(path, fplArrayCount(path), 2, rootPath, entry.name);
if (entry.type == fplFileEntryType_Directory && recursive) {
GetFilesFromDirectory(path, true, outList);
} else if (entry.type == fplFileEntryType_File) {
push_file_list_item(outList, path);
}
}
return(result);
}
int main(int argc, char **argv) {
if (argc < 2) {
return 1;
}
const char *rootPath = argv[1];
file_list_t outFileList;
init_file_list(&outFileList);
GetFilesFromDirectory(rootPath, true, &outFileList);
// ... do someting with out file list
free_file_list(&outFileList);
return 0;
}
@ fplFileEntryType_Directory
Entry is a directory.
@ fplFileEntryType_File
Entry is a file.