/* * Compression Transform * (C) 2014 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #ifndef BOTAN_COMPRESSION_TRANSFORM_H_ #define BOTAN_COMPRESSION_TRANSFORM_H_ #include #include #include namespace Botan { /** * Interface for a compression algorithm. */ class BOTAN_PUBLIC_API(2,0) Compression_Algorithm { public: /** * Create an instance based on a name, or return null if the * algo combination cannot be found. */ static std::unique_ptr create(const std::string& algo_spec); /** * Create an instance based on a name * @param algo_spec algorithm name * Throws Lookup_Error if not found. */ static std::unique_ptr create_or_throw(const std::string& algo_spec); /** * Begin compressing. Most compression algorithms offer a tunable * time/compression tradeoff parameter generally represented by * an integer in the range of 1 to 9. * * If 0 or a value out of range is provided, a compression algorithm * specific default is used. */ virtual void start(size_t comp_level = 0) = 0; /** * Process some data. * @param buf in/out parameter which will possibly be resized or swapped * @param offset an offset into blocks to begin processing * @param flush if true the compressor will be told to flush state */ virtual void update(secure_vector& buf, size_t offset = 0, bool flush = false) = 0; /** * Finish compressing * * @param final_block in/out parameter * @param offset an offset into final_block to begin processing */ virtual void finish(secure_vector& final_block, size_t offset = 0) = 0; /** * @return name of the compression algorithm */ virtual std::string name() const = 0; /** * Reset the state and abort the current message; start can be * called again to process a new message. */ virtual void clear() = 0; virtual ~Compression_Algorithm() = default; }; /* * Interface for a decompression algorithm. */ class BOTAN_PUBLIC_API(2,0) Decompression_Algorithm { public: /** * Create an instance based on a name, or return null if the * algo combination cannot be found. */ static std::unique_ptr create(const std::string& algo_spec); /** * Create an instance based on a name * @param algo_spec algorithm name * Throws Lookup_Error if not found. */ static std::unique_ptr create_or_throw(const std::string& algo_spec); /** * Begin decompressing. * Decompression does not support levels, as compression does. */ virtual void start() = 0; /** * Process some data. * @param buf in/out parameter which will possibly be resized or swapped * @param offset an offset into blocks to begin processing */ virtual void update(secure_vector& buf, size_t offset = 0) = 0; /** * Finish decompressing * * @param final_block in/out parameter * @param offset an offset into final_block to begin processing */ virtual void finish(secure_vector& final_block, size_t offset = 0) = 0; /** * @return name of the decompression algorithm */ virtual std::string name() const = 0; /** * Reset the state and abort the current message; start can be * called again to process a new message. */ virtual void clear() = 0; virtual ~Decompression_Algorithm() = default; }; BOTAN_PUBLIC_API(2,0) Compression_Algorithm* make_compressor(const std::string& type); BOTAN_PUBLIC_API(2,0) Decompression_Algorithm* make_decompressor(const std::string& type); /** * An error that occurred during compression (or decompression) */ class BOTAN_PUBLIC_API(2,9) Compression_Error : public Exception { public: /** * @param func_name the name of the compression API that was called * (eg "BZ2_bzCompressInit" or "lzma_code") * @param type what library this came from * @param rc the error return code from the compression API. The * interpretation of this value will depend on the library. */ Compression_Error(const char* func_name, ErrorType type, int rc) : Exception("Compression API " + std::string(func_name) + " failed with return code " + std::to_string(rc)), m_type(type), m_rc(rc) {} ErrorType error_type() const noexcept override { return m_type; } int error_code() const noexcept override { return m_rc; } private: ErrorType m_type; int m_rc; }; /** * Adapts a zlib style API */ class Compression_Stream { public: virtual ~Compression_Stream() = default; virtual void next_in(uint8_t* b, size_t len) = 0; virtual void next_out(uint8_t* b, size_t len) = 0; virtual size_t avail_in() const = 0; virtual size_t avail_out() const = 0; virtual uint32_t run_flag() const = 0; virtual uint32_t flush_flag() const = 0; virtual uint32_t finish_flag() const = 0; virtual bool run(uint32_t flags) = 0; }; /** * Used to implement compression using Compression_Stream */ class Stream_Compression : public Compression_Algorithm { public: void update(secure_vector& buf, size_t offset, bool flush) final override; void finish(secure_vector& buf, size_t offset) final override; void clear() final override; private: void start(size_t level) final override; void process(secure_vector& buf, size_t offset, uint32_t flags); virtual Compression_Stream* make_stream(size_t level) const = 0; secure_vector m_buffer; std::unique_ptr m_stream; }; /** * FIXME add doc */ class Stream_Decompression : public Decompression_Algorithm { public: void update(secure_vector& buf, size_t offset) final override; void finish(secure_vector& buf, size_t offset) final override; void clear() final override; private: void start() final override; void process(secure_vector& buf, size_t offset, uint32_t flags); virtual Compression_Stream* make_stream() const = 0; secure_vector m_buffer; std::unique_ptr m_stream; }; } #endif