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 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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. uint8_t ret;
  32. char *c = reinterpret_cast<char *>(&ret);
  33. file.read(c, 1);
  34. return ret;
  35. }
  36. uint16_t BinaryFile::readU16() {
  37. assert(file.is_open());
  38. uint8_t a = readU8();
  39. uint8_t b = readU8();
  40. return ((uint16_t)a | (uint16_t)(b << 8));
  41. }
  42. uint32_t BinaryFile::readU32() {
  43. assert(file.is_open());
  44. uint16_t a = readU16();
  45. uint16_t b = readU16();
  46. return ((uint32_t)a | (uint32_t)(b << 16));
  47. }
  48. uint64_t BinaryFile::readU64() {
  49. assert(file.is_open());
  50. uint32_t a = readU32();
  51. uint32_t b = readU32();
  52. return ((uint64_t)a | ((uint64_t)b << 32));
  53. }
  54. float BinaryFile::readFloat() {
  55. assert(file.is_open());
  56. uint32_t val = readU32();
  57. char *a = reinterpret_cast<char *>(&val);
  58. float ret;
  59. char *b = reinterpret_cast<char *>(&ret);
  60. for (int i = 0; i < 4; i++)
  61. b[i] = a[i];
  62. return ret;
  63. }
  64. namespace {
  65. /*! \fixme Left-Shift with signed integer is undefined!
  66. * So we can't use the same method as for unsigned integers.
  67. * Is there a portable way to read multi-byte signed integers,
  68. * without having to detect the endianness at run-time?
  69. */
  70. const int bigendiandetection = 1;
  71. #define ISBIGENDIAN() ((*(char *)&bigendiandetection) == 0)
  72. void swapByteOrder(char *d, unsigned int n) {
  73. if (ISBIGENDIAN()) {
  74. for (unsigned int i = 0; i < (n / 2); i++) {
  75. char tmp = d[i];
  76. d[i] = d[n - i - 1];
  77. d[n - i - 1] = tmp;
  78. }
  79. }
  80. }
  81. }
  82. int8_t BinaryFile::read8() {
  83. assert(file.is_open());
  84. int8_t ret;
  85. char *p = reinterpret_cast<char *>(&ret);
  86. file.read(p, sizeof(ret));
  87. return ret;
  88. }
  89. int16_t BinaryFile::read16() {
  90. assert(file.is_open());
  91. int16_t ret;
  92. char *p = reinterpret_cast<char *>(&ret);
  93. file.read(p, sizeof(ret));
  94. swapByteOrder(p, 2);
  95. return ret;
  96. }
  97. int32_t BinaryFile::read32() {
  98. assert(file.is_open());
  99. int32_t ret;
  100. char *p = reinterpret_cast<char *>(&ret);
  101. file.read(p, sizeof(ret));
  102. swapByteOrder(p, 4);
  103. return ret;
  104. }
  105. int64_t BinaryFile::read64() {
  106. assert(file.is_open());
  107. int64_t ret;
  108. char *p = reinterpret_cast<char *>(&ret);
  109. file.read(p, sizeof(ret));
  110. swapByteOrder(p, 8);
  111. return ret;
  112. }