// File: ekg[P]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;
    int line_bytes = 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 (getlineCounting(refFile, line, line_bytes)) {
            ++line_number;
            line_length = line.length();
            if (line[0] == ';') {
                // fasta comment, skip
            } else if (line[0] == '+') {
                // fastq quality header
                
                // account for header offset
                offset += line_bytes;
                
                // read in quality line so its offset will be accounted for too
                // TODO: we don't support the quality offset field of the FAI format
                getlineCounting(refFile, line, line_bytes);
                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) {
                    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_bytes) {
                        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_bytes; // first line
                    entry.line_blen = line_length;
                }
            }
            offset += line_bytes;
        }
        // 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 $0x350, %rsp            # imm = 0x350
movq %rsi, -0x2d0(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x2c8(%rbp)
leaq -0x30(%rbp), %rdi
callq 0x3430
leaq -0x68(%rbp), %rdi
callq 0x37a0
jmp 0x4249
leaq -0x68(%rbp), %rdi
callq 0x37f0
jmp 0x4254
movl $0x0, -0x78(%rbp)
movl $0x0, -0x7c(%rbp)
movq $0x0, -0x88(%rbp)
movq $0x0, -0x90(%rbp)
movb $0x0, -0x91(%rbp)
movb $0x0, -0x92(%rbp)
leaq -0x2a0(%rbp), %rdi
callq 0x3370
jmp 0x4294
movq -0x2d0(%rbp), %rdi
callq 0x3120
movq %rax, %rsi
leaq -0x2a0(%rbp), %rdi
movl $0x8, %edx
callq 0x31b0
jmp 0x42b6
leaq -0x2a0(%rbp), %rdi
callq 0x34e0
movb %al, -0x2d1(%rbp)
jmp 0x42ca
movb -0x2d1(%rbp), %al
testb $0x1, %al
jne 0x42d9
jmp 0x467d
jmp 0x42db
leaq -0x2a0(%rbp), %rdi
leaq -0x30(%rbp), %rsi
leaq -0x7c(%rbp), %rdx
callq 0x4170
movb %al, -0x2d2(%rbp)
jmp 0x42f7
movb -0x2d2(%rbp), %al
testb $0x1, %al
jne 0x4306
jmp 0x4669
movq -0x90(%rbp), %rax
incq %rax
movq %rax, -0x90(%rbp)
leaq -0x30(%rbp), %rdi
movq %rdi, -0x2e8(%rbp)
callq 0x3470
movq -0x2e8(%rbp), %rdi
movl %eax, -0x78(%rbp)
xorl %eax, %eax
movl %eax, %esi
callq 0x35c0
movq %rax, -0x2e0(%rbp)
jmp 0x4343
movq -0x2e0(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x3b, %eax
jne 0x4396
jmp 0x4652
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x4720
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x4717
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x2a0(%rbp), %rdi
callq 0x30d0
jmp 0x4717
xorl %eax, %eax
movl %eax, %esi
leaq -0x30(%rbp), %rdi
callq 0x35c0
movq %rax, -0x2f0(%rbp)
jmp 0x43ac
movq -0x2f0(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x2b, %eax
jne 0x43f7
movslq -0x7c(%rbp), %rcx
movq -0x88(%rbp), %rax
addq %rcx, %rax
movq %rax, -0x88(%rbp)
leaq -0x2a0(%rbp), %rdi
leaq -0x30(%rbp), %rsi
leaq -0x7c(%rbp), %rdx
callq 0x4170
jmp 0x43e6
leaq -0x30(%rbp), %rdi
callq 0x3470
movl %eax, -0x78(%rbp)
jmp 0x4650
xorl %eax, %eax
movl %eax, %esi
leaq -0x30(%rbp), %rdi
callq 0x35c0
movq %rax, -0x2f8(%rbp)
jmp 0x440d
movq -0x2f8(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x3e, %eax
je 0x4445
xorl %eax, %eax
movl %eax, %esi
leaq -0x30(%rbp), %rdi
callq 0x35c0
movq %rax, -0x300(%rbp)
jmp 0x4432
movq -0x300(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x40, %eax
jne 0x44d6
leaq 0x9bca(%rip), %rsi      # 0xe016
leaq -0x68(%rbp), %rdi
callq 0x6170
movb %al, -0x301(%rbp)
jmp 0x445d
movb -0x301(%rbp), %al
testb $0x1, %al
jne 0x4469
jmp 0x4496
movq -0x2c8(%rbp), %rdi
movb $0x0, -0x91(%rbp)
movb $0x0, -0x92(%rbp)
leaq -0x68(%rbp), %rsi
callq 0x4740
jmp 0x4489
leaq -0x68(%rbp), %rdi
callq 0x37f0
jmp 0x4494
jmp 0x4496
movl -0x78(%rbp), %eax
decl %eax
movslq %eax, %rcx
leaq -0x2c0(%rbp), %rdi
leaq -0x30(%rbp), %rsi
movl $0x1, %edx
callq 0x3300
jmp 0x44b5
leaq -0x68(%rbp), %rdi
leaq -0x2c0(%rbp), %rsi
callq 0x33c0
leaq -0x2c0(%rbp), %rdi
callq 0x31a0
jmp 0x464e
cmpq $-0x1, -0x40(%rbp)
jne 0x44e8
movq -0x88(%rbp), %rax
movq %rax, -0x40(%rbp)
movl -0x78(%rbp), %eax
addl -0x48(%rbp), %eax
movl %eax, -0x48(%rbp)
cmpl $0x0, -0x34(%rbp)
je 0x4640
testb $0x1, -0x91(%rbp)
jne 0x4511
testb $0x1, -0x92(%rbp)
je 0x4620
cmpl $0x0, -0x78(%rbp)
jne 0x4523
movb $0x1, -0x92(%rbp)
jmp 0x461e
testb $0x1, -0x92(%rbp)
je 0x4543
movq 0xfabd(%rip), %rdi      # 0x13ff0
leaq 0x9b41(%rip), %rsi      # 0xe07b
callq 0x32c0
jmp 0x4541
jmp 0x455a
movq 0xfaa6(%rip), %rdi      # 0x13ff0
leaq 0x9b42(%rip), %rsi      # 0xe093
callq 0x32c0
jmp 0x4558
jmp 0x455a
movq 0xfa8f(%rip), %rdi      # 0x13ff0
leaq 0x9b4a(%rip), %rsi      # 0xe0b2
callq 0x32c0
movq %rax, -0x310(%rbp)
jmp 0x4576
movq -0x310(%rbp), %rdi
movq -0x90(%rbp), %rsi
callq 0x3160
movq %rax, -0x318(%rbp)
jmp 0x4592
movq -0x318(%rbp), %rdi
leaq 0x9b1c(%rip), %rsi      # 0xe0bc
callq 0x32c0
movq %rax, -0x320(%rbp)
jmp 0x45ae
movq -0x320(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0x3290
movq %rax, -0x328(%rbp)
jmp 0x45c7
movq -0x328(%rbp), %rdi
movq 0xf9d3(%rip), %rsi      # 0x13fa8
callq 0x3320
movq %rax, -0x330(%rbp)
jmp 0x45e3
movq -0x330(%rbp), %rdi
leaq 0x9add(%rip), %rsi      # 0xe0ce
callq 0x32c0
movq %rax, -0x338(%rbp)
jmp 0x45ff
movq -0x338(%rbp), %rdi
movq 0xf99b(%rip), %rsi      # 0x13fa8
callq 0x3320
jmp 0x4614
movl $0x1, %edi
callq 0x33b0
jmp 0x4620
movl -0x34(%rbp), %eax
cmpl -0x7c(%rbp), %eax
je 0x463e
movb $0x1, -0x91(%rbp)
cmpl $0x0, -0x78(%rbp)
jne 0x463c
movb $0x1, -0x92(%rbp)
jmp 0x463e
jmp 0x464c
movl -0x7c(%rbp), %eax
movl %eax, -0x34(%rbp)
movl -0x78(%rbp), %eax
movl %eax, -0x38(%rbp)
jmp 0x464e
jmp 0x4650
jmp 0x4652
movslq -0x7c(%rbp), %rax
addq -0x88(%rbp), %rax
movq %rax, -0x88(%rbp)
jmp 0x42db
movq -0x2c8(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0x4740
jmp 0x467b
jmp 0x46f0
movq 0xf96c(%rip), %rdi      # 0x13ff0
leaq 0x9a71(%rip), %rsi      # 0xe0fc
callq 0x32c0
movq %rax, -0x340(%rbp)
jmp 0x4699
movq -0x2d0(%rbp), %rsi
movq -0x340(%rbp), %rdi
callq 0x3290
movq %rax, -0x348(%rbp)
jmp 0x46b5
movq -0x348(%rbp), %rdi
leaq 0x9a58(%rip), %rsi      # 0xe11b
callq 0x32c0
movq %rax, -0x350(%rbp)
jmp 0x46d1
movq -0x350(%rbp), %rdi
movq 0xf8c9(%rip), %rsi      # 0x13fa8
callq 0x3320
jmp 0x46e6
movl $0x1, %edi
callq 0x33b0
leaq -0x2a0(%rbp), %rdi
callq 0x30d0
leaq -0x68(%rbp), %rdi
callq 0x3840
leaq -0x30(%rbp), %rdi
callq 0x31a0
addq $0x350, %rsp            # imm = 0x350
popq %rbp
retq
leaq -0x68(%rbp), %rdi
callq 0x3840
leaq -0x30(%rbp), %rdi
callq 0x31a0
movq -0x70(%rbp), %rdi
callq 0x3540
nopw %cs:(%rax,%rax)