FASTDecompressor.cpp 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. /* Copyright (C) Teemu Suutari */
  2. #include "FASTDecompressor.hpp"
  3. #include "InputStream.hpp"
  4. #include "OutputStream.hpp"
  5. #include "common/Common.hpp"
  6. namespace ancient::internal
  7. {
  8. bool FASTDecompressor::detectHeaderXPK(uint32_t hdr) noexcept
  9. {
  10. return hdr==FourCC("FAST");
  11. }
  12. std::shared_ptr<XPKDecompressor> FASTDecompressor::create(uint32_t hdr,uint32_t recursionLevel,const Buffer &packedData,std::shared_ptr<XPKDecompressor::State> &state,bool verify)
  13. {
  14. return std::make_shared<FASTDecompressor>(hdr,recursionLevel,packedData,state,verify);
  15. }
  16. FASTDecompressor::FASTDecompressor(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)) throw Decompressor::InvalidFormatError();
  21. }
  22. FASTDecompressor::~FASTDecompressor()
  23. {
  24. // nothing needed
  25. }
  26. const std::string &FASTDecompressor::getSubName() const noexcept
  27. {
  28. static std::string name="XPK-FAST: Fast LZ77 compressor";
  29. return name;
  30. }
  31. void FASTDecompressor::decompressImpl(Buffer &rawData,const Buffer &previousData,bool verify)
  32. {
  33. ForwardInputStream forwardInputStream(_packedData,0,_packedData.size());
  34. BackwardInputStream backwardInputStream(_packedData,0,_packedData.size());
  35. forwardInputStream.link(backwardInputStream);
  36. backwardInputStream.link(forwardInputStream);
  37. MSBBitReader<BackwardInputStream> bitReader(backwardInputStream);
  38. auto readBit=[&]()->uint32_t
  39. {
  40. return bitReader.readBitsBE16(1);
  41. };
  42. auto readByte=[&]()->uint8_t
  43. {
  44. return forwardInputStream.readByte();
  45. };
  46. auto readShort=[&]()->uint16_t
  47. {
  48. const uint8_t *buf=backwardInputStream.consume(2);
  49. uint16_t ret=uint16_t(buf[0])<<8;
  50. return ret|uint16_t(buf[1]);
  51. };
  52. ForwardOutputStream outputStream(rawData,0,rawData.size());
  53. while (!outputStream.eof())
  54. {
  55. if (!readBit())
  56. {
  57. outputStream.writeByte(readByte());
  58. } else {
  59. uint16_t ld=readShort();
  60. uint32_t count=std::min(18U-(ld&0xf),uint32_t(outputStream.getEndOffset()-outputStream.getOffset()));
  61. uint32_t distance=ld>>4;
  62. outputStream.copy(distance,count);
  63. }
  64. }
  65. }
  66. }