TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Entree.cpp
1/****************************************************************************
2* Copyright (c) 2026, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#include <Entree.h>
17#include <Objet_U.h>
18#include <Nom.h>
19#include <errno.h>
20#include <fstream>
21
22using std::ifstream;
23
26 diffuse_(true),
27 istream_(nullptr)
28{
29}
30
31Entree::Entree(istream& is) : Entree()
32{
33 istream_ = new istream(is.rdbuf());
34}
35
37{
38 istream_ = new istream(is.get_istream().rdbuf());
39}
40
42{
43 return *istream_;
44}
45
46const istream& Entree::get_istream() const
47{
48 return *istream_;
49}
50void Entree::set_istream(istream* is)
51{
52 istream_ = is;
53}
54
56{
57 (*f)(*this);
58 return *this;
59}
60Entree& Entree::operator >>(istream& (*f)(istream&))
62 (*f)(*istream_);
63 return *this;
64}
65Entree& Entree::operator >>(ios& (*f)(ios&))
66{
67 (*f)(*istream_);
68 return *this;
69}
71// Operateurs d'affectation
73{
74 if(istream_)
75 delete istream_;
76 istream_ = new istream(is.rdbuf());
77 return *this;
78}
82 if(istream_)
83 delete istream_;
84 istream_ = new istream(is.get_istream().rdbuf());
85 return *this;
86}
87
88/*! @brief Lecture d'une chaine dans ostream_ bufsize est la taille du buffer alloue pour ob (y compris
89 *
90 * le caractere 0 final).
91 * La chaine contient toujours un 0 meme en cas d'echec.
92 * La methode renvoie 1 si la lecture est bonne, 0 sinon.
93 * Si le buffer est trop petit, pour l'instant on fait exit() mais
94 * par la suite on pourra tester: si strlen(ob)==bufsize-1, alors
95 * refaire lire() jusqu'a arriver au bout. Si le lire() suivant
96 * renvoie une chaine de longueur nulle, cela signifie que la taille de la
97 * chaine etait exactement bufsize-1.
98 * Attention: le comportement est different en binaire et en ascii.
99 * En binaire, on lit la chaine jusqu'au prochain '\0'.
100 * En ascii, on lit la chaine jusqu'au prochain separateur (espace, tab, fin ligne)
101 *
102 */
103int Entree::get(char* ob, std::streamsize bufsize)
104{
105 assert(istream_!=0);
106 assert(bufsize > 0);
107 ob[bufsize-1] = 1;
108 if(bin_)
109 {
110 // En binaire, on lit jusqu'au prochain caractere 0
111 // (y compris espaces, retours a la ligne etc)
112 std::streamsize i;
113 for (i = 0; i < bufsize-1; i++)
114 {
115 (*istream_).read(ob+i, sizeof(char));
116 if (!error_handle(istream_->fail()))
117 ob[i] = 0;
118 if (ob[i] == 0)
119 break;
120 }
121 ob[i] = 0;
122 }
123 else
124 {
125 // Solution C++20 : utiliser std::string puis copier
126 std::string temp;
127 (*istream_) >> temp;
128 if (!error_handle(istream_->fail()))
129 {
130 ob[0] = 0;
131 }
132 else
133 {
134 std::streamsize len = std::min(static_cast<std::streamsize>(temp.size()), bufsize - 1);
135 std::memcpy(ob, temp.c_str(), len);
136 ob[len] = '\0';
137 }
138 }
139 if (ob[bufsize-1] == 0)
140 {
141 // Note Benoit Mathieu:
142 // Si on a rempli le buffer jusqu'au bout, c'est qu'il est probablement
143 // trop petit. Lire la suite est dangereux car en ascii on ne sait pas
144 // si on a pu lire pile poil la chaine (donc c'est ok), ou si la chaine
145 // n'a pas ete lue en int. Il faut tester tres serieusement la stl et
146 // ca depend sans doute de l'implementation. Donc, si le buffer est plein,
147 // on plante le code et tant pis.
148 Cerr << "Error in Entree::lire(char* ob, int bufsize) : buffer too small" << finl;
150 }
151 return (!istream_->fail());
152}
153
154void error_convert(const char * s, const char * type)
155{
156 Cerr << "Error converting a string to type " << type << " : string = " << s << finl;
158}
159
160/*! @brief methode de conversion
161 *
162 */
163void convert_to(const char *s, int& ob)
164{
165 errno = 0;
166 char * errorptr = 0;
167 ob = (int)strtol(s, &errorptr, 0 /* base 10 par defaut */);
168 if (errno || *errorptr != 0) error_convert(s,"int");
169}
170
171void convert_to(const char *s, long& ob)
172{
173 errno = 0;
174 char * errorptr = 0;
175 ob = strtol(s, &errorptr, 0 /* base 10 par defaut */);
176 if (errno || *errorptr != 0) error_convert(s,"long");
177}
178
179void convert_to(const char *s, long long& ob)
180{
181 errno = 0;
182 char * errorptr = 0;
183#ifdef HPPA_11 /* NO_PROCESS */
184 ob = strtol(s, &errorptr, 0 /* base 10 par defaut */);
185#else /* NO_PROCESS */
186#ifdef MICROSOFT
187 ob = _strtoi64(s, &errorptr, 0 /* base 10 par defaut */);
188#else
189 ob = strtoll(s, &errorptr, 0 /* base 10 par defaut */);
190#endif
191#endif /* NO_PROCESS */
192 if (errno || *errorptr != 0) error_convert(s,"long long");
193}
194
195void convert_to(const char *s, float& ob)
196{
197 errno = 0;
198 char * errorptr = 0;
199 ob = strtof(s, &errorptr);
200 if (errno || *errorptr != 0) error_convert(s,"float");
201}
202
203void convert_to(const char *s, double& ob)
204{
205 errno = 0;
206 char * errorptr = 0;
207 ob = strtod(s, &errorptr);
208 if (errno || *errorptr != 0) error_convert(s,"double");
209}
210
211// methode virtuelle pour lire un int ou un reel. Dans cette classe de base, on lit dans le istream avec read() (si is_bin() == 1)
212// ou avec operator>>() (si is_bin() == 0). Si le drapeau check_types est mis, on appelle convert_to() pour verifier les types des objets lus.
213// Dans ce cas, pour les ints on comprend les formats 123 (decimal), 0xa345 (hexa) et autres.
214// Si une erreur se produit, on appelle error_handle_()
215// Note pour les programmeurs des classes derivees: L'implementation de cette methode doit toujours passer par hande_error()
216Entree& Entree::operator>>(double& ob) { return operator_template<double>(ob); }
217
218// methode virtuelle pour lire un tableau d'ints ou reels (le tableau doit avoir la bonne dimension: attention pas de verification possible)
219int Entree::get(double * ob, std::streamsize n) { return get_template<double>(ob,n); }
220
221Entree& Entree::operator>>(int& ob) { return operator_template<int>(ob); }
222int Entree::get(int * ob, std::streamsize n) { return get_template<int>(ob,n); }
223
224Entree& Entree::operator>>(float& ob) { return operator_template<float>(ob); }
225int Entree::get(float * ob, std::streamsize n) { return get_template<float>(ob,n); }
226
227Entree& Entree::operator>>(long& ob) { return operator_template<long>(ob); }
228int Entree::get(long * ob, std::streamsize n) { return get_template<long>(ob,n); }
229
230Entree& Entree::operator>>(long long& ob) { return operator_template<long long>(ob); }
231int Entree::get(long long * ob, std::streamsize n) { return get_template<long long>(ob,n); }
232
233// Yes this is awful. We will get rid of this along with Nom.
234Entree& Entree::operator>>(std::string& ob) { Nom tmp; *this >> tmp; ob = tmp.getString(); return *this;}
235
236Entree& Entree::operator >>(Objet_U& ob) { return ob.readOn(*this); }
237
239{
240 if(istream_)
241 {
242 int jol = 0;
243 char tmp=(char)istream_->peek();
244 while(isspace(tmp)) //tmp=='\n')
245 {
246 if(tmp=='\n')
247 jol++;
248 istream_->get(tmp);
249 tmp=(char)istream_->peek();
250 }
251 return jol;
252 }
253 return -1;
254}
255
257{
258 if(istream_)
259 return (istream_->eof());
260 else
261 return -1;
262}
264{
265 if(istream_)
266 return (istream_->fail());
267 else
268 return -1;
269}
271{
272 if(istream_)
273 return (istream_->good());
274 else
275 return -1;
276}
278{
279#ifndef TRUST_USE_UVM // ToDo bug ?
280 if(istream_)
281 delete istream_;
282#endif
283 istream_=nullptr;
284}
285
286/*! @brief Change le mode d'ecriture du fichier.
287 *
288 * Cette methode peut etre appelee n'importe quand.
289 *
290 */
291void Entree::set_bin(bool bin)
292{
293 bin_ = bin;
294 if (istream_)
295 {
296 Cerr<<"Error you cant change binary format after open "<<finl;
297 assert(0);
299 }
300}
301
302/*! @brief indique si le stream doit verifier les types des objets lus (ints et nombres flottants).
303 *
304 * Exemple : l'entree contient 123.456 123.456
305 * int i;
306 * check_types(0);
307 * is >> i; // i contient 123
308 * check_types(1);
309 * is >> i; // Erreur : on lit la chaine 123.456 et on essaye de la convertir en int
310 * Voir operator>>(int &)
311 *
312 */
314{
315 check_types_ = flag;
316}
317
318
319/*! @brief Cette fonction est appellee par operateur>>, get, get_nom ouvrir, fermer, lire, etc.
320 *
321 * .. en cas d'echec (lorsque fail() est mis)
322 * Elle renvoie 0 s'il y a eu une erreur (passer par error_handle() qui
323 * traite en inline le cas ou il n'y a pas d'erreur), et 1 s'il n'y a pas
324 * d'erreur.
325 * (par commodite de codage des methodes qui l'utilisent, on
326 * ecrira "return error_handle(fail());"
327 * Elle peut etre configuree pour
328 * - renvoyer "0" en cas d'erreur et continuer l'execution du code
329 * (cas d'un ancien code qui ne gere pas les exceptions mais teste
330 * le drapeau fail() de temps en temps)
331 * Dans ce cas les methodes operator>> continuent l'execution du code
332 * meme en cas d'echec, le contenu des variables lues est indefini !
333 * - faire Process::exit() (cas d'une portion de code dans laquelle
334 * on ne veut pas faire de gestion d'erreur du tout et ou on suppose
335 * que tout va toujours bien)
336 * - lever une exception (permet une gestion rigoureuse des erreurs
337 * et une information utilisateur optimale en fonction du contexte)
338 *
339 * @sa set_error_action()
340 *
341 */
342int Entree::error_handle_(int fail_flag)
343{
344 if (!fail_flag)
345 return 1;
346
347 switch(error_action_)
348 {
349 case ERROR_CONTINUE:
350 break;
351 case ERROR_EXIT:
352 Cerr << "Error while reading in Entree object. Exiting.\n";
353 if (istream_)
354 {
355 // On n'utilise pas Entree::eof() car dans le cas d'un Lec_Fic_Dif
356 // eof() est parallele et ca peut bloquer.
357 if (get_istream().eof())
358 Cerr << " End of file reached." << finl;
359 else
360 Cerr << " IO error (not an EOF error)." << finl;
361 }
363 break;
364 case ERROR_EXCEPTION:
366 throw (e);
367 }
368 return 0;
369}
370
371/*! @brief renvoie error_action_ pour cette entree (permet de la modifier et de restaurer ensuite la valeur anterieure)
372 *
373 */
378
379/*! @brief Change le comportement en cas d'erreur de l'entree, voir error_handle_() et get_error_action()
380 *
381 */
386
387// Detection sur un fichier de nom filename
388// est de type binaire
389int is_a_binary_file(Nom& filename)
390{
391 // On parcourt les 1000 premiers octets
392 // Detection tres imparfaite donc limite
393 // aux fichiers geom de TRUST
394 int n=0;
395 int c;
396 std::ifstream fic(filename.getChar());
397 // Si on rencontre un caractere ASCII>127
398 // alors le fichier est de type binaire
399 while((c = fic.get()) != EOF && n++<1000)
400 if ((c>127)||(c<9))
401 return 1;
402 // GF sous windows les caracteres binaire sont surtout <9
403 // else printf("ici %d %c \n",c,c);
404 return 0;
405}
406
407/*! @brief ToDo TMA : commenter
408 *
409 */
410void Entree::set_diffuse(bool diffuse)
411{
412 // virtual method does nothing ; cf override in Lec_Diffuse_base
413 diffuse_ = true;
414}
415
416
417template<typename _TYPE_>
418int Entree::get_template(_TYPE_ *ob, std::streamsize n)
419{
420 assert(istream_!=0);
421 assert(n >= 0);
422 if (bin_)
423 {
424 if (this->must_convert<_TYPE_>())
425 {
426 // Need to cast, use '>>' operator - see doc in operator_template<>
427 for (int i = 0; i < n; i++) (*this) >> ob[i];
428 }
429 else
430 {
431 // In binary, optimized block reading:
432 char *ptr = (char*) ob;
433 std::streamsize sz = sizeof(_TYPE_);
434 sz *= n;
435 istream_->read(ptr, sz);
436 error_handle(istream_->fail());
437 }
438 }
439 else
440 {
441 // En ascii : on passe par operator>> pour verifier les conversions
442 // Attention : on appelle celui de cette classe, pas de la classe derivee
443 for (int i = 0; i < n; i++) Entree::operator>>(ob[i]);
444 }
445 return (!istream_->fail());
446}
447
448// Explicit instanciations:
449template int Entree::get_template(int *ob, std::streamsize n);
450template int Entree::get_template(long *ob, std::streamsize n);
451template int Entree::get_template(long long *ob, std::streamsize n);
452template int Entree::get_template(double *ob, std::streamsize n);
453template int Entree::get_template(float *ob, std::streamsize n);
454
455
456template <typename _TYPE_>
457Entree& Entree::operator_template(_TYPE_& ob)
458{
459 assert(istream_!=0);
460 if (bin_)
461 {
462 // Do we need to worry about 32b / 64b conversion?
463 if (this->must_convert<_TYPE_>())
464 {
465 // Yes, then two cases:
466 // Case 1: requested _TYPE_ is 32b and file is 64b -> only OK if read value is actually within the 32b range
467 if (is_64b_)
468 {
469 std::int64_t pr;
470 char *ptr = (char*) &pr;
471 istream_->read(ptr, sizeof(std::int64_t));
472 if (pr > std::numeric_limits<int>::max())
473 {
474 Cerr << "Can't read this int64 binary file with an int32 binary: values too big, overflow!!" << finl;
475 throw;
476 }
477 // It's ok, we passed the check above, we can safely downcast:
478 ob = static_cast<_TYPE_>(pr);
479 }
480 // Case 2: requested _TYPE_ is 64b and file is 32b -> this is always OK, just need int to make sure we really read a 32b value
481 else
482 {
483 int pr;
484 char * ptr = (char*) &pr;
485 istream_->read(ptr, sizeof(int));
486 ob=(_TYPE_)pr;
487 }
488 }
489 else // File has the same bit-ness as binary, or we are trying to read a non-problematic type - all OK.
490 {
491 char *ptr = (char*) &ob;
492 istream_->read(ptr, sizeof(_TYPE_));
493 error_handle(istream_->fail());
494 }
495 }
496 else // Not binary, ascii format
497 {
498 if (check_types_)
499 {
500 char buffer[100];
501 int ok = Entree::get(buffer, 100); // Bien appeler get de cette classe
502 if (ok)
503 convert_to(buffer, ob);
504 }
505 else
506 {
507 (*istream_) >> ob;
508 error_handle(istream_->fail());
509 }
510 }
511 return *this;
512}
513
514// Explicit instanciations:
515template Entree& Entree::operator_template(int& ob);
516template Entree& Entree::operator_template(long& ob);
517template Entree& Entree::operator_template(long long& ob);
518template Entree& Entree::operator_template(double& ob);
519template Entree& Entree::operator_template(float& ob);
520
bool bin_
Is this a binary flux?
Definition AbstractIO.h:50
bool is_64b_
Will we be reading/writing in 64b? (Init in ctor to avoid including arch.h probably).
Definition AbstractIO.h:51
bool must_convert() const
Whether to convert an int into a long when reading/writing out data.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
virtual int good()
Definition Entree.cpp:270
virtual int error_handle_(int fail_flag)
Cette fonction est appellee par operateur>>, get, get_nom ouvrir, fermer, lire, etc.
Definition Entree.cpp:342
int error_handle(int fail_flag)
Definition Entree.h:105
Entree()
Definition Entree.cpp:24
virtual int fail()
Definition Entree.cpp:263
bool check_types_
Definition Entree.h:112
Entree & operator=(istream &is)
Definition Entree.cpp:72
virtual int get(int *ob, std::streamsize n)
Definition Entree.cpp:222
virtual void set_diffuse(bool diffuse)
ToDo TMA : commenter.
Definition Entree.cpp:410
virtual ~Entree()
Definition Entree.cpp:277
virtual int jumpOfLines()
Definition Entree.cpp:238
bool diffuse_
Definition Entree.h:114
Error_Action
Definition Entree.h:93
@ ERROR_EXCEPTION
Definition Entree.h:93
@ ERROR_EXIT
Definition Entree.h:93
@ ERROR_CONTINUE
Definition Entree.h:93
virtual void set_error_action(Error_Action)
Change le comportement en cas d'erreur de l'entree, voir error_handle_() et get_error_action().
Definition Entree.cpp:382
Error_Action error_action_
Definition Entree.h:113
Entree & operator>>(Entree &(*f)(Entree &))
Definition Entree.cpp:55
virtual int eof()
Definition Entree.cpp:256
virtual istream & get_istream()
Definition Entree.cpp:41
void set_bin(bool bin) override
Change le mode d'ecriture du fichier.
Definition Entree.cpp:291
void set_istream(istream *is)
Definition Entree.cpp:50
Error_Action get_error_action()
renvoie error_action_ pour cette entree (permet de la modifier et de restaurer ensuite la valeur ante...
Definition Entree.cpp:374
virtual void set_check_types(bool flag)
indique si le stream doit verifier les types des objets lus (ints et nombres flottants).
Definition Entree.cpp:313
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
const char * getChar() const
Definition Nom.h:91
const std::string & getString() const
Definition Nom.h:92
classe Objet_U Cette classe est la classe de base des Objets de TRUST
Definition Objet_U.h:73
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455