// File: karel-brinda[P]ococo/ext/htslib/cram/cram_decode.c
// Function: cram_next_slice
static cram_slice *cram_next_slice(cram_fd *fd, cram_container **cp) {
    cram_container *c;
    cram_slice *s = NULL;

    if (!(c = fd->ctr)) {
	// Load first container.
	do {
	    if (!(c = fd->ctr = cram_read_container(fd)))
		return NULL;
	} while (c->length == 0);

	/*
	 * The first container may be a result of a sub-range query.
	 * In which case it may still not be the optimal starting point
	 * due to skipped containers/slices in the index. 
	 */
	if (fd->range.refid != -2) {
	    while (c->ref_seq_id != -2 &&
		   (c->ref_seq_id < fd->range.refid ||
		    c->ref_seq_start + c->ref_seq_span-1 < fd->range.start)) {
		if (0 != cram_seek(fd, c->length, SEEK_CUR))
		    return NULL;
		cram_free_container(fd->ctr);
		do {
		    if (!(c = fd->ctr = cram_read_container(fd)))
			return NULL;
		} while (c->length == 0);
	    }

	    if (c->ref_seq_id != -2 && c->ref_seq_id != fd->range.refid)
		return NULL;
	}

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

	c->comp_hdr = cram_decode_compression_header(fd, c->comp_hdr_block);
	if (!c->comp_hdr)
	    return NULL;
	if (!c->comp_hdr->AP_delta &&
	    sam_hdr_sort_order(fd->header) != ORDER_COORD) {
	    pthread_mutex_lock(&fd->ref_lock);
	    fd->unsorted = 1;
	    pthread_mutex_unlock(&fd->ref_lock);
	}
    }

    if ((s = c->slice)) {
	c->slice = NULL;
	cram_free_slice(s);
	s = NULL;
    }

    if (c->curr_slice == c->max_slice) {
	cram_free_container(c);
	c = NULL;
    }

    /* Sorry this is so contorted! */
    for (;;) {
	if (fd->job_pending) {
	    cram_decode_job *j = (cram_decode_job *)fd->job_pending;
	    c = j->c;
	    s = j->s;
	    free(fd->job_pending);
	    fd->job_pending = NULL;
	} else if (!fd->ooc) {
	empty_container:
	    if (!c || c->curr_slice == c->max_slice) {
		// new container
		do {
		    if (!(c = fd->ctr = cram_read_container(fd))) {
			if (fd->pool) {
			    fd->ooc = 1;
			    break;
			}

			return NULL;
		    }
		} while (c->length == 0);
		if (fd->ooc)
		    break;

		/* Skip containers not yet spanning our range */
		if (fd->range.refid != -2 && c->ref_seq_id != -2) {
		    fd->required_fields |= SAM_POS;

		    if (c->ref_seq_id != fd->range.refid) {
			cram_free_container(c);
			fd->ctr = NULL;
			fd->ooc = 1;
			fd->eof = 1;
			break;
		    }

		    if (c->ref_seq_start > fd->range.end) {
			cram_free_container(c);
			fd->ctr = NULL;
			fd->ooc = 1;
			fd->eof = 1;
			break;
		    }

		    if (c->ref_seq_start + c->ref_seq_span-1 <
			fd->range.start) {
			c->curr_rec = c->max_rec;
			c->curr_slice = c->max_slice;
			cram_seek(fd, c->length, SEEK_CUR);
			cram_free_container(c);
			c = NULL;
			continue;
		    }
		}

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

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

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

	    if (c->num_records == 0) {
		cram_free_container(c); c = NULL;
		goto empty_container;
	    }


	    if (!(s = c->slice = cram_read_slice(fd)))
		return NULL;
	    c->curr_slice++;
	    c->curr_rec = 0;
	    c->max_rec = s->hdr->num_records;

	    s->last_apos = s->hdr->ref_seq_start;
	    
	    /* Skip slices not yet spanning our range */
	    if (fd->range.refid != -2 && s->hdr->ref_seq_id != -2) {
		if (s->hdr->ref_seq_id != fd->range.refid) {
		    fd->eof = 1;
		    cram_free_slice(s);
		    c->slice = NULL;
		    return NULL;
		}

		if (s->hdr->ref_seq_start > fd->range.end) {
		    fd->eof = 1;
		    cram_free_slice(s);
		    c->slice = NULL;
		    return NULL;
		}

		if (s->hdr->ref_seq_start + s->hdr->ref_seq_span-1 <
		    fd->range.start) {
		    cram_free_slice(s);
		    c->slice = NULL;
		    cram_free_container(c);
		    c = NULL;
		    continue;
		}
	    }
	}

	/* Test decoding of 1st seq */
	if (!c || !s)
	    break;

	if (cram_decode_slice_mt(fd, c, s, fd->header) != 0) {
	    //	if (cram_decode_slice(fd, c, s, fd->header) != 0) {
	    fprintf(stderr, "Failure to decode slice\n");
	    cram_free_slice(s);
	    c->slice = NULL;
	    return NULL;
	}

	if (!fd->pool || fd->job_pending)
	    break;

	// 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 (t_pool_results_queue_len(fd->rqueue) > fd->pool->qsize)
	    break;
    }

    if (fd->pool) {
	t_pool_result *res;
	cram_decode_job *j;
	
//	fprintf(stderr, "Thread pool len = %d, %d\n",
//		t_pool_results_queue_len(fd->rqueue),
//		t_pool_results_queue_sz(fd->rqueue));

	if (fd->ooc && t_pool_results_queue_empty(fd->rqueue))
	    return NULL;

	res = t_pool_next_result_wait(fd->rqueue);

	if (!res || !res->data) {
	    fprintf(stderr, "t_pool_next_result failure\n");
	    return NULL;
	}

	j = (cram_decode_job *)res->data;
	c = j->c;
	s = j->s;

	fd->ctr = c;

	t_pool_delete_result(res, 1);
    }

    *cp = c;
    return s;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq $0x0, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x20(%rbp)
cmpq $0x0, %rax
jne 0x2e38b
jmp 0x2e190
movq -0x10(%rbp), %rdi
callq 0x4bc50
movq -0x10(%rbp), %rcx
movq %rax, 0x38(%rcx)
movq %rax, -0x20(%rbp)
cmpq $0x0, %rax
jne 0x2e1b8
movq $0x0, -0x8(%rbp)
jmp 0x2e9d8
jmp 0x2e1ba
movq -0x20(%rbp), %rax
cmpl $0x0, (%rax)
je 0x2e190
movq -0x10(%rbp), %rax
cmpl $-0x2, 0x228(%rax)
je 0x2e2c8
jmp 0x2e1d6
movq -0x20(%rbp), %rcx
xorl %eax, %eax
cmpl $-0x2, 0x4(%rcx)
movb %al, -0x41(%rbp)
je 0x2e224
movq -0x20(%rbp), %rax
movl 0x4(%rax), %ecx
movq -0x10(%rbp), %rdx
movb $0x1, %al
cmpl 0x228(%rdx), %ecx
movb %al, -0x42(%rbp)
jl 0x2e21e
movq -0x20(%rbp), %rax
movl 0x8(%rax), %eax
movq -0x20(%rbp), %rcx
addl 0xc(%rcx), %eax
subl $0x1, %eax
movq -0x10(%rbp), %rcx
cmpl 0x22c(%rcx), %eax
setl %al
movb %al, -0x42(%rbp)
movb -0x42(%rbp), %al
movb %al, -0x41(%rbp)
movb -0x41(%rbp), %al
testb $0x1, %al
jne 0x2e22d
jmp 0x2e29c
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rax
movslq (%rax), %rsi
movl $0x1, %edx
callq 0x524e0
movl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
je 0x2e257
movq $0x0, -0x8(%rbp)
jmp 0x2e9d8
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rdi
callq 0x4b5e0
movq -0x10(%rbp), %rdi
callq 0x4bc50
movq -0x10(%rbp), %rcx
movq %rax, 0x38(%rcx)
movq %rax, -0x20(%rbp)
cmpq $0x0, %rax
jne 0x2e28c
movq $0x0, -0x8(%rbp)
jmp 0x2e9d8
jmp 0x2e28e
movq -0x20(%rbp), %rax
cmpl $0x0, (%rax)
je 0x2e264
jmp 0x2e1d6
movq -0x20(%rbp), %rax
cmpl $-0x2, 0x4(%rax)
je 0x2e2c6
movq -0x20(%rbp), %rax
movl 0x4(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0x228(%rcx), %eax
je 0x2e2c6
movq $0x0, -0x8(%rbp)
jmp 0x2e9d8
jmp 0x2e2c8
movq -0x10(%rbp), %rdi
callq 0x45bc0
movq -0x20(%rbp), %rcx
movq %rax, 0x48(%rcx)
cmpq $0x0, %rax
jne 0x2e2ec
movq $0x0, -0x8(%rbp)
jmp 0x2e9d8
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
cmpl $0x1, 0x8(%rax)
je 0x2e307
movq $0x0, -0x8(%rbp)
jmp 0x2e9d8
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rsi
callq 0x24750
movq %rax, %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x40(%rax)
movq -0x20(%rbp), %rax
cmpq $0x0, 0x40(%rax)
jne 0x2e33b
movq $0x0, -0x8(%rbp)
jmp 0x2e9d8
movq -0x20(%rbp), %rax
movq 0x40(%rax), %rax
cmpl $0x0, 0x34(%rax)
jne 0x2e389
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x5dc50
cmpl $0x2, %eax
je 0x2e389
movq -0x10(%rbp), %rdi
addq $0x8898, %rdi           # imm = 0x8898
callq 0x4880
movq -0x10(%rbp), %rax
movl $0x1, 0x8854(%rax)
movq -0x10(%rbp), %rdi
addq $0x8898, %rdi           # imm = 0x8898
callq 0x4420
jmp 0x2e38b
movq -0x20(%rbp), %rax
movq 0x80(%rax), %rax
movq %rax, -0x28(%rbp)
cmpq $0x0, %rax
je 0x2e3c0
movq -0x20(%rbp), %rax
movq $0x0, 0x80(%rax)
movq -0x28(%rbp), %rdi
callq 0x4b920
movq $0x0, -0x28(%rbp)
movq -0x20(%rbp), %rax
movl 0x54(%rax), %eax
movq -0x20(%rbp), %rcx
cmpl 0x50(%rcx), %eax
jne 0x2e3e1
movq -0x20(%rbp), %rdi
callq 0x4b5e0
movq $0x0, -0x20(%rbp)
jmp 0x2e3e3
movq -0x10(%rbp), %rax
cmpq $0x0, 0x88f0(%rax)
je 0x2e43c
movq -0x10(%rbp), %rax
movq 0x88f0(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq 0x88f0(%rax), %rdi
callq 0x46a0
movq -0x10(%rbp), %rax
movq $0x0, 0x88f0(%rax)
jmp 0x2e84c
movq -0x10(%rbp), %rax
cmpl $0x0, 0x88f8(%rax)
jne 0x2e84a
jmp 0x2e44f
cmpq $0x0, -0x20(%rbp)
je 0x2e46a
movq -0x20(%rbp), %rax
movl 0x54(%rax), %eax
movq -0x20(%rbp), %rcx
cmpl 0x50(%rcx), %eax
jne 0x2e6bc
jmp 0x2e46c
movq -0x10(%rbp), %rdi
callq 0x4bc50
movq -0x10(%rbp), %rcx
movq %rax, 0x38(%rcx)
movq %rax, -0x20(%rbp)
cmpq $0x0, %rax
jne 0x2e4b2
movq -0x10(%rbp), %rax
cmpq $0x0, 0x8860(%rax)
je 0x2e4a5
movq -0x10(%rbp), %rax
movl $0x1, 0x88f8(%rax)
jmp 0x2e4bd
movq $0x0, -0x8(%rbp)
jmp 0x2e9d8
jmp 0x2e4b4
movq -0x20(%rbp), %rax
cmpl $0x0, (%rax)
je 0x2e46c
movq -0x10(%rbp), %rax
cmpl $0x0, 0x88f8(%rax)
je 0x2e4cf
jmp 0x2e8fe
movq -0x10(%rbp), %rax
cmpl $-0x2, 0x228(%rax)
je 0x2e5f9
movq -0x20(%rbp), %rax
cmpl $-0x2, 0x4(%rax)
je 0x2e5f9
movq -0x10(%rbp), %rax
movl 0x224(%rax), %ecx
orl $0x8, %ecx
movl %ecx, 0x224(%rax)
movq -0x20(%rbp), %rax
movl 0x4(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0x228(%rcx), %eax
je 0x2e54a
movq -0x20(%rbp), %rdi
callq 0x4b5e0
movq -0x10(%rbp), %rax
movq $0x0, 0x38(%rax)
movq -0x10(%rbp), %rax
movl $0x1, 0x88f8(%rax)
movq -0x10(%rbp), %rax
movl $0x1, 0x8848(%rax)
jmp 0x2e8fe
movq -0x20(%rbp), %rax
movl 0x8(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0x230(%rcx), %eax
jle 0x2e593
movq -0x20(%rbp), %rdi
callq 0x4b5e0
movq -0x10(%rbp), %rax
movq $0x0, 0x38(%rax)
movq -0x10(%rbp), %rax
movl $0x1, 0x88f8(%rax)
movq -0x10(%rbp), %rax
movl $0x1, 0x8848(%rax)
jmp 0x2e8fe
movq -0x20(%rbp), %rax
movl 0x8(%rax), %eax
movq -0x20(%rbp), %rcx
addl 0xc(%rcx), %eax
subl $0x1, %eax
movq -0x10(%rbp), %rcx
cmpl 0x22c(%rcx), %eax
jge 0x2e5f7
movq -0x20(%rbp), %rax
movl 0x58(%rax), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x5c(%rax)
movq -0x20(%rbp), %rax
movl 0x50(%rax), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x54(%rax)
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rax
movslq (%rax), %rsi
movl $0x1, %edx
callq 0x524e0
movq -0x20(%rbp), %rdi
callq 0x4b5e0
movq $0x0, -0x20(%rbp)
jmp 0x2e3e3
jmp 0x2e5f9
movq -0x10(%rbp), %rdi
callq 0x45bc0
movq -0x20(%rbp), %rcx
movq %rax, 0x48(%rcx)
cmpq $0x0, %rax
jne 0x2e61d
movq $0x0, -0x8(%rbp)
jmp 0x2e9d8
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
cmpl $0x1, 0x8(%rax)
je 0x2e638
movq $0x0, -0x8(%rbp)
jmp 0x2e9d8
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rsi
callq 0x24750
movq %rax, %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x40(%rax)
movq -0x20(%rbp), %rax
cmpq $0x0, 0x40(%rax)
jne 0x2e66c
movq $0x0, -0x8(%rbp)
jmp 0x2e9d8
movq -0x20(%rbp), %rax
movq 0x40(%rax), %rax
cmpl $0x0, 0x34(%rax)
jne 0x2e6ba
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x5dc50
cmpl $0x2, %eax
je 0x2e6ba
movq -0x10(%rbp), %rdi
addq $0x8898, %rdi           # imm = 0x8898
callq 0x4880
movq -0x10(%rbp), %rax
movl $0x1, 0x8854(%rax)
movq -0x10(%rbp), %rdi
addq $0x8898, %rdi           # imm = 0x8898
callq 0x4420
jmp 0x2e6bc
movq -0x20(%rbp), %rax
cmpl $0x0, 0x20(%rax)
jne 0x2e6dc
movq -0x20(%rbp), %rdi
callq 0x4b5e0
movq $0x0, -0x20(%rbp)
jmp 0x2e44f
movq -0x10(%rbp), %rdi
callq 0x4f920
movq -0x20(%rbp), %rcx
movq %rax, 0x80(%rcx)
movq %rax, -0x28(%rbp)
cmpq $0x0, %rax
jne 0x2e707
movq $0x0, -0x8(%rbp)
jmp 0x2e9d8
movq -0x20(%rbp), %rax
movl 0x54(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x54(%rax)
movq -0x20(%rbp), %rax
movl $0x0, 0x5c(%rax)
movq -0x28(%rbp), %rax
movq (%rax), %rax
movl 0x10(%rax), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x58(%rax)
movq -0x28(%rbp), %rax
movq (%rax), %rax
movl 0x8(%rax), %ecx
movq -0x28(%rbp), %rax
movl %ecx, 0x20(%rax)
movq -0x10(%rbp), %rax
cmpl $-0x2, 0x228(%rax)
je 0x2e848
movq -0x28(%rbp), %rax
movq (%rax), %rax
cmpl $-0x2, 0x4(%rax)
je 0x2e848
movq -0x28(%rbp), %rax
movq (%rax), %rax
movl 0x4(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0x228(%rcx), %eax
je 0x2e7ac
movq -0x10(%rbp), %rax
movl $0x1, 0x8848(%rax)
movq -0x28(%rbp), %rdi
callq 0x4b920
movq -0x20(%rbp), %rax
movq $0x0, 0x80(%rax)
movq $0x0, -0x8(%rbp)
jmp 0x2e9d8
movq -0x28(%rbp), %rax
movq (%rax), %rax
movl 0x8(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0x230(%rcx), %eax
jle 0x2e7f5
movq -0x10(%rbp), %rax
movl $0x1, 0x8848(%rax)
movq -0x28(%rbp), %rdi
callq 0x4b920
movq -0x20(%rbp), %rax
movq $0x0, 0x80(%rax)
movq $0x0, -0x8(%rbp)
jmp 0x2e9d8
movq -0x28(%rbp), %rax
movq (%rax), %rax
movl 0x8(%rax), %eax
movq -0x28(%rbp), %rcx
movq (%rcx), %rcx
addl 0xc(%rcx), %eax
subl $0x1, %eax
movq -0x10(%rbp), %rcx
cmpl 0x22c(%rcx), %eax
jge 0x2e846
movq -0x28(%rbp), %rdi
callq 0x4b920
movq -0x20(%rbp), %rax
movq $0x0, 0x80(%rax)
movq -0x20(%rbp), %rdi
callq 0x4b5e0
movq $0x0, -0x20(%rbp)
jmp 0x2e3e3
jmp 0x2e848
jmp 0x2e84a
jmp 0x2e84c
cmpq $0x0, -0x20(%rbp)
je 0x2e85a
cmpq $0x0, -0x28(%rbp)
jne 0x2e85f
jmp 0x2e8fe
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq -0x28(%rbp), %rdx
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rcx
callq 0x2ddd0
cmpl $0x0, %eax
je 0x2e8ba
movq 0x5b74c(%rip), %rax     # 0x89fd0
movq (%rax), %rdi
leaq 0x4d5b3(%rip), %rsi     # 0x7be41
movb $0x0, %al
callq 0x4830
movq -0x28(%rbp), %rdi
callq 0x4b920
movq -0x20(%rbp), %rax
movq $0x0, 0x80(%rax)
movq $0x0, -0x8(%rbp)
jmp 0x2e9d8
movq -0x10(%rbp), %rax
cmpq $0x0, 0x8860(%rax)
je 0x2e8d6
movq -0x10(%rbp), %rax
cmpq $0x0, 0x88f0(%rax)
je 0x2e8d8
jmp 0x2e8fe
movq -0x10(%rbp), %rax
movq 0x8868(%rax), %rdi
callq 0x60420
movq -0x10(%rbp), %rcx
movq 0x8860(%rcx), %rcx
cmpl (%rcx), %eax
jle 0x2e8f9
jmp 0x2e8fe
jmp 0x2e3e3
movq -0x10(%rbp), %rax
cmpq $0x0, 0x8860(%rax)
je 0x2e9c5
movq -0x10(%rbp), %rax
cmpl $0x0, 0x88f8(%rax)
je 0x2e93f
movq -0x10(%rbp), %rax
movq 0x8868(%rax), %rdi
callq 0x603c0
cmpl $0x0, %eax
je 0x2e93f
movq $0x0, -0x8(%rbp)
jmp 0x2e9d8
movq -0x10(%rbp), %rax
movq 0x8868(%rax), %rdi
callq 0x60330
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x38(%rbp)
je 0x2e965
movq -0x38(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jne 0x2e987
movq 0x5b664(%rip), %rax     # 0x89fd0
movq (%rax), %rdi
leaq 0x4d4e4(%rip), %rsi     # 0x7be5a
movb $0x0, %al
callq 0x4830
movq $0x0, -0x8(%rbp)
jmp 0x2e9d8
movq -0x38(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x40(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x20(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x38(%rax)
movq -0x38(%rbp), %rdi
movl $0x1, %esi
callq 0x604a0
movq -0x20(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x28(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x50, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)