// File: /workspace/github_cpp_makefile_star2_O2/dannye[P]jed/src/encoder.cpp
// Function: encodeBlockComponent(BitWriter&, int*, int&, HuffmanTable const&, HuffmanTable const&)
bool encodeBlockComponent(
    BitWriter& bitWriter,
    int* const component,
    int& previousDC,
    const HuffmanTable& dcTable,
    const HuffmanTable& acTable
) {
    // encode DC value
    int coeff = component[0] - previousDC;
    previousDC = component[0];

    uint coeffLength = bitLength(std::abs(coeff));
    if (coeffLength > 11) {
        std::cout << "Error - DC coefficient length greater than 11\n";
        return false;
    }
    if (coeff < 0) {
        coeff += (1 << coeffLength) - 1;
    }

    uint code = 0;
    uint codeLength = 0;
    if (!getCode(dcTable, coeffLength, code, codeLength)) {
        std::cout << "Error - Invalid DC value\n";
        return false;
    }
    bitWriter.writeBits(code, codeLength);
    bitWriter.writeBits(coeff, coeffLength);

    // encode AC values
    for (uint i = 1; i < 64; ++i) {
        // find zero run length
        byte numZeroes = 0;
        while (i < 64 && component[zigZagMap[i]] == 0) {
            numZeroes += 1;
            i += 1;
        }

        if (i == 64) {
            if (!getCode(acTable, 0x00, code, codeLength)) {
                std::cout << "Error - Invalid AC value\n";
                return false;
            }
            bitWriter.writeBits(code, codeLength);
            return true;
        }

        while (numZeroes >= 16) {
            if (!getCode(acTable, 0xF0, code, codeLength)) {
                std::cout << "Error - Invalid AC value\n";
                return false;
            }
            bitWriter.writeBits(code, codeLength);
            numZeroes -= 16;
        }

        // find coeff length
        coeff = component[zigZagMap[i]];
        coeffLength = bitLength(std::abs(coeff));
        if (coeffLength > 10) {
            std::cout << "Error - AC coefficient length greater than 10\n";
            return false;
        }
        if (coeff < 0) {
            coeff += (1 << coeffLength) - 1;
        }

        // find symbol in table
        byte symbol = numZeroes << 4 | coeffLength;
        if (!getCode(acTable, symbol, code, codeLength)) {
            std::cout << "Error - Invalid AC value\n";
            return false;
        }
        bitWriter.writeBits(code, codeLength);
        bitWriter.writeBits(coeff, coeffLength);
    }

    return true;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %r8, 0x18(%rsp)
movq %rcx, %r12
movq %rsi, %r15
movq %rdi, 0x10(%rsp)
movl (%rsi), %eax
movl %eax, %r14d
subl (%rdx), %r14d
movl %eax, (%rdx)
movl %r14d, %edi
negl %edi
cmovsl %r14d, %edi
callq 0x2e47
cmpl $0xc, %eax
jb 0x2ee8
movq 0x40f4(%rip), %rdi      # 0x6fd0
leaq 0x1260(%rip), %rsi      # 0x4143
jmp 0x3073
movl %eax, %ebp
leaq 0x8(%rsp), %rdx
andl $0x0, (%rdx)
leaq 0x4(%rsp), %rcx
andl $0x0, (%rcx)
movzbl %bpl, %esi
movq %r12, %rdi
callq 0x2e54
testb %al, %al
je 0x3065
pushq $-0x1
popq %rax
movl %ebp, %ecx
shll %cl, %eax
notl %eax
movl %r14d, %r12d
sarl $0x1f, %r12d
andl %eax, %r12d
addl %r14d, %r12d
leaq 0x8(%rsp), %rax
movl (%rax), %esi
leaq 0x4(%rsp), %rax
movl (%rax), %edx
movq 0x10(%rsp), %rbx
movq %rbx, %rdi
callq 0x38d2
movq %rbx, %rdi
movl %r12d, %esi
movl %ebp, %edx
callq 0x38d2
pushq $0x1
popq %rbx
leaq 0x12fa(%rip), %rdx      # 0x4250
cmpl $0x3f, %ebx
ja 0x30dc
movl %ebx, %r13d
xorl %r14d, %r14d
xorl %r12d, %r12d
leaq (%r12,%r13), %rbp
cmpq $0x40, %rbp
je 0x307c
movzbl (%rdx,%rbp), %eax
cmpl $0x0, (%r15,%rax,4)
jne 0x2f8a
incq %r12
addl $-0x10, %r14d
jmp 0x2f68
movl %ebx, 0xc(%rsp)
movl %r12d, %ebx
cmpb $0x10, %bl
jb 0x2fd5
movq 0x18(%rsp), %rdi
movl $0xf0, %esi
leaq 0x8(%rsp), %rdx
leaq 0x4(%rsp), %rcx
callq 0x2e54
testb %al, %al
je 0x30c3
movl 0x8(%rsp), %esi
movl 0x4(%rsp), %edx
movq 0x10(%rsp), %rdi
callq 0x38d2
addb $-0x10, %bl
leaq 0x127d(%rip), %rdx      # 0x4250
jmp 0x2f91
movl %ebp, %eax
movzbl (%rax,%rdx), %eax
movl (%r15,%rax,4), %ebp
movl %ebp, %edi
negl %edi
cmovsl %ebp, %edi
callq 0x2e47
cmpl $0xb, %eax
movl 0xc(%rsp), %ebx
jae 0x30f5
movl %eax, 0x24(%rsp)
subl %r14d, %eax
movzbl %al, %esi
movq 0x18(%rsp), %rdi
leaq 0x8(%rsp), %rdx
leaq 0x4(%rsp), %rcx
callq 0x2e54
testb %al, %al
je 0x30ac
pushq $-0x1
popq %rax
movl 0x24(%rsp), %r14d
movl %r14d, %ecx
shll %cl, %eax
notl %eax
movl %ebp, %ecx
sarl $0x1f, %ecx
andl %eax, %ecx
addl %ebp, %ecx
movl %ecx, %ebp
movl 0x8(%rsp), %esi
movl 0x4(%rsp), %edx
movq 0x10(%rsp), %rbx
movq %rbx, %rdi
callq 0x38d2
movq %rbx, %rdi
movl %ebp, %esi
movl %r14d, %edx
callq 0x38d2
leal (%r12,%r13), %ebx
incl %ebx
jmp 0x2f4f
movq 0x3f64(%rip), %rdi      # 0x6fd0
leaq 0x10ff(%rip), %rsi      # 0x4172
callq 0x2100
xorl %eax, %eax
jmp 0x30e4
leaq 0x8(%rsp), %rdx
leaq 0x4(%rsp), %rcx
movq 0x18(%rsp), %rdi
xorl %esi, %esi
callq 0x2e54
testb %al, %al
je 0x30ac
movl 0x8(%rsp), %esi
movl 0x4(%rsp), %edx
movq 0x10(%rsp), %rdi
callq 0x38d2
movb $0x1, %cl
jmp 0x30dc
movq 0x3f1d(%rip), %rdi      # 0x6fd0
leaq 0x10d2(%rip), %rsi      # 0x418c
callq 0x2100
xorl %ecx, %ecx
jmp 0x30dc
movq 0x3f06(%rip), %rdi      # 0x6fd0
leaq 0x10bb(%rip), %rsi      # 0x418c
callq 0x2100
xorl %ecx, %ecx
movl 0xc(%rsp), %ebx
cmpl $0x40, %ebx
setae %al
orb %cl, %al
andb $0x1, %al
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x3ed4(%rip), %rdi      # 0x6fd0
leaq 0x10a3(%rip), %rsi      # 0x41a6
jmp 0x30ba