// File: /workspace/github_c_makefile_star2_O3/samtools[P]htslib/cram/cram_decode.c
// Function: cram_next_slice
cram_slice *cram_next_slice(cram_fd *fd, cram_container **cp) {
    cram_container *c_curr;  // container being consumed via cram_get_seq()
    cram_slice *s_curr = NULL;

    // Populate the first container if unknown.
    if (!(c_curr = fd->ctr)) {
        if (!(c_curr = cram_first_slice(fd)))
            return NULL;
    }

    // Discard previous slice
    if ((s_curr = c_curr->slice)) {
        c_curr->slice = NULL;
        cram_free_slice(s_curr);
        s_curr = NULL;
    }

    // If we've consumed all slices in this container, also discard
    // the container too.
    if (c_curr->curr_slice == c_curr->max_slice) {
        if (fd->ctr == c_curr)
            fd->ctr = NULL;
        if (fd->ctr_mt == c_curr)
            fd->ctr_mt = NULL;
        cram_free_container(c_curr);
        c_curr = NULL;
    }

    if (!fd->ctr_mt)
        fd->ctr_mt = c_curr;

    // Fetch the next slice (and the container if necessary).
    //
    // If single threaded this loop bails out as soon as it finds
    // a slice in range.  In this case c_next and c_curr end up being
    // the same thing.
    //
    // If multi-threaded, we loop until we have filled out
    // thread pool input queue.  Here c_next and c_curr *may* differ, as
    // can fd->ctr and fd->ctr_mt.
    for (;;) {
        cram_container *c_next = fd->ctr_mt;
        cram_slice *s_next = NULL;

        // Next slice; either from the last job we failed to push
        // to the input queue or via more I/O.
        if (fd->job_pending) {
            cram_decode_job *j = (cram_decode_job *)fd->job_pending;
            c_next = j->c;
            s_next = j->s;
            free(fd->job_pending);
            fd->job_pending = NULL;
        } else if (!fd->ooc) {
        empty_container:
            if (!c_next || c_next->curr_slice_mt == c_next->max_slice) {
                // new container
                for(;;) {
                    if (!(c_next = cram_read_container(fd))) {
                        if (fd->pool) {
                            fd->ooc = 1;
                            break;
                        }

                        return NULL;
                    }
                    c_next->curr_slice_mt = c_next->curr_slice;

                    if (c_next->length != 0)
                        break;

                    cram_free_container(c_next);
                }
                if (fd->ooc)
                    break;

//                printf("%p %d:%ld-%ld vs %d:%ld-%ld\n", fd,
//                       c_next->ref_seq_id, c_next->ref_seq_start, c_next->ref_seq_start+c_next->ref_seq_span-1,
//                       fd->range.refid, fd->range.start, fd->range.end);

                /* Skip containers not yet spanning our range */
                if (fd->range.refid != -2 && c_next->ref_seq_id != -2) {
                    // ref_id beyond end of range; bail out
                    if (c_next->ref_seq_id != fd->range.refid) {
                        cram_free_container(c_next);
                        fd->ctr_mt = NULL;
                        fd->ooc = 1;
                        break;
                    }

                    // position beyond end of range; bail out
                    if (fd->range.refid != -1 &&
                        c_next->ref_seq_start > fd->range.end) {
                        cram_free_container(c_next);
                        fd->ctr_mt = NULL;
                        fd->ooc = 1;
                        break;
                    }

                    // before start of range; skip to next container
                    if (fd->range.refid != -1 &&
                        c_next->ref_seq_start + c_next->ref_seq_span-1 <
                        fd->range.start) {
                        c_next->curr_slice_mt = c_next->max_slice;
                        cram_seek(fd, c_next->length, SEEK_CUR);
                        cram_free_container(c_next);
                        c_next = NULL;
                        continue;
                    }
                }

                // Container is valid range, so remember it for restarting
                // this function.
                fd->ctr_mt = c_next;

                if (!(c_next->comp_hdr_block = cram_read_block(fd)))
                    return NULL;
                if (c_next->comp_hdr_block->content_type != COMPRESSION_HEADER)
                    return NULL;

                c_next->comp_hdr =
                    cram_decode_compression_header(fd, c_next->comp_hdr_block);
                if (!c_next->comp_hdr)
                    return NULL;

                if (!c_next->comp_hdr->AP_delta &&
                    sam_hrecs_sort_order(fd->header->hrecs) != ORDER_COORD) {
                    pthread_mutex_lock(&fd->ref_lock);
                    fd->unsorted = 1;
                    pthread_mutex_unlock(&fd->ref_lock);
                }
            }

            if (c_next->num_records == 0) {
                if (fd->ctr == c_next)
                    fd->ctr = NULL;
                if (c_curr == c_next)
                    c_curr = NULL;
                if (fd->ctr_mt == c_next)
                    fd->ctr_mt = NULL;
                cram_free_container(c_next);
                c_next = NULL;
                goto empty_container;
            }

            if (!(s_next = c_next->slice = cram_read_slice(fd)))
                return NULL;

            s_next->slice_num = ++c_next->curr_slice_mt;
            s_next->curr_rec = 0;
            s_next->max_rec = s_next->hdr->num_records;

            s_next->last_apos = s_next->hdr->ref_seq_start;

            // We know the container overlaps our range, but with multi-slice
            // containers we may have slices that do not.  Skip these also.
            if (fd->range.refid != -2 && s_next->hdr->ref_seq_id != -2) {
                // ref_id beyond end of range; bail out
                if (s_next->hdr->ref_seq_id != fd->range.refid) {
                    fd->ooc = 1;
                    cram_free_slice(s_next);
                    c_next->slice = s_next = NULL;
                    break;
                }

                // position beyond end of range; bail out
                if (fd->range.refid != -1 &&
                    s_next->hdr->ref_seq_start > fd->range.end) {
                    fd->ooc = 1;
                    cram_free_slice(s_next);
                    c_next->slice = s_next = NULL;
                    break;
                }

                // before start of range; skip to next slice
                if (fd->range.refid != -1 &&
                    s_next->hdr->ref_seq_start + s_next->hdr->ref_seq_span-1 <
                    fd->range.start) {
                    cram_free_slice(s_next);
                    c_next->slice = s_next = NULL;
                    continue;
                }
            }
        } // end: if (!fd->ooc)

        if (!c_next || !s_next)
            break;

        // Decode the slice, either right now (non-threaded) or by pushing
        // it to the a decode queue (threaded).
        if (cram_decode_slice_mt(fd, c_next, s_next, fd->header) != 0) {
            hts_log_error("Failure to decode slice");
            cram_free_slice(s_next);
            c_next->slice = NULL;
            return NULL;
        }

        // No thread pool, so don't loop again
        if (!fd->pool) {
            c_curr = c_next;
            s_curr = s_next;
            break;
        }

        // With thread pool, but we have a job pending so our decode queue
        // is full.
        if (fd->job_pending)
            break;

        // Otherwise we're threaded with room in the decode input queue, so
        // keep reading slices for decode.
        // Push it a bit far, to qsize in queue rather than pending arrival,
        // as cram tends to be a bit bursty in decode timings.
        if (hts_tpool_process_len(fd->rqueue) >
            hts_tpool_process_qsize(fd->rqueue))
            break;
    } // end of for(;;)


    // When not threaded we've already have c_curr and s_curr.
    // Otherwise we need get them by pulling off the decode output queue.
    if (fd->pool) {
        hts_tpool_result *res;
        cram_decode_job *j;

        if (fd->ooc && hts_tpool_process_empty(fd->rqueue)) {
            fd->eof = 1;
            return NULL;
        }

        res = hts_tpool_next_result_wait(fd->rqueue);

        if (!res || !hts_tpool_result_data(res)) {
            hts_log_error("Call to hts_tpool_next_result failed");
            return NULL;
        }

        j = (cram_decode_job *)hts_tpool_result_data(res);
        c_curr = j->c;
        s_curr = j->s;

        if (j->exit_code != 0) {
            hts_log_error("Slice decode failure");
            fd->eof = 0;
            hts_tpool_delete_result(res, 1);
            return NULL;
        }

        hts_tpool_delete_result(res, 1);
    }

    *cp = c_curr;

    // Update current slice being processed (as opposed to current
    // slice in the multi-threaded reahead.
    fd->ctr = c_curr;
    if (c_curr) {
        c_curr->slice = s_curr;
        if (s_curr)
            c_curr->curr_slice = s_curr->slice_num;
    }
    if (s_curr)
        s_curr->curr_rec = 0;
    else
        fd->eof = 1;

    return s_curr;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %r14
movq %rdi, %rbx
movq 0x38(%rdi), %r15
testq %r15, %r15
je 0x3ddac
movq 0x90(%r15), %rdi
testq %rdi, %rdi
je 0x3da64
movq $0x0, 0x90(%r15)
callq 0x50127
movl 0x5c(%r15), %eax
cmpl 0x58(%r15), %eax
jne 0x3da95
cmpq %r15, 0x38(%rbx)
jne 0x3da7c
movq $0x0, 0x38(%rbx)
cmpq %r15, 0x40(%rbx)
jne 0x3da8a
movq $0x0, 0x40(%rbx)
movq %r15, %rdi
callq 0x4fe2e
xorl %r15d, %r15d
movq %r14, (%rsp)
cmpq $0x0, 0x40(%rbx)
jne 0x3daa4
movq %r15, 0x40(%rbx)
leaq 0x88f0(%rbx), %rbp
xorl %r14d, %r14d
movq 0x8970(%rbx), %rdi
testq %rdi, %rdi
je 0x3db47
movq 0x8(%rdi), %r13
movq 0x10(%rdi), %r12
callq 0x45c0
movq $0x0, 0x8970(%rbx)
testq %r13, %r13
je 0x3df4a
testq %r12, %r12
je 0x3df4a
movq 0x18(%rbx), %rcx
movq %rbx, %rdi
movq %r13, %rsi
movq %r12, %rdx
callq 0x3d3e3
testl %eax, %eax
jne 0x3dee7
cmpq $0x0, 0x88b8(%rbx)
je 0x3df19
cmpq $0x0, 0x8970(%rbx)
jne 0x3df58
movq 0x88c0(%rbx), %rdi
callq 0x3609a
movl %eax, %r12d
movq 0x88c0(%rbx), %rdi
callq 0x36ef7
cmpl %eax, %r12d
jle 0x3daae
jmp 0x3df4a
cmpl $0x0, 0x8978(%rbx)
jne 0x3df4a
movq 0x40(%rbx), %r13
testq %r13, %r13
je 0x3db74
movl 0x60(%r13), %eax
cmpl 0x58(%r13), %eax
je 0x3db74
jmp 0x3dc56
movq %r13, %rdi
callq 0x4fe2e
movq %rbx, %rdi
callq 0x5032e
movq %rax, %r13
testq %rax, %rax
je 0x3dd65
movl 0x5c(%r13), %eax
movl %eax, 0x60(%r13)
movslq (%r13), %rsi
testq %rsi, %rsi
je 0x3db6c
cmpl $0x0, 0x8978(%rbx)
jne 0x3df4a
movl 0x258(%rbx), %eax
cmpl $-0x2, %eax
je 0x3dbe9
movl 0x4(%r13), %ecx
cmpl $-0x2, %ecx
je 0x3dbe9
cmpl %eax, %ecx
jne 0x3df30
cmpl $-0x1, %eax
je 0x3dbe9
movq 0x8(%r13), %rax
cmpq 0x268(%rbx), %rax
jg 0x3df30
addq 0x10(%r13), %rax
cmpq 0x260(%rbx), %rax
jle 0x3dd43
movq %r13, 0x40(%rbx)
movq %rbx, %rdi
callq 0x4c6b7
movq %rax, 0x50(%r13)
testq %rax, %rax
je 0x3dd97
cmpl $0x1, 0x8(%rax)
jne 0x3dd97
movq %rbx, %rdi
movq %rax, %rsi
callq 0x373d4
movq %rax, 0x48(%r13)
testq %rax, %rax
je 0x3dd97
cmpl $0x0, 0x2c(%rax)
jne 0x3dc56
movq 0x18(%rbx), %rax
movq 0x38(%rax), %rdi
callq 0x8a178
cmpl $0x2, %eax
je 0x3dc56
movq %rbp, %rdi
callq 0x4750
movl $0x1, 0x88a4(%rbx)
movq %rbp, %rdi
callq 0x4340
cmpl $0x0, 0x28(%r13)
jne 0x3dc90
cmpq %r13, 0x38(%rbx)
jne 0x3dc6b
movq $0x0, 0x38(%rbx)
cmpq %r13, %r15
cmoveq %r14, %r15
cmpq %r13, 0x40(%rbx)
jne 0x3dc80
movq $0x0, 0x40(%rbx)
movq %r13, %rdi
callq 0x4fe2e
xorl %r13d, %r13d
jmp 0x3db58
movq %rbx, %rdi
callq 0x514d9
movq %rax, 0x90(%r13)
testq %rax, %rax
je 0x3dd97
movq %rax, %r12
movl 0x60(%r13), %eax
incl %eax
movl %eax, 0x60(%r13)
movl %eax, 0xe8(%r12)
movl $0x0, 0xe4(%r12)
movq (%r12), %rax
movl 0x18(%rax), %ecx
movl %ecx, 0xe0(%r12)
movq 0x8(%rax), %rcx
movq %rcx, 0x20(%r12)
movl 0x258(%rbx), %edx
cmpl $-0x2, %edx
je 0x3dad6
movl 0x4(%rax), %esi
cmpl $-0x2, %esi
je 0x3dad6
cmpl %edx, %esi
jne 0x3e07c
cmpl $-0x1, %edx
je 0x3dad6
cmpq 0x268(%rbx), %rcx
jg 0x3e07c
addq 0x10(%rax), %rcx
cmpq 0x260(%rbx), %rcx
jg 0x3dad6
movq %r12, %rdi
callq 0x50127
movq $0x0, 0x90(%r13)
jmp 0x3daae
movl 0x58(%r13), %eax
movl %eax, 0x60(%r13)
movq %rbx, %rdi
movl $0x1, %edx
callq 0x53001
movq %r13, %rdi
callq 0x4fe2e
jmp 0x3daae
cmpq $0x0, 0x88b8(%rbx)
je 0x3dd97
movl $0x1, 0x8978(%rbx)
movq 0x88c0(%rbx), %rdi
callq 0x35ff4
testl %eax, %eax
je 0x3df65
movl $0x1, 0x8890(%rbx)
xorl %r12d, %r12d
movq %r12, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
xorl %r12d, %r12d
xorl %r15d, %r15d
testq %r15, %r15
je 0x3ddbf
movq %r15, %rdi
callq 0x4fe2e
movq %rbx, %rdi
callq 0x5032e
movq %rax, 0x38(%rbx)
testq %rax, %rax
je 0x3dd9a
movq %rax, %r15
movl (%rax), %eax
movl 0x5c(%r15), %ecx
movl %ecx, 0x60(%r15)
testl %eax, %eax
je 0x3ddb2
cmpl $-0x2, 0x258(%rbx)
je 0x3ddf3
movl 0x4(%r15), %ecx
cmpl $-0x2, %ecx
jne 0x3de68
movq %rbx, %rdi
callq 0x4c6b7
movq %rax, 0x50(%r15)
testq %rax, %rax
je 0x3dd97
cmpl $0x1, 0x8(%rax)
jne 0x3dd97
movq %rbx, %rdi
movq %rax, %rsi
callq 0x373d4
movq %rax, 0x48(%r15)
testq %rax, %rax
je 0x3dd97
cmpl $0x0, 0x2c(%rax)
jne 0x3da48
movq 0x18(%rbx), %rax
movq 0x38(%rax), %rdi
callq 0x8a178
cmpl $0x2, %eax
je 0x3da48
leaq 0x88f0(%rbx), %r12
movq %r12, %rdi
callq 0x4750
movl $0x1, 0x88a4(%rbx)
movq %r12, %rdi
callq 0x4340
jmp 0x3da48
xorl %r12d, %r12d
movl 0x258(%rbx), %edx
cmpl %edx, %ecx
jl 0x3de9a
testl %edx, %edx
js 0x3e06f
cmpl %edx, %ecx
jne 0x3e06f
movq 0x10(%r15), %rcx
addq 0x8(%r15), %rcx
cmpq 0x260(%rbx), %rcx
jg 0x3ddf3
movslq %eax, %rsi
movq %rbx, %rdi
movl $0x1, %edx
callq 0x53001
testl %eax, %eax
jne 0x3dd9a
movq 0x38(%rbx), %rdi
callq 0x4fe2e
movq %rbx, %rdi
callq 0x5032e
movq %rax, 0x38(%rbx)
testq %rax, %rax
je 0x3dd9a
movq %rax, %r15
movl (%rax), %eax
testl %eax, %eax
je 0x3debb
movl 0x4(%r15), %ecx
cmpl $-0x2, %ecx
jne 0x3de6b
jmp 0x3ddf3
leaq 0x5b5c4(%rip), %rsi     # 0x994b2
leaq 0x5b5cd(%rip), %rdx     # 0x994c2
movl $0x1, %edi
xorl %eax, %eax
callq 0x13de5
movq %r12, %rdi
callq 0x50127
movq $0x0, 0x90(%r13)
jmp 0x3dd97
movq (%rsp), %rax
movq %r13, (%rax)
movq %r13, 0x38(%rbx)
movq %r12, 0x90(%r13)
jmp 0x3e048
movq %r13, %rdi
callq 0x4fe2e
movq $0x0, 0x40(%rbx)
movl $0x1, 0x8978(%rbx)
cmpq $0x0, 0x88b8(%rbx)
je 0x3dfef
cmpl $0x0, 0x8978(%rbx)
jne 0x3dd79
movq 0x88c0(%rbx), %rdi
callq 0x35e75
testq %rax, %rax
je 0x3dfcd
movq %rax, %r15
movq %rax, %rdi
callq 0x361a4
testq %rax, %rax
je 0x3dfcd
movq %r15, %rdi
callq 0x361a4
cmpl $0x0, 0x20(%rax)
je 0x3e013
leaq 0x5b517(%rip), %rsi     # 0x994b2
leaq 0x5b55d(%rip), %rdx     # 0x994ff
xorl %r12d, %r12d
movl $0x1, %edi
xorl %eax, %eax
callq 0x13de5
movl $0x0, 0x8890(%rbx)
movq %r15, %rdi
movl $0x1, %esi
callq 0x3617f
jmp 0x3dd9a
leaq 0x5b4de(%rip), %rsi     # 0x994b2
leaq 0x5b4ff(%rip), %rdx     # 0x994da
xorl %r12d, %r12d
movl $0x1, %edi
xorl %eax, %eax
callq 0x13de5
jmp 0x3dd9a
movq (%rsp), %rax
movq %r15, (%rax)
movq %r15, 0x38(%rbx)
testq %r15, %r15
je 0x3dd8d
movq $0x0, 0x90(%r15)
jmp 0x3dd8d
movq 0x8(%rax), %r13
movq 0x10(%rax), %r12
movq %r15, %rdi
movl $0x1, %esi
callq 0x3617f
movq (%rsp), %rax
movq %r13, (%rax)
movq %r13, 0x38(%rbx)
testq %r13, %r13
je 0x3e065
movq %r12, 0x90(%r13)
testq %r12, %r12
je 0x3dd8d
movl 0xe8(%r12), %eax
movl %eax, 0x5c(%r13)
movl $0x0, 0xe4(%r12)
jmp 0x3dd9a
testq %r12, %r12
jne 0x3e054
jmp 0x3dd8d
cmpl %edx, %ecx
jne 0x3dd8d
jmp 0x3ddf3
movl $0x1, 0x8978(%rbx)
movq %r12, %rdi
callq 0x50127
movq $0x0, 0x90(%r13)
jmp 0x3df4a