diff options
| author | Dan Engelbrecht <[email protected]> | 2025-01-16 09:19:08 +0100 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2025-01-16 09:19:08 +0100 |
| commit | a5158f9fc806d506590dd9bf0e3282cb76c3ac4e (patch) | |
| tree | 95a6dd46ad0520de4018e08ef6b3f409e25af3c3 /src/zencore/include | |
| parent | 5.5.17 (diff) | |
| download | zen-a5158f9fc806d506590dd9bf0e3282cb76c3ac4e.tar.xz zen-a5158f9fc806d506590dd9bf0e3282cb76c3ac4e.zip | |
move basicfile.h/cpp -> zencore (#273)
move jupiter.h/cpp -> zenutil
move packageformat.h/.cpp -> zenhttp
zenutil now depends on zenhttp instead of the inverse
Diffstat (limited to 'src/zencore/include')
| -rw-r--r-- | src/zencore/include/zencore/basicfile.h | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/src/zencore/include/zencore/basicfile.h b/src/zencore/include/zencore/basicfile.h new file mode 100644 index 000000000..03c5605df --- /dev/null +++ b/src/zencore/include/zencore/basicfile.h @@ -0,0 +1,185 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include <zencore/zencore.h> + +#include <zencore/compositebuffer.h> +#include <zencore/enumflags.h> +#include <zencore/iobuffer.h> + +#include <filesystem> +#include <functional> + +namespace zen { + +class CbObject; + +/** + * Probably the most basic file abstraction in the universe + * + * One thing of note is that there is no notion of a "current file position" + * in this API -- all reads and writes are done from explicit offsets in + * the file. This avoids concurrency issues which can occur otherwise. + * + */ + +class BasicFile +{ +public: + BasicFile() = default; + ~BasicFile(); + + BasicFile(const BasicFile&) = delete; + BasicFile& operator=(const BasicFile&) = delete; + + enum class Mode : uint32_t + { + kRead = 0, // Opens a existing file for read only + kWrite = 1, // Opens (or creates) a file for read and write + kTruncate = 2, // Opens (or creates) a file for read and write and sets the size to zero + kDelete = 3, // Opens (or creates) a file for read and write allowing .DeleteFile file disposition to be set + kTruncateDelete = + 4, // Opens (or creates) a file for read and write and sets the size to zero allowing .DeleteFile file disposition to be set + kModeMask = 0x0007, + kPreventDelete = 0x1000'0000, // Do not open with delete sharing mode (prevent other processes from deleting file while open) + kPreventWrite = 0x2000'0000, // Do not open with write sharing mode (prevent other processes from writing to file while open) + }; + + void Open(const std::filesystem::path& FileName, Mode Mode); + void Open(const std::filesystem::path& FileName, Mode Mode, std::error_code& Ec); + void Open(const std::filesystem::path& FileName, Mode Mode, std::function<bool(std::error_code& Ec)>&& RetryCallback); + void Close(); + void Read(void* Data, uint64_t Size, uint64_t FileOffset); + IoBuffer ReadRange(uint64_t FileOffset, uint64_t ByteCount); + void StreamFile(std::function<void(const void* Data, uint64_t Size)>&& ChunkFun); + void StreamByteRange(uint64_t FileOffset, uint64_t Size, std::function<void(const void* Data, uint64_t Size)>&& ChunkFun); + void Write(MemoryView Data, uint64_t FileOffset); + void Write(MemoryView Data, uint64_t FileOffset, std::error_code& Ec); + uint64_t Write(CompositeBuffer Data, uint64_t FileOffset, std::error_code& Ec); + void Write(const void* Data, uint64_t Size, uint64_t FileOffset); + void Write(const void* Data, uint64_t Size, uint64_t FileOffset, std::error_code& Ec); + void Flush(); + [[nodiscard]] uint64_t FileSize() const; + [[nodiscard]] uint64_t FileSize(std::error_code& Ec) const; + void SetFileSize(uint64_t FileSize); + IoBuffer ReadAll(); + void WriteAll(IoBuffer Data, std::error_code& Ec); + void Attach(void* Handle); + void* Detach(); + + inline void* Handle() { return m_FileHandle; } + bool IsOpen() const { return m_FileHandle != nullptr; } + +protected: + void* m_FileHandle = nullptr; // This is either null or valid +private: +}; + +ENUM_CLASS_FLAGS(BasicFile::Mode); + +/** + * Simple abstraction for a temporary file + * + * Works like a regular BasicFile but implements a simple mechanism to allow creating + * a temporary file for writing in a directory which may later be moved atomically + * into the intended location after it has been fully written to. + * + */ + +class TemporaryFile : public BasicFile +{ +public: + TemporaryFile() = default; + ~TemporaryFile(); + + TemporaryFile(const TemporaryFile&) = delete; + TemporaryFile& operator=(const TemporaryFile&) = delete; + + void CreateTemporary(std::filesystem::path TempDirName, std::error_code& Ec); + void MoveTemporaryIntoPlace(std::filesystem::path FinalFileName, std::error_code& Ec); + const std::filesystem::path& GetPath() const { return m_TempPath; } + + static void SafeWriteFile(const std::filesystem::path& Path, MemoryView Data); + static void SafeWriteFile(const std::filesystem::path& Path, MemoryView Data, std::error_code& OutEc); + +private: + void Close(); + std::filesystem::path m_TempPath; + + using BasicFile::Open; +}; + +/** Lock file abstraction + + */ + +class LockFile : protected BasicFile +{ +public: + LockFile(); + ~LockFile(); + + void Create(std::filesystem::path FileName, CbObject Payload, std::error_code& Ec); + void Update(CbObject Payload, std::error_code& Ec); + +private: +}; + +/** Adds a layer of buffered reading to a BasicFile + +This class is not intended for concurrent access, it is not thread safe. + +*/ + +class BasicFileBuffer +{ +public: + BasicFileBuffer(BasicFile& Base, uint64_t BufferSize); + ~BasicFileBuffer(); + + void Read(void* Data, uint64_t Size, uint64_t FileOffset); + MemoryView MakeView(uint64_t Size, uint64_t FileOffset); + + template<typename T> + const T* MakeView(uint64_t FileOffset) + { + MemoryView View = MakeView(sizeof(T), FileOffset); + return reinterpret_cast<const T*>(View.GetData()); + } + +private: + BasicFile& m_Base; + uint8_t* m_Buffer; + const uint64_t m_BufferSize; + uint64_t m_Size; + uint64_t m_BufferStart; + uint64_t m_BufferEnd; +}; + +/** Adds a layer of buffered writing to a BasicFile + +This class is not intended for concurrent access, it is not thread safe. + +*/ + +class BasicFileWriter +{ +public: + BasicFileWriter(BasicFile& Base, uint64_t BufferSize); + ~BasicFileWriter(); + + void Write(const void* Data, uint64_t Size, uint64_t FileOffset); + void Flush(); + +private: + BasicFile& m_Base; + uint8_t* m_Buffer; + const uint64_t m_BufferSize; + uint64_t m_BufferStart; + uint64_t m_BufferEnd; +}; + +ZENCORE_API void basicfile_forcelink(); + +} // namespace zen |