// File: /workspace/github_c_makefile_star2_O1/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
pushq %rax
movq %rdx, %r14
movq %rsi, %r15
movq %rdi, %rbx
movq %rsi, %rdi
callq *0x20(%rbx)
xorl %r13d, %r13d
xorl %edx, %edx
divl 0x8(%rbx)
movl %edx, %r12d
movq (%rbx), %rax
leaq (%r12,%r12,2), %rdx
movl 0x10(%rax,%rdx,8), %ecx
testl %ecx, %ecx
sete %bpl
je 0x5018
leaq (%rax,%rdx,8), %rax
xorl %r13d, %r13d
cmpl $0x2, %ecx
jne 0x4fda
testq %r13, %r13
cmoveq %rax, %r13
jmp 0x4fe7
movq (%rax), %rdi
movq %r15, %rsi
callq *0x18(%rbx)
testl %eax, %eax
je 0x500d
incl %r12d
movl %r12d, %eax
xorl %edx, %edx
divl 0x8(%rbx)
movq (%rbx), %rax
movl %edx, %r12d
leaq (%r12,%r12,2), %rcx
leaq (%rax,%rcx,8), %rax
movl 0x10(%rax), %ecx
testl %ecx, %ecx
sete %bpl
jne 0x4fcc
jmp 0x5018
leaq (%r12,%r12,2), %r13
shlq $0x3, %r13
addq (%rbx), %r13
testq %r13, %r13
jne 0x5028
leaq (%r12,%r12,2), %r13
shlq $0x3, %r13
addq (%rbx), %r13
testb $0x1, %bpl
je 0x503d
incl 0xc(%rbx)
cmpl $0x2, 0x10(%r13)
jne 0x5065
decl 0x10(%rbx)
jmp 0x5065
movq (%r13), %rdi
cmpq %r15, %rdi
je 0x5051
movq 0x28(%rbx), %rax
testq %rax, %rax
je 0x5051
callq *%rax
movq 0x8(%r13), %rdi
cmpq %r14, %rdi
je 0x5065
movq 0x30(%rbx), %rax
testq %rax, %rax
je 0x5065
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), %r12d
cvtsi2ss %r12d, %xmm1
divss %xmm1, %xmm0
ucomiss 0x1f09(%rip), %xmm0     # 0x6f9c
jbe 0x50b5
movq (%rbx), %r14
xorl %eax, %eax
leaq 0x40cf(%rip), %rcx      # 0x9170
movl (%rax,%rcx), %edx
cmpl %r12d, %edx
jg 0x50c4
addq $0x4, %rax
cmpq $0x68, %rax
jne 0x50a1
jmp 0x50c7
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl %edx, 0x8(%rbx)
movl 0x8(%rbx), %eax
cmpl %r12d, %eax
jne 0x50d4
addl %eax, %eax
movl %eax, 0x8(%rbx)
movslq 0x8(%rbx), %r13
leaq (,%r13,8), %rax
leaq (%rax,%rax,2), %r15
movq %r15, %rdi
callq 0x21a0
movq %rax, (%rbx)
testq %r13, %r13
jle 0x5107
xorl %ecx, %ecx
movl $0x0, 0x10(%rax,%rcx)
addq $0x18, %rcx
cmpq %rcx, %r15
jne 0x50f6
movl $0x0, 0xc(%rbx)
testl %r12d, %r12d
jle 0x5140
shlq $0x3, %r12
leaq (%r12,%r12,2), %r15
xorl %r12d, %r12d
cmpl $0x1, 0x10(%r14,%r12)
jne 0x5137
movq (%r14,%r12), %rsi
movq 0x8(%r14,%r12), %rdx
movq %rbx, %rdi
callq 0x4f8d
addq $0x18, %r12
cmpq %r12, %r15
jne 0x511e
movq %r14, %rdi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x22a0