2675 lines
96 KiB
C
2675 lines
96 KiB
C
#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 <20> supprimer dans un pointeur de
|
||
sauvegarde pour pouvoir le r<>cup<75>rer au cas o<> la proc<6F>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<72>e peut <20>tre orient<6E>e de 2 mani<6E>res :
|
||
|
||
- FIFO : un noeud sera ins<6E>r<EFBFBD> APRES un noeud de m<>me valeur (par d<>faut)
|
||
- FILO : un noeud sera ins<6E>r<EFBFBD> AVANT un noeud de m<>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 <20>ventuellement <20> 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 <20> v<>rifier si l'on trouve le m<>me nombre de noeuds
|
||
en parcourant la liste de droite <20> gauche, puis de gauche <20> 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<>rifie si le lien 'Save' contient un noeud (cela signifie
|
||
que la proc<6F>dure ND_Node_Remove n'a pas <20>t<EFBFBD> jusqu'<27> 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);
|
||
}
|