// File: zeeev[P]DASVC/bamtools/src/api/internal/index/BamToolsIndex_p.cpp
// Function: BamTools::Internal::BamToolsIndex::GetOffset(BamTools::BamRegion const&, long&, bool*)
void BamToolsIndex::GetOffset(const BamRegion& region, int64_t& offset, bool* hasAlignmentsInRegion) {

    // return false ref ID is not a valid index in file summary data
    if ( region.LeftRefID < 0 || region.LeftRefID >= (int)m_indexFileSummary.size() )
        throw BamException("BamToolsIndex::GetOffset", "invalid region requested");

    // retrieve reference index data for left bound reference
    BtiReferenceEntry refEntry(region.LeftRefID);
    ReadReferenceEntry(refEntry);

    // binary search for an overlapping block (may not be first one though)
    bool found = false;
    typedef BtiBlockVector::const_iterator BtiBlockConstIterator;
    BtiBlockConstIterator blockFirst = refEntry.Blocks.begin();
    BtiBlockConstIterator blockIter  = blockFirst;
    BtiBlockConstIterator blockLast  = refEntry.Blocks.end();
    iterator_traits<BtiBlockConstIterator>::difference_type count = distance(blockFirst, blockLast);
    iterator_traits<BtiBlockConstIterator>::difference_type step;
    while ( count > 0 ) {
        blockIter = blockFirst;
        step = count/2;
        advance(blockIter, step);

        const BtiBlock& block = (*blockIter);
        if ( block.StartPosition <= region.RightPosition ) {
            if ( block.MaxEndPosition > region.LeftPosition ) {
                offset = block.StartOffset;
                break;
            }
            blockFirst = ++blockIter;
            count -= step+1;
        }
        else count = step;
    }

    // if we didn't search "off the end" of the blocks
    if ( blockIter != blockLast ) {

        // "walk back" until we've gone too far
        while ( blockIter != blockFirst ) {
            const BtiBlock& currentBlock = (*blockIter);

            --blockIter;
            const BtiBlock& previousBlock = (*blockIter);
            if ( previousBlock.MaxEndPosition <= region.LeftPosition ) {
                offset = currentBlock.StartOffset;
                found = true;
                break;
            }
        }

        // if we walked all the way to first block, just return that and let the reader's
        // region overlap parsing do the rest
        if ( blockIter == blockFirst ) {
            const BtiBlock& block = (*blockIter);
            offset = block.StartOffset;
            found = true;
        }
    }


    // sets to false if blocks container is empty, or if no matching block could be found
    *hasAlignmentsInRegion = found;
}

// Assembly:
subq $0x198, %rsp            # imm = 0x198
movq %rdi, 0x190(%rsp)
movq %rsi, 0x188(%rsp)
movq %rdx, 0x180(%rsp)
movq %rcx, 0x178(%rsp)
movq 0x190(%rsp), %rax
movq %rax, 0x80(%rsp)
movq 0x188(%rsp), %rax
cmpl $0x0, (%rax)
jl 0xc22c2
movq 0x80(%rsp), %rdi
movq 0x188(%rsp), %rax
movl (%rax), %eax
movl %eax, 0x7c(%rsp)
addq $0x38, %rdi
callq 0x72c30
movq %rax, %rcx
movl 0x7c(%rsp), %eax
cmpl %ecx, %eax
jl 0xc240b
movb $0x1, 0x11e(%rsp)
movl $0x28, %edi
callq 0x737c0
movq %rax, 0x68(%rsp)
leaq 0x157(%rsp), %rdi
movq %rdi, 0x70(%rsp)
callq 0x7b5f0
movq 0x70(%rsp), %rdx
leaq 0x28fbb(%rip), %rsi     # 0xeb2b2
leaq 0x158(%rsp), %rdi
callq 0x78e70
jmp 0xc2306
leaq 0x11f(%rsp), %rdi
movq %rdi, 0x60(%rsp)
callq 0x7b5f0
movq 0x60(%rsp), %rdx
leaq 0x295ef(%rip), %rsi     # 0xeb913
leaq 0x120(%rsp), %rdi
callq 0x78e70
jmp 0xc2333
movq 0x68(%rsp), %rdi
leaq 0x158(%rsp), %rsi
leaq 0x120(%rsp), %rdx
callq 0x79cd0
jmp 0xc234f
movq 0x68(%rsp), %rdi
movb $0x0, 0x11e(%rsp)
movq 0x4fbad(%rip), %rsi     # 0x111f10
movq 0x4fbf6(%rip), %rdx     # 0x111f60
callq 0x7b010
jmp 0xc27d4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x148(%rsp)
movl %eax, 0x144(%rsp)
jmp 0xc23e3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x148(%rsp)
movl %eax, 0x144(%rsp)
jmp 0xc23c5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x148(%rsp)
movl %eax, 0x144(%rsp)
leaq 0x120(%rsp), %rdi
callq 0x7cce8
jmp 0xc23c3
jmp 0xc23c5
leaq 0x11f(%rsp), %rdi
callq 0x76f80
leaq 0x158(%rsp), %rdi
callq 0x7cce8
jmp 0xc23e1
jmp 0xc23e3
leaq 0x157(%rsp), %rdi
callq 0x76f80
testb $0x1, 0x11e(%rsp)
jne 0xc23fc
jmp 0xc2406
movq 0x68(%rsp), %rdi
callq 0x74e00
jmp 0xc27bf
movq 0x188(%rsp), %rsi
leaq 0xf8(%rsp), %rdi
movq %rdi, 0x58(%rsp)
callq 0x78890
movq 0x80(%rsp), %rdi
movq 0x58(%rsp), %rsi
callq 0x7ae10
jmp 0xc2439
movb $0x0, 0xf7(%rsp)
leaq 0x100(%rsp), %rdi
callq 0x7a480
movq %rax, 0x50(%rsp)
jmp 0xc2455
movq 0x50(%rsp), %rax
movq %rax, 0xe0(%rsp)
leaq 0xe8(%rsp), %rdi
leaq 0xe0(%rsp), %rsi
callq 0x7b920
jmp 0xc2479
movq 0xe8(%rsp), %rax
movq %rax, 0xd8(%rsp)
leaq 0x100(%rsp), %rdi
callq 0x7c170
movq %rax, 0x48(%rsp)
jmp 0xc249d
movq 0x48(%rsp), %rax
movq %rax, 0xc8(%rsp)
leaq 0xd0(%rsp), %rdi
leaq 0xc8(%rsp), %rsi
callq 0x7b920
jmp 0xc24c1
movq 0xe8(%rsp), %rax
movq %rax, 0xb8(%rsp)
movq 0xd0(%rsp), %rax
movq %rax, 0xb0(%rsp)
movq 0xb8(%rsp), %rdi
movq 0xb0(%rsp), %rsi
callq 0x77070
movq %rax, 0x40(%rsp)
jmp 0xc24fd
movq 0x40(%rsp), %rax
movq %rax, 0xc0(%rsp)
cmpq $0x0, 0xc0(%rsp)
jle 0xc264d
movq 0xe8(%rsp), %rax
movq %rax, 0xd8(%rsp)
movq 0xc0(%rsp), %rax
movq %rax, %rcx
shrq $0x3f, %rcx
addq %rcx, %rax
sarq %rax
movq %rax, 0xa8(%rsp)
movq 0xa8(%rsp), %rsi
leaq 0xd8(%rsp), %rdi
callq 0x7b220
jmp 0xc255d
leaq 0xd8(%rsp), %rdi
callq 0x7c950
movq %rax, 0x38(%rsp)
jmp 0xc2571
movq 0x38(%rsp), %rax
movq %rax, 0xa0(%rsp)
movq 0xa0(%rsp), %rax
movl 0x10(%rax), %eax
movq 0x188(%rsp), %rcx
cmpl 0xc(%rcx), %eax
jg 0xc2638
movq 0xa0(%rsp), %rax
movl (%rax), %eax
movq 0x188(%rsp), %rcx
cmpl 0x4(%rcx), %eax
jle 0xc25f3
movq 0xa0(%rsp), %rax
movq 0x8(%rax), %rcx
movq 0x180(%rsp), %rax
movq %rcx, (%rax)
jmp 0xc264d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x148(%rsp)
movl %eax, 0x144(%rsp)
leaq 0xf8(%rsp), %rdi
callq 0x79d10
jmp 0xc27bd
leaq 0xd8(%rsp), %rdi
callq 0x73260
movq %rax, 0x30(%rsp)
jmp 0xc2607
movq 0x30(%rsp), %rax
movq (%rax), %rax
movq %rax, 0xe8(%rsp)
movq 0xa8(%rsp), %rcx
addq $0x1, %rcx
movq 0xc0(%rsp), %rax
subq %rcx, %rax
movq %rax, 0xc0(%rsp)
jmp 0xc2648
movq 0xa8(%rsp), %rax
movq %rax, 0xc0(%rsp)
jmp 0xc250a
leaq 0xd8(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
callq 0x71c20
movb %al, 0x2f(%rsp)
jmp 0xc2668
movb 0x2f(%rsp), %al
testb $0x1, %al
jne 0xc2675
jmp 0xc2794
jmp 0xc2677
leaq 0xd8(%rsp), %rdi
leaq 0xe8(%rsp), %rsi
callq 0x71c20
movb %al, 0x2e(%rsp)
jmp 0xc2692
movb 0x2e(%rsp), %al
testb $0x1, %al
jne 0xc269f
jmp 0xc272d
leaq 0xd8(%rsp), %rdi
callq 0x7c950
movq %rax, 0x20(%rsp)
jmp 0xc26b3
movq 0x20(%rsp), %rax
movq %rax, 0x98(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x78ad0
jmp 0xc26cf
leaq 0xd8(%rsp), %rdi
callq 0x7c950
movq %rax, 0x18(%rsp)
jmp 0xc26e3
movq 0x18(%rsp), %rax
movq %rax, 0x90(%rsp)
movq 0x90(%rsp), %rax
movl (%rax), %eax
movq 0x188(%rsp), %rcx
cmpl 0x4(%rcx), %eax
jg 0xc2728
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rcx
movq 0x180(%rsp), %rax
movq %rcx, (%rax)
movb $0x1, 0xf7(%rsp)
jmp 0xc272d
jmp 0xc2677
leaq 0xd8(%rsp), %rdi
leaq 0xe8(%rsp), %rsi
callq 0x79f10
movb %al, 0x17(%rsp)
jmp 0xc2748
movb 0x17(%rsp), %al
testb $0x1, %al
jne 0xc2752
jmp 0xc2792
leaq 0xd8(%rsp), %rdi
callq 0x7c950
movq %rax, 0x8(%rsp)
jmp 0xc2766
movq 0x8(%rsp), %rax
movq %rax, 0x88(%rsp)
movq 0x88(%rsp), %rax
movq 0x8(%rax), %rcx
movq 0x180(%rsp), %rax
movq %rcx, (%rax)
movb $0x1, 0xf7(%rsp)
jmp 0xc2794
movb 0xf7(%rsp), %cl
movq 0x178(%rsp), %rax
andb $0x1, %cl
movb %cl, (%rax)
leaq 0xf8(%rsp), %rdi
callq 0x79d10
addq $0x198, %rsp            # imm = 0x198
retq
jmp 0xc27bf
movq 0x148(%rsp), %rdi
callq 0x7b550
movq %rax, %rdi
callq 0x88ef0
nopw %cs:(%rax,%rax)