#include "vfat_cluster_set_struct.h"
#include <kmalloc.h>
#include <errno.h>
#include <stddef.h>
#define hash(n) (n % CLUSTER_SET_HASH_TABLE_SIZE)
int vfat_cluster_set_init(struct vfat_cluster_set_struct *cluster_set, unsigned int size)
{
struct vfat_cluster_info_struct *ci;
int i;
if (!(cluster_set->cluster_info_table = kmalloc(size * sizeof (struct vfat_cluster_info_struct))))
return -ENOMEM;
cluster_set->cluster_info_table_size = size;
for (ci = &cluster_set->cluster_info_table[0]; ci < &cluster_set->cluster_info_table[size]; ci++)
ci->next_free = ci + 1 < &cluster_set->cluster_info_table[size] ? ci + 1 : NULL;
cluster_set->first_free = cluster_set->cluster_info_table;
cluster_set->first_nonfree = NULL;
cluster_set->last_nonfree = NULL;
for (i = 0; i < CLUSTER_SET_HASH_TABLE_SIZE; i++)
cluster_set->hash_table[i] = NULL;
return 0;
}
void vfat_cluster_set_destroy(struct vfat_cluster_set_struct *cluster_set)
{
kfree(cluster_set->cluster_info_table, cluster_set->cluster_info_table_size * sizeof (struct vfat_cluster_info_struct));
}
void vfat_cluster_set_add(struct vfat_cluster_set_struct *cluster_set, unsigned long n)
{
unsigned long hash_code;
struct vfat_cluster_info_struct *ci;
hash_code = hash(n);
for (ci = cluster_set->hash_table[hash_code]; ci; ci = ci->next_hash)
if (ci->n == n)
return;
if (!(ci = cluster_set->first_free))
return;
ci->n = n;
if (cluster_set->first_free)
cluster_set->first_free = cluster_set->first_free->next_free;
else
cluster_set->first_free = NULL;
ci->previous_nonfree = cluster_set->last_nonfree;
ci->next_nonfree = NULL;
if (cluster_set->last_nonfree)
cluster_set->last_nonfree->next_nonfree = ci;
else
cluster_set->first_nonfree = ci;
cluster_set->last_nonfree = ci;
ci->next_hash = cluster_set->hash_table[hash_code];
cluster_set->hash_table[hash_code] = ci;
}
void vfat_cluster_set_del(struct vfat_cluster_set_struct *cluster_set, unsigned long n)
{
unsigned long hash_code;
struct vfat_cluster_info_struct *pci, *ci;
hash_code = hash(n);
pci = NULL;
ci = cluster_set->hash_table[hash_code];
while (ci) {
if (ci->n == n)
goto found;
pci = ci;
ci = ci->next_hash;
}
return;
found:
if (pci)
pci->next_hash = ci->next_hash;
else
cluster_set->hash_table[hash_code] = ci->next_hash;
if (ci->previous_nonfree)
ci->previous_nonfree->next_nonfree = ci->next_nonfree;
else
cluster_set->first_nonfree = ci->next_nonfree;
if (ci->next_nonfree)
ci->next_nonfree->previous_nonfree = ci->previous_nonfree;
else
cluster_set->last_nonfree = ci->previous_nonfree;
ci->next_free = cluster_set->first_free;
cluster_set->first_free = ci;
}
unsigned long vfat_cluster_set_get(const struct vfat_cluster_set_struct *cluster_set)
{
return cluster_set->first_nonfree ? cluster_set->first_nonfree->n : 0;
}