/* Copyright (C) Teemu Suutari */ #ifndef DECOMPRESSOR_HPP #define DECOMPRESSOR_HPP #include #include #include #include #include "common/Buffer.hpp" #include "ancient.hpp" namespace ancient::internal { class Decompressor { protected: Decompressor() noexcept; public: using Error = ancient::Error; using InvalidFormatError = ancient::InvalidFormatError; using DecompressionError = ancient::DecompressionError; using VerificationError = ancient::VerificationError; Decompressor(const Decompressor&)=delete; Decompressor& operator=(const Decompressor&)=delete; virtual ~Decompressor(); // Name returned is human readable long name virtual const std::string &getName() const noexcept=0; // PackedSize or RawSize are taken from the stream if available, 0 otherwise. // for those compressors having 0 sizes, running decompression will update // the values. (make sure to allocate big-enough buffer for decompression) // There are exceptions: Some decompressors need to exact size of the packed data // in order to decompress. For those providing a indefinitely size packed stream // will not work // use the "exactSizeKnown" flag for create to tell whether you know the size or not virtual size_t getPackedSize() const noexcept=0; virtual size_t getRawSize() const noexcept=0; // Actual decompression. // verify checksum if verify==true // can throw DecompressionError if stream cant be unpacked // can throw VerificationError if verify enabled and checksum does not match void decompress(Buffer &rawData,bool verify); // in case of disk image based formats the data does not necessarily start // from logical beginnig of the image but it is offsetted inside the logical image // (f.e. DMS). getDataOffset will return the offset (or 0 if not relevant or if offset does not exist) // getImageSize will return the size of the the logical image, or 0 if not image-based format virtual size_t getImageSize() const noexcept; virtual size_t getImageOffset() const noexcept; // the functions are there to protect against "accidental" large files when parsing headers // a.k.a. 16M should be enough for everybody (sizes do not have to accurate i.e. // compressors can exclude header content for simplification) // This entirely ok for the context of "old computers" and their files, // for other usages these need to be tuned up static size_t getMaxPackedSize() noexcept; static size_t getMaxRawSize() noexcept; // Main entrypoint // if verify=true then check the packedData for errors: CRC or other checksum if available // check exactSizeKnown from size documentation // can throw InvalidFormatError if stream is not recognized or it is invalid // can throw VerificationError if verify enabled and checksum does not match static std::shared_ptr create(const Buffer &packedData,bool exactSizeKnown,bool verify); // Detect signature whether it matches to any known compressor // This does not guarantee the data is decompressable though, only signature is read static bool detect(const Buffer &packedData) noexcept; protected: virtual void decompressImpl(Buffer &rawData,bool verify)=0; }; } #endif