TrioCFD 1.9.9_beta
TrioCFD documentation
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// Assignment operators
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 Reads a string from ostream_. bufsize is the size of the buffer allocated for ob (including
89 *
90 * the final null character).
91 * The string always contains a null character even on failure.
92 * The method returns 1 if reading is successful, 0 otherwise.
93 * If the buffer is too small, we currently call exit(), but
94 * in the future we could test: if strlen(ob)==bufsize-1, then
95 * call lire() again until the end is reached. If the next lire()
96 * returns a string of length zero, it means the string length was
97 * exactly bufsize-1.
98 * Warning: the behaviour differs between binary and ASCII mode.
99 * In binary mode, the string is read until the next '\0'.
100 * In ASCII mode, the string is read until the next separator (space, tab, newline).
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 // In binary mode, read until the next null character
111 // (including spaces, newlines, 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 // C++20 solution: use std::string then copy
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 // If the buffer was filled to the end, it is probably too small.
143 // Continuing to read is dangerous because in ASCII mode we cannot know
144 // whether the string was read exactly (which would be fine) or whether
145 // it was not fully read as an int. Thorough testing of the STL would be
146 // needed, and the result likely depends on the implementation. Therefore,
147 // if the buffer is full, we abort the code.
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 Conversion method.
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 by default */);
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 by default */);
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 by default */);
185#else /* NO_PROCESS */
186#ifdef MICROSOFT
187 ob = _strtoi64(s, &errorptr, 0 /* base 10 by default */);
188#else
189 ob = strtoll(s, &errorptr, 0 /* base 10 by default */);
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// Virtual method to read an int or a real number. In this base class, reading is done from istream using read() (if is_bin() == 1)
212// or using operator>>() (if is_bin() == 0). If the check_types flag is set, convert_to() is called to verify the types of the objects read.
213// In that case, for ints, the formats 123 (decimal), 0xa345 (hexadecimal) and others are accepted.
214// If an error occurs, error_handle_() is called.
215// Note for developers of derived classes: the implementation of this method must always go through error_handle_().
216Entree& Entree::operator>>(double& ob) { return operator_template<double>(ob); }
217
218// Virtual method to read an array of ints or reals (the array must have the correct size: no verification is 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 Changes the file write mode.
287 *
288 * This method can be called at any time.
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 Indicates whether the stream should verify the types of read objects (ints and floating-point numbers).
303 *
304 * Example: the input contains 123.456 123.456
305 * int i;
306 * check_types(0);
307 * is >> i; // i contains 123
308 * check_types(1);
309 * is >> i; // Error: reads the string 123.456 and tries to convert it to int
310 * See operator>>(int &)
311 *
312 */
314{
315 check_types_ = flag;
316}
317
318
319/*! @brief This function is called by operator>>, get, get_nom, ouvrir, fermer, lire, etc.
320 *
321 * .. on failure (when fail() is set).
322 * It returns 0 if an error occurred (go through error_handle() which
323 * handles inline the case where there is no error), and 1 if there is no error.
324 * (for coding convenience, one writes "return error_handle(fail());"
325 * It can be configured to:
326 * - return "0" on error and continue code execution
327 * (case of legacy code that does not handle exceptions but periodically
328 * tests the fail() flag)
329 * In this case, operator>> methods continue execution even on failure,
330 * and the content of the read variables is undefined!
331 * - call Process::exit() (case of a code section where no error handling
332 * is desired and everything is assumed to succeed)
333 * - throw an exception (allows rigorous error handling and optimal
334 * user feedback depending on context)
335 *
336 * @sa set_error_action()
337 *
338 */
339int Entree::error_handle_(int fail_flag)
340{
341 if (!fail_flag)
342 return 1;
343
344 switch(error_action_)
345 {
346 case ERROR_CONTINUE:
347 break;
348 case ERROR_EXIT:
349 Cerr << "Error while reading in Entree object. Exiting.\n";
350 if (istream_)
351 {
352 // We do not use Entree::eof() because in the case of a Lec_Fic_Dif,
353 // eof() is parallel and could block.
354 if (get_istream().eof())
355 Cerr << " End of file reached." << finl;
356 else
357 Cerr << " IO error (not an EOF error)." << finl;
358 }
360 break;
361 case ERROR_EXCEPTION:
363 throw (e);
364 }
365 return 0;
366}
367
368/*! @brief Returns error_action_ for this input (allows modifying it and restoring the previous value afterwards).
369 *
370 */
375
376/*! @brief Changes the error behaviour of the input; see error_handle_() and get_error_action().
377 *
378 */
383
384// Detects whether a file with name filename
385// is of binary type
386int is_a_binary_file(Nom& filename)
387{
388 // Scan the first 1000 bytes
389 // Very imperfect detection, therefore limited
390 // to TRUST geometry files
391 int n=0;
392 int c;
393 std::ifstream fic(filename.getChar());
394 // If a character with ASCII value > 127 is encountered,
395 // the file is of binary type
396 while((c = fic.get()) != EOF && n++<1000)
397 if ((c>127)||(c<9))
398 return 1;
399 // GF on windows, binary characters are mostly <9
400 // else printf("ici %d %c \n",c,c);
401 return 0;
402}
403
404/*! @brief Sets the diffuse flag for this input stream.
405 *
406 * This virtual method does nothing in the base class; see override in Lec_Diffuse_base.
407 * @param diffuse Whether to diffuse data to other processes.
408 */
409void Entree::set_diffuse(bool diffuse)
410{
411 // virtual method does nothing ; cf override in Lec_Diffuse_base
412 diffuse_ = true;
413}
414
415
416template<typename _TYPE_>
417int Entree::get_template(_TYPE_ *ob, std::streamsize n)
418{
419 assert(istream_!=0);
420 assert(n >= 0);
421 if (bin_)
422 {
423 if (this->must_convert<_TYPE_>())
424 {
425 // Need to cast, use '>>' operator - see doc in operator_template<>
426 for (int i = 0; i < n; i++) (*this) >> ob[i];
427 }
428 else
429 {
430 // In binary, optimized block reading:
431 char *ptr = (char*) ob;
432 std::streamsize sz = sizeof(_TYPE_);
433 sz *= n;
434 istream_->read(ptr, sz);
435 error_handle(istream_->fail());
436 }
437 }
438 else
439 {
440 // In ASCII mode: use operator>> to verify conversions
441 // Warning: we call the one from this class, not from a derived class
442 for (int i = 0; i < n; i++) Entree::operator>>(ob[i]);
443 }
444 return (!istream_->fail());
445}
446
447// Explicit instanciations:
448template int Entree::get_template(int *ob, std::streamsize n);
449template int Entree::get_template(long *ob, std::streamsize n);
450template int Entree::get_template(long long *ob, std::streamsize n);
451template int Entree::get_template(double *ob, std::streamsize n);
452template int Entree::get_template(float *ob, std::streamsize n);
453
454
455template <typename _TYPE_>
456Entree& Entree::operator_template(_TYPE_& ob)
457{
458 assert(istream_!=0);
459 if (bin_)
460 {
461 // Do we need to worry about 32b / 64b conversion?
462 if (this->must_convert<_TYPE_>())
463 {
464 // Yes, then two cases:
465 // Case 1: requested _TYPE_ is 32b and file is 64b -> only OK if read value is actually within the 32b range
466 if (is_64b_)
467 {
468 std::int64_t pr;
469 char *ptr = (char*) &pr;
470 istream_->read(ptr, sizeof(std::int64_t));
471 if (pr > std::numeric_limits<int>::max())
472 {
473 Cerr << "Can't read this int64 binary file with an int32 binary: values too big, overflow!!" << finl;
474 throw;
475 }
476 // It's ok, we passed the check above, we can safely downcast:
477 ob = static_cast<_TYPE_>(pr);
478 }
479 // 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
480 else
481 {
482 int pr;
483 char * ptr = (char*) &pr;
484 istream_->read(ptr, sizeof(int));
485 ob=(_TYPE_)pr;
486 }
487 }
488 else // File has the same bit-ness as binary, or we are trying to read a non-problematic type - all OK.
489 {
490 char *ptr = (char*) &ob;
491 istream_->read(ptr, sizeof(_TYPE_));
492 error_handle(istream_->fail());
493 }
494 }
495 else // Not binary, ascii format
496 {
497 if (check_types_)
498 {
499 char buffer[100];
500 int ok = Entree::get(buffer, 100); // Must call get() from this class, not a derived one
501 if (ok)
502 convert_to(buffer, ob);
503 }
504 else
505 {
506 (*istream_) >> ob;
507 error_handle(istream_->fail());
508 }
509 }
510 return *this;
511}
512
513// Explicit instanciations:
514template Entree& Entree::operator_template(int& ob);
515template Entree& Entree::operator_template(long& ob);
516template Entree& Entree::operator_template(long long& ob);
517template Entree& Entree::operator_template(double& ob);
518template Entree& Entree::operator_template(float& ob);
519
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)
This function is called by operator>>, get, get_nom, ouvrir, fermer, lire, etc.
Definition Entree.cpp:339
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)
Sets the diffuse flag for this input stream.
Definition Entree.cpp:409
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)
Changes the error behaviour of the input; see error_handle_() and get_error_action().
Definition Entree.cpp:379
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
Changes the file write mode.
Definition Entree.cpp:291
void set_istream(istream *is)
Definition Entree.cpp:50
Error_Action get_error_action()
Returns error_action_ for this input (allows modifying it and restoring the previous value afterwards...
Definition Entree.cpp:371
virtual void set_check_types(bool flag)
Indicates whether the stream should verify the types of read objects (ints and floating-point numbers...
Definition Entree.cpp:313
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
const char * getChar() const
Definition Nom.h:91
const std::string & getString() const
Definition Nom.h:92
Base class for TRUST objects (Objet_U).
Definition Objet_U.h:68
virtual Entree & readOn(Entree &)
Reads an Objet_U from an input stream. Virtual method to override.
Definition Objet_U.cpp:289
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466