/* Copyright (C) 2008 Emmanuel Varoquaux This file is part of XOS. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "vfat_cluster_set_struct.h" #include #include #include #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)); } /* n doit etre non nul. */ 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; } /* n doit etre non nul. */ 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; } /* Retourne 0 si la liste est vide. */ 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; }