// File: zeeev[P]DASVC/bamtools/src/toolkit/bamtools_convert.cpp
// Function: BamTools::ConvertTool::ConvertToolPrivate::PrintJson(BamTools::BamAlignment const&)
void ConvertTool::ConvertToolPrivate::PrintJson(const BamAlignment& a) {
  
    // write name & alignment flag
    m_out << "{\"name\":\"" << a.Name << "\",\"alignmentFlag\":\"" << a.AlignmentFlag << "\",";
    
    // write reference name
    if ( (a.RefID >= 0) && (a.RefID < (int)m_references.size()) ) 
        m_out << "\"reference\":\"" << m_references[a.RefID].RefName << "\",";
    
    // write position & map quality
    m_out << "\"position\":" << a.Position+1 << ",\"mapQuality\":" << a.MapQuality << ",";
    
    // write CIGAR
    const vector<CigarOp>& cigarData = a.CigarData;
    if ( !cigarData.empty() ) {
        m_out << "\"cigar\":[";
        vector<CigarOp>::const_iterator cigarBegin = cigarData.begin();
        vector<CigarOp>::const_iterator cigarIter  = cigarBegin;
        vector<CigarOp>::const_iterator cigarEnd   = cigarData.end();
        for ( ; cigarIter != cigarEnd; ++cigarIter ) {
            const CigarOp& op = (*cigarIter);
            if (cigarIter != cigarBegin)
                m_out << ",";
            m_out << "\"" << op.Length << op.Type << "\"";
        }
        m_out << "],";
    }
    
    // write mate reference name, mate position, & insert size
    if ( a.IsPaired() && (a.MateRefID >= 0) && (a.MateRefID < (int)m_references.size()) ) {
        m_out << "\"mate\":{"
              << "\"reference\":\"" << m_references[a.MateRefID].RefName << "\","
              << "\"position\":" << a.MatePosition+1
              << ",\"insertSize\":" << a.InsertSize << "},";
    }
    
    // write sequence
    if ( !a.QueryBases.empty() ) 
        m_out << "\"queryBases\":\"" << a.QueryBases << "\",";
    
    // write qualities
    if ( !a.Qualities.empty() && a.Qualities.at(0) != (char)0xFF ) {
        string::const_iterator s = a.Qualities.begin();
        m_out << "\"qualities\":[" << static_cast<short>(*s) - 33;
        ++s;
        for ( ; s != a.Qualities.end(); ++s )
            m_out << "," << static_cast<short>(*s) - 33;
        m_out << "],";
    }
    
    // write alignment's source BAM file
    m_out << "\"filename\":\"" << a.Filename << "\",";

    // write tag data
    const char* tagData = a.TagData.c_str();
    const size_t tagDataLength = a.TagData.length();
    size_t index = 0;
    if ( index < tagDataLength ) {

        m_out << "\"tags\":{";
        
        while ( index < tagDataLength ) {

            if ( index > 0 )
                m_out << ",";
            
            // write tag name
            m_out << "\"" << a.TagData.substr(index, 2) << "\":";
            index += 2;
            
            // get data type
            char type = a.TagData.at(index);
            ++index;
            switch ( type ) {
                case (Constants::BAM_TAG_TYPE_ASCII) :
                    m_out << "\"" << tagData[index] << "\"";
                    ++index; 
                    break;
                
                case (Constants::BAM_TAG_TYPE_INT8) :
                    // force value into integer-type (instead of char value)
                    m_out << static_cast<int16_t>(tagData[index]);
                    ++index;
                    break;

                case (Constants::BAM_TAG_TYPE_UINT8) :
                    // force value into integer-type (instead of char value)
                    m_out << static_cast<uint16_t>(tagData[index]);
                    ++index; 
                    break;
                
                case (Constants::BAM_TAG_TYPE_INT16) :
                    m_out << BamTools::UnpackSignedShort(&tagData[index]);
                    index += sizeof(int16_t);
                    break;

                case (Constants::BAM_TAG_TYPE_UINT16) :
                    m_out << BamTools::UnpackUnsignedShort(&tagData[index]);
                    index += sizeof(uint16_t);
                    break;
                    
                case (Constants::BAM_TAG_TYPE_INT32) :
                    m_out << BamTools::UnpackSignedInt(&tagData[index]);
                    index += sizeof(int32_t);
                    break;

                case (Constants::BAM_TAG_TYPE_UINT32) :
                    m_out << BamTools::UnpackUnsignedInt(&tagData[index]);
                    index += sizeof(uint32_t);
                    break;

                case (Constants::BAM_TAG_TYPE_FLOAT) :
                    m_out << BamTools::UnpackFloat(&tagData[index]);
                    index += sizeof(float);
                    break;
                
                case (Constants::BAM_TAG_TYPE_HEX)    :
                case (Constants::BAM_TAG_TYPE_STRING) :
                    m_out << "\""; 
                    while (tagData[index]) {
                        if (tagData[index] == '\"')
                            m_out << "\\\""; // escape for json
                        else
                            m_out << tagData[index];
                        ++index;
                    }
                    m_out << "\""; 
                    ++index; 
                    break;      
            }
            
            if ( tagData[index] == '\0') 
                break;
        }

        m_out << "}";
    }

    m_out << "}" << endl;
}

// Assembly:
subq $0x118, %rsp            # imm = 0x118
movq %rdi, 0x110(%rsp)
movq %rsi, 0x108(%rsp)
movq 0x110(%rsp), %rdi
movq %rdi, 0x80(%rsp)
addq $0x20, %rdi
leaq 0xa1862(%rip), %rsi     # 0x12e454
callq 0x86700
movq %rax, %rdi
movq 0x108(%rsp), %rsi
callq 0x86640
movq %rax, %rdi
leaq 0xa184d(%rip), %rsi     # 0x12e45e
callq 0x86700
movq %rax, %rdi
movq 0x108(%rsp), %rax
movl 0xb4(%rax), %esi
callq 0x869c0
movq %rax, %rdi
leaq 0xa183c(%rip), %rsi     # 0x12e472
callq 0x86700
movq 0x108(%rsp), %rax
cmpl $0x0, 0xa8(%rax)
jl 0x8ccd7
movq 0x80(%rsp), %rdi
movq 0x108(%rsp), %rax
movl 0xa8(%rax), %eax
movl %eax, 0x7c(%rsp)
addq $0x8, %rdi
callq 0x91700
movq %rax, %rcx
movl 0x7c(%rsp), %eax
cmpl %ecx, %eax
jge 0x8ccd7
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
leaq 0xa17e4(%rip), %rsi     # 0x12e475
callq 0x86700
movq 0x80(%rsp), %rdi
movq %rax, 0x70(%rsp)
addq $0x8, %rdi
movq 0x108(%rsp), %rax
movslq 0xa8(%rax), %rsi
callq 0x91720
movq 0x70(%rsp), %rdi
movq %rax, %rsi
callq 0x86640
movq %rax, %rdi
leaq 0xa17a0(%rip), %rsi     # 0x12e472
callq 0x86700
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
leaq 0xa1799(%rip), %rsi     # 0x12e483
callq 0x86700
movq %rax, %rdi
movq 0x108(%rsp), %rax
movl 0xac(%rax), %esi
addl $0x1, %esi
callq 0x86d40
movq %rax, %rdi
leaq 0xa177d(%rip), %rsi     # 0x12e48f
callq 0x86700
movq %rax, %rdi
movq 0x108(%rsp), %rax
movzwl 0xb2(%rax), %esi
callq 0x86cb0
movq %rax, %rdi
leaq 0xa173b(%rip), %rsi     # 0x12e473
callq 0x86700
movq 0x108(%rsp), %rax
addq $0xb8, %rax
movq %rax, 0x100(%rsp)
movq 0x100(%rsp), %rdi
callq 0x91740
testb $0x1, %al
jne 0x8ce97
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
leaq 0xa1723(%rip), %rsi     # 0x12e49e
callq 0x86700
movq 0x100(%rsp), %rdi
callq 0x91790
movq %rax, 0xf8(%rsp)
movq 0xf8(%rsp), %rax
movq %rax, 0xf0(%rsp)
movq 0x100(%rsp), %rdi
callq 0x917c0
movq %rax, 0xe8(%rsp)
leaq 0xf0(%rsp), %rdi
leaq 0xe8(%rsp), %rsi
callq 0x917f0
testb $0x1, %al
jne 0x8cdd8
jmp 0x8ce7f
leaq 0xf0(%rsp), %rdi
callq 0x91830
movq %rax, 0xe0(%rsp)
leaq 0xf0(%rsp), %rdi
leaq 0xf8(%rsp), %rsi
callq 0x917f0
testb $0x1, %al
jne 0x8ce08
jmp 0x8ce20
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
leaq 0xa1658(%rip), %rsi     # 0x12e473
callq 0x86700
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
leaq 0xa164e(%rip), %rsi     # 0x12e481
callq 0x86700
movq %rax, %rdi
movq 0xe0(%rsp), %rax
movl 0x4(%rax), %esi
callq 0x869c0
movq %rax, %rdi
movq 0xe0(%rsp), %rax
movsbl (%rax), %esi
callq 0x86890
movq %rax, %rdi
leaq 0xa1619(%rip), %rsi     # 0x12e481
callq 0x86700
leaq 0xf0(%rsp), %rdi
callq 0x91840
jmp 0x8cdba
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
leaq 0xa1616(%rip), %rsi     # 0x12e4a8
callq 0x86700
movq 0x108(%rsp), %rdi
callq 0x863d0
testb $0x1, %al
jne 0x8cead
jmp 0x8cfb8
movq 0x108(%rsp), %rax
cmpl $0x0, 0xd0(%rax)
jl 0x8cfb8
movq 0x80(%rsp), %rdi
movq 0x108(%rsp), %rax
movl 0xd0(%rax), %eax
movl %eax, 0x6c(%rsp)
addq $0x8, %rdi
callq 0x91700
movq %rax, %rcx
movl 0x6c(%rsp), %eax
cmpl %ecx, %eax
jge 0x8cfb8
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
leaq 0xa15a4(%rip), %rsi     # 0x12e4ab
callq 0x86700
movq %rax, %rdi
leaq 0xa155f(%rip), %rsi     # 0x12e475
callq 0x86700
movq 0x80(%rsp), %rdi
movq %rax, 0x60(%rsp)
addq $0x8, %rdi
movq 0x108(%rsp), %rax
movslq 0xd0(%rax), %rsi
callq 0x91720
movq 0x60(%rsp), %rdi
movq %rax, %rsi
callq 0x86640
movq %rax, %rdi
leaq 0xa151b(%rip), %rsi     # 0x12e472
callq 0x86700
movq %rax, %rdi
leaq 0xa151d(%rip), %rsi     # 0x12e483
callq 0x86700
movq %rax, %rdi
movq 0x108(%rsp), %rax
movl 0xd4(%rax), %esi
addl $0x1, %esi
callq 0x86d40
movq %rax, %rdi
leaq 0xa1526(%rip), %rsi     # 0x12e4b4
callq 0x86700
movq %rax, %rdi
movq 0x108(%rsp), %rax
movl 0xd8(%rax), %esi
callq 0x86d40
movq %rax, %rdi
leaq 0xa1510(%rip), %rsi     # 0x12e4c3
callq 0x86700
movq 0x108(%rsp), %rdi
addq $0x28, %rdi
callq 0x86c90
testb $0x1, %al
jne 0x8d008
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
leaq 0xa14e6(%rip), %rsi     # 0x12e4c6
callq 0x86700
movq %rax, %rdi
movq 0x108(%rsp), %rsi
addq $0x28, %rsi
callq 0x86640
movq %rax, %rdi
leaq 0xa146f(%rip), %rsi     # 0x12e472
callq 0x86700
movq 0x108(%rsp), %rdi
addq $0x68, %rdi
callq 0x86c90
testb $0x1, %al
jne 0x8d13d
movq 0x108(%rsp), %rdi
addq $0x68, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x868c0
movsbl (%rax), %eax
cmpl $-0x1, %eax
je 0x8d13d
movq 0x108(%rsp), %rdi
addq $0x68, %rdi
callq 0x866b0
movq 0x80(%rsp), %rdi
movq %rax, 0xd8(%rsp)
addq $0x20, %rdi
leaq 0xa1467(%rip), %rsi     # 0x12e4d5
callq 0x86700
movq %rax, 0x58(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x91860
movq 0x58(%rsp), %rdi
movsbl (%rax), %eax
movswl %ax, %esi
subl $0x21, %esi
callq 0x86d40
leaq 0xd8(%rsp), %rdi
callq 0x91870
movq 0x108(%rsp), %rdi
addq $0x68, %rdi
callq 0x86e90
movq %rax, 0xd0(%rsp)
leaq 0xd8(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
callq 0x91890
testb $0x1, %al
jne 0x8d0d9
jmp 0x8d125
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
leaq 0xa1387(%rip), %rsi     # 0x12e473
callq 0x86700
movq %rax, 0x50(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x91860
movq 0x50(%rsp), %rdi
movsbl (%rax), %eax
movswl %ax, %esi
subl $0x21, %esi
callq 0x86d40
leaq 0xd8(%rsp), %rdi
callq 0x91870
jmp 0x8d0a5
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
leaq 0xa1370(%rip), %rsi     # 0x12e4a8
callq 0x86700
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
leaq 0xa1393(%rip), %rsi     # 0x12e4e3
callq 0x86700
movq %rax, %rdi
movq 0x108(%rsp), %rsi
addq $0xe0, %rsi
callq 0x86640
movq %rax, %rdi
leaq 0xa12fc(%rip), %rsi     # 0x12e472
callq 0x86700
movq 0x108(%rsp), %rdi
addq $0x88, %rdi
callq 0x86320
movq %rax, 0xc8(%rsp)
movq 0x108(%rsp), %rdi
addq $0x88, %rdi
callq 0x86ac0
movq %rax, 0xc0(%rsp)
movq $0x0, 0xb8(%rsp)
movq 0xb8(%rsp), %rax
cmpq 0xc0(%rsp), %rax
jae 0x8d6a3
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
leaq 0xa1308(%rip), %rsi     # 0x12e4f0
callq 0x86700
movq 0xb8(%rsp), %rax
cmpq 0xc0(%rsp), %rax
jae 0x8d68b
cmpq $0x0, 0xb8(%rsp)
jbe 0x8d226
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
leaq 0xa1252(%rip), %rsi     # 0x12e473
callq 0x86700
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
leaq 0xa1248(%rip), %rsi     # 0x12e481
callq 0x86700
movq %rax, 0x38(%rsp)
movq 0x108(%rsp), %rsi
addq $0x88, %rsi
movq 0xb8(%rsp), %rdx
leaq 0x98(%rsp), %rdi
movq %rdi, 0x40(%rsp)
movl $0x2, %ecx
callq 0x86750
movq 0x38(%rsp), %rdi
movq 0x40(%rsp), %rsi
callq 0x86640
movq %rax, 0x48(%rsp)
jmp 0x8d287
movq 0x48(%rsp), %rdi
leaq 0xa122d(%rip), %rsi     # 0x12e4c0
callq 0x86700
jmp 0x8d29a
leaq 0x98(%rsp), %rdi
callq 0x86f68
movq 0xb8(%rsp), %rax
addq $0x2, %rax
movq %rax, 0xb8(%rsp)
movq 0x108(%rsp), %rdi
addq $0x88, %rdi
movq 0xb8(%rsp), %rsi
callq 0x868c0
movb (%rax), %al
movb %al, 0x8b(%rsp)
movq 0xb8(%rsp), %rax
incq %rax
movq %rax, 0xb8(%rsp)
movsbl 0x8b(%rsp), %eax
addl $-0x41, %eax
movl %eax, %ecx
movq %rcx, 0x30(%rsp)
subl $0x32, %eax
ja 0x8d66b
movq 0x30(%rsp), %rax
leaq 0xa0cea(%rip), %rcx     # 0x12e004
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x90(%rsp)
movl %eax, 0x8c(%rsp)
leaq 0x98(%rsp), %rdi
callq 0x86f68
jmp 0x8d346
jmp 0x8d6d2
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
leaq 0xa1123(%rip), %rsi     # 0x12e481
callq 0x86700
movq %rax, %rdi
movq 0xc8(%rsp), %rax
movq 0xb8(%rsp), %rcx
movsbl (%rax,%rcx), %esi
callq 0x86890
movq %rax, %rdi
leaq 0xa10f8(%rip), %rsi     # 0x12e481
callq 0x86700
movq 0xb8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xb8(%rsp)
jmp 0x8d66b
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
movq 0xc8(%rsp), %rax
movq 0xb8(%rsp), %rcx
movsbl (%rax,%rcx), %eax
movswl %ax, %esi
callq 0x86650
movq 0xb8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xb8(%rsp)
jmp 0x8d66b
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
movq 0xc8(%rsp), %rax
movq 0xb8(%rsp), %rcx
movsbl (%rax,%rcx), %eax
movzwl %ax, %esi
callq 0x86cb0
movq 0xb8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xb8(%rsp)
jmp 0x8d66b
movq 0x80(%rsp), %rax
addq $0x20, %rax
movq %rax, 0x28(%rsp)
movq 0xc8(%rsp), %rdi
addq 0xb8(%rsp), %rdi
callq 0x918d0
movq 0x28(%rsp), %rdi
movswl %ax, %esi
callq 0x86650
movq 0xb8(%rsp), %rax
addq $0x2, %rax
movq %rax, 0xb8(%rsp)
jmp 0x8d66b
movq 0x80(%rsp), %rax
addq $0x20, %rax
movq %rax, 0x20(%rsp)
movq 0xc8(%rsp), %rdi
addq 0xb8(%rsp), %rdi
callq 0x91900
movq 0x20(%rsp), %rdi
movzwl %ax, %esi
callq 0x86cb0
movq 0xb8(%rsp), %rax
addq $0x2, %rax
movq %rax, 0xb8(%rsp)
jmp 0x8d66b
movq 0x80(%rsp), %rax
addq $0x20, %rax
movq %rax, 0x18(%rsp)
movq 0xc8(%rsp), %rdi
addq 0xb8(%rsp), %rdi
callq 0x91930
movq 0x18(%rsp), %rdi
movl %eax, %esi
callq 0x86d40
movq 0xb8(%rsp), %rax
addq $0x4, %rax
movq %rax, 0xb8(%rsp)
jmp 0x8d66b
movq 0x80(%rsp), %rax
addq $0x20, %rax
movq %rax, 0x10(%rsp)
movq 0xc8(%rsp), %rdi
addq 0xb8(%rsp), %rdi
callq 0x91980
movq 0x10(%rsp), %rdi
movl %eax, %esi
callq 0x869c0
movq 0xb8(%rsp), %rax
addq $0x4, %rax
movq %rax, 0xb8(%rsp)
jmp 0x8d66b
movq 0x80(%rsp), %rax
addq $0x20, %rax
movq %rax, 0x8(%rsp)
movq 0xc8(%rsp), %rdi
addq 0xb8(%rsp), %rdi
callq 0x919d0
movq 0x8(%rsp), %rdi
callq 0x86570
movq 0xb8(%rsp), %rax
addq $0x4, %rax
movq %rax, 0xb8(%rsp)
jmp 0x8d66b
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
leaq 0xa0ece(%rip), %rsi     # 0x12e481
callq 0x86700
movq 0xc8(%rsp), %rax
movq 0xb8(%rsp), %rcx
cmpb $0x0, (%rax,%rcx)
je 0x8d63f
movq 0xc8(%rsp), %rax
movq 0xb8(%rsp), %rcx
movsbl (%rax,%rcx), %eax
cmpl $0x22, %eax
jne 0x8d601
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
leaq 0xa0eff(%rip), %rsi     # 0x12e4f9
callq 0x86700
jmp 0x8d626
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
movq 0xc8(%rsp), %rax
movq 0xb8(%rsp), %rcx
movsbl (%rax,%rcx), %esi
callq 0x86890
movq 0xb8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xb8(%rsp)
jmp 0x8d5b8
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
leaq 0xa0e2f(%rip), %rsi     # 0x12e481
callq 0x86700
movq 0xb8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xb8(%rsp)
movq 0xc8(%rsp), %rax
movq 0xb8(%rsp), %rcx
movsbl (%rax,%rcx), %eax
cmpl $0x0, %eax
jne 0x8d686
jmp 0x8d68b
jmp 0x8d1ed
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
leaq 0xa75f1(%rip), %rsi     # 0x134c8f
callq 0x86700
movq 0x80(%rsp), %rdi
addq $0x20, %rdi
leaq 0xa75d9(%rip), %rsi     # 0x134c8f
callq 0x86700
movq %rax, %rdi
movq 0xd78ab(%rip), %rsi     # 0x164f70
callq 0x86770
addq $0x118, %rsp            # imm = 0x118
retq
movq 0x90(%rsp), %rdi
callq 0x86d80
movq %rax, %rdi
callq 0x91290
nopw (%rax,%rax)