FileSystem Explanation

The goal of the creation of FileSystem was an abstract data-stream and data-provider system. Data streams can not only be files but memory streams, compressed streams and network streams. The advantage over OS implemented streams is that you get full control over the consistent functionality.

CFile stream

Abstract data location to push or pull data. It is designed after ANSI C FILE streams. For example, it supports the same open-modes (r, w, rb, …) and seek-modes (set, cur, end). The Read and Write methods are equal to fwrite and fread.

CFileTranslator data provider

Directory handle into a data container. If located on the OS native filesystem then it is a directory handle under an absolute path. It could also be an open .zip archive.

We call it a translator. The main idea is that you can access a file tree through it. You can spawn CFile streams using the Open method. Other methods can be used to navigate the file tree or return valid relative/absolute paths.

Before destroying the translator all files that have been spawned from it should be destroyed.

CFileSystem manager

The main manager class. Only one instance can be alive at-a-time. You need to use the factory functions CFileSystem::Create and CFileSystem::Destroy to manage lifetime.

To enable threading support you can pass a NativeExecutive library instance in the construction parameters.

Error management

In general many methods in FileSystem have boolean and pointer return types. Error cases are trivial then. For more exceptional situations there is the filesystem_exception class. It contains an exception type parameter.

Methods in FileSystem are designed exception-safe. Exceptions can be thrown at any point during runtime.

Thread safety

Many methods are indeed thread-safe but not all. As a rule of thumb the library can be used by multiple threads but translators and files should be by single-threads only.

Example: Directory listing

This example code demonstrates a directory listing (download project).

// Include the main headers of the FileSystem library.
// The library should be located in the vendor directory.
#include <CFileSystemInterface.h>
#include <CFileSystem.h>

#include <iostream>

#include <assert.h>

int main( int argc, char *argv[] )
{
    // Create a standard non-multithreaded FS instance.
    fs_construction_params params;
    params.nativeExecMan = nullptr;

    CFileSystem *fsHandle = CFileSystem::Create( params );

    assert( fsHandle != nullptr );

    // We create a file translator in the application current directory.
    CFileTranslator *root = fsHandle->CreateTranslator( "" );

    assert( root != nullptr );

    // List things in this directory.
    root->ScanDirectory( "", "*", true, nullptr,
        [&]( const filePath& absPath )
    {
        // Create a relative path from the absolute path.
        filePath relPath;
        root->GetRelativePath( absPath, true, relPath );

        std::wstring outInfo;
        outInfo += relPath.convert_unicode();

        outInfo += L": ";

        // We do that by opening file handles.
        CFile *theFile = root->Open( absPath, "rb" );

        if ( theFile )
        {
            // Return the file size.
            fsOffsetNumber_t fileSize = theFile->GetSizeNative();

            outInfo += L"size=";
            outInfo += std::to_wstring( fileSize );
            outInfo += L" bytes";

            // Never forget to close handles.
            delete theFile;
        }
        else
        {
            // Handle error cases because they can always happen.
            outInfo += L"failed to open file.";
        }

        // Print out to console.
        std::wcout << outInfo << std::endl;
    }, nullptr);

    // Clean up.
    delete root;

    CFileSystem::Destroy( fsHandle );

    return 0;
}