1
0

ZENODecompressor.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /* Copyright (C) Teemu Suutari */
  2. #include "ZENODecompressor.hpp"
  3. #include "InputStream.hpp"
  4. #include "OutputStream.hpp"
  5. #include "common/Common.hpp"
  6. namespace ancient::internal
  7. {
  8. bool ZENODecompressor::detectHeaderXPK(uint32_t hdr) noexcept
  9. {
  10. return hdr==FourCC("ZENO");
  11. }
  12. std::shared_ptr<XPKDecompressor> ZENODecompressor::create(uint32_t hdr,uint32_t recursionLevel,const Buffer &packedData,std::shared_ptr<XPKDecompressor::State> &state,bool verify)
  13. {
  14. return std::make_shared<ZENODecompressor>(hdr,recursionLevel,packedData,state,verify);
  15. }
  16. ZENODecompressor::ZENODecompressor(uint32_t hdr,uint32_t recursionLevel,const Buffer &packedData,std::shared_ptr<XPKDecompressor::State> &state,bool verify) :
  17. XPKDecompressor(recursionLevel),
  18. _packedData(packedData)
  19. {
  20. if (!detectHeaderXPK(hdr) || _packedData.size()<6)
  21. throw Decompressor::InvalidFormatError();
  22. // first 4 bytes is checksum for password. It needs to be zero
  23. if (_packedData.readBE32(0)) throw Decompressor::InvalidFormatError();
  24. _maxBits=_packedData.read8(4);
  25. if (_maxBits<9 || _maxBits>20) throw Decompressor::InvalidFormatError();
  26. _startOffset=uint32_t(_packedData.read8(5))+6;
  27. if (_startOffset>=_packedData.size()) throw Decompressor::InvalidFormatError();
  28. }
  29. ZENODecompressor::~ZENODecompressor()
  30. {
  31. // nothing needed
  32. }
  33. const std::string &ZENODecompressor::getSubName() const noexcept
  34. {
  35. static std::string name="XPK-ZENO: LZW-compressor";
  36. return name;
  37. }
  38. void ZENODecompressor::decompressImpl(Buffer &rawData,const Buffer &previousData,bool verify)
  39. {
  40. ForwardInputStream inputStream(_packedData,_startOffset,_packedData.size());
  41. MSBBitReader<ForwardInputStream> bitReader(inputStream);
  42. auto readBits=[&](uint32_t count)->uint32_t
  43. {
  44. return bitReader.readBits8(count);
  45. };
  46. ForwardOutputStream outputStream(rawData,0,rawData.size());
  47. uint32_t maxCode=1<<_maxBits;
  48. uint32_t stackLength=5000; // magic constant
  49. auto prefix=std::make_unique<uint32_t[]>(maxCode-258);
  50. auto suffix=std::make_unique<uint8_t[]>(maxCode-258);
  51. auto stack=std::make_unique<uint8_t[]>(stackLength);
  52. uint32_t freeIndex,codeBits,prevCode,newCode;
  53. auto init=[&]()
  54. {
  55. codeBits=9;
  56. freeIndex=258;
  57. };
  58. init();
  59. prevCode=readBits(9);
  60. newCode=prevCode;
  61. suffix[freeIndex-258]=0;
  62. prefix[freeIndex-258]=0;
  63. freeIndex++;
  64. outputStream.writeByte(newCode);
  65. while (!outputStream.eof())
  66. {
  67. if (freeIndex+3>=(1U<<codeBits) && codeBits<_maxBits) codeBits++;
  68. uint32_t code=readBits(codeBits);
  69. switch (code)
  70. {
  71. case 256:
  72. throw Decompressor::DecompressionError();
  73. break;
  74. case 257:
  75. init();
  76. break;
  77. default:
  78. {
  79. uint32_t stackPos=0;
  80. uint32_t tmp=code;
  81. if (tmp==freeIndex)
  82. {
  83. stack[stackPos++]=newCode;
  84. tmp=prevCode;
  85. }
  86. if (tmp>=258)
  87. {
  88. do {
  89. if (stackPos+1>=stackLength || tmp>=freeIndex) throw Decompressor::DecompressionError();
  90. stack[stackPos++]=suffix[tmp-258];
  91. tmp=prefix[tmp-258];
  92. } while (tmp>=258);
  93. stack[stackPos++]=newCode=tmp;
  94. while (stackPos) outputStream.writeByte(stack[--stackPos]);
  95. } else {
  96. newCode=tmp;
  97. outputStream.writeByte(tmp);
  98. if (stackPos) outputStream.writeByte(stack[0]);
  99. }
  100. }
  101. if (freeIndex<maxCode)
  102. {
  103. suffix[freeIndex-258]=newCode;
  104. prefix[freeIndex-258]=prevCode;
  105. freeIndex++;
  106. }
  107. prevCode=code;
  108. break;
  109. }
  110. }
  111. }
  112. }