// File: /workspace/github_c_makefile_star2_O1/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
subq $0x28, %rsp
movq %rsi, %r15
movq %rdi, %rbx
movq 0x38(%rdi), %r12
testq %r12, %r12
jne 0x3fb4c
jmp 0x3fa00
movq %rax, %r12
movl 0x5c(%rax), %eax
movl %eax, 0x60(%r12)
cmpl $0x0, (%r12)
jne 0x3fa24
movq 0x38(%rbx), %rdi
testq %rdi, %rdi
je 0x3fa0e
callq 0x5295e
movq %rbx, %rdi
callq 0x52e66
movq %rax, 0x38(%rbx)
testq %rax, %rax
jne 0x3f9ee
jmp 0x3fb40
cmpl $-0x2, 0x258(%rbx)
je 0x3fa37
movl 0x4(%r12), %eax
cmpl $-0x2, %eax
jne 0x3fab6
movq %rbx, %rdi
callq 0x4ee88
movq %rax, 0x50(%r12)
testq %rax, %rax
je 0x3fb40
cmpl $0x1, 0x8(%rax)
jne 0x3fb40
movq %rbx, %rdi
movq %rax, %rsi
callq 0x387d9
movq %rax, 0x48(%r12)
testq %rax, %rax
je 0x3fb40
cmpl $0x0, 0x2c(%rax)
jne 0x3fb43
movq 0x18(%rbx), %rax
movq 0x38(%rax), %rdi
callq 0x8cb0b
cmpl $0x2, %eax
je 0x3fb43
leaq 0x88f0(%rbx), %r14
movq %r14, %rdi
callq 0x4750
movl $0x1, 0x88a4(%rbx)
movq %r14, %rdi
callq 0x4340
jmp 0x3fb43
xorl %ecx, %ecx
movl 0x258(%rbx), %edx
cmpl %edx, %eax
jl 0x3fadd
testl %edx, %edx
js 0x3fb26
cmpl %edx, %eax
jne 0x3fb26
movq 0x10(%r12), %rsi
addq 0x8(%r12), %rsi
cmpq 0x260(%rbx), %rsi
jg 0x3fb26
movslq (%r12), %rsi
movq %rbx, %rdi
movl $0x1, %edx
callq 0x55990
testl %eax, %eax
jne 0x3fb40
movq 0x38(%rbx), %rdi
callq 0x5295e
movq %rbx, %rdi
callq 0x52e66
movq %rax, 0x38(%rbx)
testq %rax, %rax
je 0x3fb40
movq %rax, %r12
cmpl $0x0, (%rax)
je 0x3fafb
movl 0x4(%r12), %eax
cmpl $-0x2, %eax
sete %cl
jne 0x3fab8
jmp 0x3fa37
cmpl %edx, %eax
sete %al
orb %al, %cl
testb $0x1, %cl
jne 0x3fa37
movl $0x1, 0x8890(%rbx)
xorl %r12d, %r12d
testq %r12, %r12
je 0x400f9
movq 0x90(%r12), %rdi
testq %rdi, %rdi
je 0x3fb6a
movq $0x0, 0x90(%r12)
callq 0x52c5d
movl 0x5c(%r12), %eax
cmpl 0x58(%r12), %eax
jne 0x3fb9d
cmpq %r12, 0x38(%rbx)
jne 0x3fb84
movq $0x0, 0x38(%rbx)
cmpq %r12, 0x40(%rbx)
jne 0x3fb92
movq $0x0, 0x40(%rbx)
movq %r12, %rdi
callq 0x5295e
xorl %r12d, %r12d
movq %r15, 0x18(%rsp)
cmpq $0x0, 0x40(%rbx)
jne 0x3fbad
movq %r12, 0x40(%rbx)
leaq 0x88f0(%rbx), %rax
movq %rax, 0x20(%rsp)
movl $0x2, %eax
movl %eax, %eax
movq %rax, (%rsp)
leaq 0x5c47d(%rip), %r13     # 0x9c048
movl $0x3, %eax
movl %eax, %eax
movq %rax, 0x10(%rsp)
movq $0x0, 0x8(%rsp)
movq 0x8970(%rbx), %rdi
testq %rdi, %rdi
je 0x3fc06
movq 0x8(%rdi), %r15
movq 0x10(%rdi), %rbp
callq 0x45c0
movq $0x0, 0x8970(%rbx)
jmp 0x3fc19
movq 0x40(%rbx), %r15
cmpl $0x0, 0x8978(%rbx)
je 0x3fcc1
xorl %ebp, %ebp
testq %r15, %r15
setne %al
testq %rbp, %rbp
setne %cl
andb %al, %cl
movl $0x2, %r14d
cmpb $0x1, %cl
jne 0x3fef2
movq 0x18(%rbx), %rcx
movq %rbx, %rdi
movq %r15, %rsi
movq %rbp, %rdx
callq 0x3f393
testl %eax, %eax
je 0x3fe9e
movl $0x1, %edi
leaq 0x5c7da(%rip), %rsi     # 0x9c436
leaq 0x5c7e3(%rip), %rdx     # 0x9c446
xorl %eax, %eax
callq 0x14378
movq %rbp, %rdi
callq 0x52c5d
movq $0x0, 0x90(%r15)
movl $0x1, %eax
movl %eax, %eax
movslq (%r13,%rax,4), %rax
addq %r13, %rax
jmpq *%rax
cmpq %r15, 0x38(%rbx)
jne 0x3fc9c
movq $0x0, 0x38(%rbx)
cmpq %r15, %r12
movl $0x0, %eax
cmoveq %rax, %r12
cmpq %r15, 0x40(%rbx)
jne 0x3fcb6
movq $0x0, 0x40(%rbx)
movq %r15, %rdi
callq 0x5295e
xorl %r15d, %r15d
testq %r15, %r15
je 0x3fcd4
movl 0x60(%r15), %eax
cmpl 0x58(%r15), %eax
jne 0x3fde5
movq %rbx, %rdi
callq 0x52e66
movq %rax, %r15
testq %rax, %rax
je 0x3fcfc
movl 0x5c(%r15), %eax
movl %eax, 0x60(%r15)
cmpl $0x0, (%r15)
jne 0x3fd14
movq %r15, %rdi
callq 0x5295e
jmp 0x3fcd4
cmpq $0x0, 0x88b8(%rbx)
je 0x3fee4
movl $0x1, 0x8978(%rbx)
cmpl $0x0, 0x8978(%rbx)
jne 0x3feec
movl 0x258(%rbx), %eax
cmpl $-0x2, %eax
je 0x3fd6d
movl 0x4(%r15), %ecx
cmpl $-0x2, %ecx
je 0x3fd6d
cmpl %eax, %ecx
jne 0x3feff
cmpl $-0x1, %eax
je 0x3fd6d
movq 0x8(%r15), %rcx
cmpq 0x268(%rbx), %rcx
jg 0x3ff27
cmpl $-0x1, %eax
je 0x3fd6d
movq 0x10(%r15), %rax
addq 0x8(%r15), %rax
cmpq 0x260(%rbx), %rax
jle 0x3ff7a
movq %r15, 0x40(%rbx)
movq %rbx, %rdi
callq 0x4ee88
movq %rax, 0x50(%r15)
movl $0x1, %r14d
testq %rax, %rax
je 0x3fef2
cmpl $0x1, 0x8(%rax)
jne 0x3fef2
movq %rbx, %rdi
movq %rax, %rsi
callq 0x387d9
movq %rax, 0x48(%r15)
testq %rax, %rax
je 0x3fef2
cmpl $0x0, 0x2c(%rax)
jne 0x3fde5
movq 0x18(%rbx), %rax
movq 0x38(%rax), %rdi
callq 0x8cb0b
cmpl $0x2, %eax
je 0x3fde5
movq 0x20(%rsp), %r14
movq %r14, %rdi
callq 0x4750
movl $0x1, 0x88a4(%rbx)
movq %r14, %rdi
callq 0x4340
cmpl $0x0, 0x28(%r15)
je 0x3fc8e
movq %rbx, %rdi
callq 0x5400a
movq %rax, 0x90(%r15)
testq %rax, %rax
je 0x3fee4
movq %rax, %rbp
movl 0x60(%r15), %eax
incl %eax
movl %eax, 0x60(%r15)
movl %eax, 0xe8(%rbp)
movl $0x0, 0xe4(%rbp)
movq (%rbp), %rax
movl 0x18(%rax), %ecx
movl %ecx, 0xe0(%rbp)
movq 0x8(%rax), %rcx
movq %rcx, 0x20(%rbp)
movl 0x258(%rbx), %edx
cmpl $-0x2, %edx
je 0x3fc19
movl 0x4(%rax), %esi
cmpl $-0x2, %esi
je 0x3fc19
cmpl %edx, %esi
jne 0x3ff4f
cmpl $-0x1, %edx
je 0x3fc19
cmpq 0x268(%rbx), %rcx
jle 0x3ffa9
movl $0x1, 0x8978(%rbx)
movq %rbp, %rdi
callq 0x52c5d
movq $0x0, 0x90(%r15)
movq (%rsp), %rax
movslq (%r13,%rax,4), %rax
addq %r13, %rax
jmpq *%rax
cmpq $0x0, 0x88b8(%rbx)
je 0x3feda
cmpq $0x0, 0x8970(%rbx)
jne 0x3fef2
movq 0x88c0(%rbx), %rdi
callq 0x3746c
movl %eax, %ebp
movq 0x88c0(%rbx), %rdi
callq 0x38318
xorl %r14d, %r14d
cmpl %eax, %ebp
setg %r14b
addl %r14d, %r14d
jmp 0x3fef2
movq %rbp, 0x8(%rsp)
movq %r15, %r12
jmp 0x3fef2
movl $0x1, %r14d
jmp 0x3fef2
movl $0x2, %r14d
movl %r14d, %eax
movslq (%r13,%rax,4), %rax
addq %r13, %rax
jmpq *%rax
movq %r15, %rdi
callq 0x5295e
movq $0x0, 0x40(%rbx)
movl $0x1, 0x8978(%rbx)
movq (%rsp), %rax
movslq (%r13,%rax,4), %rax
addq %r13, %rax
jmpq *%rax
movq %r15, %rdi
callq 0x5295e
movq $0x0, 0x40(%rbx)
movl $0x1, 0x8978(%rbx)
movq (%rsp), %rax
movslq (%r13,%rax,4), %rax
addq %r13, %rax
jmpq *%rax
movl $0x1, 0x8978(%rbx)
movq %rbp, %rdi
callq 0x52c5d
movq $0x0, 0x90(%r15)
movq (%rsp), %rax
movslq (%r13,%rax,4), %rax
addq %r13, %rax
jmpq *%rax
movl 0x58(%r15), %eax
movl %eax, 0x60(%r15)
movslq (%r15), %rsi
movq %rbx, %rdi
movl $0x1, %edx
callq 0x55990
movq %r15, %rdi
callq 0x5295e
movq 0x10(%rsp), %rax
movslq (%r13,%rax,4), %rax
addq %r13, %rax
jmpq *%rax
cmpl $-0x1, %edx
je 0x3fc19
addq 0x10(%rax), %rcx
cmpq 0x260(%rbx), %rcx
jg 0x3fc19
movq %rbp, %rdi
callq 0x52c5d
movq $0x0, 0x90(%r15)
movq 0x10(%rsp), %rax
movslq (%r13,%rax,4), %rax
addq %r13, %rax
jmpq *%rax
cmpq $0x0, 0x88b8(%rbx)
je 0x40097
cmpl $0x0, 0x8978(%rbx)
movq 0x18(%rsp), %r15
je 0x40022
movq 0x88c0(%rbx), %rdi
callq 0x373c6
testl %eax, %eax
je 0x40022
movl $0x1, 0x8890(%rbx)
xorl %ebp, %ebp
jmp 0x400ba
movq 0x88c0(%rbx), %rdi
callq 0x37249
testq %rax, %rax
je 0x4009e
movq %rax, %r14
movq %rax, %rdi
callq 0x37576
testq %rax, %rax
je 0x4009e
movq %r14, %rdi
callq 0x37576
movq 0x8(%rax), %r12
movq 0x10(%rax), %rcx
movq %rcx, 0x8(%rsp)
cmpl $0x0, 0x20(%rax)
je 0x40116
leaq 0x5c3cd(%rip), %rsi     # 0x9c436
leaq 0x5c413(%rip), %rdx     # 0x9c483
xorl %ebp, %ebp
movl $0x1, %edi
xorl %eax, %eax
callq 0x14378
movl $0x0, 0x8890(%rbx)
movq %r14, %rdi
movl $0x1, %esi
callq 0x37551
jmp 0x400ba
movq 0x18(%rsp), %r15
jmp 0x400bf
leaq 0x5c391(%rip), %rsi     # 0x9c436
leaq 0x5c3b2(%rip), %rdx     # 0x9c45e
xorl %ebp, %ebp
movl $0x1, %edi
xorl %eax, %eax
callq 0x14378
testb %bpl, %bpl
je 0x400f9
movq %r12, (%r15)
movq %r12, 0x38(%rbx)
testq %r12, %r12
movq 0x8(%rsp), %rax
je 0x400e8
movq %rax, 0x90(%r12)
testq %rax, %rax
je 0x4010a
movl 0xe8(%rax), %ecx
movl %ecx, 0x5c(%r12)
testq %rax, %rax
je 0x4010a
movl $0x0, 0xe4(%rax)
jmp 0x400fb
xorl %eax, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x1, 0x8890(%rbx)
jmp 0x400fb
movq %r14, %rdi
movl $0x1, %esi
callq 0x37551
movb $0x1, %bpl
jmp 0x400ba