aboutsummaryrefslogtreecommitdiff
path: root/src/zencore/include
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2025-01-16 09:19:08 +0100
committerGitHub Enterprise <[email protected]>2025-01-16 09:19:08 +0100
commita5158f9fc806d506590dd9bf0e3282cb76c3ac4e (patch)
tree95a6dd46ad0520de4018e08ef6b3f409e25af3c3 /src/zencore/include
parent5.5.17 (diff)
downloadzen-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.h185
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