// File: night-shift[P]Srl/src/lib/In.cpp
// Function: Srl::Lib::In::try_fetch_data(unsigned long, unsigned long)
bool In::try_fetch_data(size_t nbytes, size_t read_len)
{
    /*           (   <--------->   ) -> this needs to be preserved
     * [.........*.............*...] -> buffer
     *           |             |->  current pos
     *           |
     *           |-> possible buffer anchor
     *
     * after reading new chunk:
     *
     * ( <- preserved -> )(      <- new data ->      )
     * [*.............*..............................]
     *  |             |-> new current pos
     *  |
     *  |-> new buffer anchor
     */

    if(this->eof_reached || !this->streaming) {
        return false;
    }

    auto left = this->end - this->pos;

    read_len = (nbytes < read_len ? read_len : nbytes) - left;

    auto preserve_pos = this->anchor != nullptr
        ? this->anchor - start
        : (this->end - start) - left;

    /* small extra margin to make sure memory around the current position will be preserved in any case */
    const auto margin_sz = 32;
    auto margin = preserve_pos < margin_sz ? margin_sz - (margin_sz - preserve_pos) : margin_sz;

    auto preserve_sz = this->end - (this->start + preserve_pos - margin);
    auto bufsz = preserve_sz + read_len;

    if(this->buffer.size() < bufsz) {
        this->buffer.resize(bufsz);
    }

    if(preserve_sz > 0) {
        memmove(this->buffer.data(), &this->buffer[preserve_pos - margin], preserve_sz);
    }

    this->stream->read((char*)&this->buffer[preserve_sz], read_len);
    auto bytes_read = (size_t)this->stream->gcount();

    this->pos  = &this->buffer[preserve_sz - left];
    anchor = anchor ? nullptr : &this->buffer[margin];

    this->start = this->buffer.data();
    this->end   = this->buffer.data() + bytes_read + preserve_sz;

    if(bytes_read + left < nbytes) {
        this->eof_reached = true;

        return false;
    }

    return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x60(%rbp)
testb $0x1, 0x28(%rax)
jne 0x4429f
movq -0x60(%rbp), %rax
testb $0x1, 0x18(%rax)
jne 0x442a8
movb $0x0, -0x1(%rbp)
jmp 0x444c5
movq -0x60(%rbp), %rcx
movq 0x8(%rcx), %rax
movq 0x10(%rcx), %rcx
subq %rcx, %rax
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rax
cmpq -0x20(%rbp), %rax
jae 0x442cf
movq -0x20(%rbp), %rax
movq %rax, -0x68(%rbp)
jmp 0x442d7
movq -0x18(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0x60(%rbp), %rax
movq -0x68(%rbp), %rcx
subq -0x28(%rbp), %rcx
movq %rcx, -0x20(%rbp)
cmpq $0x0, 0x48(%rax)
je 0x44302
movq -0x60(%rbp), %rcx
movq 0x48(%rcx), %rax
movq (%rcx), %rcx
subq %rcx, %rax
movq %rax, -0x70(%rbp)
jmp 0x44318
movq -0x60(%rbp), %rcx
movq 0x8(%rcx), %rax
movq (%rcx), %rcx
subq %rcx, %rax
subq -0x28(%rbp), %rax
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rax
movq %rax, -0x30(%rbp)
movl $0x20, -0x34(%rbp)
cmpq $0x20, -0x30(%rbp)
jge 0x44345
movl $0x20, %ecx
subq -0x30(%rbp), %rcx
movl $0x20, %eax
subq %rcx, %rax
movq %rax, -0x78(%rbp)
jmp 0x44350
movl $0x20, %eax
movq %rax, -0x78(%rbp)
jmp 0x44350
movq -0x60(%rbp), %rdi
movq -0x78(%rbp), %rax
movq %rax, -0x40(%rbp)
movq 0x8(%rdi), %rax
movq (%rdi), %rcx
addq -0x30(%rbp), %rcx
xorl %edx, %edx
subq -0x40(%rbp), %rdx
addq %rdx, %rcx
subq %rcx, %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
addq -0x20(%rbp), %rax
movq %rax, -0x50(%rbp)
addq $0x30, %rdi
callq 0x37840
cmpq -0x50(%rbp), %rax
jae 0x443a3
movq -0x60(%rbp), %rdi
addq $0x30, %rdi
movq -0x50(%rbp), %rsi
callq 0x35f00
cmpq $0x0, -0x48(%rbp)
jle 0x443e0
movq -0x60(%rbp), %rdi
addq $0x30, %rdi
callq 0x36f40
movq -0x60(%rbp), %rdi
movq %rax, -0x80(%rbp)
addq $0x30, %rdi
movq -0x30(%rbp), %rsi
subq -0x40(%rbp), %rsi
callq 0x33120
movq -0x80(%rbp), %rdi
movq %rax, %rsi
movq -0x48(%rbp), %rdx
callq 0x37a20
movq -0x60(%rbp), %rdi
movq 0x20(%rdi), %rax
movq %rax, -0x88(%rbp)
addq $0x30, %rdi
movq -0x48(%rbp), %rsi
callq 0x33120
movq -0x88(%rbp), %rdi
movq %rax, %rsi
movq -0x20(%rbp), %rdx
callq 0x367d0
movq -0x60(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x38c90
movq -0x60(%rbp), %rdi
movq %rax, -0x58(%rbp)
addq $0x30, %rdi
movq -0x48(%rbp), %rsi
subq -0x28(%rbp), %rsi
callq 0x33120
movq %rax, %rcx
movq -0x60(%rbp), %rax
movq %rcx, 0x10(%rax)
cmpq $0x0, 0x48(%rax)
je 0x44452
xorl %eax, %eax
movq %rax, -0x90(%rbp)
jmp 0x4446a
movq -0x60(%rbp), %rdi
addq $0x30, %rdi
movq -0x40(%rbp), %rsi
callq 0x33120
movq %rax, -0x90(%rbp)
movq -0x60(%rbp), %rdi
movq -0x90(%rbp), %rax
movq %rax, 0x48(%rdi)
addq $0x30, %rdi
callq 0x36f40
movq -0x60(%rbp), %rdi
movq %rax, (%rdi)
addq $0x30, %rdi
callq 0x36f40
movq %rax, %rcx
movq -0x60(%rbp), %rax
addq -0x58(%rbp), %rcx
addq -0x48(%rbp), %rcx
movq %rcx, 0x8(%rax)
movq -0x58(%rbp), %rax
addq -0x28(%rbp), %rax
cmpq -0x18(%rbp), %rax
jae 0x444c1
movq -0x60(%rbp), %rax
movb $0x1, 0x28(%rax)
movb $0x0, -0x1(%rbp)
jmp 0x444c5
movb $0x1, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x90, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)