// File: /workspace/github_cpp_makefile_star2_O1/qhan1028[P]JPEG-Decoder/jpeg-decoder.cpp
// Function: read_bits(std::basic_ifstream<char, std::char_traits<char>>&, buffer&, std::vector<unsigned short, std::allocator<unsigned short>>&, unsigned char, bool)
uint16_t read_bits(ifstream& jpegfile, buffer_t& b, vector<uint16_t>& prev_dc, uint8_t n_bits, bool is_symbol) {
    char c;

    if (n_bits > b.valid_bits) {

        do {
            jpegfile.read(&c, 1);
            uint8_t byte = to_uint(c);

            if (byte == TAG) {
                jpegfile.read(&c, 1);
                if (USE_RST) { // reset dc prev
                    switch (to_uint(c)) {
                        case 0xD0: case 0xD1: case 0xD2: case 0xD3:
                        case 0xD4: case 0xD5: case 0xD6: case 0xD7:
                            for (int i = 0; i < prev_dc.size(); i++) prev_dc[i] = 0;
                            break;
                        default:;
                    }
                }
            }

            b.bits = b.bits | (to_uint(byte) << (24 - b.valid_bits));
            b.valid_bits += 8;

            //cout << b.bits << ", n_bits: " << (int)n_bits << ", valid_bits: " << (int)b.valid_bits << endl;

        } while (n_bits > b.valid_bits);
    }

    uint16_t output = 0;

    if (is_symbol) {
        output = ((b.bits >> (31)) & ((1 << 1) - 1));

        b.valid_bits -= 1;
        b.bits = b.bits << 1;

    } else {
        if(((b.bits >> (32 - 1)) & ((1 << 1) - 1)) == 0){
            output = ((b.bits >> (32 - n_bits)) | ((-1) << n_bits));
            output += 1; //why?

        } else {
            output = ((b.bits >> (32 - n_bits)) & ((1 << n_bits) - 1));
        }
        
        b.valid_bits -= n_bits;
        b.bits = b.bits << n_bits;  

        // cout << "msb: " << (int)(b.bits >> (31)) << ", shift: " << (int)((b.bits >> (31)) & ((1 << 1) - 1)) << ", output: " << (int16_t)output << endl;
    }
    
    return output;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movl %r8d, -0x30(%rbp)
movl %ecx, %r14d
movq %rdx, -0x38(%rbp)
movq %rsi, %rbx
cmpb %r14b, (%rsi)
jae 0x25e8
movq %rdi, %r13
leaq -0x29(%rbp), %r15
movl $0x1, %edx
movq %r13, %rdi
movq %r15, %rsi
callq 0x2220
movzbl -0x29(%rbp), %r12d
cmpl $0xff, %r12d
jne 0x25d2
movl $0x1, %edx
movq %r13, %rdi
movq %r15, %rsi
callq 0x2220
cmpb $0x1, 0x6c59(%rip)      # 0x91fb
jne 0x25d2
movb -0x29(%rbp), %al
andb $-0x8, %al
cmpb $-0x30, %al
jne 0x25d2
movq -0x38(%rbp), %rax
movq (%rax), %rdi
movq 0x8(%rax), %rdx
subq %rdi, %rdx
je 0x25d2
sarq %rdx
cmpq $0x1, %rdx
adcq $0x0, %rdx
addq %rdx, %rdx
xorl %esi, %esi
callq 0x2100
movb (%rbx), %al
movb $0x18, %cl
subb %al, %cl
shll %cl, %r12d
orl %r12d, 0x4(%rbx)
addb $0x8, %al
movb %al, (%rbx)
cmpb %r14b, %al
jb 0x256d
movl 0x4(%rbx), %edx
cmpb $0x0, -0x30(%rbp)
je 0x2604
movl %edx, %eax
shrl $0x1f, %eax
movb (%rbx), %sil
decb %sil
movl $0x1, %r14d
jmp 0x2630
movl %r14d, %ecx
negb %cl
movl %edx, %esi
shrl %cl, %esi
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movl %r14d, %ecx
shll %cl, %eax
shldl %cl, %edx, %edi
incl %edi
notl %eax
andl %esi, %eax
testl %edx, %edx
cmovnsl %edi, %eax
movb (%rbx), %sil
subb %r14b, %sil
movl %r14d, %ecx
shll %cl, %edx
movb %sil, (%rbx)
movl %edx, 0x4(%rbx)
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq