1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
3 | #pragma once |
4 | |
5 | #include "Prerequisites/BsPrerequisitesUtil.h" |
6 | #include <istream> |
7 | |
8 | namespace bs |
9 | { |
10 | /** @addtogroup Filesystem |
11 | * @{ |
12 | */ |
13 | |
14 | /** Supported encoding types for strings. */ |
15 | enum class StringEncoding |
16 | { |
17 | UTF8 = 1, |
18 | UTF16 = 2 |
19 | }; |
20 | |
21 | /** |
22 | * General purpose class used for encapsulating the reading and writing of data from and to various sources using a |
23 | * common interface. |
24 | */ |
25 | class BS_UTILITY_EXPORT DataStream |
26 | { |
27 | public: |
28 | enum AccessMode |
29 | { |
30 | READ = 1, |
31 | WRITE = 2 |
32 | }; |
33 | |
34 | public: |
35 | /** Creates an unnamed stream. */ |
36 | DataStream(UINT16 accessMode = READ) |
37 | : mAccess(accessMode) |
38 | { } |
39 | |
40 | /** Creates a named stream. */ |
41 | DataStream(const String& name, UINT16 accessMode = READ) |
42 | :mName(name), mAccess(accessMode) {} |
43 | |
44 | virtual ~DataStream() = default; |
45 | |
46 | const String& getName() const { return mName; } |
47 | UINT16 getAccessMode() const { return mAccess; } |
48 | |
49 | virtual bool isReadable() const { return (mAccess & READ) != 0; } |
50 | virtual bool isWriteable() const { return (mAccess & WRITE) != 0; } |
51 | virtual bool isFile() const = 0; |
52 | |
53 | /** Reads data from the buffer and copies it to the specified value. */ |
54 | template<typename T> DataStream& operator>>(T& val); |
55 | |
56 | /** |
57 | * Read the requisite number of bytes from the stream, stopping at the end of the file. Advances |
58 | * the read pointer. |
59 | * |
60 | * @param[in] buf Pre-allocated buffer to read the data into. |
61 | * @param[in] count Number of bytes to read. |
62 | * @return Number of bytes actually read. |
63 | * |
64 | * @note Stream must be created with READ access mode. |
65 | */ |
66 | virtual size_t read(void* buf, size_t count) = 0; |
67 | |
68 | /** |
69 | * Write the requisite number of bytes to the stream and advance the write pointer. |
70 | * |
71 | * @param[in] buf Buffer containing bytes to write. |
72 | * @param[in] count Number of bytes to write. |
73 | * @return Number of bytes actually written. |
74 | * |
75 | * @note Stream must be created with WRITE access mode. |
76 | */ |
77 | virtual size_t write(const void* buf, size_t count) { return 0; } |
78 | |
79 | /** |
80 | * Writes the provided narrow string to the steam. String is convered to the required encoding before being written. |
81 | * |
82 | * @param[in] string String containing narrow characters to write, encoded as UTF8. |
83 | * @param[in] encoding Encoding to convert the string to before writing. |
84 | */ |
85 | virtual void writeString(const String& string, StringEncoding encoding = StringEncoding::UTF8); |
86 | |
87 | /** |
88 | * Writes the provided wide string to the steam. String is convered to the required encoding before being written. |
89 | * |
90 | * @param[in] string String containing wide characters to write, encoded as specified by platform for |
91 | * wide characters. |
92 | * @param[in] encoding Encoding to convert the string to before writing. |
93 | */ |
94 | virtual void writeString(const WString& string, StringEncoding encoding = StringEncoding::UTF8); |
95 | |
96 | /** |
97 | * Returns a string containing the entire stream. |
98 | * |
99 | * @return String data encoded as UTF-8. |
100 | * |
101 | * @note This is a convenience method for text streams only, allowing you to retrieve a String object containing |
102 | * all the data in the stream. |
103 | */ |
104 | virtual String getAsString(); |
105 | |
106 | /** |
107 | * Returns a wide string containing the entire stream. |
108 | * |
109 | * @return Wide string encoded as specified by current platform. |
110 | * |
111 | * @note This is a convenience method for text streams only, allowing you to retrieve a WString object |
112 | * containing all the data in the stream. |
113 | */ |
114 | virtual WString getAsWString(); |
115 | |
116 | /** |
117 | * Skip a defined number of bytes. This can also be a negative value, in which case the file pointer rewinds a |
118 | * defined number of bytes. |
119 | */ |
120 | virtual void skip(size_t count) = 0; |
121 | |
122 | /** Repositions the read point to a specified byte. */ |
123 | virtual void seek(size_t pos) = 0; |
124 | |
125 | /** Returns the current byte offset from beginning. */ |
126 | virtual size_t tell() const = 0; |
127 | |
128 | /** Returns true if the stream has reached the end. */ |
129 | virtual bool eof() const = 0; |
130 | |
131 | /** Returns the total size of the data to be read from the stream, or 0 if this is indeterminate for this stream. */ |
132 | size_t size() const { return mSize; } |
133 | |
134 | /** |
135 | * Creates a copy of this stream. |
136 | * |
137 | * @param[in] copyData If true the internal stream data will be copied as well, otherwise it will just |
138 | * reference the data from the original stream (in which case the caller must ensure the |
139 | * original stream outlives the clone). This is not relevant for file streams. |
140 | */ |
141 | virtual SPtr<DataStream> clone(bool copyData = true) const = 0; |
142 | |
143 | /** Close the stream. This makes further operations invalid. */ |
144 | virtual void close() = 0; |
145 | |
146 | protected: |
147 | static const UINT32 StreamTempSize; |
148 | |
149 | String mName; |
150 | size_t mSize = 0; |
151 | UINT16 mAccess; |
152 | }; |
153 | |
154 | /** Data stream for handling data from memory. */ |
155 | class BS_UTILITY_EXPORT MemoryDataStream : public DataStream |
156 | { |
157 | public: |
158 | /** |
159 | * Allocates a new chunk of memory and wraps it in a stream. |
160 | * |
161 | * @param[in] size Size of the memory chunk in bytes. |
162 | */ |
163 | MemoryDataStream(size_t size); |
164 | |
165 | /** |
166 | * Wrap an existing memory chunk in a stream. |
167 | * |
168 | * @param[in] memory Memory to wrap the data stream around. |
169 | * @param[in] size Size of the memory chunk in bytes. |
170 | * @param[in] freeOnClose Should the memory buffer be freed when the data stream goes out of scope. |
171 | */ |
172 | MemoryDataStream(void* memory, size_t size, bool freeOnClose = true); |
173 | |
174 | /** |
175 | * Create a stream which pre-buffers the contents of another stream. Data from the other buffer will be entirely |
176 | * read and stored in an internal buffer. |
177 | * |
178 | * @param[in] sourceStream Stream to read data from. |
179 | */ |
180 | MemoryDataStream(DataStream& sourceStream); |
181 | |
182 | /** |
183 | * Create a stream which pre-buffers the contents of another stream. Data from the other buffer will be entirely |
184 | * read and stored in an internal buffer. |
185 | * |
186 | * @param[in] sourceStream Stream to read data from. |
187 | */ |
188 | MemoryDataStream(const SPtr<DataStream>& sourceStream); |
189 | |
190 | ~MemoryDataStream(); |
191 | |
192 | bool isFile() const override { return false; } |
193 | |
194 | /** Get a pointer to the start of the memory block this stream holds. */ |
195 | UINT8* getPtr() const { return mData; } |
196 | |
197 | /** Get a pointer to the current position in the memory block this stream holds. */ |
198 | UINT8* getCurrentPtr() const { return mPos; } |
199 | |
200 | /** @copydoc DataStream::read */ |
201 | size_t read(void* buf, size_t count) override; |
202 | |
203 | /** @copydoc DataStream::write */ |
204 | size_t write(const void* buf, size_t count) override; |
205 | |
206 | /** @copydoc DataStream::skip */ |
207 | void skip(size_t count) override; |
208 | |
209 | /** @copydoc DataStream::seek */ |
210 | void seek(size_t pos) override; |
211 | |
212 | /** @copydoc DataStream::tell */ |
213 | size_t tell() const override; |
214 | |
215 | /** @copydoc DataStream::eof */ |
216 | bool eof() const override; |
217 | |
218 | /** @copydoc DataStream::clone */ |
219 | SPtr<DataStream> clone(bool copyData = true) const override; |
220 | |
221 | /** @copydoc DataStream::close */ |
222 | void close() override; |
223 | |
224 | protected: |
225 | UINT8* mData; |
226 | UINT8* mPos; |
227 | UINT8* mEnd; |
228 | |
229 | bool mFreeOnClose; |
230 | }; |
231 | |
232 | /** Data stream for handling data from standard streams. */ |
233 | class BS_UTILITY_EXPORT FileDataStream : public DataStream |
234 | { |
235 | public: |
236 | /** |
237 | * Construct a file stream. |
238 | * |
239 | * @param[in] filePath Path of the file to open. |
240 | * @param[in] accessMode Determines should the file be opened in read, write or read/write mode. |
241 | * @param[in] freeOnClose Determines should the internal stream be freed once the data stream is closed or goes |
242 | * out of scope. |
243 | */ |
244 | FileDataStream(const Path& filePath, AccessMode accessMode = READ, bool freeOnClose = true); |
245 | |
246 | ~FileDataStream(); |
247 | |
248 | bool isFile() const override { return true; } |
249 | |
250 | /** @copydoc DataStream::read */ |
251 | size_t read(void* buf, size_t count) override; |
252 | |
253 | /** @copydoc DataStream::write */ |
254 | size_t write(const void* buf, size_t count) override; |
255 | |
256 | /** @copydoc DataStream::skip */ |
257 | void skip(size_t count) override; |
258 | |
259 | /** @copydoc DataStream::seek */ |
260 | void seek(size_t pos) override; |
261 | |
262 | /** @copydoc DataStream::tell */ |
263 | size_t tell() const override; |
264 | |
265 | /** @copydoc DataStream::eof */ |
266 | bool eof() const override; |
267 | |
268 | /** @copydoc DataStream::clone */ |
269 | SPtr<DataStream> clone(bool copyData = true) const override; |
270 | |
271 | /** @copydoc DataStream::close */ |
272 | void close() override; |
273 | |
274 | /** Returns the path of the file opened by the stream. */ |
275 | const Path& getPath() const { return mPath; } |
276 | |
277 | protected: |
278 | Path mPath; |
279 | SPtr<std::istream> mInStream; |
280 | SPtr<std::ifstream> mFStreamRO; |
281 | SPtr<std::fstream> mFStream; |
282 | bool mFreeOnClose; |
283 | }; |
284 | |
285 | /** @} */ |
286 | } |
287 | |
288 | |