// File: SeanChao[P]KV-Store/./skiplist.h
// Function: SkipList<unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>::put(unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>)
bool SkipList<Key, Value>::put(Key key, Value value) {
    std::shared_ptr<Node> newNode(new Node(key, value));
    std::shared_ptr<Node> ptr = skipSearch(key);  // nearest element's top level
    // if the key exists, then update its value
    if (ptr->key == key && valid(ptr)) {
        while (ptr) {
            ptr->val = value;
            ptr = ptr->below;
        }
        return true;
    }

    while (ptr->below) ptr = ptr->below;
    newNode->pred = ptr;
    newNode->succ = ptr->succ;
    ptr->succ->pred = newNode;
    ptr->succ = newNode;

    // randomly grow higher
    while (rand() & 1) {
        // find the nearest node with higher level
        while (ptr->pred && !ptr->above) ptr = ptr->pred;
        // generate the head for new higher level
        if (!ptr->above) {
            std::shared_ptr<Node> newHead(new Node());  // new head
            std::shared_ptr<Node> newTail(new Node());  // new trailing node
            newHead->below = head;
            newHead->succ = newTail;
            head->above = newHead;
            newTail->pred = newHead;
            newTail->below = tail;
            tail->above = newTail;
            head = newHead;
            tail = newTail;
        }
        ptr = ptr->above;
        // build the new level
        std::shared_ptr<Node> growNode(new Node(key, value));
        growNode->pred = ptr;
        growNode->succ = ptr->succ;
        growNode->below = newNode;
        ptr->succ->pred = growNode;
        ptr->succ = growNode;
        newNode->above = growNode;
        newNode = growNode;
    }
    return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x160, %rsp            # imm = 0x160
movq %rdx, -0xf8(%rbp)
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x100(%rbp)
movl $0x68, %edi
callq 0x4300
movq -0xf8(%rbp), %rsi
movq %rax, -0xf0(%rbp)
movb $0x1, -0x5d(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0xe8(%rbp)
leaq -0x50(%rbp), %rdi
callq 0x4170
jmp 0xb8ab
movq -0xe8(%rbp), %rsi
movq -0xf0(%rbp), %rdi
leaq -0x50(%rbp), %rdx
callq 0x100f0
jmp 0xb8c4
movq -0xf0(%rbp), %rsi
movb $0x0, -0x5d(%rbp)
leaq -0x30(%rbp), %rdi
callq 0xf1f0
jmp 0xb8da
leaq -0x50(%rbp), %rdi
callq 0x45d8
movq -0x100(%rbp), %rsi
movq -0x18(%rbp), %rdx
leaq -0x70(%rbp), %rdi
callq 0x10160
jmp 0xb8f9
leaq -0x70(%rbp), %rdi
callq 0xc7b0
movq (%rax), %rcx
movq -0x18(%rbp), %rdx
movb $0x0, -0x81(%rbp)
xorl %eax, %eax
cmpq %rdx, %rcx
movb %al, -0x101(%rbp)
jne 0xb961
leaq -0x80(%rbp), %rdi
movq %rdi, -0x110(%rbp)
leaq -0x70(%rbp), %rsi
callq 0xc8a0
movq -0x100(%rbp), %rdi
movq -0x110(%rbp), %rsi
movb $0x1, -0x81(%rbp)
callq 0xc820
movb %al, -0x102(%rbp)
jmp 0xb953
movb -0x102(%rbp), %al
movb %al, -0x101(%rbp)
jmp 0xb961
movb -0x101(%rbp), %al
movb %al, -0x111(%rbp)
testb $0x1, -0x81(%rbp)
jne 0xb978
jmp 0xb981
leaq -0x80(%rbp), %rdi
callq 0xc8d0
movb -0x111(%rbp), %al
testb $0x1, %al
jne 0xb990
jmp 0xba78
jmp 0xb992
leaq -0x70(%rbp), %rdi
callq 0xc800
testb $0x1, %al
jne 0xb9a4
jmp 0xba65
leaq -0x70(%rbp), %rdi
callq 0xc7b0
movq -0xf8(%rbp), %rsi
movq %rax, %rdi
addq $0x8, %rdi
callq 0x4040
jmp 0xb9c2
leaq -0x70(%rbp), %rdi
callq 0xc7b0
movq %rax, %rsi
addq $0x58, %rsi
leaq -0x70(%rbp), %rdi
callq 0xc7d0
jmp 0xb992
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0xba00
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x50(%rbp), %rdi
callq 0x45d8
testb $0x1, -0x5d(%rbp)
jne 0xba08
jmp 0xba19
movq -0xf0(%rbp), %rdi
movl $0x68, %esi
callq 0x4310
jmp 0xbfc0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0xbfb7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
testb $0x1, -0x81(%rbp)
jne 0xba46
jmp 0xba4f
leaq -0x80(%rbp), %rdi
callq 0xc8d0
jmp 0xbfae
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0xbfae
movb $0x1, -0x1(%rbp)
movl $0x1, -0x88(%rbp)
jmp 0xbf8e
jmp 0xba7a
leaq -0x70(%rbp), %rdi
callq 0xc7b0
movq %rax, %rdi
addq $0x58, %rdi
callq 0xc800
testb $0x1, %al
jne 0xba95
jmp 0xbab0
leaq -0x70(%rbp), %rdi
callq 0xc7b0
movq %rax, %rsi
addq $0x58, %rsi
leaq -0x70(%rbp), %rdi
callq 0xc7d0
jmp 0xba7a
leaq -0x30(%rbp), %rdi
callq 0xc7b0
movq %rax, %rdi
addq $0x28, %rdi
leaq -0x70(%rbp), %rsi
callq 0xc7d0
leaq -0x70(%rbp), %rdi
callq 0xc7b0
addq $0x38, %rax
movq %rax, -0x120(%rbp)
leaq -0x30(%rbp), %rdi
callq 0xc7b0
movq -0x120(%rbp), %rsi
movq %rax, %rdi
addq $0x38, %rdi
callq 0xc7d0
leaq -0x70(%rbp), %rdi
callq 0xc7b0
movq %rax, %rdi
addq $0x38, %rdi
callq 0xc7b0
movq %rax, %rdi
addq $0x28, %rdi
leaq -0x30(%rbp), %rsi
callq 0xc7d0
leaq -0x70(%rbp), %rdi
callq 0xc7b0
movq %rax, %rdi
addq $0x38, %rdi
leaq -0x30(%rbp), %rsi
callq 0xc7d0
callq 0x40f0
andl $0x1, %eax
cmpl $0x0, %eax
je 0xbf80
jmp 0xbb4a
leaq -0x70(%rbp), %rdi
callq 0xc7b0
movq %rax, %rdi
addq $0x28, %rdi
callq 0xc800
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0x121(%rbp)
jne 0xbb70
jmp 0xbb8d
leaq -0x70(%rbp), %rdi
callq 0xc7b0
movq %rax, %rdi
addq $0x48, %rdi
callq 0xc800
xorb $-0x1, %al
movb %al, -0x121(%rbp)
movb -0x121(%rbp), %al
testb $0x1, %al
jne 0xbb99
jmp 0xbbb4
leaq -0x70(%rbp), %rdi
callq 0xc7b0
movq %rax, %rsi
addq $0x28, %rsi
leaq -0x70(%rbp), %rdi
callq 0xc7d0
jmp 0xbb4a
leaq -0x70(%rbp), %rdi
callq 0xc7b0
movq %rax, %rdi
addq $0x48, %rdi
callq 0xc800
testb $0x1, %al
jne 0xbdaf
movl $0x68, %edi
callq 0x4300
movq %rax, -0x130(%rbp)
jmp 0xbbe4
movq -0x130(%rbp), %rdi
callq 0xf180
jmp 0xbbf2
movq -0x130(%rbp), %rsi
leaq -0x98(%rbp), %rdi
callq 0xf1f0
jmp 0xbc07
movl $0x68, %edi
callq 0x4300
movq %rax, -0x138(%rbp)
jmp 0xbc1a
movq -0x138(%rbp), %rdi
callq 0xf180
jmp 0xbc28
movq -0x138(%rbp), %rsi
leaq -0xa8(%rbp), %rdi
callq 0xf1f0
jmp 0xbc3d
leaq -0x98(%rbp), %rdi
callq 0xc7b0
movq -0x100(%rbp), %rsi
movq %rax, %rdi
addq $0x58, %rdi
callq 0xc7d0
leaq -0x98(%rbp), %rdi
callq 0xc7b0
movq %rax, %rdi
addq $0x38, %rdi
leaq -0xa8(%rbp), %rsi
callq 0xc7d0
movq -0x100(%rbp), %rdi
callq 0xc7b0
movq %rax, %rdi
addq $0x48, %rdi
leaq -0x98(%rbp), %rsi
callq 0xc7d0
leaq -0xa8(%rbp), %rdi
callq 0xc7b0
movq %rax, %rdi
addq $0x28, %rdi
leaq -0x98(%rbp), %rsi
callq 0xc7d0
movq -0x100(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x140(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0xc7b0
movq -0x140(%rbp), %rsi
movq %rax, %rdi
addq $0x58, %rdi
callq 0xc7d0
movq -0x100(%rbp), %rdi
addq $0x10, %rdi
callq 0xc7b0
movq %rax, %rdi
addq $0x48, %rdi
leaq -0xa8(%rbp), %rsi
callq 0xc7d0
movq -0x100(%rbp), %rdi
leaq -0x98(%rbp), %rsi
callq 0xc7d0
movq -0x100(%rbp), %rdi
addq $0x10, %rdi
leaq -0xa8(%rbp), %rsi
callq 0xc7d0
leaq -0xa8(%rbp), %rdi
callq 0xc8d0
leaq -0x98(%rbp), %rdi
callq 0xc8d0
jmp 0xbdaf
movq -0x130(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
movl $0x68, %esi
callq 0x4310
jmp 0xbfae
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0xbd9e
movq -0x138(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
movl $0x68, %esi
callq 0x4310
leaq -0x98(%rbp), %rdi
callq 0xc8d0
jmp 0xbfae
leaq -0x70(%rbp), %rdi
movq %rdi, -0x150(%rbp)
callq 0xc7b0
movq -0x150(%rbp), %rdi
movq %rax, %rsi
addq $0x48, %rsi
callq 0xc7d0
movl $0x68, %edi
callq 0x4300
movq %rax, -0x148(%rbp)
jmp 0xbde5
movq -0xf8(%rbp), %rsi
movb $0x1, -0xd9(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x158(%rbp)
leaq -0xd8(%rbp), %rdi
callq 0x4170
jmp 0xbe0c
movq -0x158(%rbp), %rsi
movq -0x148(%rbp), %rdi
leaq -0xd8(%rbp), %rdx
callq 0x100f0
jmp 0xbe28
movq -0x148(%rbp), %rsi
movb $0x0, -0xd9(%rbp)
leaq -0xb8(%rbp), %rdi
callq 0xf1f0
jmp 0xbe44
leaq -0xd8(%rbp), %rdi
callq 0x45d8
leaq -0xb8(%rbp), %rdi
callq 0xc7b0
movq %rax, %rdi
addq $0x28, %rdi
leaq -0x70(%rbp), %rsi
callq 0xc7d0
leaq -0x70(%rbp), %rdi
callq 0xc7b0
addq $0x38, %rax
movq %rax, -0x160(%rbp)
leaq -0xb8(%rbp), %rdi
callq 0xc7b0
movq -0x160(%rbp), %rsi
movq %rax, %rdi
addq $0x38, %rdi
callq 0xc7d0
leaq -0xb8(%rbp), %rdi
callq 0xc7b0
movq %rax, %rdi
addq $0x58, %rdi
leaq -0x30(%rbp), %rsi
callq 0xc7d0
leaq -0x70(%rbp), %rdi
callq 0xc7b0
movq %rax, %rdi
addq $0x38, %rdi
callq 0xc7b0
movq %rax, %rdi
addq $0x28, %rdi
leaq -0xb8(%rbp), %rsi
callq 0xc7d0
leaq -0x70(%rbp), %rdi
callq 0xc7b0
movq %rax, %rdi
addq $0x38, %rdi
leaq -0xb8(%rbp), %rsi
callq 0xc7d0
leaq -0x30(%rbp), %rdi
callq 0xc7b0
movq %rax, %rdi
addq $0x48, %rdi
leaq -0xb8(%rbp), %rsi
callq 0xc7d0
leaq -0x30(%rbp), %rdi
leaq -0xb8(%rbp), %rsi
callq 0xc7d0
leaq -0xb8(%rbp), %rdi
callq 0xc8d0
jmp 0xbb37
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
jmp 0xbf62
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0xd8(%rbp), %rdi
callq 0x45d8
testb $0x1, -0xd9(%rbp)
jne 0xbf6d
jmp 0xbf7e
movq -0x148(%rbp), %rdi
movl $0x68, %esi
callq 0x4310
jmp 0xbfae
movb $0x1, -0x1(%rbp)
movl $0x1, -0x88(%rbp)
leaq -0x70(%rbp), %rdi
callq 0xc8d0
leaq -0x30(%rbp), %rdi
callq 0xc8d0
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x160, %rsp            # imm = 0x160
popq %rbp
retq
leaq -0x70(%rbp), %rdi
callq 0xc8d0
leaq -0x30(%rbp), %rdi
callq 0xc8d0
movq -0x58(%rbp), %rdi
callq 0x4530
nopl (%rax)