BsDataStream.h 8.8 KB

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