BsDataStream.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsDataStream.h"
  4. #include "BsDebug.h"
  5. #include "BsException.h"
  6. #include <codecvt>
  7. namespace BansheeEngine
  8. {
  9. const UINT32 DataStream::StreamTempSize = 128;
  10. /**
  11. * @brief Checks does the provided buffer has an UTF32 byte order mark
  12. * in little endian order.
  13. */
  14. bool isUTF32LE(const UINT8* buffer)
  15. {
  16. return buffer[0] == 0xFF && buffer[1] == 0xFE && buffer[2] == 0x00 && buffer[3] == 0x00;
  17. }
  18. /**
  19. * @brief Checks does the provided buffer has an UTF32 byte order mark
  20. * in big endian order.
  21. */
  22. bool isUTF32BE(const UINT8* buffer)
  23. {
  24. return buffer[0] == 0x00 && buffer[1] == 0x00 && buffer[2] == 0xFE && buffer[3] == 0xFF;
  25. }
  26. /**
  27. * @brief Checks does the provided buffer has an UTF16 byte order mark
  28. * in little endian order.
  29. */
  30. bool isUTF16LE(const UINT8* buffer)
  31. {
  32. return buffer[0] == 0xFF && buffer[1] == 0xFE;
  33. }
  34. /**
  35. * @brief Checks does the provided buffer has an UTF16 byte order mark
  36. * in big endian order.
  37. */
  38. bool isUTF16BE(const UINT8* buffer)
  39. {
  40. return buffer[0] == 0xFE && buffer[1] == 0xFF;
  41. }
  42. /**
  43. * @brief Checks does the provided buffer has an UTF8 byte order mark.
  44. */
  45. bool isUTF8(const UINT8* buffer)
  46. {
  47. return (buffer[0] == 0xEF && buffer[1] == 0xBB && buffer[2] == 0xBF);
  48. }
  49. template <typename T> DataStream& DataStream::operator>> (T& val)
  50. {
  51. read(static_cast<void*>(&val), sizeof(T));
  52. return *this;
  53. }
  54. void DataStream::writeString(const String& string, StringEncoding encoding)
  55. {
  56. if (encoding == StringEncoding::UTF16)
  57. {
  58. const std::codecvt_mode convMode = (std::codecvt_mode)(std::generate_header);
  59. typedef std::codecvt_utf8_utf16<char, 1114111, convMode> UTF8ToUTF16Conv;
  60. std::wstring_convert<UTF8ToUTF16Conv, char> conversion("?");
  61. std::string encodedString = conversion.from_bytes(string.c_str());
  62. write(encodedString.data(), encodedString.length());
  63. }
  64. else
  65. {
  66. write(string.data(), string.length());
  67. }
  68. }
  69. void DataStream::writeString(const WString& string, StringEncoding encoding)
  70. {
  71. if (encoding == StringEncoding::UTF16)
  72. {
  73. const std::codecvt_mode convMode = (std::codecvt_mode)(std::generate_header | std::little_endian);
  74. typedef std::codecvt_utf16<wchar_t, 1114111, convMode> WCharToUTF16Conv;
  75. std::wstring_convert<WCharToUTF16Conv, wchar_t> conversion("?");
  76. std::string encodedString = conversion.to_bytes(string.c_str());
  77. write(encodedString.data(), encodedString.length());
  78. }
  79. else
  80. {
  81. const std::codecvt_mode convMode = (std::codecvt_mode)(std::generate_header);
  82. typedef std::codecvt_utf8<wchar_t, 1114111, convMode> WCharToUTF8Conv;
  83. std::wstring_convert<WCharToUTF8Conv, wchar_t> conversion("?");
  84. std::string encodedString = conversion.to_bytes(string.c_str());
  85. write(encodedString.data(), encodedString.length());
  86. }
  87. }
  88. String DataStream::getAsString()
  89. {
  90. // Read the entire buffer - ideally in one read, but if the size of
  91. // the buffer is unknown, do multiple fixed size reads.
  92. size_t bufSize = (mSize > 0 ? mSize : 4096);
  93. std::stringstream::char_type* tempBuffer = (std::stringstream::char_type*)bs_alloc((UINT32)bufSize);
  94. // Ensure read from begin of stream
  95. seek(0);
  96. std::stringstream result;
  97. while (!eof())
  98. {
  99. size_t numReadBytes = read(tempBuffer, bufSize);
  100. result.write(tempBuffer, numReadBytes);
  101. }
  102. free(tempBuffer);
  103. std::string string = result.str();
  104. UINT32 readBytes = (UINT32)string.size();
  105. if (readBytes >= 4)
  106. {
  107. if (isUTF32LE((UINT8*)string.data()))
  108. {
  109. const std::codecvt_mode convMode = (std::codecvt_mode)(std::consume_header | std::little_endian);
  110. typedef std::codecvt_utf8<UINT32, 1114111, convMode> utf8utf32;
  111. std::wstring_convert<utf8utf32, UINT32> conversion("?");
  112. UINT32* start = (UINT32*)string.data();
  113. UINT32* end = (start + (string.size() - 1) / 4);
  114. return conversion.to_bytes(start, end).c_str();
  115. }
  116. else if (isUTF32BE((UINT8*)string.data()))
  117. {
  118. const std::codecvt_mode convMode = (std::codecvt_mode)(std::consume_header);
  119. typedef std::codecvt_utf8<UINT32, 1114111, convMode> utf8utf32;
  120. std::wstring_convert<utf8utf32, UINT32> conversion("?");
  121. UINT32* start = (UINT32*)string.data();
  122. UINT32* end = (start + (string.size() - 1) / 4);
  123. return conversion.to_bytes(start, end).c_str();
  124. }
  125. }
  126. if (readBytes >= 3)
  127. {
  128. if (isUTF8((UINT8*)string.data()))
  129. {
  130. return string.c_str() + 3;
  131. }
  132. }
  133. if (readBytes >= 2)
  134. {
  135. if (isUTF16LE((UINT8*)string.data()))
  136. {
  137. const std::codecvt_mode convMode = (std::codecvt_mode)(std::little_endian);
  138. typedef std::codecvt_utf8_utf16<UINT16, 1114111, convMode> utf8utf16;
  139. std::wstring_convert<utf8utf16, UINT16> conversion("?");
  140. UINT16* start = (UINT16*)(string.c_str() + 2); // Bug?: std::consume_header seems to be ignored so I manually remove the header
  141. return conversion.to_bytes(start).c_str();
  142. }
  143. else if (isUTF16BE((UINT8*)string.data()))
  144. {
  145. const std::codecvt_mode convMode = (std::codecvt_mode)(0);
  146. typedef std::codecvt_utf8_utf16<UINT16, 1114111, convMode> utf8utf16;
  147. // Bug?: Regardless of not providing the std::little_endian flag it seems that is how the data is read
  148. // so I manually flip it
  149. UINT32 numChars = (UINT32)(string.size() - 2) / 2;
  150. for (UINT32 i = 0; i < numChars; i++)
  151. std::swap(string[i * 2 + 0], string[i * 2 + 1]);
  152. std::wstring_convert<utf8utf16, UINT16> conversion("?");
  153. UINT16* start = (UINT16*)(string.c_str() + 2); // Bug?: std::consume_header seems to be ignored so I manually remove the header
  154. return conversion.to_bytes(start).c_str();
  155. }
  156. }
  157. return string.c_str();
  158. }
  159. WString DataStream::getAsWString()
  160. {
  161. // Read the entire buffer - ideally in one read, but if the size of
  162. // the buffer is unknown, do multiple fixed size reads.
  163. size_t bufSize = (mSize > 0 ? mSize : 4096);
  164. std::stringstream::char_type* tempBuffer = (std::stringstream::char_type*)bs_alloc((UINT32)bufSize);
  165. // Ensure read from begin of stream
  166. seek(0);
  167. std::stringstream result;
  168. while (!eof())
  169. {
  170. size_t numReadBytes = read(tempBuffer, bufSize);
  171. result.write(tempBuffer, numReadBytes);
  172. }
  173. free(tempBuffer);
  174. std::string string = result.str();
  175. UINT32 readBytes = (UINT32)string.size();
  176. if (readBytes >= 4)
  177. {
  178. if (isUTF32LE((UINT8*)string.data()))
  179. {
  180. // Not supported
  181. }
  182. else if (isUTF32BE((UINT8*)string.data()))
  183. {
  184. // Not supported
  185. }
  186. }
  187. if (readBytes >= 3)
  188. {
  189. if (isUTF8((UINT8*)string.data()))
  190. {
  191. const std::codecvt_mode convMode = (std::codecvt_mode)(std::consume_header);
  192. typedef std::codecvt_utf8<wchar_t, 1114111, convMode> wcharutf8;
  193. std::wstring_convert<wcharutf8> conversion("?");
  194. return conversion.from_bytes(string).c_str();
  195. }
  196. }
  197. if (readBytes >= 2)
  198. {
  199. if (isUTF16LE((UINT8*)string.data()))
  200. {
  201. const std::codecvt_mode convMode = (std::codecvt_mode)(std::consume_header | std::little_endian);
  202. typedef std::codecvt_utf16<wchar_t, 1114111, convMode> wcharutf16;
  203. std::wstring_convert<wcharutf16> conversion("?");
  204. return conversion.from_bytes(string).c_str();
  205. }
  206. else if (isUTF16BE((UINT8*)string.data()))
  207. {
  208. const std::codecvt_mode convMode = (std::codecvt_mode)(std::consume_header);
  209. typedef std::codecvt_utf16<wchar_t, 1114111, convMode> wcharutf16;
  210. std::wstring_convert<wcharutf16> conversion("?");
  211. return conversion.from_bytes(string).c_str();
  212. }
  213. }
  214. {
  215. const std::codecvt_mode convMode = (std::codecvt_mode)(std::consume_header);
  216. typedef std::codecvt_utf8<wchar_t, 1114111, convMode> wcharutf8;
  217. std::wstring_convert<wcharutf8> conversion("?");
  218. return conversion.from_bytes(string).c_str();
  219. }
  220. }
  221. MemoryDataStream::MemoryDataStream(void* memory, size_t inSize)
  222. : DataStream(READ | WRITE), mData(nullptr)
  223. {
  224. mData = mPos = static_cast<UINT8*>(memory);
  225. mSize = inSize;
  226. mEnd = mData + mSize;
  227. assert(mEnd >= mPos);
  228. }
  229. MemoryDataStream::MemoryDataStream(DataStream& sourceStream)
  230. : DataStream(READ | WRITE), mData(nullptr)
  231. {
  232. // Copy data from incoming stream
  233. mSize = sourceStream.size();
  234. mData = (UINT8*)bs_alloc((UINT32)mSize);
  235. mPos = mData;
  236. mEnd = mData + sourceStream.read(mData, mSize);
  237. assert(mEnd >= mPos);
  238. }
  239. MemoryDataStream::MemoryDataStream(const DataStreamPtr& sourceStream)
  240. :DataStream(READ | WRITE), mData(nullptr)
  241. {
  242. // Copy data from incoming stream
  243. mSize = sourceStream->size();
  244. mData = (UINT8*)bs_alloc((UINT32)mSize);
  245. mPos = mData;
  246. mEnd = mData + sourceStream->read(mData, mSize);
  247. assert(mEnd >= mPos);
  248. }
  249. MemoryDataStream::~MemoryDataStream()
  250. {
  251. close();
  252. }
  253. size_t MemoryDataStream::read(void* buf, size_t count)
  254. {
  255. size_t cnt = count;
  256. if (mPos + cnt > mEnd)
  257. cnt = mEnd - mPos;
  258. if (cnt == 0)
  259. return 0;
  260. assert (cnt <= count);
  261. memcpy(buf, mPos, cnt);
  262. mPos += cnt;
  263. return cnt;
  264. }
  265. size_t MemoryDataStream::write(const void* buf, size_t count)
  266. {
  267. size_t written = 0;
  268. if (isWriteable())
  269. {
  270. written = count;
  271. if (mPos + written > mEnd)
  272. written = mEnd - mPos;
  273. if (written == 0)
  274. return 0;
  275. memcpy(mPos, buf, written);
  276. mPos += written;
  277. }
  278. return written;
  279. }
  280. void MemoryDataStream::skip(size_t count)
  281. {
  282. size_t newpos = (size_t)( (mPos - mData) + count );
  283. assert(mData + newpos <= mEnd);
  284. mPos = mData + newpos;
  285. }
  286. void MemoryDataStream::seek(size_t pos)
  287. {
  288. assert(mData + pos <= mEnd);
  289. mPos = mData + pos;
  290. }
  291. size_t MemoryDataStream::tell() const
  292. {
  293. return mPos - mData;
  294. }
  295. bool MemoryDataStream::eof() const
  296. {
  297. return mPos >= mEnd;
  298. }
  299. void MemoryDataStream::close()
  300. {
  301. if (mData != nullptr)
  302. {
  303. bs_free(mData);
  304. mData = nullptr;
  305. }
  306. }
  307. FileDataStream::FileDataStream(std::shared_ptr<std::ifstream> s, bool freeOnClose)
  308. : DataStream(READ), mpInStream(s), mpFStreamRO(s), mpFStream(0), mFreeOnClose(freeOnClose)
  309. {
  310. mpInStream->seekg(0, std::ios_base::end);
  311. mSize = (size_t)mpInStream->tellg();
  312. mpInStream->seekg(0, std::ios_base::beg);
  313. determineAccess();
  314. }
  315. FileDataStream::FileDataStream(std::shared_ptr<std::ifstream> s, size_t inSize, bool freeOnClose)
  316. : DataStream(READ), mpInStream(s), mpFStreamRO(s), mpFStream(0), mFreeOnClose(freeOnClose)
  317. {
  318. mSize = inSize;
  319. determineAccess();
  320. }
  321. FileDataStream::FileDataStream(std::shared_ptr<std::fstream> s, bool freeOnClose)
  322. : DataStream(READ | WRITE), mpInStream(s), mpFStreamRO(0), mpFStream(s), mFreeOnClose(freeOnClose)
  323. {
  324. mpInStream->seekg(0, std::ios_base::end);
  325. mSize = (size_t)mpInStream->tellg();
  326. mpInStream->seekg(0, std::ios_base::beg);
  327. determineAccess();
  328. }
  329. FileDataStream::FileDataStream(std::shared_ptr<std::fstream> s, size_t inSize, bool freeOnClose)
  330. : DataStream(READ | WRITE), mpInStream(s), mpFStreamRO(0), mpFStream(s), mFreeOnClose(freeOnClose)
  331. {
  332. mSize = inSize;
  333. determineAccess();
  334. }
  335. void FileDataStream::determineAccess()
  336. {
  337. mAccess = 0;
  338. if (mpInStream)
  339. mAccess |= READ;
  340. if (mpFStream)
  341. mAccess |= WRITE;
  342. }
  343. FileDataStream::~FileDataStream()
  344. {
  345. close();
  346. }
  347. size_t FileDataStream::read(void* buf, size_t count)
  348. {
  349. mpInStream->read(static_cast<char*>(buf), static_cast<std::streamsize>(count));
  350. return (size_t)mpInStream->gcount();
  351. }
  352. size_t FileDataStream::write(const void* buf, size_t count)
  353. {
  354. size_t written = 0;
  355. if (isWriteable() && mpFStream)
  356. {
  357. mpFStream->write(static_cast<const char*>(buf), static_cast<std::streamsize>(count));
  358. written = count;
  359. }
  360. return written;
  361. }
  362. void FileDataStream::skip(size_t count)
  363. {
  364. mpInStream->clear(); // Clear fail status in case eof was set
  365. mpInStream->seekg(static_cast<std::ifstream::pos_type>(count), std::ios::cur);
  366. }
  367. void FileDataStream::seek(size_t pos)
  368. {
  369. mpInStream->clear(); // Clear fail status in case eof was set
  370. mpInStream->seekg(static_cast<std::streamoff>(pos), std::ios::beg);
  371. }
  372. size_t FileDataStream::tell() const
  373. {
  374. mpInStream->clear(); // Clear fail status in case eof was set
  375. return (size_t)mpInStream->tellg();
  376. }
  377. bool FileDataStream::eof() const
  378. {
  379. return mpInStream->eof();
  380. }
  381. void FileDataStream::close()
  382. {
  383. if (mpInStream)
  384. {
  385. if (mpFStreamRO)
  386. mpFStreamRO->close();
  387. if (mpFStream)
  388. {
  389. mpFStream->flush();
  390. mpFStream->close();
  391. }
  392. if (mFreeOnClose)
  393. {
  394. mpInStream = nullptr;
  395. mpFStreamRO = nullptr;
  396. mpFStream = nullptr;
  397. }
  398. }
  399. }
  400. }