// File: /workspace/github_cpp_makefile_star2_O3/deepaktabraham[P]BPlus-Tree/src/tree.cpp
// Function: BPlusTree::Insert(float, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>)
void BPlusTree :: Insert(float key, string value)
{
	// check if tree is empty
	if(NULL == root)
	{
		// Irrespective of the order, root is always a leaf node for 
		// the first insertion. So, create a new leaf node.
		root = new LeafNode;
		root->Insert(key, value);
	}

	// if it is a subsequent insertion
	else
	{
		Node* leftNode = NULL;
		Node* rightNode = NULL;
		float* keyToParent = new float;
		bool rootPopped = false;
		
		// obtain the search path from the root to leaf node and push it on to a stack
		stack<Node*>* path = new stack<Node*>;
		Search_Path(root, key, path);

		// insert the key-value pair in the leaf node
		path->top()->Insert(key, value);

		// Split the current node and insert the middle key & children in to the parent. Perform
		// this as long as there is an imbalance in the tree, moving up the stack every iteration.
		while(path->top()->Get_Keys().size() == order)
		{
			// Update the current node as the left half and return the right half. Also 
			// obtain the middle element, which is the key to be moved up to the parent.
			leftNode = path->top();
			rightNode = leftNode->Split(keyToParent);

			// check if currently split node is not the root node
			path->pop();
			if(!path->empty())
			{
				// Insert the middle key and the right half in to 
				// the parent. The parent will be an internal node.
				path->top()->Insert(*keyToParent, rightNode);
			}

			// if currently split node is the root node
			else
			{
				// set flag indicating that the root has popped from the stack
				rootPopped = true;
				break;
			}
		}

		// new internal node needs to be created and assigned as the root
		if(rootPopped)
		{
			// create a new internal node
			InternalNode* tempRoot = new InternalNode;

			// insert the left and the right halves as the children of this new internal node
			tempRoot->Insert(*keyToParent, leftNode, rightNode);

			// mark this new internal node as the root of the tree
			root = tempRoot;
		}

		delete(keyToParent);
		delete(path);
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %rsi, %r12
movss %xmm0, -0x2c(%rbp)
movq %rdi, -0x38(%rbp)
cmpq $0x0, 0x8(%rdi)
je 0x3095
movl $0x4, %edi
callq 0x2170
movq %rax, %r15
movl $0x50, %edi
callq 0x2170
movq %rax, %r14
xorps %xmm0, %xmm0
movups %xmm0, (%rax)
movups %xmm0, 0x10(%rax)
movups %xmm0, 0x20(%rax)
movups %xmm0, 0x30(%rax)
movups %xmm0, 0x40(%rax)
movq %rax, %rdi
xorl %esi, %esi
callq 0x3cce
movq -0x38(%rbp), %rdi
movq 0x8(%rdi), %rsi
movss -0x2c(%rbp), %xmm0
movq %r14, %rdx
callq 0x2d04
movq 0x30(%r14), %rax
cmpq 0x38(%r14), %rax
jne 0x2f8e
movq 0x48(%r14), %rcx
movl $0x200, %eax            # imm = 0x200
addq -0x8(%rcx), %rax
movq -0x8(%rax), %r13
leaq -0x60(%rbp), %rbx
movq %rbx, -0x10(%rbx)
movq (%r12), %rsi
movq 0x8(%r12), %rdx
addq %rsi, %rdx
leaq -0x70(%rbp), %r12
movq %r12, %rdi
callq 0x2c66
movq (%r13), %rax
movq %r13, %rdi
movss -0x2c(%rbp), %xmm0
movq %r12, %rsi
callq *(%rax)
movq -0x70(%rbp), %rdi
cmpq %rbx, %rdi
je 0x2fd1
callq 0x2150
movq 0x30(%r14), %rax
cmpq 0x38(%r14), %rax
jne 0x2feb
movq 0x48(%r14), %rax
movq -0x8(%rax), %rax
movl $0x200, %ecx            # imm = 0x200
addq %rcx, %rax
movq -0x8(%rax), %rsi
leaq -0x50(%rbp), %rdi
callq 0x3ede
movq -0x50(%rbp), %r12
movq -0x48(%rbp), %r13
movq -0x38(%rbp), %rax
movslq (%rax), %rbx
testq %r12, %r12
je 0x3014
movq %r12, %rdi
callq 0x2150
subq %r12, %r13
sarq $0x2, %r13
cmpq %rbx, %r13
jne 0x3124
movq 0x30(%r14), %rax
cmpq 0x38(%r14), %rax
jne 0x303e
movq 0x48(%r14), %rax
movq -0x8(%rax), %rax
movl $0x200, %ecx            # imm = 0x200
addq %rcx, %rax
movq -0x8(%rax), %r12
movq (%r12), %rax
movq %r12, %rdi
movq %r15, %rsi
callq *0x28(%rax)
movq %rax, %r13
movq %r14, %rdi
callq 0x3e2a
movq 0x30(%r14), %rax
cmpq 0x10(%r14), %rax
je 0x30f3
cmpq 0x38(%r14), %rax
jne 0x307e
movq 0x48(%r14), %rax
movq -0x8(%rax), %rax
movl $0x200, %ecx            # imm = 0x200
addq %rcx, %rax
movq -0x8(%rax), %rdi
movss (%r15), %xmm0
movq (%rdi), %rax
movq %r13, %rsi
callq *0x8(%rax)
jmp 0x2fd1
movl $0x50, %edi
callq 0x2170
movq %rax, %r14
movq %rax, %rdi
callq 0x4838
movq -0x38(%rbp), %rax
movq %r14, 0x8(%rax)
leaq -0x80(%rbp), %r15
movq %r15, -0x10(%r15)
movq (%r12), %rsi
movq 0x8(%r12), %rdx
addq %rsi, %rdx
leaq -0x90(%rbp), %rbx
movq %rbx, %rdi
callq 0x2c66
movq (%r14), %rax
movq %r14, %rdi
movss -0x2c(%rbp), %xmm0
movq %rbx, %rsi
callq *(%rax)
movq -0x90(%rbp), %rdi
cmpq %r15, %rdi
jne 0x3137
jmp 0x313c
movl $0x40, %edi
callq 0x2170
movq %rax, %rbx
movq %rax, %rdi
callq 0x3f98
movss (%r15), %xmm0
movq (%rbx), %rax
movq %rbx, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq *0x10(%rax)
movq -0x38(%rbp), %rax
movq %rbx, 0x8(%rax)
movq %r15, %rdi
callq 0x2150
movq %r14, %rdi
callq 0x3a4c
movq %r14, %rdi
callq 0x2150
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rbx, %rdi
movq %rax, %rbx
jmp 0x317d
movq %rax, %rbx
movq -0x90(%rbp), %rdi
cmpq %r15, %rdi
jne 0x317d
jmp 0x3182
jmp 0x3177
movq %rbx, %rcx
movq %rax, %rbx
movq -0x70(%rbp), %rdi
cmpq %rcx, %rdi
jne 0x317d
jmp 0x3182
movq %rax, %rbx
movq %r14, %rdi
callq 0x2150
movq %rbx, %rdi
callq 0x22a0