CBinaryReader.cpp 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #include "StdInc.h"
  2. #include "CBinaryReader.h"
  3. #include <SDL_endian.h>
  4. #include "CInputStream.h"
  5. #if SDL_BYTEORDER == SDL_BIG_ENDIAN
  6. template <typename CData>
  7. CData readLE(CData data)
  8. {
  9. auto dataPtr = (char*)&data;
  10. std::reverse(dataPtr, dataPtr + sizeof(data));
  11. return data;
  12. }
  13. #else
  14. template <typename CData>
  15. CData readLE(CData data)
  16. {
  17. return data;
  18. }
  19. #endif
  20. CBinaryReader::CBinaryReader() : stream(nullptr)
  21. {
  22. }
  23. CBinaryReader::CBinaryReader(CInputStream * stream) : stream(stream)
  24. {
  25. }
  26. CInputStream * CBinaryReader::getStream()
  27. {
  28. return stream;
  29. }
  30. void CBinaryReader::setStream(CInputStream * stream)
  31. {
  32. this->stream = stream;
  33. }
  34. si64 CBinaryReader::read(ui8 * data, si64 size)
  35. {
  36. return stream->read(data, size);
  37. }
  38. template <typename CData>
  39. CData CBinaryReader::readInteger()
  40. {
  41. CData val;
  42. si64 b = stream->read(reinterpret_cast<unsigned char *>(&val), sizeof(val));
  43. if(b < sizeof(val))
  44. {
  45. throw std::runtime_error(getEndOfStreamExceptionMsg(sizeof(val)));
  46. }
  47. return readLE(val);
  48. }
  49. //FIXME: any way to do this without macro?
  50. #define INSTANTIATE(datatype, methodname) \
  51. datatype CBinaryReader::methodname() \
  52. { return readInteger<datatype>(); }
  53. // While it is certanly possible to leave only template method
  54. // but typing template parameter every time can be annoying
  55. // and templates parameters can't be resolved by return type
  56. INSTANTIATE(ui8, readUInt8)
  57. INSTANTIATE(si8, readInt8)
  58. INSTANTIATE(ui16, readUInt16)
  59. INSTANTIATE(si16, readInt16)
  60. INSTANTIATE(ui32, readUInt32)
  61. INSTANTIATE(si32, readInt32)
  62. INSTANTIATE(ui64, readUInt64)
  63. INSTANTIATE(si64, readInt64)
  64. #undef INSTANTIATE
  65. std::string CBinaryReader::readString()
  66. {
  67. int len = readUInt32();
  68. assert(len >= 0 && len <= 500000); //not too long
  69. std::string ret;
  70. ret.reserve(len);
  71. for(int gg = 0; gg < len; ++gg)
  72. {
  73. ret += readInt8();
  74. }
  75. return ret;
  76. }
  77. void CBinaryReader::skip(int count)
  78. {
  79. stream->skip(count);
  80. }
  81. std::string CBinaryReader::getEndOfStreamExceptionMsg(long bytesToRead) const
  82. {
  83. std::stringstream ss;
  84. ss << "The end of the stream was reached unexpectedly. The stream has a length of " << stream->getSize() << " and the current reading position is "
  85. << stream->tell() << ". The client wanted to read " << bytesToRead << " bytes.";
  86. return ss.str();
  87. }