/* 
 * Reference Huffman coding
 * Copyright (c) Project Nayuki
 * 
 * https://www.nayuki.io/page/reference-huffman-coding
 * https://github.com/nayuki/Reference-Huffman-coding
 */

#pragma once

#include "BitIoStream.hpp"
#include "CodeTree.hpp"


/* 
 * Reads from a Huffman-coded bit stream and decodes symbols.
 */
class HuffmanDecoder final {
	
	/*---- Fields ----*/
	
	// The underlying bit input stream.
	private: BitInputStream &input;
	
	// The code tree to use in the next read() operation. Must be given a non-null value
	// before calling read(). The tree can be changed after each symbol decoded, as long
	// as the encoder and decoder have the same tree at the same point in the code stream.
	public: const CodeTree *codeTree;
	
	
	/*---- Constructor ----*/
	
	// Constructs a Huffman decoder based on the given bit input stream.
	public: explicit HuffmanDecoder(BitInputStream &in);
	
	
	/*---- Method ----*/
	
	// Reads from the input stream to decode the next Huffman-coded symbol.
	public: int read();
	
};



/* 
 * Encodes symbols and writes to a Huffman-coded bit stream.
 */
class HuffmanEncoder final {
	
	/*---- Fields ----*/
	
	// The underlying bit output stream.
	private: BitOutputStream &output;
	
	// The code tree to use in the next write(uint32_t) operation. Must be given a non-null
	// value before calling write(). The tree can be changed after each symbol encoded, as long
	// as the encoder and decoder have the same tree at the same point in the code stream.
	public: const CodeTree *codeTree;
	
	
	/*---- Constructor ----*/
	
	// Constructs a Huffman encoder based on the given bit output stream.
	public: explicit HuffmanEncoder(BitOutputStream &out);
	
	
	/*---- Method ----*/
	
	// Encodes the given symbol and writes to the Huffman-coded output stream.
	public: void write(std::uint32_t symbol);
	
};
