CBR0Decompressor.cpp 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. /* Copyright (C) Teemu Suutari */
  2. #include "CBR0Decompressor.hpp"
  3. #include "InputStream.hpp"
  4. #include "OutputStream.hpp"
  5. #include "common/Common.hpp"
  6. namespace ancient::internal
  7. {
  8. bool CBR0Decompressor::detectHeaderXPK(uint32_t hdr) noexcept
  9. {
  10. // CBR1 is practical joke: it is the same as CBR0 but with ID changed
  11. return hdr==FourCC("CBR0") || hdr==FourCC("CBR1");
  12. }
  13. std::shared_ptr<XPKDecompressor> CBR0Decompressor::create(uint32_t hdr,uint32_t recursionLevel,const Buffer &packedData,std::shared_ptr<XPKDecompressor::State> &state,bool verify)
  14. {
  15. return std::make_shared<CBR0Decompressor>(hdr,recursionLevel,packedData,state,verify);
  16. }
  17. CBR0Decompressor::CBR0Decompressor(uint32_t hdr,uint32_t recursionLevel,const Buffer &packedData,std::shared_ptr<XPKDecompressor::State> &state,bool verify) :
  18. XPKDecompressor(recursionLevel),
  19. _packedData(packedData),
  20. _isCBR0(hdr==FourCC("CBR0"))
  21. {
  22. if (!detectHeaderXPK(hdr)) throw Decompressor::InvalidFormatError();
  23. }
  24. CBR0Decompressor::~CBR0Decompressor()
  25. {
  26. // nothing needed
  27. }
  28. const std::string &CBR0Decompressor::getSubName() const noexcept
  29. {
  30. static std::string nameCBR0="XPK-CBR0: RLE-compressor";
  31. static std::string nameCBR1="XPK-CBR1: RLE-compressor";
  32. return (_isCBR0)?nameCBR0:nameCBR1;
  33. }
  34. void CBR0Decompressor::decompressImpl(Buffer &rawData,const Buffer &previousData,bool verify)
  35. {
  36. ForwardInputStream inputStream(_packedData,0,_packedData.size());
  37. ForwardOutputStream outputStream(rawData,0,rawData.size());
  38. // barely different than RLEN, however the count is well defined here.
  39. while (!outputStream.eof())
  40. {
  41. uint32_t count=inputStream.readByte();
  42. if (count<128)
  43. {
  44. count++;
  45. for (uint32_t i=0;i<count;i++) outputStream.writeByte(inputStream.readByte());
  46. } else {
  47. count=257-count;
  48. uint8_t ch=inputStream.readByte();
  49. for (uint32_t i=0;i<count;i++) outputStream.writeByte(ch);
  50. }
  51. }
  52. }
  53. }