Archive.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #include "Archive.h"
  2. #include <cstring>
  3. #include <cstdio>
  4. #include <zlib.h>
  5. using WalrusRPG::PIAF::Archive;
  6. using WalrusRPG::PIAF::FileEntry;
  7. using WalrusRPG::PIAF::FileType;
  8. using WalrusRPG::PIAF::CompressionType;
  9. namespace
  10. {
  11. template <typename T> T read_big_endian_value(void *ptr)
  12. {
  13. T result = 0;
  14. uint8_t *data = (uint8_t *) ptr;
  15. for (unsigned i = 0; i < sizeof(T); i++)
  16. result |= data[i] << (8 * (sizeof(T) - 1 - i));
  17. return result;
  18. }
  19. // Must get a pointer on the file table.
  20. void load_file_table(FileEntry *entries, char *data, uint32_t nb_files)
  21. {
  22. for (unsigned index = 0; index < nb_files; index++)
  23. {
  24. char *current_entry_data = &data[index * 24];
  25. memcpy(entries[index].filename, current_entry_data, 8);
  26. entries[index].file_type =
  27. (FileType) read_big_endian_value<uint32_t>(&current_entry_data[8]);
  28. entries[index].compression_type =
  29. (CompressionType) read_big_endian_value<uint32_t>(
  30. &current_entry_data[12]);
  31. entries[index].file_size =
  32. read_big_endian_value<uint32_t>(&current_entry_data[16]);
  33. entries[index].data_offset =
  34. read_big_endian_value<uint32_t>(&current_entry_data[20]);
  35. }
  36. }
  37. }
  38. Archive::Archive(char *filepath)
  39. {
  40. if (filepath == nullptr)
  41. {
  42. }
  43. // TODO : throw NPE
  44. file = fopen(filepath, "rb");
  45. if (file == nullptr)
  46. {
  47. // TODO : throw Couldn't open
  48. }
  49. // loading stuff happens NOW
  50. // checking if the file is long enough to have a header
  51. fseek(file, 0L, SEEK_END);
  52. uint64_t filesize = ftell(file);
  53. fseek(file, 0L, SEEK_SET);
  54. if (filesize < 32)
  55. {
  56. // TODO : throw file too small
  57. }
  58. char header_container[32] = {0};
  59. fread(header_container, sizeof(char), 32, file);
  60. if (strncmp(header_container, "WRPGPIAF", 8) != 0)
  61. {
  62. // TODO throw bad header
  63. }
  64. uint32_t expected_checksum = read_big_endian_value<uint32_t>(&header_container[8]);
  65. if (expected_checksum != crc32(0L, (unsigned char *) header_container, 32))
  66. {
  67. // TODO throw bad checksum
  68. }
  69. // TODO : version checking
  70. version = read_big_endian_value<uint32_t>(&header_container[16]);
  71. /* if (version != CURRENT_PIAF_VERSION)
  72. * {
  73. * exception up;
  74. * throw up; // haha
  75. * }
  76. */
  77. nb_files = read_big_endian_value<uint32_t>(&header_container[20]);
  78. data_size = read_big_endian_value<uint32_t>(&header_container[24]);
  79. if (data_size != filesize - 32 - 24 * nb_files)
  80. {
  81. // T0D0 : throw wrong size exception
  82. }
  83. if (nb_files != 0)
  84. {
  85. uint32_t expected_filetable_checksum =
  86. read_big_endian_value<uint32_t>(&header_container[12]);
  87. char *file_entry_data = new char[24 * nb_files];
  88. if (expected_filetable_checksum !=
  89. crc32(0L, (unsigned char *) file_entry_data, 24 * nb_files))
  90. {
  91. // TODO : checksum exception
  92. }
  93. fseek(file, 32, SEEK_SET);
  94. fread(file_entry_data, sizeof(char), 24 * nb_files, file);
  95. entries = new FileEntry[nb_files];
  96. load_file_table(entries, file_entry_data, nb_files);
  97. delete[] file_entry_data;
  98. }
  99. }
  100. Archive::~Archive()
  101. {
  102. fclose(file);
  103. delete[] entries;
  104. }
  105. FileEntry Archive::get_file_entry(char *filename)
  106. {
  107. for (uint32_t index = 0; index < nb_files; index++)
  108. {
  109. if (strcmp(entries[index].filename, filename) == 0)
  110. {
  111. return entries[index];
  112. }
  113. }
  114. // throw exception
  115. }
  116. /*PFile*/ void /*FileEntry*/ get(char *filename)
  117. {
  118. // return PFile(get_file_entry(filename));
  119. }