RLENDecompressor.cpp 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. /* Copyright (C) Teemu Suutari */
  2. #include "RLENDecompressor.hpp"
  3. #include "InputStream.hpp"
  4. #include "OutputStream.hpp"
  5. #include "common/Common.hpp"
  6. namespace ancient::internal
  7. {
  8. bool RLENDecompressor::detectHeaderXPK(uint32_t hdr) noexcept
  9. {
  10. return hdr==FourCC("RLEN");
  11. }
  12. std::shared_ptr<XPKDecompressor> RLENDecompressor::create(uint32_t hdr,uint32_t recursionLevel,const Buffer &packedData,std::shared_ptr<XPKDecompressor::State> &state,bool verify)
  13. {
  14. return std::make_shared<RLENDecompressor>(hdr,recursionLevel,packedData,state,verify);
  15. }
  16. RLENDecompressor::RLENDecompressor(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. RLENDecompressor::~RLENDecompressor()
  23. {
  24. // nothing needed
  25. }
  26. const std::string &RLENDecompressor::getSubName() const noexcept
  27. {
  28. static std::string name="XPK-RLEN: RLE-compressor";
  29. return name;
  30. }
  31. void RLENDecompressor::decompressImpl(Buffer &rawData,const Buffer &previousData,bool verify)
  32. {
  33. ForwardInputStream inputStream(_packedData,0,_packedData.size());
  34. ForwardOutputStream outputStream(rawData,0,rawData.size());
  35. while (!outputStream.eof())
  36. {
  37. uint32_t count=uint32_t(inputStream.readByte());
  38. if (count<128)
  39. {
  40. if (!count) throw Decompressor::DecompressionError(); // lets have this as error...
  41. for (uint32_t i=0;i<count;i++) outputStream.writeByte(inputStream.readByte());
  42. } else {
  43. // I can see from different implementations that count=0x80 is buggy...
  44. // lets try to have it more or less correctly here
  45. count=256-count;
  46. uint8_t ch=inputStream.readByte();
  47. for (uint32_t i=0;i<count;i++) outputStream.writeByte(ch);
  48. }
  49. }
  50. }
  51. }