// File: zeeev[P]DASVC/bamtools/src/toolkit/bamtools_filter.cpp
// Function: BamTools::BamAlignmentChecker::checkAlignmentTag(BamTools::PropertyFilterValue const&, BamTools::BamAlignment const&)
bool checkAlignmentTag(const PropertyFilterValue& valueFilter, const BamAlignment& al) {
     
        // ensure filter contains string data
        Variant entireTagFilter = valueFilter.Value;
        if ( !entireTagFilter.is_type<string>() ) return false;

        // localize string from variant
        const string& entireTagFilterString = entireTagFilter.get<string>();

        // ensure we have at least "XX:x"
        if ( entireTagFilterString.length() < 4 ) return false;

        // get tagName & lookup in alignment
        // if found, set tagType to tag type character
        // if not found, return false
        const string& tagName = entireTagFilterString.substr(0,2);
        char tagType = '\0';
        if ( !al.GetTagType(tagName, tagType) ) return false;

        // remove tagName & ":" from beginning tagFilter
        string tagFilterString = entireTagFilterString.substr(3);

        // switch on tag type to set tag query value & parse filter token
        int8_t   asciiFilterValue,   asciiQueryValue;
        int32_t  intFilterValue,    intQueryValue;
        uint32_t uintFilterValue,   uintQueryValue;
        float    realFilterValue,   realQueryValue;
        string   stringFilterValue, stringQueryValue;

        PropertyFilterValue tagFilter;
        PropertyFilterValue::ValueCompareType compareType;
        bool keepAlignment = false;
        switch (tagType) {

            // ASCII tag type
            case 'A':
                if ( al.GetTag(tagName, asciiQueryValue) ) {
                    if ( FilterEngine<BamAlignmentChecker>::parseToken(tagFilterString, asciiFilterValue, compareType) ) {
                        tagFilter.Value = asciiFilterValue;
                        tagFilter.Type  = compareType;
                        keepAlignment   = tagFilter.check(asciiQueryValue);
                    }
                }
                break;

            // signed int tag type
            case 'c' :
            case 's' :
            case 'i' :
                if ( al.GetTag(tagName, intQueryValue) ) {
                    if ( FilterEngine<BamAlignmentChecker>::parseToken(tagFilterString, intFilterValue, compareType) ) {
                        tagFilter.Value = intFilterValue;
                        tagFilter.Type  = compareType;
                        keepAlignment   = tagFilter.check(intQueryValue);
                    }
                }
                break;

            // unsigned int tag type
            case 'C' :
            case 'S' :
            case 'I' :
                if ( al.GetTag(tagName, uintQueryValue) ) {
                    if ( FilterEngine<BamAlignmentChecker>::parseToken(tagFilterString, uintFilterValue, compareType) ) {
                        tagFilter.Value = uintFilterValue;
                        tagFilter.Type  = compareType;
                        keepAlignment   = tagFilter.check(uintQueryValue);
                    }
                }
                break;

            // 'real' tag type
            case 'f' :
                if ( al.GetTag(tagName, realQueryValue) ) {
                    if ( FilterEngine<BamAlignmentChecker>::parseToken(tagFilterString, realFilterValue, compareType) ) {
                        tagFilter.Value = realFilterValue;
                        tagFilter.Type  = compareType;
                        keepAlignment   = tagFilter.check(realQueryValue);
                    }
                }
                break;

            // string tag type

            case 'Z':
            case 'H':
                if ( al.GetTag(tagName, stringQueryValue) ) {
                    if ( FilterEngine<BamAlignmentChecker>::parseToken(tagFilterString, stringFilterValue, compareType) ) {
                        tagFilter.Value = stringFilterValue;
                        tagFilter.Type  = compareType;
                        keepAlignment   = tagFilter.check(stringQueryValue);
                    }
                }
                break;

            // unknown tag type
            default :
                keepAlignment = false;
        }

        return keepAlignment;
    }

// Assembly:
subq $0x1a8, %rsp            # imm = 0x1A8
movq %rdi, 0x198(%rsp)
movq %rsi, 0x190(%rsp)
movq %rdx, 0x188(%rsp)
movq 0x190(%rsp), %rsi
leaq 0x180(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0x95850
movq 0x38(%rsp), %rdi
callq 0xa9640
movb %al, 0x47(%rsp)
jmp 0xba449
movb 0x47(%rsp), %al
testb $0x1, %al
jne 0xba484
jmp 0xba453
movb $0x0, 0x1a7(%rsp)
movl $0x1, 0x170(%rsp)
jmp 0xbacb0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
jmp 0xbacce
leaq 0x180(%rsp), %rdi
callq 0xbb160
movq %rax, 0x30(%rsp)
jmp 0xba498
movq 0x30(%rsp), %rax
movq %rax, 0x168(%rsp)
movq 0x168(%rsp), %rdi
callq 0x86ac0
movq %rax, 0x28(%rsp)
jmp 0xba4b9
movq 0x28(%rsp), %rax
cmpq $0x4, %rax
jae 0xba4dc
movb $0x0, 0x1a7(%rsp)
movl $0x1, 0x170(%rsp)
jmp 0xbacb0
movq 0x168(%rsp), %rsi
xorl %eax, %eax
movl %eax, %edx
leaq 0x140(%rsp), %rdi
movl $0x2, %ecx
callq 0x86750
jmp 0xba4fc
leaq 0x140(%rsp), %rax
movq %rax, 0x160(%rsp)
movb $0x0, 0x13f(%rsp)
movq 0x188(%rsp), %rdi
movq 0x160(%rsp), %rsi
leaq 0x13f(%rsp), %rdx
callq 0x86a10
movb %al, 0x27(%rsp)
jmp 0xba537
movb 0x27(%rsp), %al
testb $0x1, %al
jne 0xba572
jmp 0xba541
movb $0x0, 0x1a7(%rsp)
movl $0x1, 0x170(%rsp)
jmp 0xbac8e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
jmp 0xbac9f
movq 0x168(%rsp), %rsi
leaq 0x118(%rsp), %rdi
movl $0x3, %edx
movq $-0x1, %rcx
callq 0x86750
jmp 0xba595
leaq 0xd8(%rsp), %rdi
callq 0x86a30
jmp 0xba5a4
leaq 0xb8(%rsp), %rdi
callq 0x86a30
jmp 0xba5b3
leaq 0xa0(%rsp), %rdi
callq 0x950b0
jmp 0xba5c2
movl $0x2, 0x9c(%rsp)
leaq 0xa8(%rsp), %rdi
leaq 0xa0(%rsp), %rsi
leaq 0x9c(%rsp), %rdx
callq 0xabda0
jmp 0xba5ec
leaq 0xa0(%rsp), %rdi
callq 0x94a50
jmp 0xba5fb
movb $0x0, 0x97(%rsp)
movsbl 0x13f(%rsp), %eax
addl $-0x41, %eax
movl %eax, %ecx
movq %rcx, 0x18(%rsp)
subl $0x32, %eax
ja 0xbabe9
movq 0x18(%rsp), %rax
leaq 0x74926(%rip), %rcx     # 0x12ef50
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
jmp 0xbac7d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
jmp 0xbac6a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
jmp 0xbac4a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
leaq 0xa0(%rsp), %rdi
callq 0x94a50
jmp 0xba6a1
jmp 0xbac4a
movq 0x188(%rsp), %rdi
movq 0x160(%rsp), %rsi
leaq 0x116(%rsp), %rdx
callq 0xbb9a0
movb %al, 0x17(%rsp)
jmp 0xba6c9
movb 0x17(%rsp), %al
testb $0x1, %al
jne 0xba6d6
jmp 0xba7be
leaq 0x118(%rsp), %rdi
leaq 0x117(%rsp), %rsi
leaq 0x98(%rsp), %rdx
callq 0xbbe10
movb %al, 0x16(%rsp)
jmp 0xba6f9
movb 0x16(%rsp), %al
testb $0x1, %al
jne 0xba706
jmp 0xba7bc
movsbl 0x117(%rsp), %esi
leaq 0x88(%rsp), %rdi
callq 0xbc760
jmp 0xba71d
leaq 0xa8(%rsp), %rdi
leaq 0x88(%rsp), %rsi
callq 0x949f0
jmp 0xba734
leaq 0x88(%rsp), %rdi
callq 0x94a50
jmp 0xba743
movl 0x98(%rsp), %eax
movl %eax, 0xb0(%rsp)
leaq 0xa8(%rsp), %rdi
leaq 0x116(%rsp), %rsi
callq 0xbc7e0
movb %al, 0x15(%rsp)
jmp 0xba76c
movb 0x15(%rsp), %al
andb $0x1, %al
movb %al, 0x97(%rsp)
jmp 0xba7bc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
jmp 0xbac2a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
leaq 0x88(%rsp), %rdi
callq 0x94a50
jmp 0xba7b7
jmp 0xbac2a
jmp 0xba7be
jmp 0xbabf1
movq 0x188(%rsp), %rdi
movq 0x160(%rsp), %rsi
leaq 0x10c(%rsp), %rdx
callq 0xbc9d0
movb %al, 0x14(%rsp)
jmp 0xba7e6
movb 0x14(%rsp), %al
testb $0x1, %al
jne 0xba7f3
jmp 0xba8c1
leaq 0x118(%rsp), %rdi
leaq 0x110(%rsp), %rsi
leaq 0x98(%rsp), %rdx
callq 0xa37e0
movb %al, 0x13(%rsp)
jmp 0xba816
movb 0x13(%rsp), %al
testb $0x1, %al
jne 0xba823
jmp 0xba8bf
movl 0x110(%rsp), %esi
leaq 0x80(%rsp), %rdi
callq 0xa95c0
jmp 0xba839
leaq 0xa8(%rsp), %rdi
leaq 0x80(%rsp), %rsi
callq 0x949f0
jmp 0xba850
leaq 0x80(%rsp), %rdi
callq 0x94a50
jmp 0xba85f
movl 0x98(%rsp), %eax
movl %eax, 0xb0(%rsp)
leaq 0xa8(%rsp), %rdi
leaq 0x10c(%rsp), %rsi
callq 0xb9e20
movb %al, 0x12(%rsp)
jmp 0xba888
movb 0x12(%rsp), %al
andb $0x1, %al
movb %al, 0x97(%rsp)
jmp 0xba8bf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
leaq 0x80(%rsp), %rdi
callq 0x94a50
jmp 0xba8ba
jmp 0xbac2a
jmp 0xba8c1
jmp 0xbabf1
movq 0x188(%rsp), %rdi
movq 0x160(%rsp), %rsi
leaq 0x104(%rsp), %rdx
callq 0xbce40
movb %al, 0x11(%rsp)
jmp 0xba8e9
movb 0x11(%rsp), %al
testb $0x1, %al
jne 0xba8f6
jmp 0xba9b8
leaq 0x118(%rsp), %rdi
leaq 0x108(%rsp), %rsi
leaq 0x98(%rsp), %rdx
callq 0xa5470
movb %al, 0x10(%rsp)
jmp 0xba919
movb 0x10(%rsp), %al
testb $0x1, %al
jne 0xba926
jmp 0xba9b6
movl 0x108(%rsp), %esi
leaq 0x78(%rsp), %rdi
callq 0xa9820
jmp 0xba939
leaq 0xa8(%rsp), %rdi
leaq 0x78(%rsp), %rsi
callq 0x949f0
jmp 0xba94d
leaq 0x78(%rsp), %rdi
callq 0x94a50
jmp 0xba959
movl 0x98(%rsp), %eax
movl %eax, 0xb0(%rsp)
leaq 0xa8(%rsp), %rdi
leaq 0x104(%rsp), %rsi
callq 0xb9a80
movb %al, 0xf(%rsp)
jmp 0xba982
movb 0xf(%rsp), %al
andb $0x1, %al
movb %al, 0x97(%rsp)
jmp 0xba9b6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
leaq 0x78(%rsp), %rdi
callq 0x94a50
jmp 0xba9b1
jmp 0xbac2a
jmp 0xba9b8
jmp 0xbabf1
movq 0x188(%rsp), %rdi
movq 0x160(%rsp), %rsi
leaq 0xfc(%rsp), %rdx
callq 0xbd2b0
movb %al, 0xe(%rsp)
jmp 0xba9e0
movb 0xe(%rsp), %al
testb $0x1, %al
jne 0xba9ed
jmp 0xbaab1
leaq 0x118(%rsp), %rdi
leaq 0x100(%rsp), %rsi
leaq 0x98(%rsp), %rdx
callq 0xbd720
movb %al, 0xd(%rsp)
jmp 0xbaa10
movb 0xd(%rsp), %al
testb $0x1, %al
jne 0xbaa1d
jmp 0xbaaaf
movss 0x100(%rsp), %xmm0
leaq 0x70(%rsp), %rdi
callq 0xbe070
jmp 0xbaa32
leaq 0xa8(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0x949f0
jmp 0xbaa46
leaq 0x70(%rsp), %rdi
callq 0x94a50
jmp 0xbaa52
movl 0x98(%rsp), %eax
movl %eax, 0xb0(%rsp)
leaq 0xa8(%rsp), %rdi
leaq 0xfc(%rsp), %rsi
callq 0xbe0f0
movb %al, 0xc(%rsp)
jmp 0xbaa7b
movb 0xc(%rsp), %al
andb $0x1, %al
movb %al, 0x97(%rsp)
jmp 0xbaaaf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
leaq 0x70(%rsp), %rdi
callq 0x94a50
jmp 0xbaaaa
jmp 0xbac2a
jmp 0xbaab1
jmp 0xbabf1
movq 0x188(%rsp), %rdi
movq 0x160(%rsp), %rsi
leaq 0xb8(%rsp), %rdx
callq 0xbe2f0
movb %al, 0xb(%rsp)
jmp 0xbaad9
movb 0xb(%rsp), %al
testb $0x1, %al
jne 0xbaae6
jmp 0xbabe7
leaq 0x118(%rsp), %rdi
leaq 0xd8(%rsp), %rsi
leaq 0x98(%rsp), %rdx
callq 0xa62b0
movb %al, 0xa(%rsp)
jmp 0xbab09
movb 0xa(%rsp), %al
testb $0x1, %al
jne 0xbab16
jmp 0xbabe5
leaq 0x48(%rsp), %rdi
leaq 0xd8(%rsp), %rsi
callq 0x86350
jmp 0xbab2a
leaq 0x68(%rsp), %rdi
leaq 0x48(%rsp), %rsi
callq 0x94910
jmp 0xbab3b
leaq 0xa8(%rsp), %rdi
leaq 0x68(%rsp), %rsi
callq 0x949f0
jmp 0xbab4f
leaq 0x68(%rsp), %rdi
callq 0x94a50
jmp 0xbab5b
leaq 0x48(%rsp), %rdi
callq 0x86f68
jmp 0xbab67
movl 0x98(%rsp), %eax
movl %eax, 0xb0(%rsp)
leaq 0xa8(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0xb9c50
movb %al, 0x9(%rsp)
jmp 0xbab90
movb 0x9(%rsp), %al
andb $0x1, %al
movb %al, 0x97(%rsp)
jmp 0xbabe5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
jmp 0xbabd7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x178(%rsp)
movl %eax, 0x174(%rsp)
leaq 0x68(%rsp), %rdi
callq 0x94a50
jmp 0xbabd5
jmp 0xbabd7
leaq 0x48(%rsp), %rdi
callq 0x86f68
jmp 0xbabe3
jmp 0xbac2a
jmp 0xbabe7
jmp 0xbabf1
movb $0x0, 0x97(%rsp)
movb 0x97(%rsp), %al
andb $0x1, %al
movb %al, 0x1a7(%rsp)
movl $0x1, 0x170(%rsp)
leaq 0xa8(%rsp), %rdi
callq 0xab8e0
jmp 0xbac1b
leaq 0xb8(%rsp), %rdi
callq 0x86f68
jmp 0xbac3b
leaq 0xa8(%rsp), %rdi
callq 0xab8e0
jmp 0xbac39
jmp 0xbac4a
leaq 0xd8(%rsp), %rdi
callq 0x86f68
jmp 0xbac5b
leaq 0xb8(%rsp), %rdi
callq 0x86f68
jmp 0xbac59
jmp 0xbac6a
leaq 0x118(%rsp), %rdi
callq 0x86f68
jmp 0xbac7b
leaq 0xd8(%rsp), %rdi
callq 0x86f68
jmp 0xbac79
jmp 0xbac7d
jmp 0xbac8e
leaq 0x118(%rsp), %rdi
callq 0x86f68
jmp 0xbac8c
jmp 0xbac9f
leaq 0x140(%rsp), %rdi
callq 0x86f68
jmp 0xbac9d
jmp 0xbacb0
leaq 0x140(%rsp), %rdi
callq 0x86f68
jmp 0xbacae
jmp 0xbacce
leaq 0x180(%rsp), %rdi
callq 0x94a50
movb 0x1a7(%rsp), %al
andb $0x1, %al
addq $0x1a8, %rsp            # imm = 0x1A8
retq
leaq 0x180(%rsp), %rdi
callq 0x94a50
jmp 0xbacdd
jmp 0xbacdf
movq 0x178(%rsp), %rdi
callq 0x86d80
movq %rax, %rdi
callq 0x91290
nopw %cs:(%rax,%rax)
nop