// File: LandonSwartz[P]TheGreatEncryptor/./EncryptionClass.cpp
// Function: encryption_base::decrypt_data()
bool decrypt_data() {
        if (this->hash_key == 0) {
            throw file_decryption_error("no hash key has been set");
            return false;
        }
        if (data_state == 0) {
            throw file_decryption_error("there is no data to decrypt");
            return false;
        } else if (data_state == 2) {
            throw file_decryption_error("the data has already been decrypted");
            return false;
        }
        
        // Set up the structs for the threads which will encrypt the data.
        vector<alg_prms *> encryption_alg_prms_vect;
        int indices_per_thread;
        int num_threads;
        int end_additional_increment = 0;
        // Ensure there will be at least one string per thread
        if (data->size() >= NUM_ENCRYPTION_THREADS) {
            indices_per_thread = (data->size()) / NUM_ENCRYPTION_THREADS;
            end_additional_increment = (data->size()) % NUM_ENCRYPTION_THREADS;
            num_threads = NUM_ENCRYPTION_THREADS;
        }
        // If there will not be one string per thread, simply use one thread
        else {
            num_threads = 1;
            indices_per_thread = data->size();
        }
        for (int i = 0; i < num_threads; i++) {
            alg_prms * alg_prms_strc = new alg_prms();
            alg_prms_strc->data = this->data;
            alg_prms_strc->hash_key = this->hash_key;
            alg_prms_strc->start_index = (i * indices_per_thread);
            alg_prms_strc->end_index = ((i + 1) * indices_per_thread) - 1;
            encryption_alg_prms_vect.push_back(alg_prms_strc);
        }
        // Add end_additional_increment
        encryption_alg_prms_vect.back()->end_index += end_additional_increment;

        // Create the threads to encrypt the data
        vector<pthread_t> encryption_threads;
        for (auto prm_vct : encryption_alg_prms_vect) {
            pthread_t new_thread;
            pthread_create(&new_thread, NULL, decryption_algorithm, prm_vct);
            encryption_threads.push_back(new_thread);
        }

        // Now that the threads are running, join them so the function will yield
        for (auto thread : encryption_threads) {
            pthread_join(thread, NULL);
        }

        // Delete the dynamically allocated structs once all thread operation has completed
        for (auto prm_vct : encryption_alg_prms_vect) {
            delete prm_vct;
        }

        // Return true to indicate the encryption was successful.
        return true;
    }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x110, %rsp            # imm = 0x110
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0xd0(%rbp)
cmpl $0x0, 0x10(%rax)
jne 0x575c
movl $0x10, %edi
callq 0x20e0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xd8(%rbp)
leaq 0x2ae3(%rip), %rsi      # 0x8201
callq 0x5b80
jmp 0x5725
movq -0xd8(%rbp), %rdi
leaq 0x662d(%rip), %rsi      # 0xbd60
leaq 0x486(%rip), %rdx       # 0x5bc0
callq 0x22d0
movq -0xd8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x10(%rbp)
movl %eax, -0x14(%rbp)
callq 0x2130
jmp 0x5b6e
movq -0xd0(%rbp), %rax
cmpl $0x0, (%rax)
jne 0x57c4
movl $0x10, %edi
callq 0x20e0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xe0(%rbp)
leaq 0x2ae8(%rip), %rsi      # 0x826e
callq 0x5b80
jmp 0x578d
movq -0xe0(%rbp), %rdi
leaq 0x65c5(%rip), %rsi      # 0xbd60
leaq 0x41e(%rip), %rdx       # 0x5bc0
callq 0x22d0
movq -0xe0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x10(%rbp)
movl %eax, -0x14(%rbp)
callq 0x2130
jmp 0x5b6e
movq -0xd0(%rbp), %rax
cmpl $0x2, (%rax)
jne 0x582c
movl $0x10, %edi
callq 0x20e0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xe8(%rbp)
leaq 0x2a9c(%rip), %rsi      # 0x828a
callq 0x5b80
jmp 0x57f5
movq -0xe8(%rbp), %rdi
leaq 0x655d(%rip), %rsi      # 0xbd60
leaq 0x3b6(%rip), %rdx       # 0x5bc0
callq 0x22d0
movq -0xe8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x10(%rbp)
movl %eax, -0x14(%rbp)
callq 0x2130
jmp 0x5b6e
jmp 0x582e
leaq -0x30(%rbp), %rdi
callq 0x3f80
movq -0xd0(%rbp), %rax
movl $0x0, -0x3c(%rbp)
movq 0x8(%rax), %rdi
callq 0x3fa0
cmpq $0xa, %rax
jb 0x589c
movq -0xd0(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0x3fa0
movl $0xa, %ecx
xorl %edx, %edx
divq %rcx
movq %rax, %rcx
movq -0xd0(%rbp), %rax
movl %ecx, -0x34(%rbp)
movq 0x8(%rax), %rdi
callq 0x3fa0
movl $0xa, %ecx
xorl %edx, %edx
divq %rcx
movl %edx, %eax
movl %eax, -0x3c(%rbp)
movl $0xa, -0x38(%rbp)
jmp 0x58b6
movq -0xd0(%rbp), %rax
movl $0x1, -0x38(%rbp)
movq 0x8(%rax), %rdi
callq 0x3fa0
movl %eax, -0x34(%rbp)
movl $0x0, -0x40(%rbp)
movl -0x40(%rbp), %eax
cmpl -0x38(%rbp), %eax
jge 0x5965
movl $0x18, %edi
callq 0x2190
movq %rax, -0xf0(%rbp)
jmp 0x58dc
movq -0xd0(%rbp), %rax
movq -0xf0(%rbp), %rcx
xorps %xmm0, %xmm0
movaps %xmm0, (%rcx)
movq $0x0, 0x10(%rcx)
movq %rcx, -0x48(%rbp)
movq 0x8(%rax), %rdx
movq -0x48(%rbp), %rcx
movq %rdx, (%rcx)
movl 0x10(%rax), %ecx
movq -0x48(%rbp), %rax
movl %ecx, 0x10(%rax)
movl -0x40(%rbp), %ecx
movl -0x34(%rbp), %eax
imull %eax, %ecx
movq -0x48(%rbp), %rax
movl %ecx, 0x8(%rax)
movl -0x40(%rbp), %ecx
incl %ecx
movl -0x34(%rbp), %eax
imull %eax, %ecx
decl %ecx
movq -0x48(%rbp), %rax
movl %ecx, 0xc(%rax)
leaq -0x30(%rbp), %rdi
leaq -0x48(%rbp), %rsi
callq 0x3fc0
jmp 0x5944
jmp 0x5946
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
jmp 0x58bd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x10(%rbp)
movl %eax, -0x14(%rbp)
jmp 0x5b65
movl -0x3c(%rbp), %eax
movl %eax, -0xf4(%rbp)
leaq -0x30(%rbp), %rdi
callq 0x4030
movl -0xf4(%rbp), %ecx
movq (%rax), %rax
addl 0xc(%rax), %ecx
movl %ecx, 0xc(%rax)
leaq -0x60(%rbp), %rdi
callq 0x4070
leaq -0x30(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rdi
callq 0x4090
movq %rax, -0x70(%rbp)
movq -0x68(%rbp), %rdi
callq 0x40c0
movq %rax, -0x78(%rbp)
leaq -0x70(%rbp), %rdi
leaq -0x78(%rbp), %rsi
callq 0x40f0
testb $0x1, %al
jne 0x59c4
jmp 0x5a2f
leaq -0x70(%rbp), %rdi
callq 0x4130
movq (%rax), %rax
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rcx
leaq 0x201(%rip), %rdx       # 0x5be0
xorl %eax, %eax
movl %eax, %esi
leaq -0x88(%rbp), %rdi
movq %rdi, -0x100(%rbp)
callq 0x2310
movq -0x100(%rbp), %rsi
leaq -0x60(%rbp), %rdi
callq 0x4230
jmp 0x5a08
jmp 0x5a0a
leaq -0x70(%rbp), %rdi
callq 0x42a0
jmp 0x59b1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x10(%rbp)
movl %eax, -0x14(%rbp)
leaq -0x60(%rbp), %rdi
callq 0x43a0
jmp 0x5b65
leaq -0x60(%rbp), %rax
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rdi
callq 0x42c0
movq %rax, -0x98(%rbp)
movq -0x90(%rbp), %rdi
callq 0x42f0
movq %rax, -0xa0(%rbp)
leaq -0x98(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x4320
testb $0x1, %al
jne 0x5a79
jmp 0x5ab1
leaq -0x98(%rbp), %rdi
callq 0x4360
movq (%rax), %rax
movq %rax, -0xa8(%rbp)
movq -0xa8(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x2170
jmp 0x5aa1
jmp 0x5aa3
leaq -0x98(%rbp), %rdi
callq 0x4380
jmp 0x5a60
leaq -0x30(%rbp), %rax
movq %rax, -0xb0(%rbp)
movq -0xb0(%rbp), %rdi
callq 0x4090
movq %rax, -0xb8(%rbp)
movq -0xb0(%rbp), %rdi
callq 0x40c0
movq %rax, -0xc0(%rbp)
leaq -0xb8(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
callq 0x40f0
testb $0x1, %al
jne 0x5afb
jmp 0x5b46
leaq -0xb8(%rbp), %rdi
callq 0x4130
movq (%rax), %rax
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rax
movq %rax, -0x108(%rbp)
cmpq $0x0, %rax
je 0x5b36
movq -0x108(%rbp), %rdi
movl $0x18, %esi
callq 0x21a0
jmp 0x5b38
leaq -0xb8(%rbp), %rdi
callq 0x42a0
jmp 0x5ae2
leaq -0x60(%rbp), %rdi
callq 0x43a0
leaq -0x30(%rbp), %rdi
callq 0x4400
movb $0x1, %al
andb $0x1, %al
addq $0x110, %rsp            # imm = 0x110
popq %rbp
retq
leaq -0x30(%rbp), %rdi
callq 0x4400
movq -0x10(%rbp), %rdi
callq 0x2300
nopw (%rax,%rax)