SMPLDecompressor.cpp 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. /* Copyright (C) Teemu Suutari */
  2. #include "SMPLDecompressor.hpp"
  3. #include "InputStream.hpp"
  4. #include "OutputStream.hpp"
  5. #include "HuffmanDecoder.hpp"
  6. #include "common/Common.hpp"
  7. namespace ancient::internal
  8. {
  9. bool SMPLDecompressor::detectHeaderXPK(uint32_t hdr) noexcept
  10. {
  11. return hdr==FourCC("SMPL");
  12. }
  13. std::shared_ptr<XPKDecompressor> SMPLDecompressor::create(uint32_t hdr,uint32_t recursionLevel,const Buffer &packedData,std::shared_ptr<XPKDecompressor::State> &state,bool verify)
  14. {
  15. return std::make_shared<SMPLDecompressor>(hdr,recursionLevel,packedData,state,verify);
  16. }
  17. SMPLDecompressor::SMPLDecompressor(uint32_t hdr,uint32_t recursionLevel,const Buffer &packedData,std::shared_ptr<XPKDecompressor::State> &state,bool verify) :
  18. XPKDecompressor(recursionLevel),
  19. _packedData(packedData)
  20. {
  21. if (!detectHeaderXPK(hdr) || packedData.size()<2) throw Decompressor::InvalidFormatError();
  22. if (packedData.readBE16(0)!=1) throw Decompressor::InvalidFormatError();
  23. }
  24. SMPLDecompressor::~SMPLDecompressor()
  25. {
  26. // nothing needed
  27. }
  28. const std::string &SMPLDecompressor::getSubName() const noexcept
  29. {
  30. static std::string name="XPK-SMPL: Huffman compressor with delta encoding";
  31. return name;
  32. }
  33. void SMPLDecompressor::decompressImpl(Buffer &rawData,const Buffer &previousData,bool verify)
  34. {
  35. ForwardInputStream inputStream(_packedData,2,_packedData.size());
  36. MSBBitReader<ForwardInputStream> bitReader(inputStream);
  37. auto readBits=[&](uint32_t count)->uint32_t
  38. {
  39. return bitReader.readBits8(count);
  40. };
  41. auto readBit=[&]()->uint32_t
  42. {
  43. return bitReader.readBits8(1);
  44. };
  45. ForwardOutputStream outputStream(rawData,0,rawData.size());
  46. HuffmanDecoder<uint32_t> decoder;
  47. for (uint32_t i=0;i<256;i++)
  48. {
  49. uint32_t codeLength=readBits(4);
  50. if (!codeLength) continue;
  51. if (codeLength==15) codeLength=readBits(4)+15;
  52. uint32_t code=readBits(codeLength);
  53. decoder.insert(HuffmanCode<uint32_t>{codeLength,code,i});
  54. }
  55. uint8_t accum=0;
  56. while (!outputStream.eof())
  57. {
  58. uint32_t code=decoder.decode(readBit);
  59. accum+=code;
  60. outputStream.writeByte(accum);
  61. }
  62. }
  63. }