From f7ba29ff79713a5a3c8f5b11a0ae41c3bd6e5f2e Mon Sep 17 00:00:00 2001 From: Joud Kandeel Date: Thu, 12 Mar 2026 03:31:39 +0100 Subject: [PATCH] made a win32 and posix impl --- .../IO/Stream/FileOutputStream.cpp | 123 +++++++++++++++++- .../IO/Stream/FileOutputStream.hpp | 94 ++++++++++--- 2 files changed, 197 insertions(+), 20 deletions(-) diff --git a/Minecraft-Community-Edition/IO/Stream/FileOutputStream.cpp b/Minecraft-Community-Edition/IO/Stream/FileOutputStream.cpp index cba3d1b..007a3f3 100644 --- a/Minecraft-Community-Edition/IO/Stream/FileOutputStream.cpp +++ b/Minecraft-Community-Edition/IO/Stream/FileOutputStream.cpp @@ -1,18 +1,137 @@ +#include "..\..\Common\Platform.hpp" +#ifdef MCE_PLATFORM_WINDOWS +#undef UNICODE +#define WIN32_LEAN_AND_MEAN +#include #include "FileOutputStream.hpp" namespace mce { - void FileOutputStream::flush() { + bool FileOutputStream::open(const std::string& file) { + FileOutputStream::hFile = CreateFile(file.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + return (FileOutputStream::hFile != INVALID_HANDLE_VALUE); } - size_t FileOutputStream::write(void* buffer, size_t size) { + bool FileOutputStream::isOpen() const { + return (FileOutputStream::hFile != INVALID_HANDLE_VALUE); + } + + void FileOutputStream::close() { + if (FileOutputStream::hFile != INVALID_HANDLE_VALUE) { + CloseHandle(FileOutputStream::hFile); + } + } + + size_t FileOutputStream::write(const void* buffer, size_t size) { + DWORD w; + WriteFile(FileOutputStream::hFile, buffer, size, &w, nullptr); + return static_cast(w); } size_t FileOutputStream::seek(size_t position) { + LARGE_INTEGER offset{}; + offset.QuadPart = position; + if (SetFilePointerEx(FileOutputStream::hFile, offset, nullptr, FILE_BEGIN) < 0) { + return FileOutputStream::INVALID_FILE_POSITION; + } + return position; } size_t FileOutputStream::tell() { + LARGE_INTEGER zero = { 0 }; + LARGE_INTEGER pos; + + if (SetFilePointerEx((HANDLE)FileOutputStream::hFile, zero, &pos, FILE_CURRENT) < 0) { + return FileOutputStream::INVALID_FILE_POSITION; + } + + return (size_t)pos.QuadPart; } size_t FileOutputStream::getSize() { + LARGE_INTEGER size{}; + if (GetFileSizeEx(FileOutputStream::hFile, &size) > 0) { + return FileOutputStream::INVALID_FILE_SIZE; + } + return (size_t)size.QuadPart; } } +#endif + +#if defined(MCE_PLATFORM_LINUX) || defined(MCE_PLATFORM_MACOS) +#pragma warning(disable:4996) + +#include +#include +#include "FileOutputStream.hpp" + +namespace mce { + + FileOutputStream::FileOutputStream() : + file(nullptr) {} + + FileOutputStream::~FileOutputStream() { + FileOutputStream::close(); + } + + bool FileOutputStream::open(const std::string& fileName) { + if (FileOutputStream::file) + std::fclose(FileOutputStream::file); + + FileOutputStream::file = std::fopen(fileName.c_str(), "wb"); + + return FileOutputStream::file != NULL; + } + + void FileOutputStream::close() { + if (FileOutputStream::file != nullptr) { + std::fclose(FileOutputStream::file); + FileOutputStream::file = nullptr; + } + } + + bool FileOutputStream::isOpen() const { + return FileOutputStream::file != nullptr; + } + + size_t FileOutputStream::write(const void* buffer, size_t size) { + if (FileOutputStream::file) + return std::fwrite(buffer, 1, size, FileOutputStream::file); + else + return 0; + } + + size_t FileOutputStream::seek(size_t position) { + if (FileOutputStream::file) { + if (std::fseek(FileOutputStream::file, static_cast(position), SEEK_SET)) + return FileOutputStream::INVALID_FILE_POSITION; + + return tell(); + } + else { + return FileOutputStream::INVALID_FILE_POSITION; + } + } + + size_t FileOutputStream::tell() { + if (FileOutputStream::file) + return std::ftell(FileOutputStream::file); + else + return FileOutputStream::INVALID_FILE_POSITION; + } + + size_t FileOutputStream::getSize() { + if (FileOutputStream::file) { + size_t position = FileOutputStream::tell(); + std::fseek(FileOutputStream::file, 0, SEEK_END); + size_t size = FileOutputStream::tell(); + FileOutputStream::seek(position); + return size; + } + else { + return FileOutputStream::INVALID_FILE_SIZE; + } + } +} + +#endif + diff --git a/Minecraft-Community-Edition/IO/Stream/FileOutputStream.hpp b/Minecraft-Community-Edition/IO/Stream/FileOutputStream.hpp index 29c73a2..4cf99f3 100644 --- a/Minecraft-Community-Edition/IO/Stream/FileOutputStream.hpp +++ b/Minecraft-Community-Edition/IO/Stream/FileOutputStream.hpp @@ -1,41 +1,99 @@ #pragma once - +#include "..\..\Common\Platform.hpp" #include "OutputStream.hpp" +#ifdef MCE_PLATFORM_WINDOWS +#undef INVALID_FILE_SIZE +#endif -#include +#include +#include namespace mce { +/** + * @brief Platform-independent file output stream implementation. + * + * Provides a concrete OutputStream that writes data to a file using the + * platform native file handle or FILE* depending on the platform. + */ class FileOutputStream final : public OutputStream { public: - FileOutputStream() = default; - explicit FileOutputStream(eastl::string_view file); - /** - * @brief Opens a file to read from - * @param file The path (absolute or relative) to the file + * @brief Default constructor. */ - void open(eastl::string_view file); + FileOutputStream() = default; /** - * @return True if the file was successfully opened + * @brief Opens a file for writing (creates/truncates by default). + * @param file Path (absolute or relative) to the file to open. + * @return True if the file was successfully opened. + */ + bool open(const std::string& file); + + /** + * @brief Query whether the underlying file handle is open. + * @return True when the file is open and ready for writing. */ bool isOpen() const; /** - * @brief Checks if the stream is at the end of the file - * @return True if the file stream has the end-of-file flag (EOF). - */ - bool eof() const; - - /** - * @brief Closes the file + * @brief Close the file and release any resources. */ void close(); - void flush() override; - size_t write(void* buffer, size_t size) override; + /** + * @brief Write bytes to the file. + * @param buffer Pointer to the data to write. + * @param size Number of bytes to write from buffer. + * @return Number of bytes actually written. + */ + size_t write(const void* buffer, size_t size) override; + + /** + * @brief Change the current write position in the file. + * @param position The absolute position (in bytes) to seek to. + * @return The new position in the file after seeking. + */ size_t seek(size_t position) override; + + /** + * @brief Get the current write position in the file. + * @return Current position in bytes from the start of the file. + */ size_t tell() override; + + /** + * @brief Get the total size of the underlying file in bytes. + * @return File size in bytes or INVALID_FILE_SIZE on error. + */ size_t getSize() override; + + /** + * @brief Constant indicating an invalid file size/position. + * + * This value is returned by getSize() or tell() when the operation + * fails. + */ + static inline constexpr size_t INVALID_FILE_SIZE = ~(0); + + /** + * @brief Constant indicating an invalid file position. + */ + static inline constexpr size_t INVALID_FILE_POSITION = ~(0); + + private: +#ifdef MCE_PLATFORM_WINDOWS + /** + * @brief Native Windows file handle pointer (opaque). + * + * Stored as void* to avoid including Windows headers in this header + * file. The implementation file should treat this as a HANDLE. + */ + void* hFile = nullptr; +#elif defined(MCE_PLATFORM_LINUX) || defined(MCE_PLATFORM_MACOS) + /** + * @brief Standard C FILE* used on POSIX platforms. + */ + std::FILE* file = nullptr; +#endif }; } \ No newline at end of file