libnode/lib/libnode.c

2675 lines
96 KiB
C
Raw Normal View History

#include <libnode.h>
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<43>ation d'une nouvelle structure de donn<6E>es */
/*------------------------------------------------------------------------------*/
/* (O) Root: adresse d'un pointeur sur la racine de la nouvelle structure */
/* (I) Type: type de la structure.de donn<6E>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<6E>es utiles <20> l'allocateur */
/* (I) Own_Value : indique si la structure est propri<72>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<6E>es */
/*------------------------------------------------------------------------------*/
/* (O) Root: pointeur sur la racine de la structure de donn<6E>es <20> 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<6E>es */
/* - ordonnancement d'une liste non ordonn<6E>e */
/* - r<>quilibrage d'un arbre non auto-<2D>quilibr<62> */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de la structure de donn<6E>es <20> 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<6E>es et ex<65>cution d'une */
/* commande sur chacun d'eux */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de la structure de donn<6E>es <20> parcourir */
/* (I) Command : Commande <20> ex<65>cuter sur chaque noeud travers<72> */
/* (I) Data : pointeur de donn<6E>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<72>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<6E>es d'un type en un autre */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de la structure de donn<6E>es <20> 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<6E>es */
/*------------------------------------------------------------------------------*/
/* (I) Root: pointeur sur la racine de la structure de donn<6E>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<6E>es */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de la structure de donn<6E>es <20> 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<6C>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<63>es */
/* (O) Nb_Corrected : pointeur sur le nombre d'erreurs corrig<69>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<6F>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<6E>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<75>ration de la racine d'une structure */
/*------------------------------------------------------------------------------*/
/* (O) Root : adresse du pointeur sur la racine <20> r<>cup<75>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<75>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<75>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<75>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<75>ration du noeud pr<70>c<EFBFBD>dant */
/*------------------------------------------------------------------------------*/
/* (I) Node : pointeur sur le noeud dont on cherche le pr<70>c<EFBFBD>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 <20> une structure de donn<6E>es */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de la structure de donn<6E>es */
/* (I) Node : pointeur sur le noeud <20> 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<6E>es */
/*------------------------------------------------------------------------------*/
/* (I) Node: pointeur sur le noeud <20> 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<75>re l'adresse du lien entre le noeud <20> supprimer et son p<>re */
if (Node->Parent)
{
/* Cas g<>n<EFBFBD>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 <EFBFBD> supprimer dans un pointeur de
sauvegarde pour pouvoir le r<EFBFBD>cup<EFBFBD>rer au cas o<EFBFBD> la proc<EFBFBD>dure serait
interrompue (recovery).
*/
Root->Save = Left_Node;
/* On remplace le noeud supprim<69> 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<69> 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 <20> jour des informations de profondeur : trop co<63>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 <20> partir d'une valeur */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de l'abre */
/* (O) Node : adresse du pointeur sur le noeud <20> r<>cuperer */
/* (I) Value : pointeur sur la valeur <20> rechercher */
/* (I) Data : pointeur de donn<6E>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<6E>es */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de la structure de donn<6E>es */
/* (O) Value : adresse d'un pointeur sur la valeur <20> allouer */
/* (I) ... : arguments relatifs <20> l'allocation de la valeur */
/*------------------------------------------------------------------------------*/
NDT_Status ND_Value_Alloc_I ( NDT_Root * Root, void ** Value, ... )
{
NDT_Status rc;
va_list Args;
/* R<>cup<75>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 <20> une structure de donn<6E>es */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de la structure de donn<6E>es */
/* (I) Value : pointeur sur la valeur <20> ajouter <20> la structure de donn<6E>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 <20> une valeur donn<6E>e */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de la structure de donn<6E>es */
/* (I) Reference_Value : pointeur sur la valeur de r<>f<EFBFBD>rence */
/* (I) Removed_Value : adresse d'un pointeur sur la valeur supprim<69>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 <20> la valeur de r<>f<EFBFBD>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<6E>es */
/*------------------------------------------------------------------------------*/
/* (I) Root: pointeur sur la racine de la structure de donn<6E>es */
/* (I) Value: pointeur sur la valeur <20> 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<45>cution d'une fonction Manager dont le nom est pass<73> en param<61>tre */
/*------------------------------------------------------------------------------*/
/* (I) Function : nom de la fonction manager <20> ex<65>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<45>cution d'une fonction d'allocation dont le nom est pass<73> en param<61>tre */
/*------------------------------------------------------------------------------*/
/* (I) Function : nom de la fonction <20> ex<65>cuter */
/* (O) Ptr : adresse d'un pointeur sur la zone <20> allouer */
/* (I) Size : taille de la zone <20> allouer */
/* (I) Data : donn<6E>es utilisateur utiles <20> 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<45>cution d'une fonction de d<>sallocation dont nom est pass<73> en param<61>tre */
/*------------------------------------------------------------------------------*/
/* (I) Function : nom de la fonction <20> ex<65>cuter */
/* (I) Ptr : adresse de la zone <20> d<>sallouer */
/* (I) Data : donn<6E>es utilisateur utiles <20> 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<43>ation d'une nouvelle structure de donn<6E>es */
/*------------------------------------------------------------------------------*/
/* (O) Root: adresse d'un pointeur sur la racine de la nouvelle structure */
/* (I) Type: type de la structure.de donn<6E>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<6E>es utiles <20> l'allocateur */
/* (I) Own_Value : indique si la structure est propri<72>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<6E>es */
/*------------------------------------------------------------------------------*/
/* (O) Root: pointeur sur la racine de la structure de donn<6E>es <20> 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<6E>es */
/* - ordonnancement d'une liste non ordonn<6E>e */
/* - r<>quilibrage d'un arbre non auto-<2D>quilibr<62> */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de la structure de donn<6E>es <20> 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<6E>es et ex<65>cution d'une */
/* commande sur chacun d'eux */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de la structure de donn<6E>es <20> parcourir */
/* (I) Command : Commande <20> ex<65>cuter sur chaque noeud travers<72> */
/* (I) Data : pointeur de donn<6E>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<6E>es d'un type en un autre */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de la structure de donn<6E>es <20> 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<6E>es */
/*------------------------------------------------------------------------------*/
/* (I) Root: pointeur sur la racine de la structure de donn<6E>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<6E>es */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de la structure de donn<6E>es <20> 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<6C>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<63>es */
/* (O) Nb_Corrected : pointeur sur le nombre d'erreurs corrig<69>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<6E>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<75>ration de la racine d'une structure */
/*------------------------------------------------------------------------------*/
/* (O) Root : adresse du pointeur sur la racine <20> r<>cup<75>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<75>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<75>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<75>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<75>ration du noeud pr<70>c<EFBFBD>dant */
/*------------------------------------------------------------------------------*/
/* (I) Node : pointeur sur le noeud dont on cherche le pr<70>c<EFBFBD>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 <20> une structure de donn<6E>es */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de la structure de donn<6E>es */
/* (I) Node : pointeur sur le noeud <20> 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<6E>es */
/*------------------------------------------------------------------------------*/
/* (I) Node: pointeur sur le noeud <20> 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 <20> partir d'une valeur */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de l'abre */
/* (O) Node : adresse du pointeur sur le noeud <20> r<>cuperer */
/* (I) Value : pointeur sur la valeur <20> rechercher */
/* (I) Data : pointeur de donn<6E>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<6E>es */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de la structure de donn<6E>es */
/* (O) Value : adresse d'un pointeur sur la valeur <20> allouer */
/* (I) ... : arguments relatifs <20> 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<75>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 <20> une structure de donn<6E>es */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de la structure de donn<6E>es */
/* (I) Value : pointeur sur la valeur <20> ajouter <20> la structure de donn<6E>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 <20> une valeur donn<6E>e */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de la structure de donn<6E>es */
/* (I) Reference_Value : pointeur sur la valeur de r<>f<EFBFBD>rence */
/* (I) Removed_Value : adresse d'un pointeur sur la valeur supprim<69>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<6E>es */
/*------------------------------------------------------------------------------*/
/* (I) Root: pointeur sur la racine de la structure de donn<6E>es */
/* (I) Value: pointeur sur la valeur <20> 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<45>cution d'une fonction Manager dont le nom est pass<73> en param<61>tre */
/*------------------------------------------------------------------------------*/
/* (I) Function : nom de la fonction manager <20> ex<65>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<45>cution d'une fonction d'allocation dont le nom est pass<73> en param<61>tre */
/*------------------------------------------------------------------------------*/
/* (I) Function : nom de la fonction <20> ex<65>cuter */
/* (O) Ptr : adresse d'un pointeur sur la zone <20> allouer */
/* (I) Size : taille de la zone <20> allouer */
/* (I) Data : donn<6E>es utilisateur utiles <20> 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<45>cution d'une fonction de d<>sallocation dont nom est pass<73> en param<61>tre */
/*------------------------------------------------------------------------------*/
/* (I) Function : nom de la fonction <20> ex<65>cuter */
/* (I) Ptr : adresse de la zone <20> d<>sallouer */
/* (I) Data : donn<6E>es utilisateur utiles <20> 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 <20>t<EFBFBD> trouv<75>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 <20> 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<6E>e */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine <20> 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<6E>es */
/*------------------------------------------------------------------------------*/
/* (O) New_Root: adresse du pointeur sur la nouvelle racine */
/* (I) Type: type de la structure de donn<6E>es */
/* (I) Allocator: pointeur vers la fonction d'allocation */
/* (I) Desallocator: pointeur vers la fonction de d<>sallocation */
/* (I) Data : pointeur de donn<6E>es utiles <20> 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<6E>es est propri<72>taire de ses valeurs */
strcpy ((*Root)->Manager, "Default_Manager");
strcpy ((*Root)->Allocator, Allocator);
strcpy ((*Root)->Desallocator, Desallocator);
return NDS_OK;
}
/*------------------------------------------------------------------------------*/
/* Ajout d'un noeud <20> une liste cha<68>n<EFBFBD>e */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de la liste */
/* (I) New_Node : pointeur sur le noeud <20> ajouter */
/*------------------------------------------------------------------------------*/
NDT_Status ND_List_Node_Add ( NDT_Root * Root, NDT_Node * New_Node )
{
/* Ajout dans une liste tri<72>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<EFBFBD>e peut <EFBFBD>tre orient<EFBFBD>e de 2 mani<EFBFBD>res :
- FIFO : un noeud sera ins<EFBFBD>r<EFBFBD> APRES un noeud de m<EFBFBD>me valeur (par d<EFBFBD>faut)
- FILO : un noeud sera ins<EFBFBD>r<EFBFBD> AVANT un noeud de m<EFBFBD>me valeur
*/
if (ND_IS_FILO(Root))
{
/* Pour une liste tri<72>e orient<6E>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<6E>re avant le noeud courant si le nouveau noeud est de valeur inf<6E>rieure ou <20>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 <20>t<EFBFBD> ins<6E>r<EFBFBD> */
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<72>e orient<6E>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<6E>re apr<70>s le noeud courant si le nouveau noeud est de valeur strictement sup<75>rieure ou <20>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 <20>t<EFBFBD> ins<6E>r<EFBFBD> */
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 <20> une liste */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de la liste */
/* (I) Value : pointeur sur la valeur <20> 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 <20> un arbre binaire */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de l'arbre */
/* (I) Value : pointeur sur la valeur <20> 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 <20> rechercher */
/* (I) Data : pointeur de donn<6E>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<72>es, la recherche peut <20>tre optimis<69>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<EFBFBD> d<>pass<73> la valeur recherch<63>e */
return NULL;
case NDS_GREATER:
Node = Node->Right;
break;
}
}
}
else
{
/* Pour les listes non tri<72>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 <20> rechercher */
/* (I) Data : pointeur de donn<6E>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<75> */
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<74> apr<70>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<74> 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 <20> 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<68>n<EFBFBD>e */
/*------------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine du la structure <20> 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 <20> 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 <20> 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 <EFBFBD>ventuellement <EFBFBD> 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 <20> 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 <20> 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 <20> un arbre */
/*----------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de l'arbre */
/* (I) Node : pointeur sur le noeud <20> 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 <20> l'arbre */
New_Node->Parent = Parent_Node;
New_Node->Root = Root;
*Node = New_Node;
/* Mise <20> 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 <20> 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<6E>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<68>n<EFBFBD>e : */
/*----------------------------------------------------------------------------*/
/* (I) Root : pointeur sur la racine de la liste <20> 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 <20> 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 <20> 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<75>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<75>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<65>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<65>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 <EFBFBD> v<EFBFBD>rifier si l'on trouve le m<EFBFBD>me nombre de noeuds
en parcourant la liste de droite <EFBFBD> gauche, puis de gauche <EFBFBD> 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 <20>t<EFBFBD> mis <20> 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 <20> 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 <20> 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<69> 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<63>es aux noeuds */
ND_Value_Check (Root, Nb_Detected, Nb_Corrected, Out);
/* On met <20> 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<EFBFBD>rifie si le lien 'Save' contient un noeud (cela signifie
que la proc<EFBFBD>dure ND_Node_Remove n'a pas <EFBFBD>t<EFBFBD> jusqu'<EFBFBD> son terme).
*/
if (Root->Save)
{
NDT_Node * Node;
/* On attache le noeud contenu dans 'Save' <20> l'arbre s'il n'existe pas d<>j<EFBFBD> */
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<63>der <20> 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);
}