#include VER_INFO_EXPORT (libnode,"$Revision: 1.1 $", "$Name: $",__FILE__,"$Author: smas $") /*------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------*/ /* MODELE DE FONCTION MANAGER */ /*------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------*/ NDT_Status Default_Manager ( va_list Args ) { NDT_Command Command; const char * Command_Name; Command = (NDT_Command) va_arg (Args, NDT_Command); if (Command == NDD_CMD_MAKE_VALUE) { /* NDT_Root * Root = va_arg (Args, NDT_Root *); void ** Value = va_arg (Args, void **); va_list Value_Args = va_arg (Args, va_list); ... = va_arg (Value_Args, ...); */ Command_Name = "NDD_CMD_MAKE_VALUE"; } else if (Command == NDD_CMD_SUM_VALUES) { /* void * Value = va_arg (Args, void *); int * Total = va_arg (Args, int *); */ Command_Name = "NDD_CMD_SUM_VALUES"; } else if (Command == NDD_CMD_COMP_VALUE) { /* void * Value1 = va_arg (Args, void *); void * Value2 = va_arg (Args, void *); */ Command_Name = "NDD_CMD_COMP_VALUE"; } else if (Command == NDD_CMD_PRINT_VALUE) { /* void * Value = va_arg (Args, void *); FILE * Out = va_arg (Args, FILE *); */ Command_Name = "NDD_CMD_PRINT_VALUE"; } else if (Command == NDD_CMD_DELETE_VALUE) { /* void * Value = va_arg (Args, void *); */ Command_Name = "NDD_CMD_DELETE_VALUE"; } else if (Command == NDD_CMD_PRINT_INFO) { /* NDT_Root * Root = va_arg (Args, NDT_Root *); FILE * Out = va_arg (Args, FILE *); */ Command_Name = "NDD_CMD_PRINT_INFO"; } else { sprintf (ND_Error_Msg, "Calling default manager with an undefined command %d\n", Command); ND_Error_Print (); return NDS_ERRAPI; } sprintf (ND_Error_Msg, "Calling default manager with command %d (%s)\n", Command, Command_Name); ND_Error_Print (); return NDS_OK; } /*------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------*/ /* FONCTIONS PUBLIQUES */ /*------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------*/ /* FONCTIONS OPTIMISEES (ND_MODE = 1) */ /*------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------*/ /* Initialisation du contexte de la librairie */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Library_Open_I ( int Debug_Mode ) { if (Debug_Mode == TRUE) ND_Library_Stderr_Set_I (stderr); return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Fermeture du contexte de la librairie */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Library_Close_I ( void ) { struct Symbol * Symbol, * Next_Symbol; /* Désallocation de la table des symboles locale */ Symbol = Symbol_Table; while (Symbol) { Next_Symbol = Symbol->Next; free (Symbol->Name); free (Symbol); Symbol = Next_Symbol; } Symbol_Table = NULL; return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Définition de la sortie standard des messages d'erreur de la librairie */ /*------------------------------------------------------------------------------*/ /* (I) Out : flux de sortie de l'affichage des messages d'erreur */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Library_Stderr_Set_I ( FILE * Out ) { ND_stderr = Out; return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Création d'une nouvelle structure de données */ /*------------------------------------------------------------------------------*/ /* (O) Root: adresse d'un pointeur sur la racine de la nouvelle structure */ /* (I) Type: type de la structure.de données (liste ou arbre binaire) */ /* (I) Allocator: pointeur vers la fonction d'allocation */ /* (I) Desallocator: pointeur vers la fonction de désallocation */ /* (I) Data : pointeur de données utiles à l'allocateur */ /* (I) Own_Value : indique si la structure est propriétaire de ses valeurs */ /*------------------------------------------------------------------------------*/ NDT_Status ND_DataStruct_Open_I ( NDT_Root ** Root, NDT_DataStruct_Type Type, const char * Allocator, const char * Desallocator, void * Data, int Own_Value ) { NDT_Status rc; const char * Real_Allocator, * Real_Desallocator; /* Valeurs par défaut des fonctions d'allocation et de désallocation */ if (Allocator) Real_Allocator = Allocator; else Real_Allocator = "ND_Malloc"; if (Desallocator) Real_Desallocator = Desallocator; else Real_Desallocator = "ND_Free"; rc = ND_Root_Alloc (Root, Type, Real_Allocator, Real_Desallocator, Data); if (ND_ERROR(rc)) return rc; (*Root)->Own_Value = Own_Value; return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Destruction d'une structure de données */ /*------------------------------------------------------------------------------*/ /* (O) Root: pointeur sur la racine de la structure de données à détruire */ /*------------------------------------------------------------------------------*/ NDT_Status ND_DataStruct_Close_I ( NDT_Root * Root ) { NDT_Status rc; /* On supprime toutes les valeurs de la structure */ rc = ND_DataStruct_Traverse_I (Root, NDD_CMD_DELETE_VALUE, NULL); if (ND_ERROR (rc)) return rc; return ND_Root_Free (Root); } /*------------------------------------------------------------------------------*/ /* Réorganisation d'une structure de données */ /* - ordonnancement d'une liste non ordonnée */ /* - réquilibrage d'un arbre non auto-équilibré */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure de données à supprimer */ /*------------------------------------------------------------------------------*/ NDT_Status ND_DataStruct_Reorg_I ( NDT_Root * Root ) { if (ND_IS_LIST(Root)) { if (!ND_IS_ORDERED(Root)) return ND_List_Sort (Root); else return NDS_OK; } if (ND_IS_TREE(Root)) return ND_Tree_Equalize (Root); sprintf (ND_Error_Msg, "Error ND_DataStruct_Reorg : unknown structure type (%d)", Root->Type); ND_Error_Print (); return NDS_ERRAPI; } /*------------------------------------------------------------------------------*/ /* Parcours de tous les noeuds d'une structure de données et exécution d'une */ /* commande sur chacun d'eux */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure de données à parcourir */ /* (I) Command : Commande à exécuter sur chaque noeud traversé */ /* (I) Data : pointeur de données utilisateur */ /*------------------------------------------------------------------------------*/ NDT_Status ND_DataStruct_Traverse_I ( NDT_Root * Root, NDT_Command Command, void * Data ) { NDT_Status rc; NDT_Node * Node, * Next_Node; if (Command == NDD_CMD_SUM_VALUES) *((int *)(Data)) = 0; ND_Node_First_Get_I (Root, &Node); while (Node) { Next_Node = NULL; ND_Node_Next_Get_I (Node, &Next_Node); switch (Command) { case NDD_CMD_DELETE_VALUE: /* On détruit la valeur si la structure est propriétaire de ses valeurs (TRUE par défaut) */ if (Root->Own_Value == TRUE) { rc = ND_Value_Free_I (Root, Node->Value); if (ND_ERROR(rc)) return rc; } rc = ND_Node_Remove_I (Node); if (ND_ERROR(rc)) return rc; rc = ND_Node_Free (Root, Node); if (ND_ERROR(rc)) return rc; break; case NDD_CMD_SUM_VALUES: rc = ND_Manager_Exec_I (Root->Manager, NDD_CMD_SUM_VALUES, Node->Value, (int *)Data); if (ND_ERROR(rc)) return rc; break; case NDD_CMD_PRINT_VALUE: rc = ND_Manager_Exec_I (Root->Manager, NDD_CMD_PRINT_VALUE, Node->Value, (FILE *)Data); if (ND_ERROR(rc)) return rc; fprintf ((FILE *)Data, "\n"); break; default: rc = ND_Manager_Exec_I (Root->Manager, Command, Root, Node->Value, Data); if (ND_ERROR(rc)) return rc; break; } Node = Next_Node; } return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Conversion d'une structure de données d'un type en un autre */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure de données à convertir */ /* (I) Target_Type : type de structure cible */ /*------------------------------------------------------------------------------*/ NDT_Status ND_DataStruct_Convert_I ( NDT_Root * Root, NDT_DataStruct_Type Target_Type) { NDT_Status rc; switch (Root->Type & NDD_DS_MSK) { case NDD_DS_LIST: switch (Target_Type) { case (NDD_DS_LIST | NDD_MN_ORDERED): rc = ND_List_Sort (Root); if (ND_ERROR(rc)) return rc; if (rc == NDS_OK) Root->Type = Target_Type; return rc; case (NDD_DS_TREE | NDD_MN_AUTO_EQU): rc = ND_List_Sort (Root); if (rc != NDS_OK) return rc; rc = ND_Tree_Make (Root); if (ND_ERROR(rc)) return rc; if (rc == NDS_OK) Root->Type = Target_Type; return rc; default: return NDS_OK; } break; case NDD_DS_TREE: switch (Target_Type) { case (NDD_DS_LIST | NDD_MN_ORDERED): case (NDD_DS_LIST | NDD_MN_FIFO): case (NDD_DS_LIST | NDD_MN_FILO): rc = ND_List_Make (Root); if (ND_ERROR(rc)) return rc; if (rc == NDS_OK) Root->Type = Target_Type; default: return NDS_OK; } break; default: sprintf (ND_Error_Msg, "Error ND_DataStruct_Reorg : unknown structure type (%d)", Root->Type); ND_Error_Print (); return NDS_ERRAPI; } return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Affichage d'informations sur une structure de données */ /*------------------------------------------------------------------------------*/ /* (I) Root: pointeur sur la racine de la structure de données */ /* (I) Out : flux de sortie */ /*------------------------------------------------------------------------------*/ NDT_Status ND_DataStruct_Info_Print_I ( NDT_Root * Root, FILE * Out ) { return ND_Manager_Exec_I (Root->Manager, NDD_CMD_PRINT_INFO, Root, Out); } /*------------------------------------------------------------------------------*/ /* Affichage d'une structure de données */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure de données à afficher */ /* (I) Out : flux de sortie */ /*------------------------------------------------------------------------------*/ NDT_Status ND_DataStruct_Print_I ( NDT_Root * Root, FILE * Out ) { return ND_DataStruct_Traverse_I (Root, NDD_CMD_PRINT_VALUE, Out); } /*------------------------------------------------------------------------------*/ /* Function de réparation d'une structure : */ /* - vérifie que tous les noeuds sont correctement liés les uns aux autres */ /* - corrige les informations statistiques de la racine */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure */ /* (O) Nb_Detected : pointeur sur le nombre d'erreurs détectées */ /* (O) Nb_Corrected : pointeur sur le nombre d'erreurs corrigées */ /* (I) Out : flux de sortie du rapport */ /*------------------------------------------------------------------------------*/ NDT_Status ND_DataStruct_Check_I ( NDT_Root * Root, int * Nb_Detected, int * Nb_Corrected, FILE * Out ) { if (ND_IS_LIST(Root)) ND_List_Check (Root, Nb_Detected, Nb_Corrected, Out); else if (ND_IS_TREE(Root)) ND_Tree_Check (Root, Nb_Detected, Nb_Corrected, Out); else { sprintf (ND_Error_Msg, "Error ND_DataStruct_Check : unknown structure type (%d)", Root->Type); ND_Error_Print (); (*Nb_Detected)++; return NDS_ERRAPI; } /* Affichage du résultat de la procédure de vérification */ if (*Nb_Detected == 0) fprintf (Out, "No error detected in the node structure\n"); else fprintf (Out, "%d/%d error(s) corrected in the node structure\n", *Nb_Corrected, *Nb_Detected); if (*Nb_Corrected < *Nb_Detected) return NDS_KO; return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Affiche la structure de données et ses informations statistiques */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure */ /* (I) Out : flux de sortie */ /*------------------------------------------------------------------------------*/ NDT_Status ND_DataStruct_Dump_I ( NDT_Root * Root, FILE * Out ) { NDT_Status rc; NDT_Node * Node; /* Affichage de la racine */ fprintf (Out, "Adresse structure = %p\n", Root); /* Affichage du contenu de la structure */ if (ND_IS_LIST(Root)) { Node = Root->Head; while (Node) { fprintf (Out, " (%p) [", Node); rc = ND_Manager_Exec_I (Root->Manager, NDD_CMD_PRINT_VALUE, Node->Value, Out); if (ND_ERROR(rc)) return rc; fprintf (Out, "]\n"); Node = Node->Right; } return NDS_OK; } else if (ND_IS_TREE(Root)) ND_Tree_Recursive_Print (Root->Head, 1, Out); else { sprintf (ND_Error_Msg, "Error ND_DataStruct_Dump : unknown structure type (%d)", Root->Type); ND_Error_Print (); return NDS_ERRAPI; } return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Récupération de la racine d'une structure */ /*------------------------------------------------------------------------------*/ /* (O) Root : adresse du pointeur sur la racine à récupérer */ /* (I) Node : pointeur sur le noeud dont on cherche la racine */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Node_Root_Get_I ( NDT_Root ** Root, NDT_Node * Node ) { *Root = Node->Root; return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Récupération du premier noeud d'une structure */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine dont on cherche le premier noeud */ /* (O) First_Node : adresse du pointeur sur le premier noeud */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Node_First_Get_I ( NDT_Root * Root, NDT_Node ** First_Node ) { *First_Node = NULL; if (ND_IS_LIST(Root)) *First_Node = Root->Head; if (ND_IS_TREE(Root)) *First_Node = ND_Tree_Node_First_Recursive_Get (Root->Head); if (!*First_Node) return NDS_KO; return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Récupération du dernier noeud d'une structure */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine dont on cherche le dernier noeud */ /* (O) Last_Node : adresse du pointeur sur le premier noeud */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Node_Last_Get_I ( NDT_Root * Root, NDT_Node ** Last_Node ) { *Last_Node = NULL; if (ND_IS_LIST(Root)) *Last_Node = Root->Queue; if (ND_IS_TREE(Root)) *Last_Node = ND_Tree_Node_Last_Recursive_Get (Root->Head); if (!*Last_Node) return NDS_KO; return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Récupération du noeud suivant */ /*------------------------------------------------------------------------------*/ /* (I) Node : pointeur sur le noeud dont on cherche le suivant */ /* (O) Next_Node : adresse du pointeur sur le noeud suivant */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Node_Next_Get_I ( NDT_Node * Node, NDT_Node ** Next_Node ) { if (ND_IS_LIST(Node->Root)) *Next_Node = Node->Right; if (ND_IS_TREE(Node->Root)) { if (!Node->Right) *Next_Node = ND_Tree_Parent_Next_Recursive_Get (Node); else *Next_Node = ND_Tree_Node_First_Recursive_Get (Node->Right); } if (!*Next_Node) return NDS_KO; return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Récupération du noeud précédant */ /*------------------------------------------------------------------------------*/ /* (I) Node : pointeur sur le noeud dont on cherche le précédant */ /* (O) Prev_Node : adresse du pointeur sur le noeud suivant */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Node_Previous_Get_I ( NDT_Node * Node, NDT_Node ** Prev_Node ) { if (ND_IS_LIST(Node->Root)) *Prev_Node = Node->Left; if (ND_IS_TREE(Node->Root)) { if (!Node->Left) *Prev_Node = ND_Tree_Parent_Previous_Recursive_Get (Node); else *Prev_Node = ND_Tree_Node_Last_Recursive_Get (Node->Left); } if (!*Prev_Node) return NDS_KO; return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Ajout d'un noeud à une structure de données */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure de données */ /* (I) Node : pointeur sur le noeud à ajouter */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Node_Add_I ( NDT_Root * Root, NDT_Node * Node ) { if (ND_IS_LIST(Root)) return ND_List_Node_Add (Root, Node); else if (ND_IS_TREE(Root)) return ND_Tree_Node_Add (Root, Node); else { sprintf (ND_Error_Msg, "Error ND_Node_Add : unknown structure type (%d)", Root->Type); ND_Error_Print (); return NDS_ERRAPI; } return NDS_KO; } /*------------------------------------------------------------------------------*/ /* Suppression d'un noeud dans une structure de données */ /*------------------------------------------------------------------------------*/ /* (I) Node: pointeur sur le noeud à supprimer */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Node_Remove_I ( NDT_Node * Node ) { NDT_Root * Root; Root = Node->Root; if (ND_IS_LIST(Root)) return ND_List_Node_Remove (Node); else if (ND_IS_TREE(Root)) { NDT_Node ** Tmp; /* On récupère l'adresse du lien entre le noeud à supprimer et son père */ if (Node->Parent) { /* Cas général */ if (Node == Node->Parent->Left) Tmp = &(Node->Parent->Left); else Tmp = &(Node->Parent->Right); } else { /* Cas du noeud racine */ Tmp = NULL; } if (Node->Right) { NDT_Node * Right_Node = Node->Right; NDT_Node * Left_Node = Node->Left; NDT_Node * First_Node; /* On sauve le fils gauche du noeud à supprimer dans un pointeur de sauvegarde pour pouvoir le récupérer au cas où la procédure serait interrompue (recovery). */ Root->Save = Left_Node; /* On remplace le noeud supprimé par son sous-arbre droit */ if (!Tmp) Root->Head = Root->Queue = Node->Right; else *Tmp = Node->Right; Right_Node->Parent = Node->Parent; /* On attache le sous-arbre gauche au premier noeud du sous-arbre droit */ if (Root->Save) { First_Node = ND_Tree_Node_First_Recursive_Get (Right_Node); First_Node->Left = Root->Save; Root->Save->Parent = First_Node; Root->Save = NULL; } } else { /* On remplace le noeud supprimé par son sous-arbre gauche */ if (!Tmp) Root->Head = Root->Queue = Node->Left; else *Tmp = Node->Left; if (Node->Left) Node->Left->Parent = Node->Parent; } Root->Node_Number--; /* Pas de mise à jour des informations de profondeur : trop coûteux */ Node->Left = NULL; Node->Right = NULL; Node->Parent = NULL; Node->Root = NULL; } else { sprintf (ND_Error_Msg, "Error ND_Node_Remove : unknown structure type (%d)", Root->Type); ND_Error_Print (); return NDS_ERRAPI; } return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Recherche un noeud à partir d'une valeur */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de l'abre */ /* (O) Node : adresse du pointeur sur le noeud à récuperer */ /* (I) Value : pointeur sur la valeur à rechercher */ /* (I) Data : pointeur de données */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Node_Find_I ( NDT_Root * Root, NDT_Node ** Node, void * Value, void * Data ) { if (ND_IS_LIST(Root)) *Node = ND_List_Node_Find (Root, Value, Data); else if (ND_IS_TREE(Root)) *Node = ND_Tree_Node_Find (Root, Value, Data); else { sprintf (ND_Error_Msg, "Error ND_Node_Find : unknown structure type (%d)", Root->Type); ND_Error_Print (); } if (!*Node) return NDS_KO; return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Allocation d'une valeur d'une structure de données */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure de données */ /* (O) Value : adresse d'un pointeur sur la valeur à allouer */ /* (I) ... : arguments relatifs à l'allocation de la valeur */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Value_Alloc_I ( NDT_Root * Root, void ** Value, ... ) { NDT_Status rc; va_list Args; /* Récupération des arguments pour l'allocation de la valeur */ va_start (Args, Value); /* Appel du manager */ rc = ND_Manager_Exec_I (Root->Manager, NDD_CMD_MAKE_VALUE, Root, Value, Args); va_end (Args); return rc; } /*------------------------------------------------------------------------------*/ /* Ajout d'une valeur à une structure de données */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure de données */ /* (I) Value : pointeur sur la valeur à ajouter à la structure de données */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Value_Add_I ( NDT_Root * Root, void * Value ) { if (ND_IS_LIST(Root)) return ND_List_Value_Add (Root, Value); else if (ND_IS_TREE(Root)) return ND_Tree_Value_Add (Root, Value); else { sprintf (ND_Error_Msg, "Error ND_Value_Add : unknown structure type (%d)", Root->Type); ND_Error_Print (); return NDS_ERRAPI; } return NDS_KO; } /*------------------------------------------------------------------------------*/ /* Suppression du premier noeud correspondant à une valeur donnée */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure de données */ /* (I) Reference_Value : pointeur sur la valeur de référence */ /* (I) Removed_Value : adresse d'un pointeur sur la valeur supprimée */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Value_Remove_I ( NDT_Root * Root, void * Reference_Value, void ** Removed_Value ) { NDT_Status rc; struct NDT_Node * Node; *Removed_Value = NULL; /* Recherche du premier noeud correspondant à la valeur de référence */ rc = ND_Node_Find_I (Root, &Node, Reference_Value, NULL); if (ND_ERROR(rc)) return rc; if (!Node) return NDS_KO; *Removed_Value = Node->Value; /* Retrait du noeud de la structure */ rc = ND_Node_Remove_I (Node); if (ND_ERROR(rc)) return rc; /* Désallocation du noeud */ rc = ND_Node_Free (Root, Node); return rc; } /*------------------------------------------------------------------------------*/ /* Désallocation d'une valeur d'une structure de données */ /*------------------------------------------------------------------------------*/ /* (I) Root: pointeur sur la racine de la structure de données */ /* (I) Value: pointeur sur la valeur à désallouer */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Value_Free_I ( NDT_Root * Root, void * Value ) { return ND_Manager_Exec_I (Root->Manager, NDD_CMD_DELETE_VALUE, Root, Value); } /*------------------------------------------------------------------------------*/ /* Exécution d'une fonction Manager dont le nom est passé en paramètre */ /*------------------------------------------------------------------------------*/ /* (I) Function : nom de la fonction manager à exécuter */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Manager_Exec_I ( const char * Function, ... ) { NDT_Manager * Manager; NDT_Status rc; va_list Args; va_start (Args, Function); Manager = (NDT_Manager *) ND_Symbol_Find (Function); rc = Manager (Args); va_end (Args); return rc; } /*------------------------------------------------------------------------------*/ /* Exécution d'une fonction d'allocation dont le nom est passé en paramètre */ /*------------------------------------------------------------------------------*/ /* (I) Function : nom de la fonction à exécuter */ /* (O) Ptr : adresse d'un pointeur sur la zone à allouer */ /* (I) Size : taille de la zone à allouer */ /* (I) Data : données utilisateur utiles à l'allocateur */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Allocator_Exec_I ( const char * Function, void ** Ptr, size_t Size, void * Data ) { NDT_Allocator * Allocator; *Ptr = NULL; Allocator = (NDT_Allocator *) ND_Symbol_Find (Function); return Allocator (Size, Ptr, Data); } /*------------------------------------------------------------------------------*/ /* Exécution d'une fonction de désallocation dont nom est passé en paramètre */ /*------------------------------------------------------------------------------*/ /* (I) Function : nom de la fonction à exécuter */ /* (I) Ptr : adresse de la zone à désallouer */ /* (I) Data : données utilisateur utiles à l'allocateur */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Desallocator_Exec_I ( const char * Function, void * Ptr, void * Data ) { NDT_Desallocator * Desallocator; Desallocator = (NDT_Desallocator *) ND_Symbol_Find (Function); return Desallocator (Ptr, Data); } /*------------------------------------------------------------------------------*/ /* FONCTIONS SECURISEES (ND_MODE = 0) */ /*------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------*/ /* Initialisation du contexte de la librairie */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Library_Open_C ( int Debug_Mode ) { return ND_Library_Open_I (Debug_Mode); } /*------------------------------------------------------------------------------*/ /* Fermeture du contexte de la librairie */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Library_Close_C ( void ) { return ND_Library_Close_I (); } /*------------------------------------------------------------------------------*/ /* Définition de la sortie standard des messages d'erreur de la librairie */ /*------------------------------------------------------------------------------*/ /* (I) Out : flux de sortie de l'affichage des messages d'erreur */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Library_Stderr_Set_C ( FILE * Out ) { return ND_Library_Stderr_Set_I (Out); } /*------------------------------------------------------------------------------*/ /* Création d'une nouvelle structure de données */ /*------------------------------------------------------------------------------*/ /* (O) Root: adresse d'un pointeur sur la racine de la nouvelle structure */ /* (I) Type: type de la structure.de données (liste ou arbre binaire) */ /* (I) Allocator: pointeur vers la fonction d'allocation */ /* (I) Desallocator: pointeur vers la fonction de désallocation */ /* (I) Data : pointeur de données utiles à l'allocateur */ /* (I) Own_Value : indique si la structure est propriétaire de ses valeurs */ /*------------------------------------------------------------------------------*/ NDT_Status ND_DataStruct_Open_C ( NDT_Root ** Root, NDT_DataStruct_Type Type, const char * Allocator, const char * Desallocator, void * Data, int Own_Value ) { return ND_DataStruct_Open_I (Root, Type, Allocator, Desallocator, Data, Own_Value); } /*------------------------------------------------------------------------------*/ /* Destruction d'une structure de données */ /*------------------------------------------------------------------------------*/ /* (O) Root: pointeur sur la racine de la structure de données à détruire */ /*------------------------------------------------------------------------------*/ NDT_Status ND_DataStruct_Close_C ( NDT_Root * Root ) { if (!Root) { sprintf (ND_Error_Msg, "Error ND_DataStruct_Close : structure root is null"); ND_Error_Print (); return NDS_ERRAPI; } return ND_DataStruct_Close_I (Root); } /*------------------------------------------------------------------------------*/ /* Réorganisation d'une structure de données */ /* - ordonnancement d'une liste non ordonnée */ /* - réquilibrage d'un arbre non auto-équilibré */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure de données à supprimer */ /*------------------------------------------------------------------------------*/ NDT_Status ND_DataStruct_Reorg_C ( NDT_Root * Root ) { if (!Root) { sprintf (ND_Error_Msg, "Error ND_DataStruct_Reorg : structure root is null"); ND_Error_Print (); return NDS_ERRAPI; } return ND_DataStruct_Reorg_I (Root); } /*------------------------------------------------------------------------------*/ /* Parcours de tous les noeuds d'une structure de données et exécution d'une */ /* commande sur chacun d'eux */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure de données à parcourir */ /* (I) Command : Commande à exécuter sur chaque noeud traversé */ /* (I) Data : pointeur de données utilisateur */ /*------------------------------------------------------------------------------*/ NDT_Status ND_DataStruct_Traverse_C ( NDT_Root * Root, NDT_Command Command, void * Data ) { if (!Root) { sprintf (ND_Error_Msg, "Error ND_DataStruct_Traverse : structure root is null"); ND_Error_Print (); return NDS_KO; } return ND_DataStruct_Traverse_I (Root, Command, Data); } /*------------------------------------------------------------------------------*/ /* Conversion d'une structure de données d'un type en un autre */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure de données à convertir */ /* (I) Target_Type : type de structure cible */ /*------------------------------------------------------------------------------*/ NDT_Status ND_DataStruct_Convert_C ( NDT_Root * Root, NDT_DataStruct_Type Target_Type) { if (!Root) { sprintf (ND_Error_Msg, "Error ND_DataStruct_Convert : structure root is null"); ND_Error_Print (); return NDS_ERRAPI; } return ND_DataStruct_Convert_I (Root, Target_Type); } /*------------------------------------------------------------------------------*/ /* Affichage d'informations sur une structure de données */ /*------------------------------------------------------------------------------*/ /* (I) Root: pointeur sur la racine de la structure de données */ /* (I) Out : flux de sortie */ /*------------------------------------------------------------------------------*/ NDT_Status ND_DataStruct_Info_Print_C ( NDT_Root * Root, FILE * Out ) { if (!Root) { sprintf (ND_Error_Msg, "Error ND_DataStruct_Print : structure root is null"); ND_Error_Print (); return NDS_ERRAPI; } if (!Out) { sprintf (ND_Error_Msg, "Error ND_DataStruct_Print : the stream descriptor is null"); ND_Error_Print (); return NDS_ERRAPI; } return ND_DataStruct_Info_Print_I (Root, Out); } /*------------------------------------------------------------------------------*/ /* Affichage d'une structure de données */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure de données à afficher */ /* (I) Out : flux de sortie */ /*------------------------------------------------------------------------------*/ NDT_Status ND_DataStruct_Print_C ( NDT_Root * Root, FILE * Out ) { if (!Root) { sprintf (ND_Error_Msg, "Error ND_DataStruct_Print : structure root is null"); ND_Error_Print (); return NDS_ERRAPI; } if (!Out) { sprintf (ND_Error_Msg, "Error ND_DataStruct_Print : the stream descriptor is null"); ND_Error_Print (); return NDS_ERRAPI; } return ND_DataStruct_Print_I (Root, Out); } /*------------------------------------------------------------------------------*/ /* Function de réparation d'une structure : */ /* - vérifie que tous les noeuds sont correctement liés les uns aux autres */ /* - corrige les informations statistiques de la racine */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure */ /* (O) Nb_Detected : pointeur sur le nombre d'erreurs détectées */ /* (O) Nb_Corrected : pointeur sur le nombre d'erreurs corrigées */ /* (I) Out : flux de sortie du rapport */ /*------------------------------------------------------------------------------*/ NDT_Status ND_DataStruct_Check_C ( NDT_Root * Root, int * Nb_Detected, int * Nb_Corrected, FILE * Out ) { if (!Root) { sprintf (ND_Error_Msg, "Error ND_DataStruct_Check : structure root is null"); ND_Error_Print (); (*Nb_Detected)++; return NDS_ERRAPI; } if (!Out) { sprintf (ND_Error_Msg, "Error ND_DataStruct_Check : the stream descriptor is null"); ND_Error_Print (); return NDS_ERRAPI; } return ND_DataStruct_Check_I (Root, Nb_Detected, Nb_Corrected, Out); } /*------------------------------------------------------------------------------*/ /* Affiche la structure de données et ses informations statistiques */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure */ /* (I) Out : flux de sortie */ /*------------------------------------------------------------------------------*/ NDT_Status ND_DataStruct_Dump_C ( NDT_Root * Root, FILE * Out ) { if (!Root) { sprintf (ND_Error_Msg, "Error ND_DataStruct_Dump : structure root is null"); ND_Error_Print (); return NDS_ERRAPI; } if (!Out) { sprintf (ND_Error_Msg, "Error ND_DataStruct_Dump : the stream descriptor is null"); ND_Error_Print (); return NDS_ERRAPI; } return ND_DataStruct_Dump_I (Root, Out); } /*------------------------------------------------------------------------------*/ /* Récupération de la racine d'une structure */ /*------------------------------------------------------------------------------*/ /* (O) Root : adresse du pointeur sur la racine à récupérer */ /* (I) Node : pointeur sur le noeud dont on cherche la racine */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Node_Root_Get_C ( NDT_Root ** Root, NDT_Node * Node ) { if (!Node) { sprintf (ND_Error_Msg, "Error ND_Node_Root_Get : node is null"); ND_Error_Print (); return NDS_ERRAPI; } return ND_Node_Root_Get_I (Root, Node); } /*------------------------------------------------------------------------------*/ /* Récupération du premier noeud d'une structure */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine dont on cherche le premier noeud */ /* (O) First_Node : adresse du pointeur sur le premier noeud */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Node_First_Get_C ( NDT_Root * Root, NDT_Node ** First_Node ) { if (!Root) { sprintf (ND_Error_Msg, "Error ND_Node_First_Get : structure root is null"); ND_Error_Print (); return NDS_ERRAPI; } return ND_Node_First_Get_I (Root, First_Node); } /*------------------------------------------------------------------------------*/ /* Récupération du dernier noeud d'une structure */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine dont on cherche le dernier noeud */ /* (O) Last_Node : adresse du pointeur sur le premier noeud */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Node_Last_Get_C ( NDT_Root * Root, NDT_Node ** Last_Node ) { if (!Root) { sprintf (ND_Error_Msg, "Error ND_Node_Last_Get : structure root is null"); ND_Error_Print (); return NDS_ERRAPI; } return ND_Node_Last_Get_I (Root, Last_Node); } /*------------------------------------------------------------------------------*/ /* Récupération du noeud suivant */ /*------------------------------------------------------------------------------*/ /* (I) Node : pointeur sur le noeud dont on cherche le suivant */ /* (O) Next_Node : adresse du pointeur sur le noeud suivant */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Node_Next_Get_C ( NDT_Node * Node, NDT_Node ** Next_Node ) { if (!Node) { sprintf (ND_Error_Msg, "Error ND_Node_Next_Get : node is null"); ND_Error_Print (); return NDS_ERRAPI; } return ND_Node_Next_Get_I (Node, Next_Node); } /*------------------------------------------------------------------------------*/ /* Récupération du noeud précédant */ /*------------------------------------------------------------------------------*/ /* (I) Node : pointeur sur le noeud dont on cherche le précédant */ /* (O) Prev_Node : adresse du pointeur sur le noeud suivant */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Node_Previous_Get_C ( NDT_Node * Node, NDT_Node ** Prev_Node ) { if (!Node) { sprintf (ND_Error_Msg, "Error ND_Node_Previous_Get : node is null"); ND_Error_Print (); return NDS_ERRAPI; } return ND_Node_Previous_Get_I (Node, Prev_Node); } /*------------------------------------------------------------------------------*/ /* Ajout d'un noeud à une structure de données */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure de données */ /* (I) Node : pointeur sur le noeud à ajouter */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Node_Add_C ( NDT_Root * Root, NDT_Node * Node ) { if (!Root) { sprintf (ND_Error_Msg, "Error ND_Node_Add : structure root is null"); ND_Error_Print (); return NDS_ERRAPI; } if (!Node) { sprintf (ND_Error_Msg, "Error ND_Node_Add : the node to add is null"); ND_Error_Print (); return NDS_ERRAPI; } return ND_Node_Add_I (Root, Node); } /*------------------------------------------------------------------------------*/ /* Suppression d'un noeud dans une structure de données */ /*------------------------------------------------------------------------------*/ /* (I) Node: pointeur sur le noeud à supprimer */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Node_Remove_C ( NDT_Node * Node ) { if (!Node) { sprintf (ND_Error_Msg, "Error ND_Node_Remove : the node to remove is null"); ND_Error_Print (); return NDS_ERRAPI; } return ND_Node_Remove_I (Node); } /*------------------------------------------------------------------------------*/ /* Recherche un noeud à partir d'une valeur */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de l'abre */ /* (O) Node : adresse du pointeur sur le noeud à récuperer */ /* (I) Value : pointeur sur la valeur à rechercher */ /* (I) Data : pointeur de données */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Node_Find_C ( NDT_Root * Root, NDT_Node ** Node, void * Value, void * Data ) { if (!Root) { sprintf (ND_Error_Msg, "Error ND_Node_Find : structure root is null"); ND_Error_Print (); return NDS_ERRAPI; } if (!Value) { sprintf (ND_Error_Msg, "Error ND_Node_Find : the value to find is null"); ND_Error_Print (); return NDS_ERRAPI; } return ND_Node_Find_I (Root, Node, Value, Data); } /*------------------------------------------------------------------------------*/ /* Allocation d'une valeur d'une structure de données */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure de données */ /* (O) Value : adresse d'un pointeur sur la valeur à allouer */ /* (I) ... : arguments relatifs à l'allocation de la valeur */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Value_Alloc_C ( NDT_Root * Root, void ** Value, ... ) { NDT_Status rc; va_list Args; if (!Root) { sprintf (ND_Error_Msg, "Error ND_Value_Alloc : structure root is null"); ND_Error_Print (); return NDS_ERRAPI; } /* Récupération des arguments pour l'allocation de la valeur */ va_start (Args, Value); /* Appel du manager */ rc = ND_Manager_Exec_I (Root->Manager, NDD_CMD_MAKE_VALUE, Root, Value, Args); va_end (Args); return rc; } /*------------------------------------------------------------------------------*/ /* Ajout d'une valeur à une structure de données */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure de données */ /* (I) Value : pointeur sur la valeur à ajouter à la structure de données */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Value_Add_C ( NDT_Root * Root, void * Value ) { if (!Root) { sprintf (ND_Error_Msg, "Error ND_Value_Add : structure root is null"); ND_Error_Print (); return NDS_ERRAPI; } if (!Value) { sprintf (ND_Error_Msg, "Error ND_Value_Add : the value to add is null"); ND_Error_Print (); return NDS_ERRAPI; } return ND_Value_Add_I (Root, Value ); } /*------------------------------------------------------------------------------*/ /* Suppression du premier noeud correspondant à une valeur donnée */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure de données */ /* (I) Reference_Value : pointeur sur la valeur de référence */ /* (I) Removed_Value : adresse d'un pointeur sur la valeur supprimée */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Value_Remove_C ( NDT_Root * Root, void * Reference_Value, void ** Removed_Value ) { if (!Root) { sprintf (ND_Error_Msg, "Error ND_Value_Remove : structure root is null"); ND_Error_Print (); return NDS_ERRAPI; } if (!Reference_Value) { sprintf (ND_Error_Msg, "Error ND_Value_Remove : the reference value is null"); ND_Error_Print (); return NDS_ERRAPI; } return ND_Value_Remove_I (Root, Reference_Value, Removed_Value); } /*------------------------------------------------------------------------------*/ /* Désallocation d'une valeur d'une structure de données */ /*------------------------------------------------------------------------------*/ /* (I) Root: pointeur sur la racine de la structure de données */ /* (I) Value: pointeur sur la valeur à désallouer */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Value_Free_C ( NDT_Root * Root, void * Value ) { if (!Root) { sprintf (ND_Error_Msg, "Error ND_Value_Free : structure root is null"); ND_Error_Print (); return NDS_ERRAPI; } if (!Value) { sprintf (ND_Error_Msg, "Error ND_Value_Free : the value to free is null"); ND_Error_Print (); return NDS_ERRAPI; } /* Appel du manager */ return ND_Value_Free_I (Root, Value); } /*------------------------------------------------------------------------------*/ /* Exécution d'une fonction Manager dont le nom est passé en paramètre */ /*------------------------------------------------------------------------------*/ /* (I) Function : nom de la fonction manager à exécuter */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Manager_Exec_C ( const char * Function, ... ) { NDT_Manager * Manager; NDT_Status rc; va_list Args; if (!Function || !*Function) { sprintf (ND_Error_Msg, "Error ND_Manager_Exec : undefined function name"); ND_Error_Print (); return NDS_ERRAPI; } va_start (Args, Function); Manager = (NDT_Manager *) ND_Symbol_Find (Function); if (!Manager) return NDS_ERRAPI; rc = Manager (Args); va_end (Args); return rc; } /*------------------------------------------------------------------------------*/ /* Exécution d'une fonction d'allocation dont le nom est passé en paramètre */ /*------------------------------------------------------------------------------*/ /* (I) Function : nom de la fonction à exécuter */ /* (O) Ptr : adresse d'un pointeur sur la zone à allouer */ /* (I) Size : taille de la zone à allouer */ /* (I) Data : données utilisateur utiles à l'allocateur */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Allocator_Exec_C ( const char * Function, void ** Ptr, size_t Size, void * Data ) { NDT_Allocator * Allocator; *Ptr = NULL; if (!Function || !*Function) { sprintf (ND_Error_Msg, "Error ND_Allocator_Exec : undefined function name"); ND_Error_Print (); return NDS_ERRAPI; } Allocator = (NDT_Allocator *) ND_Symbol_Find (Function); if (!Allocator) return NDS_ERRAPI; return Allocator (Size, Ptr, Data); } /*------------------------------------------------------------------------------*/ /* Exécution d'une fonction de désallocation dont nom est passé en paramètre */ /*------------------------------------------------------------------------------*/ /* (I) Function : nom de la fonction à exécuter */ /* (I) Ptr : adresse de la zone à désallouer */ /* (I) Data : données utilisateur utiles à l'allocateur */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Desallocator_Exec_C ( const char * Function, void * Ptr, void * Data ) { NDT_Desallocator * Desallocator; if (!Function || !*Function) { sprintf (ND_Error_Msg, "Error ND_Desallocator_Exec : undefined function name"); ND_Error_Print (); return NDS_ERRAPI; } Desallocator = (NDT_Desallocator *) ND_Symbol_Find (Function); if (!Desallocator) return NDS_ERRAPI; return Desallocator (Ptr, Data); } /*------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------*/ /* FONCTIONS PRIVEES */ /*------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------*/ /* Recherche d'un symbole */ /*------------------------------------------------------------------------------*/ void * ND_Symbol_Find ( const char * Symbol_Name ) { struct Symbol * Symbol; void * Ptr = NULL; /* Recherche du symbole dans la table des symboles locale */ Symbol = Symbol_Table; while (Symbol) { if (!strcmp (Symbol->Name, Symbol_Name)) return Symbol->Ptr; else Symbol = Symbol->Next; } /* Si le symbole n'a pas été trouvée dans la table des symboles locale, on l'y ajoute */ Ptr = dlsym (RTLD_DEFAULT, (const char *) Symbol_Name); if (!Ptr) { sprintf (ND_Error_Msg, "Error ND_Symbol_Find : unable to find \"%s\"' in symbol table (%s)", Symbol_Name, dlerror ()); ND_Error_Print (); return NULL; } Symbol = (struct Symbol *) malloc (sizeof (struct Symbol)); if (Symbol) { Symbol->Name = strdup (Symbol_Name); Symbol->Ptr = Ptr; Symbol->Next = Symbol_Table; Symbol_Table = Symbol; } return Ptr; } /*------------------------------------------------------------------------------*/ /* Allocation d'un noeud */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure */ /* (O) Node : adresse du pointeur sur le nouveau noeud */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Node_Alloc ( NDT_Root * Root, NDT_Node ** Node ) { NDT_Status rc; rc = ND_Allocator_Exec_I (Root->Allocator, (void **)Node, sizeof (NDT_Node), Root->User); if (ND_ERROR(rc)) return rc; (*Node)->Parent = NULL; (*Node)->Left = NULL; (*Node)->Right = NULL; (*Node)->Root = NULL; (*Node)->Value = NULL; return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Désallocation d'un noeud */ /*------------------------------------------------------------------------------*/ /* (I) Root: pointeur sur la racine de la structure */ /* (I) Node : pointeur sur le noeud à détruire */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Node_Free ( NDT_Root * Root, NDT_Node * Node ) { return ND_Desallocator_Exec_I (Root->Desallocator, Node, Root->User); } /*------------------------------------------------------------------------------*/ /* Désallocation de la racine d'une structure de donnée */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine à détruire */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Root_Free ( NDT_Root * Root ) { return ND_Desallocator_Exec_I (Root->Desallocator, Root, Root->User); } /*------------------------------------------------------------------------------*/ /* Allocation d'une racine de structure de données */ /*------------------------------------------------------------------------------*/ /* (O) New_Root: adresse du pointeur sur la nouvelle racine */ /* (I) Type: type de la structure de données */ /* (I) Allocator: pointeur vers la fonction d'allocation */ /* (I) Desallocator: pointeur vers la fonction de désallocation */ /* (I) Data : pointeur de données utiles à l'allocateur */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Root_Alloc ( NDT_Root ** Root, NDT_DataStruct_Type Type, const char * Allocator, const char * Desallocator, void * Data ) { NDT_Status rc; rc = ND_Allocator_Exec_I (Allocator, (void **)Root, sizeof (NDT_Root), Data); if (ND_ERROR(rc)) return rc; (*Root)->Type = Type; (*Root)->Head = NULL; (*Root)->Queue = NULL; (*Root)->Save = NULL; (*Root)->Max_Dif = DEF_MAX_DIF; (*Root)->Node_Number = 0; (*Root)->Max_Depth = 0; (*Root)->Min_Depth = HUGE_LONG; (*Root)->Nb_Equ = 0; (*Root)->User = Data; (*Root)->Own_Value = TRUE; /* par défaut, une structure de données est propriétaire de ses valeurs */ strcpy ((*Root)->Manager, "Default_Manager"); strcpy ((*Root)->Allocator, Allocator); strcpy ((*Root)->Desallocator, Desallocator); return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Ajout d'un noeud à une liste chaînée */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la liste */ /* (I) New_Node : pointeur sur le noeud à ajouter */ /*------------------------------------------------------------------------------*/ NDT_Status ND_List_Node_Add ( NDT_Root * Root, NDT_Node * New_Node ) { /* Ajout dans une liste triée */ if (ND_IS_ORDERED(Root)) { NDT_Node * Node; NDT_Status rc; New_Node->Root = Root; New_Node->Parent = New_Node->Left = New_Node->Right = NULL; /* Une liste triée peut être orientée de 2 manières : - FIFO : un noeud sera inséré APRES un noeud de même valeur (par défaut) - FILO : un noeud sera inséré AVANT un noeud de même valeur */ if (ND_IS_FILO(Root)) { /* Pour une liste triée orientée FILO, on parcourt la liste en sens normal */ Node = Root->Head; while (Node) { rc = ND_Manager_Exec_I (Root->Manager, NDD_CMD_COMP_VALUE, New_Node->Value, Node->Value); if (rc == NDS_GREATER) Node = Node->Right; else { /* On insère avant le noeud courant si le nouveau noeud est de valeur inférieure ou égale */ New_Node->Left = Node->Left; New_Node->Right = Node; if (!Node->Left) Root->Head = New_Node; else Node->Left->Right = New_Node; Node->Left = New_Node; Node = NULL; } } /* Insertion en queue de liste si le noeud n'a pas été inséré */ if (!New_Node->Left && !New_Node->Right) { if (!Root->Queue) Root->Head = Root->Queue = New_Node; else { Root->Queue->Right = New_Node; New_Node->Left = Root->Queue; Root->Queue = New_Node; } } } else { /* Pour une liste triée orientée FIFO, on parcourt la liste dans le sens inverse */ Node = Root->Queue; while (Node) { rc = ND_Manager_Exec_I (Root->Manager, NDD_CMD_COMP_VALUE, New_Node->Value, Node->Value); /* On insère après le noeud courant si le nouveau noeud est de valeur strictement supérieure ou égale */ if (rc == NDS_LOWER) Node = Node->Left; else { New_Node->Left = Node; New_Node->Right = Node->Right; if (!Node->Right) Root->Queue = New_Node; else Node->Right->Left = New_Node; Node->Right = New_Node; Node = NULL; } } /* Insertion en tête de liste si le noeud n'a pas été inséré */ if (!New_Node->Left && !New_Node->Right) { if (!Root->Head) Root->Head = Root->Queue = New_Node; else { Root->Head->Left = New_Node; New_Node->Right = Root->Head; Root->Head = New_Node; } } } Root->Node_Number++; return NDS_OK; } else { /* FIFO = ajout en queue de liste */ if (ND_IS_FIFO(Root)) { New_Node->Root = Root; New_Node->Parent = NULL; New_Node->Left = Root->Queue; New_Node->Right = NULL; if (!Root->Head) Root->Head = New_Node; else Root->Queue->Right = New_Node; Root->Queue = New_Node; Root->Node_Number++; return NDS_OK; } /* FILO = ajout en tête de liste */ if (ND_IS_FILO(Root)) { New_Node->Root = Root; New_Node->Parent = NULL; New_Node->Left = NULL; New_Node->Right = Root->Head; if (!Root->Queue) Root->Queue = New_Node; else Root->Head->Left = New_Node; Root->Head = New_Node; Root->Node_Number++; return NDS_OK; } } printf ("ND_List_Node_Add : unknown list type (%d)\n", Root->Type); return NDS_ERRAPI; } /*------------------------------------------------------------------------------*/ /* Ajout d'une nouvelle valeur à une liste */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la liste */ /* (I) Value : pointeur sur la valeur à ajouter */ /*------------------------------------------------------------------------------*/ NDT_Status ND_List_Value_Add ( NDT_Root * Root, void * Value ) { NDT_Status rc; NDT_Node * Node; rc = ND_Node_Alloc (Root, &Node); if (ND_ERROR(rc)) return rc; Node->Value = Value; return ND_List_Node_Add (Root, Node); } /*------------------------------------------------------------------------------*/ /* Ajout d'un noeud à un arbre binaire */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de l'arbre */ /* (I) Value : pointeur sur la valeur à ajouter */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Tree_Value_Add ( NDT_Root * Root, void * Value ) { NDT_Status rc; NDT_Node * Node; rc = ND_Node_Alloc (Root, &Node); if (ND_ERROR(rc)) return rc; Node->Value = Value; return ND_Tree_Node_Add (Root, Node); } /*------------------------------------------------------------------------------*/ /* Recherche une valeur dans une liste et retourne le noeud correspondant */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la liste */ /* (I) Value : pointeur sur la valeur à rechercher */ /* (I) Data : pointeur de données */ /*------------------------------------------------------------------------------*/ NDT_Node * ND_List_Node_Find ( NDT_Root * Root, void * Value, void * Data ) { NDT_Node * Node; NDT_Status rc; Node = Root->Head; if (ND_IS_ORDERED(Root)) { /* Pour les listes triées, la recherche peut être optimisée */ while (Node) { rc = ND_Manager_Exec_I (Root->Manager, NDD_CMD_COMP_VALUE, Value, Node->Value, Data); switch (rc) { case NDS_EQUAL: return Node; case NDS_LOWER: /* Ce n'est pas a peine de continuer car on a déjà dépassé la valeur recherchée */ return NULL; case NDS_GREATER: Node = Node->Right; break; } } } else { /* Pour les listes non triées, il faut parcourir toute la liste */ while (Node && ND_Manager_Exec_I (Root->Manager, NDD_CMD_COMP_VALUE, Value, Node->Value, Data) != NDS_EQUAL) Node = Node->Right; } return Node; } /*------------------------------------------------------------------------------*/ /* Recherche un noeud dans un arbre et retourne le pointeur sur le noeud */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de l'abre */ /* (I) Value : pointeur sur la valeur à rechercher */ /* (I) Data : pointeur de données */ /*------------------------------------------------------------------------------*/ /*------------------------------ Recursive Kernel ------------------------------*/ NDT_Node * ND_Tree_Node_Recursive_Find ( NDT_Node * Node, void * Value, void * Data ) { NDT_Status Answer; if (!Node) return NULL; Answer = ND_Manager_Exec_I (Node->Root->Manager, NDD_CMD_COMP_VALUE, Value, Node->Value, Data); /* Noeud trouvé */ if (Answer == NDS_EQUAL) return Node; /* Continuation de la recherche par appel récursif */ if (Answer == NDS_LOWER) return ND_Tree_Node_Recursive_Find (Node->Left, Value, Data); if (Answer == NDS_GREATER) return ND_Tree_Node_Recursive_Find (Node->Right, Value, Data); return NULL; } /*-------------------------------- main body ---------------------------------*/ NDT_Node * ND_Tree_Node_Find ( NDT_Root * Root, void * Value, void * Data ) { return ND_Tree_Node_Recursive_Find (Root->Head, Value, Data); } /*------------------------------------------------------------------------------*/ /* Recherche du premier noeud parent situé après */ /*------------------------------------------------------------------------------*/ /* (I) Node : pointeur sur le noeud */ /*------------------------------------------------------------------------------*/ NDT_Node * ND_Tree_Parent_Next_Recursive_Get ( NDT_Node * Node ) { if (!Node->Parent) return NULL; if (Node == Node->Parent->Right) return ND_Tree_Parent_Next_Recursive_Get (Node->Parent); return Node->Parent; } /*------------------------------------------------------------------------------*/ /* Recherche du premier noeud parent situé avant */ /*------------------------------------------------------------------------------*/ /* (I) Node : pointeur sur le noeud */ /*------------------------------------------------------------------------------*/ NDT_Node * ND_Tree_Parent_Previous_Recursive_Get ( NDT_Node * Node ) { if (!Node->Parent) return NULL; if (Node == Node->Parent->Left) return ND_Tree_Parent_Previous_Recursive_Get (Node->Parent); return Node->Parent; } /*------------------------------------------------------------------------------*/ /* Supprime le noeud d'une liste */ /*------------------------------------------------------------------------------*/ /* (I) Node : pointeur sur le noeud à supprimer */ /*------------------------------------------------------------------------------*/ NDT_Status ND_List_Node_Remove ( NDT_Node * Node ) { if (!Node->Left) Node->Root->Head = Node->Right; else Node->Left->Right = Node->Right; if (!Node->Right) Node->Root->Queue = Node->Left; else Node->Right->Left = Node->Left; Node->Root->Node_Number--; Node->Left = NULL; Node->Right = NULL; Node->Root = NULL; return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Conversion d'un arbre en liste chaînée */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine du la structure à convertir */ /*------------------------------------------------------------------------------*/ /*------------------------------- Recursive Kernel -----------------------------*/ NDT_Status ND_List_Recursive_Make ( NDT_Node * Node, NDT_Root * Root ) { NDT_Node * Right_Node; if (!Node) return NDS_OK; if (ND_List_Recursive_Make (Node->Left, Root) != NDS_OK) return NDS_KO; Right_Node = Node->Right; if (ND_List_Node_Add (Root, Node) != NDS_OK) return NDS_KO; return ND_List_Recursive_Make (Right_Node, Root); } /*--------------------------------- main body --------------------------------*/ NDT_Status ND_List_Make ( NDT_Root * Root ) { NDT_Node * Node; Node = Root->Head; Root->Head = NULL; Root->Queue = NULL; Root->Max_Dif = DEF_MAX_DIF; Root->Node_Number = 0; Root->Max_Depth = 0; Root->Min_Depth = HUGE_LONG; Root->Nb_Equ = 0; Root->Type = NDD_DS_LIST | NDD_MN_FIFO; return ND_List_Recursive_Make (Node, Root); } /*------------------------------------------------------------------------------*/ /* Conversion d'une structure en arbre binaire */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine du la structure à convertir */ /* (I) Type : type du futur arbre */ /*------------------------------------------------------------------------------*/ /*------------------------------- Recursive Kernel -----------------------------*/ NDT_Node * ND_Tree_Recursive_Make ( long Depth, long Node_Number, NDT_Node * Node ) { long Middle_Pos, Left_Len, Right_Len, i; NDT_Node * Left_Node, * Middle_Node, * Right_Node; if (!Node) return (NULL); /* On calcule le milieu de la liste */ Middle_Pos = Node_Number / 2 + 1; Middle_Node = Node; for (i = 1; i < Middle_Pos; i++) Middle_Node = Middle_Node->Right; /* On coupe la liste en deux */ if (Middle_Node->Left) { Middle_Node->Left->Right = NULL; Left_Node = Node; Left_Len = Middle_Pos - 1; } else { Left_Node = NULL; Left_Len = 0; } if (Middle_Node->Right) { Middle_Node->Right->Left = NULL; Right_Node = Middle_Node->Right; Right_Len = Node_Number - Middle_Pos; } else { Right_Node = NULL; Right_Len = 0; } /* Construction des sous-arbres */ Middle_Node->Left = ND_Tree_Recursive_Make (Depth + 1, Left_Len, Left_Node); Middle_Node->Right = ND_Tree_Recursive_Make (Depth + 1, Right_Len, Right_Node); if (Middle_Node->Left) Middle_Node->Left->Parent = Middle_Node; if (Middle_Node->Right) Middle_Node->Right->Parent = Middle_Node; /* Mise à jour des informations statistiques de la structure */ Middle_Node->Root->Node_Number++; if (!Middle_Node->Left && !Middle_Node->Right) { /* Si le noeud courant est une feuille, on met éventuellement à jour les longueurs minimale et maximale des branches de l'arbre */ if (Depth > Middle_Node->Root->Max_Depth) Middle_Node->Root->Max_Depth = Depth; if (Depth < Middle_Node->Root->Min_Depth) Middle_Node->Root->Min_Depth = Depth; } return Middle_Node; } /*--------------------------------- main body --------------------------------*/ NDT_Status ND_Tree_Make ( NDT_Root * Root ) { NDT_Status rc; NDT_Node * Node; long Node_Number; if (ND_IS_ORDERED(Root)) { rc = ND_List_Sort (Root); if (ND_ERROR(rc)) return rc; } Node = Root->Head; Node_Number = Root->Node_Number; Root->Head = NULL; Root->Queue = NULL; Root->Max_Dif = DEF_MAX_DIF; Root->Node_Number = 0; Root->Max_Depth = 0; Root->Min_Depth = HUGE_LONG; Root->Nb_Equ = 0; Root->Type = NDD_DS_TREE | NDD_MN_AUTO_EQU; Root->Head = Root->Queue = ND_Tree_Recursive_Make (1, Node_Number, Node); return NDS_OK; } /*----------------------------------------------------------------------------*/ /* Equilibrage d'un arbre binaire */ /*----------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de l'arbre */ /*----------------------------------------------------------------------------*/ NDT_Status ND_Tree_Equalize ( NDT_Root * Root ) { NDT_Status rc; NDT_DataStruct_Type Type; char Manager[30]; long Max_Dif, Nb_Equ; Type = Root->Type; strcpy (Manager, Root->Manager); Max_Dif = Root->Max_Dif; Nb_Equ = Root->Nb_Equ; rc = ND_List_Make (Root); if (ND_ERROR(rc)) return rc; Root->Type = NDD_DS_LIST | NDD_MN_ORDERED; rc = ND_Tree_Make (Root); if (ND_ERROR(rc)) return rc; Root->Type = Type; strcpy (Root->Manager, Manager); Root->Max_Dif = Max_Dif; Root->Nb_Equ = Nb_Equ + 1; return NDS_OK; } /*----------------------------------------------------------------------------*/ /* Retourne la profondeur de la plus grande branche à partir d'un noeud */ /*----------------------------------------------------------------------------*/ /* (I) Node : pointeur sur le noeud */ /*----------------------------------------------------------------------------*/ long ND_Tree_MaxDepth_Get ( NDT_Node * Node ) { long Max_Left, Max_Right; if (!Node) return 0; Max_Left = ND_Tree_MaxDepth_Get (Node->Left); Max_Right = ND_Tree_MaxDepth_Get (Node->Right); return ( max (Max_Left, Max_Right) + 1 ); } /*----------------------------------------------------------------------------*/ /* Retourne la profondeur de la plus petite branche à partir d'un noeud */ /*----------------------------------------------------------------------------*/ /* (I) Node : pointeur sur le noeud */ /*----------------------------------------------------------------------------*/ long ND_Tree_MinDepth_Get ( NDT_Node * Node) { long Min_Left, Min_Right; if (!Node) return 0; Min_Left = ND_Tree_MinDepth_Get (Node->Left); Min_Right = ND_Tree_MinDepth_Get (Node->Right); return ( min (Min_Left, Min_Right) + 1 ); } /*----------------------------------------------------------------------------*/ /* Ajoute un noeud à un arbre */ /*----------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de l'arbre */ /* (I) Node : pointeur sur le noeud à ajouter */ /*----------------------------------------------------------------------------*/ /*------------------------------ Recursive Kernel ----------------------------*/ void ND_Tree_Node_Recursive_Add ( NDT_Root * Root, NDT_Node * Parent_Node, NDT_Node ** Node, long Depth, NDT_Node * New_Node ) { if (*Node) { /* Appel récursif */ if (ND_Manager_Exec_I (Root->Manager, NDD_CMD_COMP_VALUE, New_Node->Value, (*Node)->Value) == NDS_LOWER) ND_Tree_Node_Recursive_Add (Root, (*Node), &((*Node)->Left), Depth + 1, New_Node); else ND_Tree_Node_Recursive_Add (Root, (*Node), &((*Node)->Right), Depth + 1, New_Node); } else { long Max_Depth, Min_Depth; /* Rattachement du nouveau noeud à l'arbre */ New_Node->Parent = Parent_Node; New_Node->Root = Root; *Node = New_Node; /* Mise à jour des informations statistiques de la structure */ Root->Node_Number++; Max_Depth = ND_Tree_MaxDepth_Get (New_Node); Min_Depth = ND_Tree_MinDepth_Get (New_Node); if (Max_Depth + Depth - 1 > Root->Max_Depth) Root->Max_Depth = Max_Depth + Depth - 1; if (Min_Depth + Depth - 1 < Root->Min_Depth) Root->Min_Depth = Min_Depth + Depth - 1 ; } } /*-------------------------------- main body ---------------------------------*/ NDT_Status ND_Tree_Node_Add ( NDT_Root * Root, NDT_Node * Node ) { ND_Tree_Node_Recursive_Add (Root, NULL, &(Root->Head), 1, Node); if (ND_IS_AUTO_EQU(Root) && Root->Max_Depth - Root->Min_Depth > Root->Max_Dif) return ND_Tree_Equalize (Root); return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Ajoute tous les noeud d'une liste à un arbre */ /*------------------------------------------------------------------------------*/ /* (I) Tree_Root : pointeur sur la racine de l'arbre */ /* (I) List_Root : pointeur sur la racine de la liste */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Tree_List_Add ( NDT_Root * Tree_Root, NDT_Root * List_Root) { NDT_Status rc; NDT_Node * Node; Node = List_Root->Head; while (Node) { rc = ND_Tree_Node_Add (Tree_Root, Node); if (ND_ERROR(rc)) return rc; Node = Node->Right; } return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Affiche toutes les informations d'une structure de données */ /*------------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la structure */ /*------------------------------------------------------------------------------*/ /*------------------------------- Recursive Kernel -----------------------------*/ void ND_Tree_Recursive_Print ( NDT_Node * Node, long Depth, FILE * Out ) { const int BRANCH_LEN = 4; if (!Node) return; if (Node->Right) { ND_Tree_Recursive_Print (Node->Right, Depth + 1, Out); fprintf (Out, "%*s/\n", (int)(Depth * BRANCH_LEN - 1), ""); } fprintf (Out, "%*s (%p) ", (int)((Depth - 1) * BRANCH_LEN), "", Node); /* Affichage des toutes les informations (noeud et valeur) : if (Node->Root) fprintf (Out, "Root=%p ", Node->Root); if (Node->Parent) fprintf (Out, "Parent=%p ", Node->Parent); if (Node->Left) fprintf (Out, "Left=%p ", Node->Left); if (Node->Right) fprintf (Out, "Right=%p ", Node->Right); fprintf (Out, "Value=["); ND_Manager_Exec (Node->Root->Manager, NDD_CMD_PRINT_VALUE, Node->Value, Out); fprintf (Out, "]\n"); */ /* Affichage de la valeur seule : */ ND_Manager_Exec_I (Node->Root->Manager, NDD_CMD_PRINT_VALUE, Node->Value, Out); fprintf (Out, "\n"); if (Node->Left) { fprintf (Out, "%*s\\\n", (int)(Depth * BRANCH_LEN - 1), ""); ND_Tree_Recursive_Print (Node->Left, Depth + 1, Out); } } /*------------------------------------------------------------------------------*/ /* Function de comparaison de noeuds (pour le quick sort) */ /*------------------------------------------------------------------------------*/ int ND_Node_Compare ( void ** Node1, void ** Node2 ) { NDT_Status rc; rc = ND_Manager_Exec_I (Tmp_Root->Manager, NDD_CMD_COMP_VALUE, ((NDT_Node *)(*Node1))->Value, ((NDT_Node *)(*Node2))->Value); switch ((int)rc) { case NDS_EQUAL: return 0; case NDS_LOWER: return -1; case NDS_GREATER: return 1; default: sprintf (ND_Error_Msg, "Error ND_Node_Compare : incorrect return code from the manager: %d", rc); ND_Error_Print (); return 0; } } /*----------------------------------------------------------------------------*/ /* Ordonne une liste chaînée : */ /*----------------------------------------------------------------------------*/ /* (I) Root : pointeur sur la racine de la liste à trier */ /*----------------------------------------------------------------------------*/ NDT_Status ND_List_Sort ( NDT_Root * Root ) { int i; NDT_Node * Node; void ** Tab; if (Root->Node_Number < 2) return NDS_OK; /* Allocation d'un tableau de pointeur de noeuds */ Tab = (void **) malloc (Root->Node_Number * sizeof (NDT_Node *)); /* On remplit le tableau avec les noeuds de la structure à trier */ i = 0; Node = Root->Head; while (Node) { Tab[i] = Node; Node = Node->Right; i++; } /* Tri du tableau de pointeurs de noeuds */ Tmp_Root = Root; qsort (Tab, (size_t)(Root->Node_Number), sizeof (NDT_Node *), &ND_Node_Compare); /* On met à jour les liens entre les noeuds */ for (i = 0; i < Root->Node_Number; i++) { Node = (NDT_Node *) Tab [i]; Node->Left = (i ? (NDT_Node *)(Tab [i - 1]) : NULL); Node->Right = (i != Root->Node_Number - 1 ? (NDT_Node *)(Tab [i + 1]) : NULL); } Root->Head = (NDT_Node *)(Tab [0]); Root->Queue = (NDT_Node *)(Tab [Root->Node_Number - 1]); /* Désallocation du tableau */ free (Tab); return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Récupère le premier noeud dans un sous-arbre */ /*------------------------------------------------------------------------------*/ /* (I) Node : pointeur sur le noeud racine du sous-arbre */ /*------------------------------------------------------------------------------*/ NDT_Node * ND_Tree_Node_First_Recursive_Get ( NDT_Node * Node ) { if (!Node) return NULL; if (!Node->Left) return Node; return ND_Tree_Node_First_Recursive_Get (Node->Left); } /*------------------------------------------------------------------------------*/ /* Récupère le dernier noeud dans un sous-arbre */ /*------------------------------------------------------------------------------*/ /* (I) Node : pointeur sur le noeud racine du sous-arbre */ /*------------------------------------------------------------------------------*/ NDT_Node * ND_Tree_Node_Last_Recursive_Get ( NDT_Node * Node ) { if (!Node) return NULL; if (!Node->Right) return Node; return ND_Tree_Node_Last_Recursive_Get (Node->Right); } /*------------------------------------------------------------------------------*/ /* Redéfinition de la fonction malloc () avec retour de type NDT_Status */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Malloc ( size_t Size, void ** ptr, void * Data ) { *ptr = malloc (Size); if (!*ptr) return NDS_ERRMEM; return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Redéfinition de la fonction free () avec retour de type NDT_Status */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Free (void * ptr) { if (!ptr) return NDS_ERRAPI; free (ptr); return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Function de vérification d'une liste : */ /*------------------------------------------------------------------------------*/ void ND_List_Check ( NDT_Root * Root, int * Nb_Detected, int * Nb_Corrected, FILE * Out ) { /* On vérifie les liens entre les noeuds */ ND_List_Link_Check (Root, Nb_Detected, Nb_Corrected, Out); /* On vérifie les valeurs des noeuds */ ND_Value_Check (Root, Nb_Detected, Nb_Corrected, Out); } /*------------------------------------------------------------------------------*/ /* Function de vérification et correction des liens entre noeuds d'une liste */ /*------------------------------------------------------------------------------*/ void ND_List_Link_Check ( NDT_Root * Root, int * Nb_Detected, int * Nb_Corrected, FILE * Out ) { NDT_Node * Node; int LeftToRight_Node_Number = 0; int RightToLeft_Node_Number = 0; /* On commence à vérifier si l'on trouve le même nombre de noeuds en parcourant la liste de droite à gauche, puis de gauche à droite */ Node = Root->Head; while (Node) { LeftToRight_Node_Number++; Node = Node->Right; } Node = Root->Queue; while (Node) { RightToLeft_Node_Number++; Node = Node->Left; } /* Cas où tout est OK */ if (LeftToRight_Node_Number == Root->Node_Number && LeftToRight_Node_Number == RightToLeft_Node_Number) return; /* Cas où le nombre de noeuds n'a simplement pas été mis à jour au niveau de la racine */ if (LeftToRight_Node_Number == RightToLeft_Node_Number) { Root->Node_Number = LeftToRight_Node_Number; fprintf (Out, "\t- number of node has been corrected on structure %p\n", Root); (*Nb_Detected)++; (*Nb_Corrected)++; return; } /* Cas où le parcours de gauche à droite est plus complet : il manque un lien 'Left' */ if (LeftToRight_Node_Number > RightToLeft_Node_Number) { Node = Root->Head; while (Node) { if (Node->Right && Node->Right->Left != Node) { fprintf (Out, "\t- link 'Left' has been corrected on node %p of structure %p\n", Node->Right, Root); Node->Right->Left = Node; (*Nb_Detected)++; (*Nb_Corrected)++; } if (!Node->Right && Node != Root->Queue) { fprintf (Out, "\t- link 'Queue' has been corrected on structure %p\n", Root); Root->Queue = Node; (*Nb_Detected)++; (*Nb_Corrected)++; } Node = Node->Right; } if (Root->Node_Number != LeftToRight_Node_Number) { fprintf (Out, "\t- number of node has been corrected on structure %p\n", Root); Root->Node_Number = LeftToRight_Node_Number; (*Nb_Detected)++; (*Nb_Corrected)++; } return; } /* Cas où le parcours de droite à gauche est plus complet : il manque un lien 'Right' */ if (RightToLeft_Node_Number> LeftToRight_Node_Number) { Node = Root->Queue; while (Node) { if (Node->Left && Node->Left->Right != Node) { fprintf (Out, "\t- link 'Right' has been corrected on node %p of list %p\n", Node->Left, Root); Node->Left->Right = Node; (*Nb_Detected)++; (*Nb_Corrected)++; } if (!Node->Left && Node != Root->Head) { fprintf (Out, "\t- link 'Head' has been corrected on the structure root %p\n", Root); Root->Head = Node; (*Nb_Detected)++; (*Nb_Corrected)++; } Node = Node->Left; } if (Root->Node_Number != RightToLeft_Node_Number) { fprintf (Out, "\t- number of node has been corrected on structure %p\n", Root); Root->Node_Number = RightToLeft_Node_Number; (*Nb_Detected)++; (*Nb_Corrected)++; } } } /*------------------------------------------------------------------------------*/ /* Function de vérification des valeurs des noeuds d'une liste */ /*------------------------------------------------------------------------------*/ void ND_Value_Check ( NDT_Root * Root, int * Nb_Detected, int * Nb_Corrected, FILE * Out ) { NDT_Node * Node, * Next_Node; /* Chaque noeud sans valeur est purement et simplement supprimé de la liste */ ND_Node_First_Get_I (Root, &Node); while (Node) { ND_Node_Next_Get_I (Node, &Next_Node); if (!Node->Value) { fprintf (Out, "\t- node %p has been removed from structure %p because no value is attached to it\n", Node, Root); ND_Node_Remove (Node); Node = Next_Node; (*Nb_Detected)++; (*Nb_Corrected)++; } else if (ND_Address_Check (Node->Value) != NDS_OK) { fprintf (Out, "\t- node %p has been removed from structure %p because its value cannot be accessed\n", Node, Root); ND_Node_Remove (Node); Node = Next_Node; (*Nb_Detected)++; (*Nb_Corrected)++; } else ND_Node_Next_Get (Node, &Node); } } /*------------------------------------------------------------------------------*/ /* Function de vérification d'un arbre : */ /*------------------------------------------------------------------------------*/ void ND_Tree_Check ( NDT_Root * Root, int * Nb_Detected, int * Nb_Corrected, FILE * Out ) { /* On vérifie les liens entre les noeuds */ ND_Tree_Link_Check (Root, Nb_Detected, Nb_Corrected, Out); /* On vérifie les valeurs attachées aux noeuds */ ND_Value_Check (Root, Nb_Detected, Nb_Corrected, Out); /* On met à jour les informations statistiques de la racine */ Root->Max_Depth = ND_Tree_MaxDepth_Get (Root->Head); Root->Min_Depth = ND_Tree_MaxDepth_Get (Root->Head); } /*------------------------------------------------------------------------------*/ /* Function de vérification et correction des liens entre noeuds d'un arbre */ /*------------------------------------------------------------------------------*/ void ND_Tree_Link_Check ( NDT_Root * Root, int * Nb_Detected, int * Nb_Corrected, FILE * Out ) { /* On vérifie les liens 'Parent' et les liens 'Root' de chaque noeud */ if (Root->Head) { if (Root->Head->Root != Root) { Root->Head->Root = Root; fprintf (Out, "\t- link 'Root' has been corrected on node %p of structure %p\n", Root->Head, Root); (*Nb_Detected)++; (*Nb_Corrected)++; } ND_Tree_Link_Recursive_Check (Root->Head, Nb_Detected, Nb_Corrected, Out); } /* On vérifie si le lien 'Save' contient un noeud (cela signifie que la procédure ND_Node_Remove n'a pas été jusqu'à son terme). */ if (Root->Save) { NDT_Node * Node; /* On attache le noeud contenu dans 'Save' à l'arbre s'il n'existe pas déjà */ if (ND_Node_Find (Root, &Node, Root->Save->Value, NULL) != NDS_OK) { ND_Node_Add (Root, Root->Save); fprintf (Out, "\t- saved node %p has been restored to structure %p\n", Root->Save, Root); (*Nb_Detected)++; (*Nb_Corrected)++; } Root->Save = NULL; } } /*------------------------------ Recursive Kernel ------------------------------*/ void ND_Tree_Link_Recursive_Check ( NDT_Node * Node, int * Nb_Detected, int * Nb_Corrected, FILE * Out ) { if (Node->Left) { if (Node->Left->Root != Node->Root) { Node->Left->Root = Node->Root; fprintf (Out, "\t- link 'Root' has been corrected on node %p of structure %p\n", Node->Left, Node->Root); (*Nb_Detected)++; (*Nb_Corrected)++; } if (Node->Left->Parent != Node) { Node->Left->Parent = Node; fprintf (Out, "\t- link 'Parent' has been corrected on node %p of structure %p\n", Node->Left, Node->Root); (*Nb_Detected)++; (*Nb_Corrected)++; } /* Appel récursif */ ND_Tree_Link_Recursive_Check (Node->Left, Nb_Detected, Nb_Corrected, Out); } if (Node->Right) { if (Node->Right->Root != Node->Root) { Node->Right->Root = Node->Root; fprintf (Out, "\t- link 'Root' has been corrected on node %p of structure %p\n", Node->Right, Node->Root); (*Nb_Detected)++; (*Nb_Corrected)++; } if (Node->Right->Parent != Node) { Node->Right->Parent = Node; fprintf (Out, "\t- link 'Parent' has been corrected on node %p of structure %p\n", Node->Right, Node->Root); (*Nb_Detected)++; (*Nb_Corrected)++; } /* Appel récursif */ ND_Tree_Link_Recursive_Check (Node->Right, Nb_Detected, Nb_Corrected, Out); } } /*------------------------------------------------------------------------------*/ /* Vérifie qu'une adresse est valide */ /*------------------------------------------------------------------------------*/ NDT_Status ND_Address_Check ( void * Address ) { int test; Sig_Trapped = 0; /* On trappe les signaux SIGBUS et SIGSEGV */ signal (SIGBUS, ND_Signal_Trap); signal (SIGSEGV, ND_Signal_Trap); /* On tente d'accéder à l'adresse fournie */ test = *((int *)Address); sigrelse (SIGBUS); sigrelse (SIGSEGV); if (Sig_Trapped != 0) return NDS_KO; return NDS_OK; } /*------------------------------------------------------------------------------*/ /* Trap d'un signal */ /*------------------------------------------------------------------------------*/ void ND_Signal_Trap ( int Sig_Num ) { Sig_Trapped = Sig_Num; } /*------------------------------------------------------------------------------*/ /* Routine d'affichage d'un message d'erreur */ /*------------------------------------------------------------------------------*/ void ND_Error_Print ( void ) { if (ND_stderr) fprintf (ND_stderr, "%s\n", ND_Error_Msg); }