// File: zeeev[P]DASVC/bamtools/src/utils/bamtools_utilities.cpp
// Function: BamTools::Utilities::ParseRegionString(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, BamTools::BamReader const&, BamTools::BamRegion&)
bool Utilities::ParseRegionString(const string& regionString,
                                  const BamReader& reader,
                                  BamRegion& region)
{
    // -------------------------------
    // parse region string
  
    // check first for empty string
    if ( regionString.empty() ) 
        return false;   
    
    // non-empty string, look for a colom
    size_t foundFirstColon = regionString.find(':');
    
    // store chrom strings, and numeric positions
    string startChrom;
    string stopChrom;
    int startPos;
    int stopPos;
    
    // no colon found
    // going to use entire contents of requested chromosome 
    // just store entire region string as startChrom name
    // use BamReader methods to check if its valid for current BAM file
    if ( foundFirstColon == string::npos ) {
        startChrom = regionString;
        startPos   = 0;
        stopChrom  = regionString;
        stopPos    = 0;
    }
    
    // colon found, so we at least have some sort of startPos requested
    else {
      
        // store start chrom from beginning to first colon
        startChrom = regionString.substr(0,foundFirstColon);
        
        // look for ".." after the colon
        size_t foundRangeDots = regionString.find("..", foundFirstColon+1);
        
        // no dots found
        // so we have a startPos but no range
        // store contents before colon as startChrom, after as startPos
        if ( foundRangeDots == string::npos ) {
            startPos   = atoi( regionString.substr(foundFirstColon+1).c_str() ); 
            stopChrom  = startChrom;
            stopPos    = -1;
        } 
        
        // ".." found, so we have some sort of range selected
        else {
          
            // store startPos between first colon and range dots ".."
            startPos = atoi( regionString.substr(foundFirstColon+1, foundRangeDots-foundFirstColon-1).c_str() );
          
            // look for second colon
            size_t foundSecondColon = regionString.find(':', foundRangeDots+1);
            
            // no second colon found
            // so we have a "standard" chrom:start..stop input format (on single chrom)
            if ( foundSecondColon == string::npos ) {
                stopChrom  = startChrom;
                stopPos    = atoi( regionString.substr(foundRangeDots+2).c_str() );
            }
            
            // second colon found
            // so we have a range requested across 2 chrom's
            else {
                stopChrom  = regionString.substr(foundRangeDots+2, foundSecondColon-(foundRangeDots+2));
                stopPos    = atoi( regionString.substr(foundSecondColon+1).c_str() );
            }
        }
    }

    // -------------------------------
    // validate reference IDs & genomic positions
    
    const RefVector references = reader.GetReferenceData();
    
    // if startRefID not found, return false
    int startRefID = reader.GetReferenceID(startChrom);
    if ( startRefID == -1 ) return false;
    
    // startPos cannot be greater than or equal to reference length
    const RefData& startReference = references.at(startRefID);
    if ( startPos >= startReference.RefLength ) return false;
    
    // if stopRefID not found, return false
    int stopRefID = reader.GetReferenceID(stopChrom);
    if ( stopRefID == -1 ) return false;
    
    // stopPosition cannot be larger than reference length
    const RefData& stopReference = references.at(stopRefID);
    if ( stopPos > stopReference.RefLength ) return false;
    
    // if no stopPosition specified, set to reference end
    if ( stopPos == -1 ) stopPos = stopReference.RefLength;  
    
    // -------------------------------
    // set up Region struct & return
    
    region.LeftRefID     = startRefID;
    region.LeftPosition  = startPos;
    region.RightRefID    = stopRefID;;
    region.RightPosition = stopPos;
    return true;
}

// Assembly:
subq $0x1e8, %rsp            # imm = 0x1E8
movq %rdi, 0x1d8(%rsp)
movq %rsi, 0x1d0(%rsp)
movq %rdx, 0x1c8(%rsp)
movq 0x1d8(%rsp), %rdi
callq 0x86c90
testb $0x1, %al
jne 0x114e12
jmp 0x114e1f
movb $0x0, 0x1e7(%rsp)
jmp 0x1154cc
movq 0x1d8(%rsp), %rdi
xorl %eax, %eax
movl %eax, %edx
movl $0x3a, %esi
callq 0x86960
movq %rax, 0x1c0(%rsp)
leaq 0x1a0(%rsp), %rdi
callq 0x86a30
leaq 0x180(%rsp), %rdi
callq 0x86a30
jmp 0x114e59
cmpq $-0x1, 0x1c0(%rsp)
jne 0x114edf
movq 0x1d8(%rsp), %rsi
leaq 0x1a0(%rsp), %rdi
callq 0x86070
jmp 0x114e7b
movl $0x0, 0x170(%rsp)
movq 0x1d8(%rsp), %rsi
leaq 0x180(%rsp), %rdi
callq 0x86070
jmp 0x114e9d
movl $0x0, 0x16c(%rsp)
jmp 0x1152b6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
jmp 0x1154bb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
jmp 0x1154aa
movq 0x1d8(%rsp), %rsi
movq 0x1c0(%rsp), %rcx
xorl %eax, %eax
movl %eax, %edx
leaq 0x148(%rsp), %rdi
callq 0x86750
jmp 0x114f02
leaq 0x1a0(%rsp), %rdi
leaq 0x148(%rsp), %rsi
callq 0x86070
jmp 0x114f19
leaq 0x148(%rsp), %rdi
callq 0x86f68
jmp 0x114f28
movq 0x1d8(%rsp), %rdi
movq 0x1c0(%rsp), %rdx
incq %rdx
leaq 0x1f39e(%rip), %rsi     # 0x1342e0
callq 0x86f10
movq %rax, 0x58(%rsp)
jmp 0x114f4e
movq 0x58(%rsp), %rax
movq %rax, 0x140(%rsp)
cmpq $-0x1, 0x140(%rsp)
jne 0x11503e
movq 0x1d8(%rsp), %rsi
movq 0x1c0(%rsp), %rdx
incq %rdx
leaq 0x120(%rsp), %rdi
movq $-0x1, %rcx
callq 0x86750
jmp 0x114f93
leaq 0x120(%rsp), %rdi
callq 0x86320
movq %rax, 0x50(%rsp)
jmp 0x114fa7
movq 0x50(%rsp), %rdi
callq 0x86b40
movl %eax, 0x170(%rsp)
leaq 0x120(%rsp), %rdi
callq 0x86f68
jmp 0x114fc7
leaq 0x180(%rsp), %rdi
leaq 0x1a0(%rsp), %rsi
callq 0x86070
jmp 0x114fde
movl $0xffffffff, 0x16c(%rsp) # imm = 0xFFFFFFFF
jmp 0x1152b4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
leaq 0x148(%rsp), %rdi
callq 0x86f68
jmp 0x115011
jmp 0x1154aa
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
leaq 0x120(%rsp), %rdi
callq 0x86f68
jmp 0x115039
jmp 0x1154aa
movq 0x1d8(%rsp), %rsi
movq 0x1c0(%rsp), %rcx
movq %rcx, %rdx
incq %rdx
movq 0x140(%rsp), %rax
notq %rcx
addq %rax, %rcx
leaq 0x100(%rsp), %rdi
callq 0x86750
jmp 0x115071
leaq 0x100(%rsp), %rdi
callq 0x86320
movq %rax, 0x48(%rsp)
jmp 0x115085
movq 0x48(%rsp), %rdi
callq 0x86b40
movl %eax, 0x170(%rsp)
leaq 0x100(%rsp), %rdi
callq 0x86f68
jmp 0x1150a5
movq 0x1d8(%rsp), %rdi
movq 0x140(%rsp), %rdx
incq %rdx
movl $0x3a, %esi
callq 0x86960
movq %rax, 0x40(%rsp)
jmp 0x1150c9
movq 0x40(%rsp), %rax
movq %rax, 0xf8(%rsp)
cmpq $-0x1, 0xf8(%rsp)
jne 0x1151af
leaq 0x180(%rsp), %rdi
leaq 0x1a0(%rsp), %rsi
callq 0x86070
jmp 0x1150fc
movq 0x1d8(%rsp), %rsi
movq 0x140(%rsp), %rdx
addq $0x2, %rdx
leaq 0xd8(%rsp), %rdi
movq $-0x1, %rcx
callq 0x86750
jmp 0x115126
leaq 0xd8(%rsp), %rdi
callq 0x86320
movq %rax, 0x38(%rsp)
jmp 0x11513a
movq 0x38(%rsp), %rdi
callq 0x86b40
movl %eax, 0x16c(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x86f68
jmp 0x11515a
jmp 0x1152b2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
leaq 0x100(%rsp), %rdi
callq 0x86f68
jmp 0x115182
jmp 0x1154aa
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x86f68
jmp 0x1151aa
jmp 0x1154aa
movq 0x1d8(%rsp), %rsi
movq 0x140(%rsp), %rdx
addq $0x2, %rdx
movq 0xf8(%rsp), %rcx
subq %rdx, %rcx
leaq 0xb8(%rsp), %rdi
callq 0x86750
jmp 0x1151dd
leaq 0x180(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x86070
jmp 0x1151f4
leaq 0xb8(%rsp), %rdi
callq 0x86f68
jmp 0x115203
movq 0x1d8(%rsp), %rsi
movq 0xf8(%rsp), %rdx
incq %rdx
leaq 0x98(%rsp), %rdi
movq $-0x1, %rcx
callq 0x86750
jmp 0x11522c
leaq 0x98(%rsp), %rdi
callq 0x86320
movq %rax, 0x30(%rsp)
jmp 0x115240
movq 0x30(%rsp), %rdi
callq 0x86b40
movl %eax, 0x16c(%rsp)
leaq 0x98(%rsp), %rdi
callq 0x86f68
jmp 0x115260
jmp 0x1152b2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
leaq 0xb8(%rsp), %rdi
callq 0x86f68
jmp 0x115285
jmp 0x1154aa
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
leaq 0x98(%rsp), %rdi
callq 0x86f68
jmp 0x1152ad
jmp 0x1154aa
jmp 0x1152b4
jmp 0x1152b6
movq 0x1d0(%rsp), %rdi
callq 0x860a0
movq %rax, 0x28(%rsp)
jmp 0x1152ca
movq 0x28(%rsp), %rsi
leaq 0x80(%rsp), %rdi
callq 0x926c0
jmp 0x1152de
movq 0x1d0(%rsp), %rdi
leaq 0x1a0(%rsp), %rsi
callq 0x86380
movl %eax, 0x24(%rsp)
jmp 0x1152f9
movl 0x24(%rsp), %eax
movl %eax, 0x7c(%rsp)
cmpl $-0x1, 0x7c(%rsp)
jne 0x115343
movb $0x0, 0x1e7(%rsp)
movl $0x1, 0x78(%rsp)
jmp 0x11547b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
leaq 0x80(%rsp), %rdi
callq 0x91560
jmp 0x115499
movslq 0x7c(%rsp), %rsi
leaq 0x80(%rsp), %rdi
callq 0xc6cc0
movq %rax, 0x18(%rsp)
jmp 0x11535c
movq 0x18(%rsp), %rax
movq %rax, 0x70(%rsp)
movl 0x170(%rsp), %eax
movq 0x70(%rsp), %rcx
cmpl 0x20(%rcx), %eax
jl 0x11538c
movb $0x0, 0x1e7(%rsp)
movl $0x1, 0x78(%rsp)
jmp 0x11547b
movq 0x1d0(%rsp), %rdi
leaq 0x180(%rsp), %rsi
callq 0x86380
movl %eax, 0x14(%rsp)
jmp 0x1153a7
movl 0x14(%rsp), %eax
movl %eax, 0x6c(%rsp)
cmpl $-0x1, 0x6c(%rsp)
jne 0x1153cb
movb $0x0, 0x1e7(%rsp)
movl $0x1, 0x78(%rsp)
jmp 0x11547b
movslq 0x6c(%rsp), %rsi
leaq 0x80(%rsp), %rdi
callq 0xc6cc0
movq %rax, 0x8(%rsp)
jmp 0x1153e4
movq 0x8(%rsp), %rax
movq %rax, 0x60(%rsp)
movl 0x16c(%rsp), %eax
movq 0x60(%rsp), %rcx
cmpl 0x20(%rcx), %eax
jle 0x115411
movb $0x0, 0x1e7(%rsp)
movl $0x1, 0x78(%rsp)
jmp 0x11547b
cmpl $-0x1, 0x16c(%rsp)
jne 0x11542a
movq 0x60(%rsp), %rax
movl 0x20(%rax), %eax
movl %eax, 0x16c(%rsp)
movl 0x7c(%rsp), %ecx
movq 0x1c8(%rsp), %rax
movl %ecx, (%rax)
movl 0x170(%rsp), %ecx
movq 0x1c8(%rsp), %rax
movl %ecx, 0x4(%rax)
movl 0x6c(%rsp), %ecx
movq 0x1c8(%rsp), %rax
movl %ecx, 0x8(%rax)
movl 0x16c(%rsp), %ecx
movq 0x1c8(%rsp), %rax
movl %ecx, 0xc(%rax)
movb $0x1, 0x1e7(%rsp)
movl $0x1, 0x78(%rsp)
leaq 0x80(%rsp), %rdi
callq 0x91560
jmp 0x11548a
leaq 0x180(%rsp), %rdi
callq 0x86f68
jmp 0x11549b
jmp 0x1154aa
leaq 0x1a0(%rsp), %rdi
callq 0x86f68
jmp 0x1154cc
leaq 0x180(%rsp), %rdi
callq 0x86f68
jmp 0x1154b9
jmp 0x1154bb
leaq 0x1a0(%rsp), %rdi
callq 0x86f68
jmp 0x1154ca
jmp 0x1154dd
movb 0x1e7(%rsp), %al
andb $0x1, %al
addq $0x1e8, %rsp            # imm = 0x1E8
retq
movq 0x178(%rsp), %rdi
callq 0x86d80
movq %rax, %rdi
callq 0x91290
nopw %cs:(%rax,%rax)