// File: /workspace/github_cpp_makefile_star2_O2/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, %rbp
movq %rdx, %rbx
cmpb $-0x40, 0x2065(%rdi)
pushq $0x1
popq %r14
pushq $-0x1
popq %rax
movq %rax, 0x20(%rsp)
movq %rsi, 0x8(%rsp)
jne 0x3e06
movq %rsi, %rdi
movq %r9, %rsi
callq 0x3d43
cmpb $-0x1, %al
je 0x40e4
movl %eax, %r15d
cmpb $0xc, %al
jb 0x4016
movq 0x51de(%rip), %rdi      # 0x8fd8
leaq 0x2b84(%rip), %rsi      # 0x6985
jmp 0x436e
movq %rdi, %r15
movq %r8, 0x18(%rsp)
movzbl 0x2073(%rdi), %r13d
testl %r13d, %r13d
je 0x3fe8
cmpb $0x0, 0x2075(%r15)
je 0x405d
movb 0x2076(%r15), %cl
movl %r14d, %eax
shll %cl, %eax
movl %eax, 0x10(%rsp)
movq 0x20(%rsp), %rax
shll %cl, %eax
movq %rax, 0x20(%rsp)
movq 0x18(%rsp), %rax
cmpl $0x0, (%rax)
movq 0x8(%rsp), %rbp
je 0x3fcb
movl %r13d, %r14d
xorl %r13d, %r13d
movzbl 0x2074(%r15), %eax
leal (%r14,%r13), %ecx
cmpl %eax, %ecx
jg 0x4072
leaq (%r14,%r13), %rax
leaq 0x21cf(%rip), %rcx      # 0x6050
movzbl (%rcx,%rax), %r12d
cmpl $0x0, (%rbx,%r12,4)
je 0x3ebd
movq %rbp, %rdi
callq 0x51c0
testl %eax, %eax
je 0x3ebd
cmpl $0x1, %eax
jne 0x4360
movl (%rbx,%r12,4), %eax
testl %eax, 0x10(%rsp)
jne 0x3ebd
testl %eax, %eax
movl 0x10(%rsp), %ecx
cmovsl 0x20(%rsp), %ecx
addl %eax, %ecx
movl %ecx, (%rbx,%r12,4)
incq %r13
jmp 0x3e62
movq %rbp, %rdi
movq 0x60(%rsp), %rsi
callq 0x3d43
cmpb $-0x1, %al
je 0x4360
movl %eax, %ebp
shrb $0x4, %bpl
andb $0xf, %al
je 0x3f16
movzbl %al, %eax
cmpl $0x1, %eax
jne 0x4360
movq 0x8(%rsp), %rdi
callq 0x51c0
movl 0x10(%rsp), %ecx
movl %ecx, 0x14(%rsp)
cmpl $0x1, %eax
je 0x3f28
movq 0x20(%rsp), %rcx
movl %ecx, 0x14(%rsp)
testl %eax, %eax
je 0x3f28
jmp 0x4360
movl $0x0, 0x14(%rsp)
cmpb $0xf, %bpl
jne 0x4303
movl %r13d, %r14d
leaq 0x211e(%rip), %rax      # 0x6050
addq %rax, %r14
movzbl (%r14), %r12d
cmpl $0x0, (%rbx,%r12,4)
je 0x3f6b
movq 0x8(%rsp), %rdi
callq 0x51c0
testl %eax, %eax
je 0x3f7d
cmpl $0x1, %eax
jne 0x4360
movl (%rbx,%r12,4), %eax
testl %eax, 0x10(%rsp)
jne 0x3f7d
testl %eax, %eax
js 0x3f75
addl 0x10(%rsp), %eax
jmp 0x3f79
testb %bpl, %bpl
je 0x3f96
decb %bpl
jmp 0x3f7d
addl 0x20(%rsp), %eax
movl %eax, (%rbx,%r12,4)
leal 0x1(%r13), %eax
movzbl 0x2074(%r15), %ecx
incq %r14
cmpl %ecx, %r13d
movl %eax, %r13d
jl 0x3f35
jmp 0x3f99
movl %r13d, %eax
movl 0x14(%rsp), %esi
testl %esi, %esi
je 0x3fbd
movzbl 0x2074(%r15), %ecx
cmpl %ecx, %eax
jg 0x3fbd
movl %eax, %ecx
leaq 0x209a(%rip), %rdx      # 0x6050
movzbl (%rcx,%rdx), %ecx
movl %esi, (%rbx,%rcx,4)
incl %eax
movl %eax, %r13d
movq 0x8(%rsp), %rbp
pushq $0x1
popq %r14
movzbl 0x2074(%r15), %eax
cmpl %eax, %r13d
jle 0x3ec2
movq 0x18(%rsp), %rax
movl (%rax), %eax
jmp 0x432f
cmpb $0x0, 0x2075(%r15)
je 0x4081
movq 0x8(%rsp), %rdi
callq 0x51c0
cmpl $-0x1, %eax
je 0x40e4
movb 0x2076(%r15), %cl
shll %cl, %eax
orl %eax, (%rbx)
jmp 0x4079
movzbl %r15b, %r12d
movq 0x8(%rsp), %rdi
movl %r12d, %esi
callq 0x52ce
cmpl $-0x1, %eax
je 0x40e4
testl %r12d, %r12d
je 0x4203
leal -0x1(%r15), %ecx
movl %r14d, %r13d
shll %cl, %r14d
cmpl %r14d, %eax
jge 0x4206
pushq $-0x1
popq %rdx
movl %r15d, %ecx
shll %cl, %edx
addl %edx, %eax
incl %eax
jmp 0x4206
movq 0x18(%rsp), %rcx
movl (%rcx), %eax
testl %eax, %eax
je 0x40f7
decl %eax
movl %eax, (%rcx)
jmp 0x4079
movq 0x18(%rsp), %rax
decl (%rax)
movb $0x1, %bpl
jmp 0x4375
movq 0x8(%rsp), %rdi
movq %r9, %rsi
callq 0x3d43
cmpb $-0x1, %al
je 0x40e4
movl %eax, %r12d
cmpb $0xc, %al
jae 0x3df3
movzbl %r12b, %r13d
movq 0x8(%rsp), %rdi
movl %r13d, %esi
callq 0x52ce
cmpl $-0x1, %eax
je 0x40e4
testl %r13d, %r13d
je 0x40d1
leal -0x1(%r12), %ecx
shll %cl, %r14d
cmpl %r14d, %eax
jge 0x40d1
movl %r12d, %ecx
pushq $-0x1
popq %rdx
shll %cl, %edx
addl %edx, %eax
incl %eax
addl (%rbp), %eax
movl %eax, (%rbp)
movb 0x2076(%r15), %cl
shll %cl, %eax
movl %eax, (%rbx)
jmp 0x4079
movq 0x4eed(%rip), %rdi      # 0x8fd8
leaq 0x2879(%rip), %rsi      # 0x696b
jmp 0x436e
leaq 0x1f52(%rip), %r14      # 0x6050
movzbl 0x2074(%r15), %eax
movb $0x1, %bpl
cmpl %eax, %r13d
ja 0x4375
movq 0x8(%rsp), %rdi
movq 0x60(%rsp), %rsi
callq 0x3d43
cmpb $-0x1, %al
je 0x4360
movl %eax, %r12d
movl %eax, %ecx
shrb $0x4, %cl
andb $0xf, %r12b
je 0x41c1
movzbl %cl, %eax
leal (%rax,%r13), %ecx
movzbl 0x2074(%r15), %edx
cmpl %edx, %ecx
ja 0x42e3
movzbl %r12b, %esi
movl %r13d, %ebp
subl $0x1, %eax
jb 0x416d
movzbl (%rbp,%r14), %ecx
andl $0x0, (%rbx,%rcx,4)
incl %r13d
jmp 0x4156
cmpb $0xa, %r12b
ja 0x42f3
movq 0x8(%rsp), %rdi
callq 0x52ce
cmpl $-0x1, %eax
je 0x4360
movl %r12d, %ecx
decb %cl
pushq $0x1
popq %rdx
shll %cl, %edx
pushq $-0x1
popq %rcx
movl %ecx, %esi
movl %r12d, %ecx
shll %cl, %esi
orl $0x1, %esi
cmpl %edx, %eax
movl $0x0, %ecx
cmovgel %ecx, %esi
addl %eax, %esi
movb 0x2076(%r15), %cl
shll %cl, %esi
movzbl (%rbp,%r14), %eax
movl %esi, (%rbx,%rax,4)
jmp 0x41fb
cmpb $0xf, %cl
jne 0x433c
leal 0xf(%r13), %eax
movzbl 0x2074(%r15), %ecx
cmpl %ecx, %eax
ja 0x42e3
xorl %eax, %eax
leal (%rax,%r13), %ecx
cmpl $0xf, %eax
je 0x41f8
movl %ecx, %ecx
movzbl (%rcx,%r14), %ecx
andl $0x0, (%rbx,%rcx,4)
incl %eax
jmp 0x41e0
movl %ecx, %r13d
incl %r13d
jmp 0x40fe
movl %r14d, %r13d
addl (%rbp), %eax
movl %eax, (%rbx)
movl %eax, (%rbp)
leaq 0x1e3b(%rip), %r14      # 0x6050
movl %r13d, %r12d
movb $0x1, %r15b
cmpl $0x3f, %r12d
movq 0x8(%rsp), %rdi
ja 0x42d3
movq 0x60(%rsp), %rsi
callq 0x3d43
testb %al, %al
je 0x42d3
movl %eax, %ebp
movzbl %al, %eax
cmpl $0xff, %eax
je 0x42ab
movl %ebp, %eax
shrb $0x4, %al
movl %r12d, %ecx
movzbl %al, %r15d
addq %rcx, %r15
cmpl $0x3f, %r15d
ja 0x42b4
andb $0xf, %bpl
cmpb $0xa, %bpl
ja 0x42bd
movzbl %bpl, %esi
movq 0x8(%rsp), %rdi
callq 0x52ce
cmpl $-0x1, %eax
je 0x42ab
movl %ebp, %ecx
decb %cl
movl %r13d, %edx
shll %cl, %edx
pushq $-0x1
popq %rcx
movl %ecx, %esi
movl %ebp, %ecx
shll %cl, %esi
incl %esi
cmpl %edx, %eax
movl $0x0, %ecx
cmovgel %ecx, %esi
addl %eax, %esi
movzbl (%r15,%r14), %eax
movl %esi, (%rbx,%rax,4)
leal 0x1(%r15), %r12d
jmp 0x4218
leaq 0x2702(%rip), %rsi      # 0x69b4
jmp 0x42c4
leaq 0x2713(%rip), %rsi      # 0x69ce
jmp 0x42c4
leaq 0x273c(%rip), %rsi      # 0x6a00
movq 0x4d0d(%rip), %rdi      # 0x8fd8
callq 0x20e0
xorl %r15d, %r15d
cmpl $0x40, %r12d
setae %bpl
orb %r15b, %bpl
jmp 0x4375
movq 0x4cee(%rip), %rdi      # 0x8fd8
leaq 0x273e(%rip), %rsi      # 0x6a2f
jmp 0x436e
movq 0x4cde(%rip), %rdi      # 0x8fd8
leaq 0x26ff(%rip), %rsi      # 0x6a00
jmp 0x436e
movzbl %bpl, %esi
movl %ebp, %ecx
shll %cl, %r14d
movq 0x18(%rsp), %r12
movl %r14d, (%r12)
movq 0x8(%rsp), %rbp
movq %rbp, %rdi
callq 0x52ce
cmpl $-0x1, %eax
je 0x4360
addl (%r12), %eax
movl %eax, (%r12)
testl %eax, %eax
jne 0x3e5c
jmp 0x4079
pushq $-0x1
popq %rax
shll %cl, %eax
movzbl %cl, %esi
notl %eax
movq 0x18(%rsp), %rbx
movl %eax, (%rbx)
movq 0x8(%rsp), %rdi
callq 0x52ce
cmpl $-0x1, %eax
je 0x4360
addl %eax, (%rbx)
jmp 0x4375
movq 0x4c71(%rip), %rdi      # 0x8fd8
leaq 0x2646(%rip), %rsi      # 0x69b4
callq 0x20e0
xorl %ebp, %ebp
movl %ebp, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq