carb/filesystem/IFileSystem.h

File members: carb/filesystem/IFileSystem.h

// Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
//
// NVIDIA CORPORATION and its licensors retain all intellectual property
// and proprietary rights in and to this software, related documentation
// and any modifications thereto. Any use, reproduction, disclosure or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA CORPORATION is strictly prohibited.
//

#pragma once

#include "../Defines.h"

#include "../Types.h"

#include <stdlib.h>
#include <string>
#include <time.h>
#include <vector>

namespace carb
{
namespace filesystem
{

struct File DOXYGEN_EMPTY_CLASS;
struct IFileSystem;

typedef uint32_t SubscriptionId;

const SubscriptionId kInvalidSubscriptionId = 0;

enum class DirectoryItemType
{
    eFile,
    eDirectory,
};

enum class ChangeAction
{
    eCreated,

    eModified,

    eDeleted,

    eRenamed
};

enum class WalkAction : signed char
{
    eStop = -1,

    eSkip,

    eContinue,
};

struct FileInfo
{
    DirectoryItemType type;

    time_t modifiedTimestamp;

    time_t createdTimestamp;

    size_t size;

    bool isSymlink;
};

struct DirectoryItemInfo : public FileInfo
{
    const char* path;
};

enum class FileWhence
{
    eBegin,
    eCurrent,
    eEnd,
};

enum class FileStatus
{
    eOk,
    eEof,
    eError,
};

using CanonicalFlags = uint32_t;

constexpr CanonicalFlags fCanonicalFlagCheckExists = 0x01;

typedef void (*OnChangeEventFn)(const char* path, ChangeAction action, void* userData, const char* newPath);

struct IFileSystem
{
    // 1.3: Eliminated error/warning logging and made use of ErrorApi for error codes
    CARB_PLUGIN_INTERFACE("carb::filesystem::IFileSystem", 1, 3)

    const char*(CARB_ABI* getExecutablePath)();

    const char*(CARB_ABI* getExecutableDirectoryPath)();

    const char*(CARB_ABI* getAppDirectoryPath)();

    void(CARB_ABI* setAppDirectoryPath)(const char* path);

    const char*(CARB_ABI* getCurrentDirectoryPath)();

    bool(CARB_ABI* setCurrentDirectoryPath)(const char* path);

    bool(CARB_ABI* exists)(const char* path);

    bool(CARB_ABI* isWritable)(const char* path);

    bool(CARB_ABI* isDirectory)(const char* path);

    size_t(CARB_ABI* makeCanonicalPathEx)(const char* path, const char* base, char* buffer, size_t bufferSize);

    std::string makeCanonicalPath(const char* path,
                                  const char* base = nullptr,
                                  CanonicalFlags flags = fCanonicalFlagCheckExists);

    File*(CARB_ABI* openFileToRead)(const char* path);

    File*(CARB_ABI* openFileToWrite)(const char* path);

    File*(CARB_ABI* openFileToAppend)(const char* path);

    void(CARB_ABI* closeFile)(File* file);

    size_t(CARB_ABI* getFileSize)(File* file);

    time_t(CARB_ABI* getFileModTime)(File* file);

    time_t(CARB_ABI* getModTime)(const char* path);

    time_t(CARB_ABI* getFileCreateTime)(File* file);

    time_t(CARB_ABI* getCreateTime)(const char* path);

    size_t(CARB_ABI* readFileChunk)(File* file, void* chunk, size_t chunkSize);

    size_t(CARB_ABI* writeFileChunk)(File* file, const void* chunk, const size_t chunkSize);

    char*(CARB_ABI* readFileLine)(File* file, char* line, size_t maxLineSize);

    bool(CARB_ABI* writeFileLine)(File* file, const char* line);

    void(CARB_ABI* flushFile)(File* file);

    bool(CARB_ABI* removeFile)(const char* path);

    bool(CARB_ABI* makeTempDirectory)(char* pathBuffer, size_t bufferSize);

    bool(CARB_ABI* makeDirectory)(const char* path);

    bool(CARB_ABI* makeDirectories)(const char* path);

    bool(CARB_ABI* removeDirectory)(const char* path);

    bool(CARB_ABI* copy)(const char* from, const char* to);

    bool(CARB_ABI* move)(const char* from, const char* to);

    typedef WalkAction (*OnDirectoryItemFn)(const DirectoryItemInfo* const info, void* userData);

    void(CARB_ABI* forEachDirectoryItem)(const char* path, OnDirectoryItemFn onDirectoryItem, void* userData);

    void(CARB_ABI* forEachDirectoryItemRecursive)(const char* path, OnDirectoryItemFn onDirectoryItem, void* userData);

    SubscriptionId(CARB_ABI* subscribeToChangeEvents)(const char* path, OnChangeEventFn onChangeEvent, void* userData);

    void(CARB_ABI* unsubscribeToChangeEvents)(SubscriptionId subscriptionId);

    int64_t(CARB_ABI* getFilePosition)(File* file);

    bool(CARB_ABI* setFilePosition)(File* file, int64_t offsetFromWhence, FileWhence whence);

    bool(CARB_ABI* truncateFileAtCurrentPosition)(File* file);

    bool setFilePositionBegin(File* file);

    bool setFilePositionEnd(File* file);

    File*(CARB_ABI* openFileToReadWrite)(const char* path);

    FileStatus(CARB_ABI* getFileStatus)(File* file);

    bool(CARB_ABI* getFileInfo)(const char* path, FileInfo* info);

    time_t(CARB_ABI* getCurrentTime)();

    bool(CARB_ABI* isReadable)(const char* path);

    size_t(CARB_ABI* makeCanonicalPathEx2)(
        const char* path, const char* base, CanonicalFlags flags, char* buffer, size_t bufferSize);
};

inline std::string IFileSystem::makeCanonicalPath(const char* path, const char* base, CanonicalFlags flags)
{
    std::string str(128, '\0');
    size_t bytes = this->makeCanonicalPathEx2(path, base, flags, &str[0], str.size());
    if (bytes == 0)
        return {};
    if (bytes > str.size())
    {
        str.resize(bytes);
        bytes = this->makeCanonicalPathEx2(path, base, flags, &str[0], str.size());
        CARB_ASSERT(bytes != 0 && str.size() >= bytes);
    }
    str.resize(bytes - 1); // Bytes includes the NUL terminator, so remove it here
    return str;
}

inline bool IFileSystem::setFilePositionBegin(File* file)
{
    return setFilePosition(file, 0, FileWhence::eBegin);
}

inline bool IFileSystem::setFilePositionEnd(File* file)
{
    return setFilePosition(file, 0, FileWhence::eEnd);
}

} // namespace filesystem
} // namespace carb