// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movb $0x0, -0x19(%rbp)
movq $0x0, -0x28(%rbp)
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rax
movq -0x10(%rbp), %rdi
callq *%rax
movq -0x8(%rbp), %rcx
xorl %edx, %edx
divl 0x8(%rcx)
movl %edx, -0x2c(%rbp)
movq -0x8(%rbp), %rax
movq (%rax), %rax
movl -0x2c(%rbp), %ecx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
cmpl $0x0, 0x10(%rax)
je 0x5fe7
movq -0x8(%rbp), %rax
movq (%rax), %rax
movl -0x2c(%rbp), %ecx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
cmpl $0x2, 0x10(%rax)
jne 0x5f8a
cmpq $0x0, -0x28(%rbp)
jne 0x5f88
movq -0x8(%rbp), %rax
movq (%rax), %rax
movl -0x2c(%rbp), %ecx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
jmp 0x5fce
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rax
movq -0x8(%rbp), %rcx
movq (%rcx), %rcx
movl -0x2c(%rbp), %edx
imulq $0x18, %rdx, %rdx
addq %rdx, %rcx
movq (%rcx), %rdi
movq -0x10(%rbp), %rsi
callq *%rax
cmpl $0x0, %eax
jne 0x5fcc
movb $0x1, -0x19(%rbp)
movq -0x8(%rbp), %rax
movq (%rax), %rax
movl -0x2c(%rbp), %ecx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
jmp 0x5fe7
jmp 0x5fce
jmp 0x5fd0
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movq -0x8(%rbp), %rcx
xorl %edx, %edx
divl 0x8(%rcx)
movl %edx, -0x2c(%rbp)
jmp 0x5f3a
cmpq $0x0, -0x28(%rbp)
jne 0x6003
movq -0x8(%rbp), %rax
movq (%rax), %rax
movl -0x2c(%rbp), %ecx
imulq $0x18, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
testb $0x1, -0x19(%rbp)
je 0x605f
movq -0x28(%rbp), %rax
movq (%rax), %rax
cmpq -0x10(%rbp), %rax
je 0x6032
movq -0x8(%rbp), %rax
cmpq $0x0, 0x28(%rax)
je 0x6032
movq -0x8(%rbp), %rax
movq 0x28(%rax), %rax
movq -0x28(%rbp), %rcx
movq (%rcx), %rdi
callq *%rax
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
cmpq -0x18(%rbp), %rax
je 0x605d
movq -0x8(%rbp), %rax
cmpq $0x0, 0x30(%rax)
je 0x605d
movq -0x8(%rbp), %rax
movq 0x30(%rax), %rax
movq -0x28(%rbp), %rcx
movq 0x8(%rcx), %rdi
callq *%rax
jmp 0x6085
movq -0x8(%rbp), %rax
movl 0xc(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0xc(%rax)
movq -0x28(%rbp), %rax
cmpl $0x2, 0x10(%rax)
jne 0x6083
movq -0x8(%rbp), %rax
movl 0x10(%rax), %ecx
addl $-0x1, %ecx
movl %ecx, 0x10(%rax)
jmp 0x6085
movq -0x28(%rbp), %rax
movl $0x1, 0x10(%rax)
movq -0x10(%rbp), %rcx
movq -0x28(%rbp), %rax
movq %rcx, (%rax)
movq -0x18(%rbp), %rcx
movq -0x28(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x8(%rbp), %rax
movl 0xc(%rax), %eax
movq -0x8(%rbp), %rcx
addl 0x10(%rcx), %eax
cvtsi2ss %eax, %xmm0
movq -0x8(%rbp), %rax
cvtsi2ssl 0x8(%rax), %xmm1
divss %xmm1, %xmm0
movss %xmm0, -0x30(%rbp)
movss -0x30(%rbp), %xmm0
cvtss2sd %xmm0, %xmm0
movsd 0x1ea4(%rip), %xmm1     # 0x7f80
ucomisd %xmm1, %xmm0
jbe 0x60eb
movq -0x8(%rbp), %rdi
callq 0x6100
addq $0x30, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)