+#include "tables.h"
+
+//*****************************************************************************************
+//Code
+//*****************************************************************************************
+
+//*********************************************************************************************
+//Alloue une table
+//prend en paramètre un nom de table et retourne un pointeur sur une table vide (sans champs et sans n-uplets)
+//*********************************************************************************************
+table_t * allouer_table (const char * tb)
+{
+ table_t * table;
+ //alloue la structure
+ if ( (table = (table_t *) malloc (sizeof (table_t))) == NULL)
+ {
+ fprintf(stderr, "erreur d'allocation de la table\n");
+ return NULL;
+ }
+ //copie le nom
+ table->nom = strdup(tb);
+ //initialise le nombre de champs et le nombre de n-uplets
+ table->nbchamps = 0;
+ table->nbnuplets = 0;
+
+ //initialise le verrou
+ init_verrou(&table->verrou);
+
+ //retourne le pointeur sur la table
+ return (table);
+}
+
+//*********************************************************************************************
+//Désalloue une table
+//prend en argument un pointeur sur la table à désallouer
+//*********************************************************************************************
+void desallouer_table (table_t * tb)
+{
+ int i,j;
+
+ //bloque l'accès à la table
+ DownEcriture(&tb->verrou);
+
+ //libère le nom de la table
+ free(tb->nom);
+
+ //libération des champs
+ for (i=0 ; i < tb->nbchamps ; i++)
+ {
+ //libère le nom du champ
+ free(tb->champ[i].nom);
+ //libère le type du champ
+ free(tb->champ[i].type);
+ }
+
+ //libération des n-uplets
+ for (i=0 ; i < tb->nbnuplets ; i++)
+ {
+ //pour chaque ligne supprime chaque champ
+ for (j=0 ; j < tb->nbchamps ; j++)
+ free(tb->ligne[i].donnees[j]);
+
+ //détruit le verrou du n-uplet
+ detruire_verrou(&tb->ligne[i].verrou);
+ }
+
+ //si il y avait des n-uplets, libère le pointeur sur le tableau de n-uplets
+ if (tb->nbnuplets > 0)
+ free(tb->ligne);
+
+ //déverouille le verrou
+ Up(&tb->verrou);
+
+ //détruit le verrou
+ detruire_verrou(&tb->verrou);
+
+ //libère la structure
+ free(tb);
+}
+
+//*********************************************************************************************
+//Insère un champ dans une table
+//prend en argument un pointeur sur une table, un nom et un type de champ
+//renvoie un pointeur sur la table
+//*********************************************************************************************
+table_t * inserer_champ (table_t * table, char * champ, char * type)
+{
+ //verrouille la table
+ DownEcriture(&table->verrou);
+
+ //incrémente le nombre de champs
+ table->nbchamps++;
+
+ //vérifie si on ne dépasse pas le nombre max de champs
+ if (table->nbchamps > MAX_CHAMPS)
+ {
+ fprintf(stderr, "Trop de champs\n");
+
+ //remet le nombre de champs en place
+ table->nbchamps++;
+
+ //déverrouille la table
+ Up(&table->verrou);
+ return NULL;
+ }
+
+ //Met le nom et le type du champ dans le nouveau champ
+ table->champ[table->nbchamps -1].nom = strdup(champ);
+ table->champ[table->nbchamps -1].type = strdup(type);
+
+ //déverouille la table
+ Up(&table->verrou);
+
+ //retourne un pointeur vers la table
+ return table;
+}
+
+//*********************************************************************************************
+//Insère un n-uplet dans une table
+//prend en argument un pointeur sur une table et une ligne
+//renvoie 0 si le n-uplet n'a pas pu être ajouté et 1 sinon
+//*********************************************************************************************
+int inserer_nuplet(table_t * table, char * ligne)
+{
+ int i, j;
+ int position = 0;
+ int position2 = 0;
+ int valeur;
+ char champ[TAILLE_STR];
+ char intvaleur[TAILLE_STR];
+
+ //vérouille la table
+ DownEcriture(&table->verrou);
+
+ //incrémente le nombre de n-uplets
+ table->nbnuplets++;
+
+ //si c'est le premier n-uplet il faut allouer un n-uplet
+ if (table->nbnuplets == 1)
+ if ((table->ligne = (nuplet_t *) malloc(sizeof(nuplet_t))) == NULL)
+ {
+ fprintf(stderr,"erreur à l'allocation d'un n-uplet\n");
+ free(champ);
+ free(intvaleur);
+ //remet le nombre de n-uplets comme il était
+ table->nbnuplets--;
+ //déverouille la table
+ Up(&table->verrou);
+ return 0;
+ }
+ else
+ if ((table->ligne = (nuplet_t *) realloc(table->ligne, table->nbnuplets * sizeof(nuplet_t))) == NULL)
+ {
+ fprintf(stderr,"erreur à l'allocation d'un n-uplet\n");
+ free(champ);
+ free(intvaleur);
+ //remet le nombre de n-uplets comme il était
+ table->nbnuplets--;
+ //déverouille la table
+ Up(&table->verrou);
+ return 0;
+ }
+
+ //initialise le verrou du n-uplet
+ init_verrou(&table->ligne[table->nbnuplets - 1].verrou);
+
+ //lecture des champs
+ for (i=0 ; i< table->nbchamps ; i++)
+ {
+ //si le champ suivant est un INT
+ if (strcmp(table->champ[i].type,"INT") == 0)
+ {
+ //lit un int
+ if (sscanf (&ligne[position],"%d %n", &valeur, &position2) !=1)
+ {
+ //c'était pas un INT
+ fprintf(stderr,"erreur à l'insertion d'un n-uplet\n");
+ //libère les champs ajoutés
+ for (j=0 ; j<i ; j++)
+ free(table->ligne[table->nbnuplets - 1].donnees[j]);
+
+ //décrémente le nombre de n-uplets
+ table->nbnuplets--;
+
+ free(champ);
+ free(intvaleur);
+
+ //déverouille la table
+ Up(&table->verrou);
+ return 0;
+ }
+ //avance le "curseur"
+ position += position2;
+
+ //ajoute la valeur dans le n-uplet
+ sprintf(intvaleur,"%d",valeur);
+ table->ligne[table->nbnuplets - 1].donnees[i] = strdup(intvaleur);
+ }
+ //si le champ suivant est un CHAR
+ else if (strcmp(table->champ[i].type,"CHAR") == 0)
+ {
+ //lit un champ
+ if (sscanf (&ligne[position],"%s %n", champ, &position2) !=1)
+ {
+ fprintf(stderr,"erreur à l'insertion d'un n-uplet\n");
+ //libère les champs ajoutés
+ for (j=0 ; j<i ; j++)
+ free(table->ligne[table->nbnuplets - 1].donnees[j]);
+
+ //décrémente le nombre de n-uplet
+ table->nbnuplets--;
+
+ free(champ);
+ free(intvaleur);
+
+ //déverouille la table
+ Up(&table->verrou);
+ return 0;
+ }
+
+ //avance le "curseur"
+ position += position2;
+
+ //ajout de la donnée
+ table->ligne[table->nbnuplets - 1].donnees[i] = strdup(champ);
+ }
+ else //y'a une erreur de type dans la table elle même. Ca c'est pas bien
+ {
+ fprintf(stderr,"erreur de type\n");
+
+ //décrémente le nombre de n-uplets
+ table->nbnuplets--;
+
+ free(champ);
+ free(intvaleur);
+
+ //déverouille la table
+ Up(&table->verrou);
+ return 0;
+ }
+ }
+
+ //déverouille la table
+ Up(&table->verrou);
+
+ //retourne une réponse positive
+ return 1;
+}
+
+//*********************************************************************************************
+//Cherche la table passée en paramètre dans la liste des tables de l'utilisateur passée en argument
+//retourne le nom du fichier contenant la table
+//*********************************************************************************************
+char *ch_table_dans_liste (const char * table, const char * liste)
+{
+ FILE *ls;
+
+ char *vt; //nom de table lu dans le fichier
+ char *fichier; //nom du fichier où se trouve la table
+ char *ligne; //ligne de la table
+
+ //ouverture de la liste des tables en lecture
+ if ((ls = fopen(liste, "r")) == NULL)
+ {
+ perror("ouverture du fichier de mots de passe");
+ return NULL;
+ }
+
+ //allocations
+ if ((vt = (char *) malloc (TAILLE_STR * sizeof(char))) == NULL)
+ {
+ fprintf (stderr,"Problème d'allocation mémoire\n");
+ return NULL;
+ }
+ if ((ligne = (char *) malloc (TAILLE_STR * sizeof(char))) == NULL)
+ {
+ fprintf (stderr,"Problème d'allocation mémoire\n");
+ return NULL;
+ }
+ if ((fichier = (char *) malloc (TAILLE_STR * sizeof(char))) == NULL)
+ {
+ fprintf (stderr,"Problème d'allocation mémoire\n");
+ return NULL;
+ }
+
+ //lit une ligne dans la liste
+ while (fgets(ligne, TAILLE_STR, ls) != NULL)
+ {
+ //enlève l'éventuel caractère de fin de ligne
+ if (ligne[strlen(ligne) - 1] == '\n')
+ ligne[strlen(ligne) - 1] = '\0';
+
+ //enregistre le nom de table et le nom de fichier
+ if (sscanf(ligne, "%s %s",vt, fichier) >= 0)
+ {
+ //compare les noms de tables
+ if (strcmp(vt,table) == 0)
+ {
+ //libération de la chaîne allouée
+ free(vt);
+ free(ligne);
+
+ //fermeture du fichier
+ fclose(ls);
+
+ //on retourne le nom du fichier contenant la table
+ return (fichier);
+ }
+ }
+ else break; //plus rien d'intéresssant à lire
+ }
+
+ //libération de la chaîne allouée
+ free(vt);
+ free(ligne);
+
+ //fermeture du fichier
+ fclose(ls);
+
+ //retourne NULL : on n'a pas trouvé la table
+ return NULL;
+}
+
+//*********************************************************************************************
+//Cherche la table passée en paramètre dans les tables chargées en mémoire (pointées dans
+//la table des tables passée en paramètre
+//retourne -1 si la talbe n'est pas trouvée et son index sinon
+//*********************************************************************************************
+int ch_table_dans_tables (const char * table, ls_table_t * liste_tab)
+{
+ int i;
+
+ //On pose le verrou en lecture sur la table
+ DownLecture (&liste_tab->verrou);
+
+ //Section critique
+ for (i=0 ; i < liste_tab->nbtables ; i++)
+ { //si la table n'a pas été déchargée (ça arrive qu'elle soit déchargée avec decharger_tables)
+ if ( liste_tab->table[i] != NULL)
+ {
+ //si c'est la bonne table
+ if (strcmp( liste_tab->table[i]->nom, table) == 0)
+ {
+ //on relache le verrou
+ Up(&liste_tab->verrou);
+
+ //on a trouvé : on retourne l'index de la table dans la liste des tables chargées
+ return(i);
+ }
+ }
+ }
+
+ //on relache le verrou
+ Up(&liste_tab->verrou);
+
+ //on a pas trouvé
+ return(-1);
+}
+
+//*********************************************************************************************
+//Ajoute la table dans la table des tables chargées en mémoire
+//prend en argument un pointeur sur une table, une liste de tables et le nom du fichier contenant la table
+//*********************************************************************************************
+int ajouter_table_ds_tables (table_t * table, ls_table_t * liste_tab, const char * fichier)
+{
+
+ //protection le la liste des tables en lecture pour lire le nombre de tables chargées
+ DownLecture(&liste_tab->verrou);
+
+ //Si il y a trop de tables chargées, on en décharge une
+ if ( (liste_tab->nbtables + 1) > MAX_TABLES)
+ {
+
+ //on relache le mutex sur la liste sinon le déchargement va bloquer
+ Up(&liste_tab->verrou);
+
+ //on décharge une table
+ if (decharger_une_table (liste_tab, fichier) == 0)
+ return (-1);
+
+ //on pose le verrou en écriture cette fois
+ DownEcriture(&liste_tab->verrou);
+ }
+ else
+ {
+
+ //on relache le mutex de lecture
+ Up(&liste_tab->verrou);
+
+ //et on le pose en écriture
+ DownEcriture(&liste_tab->verrou);
+ }
+
+ //incrémentation du nombre de tables
+ liste_tab->nbtables++;
+
+ //on fait pointer la nouvelle table de la liste sur la structure passée en param
+ liste_tab->table[liste_tab->nbtables - 1] = table;
+
+ //déverouillage de la table
+ Up(&liste_tab->verrou);
+
+ //on retourne l'index de la table dans la liste
+ return (liste_tab->nbtables - 1);
+
+}
+
+//*********************************************************************************************
+//initialise une liste de tables
+//retourne un pointeur sur une liste de tables
+//*********************************************************************************************
+ls_table_t * init_liste_tb_ch(void)
+{
+ ls_table_t * liste;
+
+ //alloue la liste
+ if ((liste = (ls_table_t *)malloc(sizeof(ls_table_t))) == NULL)
+ {
+ fprintf(stderr, "erreur d'allocation mémoire\n");
+ return NULL;
+ }
+
+ //initialise le nombre de tables
+ liste->nbtables = 0;
+
+ //initialise le verrou
+ init_verrou(&liste->verrou);
+
+ //retourne un pointeur sur la liste
+ return (liste);
+}
+
+//*********************************************************************************************
+//Charge une table en mémoire. Retourne l'index de la table dans la liste des tables chargées en mémoire.
+//retourne -1 si la table n'a pas pu être chargée
+//*********************************************************************************************
+int charger_table (const char * table, const char * liste, ls_table_t * tb)
+{
+ FILE *flux;
+ char *fichier;
+ int index;
+
+ table_t * a_inserer;
+
+ //allocation
+ if ((fichier = (char *) malloc (TAILLE_STR * sizeof(char))) == NULL)
+ {
+ fprintf (stderr,"Problème d'allocation mémoire\n");
+ return (-1);
+ }
+
+ //cherche le fichier dans lequel se trouve la table
+ if ((fichier = ch_table_dans_liste(table, liste)) == NULL)
+ {
+ //la table n'est pas dans la liste : on ne peut pas la charger
+ return (-1);
+ }
+ //recherche la table dans la liste des tables chargées en mémoire
+ if ((index = ch_table_dans_tables(table, tb)) != -1)
+ //retourne l'index où la table est déjà chargée
+ return (index);
+
+ //ouverture du flux sur le fichier contenant la table
+ flux = fopen(fichier,"r");
+ //recherche les tables les unes après les autres dans le fichier
+ while(1)
+ {
+ //charge la première table du flux
+ //on lit séquentiellement les tables dans le flux
+ if ((a_inserer = fichier2table (flux)) == NULL)
+ {
+ desallouer_table(a_inserer);
+ //fermeture du flux
+ fclose(flux);
+ return (0);
+ }
+ //si c'est la bonne table, on sort de la boucle
+ if (strcmp(a_inserer->nom,table) != 0)
+ break;
+ //sinon on désalloue et on recommence
+ else
+ desallouer_table(a_inserer);
+ }
+
+ //fermeture du flux
+ fclose(flux);
+
+ //a_inserer contient la table que nous voulons
+ //--> on l'ajoute dans la table des tables chargées en mémoire
+ if ((index = ajouter_table_ds_tables (a_inserer, tb, liste)) == -1)
+ {
+ fprintf(stderr, "erreur au chargement de la table %s\n",a_inserer->nom);
+ return(-1);
+ }
+
+ //retourne la place de la table dans la table des tables
+ return (index);
+}
+
+//*********************************************************************************************
+//Lit la première table trouvée dans le flux et construit une structure contenant la table et renvoie un pointeur sur
+//cette structure
+//*********************************************************************************************
+table_t * fichier2table (FILE * fichier)
+{
+ table_t * table;
+ char *nom;
+ char *ligne;
+ char *champ;
+ char *type;
+ int nbchamps, nbnuplets, i;
+
+ //alloue les pointeurs
+ if ((nom = (char *) malloc (TAILLE_STR * sizeof(char))) == NULL)
+ {
+ fprintf (stderr,"Problème d'allocation mémoire\n");
+ return ((table_t *)NULL);
+ }
+ if ((champ = (char *) malloc (TAILLE_STR * sizeof(char))) == NULL)
+ {
+ fprintf (stderr,"Problème d'allocation mémoire\n");
+ free(nom);
+ return ((table_t *)NULL);
+ }
+ if ((type = (char *) malloc (TAILLE_STR * sizeof(char))) == NULL)
+ {
+ fprintf (stderr,"Problème d'allocation mémoire\n");
+ free(nom);
+ free(champ);
+ return ((table_t *)NULL);
+ }
+ if ((ligne = (char *) malloc (TAILLE_STR * sizeof(char))) == NULL)
+ {
+ fprintf (stderr,"Problème d'allocation mémoire\n");
+ free(nom);
+ free(champ);
+ free(type);
+ return ((table_t *)NULL);
+ }
+
+ //lecture de la première ligne du flux
+ if (fgets(ligne,TAILLE_STR,fichier) == NULL)
+ {
+ free(nom);
+ free(champ);
+ free(type);
+ free(ligne);
+ return ((table_t *)NULL);
+ }
+
+ //Lecture du nom de la table, du nombre de champs et de n-uplets
+ if (sscanf(ligne, "%s %d %d\n", nom, &nbchamps, &nbnuplets) !=3)
+ {
+ free(nom);
+ free(champ);
+ free(type);
+ free(ligne);
+ return ((table_t *)NULL);
+ }
+
+ //allocation de la table
+ if ((table = allouer_table(nom)) == NULL)
+ {
+ fprintf (stderr,"Problème d'allocation de la table\n");
+ free(nom);
+ free(champ);
+ free(type);
+ free(ligne);
+ return ((table_t *)NULL);
+ }
+
+ //lit les champs
+ for (i=0 ; i < nbchamps ; i++)
+ {
+ //lecture du nom du champ et du type
+ if (fscanf(fichier, "%s %s\n", champ, type) !=2)
+ {
+ fprintf(stderr,"erreur à la lecture des champs\n");
+ desallouer_table (table);
+ free(nom);
+ free(champ);
+ free(type);
+ free(ligne);
+ return ((table_t *)NULL);
+ }
+ //insère le champ
+ if (inserer_champ (table, champ, type) == 0)
+ {
+ fprintf(stderr,"erreur à l'insertion des champs\n");
+ desallouer_table (table);
+ free(nom);
+ free(champ);
+ free(type);
+ free(ligne);
+ return ((table_t *)NULL);
+ }
+ }
+
+ //lit les n-uplets
+ for (i = 0 ; i < nbnuplets ; i++)
+ {
+ //lecture d'un n-uplet
+ if (fgets(ligne, TAILLE_STR, fichier) == NULL)
+ {
+ fprintf(stderr,"erreur à la lecture des n-uplets\n");
+ desallouer_table (table);
+ free(nom);
+ free(champ);
+ free(type);
+ free(ligne);
+ return ((table_t *)NULL);
+ }
+ //tradition oblige : on enlève l'éventuel caractère de fin de ligne
+ if (ligne[strlen(ligne) - 1] == '\n')
+ ligne[strlen(ligne) - 1] = '\0';
+
+ //insertion du nuplet dans la table
+ if (inserer_nuplet(table,ligne) == 0)
+ {
+ fprintf(stderr,"erreur à l'insertion des n-uplets\n");
+ desallouer_table (table);
+ free(nom);
+ free(champ);
+ free(type);
+ free(ligne);
+ return ((table_t *)NULL);
+ }
+ }
+
+ //libération ...
+ free(nom);
+ free(champ);
+ free(type);
+ free(ligne);
+
+ //retourneun pointeru sur la table
+ return table;
+}
+
+//*********************************************************************************************
+//écrit les données de la table (y compris le nom, les champs etc..) dans le flux passé en paramètre
+//*********************************************************************************************
+int table2fichier (table_t * table, FILE * fichier)
+{
+ int i, j;
+
+ //pose le verrou de la table en lecture
+ DownLecture(&table->verrou);
+
+ //Enregistrement du nom de la table, du nombre de champs et de n-uplets
+ fprintf(fichier, "%s %d %d\n", table->nom, table->nbchamps, table->nbnuplets);
+
+ //Enregistrement des champs et de leur type
+ for (i=0 ; i < table->nbchamps ; i++)
+ fprintf(fichier, "%s %s\n", table->champ[i].nom, table->champ[i].type);
+
+ //enregistrement des n-uplets...
+ for (i = 0 ; i < table->nbnuplets ; i++)
+ {
+ //...champ par champ
+ for (j = 0 ; j < table->nbchamps ; j++)
+ {
+ //verouille le n-uplet en lecture
+ DownLecture(&table->ligne[i].verrou);
+
+ //écriture de la donnée
+ fprintf (fichier, "%s ", table->ligne[i].donnees[j]);
+
+ //déverouille le n-uplet
+ Up(&table->ligne[i].verrou);
+ }
+ //passe à la ligne à la fin du n-uplet
+ fprintf (fichier, "\n");
+ }
+
+ //relache le verrou sur la table
+ Up(&table->verrou);
+
+ //retourne une réponse positive
+ return 1;
+}
+
+//*********************************************************************************************
+//Renvoie un pointeur sur une table issue de celle passée en paramètre. Le champ est le premier passé en paramètre
+//et les n-uplets doivent satisfaire l'égalité champ2 = valeur dans la table d'origine pour figurer dans celle ci
+//c'est le résultat de la requête : SELECT champ1 FROM table WHERE champ2 = valeur
+//*********************************************************************************************
+table_t * sel_champs(const char * table, const char * champ1, const char * champ2, const char * valeur, const char * liste, ls_table_t * tb)
+{
+ int index, i = 0;
+ int c1 = -1;
+ int c2 = -1;
+ char *ligne;
+
+ //allocation (pas de chômage en tout cas parce qu'il va travailler le gaillard !)
+ if ((ligne = (char *) malloc (TAILLE_STR * sizeof(char))) == NULL)
+ {
+ fprintf (stderr,"Problème d'allocation mémoire\n");
+ return NULL;
+ }
+
+ //table contenant le résultat de la requête
+ table_t * table_resultat;
+
+ //allocation de table résultat
+ table_resultat = allouer_table("resultat");
+
+ //recherche de la table
+ if ((index = charger_table (table, liste, tb)) == -1)
+ {
+ //la table n'existe pas
+ free(ligne);
+ //on libère la table de résultat
+ desallouer_table(table_resultat);
+
+ //retourne un pointeur nul
+ return NULL;
+ }
+
+ //recherche des indices des champs en paramètre
+ for (i=0 ; i < tb->table[index]->nbchamps ; i++)
+ {
+ //est-ce le champ1 ?
+ if (strcmp(tb->table[index]->champ[i].nom,champ1) == 0)
+ c1 = i;
+ //est-ce le champ2 ?
+ if (strcmp(tb->table[index]->champ[i].nom,champ2) == 0)
+ c2 = i;
+ }
+
+ //si au moins l'un des deux n'existe pas...
+ if ((c1 == -1) || (c2 == -1))
+ {
+ //...on libère tout
+ free(ligne);
+ desallouer_table(table_resultat);
+ //on reourne un pointeur nul
+ return NULL;
+ }
+
+ //ajout du champ1 dans la table
+ if ((table_resultat = inserer_champ (table_resultat, strdup(champ1),tb->table[index]->champ[c1].type)) == NULL)
+ {
+ fprintf(stderr, "erreur à l'insertion du champ1\n");
+ free(ligne);
+ desallouer_table(table_resultat);
+ }
+
+ //recherche des enregistrement tels que "champ2 = valeur"
+
+ //on parcourt tous les nuplets de la table
+ for (i=0 ; i < tb->table[index]->nbnuplets ; i++)
+ {
+ //on compare les données du champ2 avec valeur
+ if (strcmp(tb->table[index]->ligne[i].donnees[c2], valeur) == 0)
+ {
+ //si c'estbon, on ajoute le nuplet à la table
+ sprintf(ligne,"%s %s",tb->table[index]->ligne[i].donnees[c1], tb->table[index]->champ[c1].type);
+ if (inserer_nuplet(table_resultat, ligne) == 0)
+ fprintf(stderr,"erreur à l'insertion du n-uplet\n");
+ }
+ }
+
+ //on libère la ligne
+ free (ligne);
+
+ //on retourne un pointeur vers la table de résultat
+ return table_resultat;
+}
+
+//*********************************************************************************************
+//Met à "valeur1" les champs "champ1" de la table "table" pous lesquels le champ "champ2" vaut "valeur2"
+//retourne 1 si ça se passe bien et 0 sinon
+//*********************************************************************************************
+int update_table(const char * table, const char * champ1, const char * champ2, const char * valeur1, const char * valeur2, const char * liste, ls_table_t * tb)
+{
+ int index, i = 0;
+ int c1 = -1;
+ int c2 = -1;
+
+ //recherche de la table
+ if ((index = charger_table (table, liste, tb)) == -1)
+ {
+ //la table n'existe pas
+ return 0;
+ }
+
+ //recherche des indices des champs en paramètre
+ for (i=0 ; i < tb->table[index]->nbchamps ; i++)
+ {
+ //est-ce le champ1 ?
+ if (strcmp(tb->table[index]->champ[i].nom,champ1) == 0)
+ c1 = i;
+ //est-ce le champ2 ?
+ if (strcmp(tb->table[index]->champ[i].nom,champ2) == 0)
+ c2 = i;
+ }
+
+ //si au moins un des champs n'existe pas
+ if ((c1 == -1) || (c2 == -1))
+ //on repart la tête basse
+ return 0;
+
+ //recherche des enregistrement tels que "champ2 = valeur2"
+
+ //on parcourt les n-uplets
+ for (i=0 ; i < tb->table[index]->nbnuplets ; i++)
+ {
+ //on compare la valeur de champ2 avec valeur2
+ if (strcmp(tb->table[index]->ligne[i].donnees[c2], valeur2) == 0)
+ {
+ //on regarde le type
+ //si c'est un INT
+ if (strcmp(tb->table[index]->champ[c1].type,"INT") == 0)
+ {
+ //on bloque la ligne en écriture
+ DownEcriture(&tb->table[index]->ligne[i].verrou);
+
+ //on s'assure que le champ sera un INT, et on copie
+ sprintf(tb->table[index]->ligne[i].donnees[c1],"%d",atoi(valeur1));
+
+ //on relache le verrou
+ Up(&tb->table[index]->ligne[i].verrou);
+ }
+ else
+ {
+ //on bloque la ligne en écriture
+ DownEcriture(&tb->table[index]->ligne[i].verrou);
+
+ //on recopie la donnée
+ sprintf(tb->table[index]->ligne[i].donnees[c1],"%s",valeur1);
+
+ //on relache le verrou
+ Up(&tb->table[index]->ligne[i].verrou);
+ }
+ }
+ }
+
+ //on renvoit une bonne nouvelle
+ return 1;
+}
+
+//*********************************************************************************************
+//Insère la table passée en paramètre dans la liste des tables de l'utilisateur passée en argument
+//fichier désigne le fichier où est placée la table
+//*********************************************************************************************
+int ins_table_dans_liste (const char * table, const char * liste, const char * fichier)
+{
+ FILE *ls;
+
+ char *vt; //nom de table lu dans le fichier
+ char *ligne; //ligne de la table
+
+ //allocation
+ if ((vt = (char *) malloc (TAILLE_STR * sizeof(char))) == NULL)
+ {
+ fprintf (stderr,"Problème d'allocation mémoire\n");
+ return 0;
+ }
+ if ((ligne = (char *) malloc (TAILLE_STR * sizeof(char))) == NULL)
+ {
+ fprintf (stderr,"Problème d'allocation mémoire\n");
+ return 0;
+ }
+
+ //ouverture de la liste en lecture / écriture
+ if ((ls = fopen(liste, "r+")) == NULL)
+ {
+ perror("ouverture du fichier des tables");
+ return 0;
+ }
+
+ //lit une ligne
+ while (fgets(ligne, TAILLE_STR, ls) != NULL)
+ //enregistre le nom de la table
+ if (sscanf(ligne, "%s %*s",vt) == 1)
+ {
+ //compare le nom de la table et celui du nom trouvé dans le fichier
+ if (strcmp(vt,table) == 0)
+ {
+ //fermeture du fichier
+ fclose(ls);
+ //libération de la chaîne allouée
+ free(vt);
+ free(ligne);
+
+ //la table était déjà dans la liste --> on ne l'ajoute pas
+ return 0;
+ }
+ }
+ else break;
+
+ //la table n'y est pas déjà -> on l'ajoute
+ fprintf(ls,"%s %s\n",table, fichier);
+
+ //fermeture du fichier
+ fclose(ls);
+
+ //libération de la chaîne allouée
+ free(vt);
+ free(ligne);
+
+ //et on signale que la table a été ajoutée
+ return 1;
+}
+
+//*********************************************************************************************
+//affiche un table passée en paramètre sur le flux désigné
+//*********************************************************************************************
+void afficher_table (table_t * table, FILE * sortie)
+{
+ int i,j;
+
+ //pose le verrou de la table en lecture
+ DownLecture(&table->verrou);
+
+ //affiche le nom de la table
+ fprintf(sortie,"\nTable %s\n",table->nom);
+
+ //affiche le haut du tableau
+ for (i=0 ; i<table->nbchamps ; i++)
+ fprintf(sortie, "_____________");
+ fprintf(sortie,"_\n");
+
+ //affiche les noms des champs
+ for (i=0 ; i<table->nbchamps ; i++)
+ fprintf(sortie, "| %10s ",table->champ[i]);
+ fprintf(sortie,"|\n");
+
+ //affiche le milieu du tableau
+ for (i=0 ; i<table->nbchamps ; i++)
+ fprintf(sortie, "|------------");
+ fprintf(sortie,"|\n");
+
+ //affiche les n-uplets
+ for (i=0 ; i<table->nbnuplets ; i++)
+ {
+ //verouille le n-uplet en lecture
+ DownLecture(&table->ligne[i].verrou);
+
+ //affiche n-uplet par n-uplet
+ for (j=0 ; j<table->nbchamps ; j++)
+ fprintf(sortie, "| %10s ",table->ligne[i].donnees[j]);
+ fprintf(sortie,"|\n");
+
+ //déverouille le n-uplet
+ Up(&table->ligne[i].verrou);
+ }
+
+ //affiche le bas du tableau
+ for (i=0 ; i<table->nbchamps ; i++)
+ fprintf(sortie, "|------------");
+ fprintf(sortie,"|\n");
+
+ //déverouille la table
+ Up(&table->verrou);
+}
+
+//*********************************************************************************************
+//décharge les tables de la liste passée en argument et les enregistre dans le fichier indiqué
+//*********************************************************************************************
+int decharger_tables (ls_table_t * tables, const char * fichier)
+{
+ FILE *fich_temp;
+ FILE *liste;
+
+ table_t * table_temp;
+
+ int index, i, test;
+
+ char c;
+
+ //lit les tables du fichier et regarde si elles sont chargées en mémoire. Si elles y sont on enregistre la version
+ //en mémoire sionon on enregistre la version qui était déjà dans le fichier
+
+ //ouvre la liste en lecture
+ if ((liste = fopen(fichier,"r")) == NULL)
+ {
+ perror("lecture des données");
+ return 0;
+ }
+
+ //ouvre (et crée un fichier temporaire) en écriture
+ if ((fich_temp = fopen("fich_temp","w")) == NULL)
+ {
+ perror("lecture des données");
+ fclose(liste);
+ return 0;
+ }
+
+ //charge les tables du fichier
+ while ((table_temp = fichier2table (liste)) != NULL)
+ {
+ //si la table n'est pas chargée
+ if ((index = ch_table_dans_tables(table_temp->nom, tables)) == -1)
+ {
+ //on l'enregistre dans le fichier
+ if ((test = table2fichier(table_temp, fich_temp)) == 0)
+ {
+ perror("écriture de la table");
+ fclose(liste);
+ fclose(fich_temp);
+ return 0;
+ }
+ }
+ else //la table est la table No index dans la liste des tables
+ {
+ //enregistrement de la table qui est en mémoire principale
+ //(écrasement de la table qui se trouvait dans le fichier)
+ if ((test = table2fichier(tables->table[index], fich_temp)) == 0)
+ {
+ perror("écriture de la table");
+ fclose(liste);
+ fclose(fich_temp);
+ return 0;
+ }
+ //désallocation de la table
+ desallouer_table(tables->table[index]);
+ //met le pointeur à NULL
+ //pour éviter de la réenregistrer dans la phase suivante
+ tables->table[index] = NULL;
+ }
+ desallouer_table(table_temp);
+ }
+
+ //enregistrement des nouvelles tables (elles sont juste en mémoire et pas dans un fichier)
+ for (i=0 ; i < tables->nbtables ; i++)
+ {
+ //si la table n'a pas été déchargée
+ if (tables->table[i] != NULL)
+ {
+ //enregistrement de la table
+ if ((test = table2fichier(tables->table[i], fich_temp)) == 0)
+ {
+ perror("écriture de la table");
+ fclose(liste);
+ fclose(fich_temp);
+ return 0;
+ }
+ //désallocation de la table
+ desallouer_table(tables->table[i]);
+ //marque la table comme déchargée
+ tables->table[i] = NULL;
+ }
+ }
+
+ //ferme les flux
+ fclose(liste);
+ fclose(fich_temp);
+
+ //ouverture des flux pour la copie
+ if ((liste = fopen(fichier, "w")) == NULL)
+ {
+ perror("ouverture du fichier de mots de passe en écriture");
+ return 0;
+ }
+ if ((fich_temp = fopen("fich_temp", "r")) == NULL)
+ {
+ perror("ouverture du fichier temporaire en lecture");
+ fclose(liste);
+ return 0;
+ }
+
+ //copie de fich_tmp dans liste
+ while ((c = getc(fich_temp)) != EOF)
+ {
+ putc(c, liste);
+ }
+
+ //ferme les flux
+ fclose(liste);
+ fclose(fich_temp);
+
+ //supprime le fichier temporaire
+ unlink ("fich_temp");
+
+ //retourne la réponse
+ return 1;
+}
+
+//*********************************************************************************************
+//décharge une table. L'algorithme utilisé enlève tout simplement la première table chargée
+//puis décale les autres dans la table
+//*********************************************************************************************
+int decharger_une_table (ls_table_t * tables, const char * fichier)
+{
+ FILE *fich_temp;
+ FILE *liste;
+
+ table_t * table_temp;
+
+ int index, i, test;
+
+ char c;
+
+ //ouvre le fichier contenant les tables en lecture
+ if ((liste = fopen(fichier,"r")) == NULL)
+ {
+ perror("lecture des données");
+ return 0;
+ }
+
+ //ouvre (et crée) un fichier temporaire
+ if ((fich_temp = fopen("fich_temp","w")) == NULL)
+ {
+ perror("lecture des données");
+ fclose(liste);
+ return 0;
+ }
+
+ //charge les tables
+ while ((table_temp = fichier2table (liste)) != NULL)
+ {
+ //si la table n'est pas chargée
+ if ((index = ch_table_dans_tables(table_temp->nom, tables)) == -1)
+ {
+ //on la remet dans le fichier (en passant par le fichier temporaire)
+ if ((test = table2fichier(table_temp, fich_temp)) == 0)
+ {
+ perror("écriture de la table");
+ fclose(liste);
+ fclose(fich_temp);
+ //Up(&tables->verrou);
+ return 0;
+ }
+ }
+ else //la table est la table No index dans la liste des tables
+ {
+ //si c'est la première table
+ if (index == 0)
+ {
+ //enregistrement de la table qui est en mémoire
+ if ((test = table2fichier(tables->table[index], fich_temp)) == 0)
+ {
+ perror("écriture de la table");
+ fclose(liste);
+ fclose(fich_temp);
+ //Up(&tables->verrou);
+ return 0;
+ }
+ }
+ //désallocation de la table
+ desallouer_table(tables->table[index]);
+ //marque la table comme déchargée
+ tables->table[index] = NULL;
+ }
+ //désallocation de la table qui vient d'être chargée
+ desallouer_table(table_temp);
+ }
+
+ //verrouille la liste des tables
+ DownEcriture(&tables->verrou);
+
+ //décalage des tables dans la liste
+ for (i=0 ; i < tables->nbtables - 1; i++)
+ tables->table[i] = tables->table[i + 1];
+
+ //marque comme non lue la dernière table
+ tables->table[tables->nbtables - 1] = NULL;
+ tables->nbtables--;
+
+ //on déverouille la liste
+ Up(&tables->verrou);
+
+ //ferme les flux
+ fclose(liste);
+ fclose(fich_temp);
+
+ //ouverture des flux pour la copie
+ if ((liste = fopen(fichier, "w")) == NULL)
+ {
+ perror("ouverture du fichier de mots de passe en écriture");
+ return 0;
+ }
+ if ((fich_temp = fopen("fich_temp", "r")) == NULL)
+ {
+ perror("ouverture du fichier temporaire en lecture");
+ fclose(liste);
+ return 0;
+ }
+ //copie de fich_tmp dans liste
+ while ((c = getc(fich_temp)) != EOF)
+ putc(c, liste);
+
+ //ferme les flux
+ fclose(liste);
+ fclose(fich_temp);
+
+ //supprime le fichier temporaire
+ unlink ("fich_temp");
+
+ //et donne une bonne réponse
+ return 1;
+}