BsFileSerializer.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsFileSerializer.h"
  4. #include "BsException.h"
  5. #include "BsIReflectable.h"
  6. #include "BsBinarySerializer.h"
  7. #include "BsFileSystem.h"
  8. #include "BsDebug.h"
  9. #include <numeric>
  10. using namespace std::placeholders;
  11. namespace BansheeEngine
  12. {
  13. FileEncoder::FileEncoder(const Path& fileLocation)
  14. :mWriteBuffer(nullptr)
  15. {
  16. mWriteBuffer = (UINT8*)bs_alloc(WRITE_BUFFER_SIZE);
  17. Path parentDir = fileLocation.getDirectory();
  18. if (!FileSystem::exists(parentDir))
  19. FileSystem::createDir(parentDir);
  20. mOutputStream.open(fileLocation.toString().c_str(), std::ios::out | std::ios::binary);
  21. if (mOutputStream.fail())
  22. {
  23. LOGWRN("Failed to save file: \"" + fileLocation.toString() + "\". Error: " + strerror(errno) + ".");
  24. }
  25. }
  26. FileEncoder::~FileEncoder()
  27. {
  28. bs_free(mWriteBuffer);
  29. mOutputStream.close();
  30. mOutputStream.clear();
  31. }
  32. void FileEncoder::encode(IReflectable* object)
  33. {
  34. if (object == nullptr)
  35. return;
  36. UINT64 curPos = (UINT64)mOutputStream.tellp();
  37. mOutputStream.seekp(sizeof(UINT32), std::ios_base::cur);
  38. BinarySerializer bs;
  39. UINT32 totalBytesWritten = 0;
  40. bs.encode(object, mWriteBuffer, WRITE_BUFFER_SIZE, &totalBytesWritten, std::bind(&FileEncoder::flushBuffer, this, _1, _2, _3));
  41. mOutputStream.seekp(curPos);
  42. mOutputStream.write((char*)&totalBytesWritten, sizeof(totalBytesWritten));
  43. mOutputStream.seekp(totalBytesWritten, std::ios_base::cur);
  44. }
  45. UINT8* FileEncoder::flushBuffer(UINT8* bufferStart, UINT32 bytesWritten, UINT32& newBufferSize)
  46. {
  47. mOutputStream.write((const char*)bufferStart, bytesWritten);
  48. return bufferStart;
  49. }
  50. FileDecoder::FileDecoder(const Path& fileLocation)
  51. {
  52. mInputStream.open(fileLocation.toString().c_str(), std::ios::in | std::ios::ate | std::ios::binary);
  53. if (mInputStream.fail())
  54. {
  55. LOGWRN("Failed to open file: \"" + fileLocation.toString() + "\". Error: " + strerror(errno) + ".");
  56. }
  57. std::streamoff fileSize = mInputStream.tellg();
  58. if (fileSize > std::numeric_limits<UINT32>::max())
  59. {
  60. BS_EXCEPT(InternalErrorException,
  61. "File size is larger that UINT32 can hold. Ask a programmer to use a bigger data type.");
  62. }
  63. mInputStream.seekg(0, std::ios::beg);
  64. }
  65. FileDecoder::~FileDecoder()
  66. {
  67. mInputStream.close();
  68. mInputStream.clear();
  69. }
  70. std::shared_ptr<IReflectable> FileDecoder::decode()
  71. {
  72. if (mInputStream.fail() || mInputStream.eof())
  73. return nullptr;
  74. UINT32 objectSize = 0;
  75. mInputStream.read((char*)&objectSize, sizeof(objectSize));
  76. UINT8* readBuffer = (UINT8*)bs_alloc((UINT32)objectSize); // TODO - Low priority. Consider upgrading BinarySerializer so we don't have to read everything at once
  77. mInputStream.read((char*)readBuffer, objectSize);
  78. BinarySerializer bs;
  79. std::shared_ptr<IReflectable> object = bs.decode(readBuffer, objectSize);
  80. bs_free(readBuffer);
  81. return object;
  82. }
  83. void FileDecoder::skip()
  84. {
  85. if (mInputStream.eof())
  86. return;
  87. UINT32 objectSize = 0;
  88. mInputStream.read((char*)&objectSize, sizeof(objectSize));
  89. mInputStream.seekg(objectSize, std::ios::cur);
  90. }
  91. }