// File: nmmmnu[P]HM3/hm3/skiplist.cc
// Function: hm3::SkipList::locate_(StringRef const&, bool) const
auto SkipList::locate_(const StringRef &key, bool const complete_evaluation) const -> NodeLocator{
	// it is extremly dangerous to have key == nullptr here.
	if (key.empty()){
		std::logic_error exception("Key can not be nullptr in SkipList::_locate");
		throw exception;
	}

	NodeArrayC loc;

	// smart over-optimizations, such skip NULL lanes or
	// start from the middle of the list did not pay off.

	int cmp = 1;

	const Node *node = nullptr;
	const Node *prev = nullptr;

	height_type height = height_;
	while(height){
		node = prev ? prev : heads_[height - 1];

		while(node){
			const Pair & data = node->data;
			cmp = data.cmp(key);

			if (cmp >= 0)
				break;

			prev = node;
			node = node->next[height - 1];
		}


		if (complete_evaluation == false && cmp == 0)
			return { node, loc };

		loc[height - 1] = prev;

		--height;
	}

	return { cmp ? nullptr : node , loc };
}

// Assembly:
subq $0x2a8, %rsp            # imm = 0x2A8
movq %rdi, 0x30(%rsp)
movb %cl, %al
movq %rdi, 0x38(%rsp)
movq %rsi, 0x2a0(%rsp)
movq %rdx, 0x298(%rsp)
andb $0x1, %al
movb %al, 0x297(%rsp)
movq 0x2a0(%rsp), %rax
movq %rax, 0x40(%rsp)
movq 0x298(%rsp), %rdi
callq 0xa220
testb $0x1, %al
jne 0x1304c
jmp 0x130c4
leaq 0x422b(%rip), %rsi      # 0x1727e
leaq 0x280(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x21c0
movl $0x10, %edi
callq 0x20a0
movq 0x20(%rsp), %rsi
movq %rax, %rdi
movq %rdi, 0x28(%rsp)
callq 0x2110
movq 0x28(%rsp), %rdi
movq 0xbf5b(%rip), %rsi      # 0x1efe8
movq 0xbf44(%rip), %rdx      # 0x1efd8
callq 0x2210
jmp 0x1324e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x278(%rsp)
movl %eax, 0x274(%rsp)
leaq 0x280(%rsp), %rdi
callq 0x2248
jmp 0x13241
movq 0x40(%rsp), %rax
movl $0x1, 0x6c(%rsp)
movq $0x0, 0x60(%rsp)
movq $0x0, 0x58(%rsp)
movb (%rax), %al
movb %al, 0x57(%rsp)
cmpb $0x0, 0x57(%rsp)
je 0x131fa
cmpq $0x0, 0x58(%rsp)
je 0x13108
movq 0x58(%rsp), %rax
movq %rax, 0x18(%rsp)
jmp 0x13129
movq 0x40(%rsp), %rdi
addq $0x8, %rdi
movzbl 0x57(%rsp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0xb9e0
movq (%rax), %rax
movq %rax, 0x18(%rsp)
movq 0x18(%rsp), %rax
movq %rax, 0x60(%rsp)
cmpq $0x0, 0x60(%rsp)
je 0x1318a
movq 0x60(%rsp), %rax
movq %rax, 0x48(%rsp)
movq 0x48(%rsp), %rdi
movq 0x298(%rsp), %rsi
callq 0xebb0
movl %eax, 0x6c(%rsp)
cmpl $0x0, 0x6c(%rsp)
jl 0x13164
jmp 0x1318a
movq 0x60(%rsp), %rax
movq %rax, 0x58(%rsp)
movq 0x60(%rsp), %rax
movzbl 0x57(%rsp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movq 0x8(%rax,%rcx,8), %rax
movq %rax, 0x60(%rsp)
jmp 0x13133
movb 0x297(%rsp), %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
jne 0x131c4
cmpl $0x0, 0x6c(%rsp)
jne 0x131c4
movq 0x30(%rsp), %rdi
movq 0x60(%rsp), %rax
movq %rax, (%rdi)
addq $0x8, %rdi
leaq 0x70(%rsp), %rsi
movl $0x200, %edx            # imm = 0x200
callq 0x2140
jmp 0x13234
movq 0x58(%rsp), %rax
movq %rax, 0x10(%rsp)
movzbl 0x57(%rsp), %eax
subl $0x1, %eax
movslq %eax, %rsi
leaq 0x70(%rsp), %rdi
callq 0x140a0
movq 0x10(%rsp), %rcx
movq %rcx, (%rax)
movb 0x57(%rsp), %al
addb $-0x1, %al
movb %al, 0x57(%rsp)
jmp 0x130e9
cmpl $0x0, 0x6c(%rsp)
je 0x1320a
xorl %eax, %eax
movq %rax, 0x8(%rsp)
jmp 0x13214
movq 0x60(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0x30(%rsp), %rdi
movq 0x8(%rsp), %rax
movq %rax, (%rdi)
addq $0x8, %rdi
leaq 0x70(%rsp), %rsi
movl $0x200, %edx            # imm = 0x200
callq 0x2140
movq 0x38(%rsp), %rax
addq $0x2a8, %rsp            # imm = 0x2A8
retq
movq 0x278(%rsp), %rdi
callq 0x2220
nop