// File: ivan-tkatchev[P]yalz77/./lz77.h
// Function: lz77::decompress_t::feed(unsigned char const*, unsigned char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>&)
bool feed(const unsigned char* i, const unsigned char* e, std::string& remaining) {

        // This function is complex because it is streamable and robust.
        // The routine checks if the input isn't complete and will properly
        // pick up from where we left off when the rest of the input arrives.
        
        if (state.state == state_t::INIT) {

            ret.clear();

            size_t size;
            if (!pop_vlq_uint(i, e, size))
                return true;

            ++i;

            state = state_t();

            if (max_size && size > max_size)
                throw std::length_error("Uncompressed data in message deemed too large");

            ret.resize(size);

            outb = (unsigned char*)ret.data();
            oute = outb + size;
            out = outb;

            state.state = state_t::START;
        }

        while (i != e) {

            if (out == oute) {
                remaining.assign(i, e);
                state.state = state_t::INIT;
                return true;
            }

            if (state.state == state_t::START) {

                if (!pop_vlq_uint(i, e, state.msg))
                    return false;

                ++i;

                state.state = ((state.msg & 1) ? state_t::READ_DATA : state_t::READ_RUN);

                state.msg = state.msg >> 1;
            }

            if (state.state == state_t::READ_DATA) {

                size_t len = state.msg;
                
                if (out + len > oute)
                    throw std::runtime_error("Malformed data while uncompressing");

                if (i == e)
                    return false;

                if (i + len > e) {

                    size_t l = e - i;
                    ::memcpy(out, &(*i), l);
                    out += l;
                    state.msg -= l;

                    return false;
                }

                ::memcpy(out, &(*i), len);
                out += len;
                i += len;

                state.state = state_t::START;

            } else if (state.state == state_t::READ_RUN) {

                size_t shortrun = state.msg & (SHORTRUN_MAX - 1);

                if (shortrun) {

                    state.run = shortrun;

                } else {

                    if (!pop_vlq_uint(i, e, state.run))
                        return false;

                    ++i;
                }

                size_t off = (state.msg >> SHORTRUN_BITS);
                size_t run = state.run + MIN_RUN - 1;

                unsigned char* outi = out - off;

                if (outi >= oute || outi < outb || out + run > oute || out + run < out)
                    throw std::runtime_error("Malformed data while uncompressing");

                if (outi + run < out) {
                    ::memcpy(out, outi, run);
                    out += run;

                } else {

                    while (run > 0) {
                        *out = *outi;
                        ++out;
                        ++outi;
                        --run;
                    }
                }

                state.state = state_t::START;
            }
        }

        if (out == oute) {
            remaining.assign(i, e);
            state.state = state_t::INIT;
            return true;
        }

        return false;
    }

// Assembly:
subq $0xb8, %rsp
movq %rdi, 0xa8(%rsp)
movq %rsi, 0xa0(%rsp)
movq %rdx, 0x98(%rsp)
movq %rcx, 0x90(%rsp)
movq 0xa8(%rsp), %rax
movq %rax, 0x18(%rsp)
cmpl $0x0, 0x60(%rax)
jne 0x2f39
movq 0x18(%rsp), %rdi
addq $0x8, %rdi
callq 0x2250
movq 0x18(%rsp), %rdi
movq 0x98(%rsp), %rdx
leaq 0xa0(%rsp), %rsi
leaq 0x88(%rsp), %rcx
callq 0x5200
testb $0x1, %al
jne 0x2e3f
movb $0x1, 0xb7(%rsp)
jmp 0x33b4
movq 0xa0(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xa0(%rsp)
leaq 0x60(%rsp), %rdi
callq 0x51c0
movq 0x18(%rsp), %rdi
addq $0x40, %rdi
leaq 0x60(%rsp), %rsi
movl $0x24, %edx
callq 0x2170
movq 0x18(%rsp), %rax
cmpq $0x0, (%rax)
je 0x2eea
movq 0x18(%rsp), %rcx
movq 0x88(%rsp), %rax
cmpq (%rcx), %rax
jbe 0x2eea
movl $0x10, %edi
callq 0x20b0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x10(%rsp)
leaq 0x32af(%rip), %rsi      # 0x615d
callq 0x2210
jmp 0x2eb5
movq 0x10(%rsp), %rdi
movq 0x610f(%rip), %rsi      # 0x8fd0
movq 0x60f0(%rip), %rdx      # 0x8fb8
callq 0x22f0
movq 0x10(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x58(%rsp)
movl %eax, 0x54(%rsp)
callq 0x2140
jmp 0x33c5
movq 0x18(%rsp), %rdi
addq $0x8, %rdi
movq 0x88(%rsp), %rsi
callq 0x2260
movq 0x18(%rsp), %rdi
addq $0x8, %rdi
callq 0x20d0
movq %rax, %rcx
movq 0x18(%rsp), %rax
movq %rcx, 0x30(%rax)
movq 0x30(%rax), %rcx
addq 0x88(%rsp), %rcx
movq %rcx, 0x38(%rax)
movq 0x30(%rax), %rcx
movq %rcx, 0x28(%rax)
movl $0x1, 0x60(%rax)
jmp 0x2f3b
movq 0xa0(%rsp), %rax
cmpq 0x98(%rsp), %rax
je 0x336a
movq 0x18(%rsp), %rcx
movq 0x28(%rcx), %rax
cmpq 0x38(%rcx), %rax
jne 0x2f96
movq 0x90(%rsp), %rdi
movq 0xa0(%rsp), %rsi
movq 0x98(%rsp), %rdx
callq 0x52f0
movq 0x18(%rsp), %rax
movl $0x0, 0x60(%rax)
movb $0x1, 0xb7(%rsp)
jmp 0x33b4
movq 0x18(%rsp), %rax
cmpl $0x1, 0x60(%rax)
jne 0x3013
movq 0x18(%rsp), %rdi
movq 0x98(%rsp), %rdx
movq %rdi, %rcx
addq $0x40, %rcx
leaq 0xa0(%rsp), %rsi
callq 0x5200
testb $0x1, %al
jne 0x2fd3
movb $0x0, 0xb7(%rsp)
jmp 0x33b4
movq 0x18(%rsp), %rax
movq 0xa0(%rsp), %rcx
addq $0x1, %rcx
movq %rcx, 0xa0(%rsp)
movq 0x40(%rax), %rsi
andq $0x1, %rsi
movl $0x3, %ecx
movl $0x2, %edx
cmpq $0x0, %rsi
cmovnel %edx, %ecx
movl %ecx, 0x60(%rax)
movq 0x40(%rax), %rcx
shrq %rcx
movq %rcx, 0x40(%rax)
movq 0x18(%rsp), %rax
cmpl $0x2, 0x60(%rax)
jne 0x317d
movq 0x18(%rsp), %rcx
movq 0x40(%rcx), %rax
movq %rax, 0x48(%rsp)
movq 0x28(%rcx), %rax
addq 0x48(%rsp), %rax
cmpq 0x38(%rcx), %rax
jbe 0x3097
movl $0x10, %edi
callq 0x20b0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x8(%rsp)
leaq 0x3130(%rip), %rsi      # 0x618b
callq 0x2080
jmp 0x3062
movq 0x8(%rsp), %rdi
movq 0x5f82(%rip), %rsi      # 0x8ff0
movq 0x5f4b(%rip), %rdx      # 0x8fc0
callq 0x22f0
movq 0x8(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x58(%rsp)
movl %eax, 0x54(%rsp)
callq 0x2140
jmp 0x33c5
movq 0xa0(%rsp), %rax
cmpq 0x98(%rsp), %rax
jne 0x30b6
movb $0x0, 0xb7(%rsp)
jmp 0x33b4
movq 0xa0(%rsp), %rax
addq 0x48(%rsp), %rax
cmpq 0x98(%rsp), %rax
jbe 0x312f
movq 0x18(%rsp), %rax
movq 0x98(%rsp), %rcx
movq 0xa0(%rsp), %rdx
subq %rdx, %rcx
movq %rcx, 0x40(%rsp)
movq 0x28(%rax), %rdi
movq 0xa0(%rsp), %rsi
movq 0x40(%rsp), %rdx
callq 0x2170
movq 0x18(%rsp), %rax
movq 0x40(%rsp), %rcx
addq 0x28(%rax), %rcx
movq %rcx, 0x28(%rax)
movq 0x40(%rsp), %rdx
movq 0x40(%rax), %rcx
subq %rdx, %rcx
movq %rcx, 0x40(%rax)
movb $0x0, 0xb7(%rsp)
jmp 0x33b4
movq 0x18(%rsp), %rax
movq 0x28(%rax), %rdi
movq 0xa0(%rsp), %rsi
movq 0x48(%rsp), %rdx
callq 0x2170
movq 0x18(%rsp), %rax
movq 0x48(%rsp), %rcx
addq 0x28(%rax), %rcx
movq %rcx, 0x28(%rax)
movq 0x48(%rsp), %rcx
addq 0xa0(%rsp), %rcx
movq %rcx, 0xa0(%rsp)
movl $0x1, 0x60(%rax)
jmp 0x3365
movq 0x18(%rsp), %rax
cmpl $0x3, 0x60(%rax)
jne 0x3363
movq 0x18(%rsp), %rax
movq 0x40(%rax), %rax
andq $0x7, %rax
movq %rax, 0x38(%rsp)
cmpq $0x0, 0x38(%rsp)
je 0x31b6
movq 0x18(%rsp), %rax
movq 0x38(%rsp), %rcx
movq %rcx, 0x48(%rax)
jmp 0x3200
movq 0x18(%rsp), %rdi
movq 0x98(%rsp), %rdx
movq %rdi, %rcx
addq $0x40, %rcx
addq $0x8, %rcx
leaq 0xa0(%rsp), %rsi
callq 0x5200
testb $0x1, %al
jne 0x31ec
movb $0x0, 0xb7(%rsp)
jmp 0x33b4
movq 0xa0(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xa0(%rsp)
movq 0x18(%rsp), %rcx
movq 0x40(%rcx), %rax
shrq $0x3, %rax
movq %rax, 0x30(%rsp)
movq 0x48(%rcx), %rax
addq $0x5, %rax
subq $0x1, %rax
movq %rax, 0x28(%rsp)
movq 0x28(%rcx), %rax
xorl %edx, %edx
subq 0x30(%rsp), %rdx
addq %rdx, %rax
movq %rax, 0x20(%rsp)
movq 0x20(%rsp), %rax
cmpq 0x38(%rcx), %rax
jae 0x3279
movq 0x18(%rsp), %rcx
movq 0x20(%rsp), %rax
cmpq 0x30(%rcx), %rax
jb 0x3279
movq 0x18(%rsp), %rcx
movq 0x28(%rcx), %rax
addq 0x28(%rsp), %rax
cmpq 0x38(%rcx), %rax
ja 0x3279
movq 0x18(%rsp), %rcx
movq 0x28(%rcx), %rax
addq 0x28(%rsp), %rax
cmpq 0x28(%rcx), %rax
jae 0x32ce
movl $0x10, %edi
callq 0x20b0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, (%rsp)
leaq 0x2ef7(%rip), %rsi      # 0x618b
callq 0x2080
jmp 0x329b
movq (%rsp), %rdi
movq 0x5d4a(%rip), %rsi      # 0x8ff0
movq 0x5d13(%rip), %rdx      # 0x8fc0
callq 0x22f0
movq (%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x58(%rsp)
movl %eax, 0x54(%rsp)
callq 0x2140
jmp 0x33c5
movq 0x18(%rsp), %rcx
movq 0x20(%rsp), %rax
addq 0x28(%rsp), %rax
cmpq 0x28(%rcx), %rax
jae 0x330f
movq 0x18(%rsp), %rax
movq 0x28(%rax), %rdi
movq 0x20(%rsp), %rsi
movq 0x28(%rsp), %rdx
callq 0x2170
movq 0x18(%rsp), %rax
movq 0x28(%rsp), %rcx
addq 0x28(%rax), %rcx
movq %rcx, 0x28(%rax)
jmp 0x3357
jmp 0x3311
cmpq $0x0, 0x28(%rsp)
jbe 0x3355
movq 0x18(%rsp), %rax
movq 0x20(%rsp), %rcx
movb (%rcx), %dl
movq 0x28(%rax), %rcx
movb %dl, (%rcx)
movq 0x28(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x28(%rax)
movq 0x20(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x20(%rsp)
movq 0x28(%rsp), %rax
addq $-0x1, %rax
movq %rax, 0x28(%rsp)
jmp 0x3311
jmp 0x3357
movq 0x18(%rsp), %rax
movl $0x1, 0x60(%rax)
jmp 0x3365
jmp 0x2f3b
movq 0x18(%rsp), %rcx
movq 0x28(%rcx), %rax
cmpq 0x38(%rcx), %rax
jne 0x33ac
movq 0x90(%rsp), %rdi
movq 0xa0(%rsp), %rsi
movq 0x98(%rsp), %rdx
callq 0x52f0
movq 0x18(%rsp), %rax
movl $0x0, 0x60(%rax)
movb $0x1, 0xb7(%rsp)
jmp 0x33b4
movb $0x0, 0xb7(%rsp)
movb 0xb7(%rsp), %al
andb $0x1, %al
addq $0xb8, %rsp
retq
movq 0x58(%rsp), %rdi
callq 0x2300
nop