BinaryReader.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. * Copyright (C) 2022 The V-Gears Team
  3. *
  4. * This file is part of V-Gears
  5. *
  6. * V-Gears is free software: you can redistribute it and/or modify it under
  7. * terms of the GNU General Public License as published by the Free Software
  8. * Foundation, version 3.0 (GPLv3) of the License.
  9. *
  10. * V-Gears is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. */
  15. #pragma once
  16. #include <fstream>
  17. #include <sstream>
  18. #include <iterator>
  19. #include "decompiler/unknown_opcode_exception.h"
  20. /**
  21. * REader for binary files.
  22. */
  23. class BinaryReader{
  24. public:
  25. /**
  26. * Reads a file, from start to end.
  27. *
  28. * @oaram file_name[in] Path and name of the file to read.
  29. * @return Read bytes.
  30. * @throws std::runtime_error if the file can't be opened for reading.
  31. */
  32. static std::vector<unsigned char> ReadAll(std::string file_name){
  33. std::ifstream file(file_name.c_str(), std::ios::binary | std::ios::ate);
  34. if (file.is_open()){
  35. size_t file_size_in_bytes = size_t(file.tellg());
  36. std::vector<unsigned char> file_contents(file_size_in_bytes);
  37. file.seekg(0, std::ios::beg);
  38. file.read(reinterpret_cast<char*>(file_contents.data()), file_contents.size());
  39. return file_contents;
  40. }
  41. else throw std::runtime_error("Can't open file");
  42. }
  43. /**
  44. * Constructor.
  45. *
  46. * @param data[in] Bytes for the reader
  47. */
  48. BinaryReader(std::vector<unsigned char>&& data){
  49. size_ = data.size();
  50. std::copy(data.begin(), data.end(), std::ostream_iterator<unsigned char>(stream_));
  51. stream_.seekg(std::ios::beg);
  52. }
  53. /**
  54. * Retrieves the size of the data in the reader.
  55. *
  56. * @return The size of the data in bytes.
  57. */
  58. size_t GetSize() const{return size_;}
  59. /**
  60. * Moves the stream cursor.
  61. *
  62. * @param position[in] Position (offset) of the cursor.
  63. * @throws InternalDecompilerError if the position is invalid.
  64. */
  65. void Seek(unsigned int position){
  66. if (!stream_.seekg(position)) throw InternalDecompilerError();
  67. }
  68. /**
  69. * Retrieves the current stream cursor position.
  70. *
  71. * @return position[in] Position (offset) of the cursor.
  72. */
  73. unsigned int GetPosition(){return static_cast<unsigned int>(stream_.tellg());}
  74. /**
  75. * Reads 32 bits of data as an unsigned integer.
  76. *
  77. * It advances the stream cursor.
  78. *
  79. * @return Read bits.
  80. * @throws InternalDecompilerError if there is not enough data.
  81. */
  82. unsigned int ReadU32(){return InternalRead<unsigned int>();}
  83. /**
  84. * Reads 32 bits of data as a signed integer.
  85. *
  86. * It advances the stream cursor.
  87. *
  88. * @return Read bits.
  89. * @throws InternalDecompilerError if there is not enough data.
  90. */
  91. signed int ReadS32(){return InternalRead<signed int>();}
  92. /**
  93. * Reads 16 bits of data as an unsigned integer.
  94. *
  95. * It advances the stream cursor.
  96. *
  97. * @return Read bits.
  98. * @throws InternalDecompilerError if there is not enough data.
  99. */
  100. signed short int ReadS16(){return InternalRead<signed short int>();}
  101. /**
  102. * Reads 16 bits of data as a signed integer.
  103. *
  104. * It advances the stream cursor.
  105. *
  106. * @return Read bits.
  107. * @throws InternalDecompilerError if there is not enough data.
  108. */
  109. unsigned short int ReadU16(){return InternalRead<unsigned short int>();}
  110. /**
  111. * Reads 8 bits of data as an unsigned integer.
  112. *
  113. * It advances the stream cursor.
  114. *
  115. * @return Read bits.
  116. * @throws InternalDecompilerError if there is not enough data.
  117. */
  118. unsigned char ReadU8(){return InternalRead<unsigned char>();}
  119. /**
  120. * Reads 8 bits of data as a signed integer.
  121. *
  122. * It advances the stream cursor.
  123. *
  124. * @return Read bits.
  125. * @throws InternalDecompilerError if there is not enough data.
  126. */
  127. signed char ReadS8(){return InternalRead<signed char>();}
  128. private:
  129. /**
  130. * Reads T bits of data as a signed integer.
  131. *
  132. * It advances the stream cursor.
  133. *
  134. * @return Read bits.
  135. * @throws InternalDecompilerError if there is not enough data.
  136. */
  137. template<class T> T InternalRead(){
  138. T r = {};
  139. if (!stream_.read(reinterpret_cast<char*>(&r), sizeof(r)))
  140. throw InternalDecompilerError();
  141. return r;
  142. }
  143. /**
  144. * The data stream.
  145. */
  146. std::stringstream stream_;
  147. /**
  148. * The size of the data, in bytes.
  149. */
  150. size_t size_ = 0;
  151. };