// File: MITRECND[P]snugglefish/src/nGramSearch.cpp
// Function: snugglefish::nGramSearch::searchNGrams[abi:cxx11](std::vector<unsigned long, std::allocator<unsigned long>>)
vector<string>* nGramSearch::searchNGrams(vector<uint64_t> nGramQuery){
    vector<string>* matchedFiles = new vector<string>;
    pthread_t * threads;
    thread_data* tdata;
    void* status;

    tdata = new thread_data();

    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    pthread_mutex_init(&(tdata->queueMutex), NULL);
    pthread_mutex_init(&(tdata->smFileMutex), NULL);
    pthread_mutex_init(&(tdata->mfMutex), NULL);

    tdata->ngramLength = ngramLength;
    tdata->queue = 0;
    tdata->maximumIndex = numIndexFiles;

    tdata->masterFile = (this->masterFile);
    tdata->matchedFiles = matchedFiles;
    tdata->baseFileName = &baseFileName;
    tdata->nGramQuery = &(nGramQuery);

    threads = (pthread_t*) malloc(numThreads * sizeof(pthread_t));

    //Create the threads
    for(uint32_t i = 0; i < numThreads; i++){
        pthread_create(& threads[i], &attr, searchNGramThread, (void*) (tdata));
    }
    
    //Join on them
    for(uint32_t i = 0; i < numThreads; i++){
        pthread_join(threads[i], &status);
    }

    pthread_mutex_destroy(&(tdata->queueMutex));
    pthread_mutex_destroy(&(tdata->smFileMutex));
    pthread_mutex_destroy(&(tdata->mfMutex));
    pthread_attr_destroy(&attr);

    free(threads);
    delete tdata;
    masterFile->close();
    return matchedFiles;

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa0, %rsp
movq %rsi, -0x80(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x78(%rbp)
movl $0x18, %edi
callq 0xe300
movq %rax, %rdi
movq %rdi, -0x90(%rbp)
callq 0x10350
movq -0x90(%rbp), %rax
movq %rax, -0x18(%rbp)
movl $0xa8, %edi
callq 0xe300
movq %rax, %rdi
movq %rdi, -0x88(%rbp)
xorl %esi, %esi
movl $0xa8, %edx
callq 0xe1a0
movq -0x88(%rbp), %rax
movq %rax, -0x28(%rbp)
leaq -0x68(%rbp), %rdi
callq 0xe3d0
leaq -0x68(%rbp), %rdi
xorl %esi, %esi
callq 0xe430
movq -0x28(%rbp), %rdi
addq $0x30, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xe4e0
movq -0x28(%rbp), %rdi
addq $0x58, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xe4e0
movq -0x28(%rbp), %rdi
addq $0x80, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xe4e0
movq -0x80(%rbp), %rsi
movq -0x78(%rbp), %rax
movzbl 0x28(%rax), %edx
movq -0x28(%rbp), %rcx
movl %edx, 0x8(%rcx)
movq -0x28(%rbp), %rcx
movl $0x0, (%rcx)
movl 0x48(%rax), %edx
movq -0x28(%rbp), %rcx
movl %edx, 0x4(%rcx)
movq 0x40(%rax), %rdx
movq -0x28(%rbp), %rcx
movq %rdx, 0x10(%rcx)
movq -0x18(%rbp), %rdx
movq -0x28(%rbp), %rcx
movq %rdx, 0x18(%rcx)
movq %rax, %rdx
addq $0x8, %rdx
movq -0x28(%rbp), %rcx
movq %rdx, 0x20(%rcx)
movq -0x28(%rbp), %rcx
movq %rsi, 0x28(%rcx)
movl 0x38(%rax), %eax
movl %eax, %edi
shlq $0x3, %rdi
callq 0xe440
movq %rax, -0x20(%rbp)
movl $0x0, -0x6c(%rbp)
movq -0x78(%rbp), %rcx
movl -0x6c(%rbp), %eax
cmpl 0x38(%rcx), %eax
jae 0x12dd0
movq -0x20(%rbp), %rdi
movl -0x6c(%rbp), %eax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x28(%rbp), %rcx
leaq -0x68(%rbp), %rsi
leaq 0xc0(%rip), %rdx        # 0x12e80
callq 0xe620
movl -0x6c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0x12d97
movl $0x0, -0x70(%rbp)
movq -0x78(%rbp), %rcx
movl -0x70(%rbp), %eax
cmpl 0x38(%rcx), %eax
jae 0x12e02
movq -0x20(%rbp), %rax
movl -0x70(%rbp), %ecx
movq (%rax,%rcx,8), %rdi
leaq -0x30(%rbp), %rsi
callq 0xe2d0
movl -0x70(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x70(%rbp)
jmp 0x12dd7
movq -0x28(%rbp), %rdi
addq $0x30, %rdi
callq 0xe390
movq -0x28(%rbp), %rdi
addq $0x58, %rdi
callq 0xe390
movq -0x28(%rbp), %rdi
addq $0x80, %rdi
callq 0xe390
leaq -0x68(%rbp), %rdi
callq 0xe570
movq -0x20(%rbp), %rdi
callq 0xe3b0
movq -0x28(%rbp), %rax
movq %rax, -0x98(%rbp)
cmpq $0x0, %rax
je 0x12e60
movq -0x98(%rbp), %rdi
movl $0xa8, %esi
callq 0xe310
movq -0x78(%rbp), %rax
movq 0x40(%rax), %rdi
callq 0x17bd0
movq -0x18(%rbp), %rax
addq $0xa0, %rsp
popq %rbp
retq
nopw (%rax,%rax)