DotNetDupe 4.0.6
C++17/20 Implementation of the .NET Base Class Library (BCL)
Loading...
Searching...
No Matches
MemoryStream.cpp
Go to the documentation of this file.
1#include "pch.h"
6#include <vector>
7#include <algorithm>
8#include <cstring>
9
10namespace DotNetDupe {
11 namespace System {
12 namespace IO {
13
14 struct MemoryStream::MemoryStreamImpl {
15 std::vector<char> m_buffer;
16 long m_position;
17 bool m_writable;
18 bool m_disposed;
19
20 MemoryStreamImpl() : m_position(0), m_writable(true), m_disposed(false) {}
21 MemoryStreamImpl(bool writable) : m_position(0), m_writable(writable), m_disposed(false) {}
22 };
23
24 MemoryStream::MemoryStream() : m_pImpl(new MemoryStreamImpl()) {}
25
26 MemoryStream::MemoryStream(const Array<char>& buffer) : m_pImpl(new MemoryStreamImpl()) {
28 m_pImpl->m_buffer.assign(buffer.GetData(), buffer.GetData() + buffer.GetLength());
29 }
30
31 MemoryStream::MemoryStream(const Array<char>& buffer, bool writable) : m_pImpl(new MemoryStreamImpl(writable)) {
33 m_pImpl->m_buffer.assign(buffer.GetData(), buffer.GetData() + buffer.GetLength());
34 }
35
38 Dispose();
39 delete m_pImpl;
40 }
41
42 bool MemoryStream::CanRead() const {
43 return !m_pImpl->m_disposed;
44 }
45
46 bool MemoryStream::CanSeek() const {
47 return !m_pImpl->m_disposed;
48 }
49
51 return m_pImpl->m_writable && !m_pImpl->m_disposed;
52 }
53
56 if (m_pImpl->m_disposed) throw IOException("Stream is closed.");
57 return static_cast<long>(m_pImpl->m_buffer.size());
58 }
59
62 if (m_pImpl->m_disposed) throw IOException("Stream is closed.");
63 return m_pImpl->m_position;
64 }
65
66 void MemoryStream::SetPosition(long value) {
68 if (m_pImpl->m_disposed) throw IOException("Stream is closed.");
69 if (value < 0) throw ArgumentOutOfRangeException("position");
70
71 m_pImpl->m_position = value;
72 }
73
76 }
77
78 int MemoryStream::Read(char* buffer, int offset, int count) {
80 if (m_pImpl->m_disposed) throw IOException("Stream is closed.");
81 if (buffer == nullptr) throw ArgumentNullException("buffer");
82 if (offset < 0 || count < 0) throw ArgumentOutOfRangeException("offset or count");
83
85 long remaining = GetLength() - m_pImpl->m_position;
86 if (remaining <= 0) return 0;
87
89 int toRead = static_cast<int>((std::min)(static_cast<long>(count), remaining));
90 std::memcpy(buffer + offset, m_pImpl->m_buffer.data() + m_pImpl->m_position, toRead);
91 m_pImpl->m_position += toRead;
92 return toRead;
93 }
94
96 static long CalculateSeekPosition(long currentPos, long length, long offset, int origin) {
97 if (origin == 0) return offset;
98 if (origin == 1) return currentPos + offset;
99 if (origin == 2) return length + offset;
100 throw ArgumentException("Invalid seek origin.");
101 }
102
103 long MemoryStream::Seek(long offset, int origin) {
105 if (m_pImpl->m_disposed) throw IOException("Stream is closed.");
106
108 long newPosition = CalculateSeekPosition(m_pImpl->m_position, GetLength(), offset, origin);
109 if (newPosition < 0) throw IOException("An attempt was made to move the file pointer before the beginning of the file.");
110
111 m_pImpl->m_position = newPosition;
112 return m_pImpl->m_position;
113 }
114
115 void MemoryStream::SetLength(long value) {
117 if (m_pImpl->m_disposed) throw IOException("Stream is closed.");
118 if (!m_pImpl->m_writable) throw IOException("Stream is not writable.");
119 if (value < 0) throw ArgumentOutOfRangeException("value");
120
122 m_pImpl->m_buffer.resize(static_cast<size_t>(value), 0);
123 if (m_pImpl->m_position > value) {
124 m_pImpl->m_position = value;
125 }
126 }
127
128 void MemoryStream::Write(const char* buffer, int offset, int count) {
130 if (m_pImpl->m_disposed) throw IOException("Stream is closed.");
131 if (!m_pImpl->m_writable) throw IOException("Stream is not writable.");
132 if (buffer == nullptr) throw ArgumentNullException("buffer");
133 if (offset < 0 || count < 0) throw ArgumentOutOfRangeException("offset or count");
134
136 long requiredSize = m_pImpl->m_position + count;
137 if (requiredSize > GetLength()) {
138 m_pImpl->m_buffer.resize(static_cast<size_t>(requiredSize));
139 }
140
142 std::memcpy(m_pImpl->m_buffer.data() + m_pImpl->m_position, buffer + offset, count);
143 m_pImpl->m_position += count;
144 }
145
148 m_pImpl->m_disposed = true;
149 }
150
153 int size = static_cast<int>(m_pImpl->m_buffer.size());
154 Array<char> arr(size);
155 if (size > 0) {
156 std::memcpy(arr.GetData(), m_pImpl->m_buffer.data(), size);
157 }
158 return arr;
159 }
160 }
161 }
162}
Defines the exception thrown when a null reference is passed to a method that does not accept it.
Defines the exception thrown when an argument value is outside the acceptable range of values.
The exception that is thrown when an I/O error occurs.
ArgumentException(const String &sMessage)
Initializes a new instance of the ArgumentException class with a specified error message.
ArgumentNullException(const String &sMessage)
Initializes a new instance of the ArgumentNullException class with a specified error message.
ArgumentOutOfRangeException(const String &sMessage)
Initializes a new instance of the ArgumentOutOfRangeException class with a specified error message.
Provides methods for creating, manipulating, searching, and sorting arrays, thereby serving as the ba...
Definition Array.h:29
int GetLength() const
Gets the total number of elements in all dimensions of the Array.
Definition Array.h:142
T * GetData()
Gets a pointer to the contiguous internal element buffer.
Definition Array.h:146
IOException()
Initializes a new instance of the IOException class with a default message.
Definition Exception.cpp:56
void SetLength(long value) override
Sets the length of the current stream to the specified value.
~MemoryStream()
Destructor releasing encapsulated memory resources.
int Read(char *buffer, int offset, int count) override
Reads a block of bytes from the current stream and writes the data to a buffer.
long GetPosition() const override
Gets the current position within the stream.
bool CanSeek() const override
Gets a value indicating whether the current stream supports seeking.
void Flush() override
Overrides the Flush method so that no action is performed.
void Dispose() override
Releases the unmanaged resources used by the MemoryStream.
void SetPosition(long value) override
Sets the current position within the stream.
bool CanRead() const override
Gets a value indicating whether the current stream supports reading.
long Seek(long offset, int origin) override
Sets the position within the current stream to the specified value.
long GetLength() const override
Returns the length of the stream in bytes.
Array< char > ToArray() const
Writes the stream contents to a byte array, regardless of the Position property.
void Write(const char *buffer, int offset, int count) override
Writes a block of bytes to the current stream using data read from a buffer.
MemoryStream()
Initializes a new non-resizable instance of the MemoryStream class with an expandable capacity initia...
bool CanWrite() const override
Gets a value indicating whether the current stream supports writing.
static long CalculateSeekPosition(long currentPos, long length, long offset, int origin)
Calculate new absolute position from origin and offset.