IFileSystem2.h#
Fully qualified name: carb/filesystem/detail/IFileSystem2.h
File members: carb/filesystem/detail/IFileSystem2.h
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: LicenseRef-NvidiaProprietary
//
// NVIDIA CORPORATION, its affiliates and licensors retain all intellectual
// property and proprietary rights in and to this material, related
// documentation and any modifications thereto. Any use, reproduction,
// disclosure or distribution of this material and related documentation
// without an express license agreement from NVIDIA CORPORATION or
// its affiliates is strictly prohibited.
#pragma once
#ifndef carb_filesystem_IFileSystem_latest
# error Must include via ../IFileSystem1.h
#endif
#if !CARB_VERSION_ATLEAST(carb_filesystem_IFileSystem, 2, 0)
# error Version too low to be included
#elif CARB_VERSION_ATLEAST(carb_filesystem_IFileSystem, 3, 0)
# error Version too high to be included
#endif
#include "../../cpp/ZStringView.h"
#include "../../Error.h"
#include "../../../omni/Expected.h"
#include "../../../omni/MoveOnlyFunction.h"
#include "../../../omni/String.h"
namespace carb::filesystem
{
#ifndef DOXYGEN_BUILD
inline namespace v2
{
#endif
struct DirectoryItemInfo : public FileInfo
{
cpp::zstring_view path;
};
struct FileTime
{
time_t time;
uint32_t nano;
};
#ifndef DOXYGEN_BUILD
inline bool operator==(const FileTime& lhs, const FileTime& rhs) noexcept
{
return lhs.time == rhs.time && lhs.nano == rhs.nano;
}
inline bool operator!=(const FileTime& lhs, const FileTime& rhs) noexcept
{
return !(lhs == rhs);
}
inline bool operator<(const FileTime& lhs, const FileTime& rhs) noexcept
{
if (lhs.time < rhs.time)
return true;
return lhs.time == rhs.time ? lhs.nano < rhs.nano : false;
}
inline bool operator>(const FileTime& lhs, const FileTime& rhs) noexcept
{
return rhs < lhs;
}
inline bool operator<=(const FileTime& lhs, const FileTime& rhs) noexcept
{
return !(lhs > rhs);
}
inline bool operator>=(const FileTime& lhs, const FileTime& rhs) noexcept
{
return !(lhs < rhs);
}
#endif
class File
{
public:
virtual void release() noexcept = 0;
virtual omni::expected<void, ErrorCode> close() noexcept = 0;
virtual omni::expected<size_t, ErrorCode> getSize() noexcept = 0;
virtual omni::expected<FileTime, ErrorCode> getModTime() noexcept = 0;
virtual omni::expected<FileTime, ErrorCode> getCreateTime() noexcept = 0;
virtual omni::expected<size_t, ErrorCode> readChunk(void* buffer, size_t bytes) noexcept = 0;
virtual omni::expected<size_t, ErrorCode> writeChunk(const void* buffer, size_t bytes) noexcept = 0;
virtual omni::expected<omni::string, ErrorCode> readLine() noexcept = 0;
virtual omni::expected<void, ErrorCode> readLine(omni::string& out) noexcept = 0;
virtual omni::expected<void, ErrorCode> writeLine(cpp::string_view line) noexcept = 0;
virtual omni::expected<void, ErrorCode> flush() noexcept = 0;
virtual omni::expected<size_t, ErrorCode> getPosition() const noexcept = 0;
virtual omni::expected<void, ErrorCode> setPosition(int64_t offset, FileWhence whence) noexcept = 0;
virtual omni::expected<void, ErrorCode> truncate() noexcept = 0;
virtual FileStatus getStatus() const noexcept = 0;
bool isEof() const noexcept
{
return getStatus() == FileStatus::eEof;
}
bool isError() const noexcept
{
return getStatus() == FileStatus::eError;
}
virtual omni::expected<void, ErrorCode> getFileInfo(FileInfo& info) noexcept = 0;
omni::expected<void, ErrorCode> resetPositionBegin() noexcept
{
return setPosition(0, FileWhence::eBegin);
}
omni::expected<void, ErrorCode> resetPositionEnd() noexcept
{
return setPosition(0, FileWhence::eEnd);
}
};
namespace v2_detail
{
struct FileReleaser
{
void operator()(File* f)
{
f->release();
}
};
} // namespace v2_detail
using ScopedFile = std::unique_ptr<File, v2_detail::FileReleaser>;
struct IFileSystem
{
CARB_PLUGIN_INTERFACE_EX("carb::filesystem::IFileSystem",
carb_filesystem_IFileSystem_latest,
carb_filesystem_IFileSystem)
virtual cpp::zstring_view getExecutablePath() const noexcept = 0;
virtual cpp::zstring_view getExecutableDirectoryPath() const noexcept = 0;
virtual omni::expected<void, ErrorCode> setAppDirectoryPath(cpp::string_view path) noexcept = 0;
virtual omni::string getAppDirectoryPath() const noexcept = 0;
virtual omni::expected<void, ErrorCode> setWorkingDirectory(cpp::string_view path) const noexcept = 0;
virtual omni::expected<omni::string, ErrorCode> getWorkingDirectory() const noexcept = 0;
virtual omni::expected<bool, ErrorCode> checkExists(cpp::string_view path) const noexcept = 0;
bool exists(cpp::string_view path) const noexcept
{
return checkExists(path).value_or(false);
}
virtual omni::expected<bool, ErrorCode> checkWritable(cpp::string_view path) const noexcept = 0;
bool isWritable(cpp::string_view path) const noexcept
{
return checkWritable(path).value_or(false);
}
virtual omni::expected<bool, ErrorCode> checkReadable(cpp::string_view path) const noexcept = 0;
bool isReadable(cpp::string_view path) const noexcept
{
return checkReadable(path).value_or(false);
}
virtual omni::expected<bool, ErrorCode> checkDirectory(cpp::string_view path) const noexcept = 0;
bool isDirectory(cpp::string_view path) const noexcept
{
return checkDirectory(path).value_or(false);
}
virtual omni::expected<omni::string, ErrorCode> makeCanonicalPath(cpp::string_view path,
bool mustExist = true) const noexcept = 0;
virtual omni::expected<omni::string, ErrorCode> makeCanonicalPath(cpp::string_view path,
cpp::string_view base,
bool mustExist = true) const noexcept = 0;
omni::expected<ScopedFile, ErrorCode> open(cpp::string_view path, OpenMode mode, bool binary) const noexcept
{
return internalOpen(path, mode, binary).transform([](File* in) { return ScopedFile(in); });
}
virtual omni::expected<FileTime, ErrorCode> getModTime(cpp::string_view path) const noexcept = 0;
virtual omni::expected<FileTime, ErrorCode> getCreateTime(cpp::string_view path) const noexcept = 0;
virtual FileTime getCurrentTime() const noexcept = 0;
virtual omni::expected<void, ErrorCode> removeFile(cpp::string_view path) const noexcept = 0;
virtual omni::expected<void, ErrorCode> removeDirectory(cpp::string_view path) const noexcept = 0;
virtual omni::expected<omni::string, ErrorCode> makeTempDirectory() const noexcept = 0;
virtual omni::expected<CreateType, ErrorCode> makeSingleDirectory(cpp::string_view path) const noexcept = 0;
virtual omni::expected<CreateType, ErrorCode> makeDirectories(cpp::string_view path) const noexcept = 0;
virtual omni::expected<void, ErrorCode> copyFile(cpp::string_view from, cpp::string_view to) const noexcept = 0;
virtual omni::expected<void, ErrorCode> movePath(cpp::string_view from, cpp::string_view to) const noexcept = 0;
template <typename Pred>
omni::expected<void, ErrorCode> forEachDirectoryItem(cpp::string_view path, bool recurse, Pred&& pred) const;
virtual omni::expected<SubscriptionId, ErrorCode> subscribeToChangeEvents(
cpp::string_view path,
omni::move_only_function<void(cpp::zstring_view, ChangeAction, cpp::zstring_view)> func) const noexcept = 0;
virtual omni::expected<void, ErrorCode> unsubscribeFromChangeEvents(SubscriptionId id) const noexcept = 0;
virtual omni::expected<void, ErrorCode> getFileInfo(cpp::string_view path, FileInfo& out) const noexcept = 0;
private:
virtual omni::expected<File*, ErrorCode> internalOpen(cpp::string_view path,
OpenMode mode,
bool binary) const noexcept = 0;
virtual omni::expected<void, ErrorCode> internalForEachDirectoryItem(cpp::string_view path,
bool recurse,
WalkAction (*callback)(const DirectoryItemInfo&,
void* userData),
void* userData) const noexcept = 0;
};
template <typename Pred>
omni::expected<void, ErrorCode> IFileSystem::forEachDirectoryItem(cpp::string_view path, bool recurse, Pred&& pred) const
{
using PredType = std::decay_t<Pred>;
using RetType = cpp::invoke_result_t<Pred, const DirectoryItemInfo&>;
if constexpr (std::is_void_v<RetType>)
{
return internalForEachDirectoryItem(path, recurse,
+[](const DirectoryItemInfo& info, void* ud) {
(*static_cast<PredType*>(ud))(info);
return WalkAction::eContinue;
},
reinterpret_cast<void*>(&pred));
}
else
{
static_assert(std::is_same_v<WalkAction, RetType>, "Predicate must return WalkAction");
return internalForEachDirectoryItem(
path, recurse, +[](const DirectoryItemInfo& info, void* ud) { return (*static_cast<PredType*>(ud))(info); },
reinterpret_cast<void*>(&pred));
}
}
#ifndef DOXYGEN_BUILD
} // namespace v2
#endif
} // namespace carb::filesystem