gzip.hpp 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. #pragma once
  2. #include <nall/file.hpp>
  3. #include <nall/decode/inflate.hpp>
  4. namespace nall::Decode {
  5. struct GZIP {
  6. inline ~GZIP();
  7. inline auto decompress(const string& filename) -> bool;
  8. inline auto decompress(const uint8_t* data, uint size) -> bool;
  9. string filename;
  10. uint8_t* data = nullptr;
  11. uint size = 0;
  12. };
  13. GZIP::~GZIP() {
  14. if(data) delete[] data;
  15. }
  16. auto GZIP::decompress(const string& filename) -> bool {
  17. if(auto memory = file::read(filename)) {
  18. return decompress(memory.data(), memory.size());
  19. }
  20. return false;
  21. }
  22. auto GZIP::decompress(const uint8_t* data, uint size) -> bool {
  23. if(size < 18) return false;
  24. if(data[0] != 0x1f) return false;
  25. if(data[1] != 0x8b) return false;
  26. uint cm = data[2];
  27. uint flg = data[3];
  28. uint mtime = data[4];
  29. mtime |= data[5] << 8;
  30. mtime |= data[6] << 16;
  31. mtime |= data[7] << 24;
  32. uint xfl = data[8];
  33. uint os = data[9];
  34. uint p = 10;
  35. uint isize = data[size - 4];
  36. isize |= data[size - 3] << 8;
  37. isize |= data[size - 2] << 16;
  38. isize |= data[size - 1] << 24;
  39. filename = "";
  40. if(flg & 0x04) { //FEXTRA
  41. uint xlen = data[p + 0];
  42. xlen |= data[p + 1] << 8;
  43. p += 2 + xlen;
  44. }
  45. if(flg & 0x08) { //FNAME
  46. char buffer[PATH_MAX];
  47. for(uint n = 0; n < PATH_MAX; n++, p++) {
  48. buffer[n] = data[p];
  49. if(data[p] == 0) break;
  50. }
  51. if(data[p++]) return false;
  52. filename = buffer;
  53. }
  54. if(flg & 0x10) { //FCOMMENT
  55. while(data[p++]);
  56. }
  57. if(flg & 0x02) { //FHCRC
  58. p += 2;
  59. }
  60. this->size = isize;
  61. this->data = new uint8_t[this->size];
  62. return inflate(this->data, this->size, data + p, size - p - 8);
  63. }
  64. }