// File: /workspace/github_c_makefile_star2_O2/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 %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdx, 0x10(%rsp)
movq %rdi, %rbx
movq %rsi, 0x8(%rsp)
movq %rsi, %rdi
callq *0x20(%rbx)
movl 0x8(%rbx), %ecx
xorl %r13d, %r13d
xorl %edx, %edx
divl %ecx
movq (%rbx), %rbp
movl %edx, %r12d
imulq $0x18, %r12, %r15
movl 0x10(%rbp,%r15), %r14d
testl %r14d, %r14d
je 0x4c2c
addq %r15, %rbp
cmpl $0x2, %r14d
jne 0x4c0a
testq %r13, %r13
cmoveq %rbp, %r13
jmp 0x4c1d
movq (%rbp), %rdi
movq 0x8(%rsp), %rsi
callq *0x18(%rbx)
testl %eax, %eax
je 0x4c25
movl 0x8(%rbx), %ecx
incl %r12d
movl %r12d, %eax
jmp 0x4be0
movq (%rbx), %rbp
leaq (%r15,%rbp), %r13
addq %r15, %rbp
testq %r13, %r13
cmovneq %r13, %rbp
testl %r14d, %r14d
je 0x4c6c
movq (%rbp), %rdi
cmpq 0x8(%rsp), %rdi
movq 0x10(%rsp), %r14
je 0x4c56
movq 0x28(%rbx), %rax
testq %rax, %rax
je 0x4c56
callq *%rax
movq 0x8(%rbp), %rdi
cmpq %r14, %rdi
je 0x4c7d
movq 0x30(%rbx), %rax
testq %rax, %rax
je 0x4c7d
callq *%rax
jmp 0x4c7d
incl 0xc(%rbx)
cmpl $0x2, 0x10(%rbp)
movq 0x10(%rsp), %r14
jne 0x4c7d
decl 0x10(%rbx)
movl $0x1, 0x10(%rbp)
movq 0x8(%rsp), %rax
movq %rax, (%rbp)
movq %r14, 0x8(%rbp)
movl 0x10(%rbx), %eax
addl 0xc(%rbx), %eax
cvtsi2ss %eax, %xmm0
movl 0x8(%rbx), %r15d
cvtsi2ss %r15d, %xmm1
divss %xmm1, %xmm0
ucomiss 0x12ed(%rip), %xmm0     # 0x5f9c
jbe 0x4cd1
movq (%rbx), %r14
xorl %eax, %eax
leaq 0x34b3(%rip), %rcx      # 0x8170
cmpq $0x68, %rax
je 0x4ce0
movl (%rax,%rcx), %edx
addq $0x4, %rax
cmpl %r15d, %edx
jle 0x4cbd
jmp 0x4ce4
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leal (%r15,%r15), %edx
movl %edx, 0x8(%rbx)
movslq %edx, %r12
imulq $0x18, %r12, %rdi
callq 0x2190
movq %rax, (%rbx)
xorl %ecx, %ecx
testl %r12d, %r12d
cmovlel %ecx, %r12d
imulq $0x18, %r12, %rdx
cmpq %rcx, %rdx
je 0x4d13
andl $0x0, 0x10(%rax,%rcx)
addq $0x18, %rcx
jmp 0x4d03
andl $0x0, 0xc(%rbx)
xorl %r12d, %r12d
testl %r15d, %r15d
cmovlel %r12d, %r15d
imulq $0x18, %r15, %r15
cmpq %r12, %r15
je 0x4d49
cmpl $0x1, 0x10(%r14,%r12)
jne 0x4d43
movq (%r14,%r12), %rsi
movq 0x8(%r14,%r12), %rdx
movq %rbx, %rdi
callq 0x4bb9
addq $0x18, %r12
jmp 0x4d25
movq %r14, %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x2290