// File: /workspace/github_cpp_makefile_star2_O3/dannye[P]jed/src/decoder.cpp
// Function: decodeBlockComponent(JPGImage const*, BitReader&, int*, int&, unsigned int&, HuffmanTable const&, HuffmanTable const&)
bool decodeBlockComponent(
    const JPGImage* const image,
    BitReader& bitReader,
    int* const component,
    int& previousDC,
    uint& skips,
    const HuffmanTable& dcTable,
    const HuffmanTable& acTable
) {
    if (image->frameType == SOF0) {
        // get the DC value for this block component
        byte length = getNextSymbol(bitReader, dcTable);
        if (length == (byte)-1) {
            std::cout << "Error - Invalid DC value\n";
            return false;
        }
        if (length > 11) {
            std::cout << "Error - DC coefficient length greater than 11\n";
            return false;
        }

        int coeff = bitReader.readBits(length);
        if (coeff == -1) {
            std::cout << "Error - Invalid DC value\n";
            return false;
        }
        if (length != 0 && coeff < (1 << (length - 1))) {
            coeff -= (1 << length) - 1;
        }
        component[0] = coeff + previousDC;
        previousDC = component[0];

        // get the AC values for this block component
        for (uint i = 1; i < 64; ++i) {
            byte symbol = getNextSymbol(bitReader, acTable);
            if (symbol == (byte)-1) {
                std::cout << "Error - Invalid AC value\n";
                return false;
            }

            // symbol 0x00 means fill remainder of component with 0
            if (symbol == 0x00) {
                return true;
            }

            // otherwise, read next component coefficient
            byte numZeroes = symbol >> 4;
            byte coeffLength = symbol & 0x0F;
            coeff = 0;

            if (i + numZeroes >= 64) {
                std::cout << "Error - Zero run-length exceeded block component\n";
                return false;
            }
            i += numZeroes;

            if (coeffLength > 10) {
                std::cout << "Error - AC coefficient length greater than 10\n";
                return false;
            }
            coeff = bitReader.readBits(coeffLength);
            if (coeff == -1) {
                std::cout << "Error - Invalid AC value\n";
                return false;
            }
            if (coeff < (1 << (coeffLength - 1))) {
                coeff -= (1 << coeffLength) - 1;
            }
            component[zigZagMap[i]] = coeff;
        }
        return true;
    }
    else { // image->frameType == SOF2
        if (image->startOfSelection == 0 && image->successiveApproximationHigh == 0) {
            // DC first visit
            byte length = getNextSymbol(bitReader, dcTable);
            if (length == (byte)-1) {
                std::cout << "Error - Invalid DC value\n";
                return false;
            }
            if (length > 11) {
                std::cout << "Error - DC coefficient length greater than 11\n";
                return false;
            }

            int coeff = bitReader.readBits(length);
            if (coeff == -1) {
                std::cout << "Error - Invalid DC value\n";
                return false;
            }
            if (length != 0 && coeff < (1 << (length - 1))) {
                coeff -= (1 << length) - 1;
            }
            coeff += previousDC;
            previousDC = coeff;
            component[0] = coeff << image->successiveApproximationLow;
            return true;
        }
        else if (image->startOfSelection == 0 && image->successiveApproximationHigh != 0) {
            // DC refinement
            int bit = bitReader.readBit();
            if (bit == -1) {
                std::cout << "Error - Invalid DC value\n";
                return false;
            }
            component[0] |= bit << image->successiveApproximationLow;
            return true;
        }
        else if (image->startOfSelection != 0 && image->successiveApproximationHigh == 0) {
            // AC first visit
            if (skips > 0) {
                skips -= 1;
                return true;
            }
            for (uint i = image->startOfSelection; i <= image->endOfSelection; ++i) {
                byte symbol = getNextSymbol(bitReader, acTable);
                if (symbol == (byte)-1) {
                    std::cout << "Error - Invalid AC value\n";
                    return false;
                }

                byte numZeroes = symbol >> 4;
                byte coeffLength = symbol & 0x0F;

                if (coeffLength != 0) {
                    if (i + numZeroes > image->endOfSelection) {
                        std::cout << "Error - Zero run-length exceeded spectral selection\n";
                        return false;
                    }
                    for (uint j = 0; j < numZeroes; ++j, ++i) {
                        component[zigZagMap[i]] = 0;
                    }
                    if (coeffLength > 10) {
                        std::cout << "Error - AC coefficient length greater than 10\n";
                        return false;
                    }

                    int coeff = bitReader.readBits(coeffLength);
                    if (coeff == -1) {
                        std::cout << "Error - Invalid AC value\n";
                        return false;
                    }
                    if (coeff < (1 << (coeffLength - 1))) {
                        coeff -= (1 << coeffLength) - 1;
                    }
                    component[zigZagMap[i]] = coeff << image->successiveApproximationLow;
                }
                else {
                    if (numZeroes == 15) {
                        if (i + numZeroes > image->endOfSelection) {
                            std::cout << "Error - Zero run-length exceeded spectral selection\n";
                            return false;
                        }
                        for (uint j = 0; j < numZeroes; ++j, ++i) {
                            component[zigZagMap[i]] = 0;
                        }
                    }
                    else {
                        skips = (1 << numZeroes) - 1;
                        uint extraSkips = bitReader.readBits(numZeroes);
                        if (extraSkips == (uint)-1) {
                            std::cout << "Error - Invalid AC value\n";
                            return false;
                        }
                        skips += extraSkips;
                        break;
                    }
                }
            }
            return true;
        }
        else { // image->startOfSelection != 0 && image->successiveApproximationHigh != 0
            // AC refinement
            int positive = 1 << image->successiveApproximationLow;
            int negative = ((unsigned)-1) << image->successiveApproximationLow;
            int i = image->startOfSelection;
            if (skips == 0) {
                for (; i <= image->endOfSelection; ++i) {
                    byte symbol = getNextSymbol(bitReader, acTable);
                    if (symbol == (byte)-1) {
                        std::cout << "Error - Invalid AC value\n";
                        return false;
                    }

                    byte numZeroes = symbol >> 4;
                    byte coeffLength = symbol & 0x0F;
                    int coeff = 0;

                    if (coeffLength != 0) {
                        if (coeffLength != 1) {
                            std::cout << "Error - Invalid AC value\n";
                            return false;
                        }
                        switch (bitReader.readBit()) {
                        case 1:
                            coeff = positive;
                            break;
                        case 0:
                            coeff = negative;
                            break;
                        default: // -1, data stream is empty
                            std::cout << "Error - Invalid AC value\n";
                            return false;
                        }
                    }
                    else {
                        if (numZeroes != 15) {
                            skips = 1 << numZeroes;
                            uint extraSkips = bitReader.readBits(numZeroes);
                            if (extraSkips == (uint)-1) {
                                std::cout << "Error - Invalid AC value\n";
                                return false;
                            }
                            skips += extraSkips;
                            break;
                        }
                    }

                    do {
                        if (component[zigZagMap[i]] != 0) {
                            switch (bitReader.readBit()) {
                            case 1:
                                if ((component[zigZagMap[i]] & positive) == 0) {
                                    if (component[zigZagMap[i]] >= 0) {
                                        component[zigZagMap[i]] += positive;
                                    }
                                    else {
                                        component[zigZagMap[i]] += negative;
                                    }
                                }
                                break;
                            case 0:
                                // do nothing
                                break;
                            default: // -1, data stream is empty
                                std::cout << "Error - Invalid AC value\n";
                                return false;
                            }
                        }
                        else {
                            if (numZeroes == 0) {
                                break;
                            }
                            numZeroes -= 1;
                        }

                        i += 1;
                    } while (i <= image->endOfSelection);

                    if (coeff != 0 && i <= image->endOfSelection) {
                        component[zigZagMap[i]] = coeff;
                    }
                }
            }

            if (skips > 0) {
                for (; i <= image->endOfSelection; ++i) {
                    if (component[zigZagMap[i]] != 0) {
                        switch (bitReader.readBit()) {
                        case 1:
                            if ((component[zigZagMap[i]] & positive) == 0) {
                                if (component[zigZagMap[i]] >= 0) {
                                    component[zigZagMap[i]] += positive;
                                }
                                else {
                                    component[zigZagMap[i]] += negative;
                                }
                            }
                            break;
                        case 0:
                            // do nothing
                            break;
                        default: // -1, data stream is empty
                            std::cout << "Error - Invalid AC value\n";
                            return false;
                        }
                    }
                }
                skips -= 1;
            }
            return true;
        }
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %rcx, %r13
movq %rsi, %r14
movq 0x60(%rsp), %r12
cmpb $-0x40, 0x2065(%rdi)
movq %rdx, 0x10(%rsp)
jne 0x4c46
movq %r14, %rdi
movq %r9, %rsi
callq 0x4b84
cmpb $-0x1, %al
je 0x504b
movl %eax, %r15d
cmpb $0xc, %al
jb 0x4d42
movq 0x53a3(%rip), %rdi      # 0x9fd8
leaq 0x2de9(%rip), %rsi      # 0x7a25
movl $0x2e, %edx
jmp 0x505e
movq %rdi, %r15
movzbl 0x2073(%rdi), %ebp
testl %ebp, %ebp
je 0x4d0e
movq %r8, %rbx
cmpb $0x0, 0x2075(%r15)
je 0x4e7d
movb 0x2076(%r15), %cl
movl $0x1, %eax
shll %cl, %eax
movl %eax, 0xc(%rsp)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
shll %cl, %eax
movl %eax, 0x1c(%rsp)
movl (%rbx), %esi
testl %esi, %esi
je 0x4e92
movzbl 0x2074(%r15), %eax
cmpl %eax, %ebp
jg 0x4d05
movq %rbx, %r13
movl %ebp, %eax
decl %ebp
leaq 0x2446(%rip), %rbx      # 0x70f0
addq %rax, %rbx
movzbl (%rbx), %r12d
cmpl $0x0, (%rdx,%r12,4)
je 0x4ced
movq %r14, %rdi
callq 0x638a
movq 0x10(%rsp), %rdx
testl %eax, %eax
je 0x4ced
cmpl $0x1, %eax
jne 0x52fe
movl (%rdx,%r12,4), %eax
testl %eax, 0xc(%rsp)
jne 0x4ced
testl %eax, %eax
movl 0xc(%rsp), %ecx
cmovsl 0x1c(%rsp), %ecx
addl %eax, %ecx
movl %ecx, (%rdx,%r12,4)
movzbl 0x2074(%r15), %eax
incl %ebp
incq %rbx
cmpl %eax, %ebp
jl 0x4cad
movq %r13, %rbx
movl (%r13), %esi
decl %esi
movl %esi, (%rbx)
jmp 0x4e8b
cmpb $0x0, 0x2075(%r15)
je 0x4fcd
movq %r14, %rdi
callq 0x638a
cmpl $-0x1, %eax
je 0x504b
movb 0x2076(%r15), %cl
shll %cl, %eax
movq 0x10(%rsp), %rcx
orl %eax, (%rcx)
jmp 0x4e8b
movzbl %r15b, %ebx
movl $0x0, %eax
testl %ebx, %ebx
je 0x4d97
xorl %ebp, %ebp
movq %r14, %rdi
callq 0x638a
cmpl $-0x1, %eax
je 0x504b
addl %ebp, %ebp
orl %ebp, %eax
movl %eax, %ebp
decl %ebx
jne 0x4d51
cmpl $-0x1, %eax
je 0x504b
testb %r15b, %r15b
je 0x4d97
leal -0x1(%r15), %ecx
movl $0x1, %edx
shll %cl, %edx
cmpl %edx, %eax
jge 0x4d97
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl %r15d, %ecx
shll %cl, %edx
addl %edx, %eax
incl %eax
addl (%r13), %eax
movq 0x10(%rsp), %rcx
movl %eax, (%rcx)
movl %eax, (%r13)
movl $0x1, %ebx
movq %r14, %rdi
movq %r12, %rsi
callq 0x4b84
testb %al, %al
je 0x51ef
movl %eax, %ebp
movzbl %al, %eax
cmpl $0xff, %eax
je 0x5074
movl %ebp, %eax
shrb $0x4, %al
movl %ebx, %ecx
movzbl %al, %r13d
addq %rcx, %r13
cmpl $0x40, %r13d
jae 0x51f8
andb $0xf, %bpl
cmpb $0xb, %bpl
jae 0x5210
movq %r12, %r15
movzbl %bpl, %ebx
testl %ebx, %ebx
je 0x4e2a
xorl %r12d, %r12d
movq %r14, %rdi
callq 0x638a
cmpl $-0x1, %eax
je 0x5074
addl %r12d, %r12d
orl %r12d, %eax
movl %eax, %r12d
decl %ebx
jne 0x4e02
cmpl $-0x1, %eax
jne 0x4e2c
jmp 0x5074
xorl %eax, %eax
movl %ebp, %ecx
decb %cl
movl $0x1, %edx
shll %cl, %edx
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl %ebp, %ecx
shll %cl, %esi
incl %esi
cmpl %edx, %eax
movl $0x0, %ecx
cmovgel %ecx, %esi
addl %eax, %esi
leaq 0x229b(%rip), %rax      # 0x70f0
movzbl (%r13,%rax), %eax
movq 0x10(%rsp), %rcx
movl %esi, (%rcx,%rax,4)
leal 0x1(%r13), %ebx
cmpl $0x3f, %r13d
movq %r15, %r12
jne 0x4dab
movb $0x1, %cl
movb $0x1, %al
jmp 0x5090
movl (%rbx), %eax
testl %eax, %eax
je 0x5096
decl %eax
movl %eax, (%rbx)
movb $0x1, %al
jmp 0x5065
movb $0x1, %al
cmpb 0x2074(%r15), %bpl
ja 0x5065
movq %rbx, 0x20(%rsp)
movq %r14, %rdi
movq %r12, %rsi
callq 0x4b84
cmpb $-0x1, %al
je 0x52fe
movl %eax, %edx
movl %eax, %r13d
shrb $0x4, %r13b
andb $0xf, %al
je 0x4ef8
movzbl %al, %eax
cmpl $0x1, %eax
jne 0x52fe
movq %r14, %rdi
callq 0x638a
movl 0xc(%rsp), %ecx
movl %ecx, 0x18(%rsp)
cmpl $0x1, %eax
je 0x4f0a
movl 0x1c(%rsp), %ecx
movl %ecx, 0x18(%rsp)
testl %eax, %eax
je 0x4f0a
jmp 0x52fe
movl $0x0, 0x18(%rsp)
cmpb $0xf, %r13b
jne 0x5228
movl %ebp, %ebx
leaq 0x21dd(%rip), %rax      # 0x70f0
addq %rax, %rbx
movq 0x10(%rsp), %rdx
movl %ebp, %r12d
movzbl (%rbx), %ebp
cmpl $0x0, (%rdx,%rbp,4)
je 0x4f54
movq %r14, %rdi
callq 0x638a
testl %eax, %eax
je 0x4f5e
cmpl $0x1, %eax
movq 0x10(%rsp), %rdx
jne 0x52fe
movl (%rdx,%rbp,4), %eax
testl %eax, 0xc(%rsp)
jne 0x4f6c
testl %eax, %eax
js 0x4f65
addl 0xc(%rsp), %eax
jmp 0x4f69
testb %r13b, %r13b
je 0x4f86
decb %r13b
jmp 0x4f6c
movq 0x10(%rsp), %rdx
jmp 0x4f6c
addl 0x1c(%rsp), %eax
movl %eax, (%rdx,%rbp,4)
leal 0x1(%r12), %ebp
movzbl 0x2074(%r15), %eax
incq %rbx
cmpl %eax, %r12d
jl 0x4f1b
movl %ebp, %r12d
jmp 0x4f8d
movb 0x2074(%r15), %al
movl 0x18(%rsp), %edi
movzbl %al, %eax
testl %edi, %edi
je 0x4fae
cmpl %eax, %r12d
jg 0x4fae
movl %r12d, %ecx
leaq 0x2149(%rip), %rsi      # 0x70f0
movzbl (%rcx,%rsi), %ecx
movl %edi, (%rdx,%rcx,4)
leal 0x1(%r12), %ebp
cmpl %eax, %r12d
movq 0x20(%rsp), %rbx
movq 0x60(%rsp), %r12
jl 0x4ea6
movl (%rbx), %esi
jmp 0x527e
movq %r14, %rdi
movq %r9, %rsi
callq 0x4b84
cmpb $-0x1, %al
je 0x504b
movl %eax, %r12d
cmpb $0xc, %al
movq 0x10(%rsp), %rsi
jae 0x4c2e
movzbl %r12b, %ebx
testl %ebx, %ebx
je 0x51d5
xorl %ebp, %ebp
movq %r14, %rdi
callq 0x638a
movq 0x10(%rsp), %rsi
cmpl $-0x1, %eax
je 0x504b
addl %ebp, %ebp
orl %ebp, %eax
movl %eax, %ebp
decl %ebx
jne 0x4ffa
cmpl $-0x1, %eax
je 0x504b
testb %r12b, %r12b
je 0x51d7
leal -0x1(%r12), %ecx
movl $0x1, %edx
shll %cl, %edx
cmpl %edx, %eax
jge 0x51d7
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl %r12d, %ecx
shll %cl, %edx
addl %edx, %eax
incl %eax
jmp 0x51d7
movq 0x4f86(%rip), %rdi      # 0x9fd8
leaq 0x29b2(%rip), %rsi      # 0x7a0b
movl $0x19, %edx
callq 0x2130
xorl %eax, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x4f5d(%rip), %rdi      # 0x9fd8
leaq 0x29d2(%rip), %rsi      # 0x7a54
movl $0x19, %edx
callq 0x2130
xorl %ecx, %ecx
xorl %eax, %eax
orb %al, %cl
movl %ecx, %eax
jmp 0x5065
movb $0x1, %al
cmpb 0x2074(%r15), %bpl
ja 0x5065
movq %rbx, 0x20(%rsp)
leaq 0x2043(%rip), %r12      # 0x70f0
movq %r14, %rdi
movq 0x60(%rsp), %rsi
callq 0x4b84
cmpb $-0x1, %al
je 0x52fe
movl %eax, %edx
movl %eax, %ecx
shrb $0x4, %cl
movl %eax, %edi
andb $0xf, %dil
je 0x518b
movzbl %cl, %eax
leal (%rax,%rbp), %ecx
movzbl 0x2074(%r15), %esi
cmpl %esi, %ecx
movq 0x10(%rsp), %rsi
ja 0x528d
cmpb $0x10, %dl
jb 0x5109
movl %ebp, %ecx
movzbl (%rcx,%r12), %ecx
movl $0x0, (%rsi,%rcx,4)
incl %ebp
decl %eax
jne 0x50f5
cmpb $0xa, %dil
ja 0x52a5
movb %dil, 0xc(%rsp)
movzbl %dil, %r13d
xorl %ebx, %ebx
movq %r14, %rdi
callq 0x638a
cmpl $-0x1, %eax
je 0x52fe
addl %ebx, %ebx
orl %eax, %ebx
decl %r13d
jne 0x511e
cmpl $-0x1, %ebx
je 0x52fe
movb 0xc(%rsp), %sil
movl %esi, %ecx
decb %cl
movl $0x1, %eax
shll %cl, %eax
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl %esi, %ecx
shll %cl, %edx
orl $0x1, %edx
cmpl %eax, %ebx
movl $0x0, %eax
cmovgel %eax, %edx
addl %ebx, %edx
movb 0x2076(%r15), %cl
shll %cl, %edx
movl %ebp, %eax
movzbl (%rax,%r12), %eax
movq 0x10(%rsp), %rcx
movl %edx, (%rcx,%rax,4)
movzbl 0x2074(%r15), %eax
jmp 0x51c6
cmpb $0xf, %cl
movq 0x10(%rsp), %rsi
jne 0x52b8
leal 0xf(%rbp), %ecx
movzbl 0x2074(%r15), %eax
cmpl %eax, %ecx
ja 0x528d
xorl %ecx, %ecx
leal (%rcx,%rbp), %edx
movzbl (%rdx,%r12), %edx
movl $0x0, (%rsi,%rdx,4)
incl %ecx
cmpl $0xf, %ecx
jne 0x51ae
addl %ecx, %ebp
incl %ebp
cmpl %eax, %ebp
jbe 0x50ad
jmp 0x4e8b
xorl %eax, %eax
addl (%r13), %eax
movl %eax, (%r13)
movb 0x2076(%r15), %cl
shll %cl, %eax
movl %eax, (%rsi)
jmp 0x4e8b
movb $0x1, %al
xorl %ecx, %ecx
jmp 0x5090
movq 0x4dd9(%rip), %rdi      # 0x9fd8
leaq 0x2868(%rip), %rsi      # 0x7a6e
movl $0x31, %edx
jmp 0x5087
movq 0x4dc1(%rip), %rdi      # 0x9fd8
leaq 0x2882(%rip), %rsi      # 0x7aa0
movl $0x2e, %edx
jmp 0x5087
movl $0x1, %esi
movl %r13d, %ecx
shll %cl, %esi
movl %esi, (%rbx)
xorl %eax, %eax
cmpb $0x10, %dl
movq 0x10(%rsp), %rdx
jb 0x527a
movzbl %r13b, %ebx
xorl %r12d, %r12d
movq %r14, %rdi
callq 0x638a
movq 0x10(%rsp), %rdx
cmpl $-0x1, %eax
je 0x52fe
addl %r12d, %r12d
orl %r12d, %eax
movl %eax, %r12d
decl %ebx
jne 0x5247
cmpl $-0x1, %eax
je 0x52fe
movq 0x20(%rsp), %rbx
movl (%rbx), %esi
addl %eax, %esi
movl %esi, (%rbx)
testl %esi, %esi
movb $0x1, %al
jne 0x4c90
jmp 0x5065
movq 0x4d44(%rip), %rdi      # 0x9fd8
leaq 0x2834(%rip), %rsi      # 0x7acf
movl $0x34, %edx
jmp 0x505e
movq 0x4d2c(%rip), %rdi      # 0x9fd8
leaq 0x27ed(%rip), %rsi      # 0x7aa0
jmp 0x4c3c
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
shll %cl, %esi
notl %esi
movq 0x20(%rsp), %r15
movl %esi, (%r15)
xorl %eax, %eax
cmpb $0x10, %dl
jb 0x52f4
movzbl %cl, %ebx
xorl %ebp, %ebp
movq %r14, %rdi
callq 0x638a
cmpl $-0x1, %eax
je 0x52fe
addl %ebp, %ebp
orl %ebp, %eax
movl %eax, %ebp
decl %ebx
jne 0x52d5
cmpl $-0x1, %eax
je 0x52fe
movl (%r15), %esi
addl %eax, %esi
movl %esi, (%r15)
jmp 0x4e8b
movq 0x4cd3(%rip), %rdi      # 0x9fd8
leaq 0x2748(%rip), %rsi      # 0x7a54
jmp 0x5059