
// This file is part of the Herezh++ application.
//
// The finite element software Herezh++ is dedicated to the field
// of mechanics for large transformations of solid structures.
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
//
// Herezh++ is distributed under GPL 3 license ou ultérieure.
//
// Copyright (C) 1997-2022 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL  : gerardrio56@free.fr
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.

/************************************************************************
 *                                                                      *
 *     DATE:        23/01/97                                            *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *     BUT:         definir l'ensemble des outils relatifs aux          *
 *                  operations basiques de lecture dans le fichier      *
 *                  d'entree                                            *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *                                                                      *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                      *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                      *
 *                                                                $     *
 *                                                                      *
 ************************************************************************/

#ifndef UtiLecture_H
#define UtiLecture_H

#include <fstream>
//#include "Debug.h"

#ifndef ENLINUX_STREAM
  #include <sstream> // pour le flot en memoire centrale
#else  
  #include <strstream> // pour le flot en memoire centrale
#endif
#include <string.h>
#include <string>
#include <list>
#include "Sortie.h"
#include <map>
#ifdef UTILISATION_MPI
  #include "mpi.h"
  #include <boost/mpi/environment.hpp>
  #include <boost/mpi/communicator.hpp>
  #include <boost/serialization/string.hpp>
  #include <boost/mpi.hpp>
  namespace mpi = boost::mpi;
#endif
        using namespace std;

/** @defgroup Goupe_relatif_aux_entrees_sorties
*
*     BUT:   groupe relatif aux méthodes de lectures et d'écritures sur fichiers, écrans
*
*
* \author    Gérard Rio
* \version   1.0
* \date       23/01/97
* \brief       groupe relatif aux méthodes de lectures et d'écritures sur fichiers, écrans
*
*/

/// @addtogroup Goupe_relatif_aux_entrees_sorties
///  @{
///


class UtilLecture
{
  public :
    // VARIABLES PUBLIQUES : 
    
     // --------------- cas du fichier principal .info et dérivés ------------------
       
     char* tablcar ;     //  buffer contenant les infos utiles courantes
     const int longueur; // longueur maxi du tableau de travail
     class ErrNouvelleDonnee  // gestion d'exception pour nouvel_Enreg
     // =1 lecture OK on est arrive a la fin de tous les  fichiers, < 0 probleme de lecture
      { public :
         int lecture;
         ErrNouvelleDonnee (int entrees) {lecture = entrees;} ;  // CONSTRUCTEURS
         ~ErrNouvelleDonnee () {};// DESTRUCTEUR :
       };
     
     // Flot d'entree      
     // pour la lecture en memoire centrale, permet la conversion de type
     // dans le cas de lecture de tableau de character il faut tout
     // d'abord preciser le nombre de carractere a lire avec la fonction
     // membre width(nb de crarac) 
     // a utiliser pour la lecture d'entier, de reelle etc

     #ifndef ENLINUX_STREAM
        istringstream * entree;
        ostringstream * sortie;
     #else
        istrstream * entree;
        ostrstream * sortie;
     #endif
                 
     // retour du fichier dans lequel on écrit les commandes .info
     ofstream * Commande_pointInfo() {return ptrcommandefich;};
     // retour du fichier dans lequel on écrit le schema XML
     ofstream * ShemaXML() {return ptrschemaXMLfich;};
 
     // fichier de recopie des informations lue par le programme
     ofstream * copie;
 
     // --------------- fin du cas du fichier principal .info et dérivés ------------------
     // --------------- cas du fichier de commandes de visualisation ------------------
       
     char* tablcarCVisu ;     //  buffer contenant les infos utiles courantes
     class ErrNouvelleDonneeCVisu  // gestion d'exception pour nouvel_EnregCVisu
     // =1 lecture OK on est arrive a la fin de tous les  fichiers, < 0 probleme de lecture
     // = 0 probleme d'ouverture de fichier en lecture
     // = 10 probleme en ouverture pour l'écriture
       { public :
          int lecture;
          ErrNouvelleDonneeCVisu (int entrees) {lecture = entrees;} ;  // CONSTRUCTEURS
          ~ErrNouvelleDonneeCVisu () {};// DESTRUCTEUR :
       };
      
     // Flot d'entree      
     // pour la lecture en memoire centrale, permet la conversion de type
     // dans le cas de lecture de tableau de character il faut tout
     // d'abord preciser le nombre de carractere a lire avec la fonction
     // membre width(nb de crarac) 
     // a utiliser pour la lecture d'entier, de reelle etc

     #ifndef ENLINUX_STREAM
        istringstream * entCVisu;
     #else
        istrstream * entCVisu;
     #endif
                  
       // --------------- fin du cas du fichier de commandes de visualisation ------------------
          
    // CONSTRUCTEURS :
     // ++ le constructeur officiel ++
     // il y a passage éventuelle d'argument : argc=le nombre d'argument
     // argv : donne un tableau correspondant de mots clés
     // ---> lecture de la racine du nom du fichier princial
     UtilLecture (int argc=0, const char * argv[] = NULL) ;  
    // DESTRUCTEUR :
     ~UtilLecture () ;
       
    // METHODES PUBLIQUES :
     // ouverture du fichier de lecture. Les infos interressantes se trouvent 
     // dans la chaine pointee par tablcar : 
     //     
     // ou cela peut-être l'ouverture d'un nouveau fichier d'écriture de commande
     // ceci en fonction des réponses de l'utilisateur lors de la création de l'instance
     // UtilLecture. Dans ce cas le fichier .info n'est disponible qu'en écriture !!! 
     // aucune des fonctions de lecture sont activable :
     //     
     // en retour idem = Lec_ent_info()
     int OuvrirFichier ();
 
     // raffraichir le dernier fichier de lecture .info en cours
     // il y a fermeture puis ouverture au même endroit du fichier  .info
     void Raffraichir_pointInfo();
     
     // fermeture du fichier .info qui est en création donc en écriture
     //(ce n'est pas celui qui serait en lecture !!),
     void fermeture_pointInfo();
     // fermeture du fichier SchemaXML
     void fermetureSchemaXML();
      
     // ouverture d'un fichier de copie des infos lue par le programme 
     // utilise pour verifier la bonne lecture
     void OuvrirCopie();
     // fermeture du fichier
     void FermerCopie();
       
     // redirection du flot d'entré vers un nouveau fichier
     // nevezFich pointe sur le nom du nouveau fichier
     void NouveauFichier( char* nevezFich)  ;
    
     // fermeture du flot actuel, et retour sur le flot précédent
     // indic est un indicateur de retour
     // = 0 il reste encore des fichiers intermédiaires ouverts
     // =1 on se situe sur le flot primaire
     void FermetureFichier(int& indic); 

     // lecture d'une nouvelle ligne de donnee utilisable pour les donnees
     // lorsqu'apparait le signe < dans le fichier d'entree il y a automatiquement
     // ouverture d'un nouveau fichier
     void NouvelleDonnee();

     // idem mais sans ouverture de fichier automatique
     // le signe < est conservé dans la ligne
     void NouvelleDonneeSansInf();
 
     // Retour du flot au debut de l'enregistrement
     // a utiliser s'il y a eu une erreur de lecture sur le flot
     // mais que l'on connait l'erreur et l'on veut relire
     // par exemple : on essaie un string -> erreur, alors c'est un reel
     // on veut relire un reel, on utilise FlotDebutDonnee() avant
     void FlotDebutDonnee(); 

     // gestion d'erreur d'entree
     // ecriture d'un message d'erreur du a une mauvaise lecture
     // le programme ecrit la chaine transmise puis le contenu des buffers
     void ErreurLecture(UtilLecture::ErrNouvelleDonnee,char*); 
 
     // ecriture d'un message et du contenu des buffers courant
     void MessageBuffer(string);

     // affichage sur la sortie standard de l'enregistrement courant
     void AfficheEnreg () const ;
 
     // retourne la racine du nom du fichier principal
     char* RacineNom() { return (char*)nomRacine.c_str() ;}; 
     
     // indique de type d'entrée des données ou de sortie
     // dans le cas ou c'est une création de fichier de commande
     // = -11 indique que l'on cré un fichier de commande .info
     // = -12 création du fichier schema XML
     // = 0 indique que ce sera via le fichier info
     // = 1 ce sera via un fichier base-info
     // = 2 ce sera via un serveur base-info
     int Lec_ent_info () {return lec_ent_info;}; 
       
  // -------------- cas de la base d'info ----------------
     //fichier base_info dans lequel sont lus les enregistrements
     // dans le  cas ou celui-ci n'est pas ouvert il y a ouverture
#ifndef UTILISATION_MPI
     ifstream * Ent_BI() ;
     // et pour l'écriture
     // dans le  cas ou celui-ci n'est pas ouvert il y a ouverture
     ofstream * Sort_BI() ;
     const streampos position_debut_fichier=(ios::beg);
#else
     MPI_File * Ent_BI(); // cas MPI
     MPI_File * Sort_BI(); //  "  "
     const MPI_Offset position_debut_fichier=0;
#endif
     // ouverture du fichier base_info après le .info  dans le cas d'un restart par exemple
     // dans le cas ou le fichier est déjà ouvert en lecture ou écriture dans le type demandé
     // il n'y a aucune action
     // a priori le fichier est ouvert en lecture  : lecture
     // mais il peut également être en écriture : ecriture
     void Ouverture_base_info(string type_entree="lecture");
     // fermeture du fichier base_info 
     void Fermeture_base_info();
     // positionnement dans le fichier d'entrès au niveau d'un numéro d'incrément
     // si l'on ne trouve pas le numéro on renvoi un indicateur à false
     bool Positionnement_base_info(int inc_voulu);
#ifndef UTILISATION_MPI
     // positionnement à un offset donné, en écriture
     void Sort_BI_Positionnement_offset(const streampos&  posi) {Sort_BI()->seekp(posi);};
#else
     // positionnement à un offset donné, en écriture
     void Sort_BI_Positionnement_offset(const MPI_Offset&  posi) {MPI_File_seek(sort_MPI_BI, posi, MPI_SEEK_SET);};
#endif
     // enregistrement de la position
     // normalement correspond à un début d'incrément
     void Enregistrement_position_increment_base_info(int incr);
     // renvoi tous les incréments actuellements enregistré
     list <int>  Liste_increment(); 
     
  // -------------- cas des temps de calcul ----------------
     // ouverture du fichier spécifique des temps cpu
     void Ouverture_fichier_temps_cpu();
     // fermeture du fichier des temps cpu
     void Fermeture_fichier_temps_cpu();
     // récupération du fichier des temps cpu
     ofstream & Sort_temps_cpu() { return *sort__temps_cpu;};

  // -------------- cas de la visualisation ----------------
    //        +++ vrml ++++
     // ouverture du fichier principal vrml
     void Ouverture_fichier_principal_vrml();
     // fermeture du fichier principal vrml
     void Fermeture_fichier_principal_vrml();
     // récupération du fichier principal vrml
     ofstream & Sort_princ_vrml() { return *sort_princ_vrml;};
     // ouverture du fichier de légendes vrml
     void Ouverture_fichier_legende_vrml();
     // fermeture du fichier légendes vrml
     void Fermeture_fichier_legende_vrml();
     // récupération du fichier légendes vrml
     ofstream & Sort_legende_vrml() { return *sort_legende_vrml;};
     // existance
     bool Existe_princ_vrml() const {return (sort_princ_vrml==NULL ? false : true); };
    //        +++ maple ++++
     // ouverture du fichier maple
     void Ouverture_fichier_principal_maple();
     // fermeture du fichier principal maple
     void Fermeture_fichier_principal_maple();
     // récupération du fichier principal maple
     ofstream & Sort_princ_maple() { return *sort_princ_maple;};
     // existance
     bool Existe_princ_maple() const {return (sort_princ_maple==NULL ? false : true); };
    //        +++ geomview ++++
     // ouverture du fichier principal geomview
     void Ouverture_fichier_principal_geomview();
     // fermeture du fichier principal geomview
     void Fermeture_fichier_principal_geomview();
     // récupération du fichier principal geomview
     ofstream & Sort_princ_geomview() { return *sort_princ_geomview;};
     // ouverture du fichier de légendes geomview
     void Ouverture_fichier_legende_geomview();
     // fermeture du fichier légendes geomview
     void Fermeture_fichier_legende_geomview();
     // récupération du fichier légendes geomview
     ofstream & Sort_legende_geomview() { return *sort_legende_geomview;};
     // existance
     bool Existe_princ_geomview() const {return (sort_princ_geomview==NULL ? false : true); };
     bool Existe_legende_geomview() const {return (sort_legende_geomview==NULL ? false : true); };
    //        +++ Gid ++++
     // ouverture du fichier pour le maillage initial Gid
     void Ouverture_fichier_initial_Gid();
     // fermeture du fichier maillage initial Gid
     void Fermeture_fichier_initial_Gid();
     // récupération du fichier maillage initial Gid
     ofstream & Sort_initial_Gid() { return *sort_initial_Gid;};
     // ouverture du fichier résultat Gid
     void Ouverture_fichier_resultat_Gid();
     // fermeture du fichier résultat Gid
     void Fermeture_fichier_resultat_Gid();
     // récupération du fichier résultats Gid
     ofstream & Sort_resultat_Gid() { return *sort_resultat_Gid;};
     // existance
     bool Existe_initial_Gid() const {return (sort_initial_Gid==NULL ? false : true); };
     bool Existe_resultat_Gid() const {return (sort_resultat_Gid==NULL ? false : true); };

    //        +++ Gmsh ++++
     // ouverture du fichier pour le maillage initial Gmsh
     void Ouverture_fichier_initial_Gmsh();
     // fermeture du fichier maillage initial Gmsh
     void Fermeture_fichier_initial_Gmsh();
     // récupération du fichier maillage initial Gmsh
     ofstream & Sort_initial_Gmsh() { return *sort_initial_Gmsh;};
     // création du répertoire contenant tous les fichiers résultats
     void CreationRepertoireResultat();
     // ouverture d'un fichier résultat Gmsh, comprenant un nom particulier
     // si le fichier n'existe pas -> création
     void Ouverture_fichier_resultat_Gmsh(const string& nom);
     // ouverture d'un ensemble de fichiers: ces fichiers seront ensuite accessibles
     // si un des fichiers n'existe pas -> création
     void Ouverture_fichier_resultat_Gmsh(const list <string>& list_nom);
     // récupération de la liste de noms de base qui servent pour la création des
     // fichiers de base: cette liste = la somme des noms passés en paramètre via les
     // méthode Ouverture_fichier_resultat_Gmsh et Ouverture_fichier_resultat_Gmsh
     // chaque nom peut ensuite être utilisé dans les méthodes d'accès, ouverture, fermeture
     const list <string>& Noms_base_fichiers_gmsh() const { return noms_base_fichiers_gmsh;};
     
     // fermeture d'un  fichier résultat Gmsh 
     void Fermeture_fichier_resultat_Gmsh(const string& nom);
     // fermeture de tous les fichiers résultat
     void Fermeture_TousLesFichiersResultats_Gmsh();
     // récupération d'un fichier résultats Gmsh
     ofstream & Sort_resultat_Gmsh(const string& nom); 
     // existance
     bool Existe_initial_Gmsh() const {return (sort_initial_Gmsh==NULL ? false : true); };
     // pour tester l'existance d'un fichier resultat on utilise la liste Noms_base_fichiers_gmsh()

     // ------------ automatisation de la visualisation ------
     // ouverture du fichier CommandeVisu s'il est déjà ouvert on ne fait rien
     // a priori le fichier est ouvert en lecture  : type_entree = "lecture"
     // mais il peut également être en écriture : type_entree = "ecriture"
     void Ouverture_CommandeVisu(string type_entree);
     // fermeture du fichier CommandeVisu 
     void Fermeture_CommandeVisu();
     // changement du nom de fichier .CVisu
     // entraîne la fermeture du fichier en cours, en lecture et en écriture
     // il n'y a pas de vérification à ce niveau d'existence éventuelle
     // car on ne sait pas ce que l'on veut en faire
     // si la chaine de caractère passée en paramètre est non nulle on l'utilise
     // sinon on passe en interactif et on demande le nom de la chaine
     void Changement_NomCVisu(string nouveauNomCvisu);
     //fichier CommandeVisu dans lequel sont lus les enregistrements
     // uniquement  l'écriture est à accés directe
     ofstream * Sort_CommandeVisu();         
     // lecture d'une nouvelle ligne de donnee utilisable pour l'entree de donnee
     // dans le fichier de commande de visualisation (idem NouvelleDonnee mais en plus simple
     // car il n'y a pas de fichier inclus) 
     void NouvelleDonneeCVisu();
     // recherche dans le fichier de commande la chaine de caractère passée en paramètre
     // retour false: si on ne trouve pas la chaine
     // retour true: si on la trouve, et dans ce cas le pointeur courant du fichier est 
     //              positionné sur la ligne de la chaine
     bool PositionEtExisteCVisu(const string chaine);
	  
     //------------ utilitaire de lecture d'un parametre précédé d'un mot clé, avec une restriction
     // sur les valeurs
     // val_defaut: si la grandeur n'est pas lue, elle est mise par défaut = val_defaut
     // nom_class_methode: le nom de la methode qui appel l'utilitaire -> sortie dans le  message si pb
     // min max : les bornes entre lesquelles doit se trouver le parametre lue sinon -> génération d'une erreur et arrêt
     //           si max < min alors la condition n'est pas prise en compte
     // mot_cle : mot_cle devant précéder le parametre
     // parametre: le parametre à lire
     // retourne un boolean: indique si oui ou non il y a eu lecture
     bool Lecture_un_parametre_int(int val_defaut,const string& nom_class_methode
									       ,int min, int max, string& mot_cle, int& parametre ) const;
     // idem pour un double
     bool Lecture_un_parametre_double(double val_defaut,const string& nom_class_methode
									             ,double min, double max,const string& mot_cle, double& parametre ) const;
     // lecture et passage d'un mot clé: il y a simplement vérification que c'est le bon mot clé qui est lue
     // ramène si oui ou non le mot clé à été lue
     bool Lecture_et_verif_mot_cle(const string& nom_class_methode,const string& mot_cle) const;
     // idem pour un mot clé et un string: nom
     bool Lecture_mot_cle_et_string(const string& nom_class_methode,const string& mot_cle,string& nom) const;
 
     //------------- utilitaires de lecture d'une grandeurs qui peut-être une constante utilisateur ---
//     int Lect_avec_const_int_utilisateur()const;
     double lect_avec_const_double_utilisateur(string erreur) const;
     
     // modification interactive d'une constante utilisateur
     // la constante doit déjà exister
     static void Modif_interactive_constante_utilisateur();


     // ----------- définition de conteneurs à usage interne -----------
     // cependant elles ne peuvent pas être déclaré en protégé ??
     //	protected :
//private : 
     // définition de type particulier
     // def d'un maillon de liste chainee pour memoriser les differentes ouverture
     // de fichier
     class PointFich 
        { public :
           PointFich* t1;     // adresse du maillon precedent
           string nom;        // nom du fichier
           ifstream * sauvePtr; // sauvegarde de pointeur de fichier
           int numLigne; // numero de la ligne actuellement lue
           PointFich ( ) : nom(0),numLigne(0),t1(NULL),sauvePtr(NULL) {}; // défaut, ne doit pas être utilisé
           // constructeur utile:
           PointFich ( PointFich* x1,ifstream * x2,string n) : nom(n),numLigne(0),t1(x1),sauvePtr(x2) {};
           // constructeur de copie
           PointFich (const PointFich& a) : nom(a.nom),numLigne(a.numLigne),t1(a.t1),sauvePtr(a.sauvePtr) {};
           ~PointFich () {};
           // operateur =
           PointFich& operator= (const PointFich & a) {nom=a.nom;numLigne=a.numLigne;t1=a.t1;sauvePtr=a.sauvePtr;return *this;};
        };   
     // gestion d'exception pour nouvel_Enreg
      class ErrNouvelEnreg  
     // =0 lecture OK, sinon =1 -> fin de fichier, < 0 probleme de lecture
         { public :
            int lecture;   
            ErrNouvelEnreg (int entrees) {lecture = entrees;} ;  // CONSTRUCTEURS 
            ~ErrNouvelEnreg () {};// DESTRUCTEUR :
          };  
     // def d'une position d'incrément dans le fichier base_info
     class Position_BI 
        { 
          // surcharge de l'operator de lecture
          friend istream & operator >> (istream & entree, Position_BI& a);  
          // surcharge de l'operator d'ecriture
          friend ostream & operator << (ostream & sort, const Position_BI& a);
          
          public :
   #ifndef UTILISATION_MPI
           Position_BI(streampos  posi=(ios::beg), int num = 0) :  // constructeur
   #else
           Position_BI(MPI_Offset  posi=0, int num = 0) :  // constructeur
   #endif
             position (posi), num_incr(num)
               {};
           ~Position_BI() {}; // destructeur
           Position_BI(const Position_BI& a) : // constructeur de copie
             position (a.position),num_incr(a.num_incr)
               {}; 
           // surcharge des operateurs : ce qui est testé c'est le numéro d'incrément
           bool operator == ( const Position_BI& a) const
             {if (a.num_incr == this->num_incr) return true; else return false;};
           bool operator > ( const Position_BI& a) const
             { return (this->num_incr > a.num_incr);};
           bool operator < ( const Position_BI& a) const
             { return (this->num_incr < a.num_incr);};
         
           Position_BI& operator = (const  Position_BI& a)
             {position = a.position; num_incr = a.num_incr;return *this;}; 
           bool operator != (const  Position_BI& a)
             { return !(*this == a);};
           // données
   #ifndef UTILISATION_MPI
           streampos position; // position dans le fichier
   #else
           MPI_Offset position;
   #endif
           int       num_incr; // numéro de l'incrément
        };   
     // gestion d'exception pour nouvel_EnregCVisu
      class ErrNouvelEnregCVisu  
     // =0 lecture OK, sinon =1 -> fin de fichier, < 0 probleme de lecture  
        { public :
           int lecture;   
           ErrNouvelEnregCVisu (int entrees) {lecture = entrees;} ;  // CONSTRUCTEURS 
           ~ErrNouvelEnregCVisu () {};// DESTRUCTEUR :
        };
        
      // retour de l'offset du début de l'incrément s'il existe
      // retour d'un nombre négatif s'il n'existe pas
 #ifndef UTILISATION_MPI
      streampos  OffsetPosition(int incr);
 #else
      MPI_Offset  OffsetPosition(int incr);
 #endif

    // VARIABLES PROTEGEES :
    private : 
      
      char*  pteurnom;  // pointeur sur la racine du nom du fichier principal
      string nomRacine; // racine du nom du fichier principal
      ifstream * ptrfich ; //fichier dans lequel sont lus les enregistrements
      ofstream *  ptrcommandefich;// fichier dans lequel on écrit les commandes .info
      ofstream *  ptrschemaXMLfich;// fichier dans lequel on écrit le schema XML
      char* tableau ;  // le tableau de travail intermediaire 
		    char* tabMultiLignes; // stockage intermédiaire de plusieurs lignes
      string nomCourant; // nom du fichier courant ouvert en lecture
      int lec_ent_info; // type d'entrée des données
         // = 0 indique que ce sera via le fichier info
         // = 1 ce sera via un fichier base-info
         // = 2 ce sera via un serveur base-info
         // = -11 création d'un fichier de commande
         // = -12 création du schema XML
    #ifndef UTILISATION_MPI
      fstream * ent_BI ; //fichier base_info dans lequel sont lus les enregistrements
      fstream * sort_BI ; //fichier base_info de sauvegarde
      fstream * ent_PI ; //fichier  de la liste des pointeurs d'incréments de base info
      fstream * sort_PI ; //  "   " 
    #else
      MPI_File   ent_MPI_BI ; // pointeur fichier commun
      MPI_File   sort_MPI_BI ; //  "  "
      int  taille_buffer_Nouvelle_enreg_MPI; // la taille du buffer pour chaque enreg
      char * buffer_MPI; // le tableau du buffer associé
      MPI_Offset offset_Nouvelle_enreg_MPI; //l'offset actuel du buffer lue par Nouvelle_enreg_MPI
      int lecture_MPI_BI_en_cours; // " " =0 le fichier n'est pas ouvert, =1 le buffer n'est pas encore rempli
                                   // = 2 la lecture est en cours et le buffer est rempli
      int taille_actuelle_buffer; // " "
      int dernier_posi_dans_buffer; // " "
      
      MPI_File   ent_MPI_PI ; // pointeur fichier liste des pointeurs d'incréments de base info
      MPI_File   sort_MPI_PI ; // "   "
      //, num du cpu en cours dans les opérations
      int num_cpu_en_cours_BI; // d'i/o sur .BI et .PI
    #endif
          // -------cas des temps de calcul ----------------
      ofstream * sort__temps_cpu;
          // ------ pour la visualisation -----
      ofstream * sort_princ_vrml; // fichier principal vrml
      ofstream * sort_legende_vrml; // fichier de legendes vrml
      ofstream * sort_princ_maple; // fichier principal maple
      ofstream * sort_princ_geomview; // fichier principal geomview
      ofstream * sort_legende_geomview; // fichier de legendes geomview
      ofstream * sort_initial_Gid; // fichier maillage initial pour Gid
      ofstream * sort_resultat_Gid; // fichier des résultats pour Gid
      ofstream * sort_initial_Gmsh; // fichier maillage initial pour Gmsh
      map < string, ofstream * , std::less <string> > sort_resultat_Gmsh;
      list <string> noms_base_fichiers_gmsh; // la liste des clés dans la map
        // on double l'info, mais cela permet de récupérer la liste indépendamment de la map
          // ------ pour l'automatisation de l'interactif ---------
      fstream * sort_CommandeVisu; // écriture des parametres de visualisation
      fstream * ent_CommandeVisu;  // lecture des parametres de visualisation
      char* tableauCVisu ;  // le tableau de travail intermediaire 
      char* ptnomCVisu; // le pointeur de nom pour le CVisu
      string nomRacineCVisu; // racine du nom pour le CVisu
      
      int dernier_increment_lu;  // variable de travail pour Increment_suivant_base_info
      
      // liste des posistions déjà investiguées dans le fichier .base_info
      list <Position_BI> liste_posi_BI;  
      // maillon courant des fichiers ouverts via .info
      PointFich*   maille1;
      
    
    // METHODES PROTEGEES :
    
      void  Nouvel_enreg () ; // lecture d'un nouvelle enregistrement 
                       // dans le fichier courant
      void  Nouvel_enregCvisu () ; // lecture d'un nouvelle enregistrement 
                       // dans le fichier de commande de visualisation
      // ouverture du fichier CommandeVisu dans lequel sont lus les enregistrements
      ifstream * Ent_CommandeVisu(); 
      // cherche l'apparition d'une chaine de caractere -> pas bon a priori
      void Cherche(const char *); 
      // entrée par argument au niveau de la construction de l'objet UtilLecture
      // dans le cas où il y a eu un pb lec_ent_info=-100, et rien n'est initialisé
      bool EntreeParArgument(int argc, const char * argv[]);       
      // entrée interactive au niveau de la construction de l'objet UtilLecture
      // dans le cas où il y a eu un pb lec_ent_info=-100, et rien n'est initialisé
      void EntreeInteractive(string& ancien,bool& ouverture_ancien);
      
      // positionnement dans le fichier d'entrès au niveau du numéro d'incrément suivant
      // si l'on ne trouve pas de numéro on renvoi un indicateur à false
      // la méthode renvoie également la position du début de l'incrément
      // et le numéro trouvé d'incrément
      // il s'agit d'une méthode interne utilisée uniquement par la classe
   #ifndef UTILISATION_MPI
      bool Increment_suivant_base_info(streampos& debut_increment,int& inc_lu);
   #else
      // et en MPI par proc 0, on fait donc des appels non collectifs à Nouvelle_enreg_MPI_BI
      bool Increment_suivant_base_info(MPI_Offset& debut_increment,int& inc_lu);

      // ramène un nouvel enregistrement dans le buffer passé en paramètre
      // ramène true tant que l'on n'a pas atteind la fin de fichier
      // collectif: indique si on veut une utilisation collective ou pas
      // en sortie posi_suivant: qui indique l'offset du prochain charactère qu'on voudrait lire
      // important: le pointeur de fichier en sortie n'est pas posi_suivant, il suit en fait
      // la lecture d'un gros buffer interne, du coup si on veut une nouvelle lecture
      // en dehors de Nouvelle_enreg_MPI_BI, il faut au paravent se positionner sur posi_suivant
      bool Nouvelle_enreg_MPI_BI(MPI_File * file,string & buf,bool collectif,MPI_Offset& posi_suivant);
   #endif
                        
    
 };
 /// @}  // end of group

#endif  
