// File: zeeev[P]DASVC/fastahack/Fasta.cpp
// Function: FastaIndex::indexReference(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>)
void FastaIndex::indexReference(string refname) {
    // overview:
    //  for line in the reference fasta file
    //  track byte offset from the start of the file
    //  if line is a fasta header, take the name and dump the last sequnece to the index
    //  if line is a sequence, add it to the current sequence
    //cerr << "indexing fasta reference " << refname << endl;
    string line;
    FastaIndexEntry entry;  // an entry buffer used in processing
    entry.clear();
    int line_length = 0;
    long long offset = 0;  // byte offset from start of file
    long long line_number = 0; // current line number
    bool mismatchedLineLengths = false; // flag to indicate if our line length changes mid-file
                                        // this will be used to raise an error
                                        // if we have a line length change at
                                        // any line other than the last line in
                                        // the sequence
    bool emptyLine = false;  // flag to catch empty lines, which we allow for
                             // index generation only on the last line of the sequence
    ifstream refFile;
    refFile.open(refname.c_str());
    if (refFile.is_open()) {
        while (getline(refFile, line)) {
            ++line_number;
            line_length = line.length();
            if (line[0] == ';') {
                // fasta comment, skip
            } else if (line[0] == '+') {
                // fastq quality header
                getline(refFile, line);
                line_length = line.length();
                offset += line_length + 1;
                // get and don't handle the quality line
                getline(refFile, line);
                line_length = line.length();
            } else if (line[0] == '>' || line[0] == '@') { // fasta /fastq header
                // if we aren't on the first entry, push the last sequence into the index
                if (entry.name != "") {
                    mismatchedLineLengths = false; // reset line length error tracker for every new sequence
                    emptyLine = false;
                    flushEntryToIndex(entry);
                    entry.clear();
                }
                entry.name = line.substr(1, line_length - 1);
            } else { // we assume we have found a sequence line
                if (entry.offset == -1) // NB initially the offset is -1
                    entry.offset = offset;
                entry.length += line_length;
                if (entry.line_len) {
                    //entry.line_len = entry.line_len ? entry.line_len : line_length + 1;
                    if (mismatchedLineLengths || emptyLine) {
                        if (line_length == 0) {
                            emptyLine = true; // flag empty lines, raise error only if this is embedded in the sequence
                        } else {
                            if (emptyLine) {
                                cerr << "ERROR: embedded newline";
                            } else {
                                cerr << "ERROR: mismatched line lengths";
                            }
                            cerr << " at line " << line_number << " within sequence " << entry.name <<
                                endl << "File not suitable for fasta index generation." << endl;
                            exit(1);
                        }
                    }
                    // this flag is set here and checked on the next line
                    // because we may have reached the end of the sequence, in
                    // which case a mismatched line length is OK
                    if (entry.line_len != line_length + 1) {
                        mismatchedLineLengths = true;
                        if (line_length == 0) {
                            emptyLine = true; // flag empty lines, raise error only if this is embedded in the sequence
                        }
                    }
                } else {
                    entry.line_len = line_length + 1; // first line
                }
                entry.line_blen = entry.line_len - 1;
            }
            offset += line_length + 1;
        }
        // we've hit the end of the fasta file!
        // flush the last entry
        flushEntryToIndex(entry);
    } else {
        cerr << "could not open reference file " << refname << " for indexing!" << endl;
        exit(1);
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x360, %rsp            # imm = 0x360
movq %rsi, -0x2c8(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x2c0(%rbp)
leaq -0x30(%rbp), %rdi
callq 0x3400
leaq -0x68(%rbp), %rdi
callq 0x3760
jmp 0x4149
leaq -0x68(%rbp), %rdi
callq 0x37b0
jmp 0x4154
movl $0x0, -0x78(%rbp)
movq $0x0, -0x80(%rbp)
movq $0x0, -0x88(%rbp)
movb $0x0, -0x89(%rbp)
movb $0x0, -0x8a(%rbp)
leaq -0x298(%rbp), %rdi
callq 0x3360
jmp 0x418a
movq -0x2c8(%rbp), %rdi
callq 0x3120
movq %rax, %rsi
leaq -0x298(%rbp), %rdi
movl $0x8, %edx
callq 0x31b0
jmp 0x41ac
leaq -0x298(%rbp), %rdi
callq 0x34b0
movb %al, -0x2c9(%rbp)
jmp 0x41c0
movb -0x2c9(%rbp), %al
testb $0x1, %al
jne 0x41cf
jmp 0x45b2
jmp 0x41d1
leaq -0x298(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0x30b0
movq %rax, -0x2d8(%rbp)
jmp 0x41ea
movq -0x2d8(%rbp), %rdi
movq (%rdi), %rax
movq -0x18(%rax), %rax
addq %rax, %rdi
callq 0x33c0
movb %al, -0x2d9(%rbp)
jmp 0x4208
movb -0x2d9(%rbp), %al
testb $0x1, %al
jne 0x4217
jmp 0x459e
movq -0x88(%rbp), %rax
incq %rax
movq %rax, -0x88(%rbp)
leaq -0x30(%rbp), %rdi
movq %rdi, -0x2f0(%rbp)
callq 0x3440
movq -0x2f0(%rbp), %rdi
movl %eax, -0x78(%rbp)
xorl %eax, %eax
movl %eax, %esi
callq 0x3580
movq %rax, -0x2e8(%rbp)
jmp 0x4254
movq -0x2e8(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x3b, %eax
jne 0x42a7
jmp 0x4589
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x4655
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x464c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x298(%rbp), %rdi
callq 0x30d0
jmp 0x464c
xorl %eax, %eax
movl %eax, %esi
leaq -0x30(%rbp), %rdi
callq 0x3580
movq %rax, -0x2f8(%rbp)
jmp 0x42bd
movq -0x2f8(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x2b, %eax
jne 0x4328
leaq -0x298(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0x30b0
jmp 0x42de
leaq -0x30(%rbp), %rdi
movq %rdi, -0x300(%rbp)
callq 0x3440
movq -0x300(%rbp), %rsi
movl %eax, -0x78(%rbp)
movslq -0x78(%rbp), %rax
movq -0x80(%rbp), %rcx
leaq 0x1(%rax,%rcx), %rax
movq %rax, -0x80(%rbp)
leaq -0x298(%rbp), %rdi
callq 0x30b0
jmp 0x4317
leaq -0x30(%rbp), %rdi
callq 0x3440
movl %eax, -0x78(%rbp)
jmp 0x4587
xorl %eax, %eax
movl %eax, %esi
leaq -0x30(%rbp), %rdi
callq 0x3580
movq %rax, -0x308(%rbp)
jmp 0x433e
movq -0x308(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x3e, %eax
je 0x4376
xorl %eax, %eax
movl %eax, %esi
leaq -0x30(%rbp), %rdi
callq 0x3580
movq %rax, -0x310(%rbp)
jmp 0x4363
movq -0x310(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x40, %eax
jne 0x4407
leaq 0x9c99(%rip), %rsi      # 0xe016
leaq -0x68(%rbp), %rdi
callq 0x6000
movb %al, -0x311(%rbp)
jmp 0x438e
movb -0x311(%rbp), %al
testb $0x1, %al
jne 0x439a
jmp 0x43c7
movq -0x2c0(%rbp), %rdi
movb $0x0, -0x89(%rbp)
movb $0x0, -0x8a(%rbp)
leaq -0x68(%rbp), %rsi
callq 0x4670
jmp 0x43ba
leaq -0x68(%rbp), %rdi
callq 0x37b0
jmp 0x43c5
jmp 0x43c7
movl -0x78(%rbp), %eax
decl %eax
movslq %eax, %rcx
leaq -0x2b8(%rbp), %rdi
leaq -0x30(%rbp), %rsi
movl $0x1, %edx
callq 0x32f0
jmp 0x43e6
leaq -0x68(%rbp), %rdi
leaq -0x2b8(%rbp), %rsi
callq 0x33a0
leaq -0x2b8(%rbp), %rdi
callq 0x31a0
jmp 0x4585
cmpq $-0x1, -0x40(%rbp)
jne 0x4416
movq -0x80(%rbp), %rax
movq %rax, -0x40(%rbp)
movl -0x78(%rbp), %eax
addl -0x48(%rbp), %eax
movl %eax, -0x48(%rbp)
cmpl $0x0, -0x34(%rbp)
je 0x4573
testb $0x1, -0x89(%rbp)
jne 0x443f
testb $0x1, -0x8a(%rbp)
je 0x454e
cmpl $0x0, -0x78(%rbp)
jne 0x4451
movb $0x1, -0x8a(%rbp)
jmp 0x454c
testb $0x1, -0x8a(%rbp)
je 0x4471
movq 0xfb8f(%rip), %rdi      # 0x13ff0
leaq 0x9c13(%rip), %rsi      # 0xe07b
callq 0x32b0
jmp 0x446f
jmp 0x4488
movq 0xfb78(%rip), %rdi      # 0x13ff0
leaq 0x9c14(%rip), %rsi      # 0xe093
callq 0x32b0
jmp 0x4486
jmp 0x4488
movq 0xfb61(%rip), %rdi      # 0x13ff0
leaq 0x9c1c(%rip), %rsi      # 0xe0b2
callq 0x32b0
movq %rax, -0x320(%rbp)
jmp 0x44a4
movq -0x320(%rbp), %rdi
movq -0x88(%rbp), %rsi
callq 0x3160
movq %rax, -0x328(%rbp)
jmp 0x44c0
movq -0x328(%rbp), %rdi
leaq 0x9bee(%rip), %rsi      # 0xe0bc
callq 0x32b0
movq %rax, -0x330(%rbp)
jmp 0x44dc
movq -0x330(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0x3280
movq %rax, -0x338(%rbp)
jmp 0x44f5
movq -0x338(%rbp), %rdi
movq 0xfaa5(%rip), %rsi      # 0x13fa8
callq 0x3310
movq %rax, -0x340(%rbp)
jmp 0x4511
movq -0x340(%rbp), %rdi
leaq 0x9baf(%rip), %rsi      # 0xe0ce
callq 0x32b0
movq %rax, -0x348(%rbp)
jmp 0x452d
movq -0x348(%rbp), %rdi
movq 0xfa6d(%rip), %rsi      # 0x13fa8
callq 0x3310
jmp 0x4542
movl $0x1, %edi
callq 0x3390
jmp 0x454e
movl -0x34(%rbp), %eax
movl -0x78(%rbp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
je 0x4571
movb $0x1, -0x89(%rbp)
cmpl $0x0, -0x78(%rbp)
jne 0x456f
movb $0x1, -0x8a(%rbp)
jmp 0x4571
jmp 0x457c
movl -0x78(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
movl -0x34(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x38(%rbp)
jmp 0x4587
jmp 0x4589
movl -0x78(%rbp), %eax
addl $0x1, %eax
cltq
addq -0x80(%rbp), %rax
movq %rax, -0x80(%rbp)
jmp 0x41d1
movq -0x2c0(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0x4670
jmp 0x45b0
jmp 0x4625
movq 0xfa37(%rip), %rdi      # 0x13ff0
leaq 0x9b3c(%rip), %rsi      # 0xe0fc
callq 0x32b0
movq %rax, -0x350(%rbp)
jmp 0x45ce
movq -0x2c8(%rbp), %rsi
movq -0x350(%rbp), %rdi
callq 0x3280
movq %rax, -0x358(%rbp)
jmp 0x45ea
movq -0x358(%rbp), %rdi
leaq 0x9b23(%rip), %rsi      # 0xe11b
callq 0x32b0
movq %rax, -0x360(%rbp)
jmp 0x4606
movq -0x360(%rbp), %rdi
movq 0xf994(%rip), %rsi      # 0x13fa8
callq 0x3310
jmp 0x461b
movl $0x1, %edi
callq 0x3390
leaq -0x298(%rbp), %rdi
callq 0x30d0
leaq -0x68(%rbp), %rdi
callq 0x3800
leaq -0x30(%rbp), %rdi
callq 0x31a0
addq $0x360, %rsp            # imm = 0x360
popq %rbp
retq
leaq -0x68(%rbp), %rdi
callq 0x3800
leaq -0x30(%rbp), %rdi
callq 0x31a0
movq -0x70(%rbp), %rdi
callq 0x3500
nopw (%rax,%rax)