// File: /workspace/github_cpp_makefile_star2_O1/VanAndelInstitute[P]intent/include/zstr.hpp
// Function: zstr::istreambuf::underflow()
virtual std::streambuf::int_type underflow()
    {
        if (this->gptr() == this->egptr())
        {
            // pointers for free region in output buffer
            char * out_buff_free_start = out_buff;
            do
            {
                // read more input if none available
                if (in_buff_start == in_buff_end)
                {
                    // empty input buffer: refill from the start
                    in_buff_start = in_buff;
                    std::streamsize sz = sbuf_p->sgetn(in_buff, buff_size);
                    in_buff_end = in_buff + sz;
                    if (in_buff_end == in_buff_start) break; // end of input
                }
                // auto detect if the stream contains text or deflate data
                if (auto_detect && ! auto_detect_run)
                {
                    auto_detect_run = true;
                    unsigned char b0 = *reinterpret_cast< unsigned char * >(in_buff_start);
                    unsigned char b1 = *reinterpret_cast< unsigned char * >(in_buff_start + 1);
                    // Ref:
                    // http://en.wikipedia.org/wiki/Gzip
                    // http://stackoverflow.com/questions/9050260/what-does-a-zlib-header-look-like
                    is_text = ! (in_buff_start + 2 <= in_buff_end
                                 && ((b0 == 0x1F && b1 == 0x8B)         // gzip header
                                     || (b0 == 0x78 && (b1 == 0x01      // zlib header
                                                        || b1 == 0x9C
                                                        || b1 == 0xDA))));
                }
                if (is_text)
                {
                    // simply swap in_buff and out_buff, and adjust pointers
                    assert(in_buff_start == in_buff);
                    std::swap(in_buff, out_buff);
                    out_buff_free_start = in_buff_end;
                    in_buff_start = in_buff;
                    in_buff_end = in_buff;
                }
                else
                {
                    // run inflate() on input
                    if (! zstrm_p) zstrm_p = new detail::z_stream_wrapper(true);
                    zstrm_p->next_in = reinterpret_cast< decltype(zstrm_p->next_in) >(in_buff_start);
                    zstrm_p->avail_in = in_buff_end - in_buff_start;
                    zstrm_p->next_out = reinterpret_cast< decltype(zstrm_p->next_out) >(out_buff_free_start);
                    zstrm_p->avail_out = (out_buff + buff_size) - out_buff_free_start;
                    int ret = inflate(zstrm_p, Z_NO_FLUSH);
                    // process return code
                    if (ret != Z_OK && ret != Z_STREAM_END) throw Exception(zstrm_p, ret);
                    // update in&out pointers following inflate()
                    in_buff_start = reinterpret_cast< decltype(in_buff_start) >(zstrm_p->next_in);
                    in_buff_end = in_buff_start + zstrm_p->avail_in;
                    out_buff_free_start = reinterpret_cast< decltype(out_buff_free_start) >(zstrm_p->next_out);
                    assert(out_buff_free_start + zstrm_p->avail_out == out_buff + buff_size);
                    // if stream ended, deallocate inflator
                    if (ret == Z_STREAM_END)
                    {
                        delete zstrm_p;
                        zstrm_p = nullptr;
                    }
                }
            } while (out_buff_free_start == out_buff);
            // 2 exit conditions:
            // - end of input: there might or might not be output available
            // - out_buff_free_start != out_buff: output available
            this->setg(out_buff, out_buff, out_buff_free_start);
        }
        return this->gptr() == this->egptr()
            ? traits_type::eof()
            : traits_type::to_int_type(*this->gptr());
    }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
movq 0x10(%rdi), %rax
cmpq 0x18(%rdi), %rax
jne 0x1ad79
movq 0x60(%rbx), %r15
movq 0x50(%rbx), %rax
cmpq 0x58(%rbx), %rax
jne 0x1ac22
movq 0x40(%rbx), %rdi
movq 0x48(%rbx), %rsi
movq %rsi, 0x50(%rbx)
movq 0x70(%rbx), %rdx
movq (%rdi), %rax
callq *0x40(%rax)
addq 0x48(%rbx), %rax
movq %rax, 0x58(%rbx)
cmpq 0x50(%rbx), %rax
je 0x1ad69
cmpb $0x1, 0x78(%rbx)
jne 0x1ac7f
cmpb $0x0, 0x79(%rbx)
jne 0x1ac7f
movb $0x1, 0x79(%rbx)
movq 0x50(%rbx), %rcx
leaq 0x2(%rcx), %rdx
movb $0x1, %al
cmpq 0x58(%rbx), %rdx
ja 0x1ac7c
movb (%rcx), %dl
movb 0x1(%rcx), %cl
movl %edx, %esi
xorb $0x1f, %sil
movl %ecx, %edi
xorb $-0x75, %dil
orb %sil, %dil
jne 0x1ac5c
xorl %eax, %eax
jmp 0x1ac7c
cmpb $0x78, %dl
jne 0x1ac7c
movzbl %cl, %ecx
xorl %eax, %eax
cmpl $0x1, %ecx
je 0x1ac7c
cmpl $0x9c, %ecx
je 0x1ac7c
cmpl $0xda, %ecx
setne %al
movb %al, 0x7a(%rbx)
cmpb $0x1, 0x7a(%rbx)
jne 0x1acb0
movq 0x48(%rbx), %rax
cmpq %rax, 0x50(%rbx)
jne 0x1ade8
movq 0x58(%rbx), %r15
movq 0x60(%rbx), %rcx
movq %rcx, 0x48(%rbx)
movq %rax, 0x60(%rbx)
movq %rcx, 0x50(%rbx)
movq %rcx, 0x58(%rbx)
jmp 0x1ad5f
cmpq $0x0, 0x68(%rbx)
jne 0x1acda
movl $0x78, %edi
callq 0x63b0
movq %rax, %r14
movq %rax, %rdi
movl $0x1, %esi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
callq 0x1ae4a
movq %r14, 0x68(%rbx)
movq 0x50(%rbx), %rax
movq 0x68(%rbx), %rdi
movq %rax, (%rdi)
movl 0x58(%rbx), %ecx
subl %eax, %ecx
movl %ecx, 0x8(%rdi)
movq %r15, 0x18(%rdi)
movl 0x60(%rbx), %eax
addl 0x70(%rbx), %eax
subl %r15d, %eax
movl %eax, 0x20(%rdi)
xorl %esi, %esi
callq 0x6300
movl %eax, %ebp
cmpl $0x2, %eax
jae 0x1adb7
movq 0x60(%rbx), %rax
movq 0x68(%rbx), %r14
movq (%r14), %rcx
movq %rcx, 0x50(%rbx)
movl 0x8(%r14), %edx
addq %rcx, %rdx
movq %rdx, 0x58(%rbx)
movq 0x18(%r14), %r15
movl 0x20(%r14), %ecx
addq %r15, %rcx
addq 0x70(%rbx), %rax
cmpq %rax, %rcx
jne 0x1ad98
cmpl $0x1, %ebp
jne 0x1ad5f
movq %r14, %rdi
callq 0x1ae2c
movl $0x78, %esi
movq %r14, %rdi
callq 0x63c0
movq $0x0, 0x68(%rbx)
cmpq 0x60(%rbx), %r15
je 0x1abf0
movq 0x60(%rbx), %rax
movq %rax, 0x8(%rbx)
movq %rax, 0x10(%rbx)
movq %r15, 0x18(%rbx)
movq 0x10(%rbx), %rax
cmpq 0x18(%rbx), %rax
je 0x1ad88
movzbl (%rax), %eax
jmp 0x1ad8d
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
leaq 0x1687e(%rip), %rdi     # 0x3161d
leaq 0x167cc(%rip), %rsi     # 0x31572
leaq 0x16831(%rip), %rcx     # 0x315de
movl $0xc0, %edx
callq 0x6290
movl $0x28, %edi
callq 0x61f0
movq %rax, %r14
movq 0x68(%rbx), %rsi
movq %rax, %rdi
movl %ebp, %edx
callq 0x1af0a
leaq 0x23957(%rip), %rsi     # 0x3e730
leaq 0x3b4(%rip), %rdx       # 0x1b194
movq %r14, %rdi
callq 0x6640
leaq 0x167d6(%rip), %rdi     # 0x315c5
leaq 0x1677c(%rip), %rsi     # 0x31572
leaq 0x167e1(%rip), %rcx     # 0x315de
movl $0xab, %edx
callq 0x6290
movq %rax, %rbx
movl $0x78, %esi
movq %r14, %rdi
callq 0x63c0
jmp 0x1ae24
movq %rax, %rbx
movq %r14, %rdi
callq 0x62e0
movq %rbx, %rdi
callq 0x6660