Open Source Tomb Raider Engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

binary.cpp 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*!
  2. * \file src/utils/binary.cpp
  3. * \brief Binary file reading utilities
  4. *
  5. * \author xythobuz
  6. */
  7. #include "global.h"
  8. #include "utils/binary.h"
  9. BinaryFile::~BinaryFile() {
  10. if (file.is_open())
  11. file.close();
  12. }
  13. int BinaryFile::open(const char* f) {
  14. if (file.is_open()) {
  15. return 1;
  16. } else {
  17. file.open(f, std::ios_base::in | std::ios_base::binary);
  18. return (file ? 0 : 1);
  19. }
  20. }
  21. long long BinaryFile::tell() {
  22. assert(file.is_open());
  23. return file.tellg();
  24. }
  25. void BinaryFile::seek(long long pos) {
  26. assert(file.is_open());
  27. file.seekg(pos);
  28. }
  29. uint8_t BinaryFile::readU8() {
  30. assert(file.is_open());
  31. assert(file.good());
  32. uint8_t ret;
  33. char* c = reinterpret_cast<char*>(&ret);
  34. file.read(c, 1);
  35. return ret;
  36. }
  37. uint16_t BinaryFile::readU16() {
  38. assert(file.is_open());
  39. assert(file.good());
  40. uint8_t a = readU8();
  41. uint8_t b = readU8();
  42. return ((uint16_t)a | (uint16_t)(b << 8));
  43. }
  44. uint32_t BinaryFile::readU32() {
  45. assert(file.is_open());
  46. assert(file.good());
  47. uint16_t a = readU16();
  48. uint16_t b = readU16();
  49. return ((uint32_t)a | (uint32_t)(b << 16));
  50. }
  51. uint64_t BinaryFile::readU64() {
  52. assert(file.is_open());
  53. assert(file.good());
  54. uint32_t a = readU32();
  55. uint32_t b = readU32();
  56. return ((uint64_t)a | ((uint64_t)b << 32));
  57. }
  58. float BinaryFile::readFloat() {
  59. assert(file.is_open());
  60. assert(file.good());
  61. uint32_t val = readU32();
  62. char* a = reinterpret_cast<char*>(&val);
  63. float ret;
  64. char* b = reinterpret_cast<char*>(&ret);
  65. for (int i = 0; i < 4; i++)
  66. b[i] = a[i];
  67. return ret;
  68. }
  69. namespace {
  70. /*! \fixme Left-Shift with signed integer is undefined!
  71. * So we can't use the same method as for unsigned integers.
  72. * Is there a portable way to read multi-byte signed integers,
  73. * without having to detect the endianness at run-time?
  74. */
  75. const int bigendiandetection = 1;
  76. #define ISBIGENDIAN() ((*(char *)&bigendiandetection) == 0)
  77. void swapByteOrder(char* d, unsigned int n) {
  78. if (ISBIGENDIAN()) {
  79. for (unsigned int i = 0; i < (n / 2); i++) {
  80. char tmp = d[i];
  81. d[i] = d[n - i - 1];
  82. d[n - i - 1] = tmp;
  83. }
  84. }
  85. }
  86. }
  87. int8_t BinaryFile::read8() {
  88. assert(file.is_open());
  89. assert(file.good());
  90. int8_t ret;
  91. char* p = reinterpret_cast<char*>(&ret);
  92. file.read(p, sizeof(ret));
  93. return ret;
  94. }
  95. int16_t BinaryFile::read16() {
  96. assert(file.is_open());
  97. assert(file.good());
  98. int16_t ret;
  99. char* p = reinterpret_cast<char*>(&ret);
  100. file.read(p, sizeof(ret));
  101. swapByteOrder(p, 2);
  102. return ret;
  103. }
  104. int32_t BinaryFile::read32() {
  105. assert(file.is_open());
  106. assert(file.good());
  107. int32_t ret;
  108. char* p = reinterpret_cast<char*>(&ret);
  109. file.read(p, sizeof(ret));
  110. swapByteOrder(p, 4);
  111. return ret;
  112. }
  113. int64_t BinaryFile::read64() {
  114. assert(file.is_open());
  115. assert(file.good());
  116. int64_t ret;
  117. char* p = reinterpret_cast<char*>(&ret);
  118. file.read(p, sizeof(ret));
  119. swapByteOrder(p, 8);
  120. return ret;
  121. }