// File: /workspace/github_cpp_makefile_star2_O3/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
movb (%rsi), %dl
cmpb %r14b, %dl
jae 0x25eb
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 0x25d4
movl $0x1, %edx
movq %r13, %rdi
movq %r15, %rsi
callq 0x2220
cmpb $0x1, 0x6c57(%rip)      # 0x91fb
jne 0x25d4
movb -0x29(%rbp), %al
andb $-0x8, %al
cmpb $-0x30, %al
jne 0x25d4
movq -0x38(%rbp), %rax
movq (%rax), %rdi
movq 0x8(%rax), %rdx
subq %rdi, %rdx
je 0x25d4
sarq %rdx
cmpq $0x1, %rdx
adcq $0x0, %rdx
addq %rdx, %rdx
xorl %esi, %esi
callq 0x2100
movb (%rbx), %dl
movb $0x18, %cl
subb %dl, %cl
shll %cl, %r12d
orl %r12d, 0x4(%rbx)
addb $0x8, %dl
movb %dl, (%rbx)
cmpb %r14b, %dl
jb 0x256f
movl 0x4(%rbx), %esi
cmpb $0x0, -0x30(%rbp)
je 0x2603
movl %esi, %eax
shrl $0x1f, %eax
decb %dl
movl $0x1, %r14d
jmp 0x2630
movl %r14d, %ecx
negb %cl
movl %esi, %edi
shrl %cl, %edi
movl $0xffffffff, %r8d       # imm = 0xFFFFFFFF
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movl %r14d, %ecx
shll %cl, %eax
shldl %cl, %esi, %r8d
incl %r8d
notl %eax
andl %edi, %eax
testl %esi, %esi
cmovnsl %r8d, %eax
subb %r14b, %dl
movl %r14d, %ecx
shll %cl, %esi
movb %dl, (%rbx)
movl %esi, 0x4(%rbx)
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq