// File: vgteam[P]stream/src/stream.hpp
// Function: bool stream::for_each<Person>(std::istream&, std::function<void (Person&)>&, std::function<void (unsigned long)>&)
bool for_each(std::istream& in,
              std::function<void(T&)>& lambda,
              std::function<void(uint64_t)>& handle_count) {

    ::google::protobuf::io::ZeroCopyInputStream *raw_in =
          new ::google::protobuf::io::IstreamInputStream(&in);
    ::google::protobuf::io::GzipInputStream *gzip_in =
          new ::google::protobuf::io::GzipInputStream(raw_in);
    ::google::protobuf::io::CodedInputStream *coded_in =
          new ::google::protobuf::io::CodedInputStream(gzip_in);

    uint64_t count;
    coded_in->ReadVarint64((::google::protobuf::uint64*) &count);
    // this loop handles a chunked file with many pieces
    // such as we might write in a multithreaded process
    if (!count) return !count;
    do {

        handle_count(count);

        std::string s;
        for (uint64_t i = 0; i < count; ++i) {
            uint32_t msgSize = 0;
            delete coded_in;
            coded_in = new ::google::protobuf::io::CodedInputStream(gzip_in);
            // the messages are prefixed by their size
            coded_in->ReadVarint32(&msgSize);
            if ((msgSize > 0) &&
                (coded_in->ReadString(&s, msgSize))) {
                T object;
                object.ParseFromString(s);
                lambda(object);
            }
        }
    } while (coded_in->ReadVarint64((::google::protobuf::uint64*) &count));

    delete coded_in;
    delete gzip_in;
    delete raw_in;

    return !count;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x100, %rsp            # imm = 0x100
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movl $0x50, %edi
callq 0x4320
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xb8(%rbp)
movq -0x10(%rbp), %rsi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
callq 0x4310
jmp 0xa9ce
movq -0xb8(%rbp), %rax
movq %rax, -0x28(%rbp)
movl $0xb0, %edi
callq 0x4320
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xc0(%rbp)
movq -0x28(%rbp), %rsi
xorl %edx, %edx
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
callq 0x4530
jmp 0xaa02
movq -0xc0(%rbp), %rax
movq %rax, -0x40(%rbp)
movl $0x50, %edi
callq 0x4320
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xc8(%rbp)
movq -0x40(%rbp), %rsi
callq 0xb040
jmp 0xaa2f
movq -0xc8(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rdi
leaq -0x50(%rbp), %rsi
callq 0xb0d0
cmpq $0x0, -0x50(%rbp)
jne 0xaac8
cmpq $0x0, -0x50(%rbp)
setne %al
xorb $-0x1, %al
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0xace2
movq -0xb8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
movl $0x50, %esi
callq 0x4330
jmp 0xacf0
movq -0xc0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
movl $0xb0, %esi
callq 0x4330
jmp 0xacf0
movq -0xc8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
movl $0x50, %esi
callq 0x4330
jmp 0xacf0
jmp 0xaaca
movq -0x20(%rbp), %rdi
movq -0x50(%rbp), %rsi
callq 0xb170
leaq -0x70(%rbp), %rdi
callq 0x4420
movq $0x0, -0x78(%rbp)
movq -0x78(%rbp), %rax
cmpq -0x50(%rbp), %rax
jae 0xac3e
movl $0x0, -0x7c(%rbp)
movq -0x48(%rbp), %rax
movq %rax, -0xd0(%rbp)
cmpq $0x0, %rax
je 0xab2b
movq -0xd0(%rbp), %rdi
callq 0x4490
movq -0xd0(%rbp), %rdi
movl $0x50, %esi
callq 0x4330
movl $0x50, %edi
callq 0x4320
movq %rax, -0xd8(%rbp)
jmp 0xab3e
movq -0xd8(%rbp), %rdi
movq -0x40(%rbp), %rsi
callq 0xb040
jmp 0xab50
movq -0xd8(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rdi
leaq -0x7c(%rbp), %rsi
callq 0xb1b0
jmp 0xab6a
cmpl $0x0, -0x7c(%rbp)
jbe 0xac2b
movq -0x48(%rbp), %rdi
movl -0x7c(%rbp), %edx
leaq -0x70(%rbp), %rsi
callq 0x4150
movb %al, -0xd9(%rbp)
jmp 0xab8c
movb -0xd9(%rbp), %al
testb $0x1, %al
jne 0xab9b
jmp 0xac2b
leaq -0xb0(%rbp), %rdi
callq 0x6c10
jmp 0xaba9
leaq -0xb0(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x45b0
jmp 0xabbb
movq -0x18(%rbp), %rdi
leaq -0xb0(%rbp), %rsi
callq 0xb250
jmp 0xabcd
leaq -0xb0(%rbp), %rdi
callq 0x4b60
jmp 0xac2b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
jmp 0xacd7
movq -0xd8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
movl $0x50, %esi
callq 0x4330
jmp 0xacd7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0x4b60
jmp 0xacd7
jmp 0xac2d
movq -0x78(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x78(%rbp)
jmp 0xaae8
leaq -0x70(%rbp), %rdi
callq 0x41f0
movq -0x48(%rbp), %rdi
leaq -0x50(%rbp), %rsi
callq 0xb0d0
testb $0x1, %al
jne 0xaaca
movq -0x48(%rbp), %rax
movq %rax, -0xe8(%rbp)
cmpq $0x0, %rax
je 0xac8a
movq -0xe8(%rbp), %rdi
callq 0x4490
movq -0xe8(%rbp), %rdi
movl $0x50, %esi
callq 0x4330
movq -0x40(%rbp), %rax
movq %rax, -0xf0(%rbp)
cmpq $0x0, %rax
je 0xaca8
movq -0xf0(%rbp), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
movq -0x28(%rbp), %rax
movq %rax, -0xf8(%rbp)
cmpq $0x0, %rax
je 0xacc6
movq -0xf8(%rbp), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
cmpq $0x0, -0x50(%rbp)
setne %al
xorb $-0x1, %al
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0xace2
leaq -0x70(%rbp), %rdi
callq 0x41f0
jmp 0xacf0
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x100, %rsp            # imm = 0x100
popq %rbp
retq
movq -0x30(%rbp), %rdi
callq 0x4580
nopl (%rax)