// File: /workspace/github_cpp_makefile_star2_O2/irakr[P]Minimal-File-Compression-Tool/src/huffman-encoder.cpp
// Function: HuffmanEncoder::encode(unsigned char*, long*)
byte* HuffmanEncoder :: encode(byte *in_buff, fsize_t *buff_len) {
	Log(this, "Started...");

	m_inBuffSize = *buff_len;

	// This will hold bytes of the compressed data;
	// Header + content
	byte *out_buff = NULL;

	try {
		// All the 3 statements below must be in this sequence only.
		buildFrequencyTable(in_buff);			// (OK)
		buildHuffmanTree();						// (OK)
		buildCodewordTable();					// (OK)
	}
	catch(std::exception &e) {
		std::cerr << e.what() << std::endl
			<< "[.......Rethrowing exception]" << std::endl;
		throw (new std::exception(e));
	}

	// Build the file header.
	HeaderStruct header;
	build_header(&header, *m_codewordTable);
	header.header_size = get_header_size(&header);
	header.original_size = m_inBuffSize;
	header.compressed_size = get_compressed_size(&header, *m_frequencyTable);
	
	// Build the compressed data(payload)
	size_t out_size = header.header_size + header.compressed_size + PREFIX_LEN;
	
	// If compression not useful.
	if(out_size >= m_inBuffSize)
	    return NULL;
	// Else continue encoding...
	out_buff = new byte[out_size];
	::memcpy((byte*)out_buff, (byte*)PREFIX_STR, PREFIX_LEN);
	
	dump_header(&header, out_buff + PREFIX_LEN);
    dump_content(&header, in_buff, *buff_len, out_buff + header.header_size);
	
	// Return compressed file buffer and its size.
	*buff_len = out_size;
	return out_buff;
}

// Assembly:
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x30, %rsp
movq %rdx, %rbx
movq %rsi, %r14
movq %rdi, %r15
movq (%rdx), %rax
movq %rax, 0x28(%rdi)
callq 0x26f0
movq %r15, %rdi
callq 0x27c4
movq %r15, %rdi
callq 0x28a6
movq 0x40(%r15), %rsi
leaq 0x8(%rsp), %r12
movq %r12, %rdi
callq 0x41c2
movq %r12, %rdi
callq 0x41ac
movl %eax, (%r12)
movq 0x28(%r15), %rax
movq %rax, 0x8(%r12)
movq 0x30(%r15), %rsi
movq %r12, %rdi
callq 0x426e
movq %rax, 0x10(%r12)
movslq (%r12), %rcx
leaq (%rax,%rcx), %r12
addq $0x4, %r12
cmpq 0x28(%r15), %r12
jae 0x2633
movq %r12, %rdi
callq 0x2030
movq %rax, %r15
movl $0xffff5a5a, (%rax)     # imm = 0xFFFF5A5A
leaq 0x4(%rax), %rsi
leaq 0x8(%rsp), %r13
movq %r13, %rdi
callq 0x4344
movq (%rbx), %rdx
movslq (%r13), %rcx
addq %r15, %rcx
movq %r13, %rdi
movq %r14, %rsi
callq 0x4387
movq %r12, (%rbx)
jmp 0x2636
xorl %r15d, %r15d
movq %r15, %rax
addq $0x30, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
retq
movq %rax, %rbx
cmpl $0x1, %edx
jne 0x26df
movq %rbx, %rdi
callq 0x20d0
movq (%rax), %rcx
movq %rax, %rdi
callq *0x10(%rcx)
movq 0x6985(%rip), %rdi      # 0x8ff0
movq %rax, %rsi
callq 0x21c0
movq %rax, %rdi
callq 0x2100
leaq 0x29ae(%rip), %rsi      # 0x5030
movq %rax, %rdi
callq 0x21c0
movq %rax, %rdi
callq 0x2100
pushq $0x8
popq %rbx
movq %rbx, %rdi
callq 0x2110
movq %rax, %r14
movq %rbx, %rdi
callq 0x21d0
movq 0x6909(%rip), %rcx      # 0x8fb8
addq $0x10, %rcx
movq %rcx, (%rax)
movq %rax, (%r14)
leaq 0x65c0(%rip), %rsi      # 0x8c80
movq %r14, %rdi
xorl %edx, %edx
callq 0x22f0
movq %rax, %rbx
movq %r14, %rdi
callq 0x2160
jmp 0x26da
movq %rax, %rbx
callq 0x22d0
movq %rbx, %rdi
callq 0x2310
movq %rax, %rdi
callq 0x2a52
nop