// File: lukasz-wiecaszek[P]h264iframedecoder/./istream.hpp
// Function: ymn::istream<0>::peek_bits(unsigned int, unsigned int&)
bool peek_bits(uint32_t number_of_bits, uint32_t& value)
    {
        assert(number_of_bits <= 32);

        /* verify whether we don't go beyond size of the stream */
        if ((m_position.to_bits() + number_of_bits) <= (m_size * BITS_PER_BYTE)) {

            uint32_t v = 0;
            uint32_t bits_remaining = number_of_bits;
            uint32_t bits_to_read;

            uint32_t byte_pos = m_position.m_byte_position;
            uint32_t bit_pos = m_position.m_bit_position;

            while (bits_remaining > 0) {
                /* there is more bits to be peeked than bits left in current byte */
                if ((bit_pos + bits_remaining) >= BITS_PER_BYTE) {
                    /* number of bits left in current byte */
                    bits_to_read = BITS_PER_BYTE - bit_pos;

                    /* shift the result by number of bits to be peeked
                    to make room for new data */
                    v <<= bits_to_read;
                    /* add to the result value */
                    v |= m_buffer[byte_pos] & ((1U << bits_to_read) - 1);

                    /* move to the next byte in the stream */
                    byte_pos++;
                    /* and reset bit position to the begining of a byte */
                    bit_pos = 0;
                }
                else {
                    /* there remains less than 8 bits to be peeked */
                    bits_to_read = bits_remaining;

                    /* shift the result by number of bits to be peeked
                    to make room for new data */
                    v <<= bits_to_read;

                    /* advance bit position */
                    bit_pos += bits_to_read;

                    /* add to the result value */
                    v |= (m_buffer[byte_pos] >> (BITS_PER_BYTE - bit_pos)) & ((1U << bits_to_read) - 1);
                }

                /* decrease the number of remaining bits by number of bits peeked in this iteration */
                bits_remaining -= bits_to_read;
            }

            value = v;
            return true;
        }
        else {
            m_status |= ISTREAM_STATUS_EOS_REACHED;
            if (m_error_function)
                m_error_function(m_position, m_position + number_of_bits);
            return false;
        }
    }

// Assembly:
subq $0x68, %rsp
movq %rdi, 0x58(%rsp)
movl %esi, 0x54(%rsp)
movq %rdx, 0x48(%rsp)
movq 0x58(%rsp), %rax
movq %rax, 0x18(%rsp)
cmpl $0x20, 0x54(%rsp)
ja 0x17de5
jmp 0x17e04
leaq 0xda34(%rip), %rdi      # 0x25820
leaq 0xda42(%rip), %rsi      # 0x25835
movl $0x1eb, %edx            # imm = 0x1EB
leaq 0xda44(%rip), %rcx      # 0x25843
callq 0x20f0
movq 0x18(%rsp), %rdi
addq $0x10, %rdi
callq 0x17fc0
movq 0x18(%rsp), %rcx
movl 0x54(%rsp), %edx
addq %rdx, %rax
movq 0x8(%rcx), %rcx
shlq $0x3, %rcx
cmpq %rcx, %rax
ja 0x17f46
movq 0x18(%rsp), %rax
movl $0x0, 0x44(%rsp)
movl 0x54(%rsp), %ecx
movl %ecx, 0x40(%rsp)
movq 0x10(%rax), %rcx
movl %ecx, 0x38(%rsp)
movq 0x18(%rax), %rax
movl %eax, 0x34(%rsp)
cmpl $0x0, 0x40(%rsp)
jbe 0x17f34
movl 0x34(%rsp), %eax
addl 0x40(%rsp), %eax
cmpl $0x8, %eax
jb 0x17ec8
movq 0x18(%rsp), %rax
movl $0x8, %ecx
subl 0x34(%rsp), %ecx
movl %ecx, 0x3c(%rsp)
movl 0x3c(%rsp), %ecx
movl 0x44(%rsp), %edx
shll %cl, %edx
movl %edx, %ecx
movl %ecx, 0x44(%rsp)
movq (%rax), %rax
movl 0x38(%rsp), %ecx
movzbl (%rax,%rcx), %eax
movl 0x3c(%rsp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
subl $0x1, %ecx
andl %ecx, %eax
orl 0x44(%rsp), %eax
movl %eax, 0x44(%rsp)
movl 0x38(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x38(%rsp)
movl $0x0, 0x34(%rsp)
jmp 0x17f21
movq 0x18(%rsp), %rax
movl 0x40(%rsp), %ecx
movl %ecx, 0x3c(%rsp)
movl 0x3c(%rsp), %ecx
movl 0x44(%rsp), %edx
shll %cl, %edx
movl %edx, %ecx
movl %ecx, 0x44(%rsp)
movl 0x3c(%rsp), %ecx
addl 0x34(%rsp), %ecx
movl %ecx, 0x34(%rsp)
movq (%rax), %rax
movl 0x38(%rsp), %ecx
movzbl (%rax,%rcx), %eax
movl $0x8, %ecx
subl 0x34(%rsp), %ecx
sarl %cl, %eax
movl 0x3c(%rsp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
subl $0x1, %ecx
andl %ecx, %eax
orl 0x44(%rsp), %eax
movl %eax, 0x44(%rsp)
movl 0x3c(%rsp), %ecx
movl 0x40(%rsp), %eax
subl %ecx, %eax
movl %eax, 0x40(%rsp)
jmp 0x17e54
movl 0x44(%rsp), %ecx
movq 0x48(%rsp), %rax
movl %ecx, (%rax)
movb $0x1, 0x67(%rsp)
jmp 0x17fb2
movq 0x18(%rsp), %rdi
movl 0x20(%rdi), %eax
orl $0x1, %eax
movl %eax, 0x20(%rdi)
addq $0x28, %rdi
callq 0x17fe0
testb $0x1, %al
jne 0x17f63
jmp 0x17fad
movq 0x18(%rsp), %rdi
movq %rdi, %rax
addq $0x28, %rax
movq %rax, 0x8(%rsp)
movq %rdi, %rax
addq $0x10, %rax
movq %rax, 0x10(%rsp)
addq $0x10, %rdi
movl 0x54(%rsp), %eax
movl %eax, %esi
callq 0x18050
movq 0x8(%rsp), %rdi
movq 0x10(%rsp), %rsi
movq %rax, 0x20(%rsp)
movq %rdx, 0x28(%rsp)
leaq 0x20(%rsp), %rdx
callq 0x18000
movb $0x0, 0x67(%rsp)
movb 0x67(%rsp), %al
andb $0x1, %al
addq $0x68, %rsp
retq
nopl (%rax)