// File: /workspace/github_c_makefile_star2_O3/chatziko-k08[P]lecture-code/tests/../modules/UsingHashTable/ADTMap.c
// Function: map_insert
void map_insert(Map map, Pointer key, Pointer value) {
	// Σκανάρουμε το Hash Table μέχρι να βρούμε διαθέσιμη θέση για να τοποθετήσουμε το ζευγάρι,
	// ή μέχρι να βρούμε το κλειδί ώστε να το αντικαταστήσουμε.
	bool already_in_map = false;
	MapNode node = NULL;
	uint pos;
	for (pos = map->hash_function(key) % map->capacity;		// ξεκινώντας από τη θέση που κάνει hash το key
		map->array[pos].state != EMPTY;						// αν φτάσουμε σε EMPTY σταματάμε
		pos = (pos + 1) % map->capacity) {					// linear probing, γυρνώντας στην αρχή όταν φτάσουμε στη τέλος του πίνακα

		if (map->array[pos].state == DELETED) {
			// Βρήκαμε DELETED θέση. Θα μπορούσαμε να βάλουμε το ζευγάρι εδώ, αλλά _μόνο_ αν το key δεν υπάρχει ήδη.
			// Οπότε σημειώνουμε τη θέση, αλλά συνεχίζουμε την αναζήτηση, το key μπορεί να βρίσκεται πιο μετά.
			if (node == NULL)
				node = &map->array[pos];

		} else if (map->compare(map->array[pos].key, key) == 0) {
			already_in_map = true;
			node = &map->array[pos];						// βρήκαμε το key, το ζευγάρι θα μπει αναγκαστικά εδώ (ακόμα και αν είχαμε προηγουμένως βρει DELETED θέση)
			break;											// και δε χρειάζεται να συνεχίζουμε την αναζήτηση.
		}
	}
	if (node == NULL)										// αν βρήκαμε EMPTY (όχι DELETED, ούτε το key), το node δεν έχει πάρει ακόμα τιμή
		node = &map->array[pos];

	// Σε αυτό το σημείο, το node είναι ο κόμβος στον οποίο θα γίνει εισαγωγή.
	if (already_in_map) {
		// Αν αντικαθιστούμε παλιά key/value, τa κάνουμε destropy
		if (node->key != key && map->destroy_key != NULL)
			map->destroy_key(node->key);

		if (node->value != value && map->destroy_value != NULL)
			map->destroy_value(node->value);

	} else {
		// Νέο στοιχείο, αυξάνουμε τα συνολικά στοιχεία του map
		map->size++;

		if (node->state == DELETED)							// αν βρήκαμε DELETED, θα αλλάξει σε OCCUPIED
			map->deleted--;
	}

	// Προσθήκη τιμών στον κόμβο
	node->state = OCCUPIED;
	node->key = key;
	node->value = value;

	// Αν με την νέα εισαγωγή ξεπερνάμε το μέγιστο load factor, πρέπει να κάνουμε rehash.
	// Στο load factor μετράμε και τα DELETED, γιατί και αυτά επηρρεάζουν τις αναζητήσεις.
	float load_factor = (float)(map->size + map->deleted) / map->capacity;
	if (load_factor > MAX_LOAD_FACTOR)
		rehash(map);
}

// Assembly:
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
movq %rdx, %r14
movq %rsi, %r15
movq %rdi, %rbx
movq %rsi, %rdi
callq *0x20(%rbx)
movl 0x8(%rbx), %esi
xorl %edx, %edx
divl %esi
movl %edx, %r12d
movq (%rbx), %rcx
leaq (%r12,%r12,2), %rax
movl 0x10(%rcx,%rax,8), %edx
testl %edx, %edx
je 0x4fec
leaq (%rcx,%rax,8), %rax
xorl %r13d, %r13d
cmpl $0x2, %edx
jne 0x4fb9
testq %r13, %r13
cmoveq %rax, %r13
jmp 0x4fcc
movq (%rax), %rdi
movq %r15, %rsi
callq *0x18(%rbx)
testl %eax, %eax
je 0x4ff2
movl 0x8(%rbx), %esi
movq (%rbx), %rcx
incl %r12d
movl %r12d, %eax
xorl %edx, %edx
divl %esi
movl %edx, %r12d
leaq (%r12,%r12,2), %rax
leaq (%rcx,%rax,8), %rax
movl 0x10(%rax), %edx
testl %edx, %edx
jne 0x4fab
movb $0x1, %al
jmp 0x4fff
leaq (%rcx,%rax,8), %r13
jmp 0x5010
movq (%rbx), %rcx
leaq (%r12,%r12,2), %rax
leaq (%rcx,%rax,8), %r13
xorl %eax, %eax
testq %r13, %r13
jne 0x500c
leaq (%r12,%r12,2), %rdx
leaq (%rcx,%rdx,8), %r13
testb %al, %al
je 0x501f
incl 0xc(%rbx)
cmpl $0x2, 0x10(%r13)
jne 0x5047
decl 0x10(%rbx)
jmp 0x5047
movq (%r13), %rdi
cmpq %r15, %rdi
je 0x5033
movq 0x28(%rbx), %rax
testq %rax, %rax
je 0x5033
callq *%rax
movq 0x8(%r13), %rdi
cmpq %r14, %rdi
je 0x5047
movq 0x30(%rbx), %rax
testq %rax, %rax
je 0x5047
callq *%rax
movl $0x1, 0x10(%r13)
movq %r15, (%r13)
movq %r14, 0x8(%r13)
movl 0x10(%rbx), %eax
addl 0xc(%rbx), %eax
cvtsi2ss %eax, %xmm0
movl 0x8(%rbx), %r15d
cvtsi2ss %r15d, %xmm1
divss %xmm1, %xmm0
ucomiss 0x1f7b(%rip), %xmm0     # 0x6ff0
jbe 0x5212
movq (%rbx), %r14
xorl %eax, %eax
leaq 0x40e9(%rip), %rcx      # 0x9170
movl (%rax,%rcx), %r12d
cmpl %r15d, %r12d
jg 0x509e
addq $0x4, %rax
cmpq $0x68, %rax
jne 0x5087
leal (%r15,%r15), %r12d
movl %r12d, 0x8(%rbx)
movslq %r12d, %r13
leaq (,%r13,8), %rax
leaq (%rax,%rax,2), %rdi
callq 0x21a0
movq %rax, (%rbx)
testl %r13d, %r13d
jle 0x51c8
movl %r12d, %ecx
addl $0x3, %r12d
decq %rcx
movq %rcx, %xmm0
pshufd $0x44, %xmm0, %xmm0     # xmm0 = xmm0[0,1,0,1]
shrl $0x2, %r12d
shlq $0x5, %r12
leaq (%r12,%r12,2), %rcx
movdqa 0x1eb6(%rip), %xmm1     # 0x6fa0
movdqa 0x1ebe(%rip), %xmm2     # 0x6fb0
xorl %edx, %edx
movdqa 0x1ec4(%rip), %xmm3     # 0x6fc0
pxor %xmm3, %xmm0
pcmpeqd %xmm4, %xmm4
movdqa 0x1ec4(%rip), %xmm5     # 0x6fd0
movdqa %xmm2, %xmm6
pxor %xmm3, %xmm6
movdqa %xmm6, %xmm7
pcmpgtd %xmm0, %xmm7
pcmpeqd %xmm0, %xmm6
pshufd $0xf5, %xmm6, %xmm8     # xmm8 = xmm6[1,1,3,3]
pand %xmm7, %xmm8
pshufd $0xf5, %xmm7, %xmm6     # xmm6 = xmm7[1,1,3,3]
por %xmm8, %xmm6
movd %xmm6, %esi
notl %esi
testb $0x1, %sil
je 0x5149
movl $0x0, 0x10(%rax,%rdx)
pxor %xmm4, %xmm6
pextrw $0x4, %xmm6, %esi
testb $0x1, %sil
je 0x5160
movl $0x0, 0x28(%rax,%rdx)
movdqa %xmm1, %xmm6
pxor %xmm3, %xmm6
movdqa %xmm6, %xmm7
pcmpgtd %xmm0, %xmm7
pcmpeqd %xmm0, %xmm6
pshufd $0xf5, %xmm6, %xmm8     # xmm8 = xmm6[1,1,3,3]
pand %xmm7, %xmm8
pshufd $0xf5, %xmm7, %xmm6     # xmm6 = xmm7[1,1,3,3]
por %xmm8, %xmm6
pxor %xmm4, %xmm6
pextrw $0x0, %xmm6, %esi
testb $0x1, %sil
je 0x51a0
movl $0x0, 0x40(%rax,%rdx)
pextrw $0x4, %xmm6, %esi
testb $0x1, %sil
je 0x51b3
movl $0x0, 0x58(%rax,%rdx)
paddq %xmm5, %xmm2
paddq %xmm5, %xmm1
addq $0x60, %rdx
cmpq %rdx, %rcx
jne 0x510c
movl $0x0, 0xc(%rbx)
testl %r15d, %r15d
jle 0x5201
shlq $0x3, %r15
leaq (%r15,%r15,2), %r15
xorl %r12d, %r12d
cmpl $0x1, 0x10(%r14,%r12)
jne 0x51f8
movq (%r14,%r12), %rsi
movq 0x8(%r14,%r12), %rdx
movq %rbx, %rdi
callq 0x4f73
addq $0x18, %r12
cmpq %r12, %r15
jne 0x51df
movq %r14, %rdi
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
jmp 0x22a0
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
retq