// File: aalto-speech[P]ftk/util/Ngram.cc
// Function: Ngram::read_arpa(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>)
void
Ngram::read_arpa(string arpafname) {

    ifstream arpafile(arpafname);
    string header_error("Invalid ARPA header");
    if (!arpafile) throw string("Problem opening ARPA file: " + arpafname);

    int linei = 0;
    string line;
    _getline(arpafile, line, linei);
    while (line.length() == 0)
        _getline(arpafile, line, linei);

    if (line.find("\\data\\") == string::npos) throw header_error;
    _getline(arpafile, line, linei);

    int curr_ngram_order = 1;
    int total_ngram_count = 0;
    while (line.length() > 0) {
        if (line.find("ngram ") == string::npos) throw header_error;
        stringstream vals(line);
        getline(vals, line, '=');
        getline(vals, line, '=');
        int count = stoi(line);
        ngram_counts_per_order[curr_ngram_order] = count;
        total_ngram_count += count;
        curr_ngram_order++;
        _getline(arpafile, line, linei);
    }

    int max_ngram_order = curr_ngram_order-1;
    int total_ngrams_read = 0;
    curr_ngram_order = 1;
    nodes.resize(total_ngram_count+1);
    arc_words.resize(total_ngram_count);
    arc_target_nodes.resize(total_ngram_count);
    int curr_node_idx = 1;
    int curr_arc_idx = 0;

    while (curr_ngram_order <= max_ngram_order) {

        while (line.length() == 0)
            _getline(arpafile, line, linei);
        if (line.find("-grams") == string::npos) {
            cerr << line;
            throw header_error;
        }

        _getline(arpafile, line, linei);
        vector<NgramInfo> order_ngrams;
        int ngrams_read = read_arpa_read_order(arpafile, order_ngrams, line, curr_ngram_order, linei);

        cerr << "n-grams for order " << curr_ngram_order << ": " << ngrams_read << endl;
        if (ngrams_read != ngram_counts_per_order[curr_ngram_order])
            throw string("Invalid number of n-grams for order: " + curr_ngram_order);

        sort(order_ngrams.begin(), order_ngrams.end());

        read_arpa_insert_order_to_tree(order_ngrams, curr_node_idx, curr_arc_idx, curr_ngram_order);

        max_order = curr_ngram_order;
        curr_ngram_order++;
        total_ngrams_read += ngrams_read;
    }

    sentence_start_symbol_idx = vocabulary_lookup[sentence_start_symbol];
    sentence_start_node = find_node(root_node, sentence_start_symbol_idx);
    if (sentence_start_node == -1) throw string("Sentence start symbol not found.");
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x540, %rsp            # imm = 0x540
movq %rsi, -0x468(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x460(%rbp)
leaq -0x218(%rbp), %rdi
movl $0x8, %edx
callq 0x4640
leaq -0x239(%rbp), %rdi
movq %rdi, -0x458(%rbp)
callq 0x46f0
movq -0x458(%rbp), %rdx
leaq 0x540eb(%rip), %rsi     # 0x66432
leaq -0x238(%rbp), %rdi
callq 0x4550
jmp 0x12355
leaq -0x239(%rbp), %rdi
callq 0x4420
movq -0x218(%rbp), %rax
movq -0x18(%rax), %rax
leaq -0x218(%rbp,%rax), %rdi
callq 0x41d0
movb %al, -0x469(%rbp)
jmp 0x12381
movb -0x469(%rbp), %al
testb $0x1, %al
jne 0x12390
jmp 0x12438
movl $0x20, %edi
callq 0x41e0
movq -0x468(%rbp), %rdx
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x478(%rbp)
leaq 0x54091(%rip), %rsi     # 0x66446
callq 0x13840
jmp 0x123bc
movq -0x478(%rbp), %rdi
leaq 0x81986(%rip), %rsi     # 0x93d50
movq 0x81bcf(%rip), %rdx     # 0x93fa0
callq 0x46b0
jmp 0x12c76
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x248(%rbp)
movl %eax, -0x24c(%rbp)
leaq -0x239(%rbp), %rdi
callq 0x4420
jmp 0x12c5e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x248(%rbp)
movl %eax, -0x24c(%rbp)
jmp 0x12c52
movq -0x478(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x248(%rbp)
movl %eax, -0x24c(%rbp)
callq 0x42f0
jmp 0x12c52
movl $0x0, -0x250(%rbp)
leaq -0x270(%rbp), %rdi
movq %rdi, -0x480(%rbp)
callq 0x4560
movq -0x480(%rbp), %rsi
leaq -0x218(%rbp), %rdi
leaq -0x250(%rbp), %rdx
callq 0x121d0
jmp 0x12471
jmp 0x12473
leaq -0x270(%rbp), %rdi
callq 0x45e0
cmpq $0x0, %rax
jne 0x124ba
leaq -0x218(%rbp), %rdi
leaq -0x270(%rbp), %rsi
leaq -0x250(%rbp), %rdx
callq 0x121d0
jmp 0x124a1
jmp 0x12473
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x248(%rbp)
movl %eax, -0x24c(%rbp)
jmp 0x12c46
leaq -0x270(%rbp), %rdi
leaq 0x53f9a(%rip), %rsi     # 0x66462
xorl %eax, %eax
movl %eax, %edx
callq 0x47e0
cmpq $-0x1, %rax
jne 0x12516
movl $0x20, %edi
callq 0x41e0
movq %rax, %rdi
movq %rdi, -0x488(%rbp)
leaq -0x238(%rbp), %rsi
callq 0x4250
movq -0x488(%rbp), %rdi
leaq 0x8184b(%rip), %rsi     # 0x93d50
movq 0x81a94(%rip), %rdx     # 0x93fa0
callq 0x46b0
jmp 0x12c76
leaq -0x218(%rbp), %rdi
leaq -0x270(%rbp), %rsi
leaq -0x250(%rbp), %rdx
callq 0x121d0
jmp 0x12532
movl $0x1, -0x274(%rbp)
movl $0x0, -0x278(%rbp)
leaq -0x270(%rbp), %rdi
callq 0x45e0
cmpq $0x0, %rax
jbe 0x126f7
leaq -0x270(%rbp), %rdi
leaq 0x53eff(%rip), %rsi     # 0x66469
xorl %eax, %eax
movl %eax, %edx
callq 0x47e0
cmpq $-0x1, %rax
jne 0x125b8
movl $0x20, %edi
callq 0x41e0
movq %rax, %rdi
movq %rdi, -0x490(%rbp)
leaq -0x238(%rbp), %rsi
callq 0x4250
movq -0x490(%rbp), %rdi
leaq 0x817a9(%rip), %rsi     # 0x93d50
movq 0x819f2(%rip), %rdx     # 0x93fa0
callq 0x46b0
jmp 0x12c76
movl $0x10, %edi
movl $0x8, %esi
callq 0x13950
movl %eax, -0x494(%rbp)
jmp 0x125cf
movl -0x494(%rbp), %edx
leaq -0x400(%rbp), %rdi
leaq -0x270(%rbp), %rsi
callq 0x4630
jmp 0x125ea
leaq -0x400(%rbp), %rdi
leaq -0x270(%rbp), %rsi
movl $0x3d, %edx
callq 0x4750
jmp 0x12604
leaq -0x400(%rbp), %rdi
leaq -0x270(%rbp), %rsi
movl $0x3d, %edx
callq 0x4750
jmp 0x1261e
xorl %eax, %eax
movl %eax, %esi
leaq -0x270(%rbp), %rdi
movl $0xa, %edx
callq 0x13970
movl %eax, -0x498(%rbp)
jmp 0x1263b
movq -0x460(%rbp), %rdi
movl -0x498(%rbp), %eax
movl %eax, -0x404(%rbp)
movl -0x404(%rbp), %eax
movl %eax, -0x4a4(%rbp)
addq $0xc0, %rdi
leaq -0x274(%rbp), %rsi
callq 0x139b0
movq %rax, -0x4a0(%rbp)
jmp 0x12676
movq -0x4a0(%rbp), %rax
movl -0x4a4(%rbp), %ecx
movl %ecx, (%rax)
movl -0x404(%rbp), %ecx
movl -0x278(%rbp), %eax
addl %ecx, %eax
movl %eax, -0x278(%rbp)
movl -0x274(%rbp), %eax
incl %eax
movl %eax, -0x274(%rbp)
leaq -0x218(%rbp), %rdi
leaq -0x270(%rbp), %rsi
leaq -0x250(%rbp), %rdx
callq 0x121d0
jmp 0x126c3
leaq -0x400(%rbp), %rdi
callq 0x4310
jmp 0x12546
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x248(%rbp)
movl %eax, -0x24c(%rbp)
leaq -0x400(%rbp), %rdi
callq 0x4310
jmp 0x12c46
movq -0x460(%rbp), %rdi
movl -0x274(%rbp), %eax
decl %eax
movl %eax, -0x408(%rbp)
movl $0x0, -0x40c(%rbp)
movl $0x1, -0x274(%rbp)
addq $0x78, %rdi
movl -0x278(%rbp), %eax
incl %eax
movslq %eax, %rsi
callq 0x13a90
jmp 0x12736
movq -0x460(%rbp), %rdi
addq $0x90, %rdi
movslq -0x278(%rbp), %rsi
callq 0x13b20
jmp 0x12752
movq -0x460(%rbp), %rdi
addq $0xa8, %rdi
movslq -0x278(%rbp), %rsi
callq 0x13b20
jmp 0x1276e
movl $0x1, -0x410(%rbp)
movl $0x0, -0x414(%rbp)
movl -0x274(%rbp), %eax
cmpl -0x408(%rbp), %eax
jg 0x12b0f
jmp 0x12796
leaq -0x270(%rbp), %rdi
callq 0x45e0
cmpq $0x0, %rax
jne 0x127c6
leaq -0x218(%rbp), %rdi
leaq -0x270(%rbp), %rsi
leaq -0x250(%rbp), %rdx
callq 0x121d0
jmp 0x127c4
jmp 0x12796
leaq -0x270(%rbp), %rdi
leaq 0x53db5(%rip), %rsi     # 0x66589
xorl %eax, %eax
movl %eax, %edx
callq 0x47e0
cmpq $-0x1, %rax
jne 0x12837
movq 0x817fe(%rip), %rdi     # 0x93fe8
leaq -0x270(%rbp), %rsi
callq 0x4380
jmp 0x127f8
movl $0x20, %edi
callq 0x41e0
movq %rax, %rdi
movq %rdi, -0x4b0(%rbp)
leaq -0x238(%rbp), %rsi
callq 0x4250
movq -0x4b0(%rbp), %rdi
leaq 0x8152a(%rip), %rsi     # 0x93d50
movq 0x81773(%rip), %rdx     # 0x93fa0
callq 0x46b0
jmp 0x12c76
leaq -0x218(%rbp), %rdi
leaq -0x270(%rbp), %rsi
leaq -0x250(%rbp), %rdx
callq 0x121d0
jmp 0x12853
leaq -0x430(%rbp), %rdi
movq %rdi, -0x4c0(%rbp)
callq 0x13bb0
movq -0x460(%rbp), %rdi
movq -0x4c0(%rbp), %rdx
movl -0x274(%rbp), %r8d
leaq -0x218(%rbp), %rsi
leaq -0x270(%rbp), %rcx
leaq -0x250(%rbp), %r9
callq 0x12c80
movl %eax, -0x4b4(%rbp)
jmp 0x1289d
movl -0x4b4(%rbp), %eax
movl %eax, -0x434(%rbp)
movq 0x81738(%rip), %rdi     # 0x93fe8
leaq 0x53bb9(%rip), %rsi     # 0x66470
callq 0x43c0
movq %rax, -0x4c8(%rbp)
jmp 0x128c5
movq -0x4c8(%rbp), %rdi
movl -0x274(%rbp), %esi
callq 0x46d0
movq %rax, -0x4d0(%rbp)
jmp 0x128e0
movq -0x4d0(%rbp), %rdi
leaq 0x53e08(%rip), %rsi     # 0x666f6
callq 0x43c0
movq %rax, -0x4d8(%rbp)
jmp 0x128fc
movq -0x4d8(%rbp), %rdi
movl -0x434(%rbp), %esi
callq 0x46d0
movq %rax, -0x4e0(%rbp)
jmp 0x12917
movq -0x4e0(%rbp), %rdi
movq 0x81673(%rip), %rsi     # 0x93f98
callq 0x4400
jmp 0x1292c
movq -0x460(%rbp), %rdi
movl -0x434(%rbp), %eax
movl %eax, -0x4ec(%rbp)
addq $0xc0, %rdi
leaq -0x274(%rbp), %rsi
callq 0x139b0
movq %rax, -0x4e8(%rbp)
jmp 0x1295b
movl -0x4ec(%rbp), %eax
movq -0x4e8(%rbp), %rcx
cmpl (%rcx), %eax
je 0x12a4d
movb $0x1, -0x436(%rbp)
movl $0x20, %edi
callq 0x41e0
movq %rax, -0x508(%rbp)
movq %rax, -0x510(%rbp)
movslq -0x274(%rbp), %rcx
leaq 0x53ae6(%rip), %rax     # 0x66483
addq %rcx, %rax
movq %rax, -0x500(%rbp)
leaq -0x435(%rbp), %rdi
movq %rdi, -0x4f8(%rbp)
callq 0x46f0
movq -0x508(%rbp), %rdi
movq -0x500(%rbp), %rsi
movq -0x4f8(%rbp), %rdx
callq 0x4550
jmp 0x129d6
movq -0x510(%rbp), %rdi
movb $0x0, -0x436(%rbp)
leaq 0x81365(%rip), %rsi     # 0x93d50
movq 0x815ae(%rip), %rdx     # 0x93fa0
callq 0x46b0
jmp 0x12c76
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x248(%rbp)
movl %eax, -0x24c(%rbp)
jmp 0x12afe
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x248(%rbp)
movl %eax, -0x24c(%rbp)
leaq -0x435(%rbp), %rdi
callq 0x4420
testb $0x1, -0x436(%rbp)
jne 0x12a3c
jmp 0x12a48
movq -0x510(%rbp), %rdi
callq 0x42f0
jmp 0x12afe
leaq -0x430(%rbp), %rdi
movq %rdi, -0x518(%rbp)
callq 0x13c10
movq -0x518(%rbp), %rdi
movq %rax, -0x440(%rbp)
callq 0x13c40
movq %rax, -0x448(%rbp)
movq -0x440(%rbp), %rdi
movq -0x448(%rbp), %rsi
callq 0x13bd0
jmp 0x12a8f
movq -0x460(%rbp), %rdi
movl -0x274(%rbp), %r8d
leaq -0x430(%rbp), %rsi
leaq -0x410(%rbp), %rdx
leaq -0x414(%rbp), %rcx
callq 0x13210
jmp 0x12ab9
movq -0x460(%rbp), %rax
movl -0x274(%rbp), %ecx
movl %ecx, 0xf0(%rax)
movl -0x274(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x274(%rbp)
movl -0x434(%rbp), %eax
addl -0x40c(%rbp), %eax
movl %eax, -0x40c(%rbp)
leaq -0x430(%rbp), %rdi
callq 0x13c70
jmp 0x12782
leaq -0x430(%rbp), %rdi
callq 0x13c70
jmp 0x12c46
movq -0x460(%rbp), %rsi
movq %rsi, %rdi
addq $0x48, %rdi
addq $0x10, %rsi
callq 0xa7c0
movq %rax, -0x520(%rbp)
jmp 0x12b2f
movq -0x460(%rbp), %rdi
movq -0x520(%rbp), %rax
movl (%rax), %eax
movl %eax, 0x8(%rdi)
movl (%rdi), %esi
movl 0x8(%rdi), %edx
callq 0x11fd0
movl %eax, -0x524(%rbp)
jmp 0x12b54
movq -0x460(%rbp), %rax
movl -0x524(%rbp), %ecx
movl %ecx, 0x4(%rax)
cmpl $-0x1, 0x4(%rax)
jne 0x12c19
movb $0x1, -0x44a(%rbp)
movl $0x20, %edi
callq 0x41e0
movq %rax, -0x538(%rbp)
movq %rax, -0x540(%rbp)
leaq -0x449(%rbp), %rdi
movq %rdi, -0x530(%rbp)
callq 0x46f0
movq -0x538(%rbp), %rdi
movq -0x530(%rbp), %rdx
leaq 0x538f4(%rip), %rsi     # 0x664a9
callq 0x4550
jmp 0x12bbc
movq -0x540(%rbp), %rdi
movb $0x0, -0x44a(%rbp)
leaq 0x8117f(%rip), %rsi     # 0x93d50
movq 0x813c8(%rip), %rdx     # 0x93fa0
callq 0x46b0
jmp 0x12c76
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x248(%rbp)
movl %eax, -0x24c(%rbp)
leaq -0x449(%rbp), %rdi
callq 0x4420
testb $0x1, -0x44a(%rbp)
jne 0x12c0b
jmp 0x12c17
movq -0x540(%rbp), %rdi
callq 0x42f0
jmp 0x12c46
leaq -0x270(%rbp), %rdi
callq 0x4828
leaq -0x238(%rbp), %rdi
callq 0x4828
leaq -0x218(%rbp), %rdi
callq 0x4100
addq $0x540, %rsp            # imm = 0x540
popq %rbp
retq
leaq -0x270(%rbp), %rdi
callq 0x4828
leaq -0x238(%rbp), %rdi
callq 0x4828
leaq -0x218(%rbp), %rdi
callq 0x4100
movq -0x248(%rbp), %rdi
callq 0x46e0
nopw %cs:(%rax,%rax)