Core/Stream: Add MemoryMapped stream options (allowing for direct memory access)
This commit is contained in:
parent
3000345eab
commit
34abeeb7bd
|
|
@ -228,6 +228,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
|
|
||||||
|
MemoryMapped,
|
||||||
Sequential,
|
Sequential,
|
||||||
Text,
|
Text,
|
||||||
Unbuffered,
|
Unbuffered,
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ namespace Nz
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void FlushStream() override;
|
void FlushStream() override;
|
||||||
|
void* GetMemoryMappedPointer() const override;
|
||||||
std::size_t ReadBlock(void* buffer, std::size_t size) override;
|
std::size_t ReadBlock(void* buffer, std::size_t size) override;
|
||||||
bool SeekStreamCursor(UInt64 offset) override;
|
bool SeekStreamCursor(UInt64 offset) override;
|
||||||
UInt64 TellStreamCursor() const override;
|
UInt64 TellStreamCursor() const override;
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ namespace Nz
|
||||||
* \brief Constructs a MemoryStream object by default
|
* \brief Constructs a MemoryStream object by default
|
||||||
*/
|
*/
|
||||||
inline MemoryStream::MemoryStream() :
|
inline MemoryStream::MemoryStream() :
|
||||||
Stream(StreamOption::None, OpenMode_ReadWrite),
|
Stream(StreamOption::MemoryMapped, OpenMode_ReadWrite),
|
||||||
m_pos(0)
|
m_pos(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,20 +18,21 @@ namespace Nz
|
||||||
MemoryView(void* ptr, UInt64 size);
|
MemoryView(void* ptr, UInt64 size);
|
||||||
MemoryView(const void* ptr, UInt64 size);
|
MemoryView(const void* ptr, UInt64 size);
|
||||||
MemoryView(const MemoryView&) = delete;
|
MemoryView(const MemoryView&) = delete;
|
||||||
MemoryView(MemoryView&&) = delete; ///TODO
|
MemoryView(MemoryView&&) noexcept = default;
|
||||||
~MemoryView() = default;
|
~MemoryView() = default;
|
||||||
|
|
||||||
UInt64 GetSize() const override;
|
UInt64 GetSize() const override;
|
||||||
|
|
||||||
MemoryView& operator=(const MemoryView&) = delete;
|
MemoryView& operator=(const MemoryView&) = delete;
|
||||||
MemoryView& operator=(MemoryView&&) = delete; ///TODO
|
MemoryView& operator=(MemoryView&&) noexcept = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void FlushStream() override;
|
void FlushStream() override;
|
||||||
|
void* GetMemoryMappedPointer() const override;
|
||||||
std::size_t ReadBlock(void* buffer, std::size_t size) override;
|
std::size_t ReadBlock(void* buffer, std::size_t size) override;
|
||||||
bool SeekStreamCursor(UInt64 offset) override;
|
bool SeekStreamCursor(UInt64 offset) override;
|
||||||
UInt64 TellStreamCursor() const override;
|
|
||||||
bool TestStreamEnd() const override;
|
bool TestStreamEnd() const override;
|
||||||
|
UInt64 TellStreamCursor() const override;
|
||||||
std::size_t WriteBlock(const void* buffer, std::size_t size) override;
|
std::size_t WriteBlock(const void* buffer, std::size_t size) override;
|
||||||
|
|
||||||
UInt8* m_ptr;
|
UInt8* m_ptr;
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
class AbstractHash;
|
||||||
class ByteArray;
|
class ByteArray;
|
||||||
|
|
||||||
class NAZARA_CORE_API Stream
|
class NAZARA_CORE_API Stream
|
||||||
|
|
@ -33,18 +34,20 @@ namespace Nz
|
||||||
|
|
||||||
inline void Flush();
|
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;
|
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;
|
virtual UInt64 GetSize() const = 0;
|
||||||
|
inline StreamOptionFlags GetStreamOptions() const;
|
||||||
|
|
||||||
std::size_t Read(void* buffer, std::size_t size);
|
std::size_t Read(void* buffer, std::size_t size);
|
||||||
virtual std::string ReadLine(unsigned int lineSize = 0);
|
virtual std::string ReadLine(unsigned int lineSize = 0);
|
||||||
|
|
||||||
inline bool IsBufferingEnabled() const;
|
inline bool IsBufferingEnabled() const;
|
||||||
|
inline bool IsMemoryMapped() const;
|
||||||
inline bool IsReadable() const;
|
inline bool IsReadable() const;
|
||||||
inline bool IsSequential() const;
|
inline bool IsSequential() const;
|
||||||
inline bool IsTextModeEnabled() const;
|
inline bool IsTextModeEnabled() const;
|
||||||
|
|
@ -65,6 +68,7 @@ namespace Nz
|
||||||
inline Stream(StreamOptionFlags streamOptions = StreamOption::None, OpenModeFlags openMode = OpenMode::NotOpen);
|
inline Stream(StreamOptionFlags streamOptions = StreamOption::None, OpenModeFlags openMode = OpenMode::NotOpen);
|
||||||
|
|
||||||
virtual void FlushStream() = 0;
|
virtual void FlushStream() = 0;
|
||||||
|
virtual void* GetMemoryMappedPointer() const;
|
||||||
virtual std::size_t ReadBlock(void* buffer, std::size_t size) = 0;
|
virtual std::size_t ReadBlock(void* buffer, std::size_t size) = 0;
|
||||||
virtual bool SeekStreamCursor(UInt64 offset) = 0;
|
virtual bool SeekStreamCursor(UInt64 offset) = 0;
|
||||||
virtual UInt64 TellStreamCursor() const = 0;
|
virtual UInt64 TellStreamCursor() const = 0;
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ namespace Nz
|
||||||
* \param streamOptions Options for the stream
|
* \param streamOptions Options for the stream
|
||||||
* \param openMode Reading/writing mode for the stream
|
* \param openMode Reading/writing mode for the stream
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline Stream::Stream(StreamOptionFlags streamOptions, OpenModeFlags openMode) :
|
inline Stream::Stream(StreamOptionFlags streamOptions, OpenModeFlags openMode) :
|
||||||
m_bufferCapacity(0),
|
m_bufferCapacity(0),
|
||||||
m_bufferOffset(0),
|
m_bufferOffset(0),
|
||||||
|
|
@ -32,12 +31,11 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param textMode Enables the mode or disables
|
* \param textMode Enables the mode or disables
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline void Stream::EnableBuffering(bool buffering, std::size_t bufferSize)
|
inline void Stream::EnableBuffering(bool buffering, std::size_t bufferSize)
|
||||||
{
|
{
|
||||||
if (buffering)
|
if (buffering)
|
||||||
{
|
{
|
||||||
m_streamOptions &= ~StreamOption::Unbuffered;
|
m_streamOptions.Clear(StreamOption::Unbuffered);
|
||||||
if (m_bufferCapacity != bufferSize)
|
if (m_bufferCapacity != bufferSize)
|
||||||
{
|
{
|
||||||
m_buffer = std::make_unique<UInt8[]>(bufferSize);
|
m_buffer = std::make_unique<UInt8[]>(bufferSize);
|
||||||
|
|
@ -49,7 +47,7 @@ namespace Nz
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_streamOptions |= StreamOption::Unbuffered;
|
m_streamOptions.Set(StreamOption::Unbuffered);
|
||||||
m_buffer.reset();
|
m_buffer.reset();
|
||||||
m_bufferCapacity = 0;
|
m_bufferCapacity = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -58,9 +56,9 @@ namespace Nz
|
||||||
inline void Stream::EnableTextMode(bool textMode)
|
inline void Stream::EnableTextMode(bool textMode)
|
||||||
{
|
{
|
||||||
if (textMode)
|
if (textMode)
|
||||||
m_streamOptions |= StreamOption::Text;
|
m_streamOptions.Set(StreamOption::Text);
|
||||||
else
|
else
|
||||||
m_streamOptions &= ~StreamOption::Text;
|
m_streamOptions.Clear(StreamOption::Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -76,11 +74,24 @@ namespace Nz
|
||||||
FlushStream();
|
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
|
* \brief Gets the open mode of the stream
|
||||||
* \return Reading/writing mode for the stream
|
* \return Reading/writing mode for the stream
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline OpenModeFlags Stream::GetOpenMode() const
|
inline OpenModeFlags Stream::GetOpenMode() const
|
||||||
{
|
{
|
||||||
return m_openMode;
|
return m_openMode;
|
||||||
|
|
@ -90,7 +101,6 @@ namespace Nz
|
||||||
* \brief Gets the options of the stream
|
* \brief Gets the options of the stream
|
||||||
* \return Options of the stream
|
* \return Options of the stream
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline StreamOptionFlags Stream::GetStreamOptions() const
|
inline StreamOptionFlags Stream::GetStreamOptions() const
|
||||||
{
|
{
|
||||||
return m_streamOptions;
|
return m_streamOptions;
|
||||||
|
|
@ -100,45 +110,46 @@ namespace Nz
|
||||||
* \brief Checks whether the stream is readable
|
* \brief Checks whether the stream is readable
|
||||||
* \return true if it is the case
|
* \return true if it is the case
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline bool Stream::IsBufferingEnabled() const
|
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
|
inline bool Stream::IsReadable() const
|
||||||
{
|
{
|
||||||
return (m_openMode & OpenMode::ReadOnly) != 0;
|
return m_openMode.Test(OpenMode::ReadOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Checks whether the stream is sequential
|
* \brief Checks whether the stream is sequential
|
||||||
* \return true if it is the case
|
* \return true if it is the case
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline bool Stream::IsSequential() const
|
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
|
* \brief Checks whether the stream has text mode enabled
|
||||||
* \return true if it is the case
|
* \return true if it is the case
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline bool Stream::IsTextModeEnabled() const
|
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
|
* \brief Checks whether the stream can be written
|
||||||
* \return true if it is the case
|
* \return true if it is the case
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline bool Stream::IsWritable() const
|
inline bool Stream::IsWritable() const
|
||||||
{
|
{
|
||||||
return (m_openMode & OpenMode::WriteOnly) != 0;
|
return m_openMode.Test(OpenMode::WriteOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,11 @@ namespace Nz
|
||||||
// Nothing to flush
|
// Nothing to flush
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* MemoryStream::GetMemoryMappedPointer() const
|
||||||
|
{
|
||||||
|
return m_buffer->GetBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Reads blocks
|
* \brief Reads blocks
|
||||||
* \return Number of blocks read
|
* \return Number of blocks read
|
||||||
|
|
|
||||||
|
|
@ -42,13 +42,26 @@ namespace Nz
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MemoryView::MemoryView(const void* ptr, UInt64 size) :
|
MemoryView::MemoryView(const void* ptr, UInt64 size) :
|
||||||
Stream(StreamOption::None, OpenMode::ReadOnly),
|
Stream(StreamOption::MemoryMapped, OpenMode::ReadOnly),
|
||||||
m_ptr(static_cast<UInt8*>(const_cast<void*>(ptr))), //< Okay, right, const_cast is bad, but this pointer is still read-only
|
m_ptr(static_cast<UInt8*>(const_cast<void*>(ptr))), //< Okay, right, const_cast is bad, but this pointer is still read-only
|
||||||
m_pos(0),
|
m_pos(0),
|
||||||
m_size(size)
|
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
|
* \brief Gets the size of the raw memory
|
||||||
* \return Size of the memory
|
* \return Size of the memory
|
||||||
|
|
@ -59,15 +72,6 @@ namespace Nz
|
||||||
return m_size;
|
return m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Flushes the stream
|
|
||||||
*/
|
|
||||||
|
|
||||||
void MemoryView::FlushStream()
|
|
||||||
{
|
|
||||||
// Nothing to do
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Reads blocks
|
* \brief Reads blocks
|
||||||
* \return Number of blocks read
|
* \return Number of blocks read
|
||||||
|
|
@ -100,15 +104,6 @@ namespace Nz
|
||||||
return true;
|
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
|
* \brief Checks whether the stream reached the end of the stream
|
||||||
* \return true if cursor is at 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;
|
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
|
* \brief Writes blocks
|
||||||
* \return Number of blocks written
|
* \return Number of blocks written
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include <Nazara/Core/ByteArray.hpp>
|
#include <Nazara/Core/ByteArray.hpp>
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
#include <Nazara/Core/StringExt.hpp>
|
#include <Nazara/Core/StringExt.hpp>
|
||||||
|
#include <Nazara/Utils/CallOnExit.hpp>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <Nazara/Core/Debug.hpp>
|
#include <Nazara/Core/Debug.hpp>
|
||||||
|
|
||||||
|
|
@ -34,26 +35,6 @@ namespace Nz
|
||||||
return TestStreamEnd();
|
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
|
UInt64 Stream::GetCursorPos() const
|
||||||
{
|
{
|
||||||
if (m_bufferCapacity == 0)
|
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
|
* \brief Reads the stream and puts the result in a buffer
|
||||||
* \return Size of the read
|
* \return Size of the read
|
||||||
|
|
@ -264,17 +263,22 @@ namespace Nz
|
||||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||||
std::string temp(string);
|
std::string temp(string);
|
||||||
ReplaceStr(temp, "\n", "\r\n");
|
ReplaceStr(temp, "\n", "\r\n");
|
||||||
#elif defined(NAZARA_PLATFORM_LINUX) || defined(NAZARA_PLATFORM_WEB)
|
|
||||||
std::string_view temp(string);
|
string = temp;
|
||||||
// Nothing to do
|
|
||||||
#elif defined(NAZARA_PLATFORM_MACOS)
|
#elif defined(NAZARA_PLATFORM_MACOS)
|
||||||
std::string temp(string);
|
std::string temp(string);
|
||||||
ReplaceStr(temp, "\n", "\r");
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue