diff --git a/include/Nazara/Core/Enums.hpp b/include/Nazara/Core/Enums.hpp index c351b5dd9..c43921bd4 100644 --- a/include/Nazara/Core/Enums.hpp +++ b/include/Nazara/Core/Enums.hpp @@ -228,6 +228,7 @@ namespace Nz { None, + MemoryMapped, Sequential, Text, Unbuffered, diff --git a/include/Nazara/Core/MemoryStream.hpp b/include/Nazara/Core/MemoryStream.hpp index 453fbff77..3e950ef1a 100644 --- a/include/Nazara/Core/MemoryStream.hpp +++ b/include/Nazara/Core/MemoryStream.hpp @@ -37,6 +37,7 @@ namespace Nz private: void FlushStream() override; + void* GetMemoryMappedPointer() const override; std::size_t ReadBlock(void* buffer, std::size_t size) override; bool SeekStreamCursor(UInt64 offset) override; UInt64 TellStreamCursor() const override; diff --git a/include/Nazara/Core/MemoryStream.inl b/include/Nazara/Core/MemoryStream.inl index dc9998e01..37aa3c207 100644 --- a/include/Nazara/Core/MemoryStream.inl +++ b/include/Nazara/Core/MemoryStream.inl @@ -14,7 +14,7 @@ namespace Nz * \brief Constructs a MemoryStream object by default */ inline MemoryStream::MemoryStream() : - Stream(StreamOption::None, OpenMode_ReadWrite), + Stream(StreamOption::MemoryMapped, OpenMode_ReadWrite), m_pos(0) { } diff --git a/include/Nazara/Core/MemoryView.hpp b/include/Nazara/Core/MemoryView.hpp index 6b89fbeda..be26fa798 100644 --- a/include/Nazara/Core/MemoryView.hpp +++ b/include/Nazara/Core/MemoryView.hpp @@ -18,20 +18,21 @@ namespace Nz MemoryView(void* ptr, UInt64 size); MemoryView(const void* ptr, UInt64 size); MemoryView(const MemoryView&) = delete; - MemoryView(MemoryView&&) = delete; ///TODO + MemoryView(MemoryView&&) noexcept = default; ~MemoryView() = default; UInt64 GetSize() const override; MemoryView& operator=(const MemoryView&) = delete; - MemoryView& operator=(MemoryView&&) = delete; ///TODO + MemoryView& operator=(MemoryView&&) noexcept = default; private: void FlushStream() override; + void* GetMemoryMappedPointer() const override; std::size_t ReadBlock(void* buffer, std::size_t size) override; bool SeekStreamCursor(UInt64 offset) override; - UInt64 TellStreamCursor() const override; bool TestStreamEnd() const override; + UInt64 TellStreamCursor() const override; std::size_t WriteBlock(const void* buffer, std::size_t size) override; UInt8* m_ptr; diff --git a/include/Nazara/Core/Stream.hpp b/include/Nazara/Core/Stream.hpp index b5742bfe2..640c5a507 100644 --- a/include/Nazara/Core/Stream.hpp +++ b/include/Nazara/Core/Stream.hpp @@ -17,6 +17,7 @@ namespace Nz { + class AbstractHash; class ByteArray; class NAZARA_CORE_API Stream @@ -33,18 +34,20 @@ namespace Nz inline void Flush(); - virtual std::filesystem::path GetDirectory() const; - virtual std::filesystem::path GetPath() const; - inline OpenModeFlags GetOpenMode() const; - inline StreamOptionFlags GetStreamOptions() const; - UInt64 GetCursorPos() const; + virtual std::filesystem::path GetDirectory() const; + inline const void* GetMappedPointer() const; + inline void* GetMappedPointerMutable(); + inline OpenModeFlags GetOpenMode() const; + virtual std::filesystem::path GetPath() const; virtual UInt64 GetSize() const = 0; + inline StreamOptionFlags GetStreamOptions() const; std::size_t Read(void* buffer, std::size_t size); virtual std::string ReadLine(unsigned int lineSize = 0); inline bool IsBufferingEnabled() const; + inline bool IsMemoryMapped() const; inline bool IsReadable() const; inline bool IsSequential() const; inline bool IsTextModeEnabled() const; @@ -65,6 +68,7 @@ namespace Nz inline Stream(StreamOptionFlags streamOptions = StreamOption::None, OpenModeFlags openMode = OpenMode::NotOpen); virtual void FlushStream() = 0; + virtual void* GetMemoryMappedPointer() const; virtual std::size_t ReadBlock(void* buffer, std::size_t size) = 0; virtual bool SeekStreamCursor(UInt64 offset) = 0; virtual UInt64 TellStreamCursor() const = 0; diff --git a/include/Nazara/Core/Stream.inl b/include/Nazara/Core/Stream.inl index 7f47dca0b..c0bc74e86 100644 --- a/include/Nazara/Core/Stream.inl +++ b/include/Nazara/Core/Stream.inl @@ -16,7 +16,6 @@ namespace Nz * \param streamOptions Options for the stream * \param openMode Reading/writing mode for the stream */ - inline Stream::Stream(StreamOptionFlags streamOptions, OpenModeFlags openMode) : m_bufferCapacity(0), m_bufferOffset(0), @@ -32,12 +31,11 @@ namespace Nz * * \param textMode Enables the mode or disables */ - inline void Stream::EnableBuffering(bool buffering, std::size_t bufferSize) { if (buffering) { - m_streamOptions &= ~StreamOption::Unbuffered; + m_streamOptions.Clear(StreamOption::Unbuffered); if (m_bufferCapacity != bufferSize) { m_buffer = std::make_unique(bufferSize); @@ -49,7 +47,7 @@ namespace Nz } else { - m_streamOptions |= StreamOption::Unbuffered; + m_streamOptions.Set(StreamOption::Unbuffered); m_buffer.reset(); m_bufferCapacity = 0; } @@ -58,9 +56,9 @@ namespace Nz inline void Stream::EnableTextMode(bool textMode) { if (textMode) - m_streamOptions |= StreamOption::Text; + m_streamOptions.Set(StreamOption::Text); else - m_streamOptions &= ~StreamOption::Text; + m_streamOptions.Clear(StreamOption::Text); } /*! @@ -76,11 +74,24 @@ namespace Nz FlushStream(); } + inline const void* Stream::GetMappedPointer() const + { + NazaraAssert(IsMemoryMapped(), "Stream is not memory-mapped"); + NazaraAssert(IsReadable(), "Stream is not readable"); + return GetMemoryMappedPointer(); + } + + inline void* Stream::GetMappedPointerMutable() + { + NazaraAssert(IsMemoryMapped(), "Stream is not memory-mapped"); + NazaraAssert(IsWritable(), "Stream is not writable"); + return GetMemoryMappedPointer(); + } + /*! * \brief Gets the open mode of the stream * \return Reading/writing mode for the stream */ - inline OpenModeFlags Stream::GetOpenMode() const { return m_openMode; @@ -90,7 +101,6 @@ namespace Nz * \brief Gets the options of the stream * \return Options of the stream */ - inline StreamOptionFlags Stream::GetStreamOptions() const { return m_streamOptions; @@ -100,45 +110,46 @@ namespace Nz * \brief Checks whether the stream is readable * \return true if it is the case */ - inline bool Stream::IsBufferingEnabled() const { - return (m_streamOptions & StreamOption::Unbuffered) == 0; + return m_streamOptions.Test(StreamOption::Unbuffered); + } + + inline bool Stream::IsMemoryMapped() const + { + return m_streamOptions.Test(StreamOption::MemoryMapped); } inline bool Stream::IsReadable() const { - return (m_openMode & OpenMode::ReadOnly) != 0; + return m_openMode.Test(OpenMode::ReadOnly); } /*! * \brief Checks whether the stream is sequential * \return true if it is the case */ - inline bool Stream::IsSequential() const { - return (m_streamOptions & StreamOption::Sequential) != 0; + return m_streamOptions.Test(StreamOption::Sequential); } /*! * \brief Checks whether the stream has text mode enabled * \return true if it is the case */ - inline bool Stream::IsTextModeEnabled() const { - return (m_streamOptions & StreamOption::Text) != 0; + return m_streamOptions.Test(StreamOption::Text); } /*! * \brief Checks whether the stream can be written * \return true if it is the case */ - inline bool Stream::IsWritable() const { - return (m_openMode & OpenMode::WriteOnly) != 0; + return m_openMode.Test(OpenMode::WriteOnly); } /*! diff --git a/src/Nazara/Core/MemoryStream.cpp b/src/Nazara/Core/MemoryStream.cpp index 05310cd5e..0dca6926d 100644 --- a/src/Nazara/Core/MemoryStream.cpp +++ b/src/Nazara/Core/MemoryStream.cpp @@ -62,6 +62,11 @@ namespace Nz // Nothing to flush } + void* MemoryStream::GetMemoryMappedPointer() const + { + return m_buffer->GetBuffer(); + } + /*! * \brief Reads blocks * \return Number of blocks read diff --git a/src/Nazara/Core/MemoryView.cpp b/src/Nazara/Core/MemoryView.cpp index 012041081..11453fc70 100644 --- a/src/Nazara/Core/MemoryView.cpp +++ b/src/Nazara/Core/MemoryView.cpp @@ -42,13 +42,26 @@ namespace Nz */ MemoryView::MemoryView(const void* ptr, UInt64 size) : - Stream(StreamOption::None, OpenMode::ReadOnly), + Stream(StreamOption::MemoryMapped, OpenMode::ReadOnly), m_ptr(static_cast(const_cast(ptr))), //< Okay, right, const_cast is bad, but this pointer is still read-only m_pos(0), m_size(size) { } + /*! + * \brief Flushes the stream + */ + void MemoryView::FlushStream() + { + // Nothing to do + } + + void* MemoryView::GetMemoryMappedPointer() const + { + return m_ptr; + } + /*! * \brief Gets the size of the raw memory * \return Size of the memory @@ -59,15 +72,6 @@ namespace Nz return m_size; } - /*! - * \brief Flushes the stream - */ - - void MemoryView::FlushStream() - { - // Nothing to do - } - /*! * \brief Reads blocks * \return Number of blocks read @@ -100,15 +104,6 @@ namespace Nz return true; } - /*! - * \brief Gets the position of the cursor - * \return Position of the cursor - */ - UInt64 MemoryView::TellStreamCursor() const - { - return m_pos; - } - /*! * \brief Checks whether the stream reached the end of the stream * \return true if cursor is at the end of the stream @@ -118,6 +113,15 @@ namespace Nz return m_pos >= m_size; } + /*! + * \brief Gets the position of the cursor + * \return Position of the cursor + */ + UInt64 MemoryView::TellStreamCursor() const + { + return m_pos; + } + /*! * \brief Writes blocks * \return Number of blocks written diff --git a/src/Nazara/Core/Stream.cpp b/src/Nazara/Core/Stream.cpp index a28ce5604..102f739d5 100644 --- a/src/Nazara/Core/Stream.cpp +++ b/src/Nazara/Core/Stream.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -34,26 +35,6 @@ namespace Nz return TestStreamEnd(); } - /*! - * \brief Gets the directory of the stream - * \return Empty string (meant to be virtual) - */ - - std::filesystem::path Stream::GetDirectory() const - { - return {}; - } - - /*! - * \brief Gets the path of the stream - * \return Empty string (meant to be virtual) - */ - - std::filesystem::path Stream::GetPath() const - { - return {}; - } - UInt64 Stream::GetCursorPos() const { if (m_bufferCapacity == 0) @@ -65,6 +46,24 @@ namespace Nz } } + /*! + * \brief Gets the directory of the stream + * \return Empty string (meant to be virtual) + */ + std::filesystem::path Stream::GetDirectory() const + { + return {}; + } + + /*! + * \brief Gets the path of the stream + * \return Empty string (meant to be virtual) + */ + std::filesystem::path Stream::GetPath() const + { + return {}; + } + /*! * \brief Reads the stream and puts the result in a buffer * \return Size of the read @@ -264,17 +263,22 @@ namespace Nz #if defined(NAZARA_PLATFORM_WINDOWS) std::string temp(string); ReplaceStr(temp, "\n", "\r\n"); -#elif defined(NAZARA_PLATFORM_LINUX) || defined(NAZARA_PLATFORM_WEB) - std::string_view temp(string); - // Nothing to do + + string = temp; #elif defined(NAZARA_PLATFORM_MACOS) std::string temp(string); ReplaceStr(temp, "\n", "\r"); -#endif - return Write(temp.data(), temp.size()) == temp.size(); + string = temp; +#endif } - else - return Write(string.data(), string.size()) == string.size(); + + return Write(string.data(), string.size()) == string.size(); + } + + void* Stream::GetMemoryMappedPointer() const + { + NazaraError("Stream set the MemoryMapped option but did not implement GetMemoryMappedPointer"); + return nullptr; } }