libMesh
xdr_cxx.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 // C/C++ includes
20 #include <cstring>
21 #include <limits>
22 #include <iomanip>
23 #include <memory>
24 #include <sstream>
25 #include <fstream>
26 
27 // Local includes
28 #include "libmesh/xdr_cxx.h"
29 #include "libmesh/libmesh_logging.h"
30 #ifdef LIBMESH_HAVE_GZSTREAM
31 # include "gzstream.h" // For reading/writing compressed streams
32 #endif
33 #include "libmesh/utility.h" // unzip_file
34 
35 #ifdef LIBMESH_HAVE_UNISTD_H
36 #include <unistd.h> // for getpid() on Unix
37 #endif
38 #ifdef LIBMESH_HAVE_PROCESS_H
39 #include <process.h> // for getpid() on Windows
40 #endif
41 
42 // Anonymous namespace for implementation details.
43 namespace {
44 
45 // Nasty hacks for reading/writing zipped files
46 void bzip_file (std::string_view unzipped_name)
47 {
48 #ifdef LIBMESH_HAVE_BZIP
49  LOG_SCOPE("system(bzip2)", "XdrIO");
50 
51  std::string system_string = "bzip2 -f ";
52  system_string += unzipped_name;
53  if (std::system(system_string.c_str()))
54  libmesh_file_error(system_string);
55 #else
56  libmesh_error_msg("ERROR: need bzip2/bunzip2 to create " << unzipped_name << ".bz2");
57 #endif
58 }
59 
60 void xzip_file (std::string_view unzipped_name)
61 {
62 #ifdef LIBMESH_HAVE_XZ
63  LOG_SCOPE("system(xz)", "XdrIO");
64 
65  std::string system_string = "xz -f ";
66  system_string += unzipped_name;
67  if (std::system(system_string.c_str()))
68  libmesh_file_error(system_string);
69 #else
70  libmesh_error_msg("ERROR: need xz to create " << unzipped_name << ".xz");
71 #endif
72 }
73 
74 
75 // remove an unzipped file
76 void remove_unzipped_file (std::string_view name)
77 {
78  std::ostringstream pid_suffix;
79  pid_suffix << '_' << getpid();
80 
81  // If we temporarily decompressed a file, remove the
82  // uncompressed version
83  if (name.rfind(".bz2") == name.size() - 4)
84  {
85  std::string new_name(name.begin(), name.end()-4);
86  new_name += pid_suffix.str();
87  std::remove(new_name.c_str());
88  }
89  if (name.rfind(".xz") == name.size() - 3)
90  {
91  std::string new_name(name.begin(), name.end()-3);
92  new_name += pid_suffix.str();
93  std::remove(new_name.c_str());
94  }
95 }
96 }
97 
98 namespace libMesh
99 {
100 
101 //-------------------------------------------------------------
102 // Xdr class implementation
103 Xdr::Xdr (std::string name,
104  const XdrMODE m) :
105  mode(m),
106  file_name(std::move(name)),
107 #ifdef LIBMESH_HAVE_XDR
108  fp(nullptr),
109 #endif
110  in(),
111  out(),
112  comm_len(xdr_MAX_STRING_LENGTH),
113  gzipped_file(false),
114  bzipped_file(false),
115  xzipped_file(false),
116  version_number(LIBMESH_VERSION_ID(LIBMESH_MAJOR_VERSION, LIBMESH_MINOR_VERSION, LIBMESH_MICRO_VERSION))
117 {
118  this->open(file_name);
119 }
120 
121 
122 
123 Xdr::Xdr (std::ostream & stream) :
124  mode(WRITE),
125  file_name(),
126 #ifdef LIBMESH_HAVE_XDR
127  fp(nullptr),
128 #endif
129  in(),
130  out(std::make_unique<std::ostream>(stream.rdbuf())),
131  comm_len(xdr_MAX_STRING_LENGTH),
132  gzipped_file(false),
133  bzipped_file(false),
134  xzipped_file(false),
135  version_number(LIBMESH_VERSION_ID(LIBMESH_MAJOR_VERSION, LIBMESH_MINOR_VERSION, LIBMESH_MICRO_VERSION))
136 {
137 }
138 
139 
140 
141 Xdr::Xdr (std::istream & stream) :
142  mode(READ),
143  file_name(),
144 #ifdef LIBMESH_HAVE_XDR
145  fp(nullptr),
146 #endif
147  in(std::make_unique<std::istream>(stream.rdbuf())),
148  out(),
149  comm_len(xdr_MAX_STRING_LENGTH),
150  gzipped_file(false),
151  bzipped_file(false),
152  xzipped_file(false),
153  version_number(LIBMESH_VERSION_ID(LIBMESH_MAJOR_VERSION, LIBMESH_MINOR_VERSION, LIBMESH_MICRO_VERSION))
154 {
155 }
156 
157 
158 
160 {
161  this->close();
162 }
163 
164 
165 
166 void Xdr::open (std::string name)
167 {
168  file_name = std::move(name);
169 
170  if (file_name == "")
171  return;
172 
173  switch (mode)
174  {
175  case ENCODE:
176  case DECODE:
177  {
178 #ifdef LIBMESH_HAVE_XDR
179 
180  fp = fopen(file_name.c_str(), (mode == ENCODE) ? "w" : "r");
181  if (!fp)
182  libmesh_file_error(file_name.c_str());
183  xdrs = std::make_unique<XDR>();
184  xdrstdio_create (xdrs.get(), fp, (mode == ENCODE) ? XDR_ENCODE : XDR_DECODE);
185 #else
186 
187  libmesh_error_msg("ERROR: Functionality is not available.\n" \
188  << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
189  << "The XDR interface is not available in this installation");
190 
191 #endif
192  return;
193 
194  }
195 
196  case READ:
197  {
198  gzipped_file = (file_name.rfind(".gz") == file_name.size() - 3);
199  bzipped_file = (file_name.rfind(".bz2") == file_name.size() - 4);
200  xzipped_file = (file_name.rfind(".xz") == file_name.size() - 3);
201 
202  if (gzipped_file)
203  {
204 #ifdef LIBMESH_HAVE_GZSTREAM
205  auto inf = std::make_unique<igzstream>();
206  libmesh_assert(inf);
207  inf->open(file_name.c_str(), std::ios::in);
208  in = std::move(inf);
209 #else
210  libmesh_error_msg("ERROR: need gzstream to handle .gz files!!!");
211 #endif
212  }
213  else
214  {
215  auto inf = std::make_unique<std::ifstream>();
216  libmesh_assert(inf);
217 
218  std::string new_name = Utility::unzip_file(file_name);
219 
220  inf->open(new_name.c_str(), std::ios::in);
221  in = std::move(inf);
222  }
223 
224  libmesh_assert(in.get());
225 
226  if (!in->good())
227  libmesh_file_error(file_name);
228  return;
229  }
230 
231  case WRITE:
232  {
233  gzipped_file = (file_name.rfind(".gz") == file_name.size() - 3);
234  bzipped_file = (file_name.rfind(".bz2") == file_name.size() - 4);
235  xzipped_file = (file_name.rfind(".xz") == file_name.size() - 3);
236 
237  if (gzipped_file)
238  {
239 #ifdef LIBMESH_HAVE_GZSTREAM
240  auto outf = std::make_unique<ogzstream>();
241  libmesh_assert(outf);
242  outf->open(file_name.c_str(), std::ios::out);
243  out = std::move(outf);
244 #else
245  libmesh_error_msg("ERROR: need gzstream to handle .gz files!!!");
246 #endif
247  }
248  else
249  {
250  auto outf = std::make_unique<std::ofstream>();
251  libmesh_assert(outf);
252 
253  std::string new_name = file_name;
254 
255  if (bzipped_file)
256  new_name.erase(new_name.end() - 4, new_name.end());
257 
258  if (xzipped_file)
259  new_name.erase(new_name.end() - 3, new_name.end());
260 
261  outf->open(new_name.c_str(), std::ios::out);
262  out = std::move(outf);
263  }
264 
265  libmesh_assert(out.get());
266  libmesh_assert (out->good());
267  return;
268  }
269 
270  default:
271  libmesh_error_msg("Invalid mode = " << mode);
272  }
273 }
274 
275 
276 
277 void Xdr::close ()
278 {
279  switch (mode)
280  {
281  case ENCODE:
282  case DECODE:
283  {
284 #ifdef LIBMESH_HAVE_XDR
285 
286  if (xdrs)
287  {
288  xdr_destroy (xdrs.get());
289  xdrs.reset();
290  }
291 
292  if (fp)
293  {
294  fflush(fp);
295  fclose(fp);
296  fp = nullptr;
297  }
298 #else
299 
300  libmesh_error_msg("ERROR: Functionality is not available.\n" \
301  << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
302  << "The XDR interface is not available in this installation");
303 
304 #endif
305  file_name = "";
306  return;
307  }
308 
309  case READ:
310  {
311  if (in.get() != nullptr)
312  {
313  in.reset();
314 
315  if (bzipped_file || xzipped_file)
316  remove_unzipped_file(file_name);
317  }
318  file_name = "";
319  return;
320  }
321 
322  case WRITE:
323  {
324  if (out.get() != nullptr)
325  {
326  out.reset();
327 
328  if (bzipped_file)
329  bzip_file(std::string(file_name.begin(), file_name.end()-4));
330 
331  else if (xzipped_file)
332  xzip_file(std::string(file_name.begin(), file_name.end()-3));
333  }
334  file_name = "";
335  return;
336  }
337 
338  default:
339  libmesh_error_msg("Invalid mode = " << mode);
340  }
341 }
342 
343 
344 
345 bool Xdr::is_open() const
346 {
347  switch (mode)
348  {
349  case ENCODE:
350  case DECODE:
351  {
352 #ifdef LIBMESH_HAVE_XDR
353 
354  if (fp)
355  if (xdrs)
356  return true;
357 
358  return false;
359 
360 #else
361 
362  libmesh_error_msg("ERROR: Functionality is not available.\n" \
363  << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
364  << "The XDR interface is not available in this installation");
365 
366  return false;
367 
368 #endif
369 
370  }
371 
372  case READ:
373  {
374  if (in.get() != nullptr)
375  return in->good();
376  return false;
377  }
378 
379  case WRITE:
380  {
381  if (out.get() != nullptr)
382  return out->good();
383  return false;
384  }
385 
386  default:
387  libmesh_error_msg("Invalid mode = " << mode);
388  }
389 
390  return false;
391 }
392 
393 
394 
396 {
397  switch (mode)
398  {
399  case ENCODE:
400  case DECODE:
401  {
402 #ifdef LIBMESH_HAVE_XDR
404 
405  // Are we already at eof?
406  if (feof(fp))
407  return true;
408 
409  // Or about to reach eof?
410  int next = fgetc(fp);
411  if (next == EOF)
412  {
413  // We should *only* be at EOF, not otherwise broken
414  libmesh_assert(feof(fp));
415  libmesh_assert(!ferror(fp));
416 
417  // Reset the EOF indicator
418  clearerr(fp);
419  libmesh_assert(!ferror(fp));
420 
421  // We saw EOF
422  return true;
423  }
424 
425  // We didn't see EOF; restore whatever we did see.
426  ungetc(next, fp);
427  break;
428 #else
429 
430  libmesh_error_msg("ERROR: Functionality is not available.\n" \
431  << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
432  << "The XDR interface is not available in this installation");
433 
434  return false;
435 
436 #endif
437 
438  }
439  case READ:
440  {
441  libmesh_assert(in.get());
442 
443  // Are we already at eof?
444  if (in->eof())
445  return true;
446 
447  // Or about to reach eof?
448  int next = in->peek();
449  if (next == EOF)
450  {
451  // We should *only* be at EOF, not otherwise broken
452  libmesh_assert(in->eof());
453  libmesh_assert(!in->fail());
454 
455  // Reset the EOF indicator
456  in->clear();
457  libmesh_assert(in->good());
458 
459  // We saw EOF
460  return true;
461  }
462  break;
463  }
464  default:
465  libmesh_error();
466  }
467 
468  return false;
469 }
470 
471 
472 
473 #ifdef LIBMESH_HAVE_XDR
474 
475 // Anonymous namespace for Xdr::data helper functions
476 namespace
477 {
478 
479 template <typename T>
480 xdrproc_t xdr_translator();
481 
482 template <typename T>
483 bool xdr_translate(XDR * x, T & a)
484 {
485  return (xdr_translator<T>())(x, &a, 0);
486 }
487 
488 template <>
489 bool xdr_translate(XDR * x,
490  std::string & s)
491 {
492  char sptr[xdr_MAX_STRING_LENGTH+1];
493  std::copy(s.begin(), s.end(), sptr);
494  sptr[s.size()] = 0;
495  unsigned int length = xdr_MAX_STRING_LENGTH;
496 
497  // Get a pointer to the beginning of the buffer. We need to pass
498  // its address to the xdr API.
499  char * begin = sptr;
500  bool b = xdr_string(x, &begin, length);
501 
502  // This is necessary when reading, but inefficient when writing...
503  length = cast_int<unsigned int>(std::strlen(sptr));
504  s.resize(length);
505  std::copy(sptr, sptr+length, s.begin());
506 
507  return b;
508 }
509 
510 template <typename T>
511 bool xdr_translate(XDR * x, std::complex<T> & a)
512 {
513  T r = a.real(), i = a.imag();
514  bool b1 = xdr_translate(x, r);
515  bool b2 = xdr_translate(x, i);
516  a = std::complex<T>(r,i);
517  return (b1 && b2);
518 }
519 
520 template <typename T>
521 bool xdr_translate(XDR * x, std::vector<T> & a)
522 {
523  unsigned int length = cast_int<unsigned int>(a.size());
524  xdr_u_int(x, &length);
525  if (length > 0)
526  {
527  a.resize(length);
528  return xdr_vector(x, reinterpret_cast<char *>(a.data()), length, sizeof(T),
529  xdr_translator<T>());
530  }
531  else
532  return true;
533 }
534 
535 template <typename T>
536 bool xdr_translate(XDR * x, std::vector<std::complex<T>> & a)
537 {
538  unsigned int length = cast_int<unsigned int>(a.size());
539  bool b = xdr_u_int(x, &length);
540  a.resize(length);
541  for (auto & val : a)
542  if (!xdr_translate(x, val))
543  b = false;
544  return b;
545 }
546 
547 template <>
548 bool xdr_translate(XDR * x, std::vector<std::string> & s)
549 {
550  unsigned int length = cast_int<unsigned int>(s.size());
551  bool b = xdr_u_int(x, &length);
552  s.resize(length);
553  for (auto & val : s)
554  if (!xdr_translate(x, val))
555  b = false;
556  return b;
557 }
558 
559 template <>
560 xdrproc_t xdr_translator<int>()
561 {
562  // Don't let XDR truncate anything on systems where int is 64-bit;
563  // xdr_int is hard-coded to write 32 bits.
564  if (sizeof(int) <= 4)
565  return (xdrproc_t)(xdr_int);
566  else if (sizeof(int) == sizeof(long long))
567  return (xdrproc_t)(xdr_longlong_t);
568  else if (sizeof(int) == sizeof(long))
569  return (xdrproc_t)(xdr_long);
570  else
571  libmesh_error();
572 }
573 
574 template <>
575 xdrproc_t xdr_translator<unsigned int>()
576 {
577  // Don't let XDR truncate anything on systems where int is 64-bit;
578  // xdr_u_int is hard-coded to write 32 bits.
579  if (sizeof(unsigned int) <= 4)
580  return (xdrproc_t)(xdr_u_int);
581  else if (sizeof(unsigned int) == sizeof(unsigned long))
582  return (xdrproc_t)(xdr_u_long);
583  else if (sizeof(unsigned int) == sizeof(unsigned long long))
584  return (xdrproc_t)(xdr_u_longlong_t);
585  else
586  libmesh_error();
587 }
588 
589 template <>
590 xdrproc_t xdr_translator<long int>()
591 {
592  // Don't let XDR truncate anything on systems where long is 64-bit;
593  // xdr_long is hard-coded to write 32 bits.
594  if (sizeof(long int) <= 4)
595  return (xdrproc_t)(xdr_long);
596  else if (sizeof(long int) == sizeof(long long))
597  return (xdrproc_t)(xdr_longlong_t);
598  else
599  libmesh_error();
600 }
601 
602 template <>
603 xdrproc_t xdr_translator<unsigned long int>()
604 {
605  // Don't let XDR truncate anything on systems where long is 64-bit;
606  // xdr_u_long is hard-coded to write 32 bits. This bit us HARD.
607  if (sizeof(unsigned long int) <= 4)
608  return (xdrproc_t)(xdr_u_long);
609  else if (sizeof(unsigned long int) == sizeof(unsigned long long))
610  return (xdrproc_t)(xdr_u_longlong_t);
611  else
612  libmesh_error();
613 }
614 
615 // All the other XDR routines should be safe, unless
616 // 1. You're on a system with sizeof(short)==8 and you want to store
617 // n>2^32 in a short; this will never happen since we assume
618 // sizeof(short) may be as small as 2 bytes and we use at least int
619 // for anything larger.
620 // 2. You're on a system with sizeof(long long) > 8, and you want to
621 // store n>2^64 in one. Welcome, 22nd century programmers; sorry we
622 // couldn't accommodate you.
623 template <>
624 xdrproc_t xdr_translator<long long>() { return (xdrproc_t)(xdr_longlong_t); }
625 
626 template <>
627 xdrproc_t xdr_translator<unsigned long long>() { return (xdrproc_t)(xdr_u_longlong_t); }
628 
629 template <>
630 xdrproc_t xdr_translator<short int>() { return (xdrproc_t)(xdr_short); }
631 
632 template <>
633 xdrproc_t xdr_translator<unsigned short int>() { return (xdrproc_t)(xdr_u_short); }
634 
635 template <>
636 xdrproc_t xdr_translator<char>() { return (xdrproc_t)(xdr_char); }
637 
638 template <>
639 xdrproc_t xdr_translator<signed char>() { return (xdrproc_t)(xdr_char); }
640 
641 template <>
642 xdrproc_t xdr_translator<unsigned char>() { return (xdrproc_t)(xdr_u_char); }
643 
644 template <>
645 xdrproc_t xdr_translator<float>() { return (xdrproc_t)(xdr_float); }
646 
647 template <>
648 xdrproc_t xdr_translator<double>() { return (xdrproc_t)(xdr_double); }
649 
650 // FIXME - no XDR love for quadruple precision; not even for long double?
651 template <>
652 xdrproc_t xdr_translator<long double>() { return (xdrproc_t)(xdr_double); }
653 
654 #ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
655 template <>
656 xdrproc_t xdr_translator<Real>() { return (xdrproc_t)(xdr_double); }
657 #endif
658 
659 } // end anonymous namespace
660 
661 #endif
662 
663 template <typename T>
664 void Xdr::do_read(T & a)
665 {
666  *in >> a;
667  in->getline(comm, comm_len);
668 }
669 
670 template <typename T>
671 void Xdr::do_read(std::complex<T> & a)
672 {
673  T r, i;
674  *in >> r >> i;
675  a = std::complex<T>(r,i);
676  in->getline(comm, comm_len);
677 }
678 
679 template <>
680 void Xdr::do_read(std::string & a)
681 {
682  in->getline(comm, comm_len);
683 
684  a = "";
685 
686  for (unsigned int c=0, sl=std::strlen(comm); c!=sl; c++)
687  {
688  if (comm[c] == '\t')
689  break;
690  a.push_back(comm[c]);
691  }
692 }
693 
694 template <typename T>
695 void Xdr::do_read(std::vector<T> & a)
696 {
697  unsigned int length=0;
698  data(length, "# vector length");
699  a.resize(length);
700 
701  for (T & a_i : a)
702  {
703  libmesh_assert(in.get());
704  libmesh_assert (in->good());
705  *in >> a_i;
706  }
707  in->getline(comm, comm_len);
708 }
709 
710 template <typename T>
711 void Xdr::do_read(std::vector<std::complex<T>> & a)
712 {
713  unsigned int length=0;
714  data(length, "# vector length x 2 (complex)");
715  a.resize(length);
716 
717  for (std::complex<T> & a_i : a)
718  {
719  T r, im;
720  libmesh_assert(in.get());
721  libmesh_assert (in->good());
722  *in >> r >> im;
723  a_i = std::complex<T>(r,im);
724  }
725  in->getline(comm, comm_len);
726 }
727 
728 template <typename T>
729 void Xdr::do_write(T & a) { *out << a; }
730 
731 template <typename T>
732 void Xdr::do_write(std::complex<T> & a)
733 {
734  *out << a.real() << "\t " << a.imag();
735 }
736 
737 template <typename T>
738 void Xdr::do_write(std::vector<T> & a)
739 {
740  std::size_t length = a.size();
741  data(length, "# vector length");
742 
743  // Use scientific precision with lots of digits for the original type T.
744  *out << std::scientific
745  << std::setprecision(std::numeric_limits<T>::max_digits10);
746 
747  for (T & a_i : a)
748  {
749  libmesh_assert(out.get());
750  libmesh_assert (out->good());
751  this->do_write(a_i);
752  *out << "\t ";
753  }
754 }
755 
756 template <typename T>
757 void Xdr::do_write(std::vector<std::complex<T>> & a)
758 {
759  std::size_t length=a.size();
760  data(length, "# vector length x 2 (complex)");
761 
762  // Use scientific precision with lots of digits for the original type T.
763  *out << std::scientific
764  << std::setprecision(std::numeric_limits<T>::max_digits10);
765 
766  for (std::complex<T> & a_i : a)
767  {
768  libmesh_assert(out.get());
769  libmesh_assert (out->good());
770  this->do_write(a_i);
771  *out << "\t ";
772  }
773 }
774 
775 
776 
777 template <typename T>
778 void Xdr::data (T & a, std::string_view comment_in)
779 {
780  switch (mode)
781  {
782  case ENCODE:
783  case DECODE:
784  {
785 #ifdef LIBMESH_HAVE_XDR
786 
788 
789  xdr_translate(xdrs.get(), a);
790 
791 #else
792 
793  libmesh_error_msg("ERROR: Functionality is not available.\n" \
794  << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
795  << "The XDR interface is not available in this installation");
796 
797 #endif
798  return;
799  }
800 
801  case READ:
802  {
803  libmesh_assert(in.get());
804  libmesh_assert (in->good());
805 
806  this->do_read(a);
807 
808  return;
809  }
810 
811  case WRITE:
812  {
813  libmesh_assert(out.get());
814  libmesh_assert (out->good());
815 
816  // We will use scientific notation sufficient to exactly
817  // represent our floating point precision in the following
818  // output. The desired precision and format will
819  // automatically determine the width.
820  *out << std::scientific
821  << std::setprecision(std::numeric_limits<T>::max_digits10);
822 
823  this->do_write(a);
824 
825  // If there's a comment provided, write a tab character and
826  // then the comment.
827  if (comment_in != "")
828  *out << "\t " << comment_in;
829 
830  // Go to the next line.
831  *out << '\n';
832 
833  return;
834  }
835 
836  default:
837  libmesh_error_msg("Invalid mode = " << mode);
838  }
839 }
840 
841 
842 template <typename T>
843 void Xdr::data_stream (T * val, const unsigned int len, const unsigned int line_break)
844 {
845  switch (mode)
846  {
847  case ENCODE:
848  {
849 #ifdef LIBMESH_HAVE_XDR
850 
851  libmesh_assert (this->is_open());
852 
853  unsigned int size_of_type = cast_int<unsigned int>(sizeof(T));
854 
855  xdr_vector(xdrs.get(),
856  (char *) val,
857  len,
858  size_of_type,
859  xdr_translator<T>());
860 #else
861  libmesh_error_msg("ERROR: Functionality is not available.\n" \
862  << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
863  << "The XDR interface is not available in this installation");
864 
865 #endif
866  return;
867  }
868 
869  case DECODE:
870  {
871 #ifdef LIBMESH_HAVE_XDR
872 
873  libmesh_assert (this->is_open());
874 
875  unsigned int size_of_type = cast_int<unsigned int>(sizeof(T));
876 
877  if (len > 0)
878  xdr_vector(xdrs.get(),
879  (char *) val,
880  len,
881  size_of_type,
882  xdr_translator<T>());
883 #else
884  libmesh_error_msg("ERROR: Functionality is not available.\n" \
885  << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
886  << "The XDR interface is not available in this installation");
887 
888 #endif
889  return;
890  }
891 
892  case READ:
893  {
894  libmesh_assert(in.get());
895  libmesh_assert (in->good());
896 
897  for (unsigned int i=0; i<len; i++)
898  {
899  libmesh_assert(in.get());
900  libmesh_assert (in->good());
901  *in >> val[i];
902  }
903 
904  return;
905  }
906 
907  case WRITE:
908  {
909  libmesh_assert(out.get());
910  libmesh_assert (out->good());
911 
912  // We will use scientific notation sufficient to exactly
913  // represent our floating point precision in the following
914  // output. The desired precision and format will
915  // automatically determine the width.
916  *out << std::scientific
917  << std::setprecision(std::numeric_limits<T>::max_digits10);
918 
919  if (line_break == libMesh::invalid_uint)
920  for (unsigned int i=0; i<len; i++)
921  {
922  libmesh_assert(out.get());
923  libmesh_assert (out->good());
924  *out << val[i] << " ";
925  }
926  else
927  {
928  const unsigned imax = std::min(line_break, len);
929  unsigned int cnt=0;
930  while (cnt < len)
931  {
932  for (unsigned int i=0; (i<imax && cnt<len); i++)
933  {
934  libmesh_assert(out.get());
935  libmesh_assert (out->good());
936  *out << val[cnt++];
937 
938  // Write a space unless this is the last character on the current line.
939  if (i+1 != imax)
940  *out << " ";
941  }
942  libmesh_assert(out.get());
943  libmesh_assert (out->good());
944  *out << '\n';
945  }
946  }
947 
948  return;
949  }
950 
951  default:
952  libmesh_error_msg("Invalid mode = " << mode);
953  }
954 }
955 
956 
957 
958 template <>
959 void Xdr::data_stream (double * val, const unsigned int len, const unsigned int line_break)
960 {
961  this->_xfp_data_stream
962  (val, len,
963 #ifdef LIBMESH_HAVE_XDR
964  (xdrproc_t)xdr_double,
965 #else
966  nullptr,
967 #endif
968  line_break, std::numeric_limits<double>::max_digits10);
969 }
970 
971 
972 
973 template <>
974 void Xdr::data_stream (float * val, const unsigned int len, const unsigned int line_break)
975 {
976  this->_xfp_data_stream
977  (val, len,
978 #ifdef LIBMESH_HAVE_XDR
979  (xdrproc_t)xdr_float,
980 #else
981  nullptr,
982 #endif
983  line_break, std::numeric_limits<float>::max_digits10);
984 }
985 
986 
987 
988 template <>
989 void Xdr::data_stream (long double * val, const unsigned int len, const unsigned int line_break)
990 {
991  this->_xfp_data_stream
992  (val, len, nullptr, line_break,
993  std::numeric_limits<long double>::max_digits10);
994 }
995 
996 
997 #ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
998 template <>
999 void Xdr::data_stream (Real * val, const unsigned int len, const unsigned int line_break)
1000 {
1001  this->_xfp_data_stream(val, len, nullptr, line_break, 36);
1002 }
1003 #endif // LIBMESH_DEFAULT_QUADRUPLE_PRECISION
1004 
1005 
1006 
1007 template <typename XFP>
1008 void Xdr::_xfp_data_stream (XFP * val, const unsigned int len,
1009 #ifdef LIBMESH_HAVE_XDR
1010  xdrproc_t xdr_proc,
1011 #else
1012  void *,
1013 #endif
1014  const unsigned int line_break,
1015  const int n_digits)
1016 {
1017  switch (mode)
1018  {
1019  case ENCODE:
1020  case DECODE:
1021  {
1022 #ifdef LIBMESH_HAVE_XDR
1023  libmesh_assert (this->is_open());
1024 
1025  if (len > 0)
1026  {
1027  if (xdr_proc)
1028  {
1029  xdr_vector(xdrs.get(),
1030  (char *) val,
1031  len,
1032  sizeof(XFP),
1033  xdr_proc);
1034  return;
1035  }
1036 
1037  // FIXME[JWP]: How to implement this for long double? Mac
1038  // OS X defines 'xdr_quadruple' but AFAICT, it does not
1039  // exist for Linux... for now, reading/writing XDR files
1040  // with long doubles drops back to double precision, but
1041  // you can still write long double ASCII files of course.
1042 
1043  // FIXME[RHS]: 128 bit FP has the same problem as long
1044  // double, only much worse since even _Quad/__float128
1045  // aren't standard either.
1046 
1047  std::vector<double> io_buffer (len);
1048 
1049  // Fill io_buffer if we are writing.
1050  if (mode == ENCODE)
1051  for (unsigned int i=0, cnt=0; i<len; i++)
1052  io_buffer[cnt++] = double(val[i]);
1053 
1054  xdr_vector(xdrs.get(),
1055  reinterpret_cast<char *>(io_buffer.data()),
1056  len,
1057  sizeof(double),
1058  (xdrproc_t) xdr_double);
1059 
1060  // Fill val array if we are reading.
1061  if (mode == DECODE)
1062  for (unsigned int i=0, cnt=0; i<len; i++)
1063  {
1064  val[i] = io_buffer[cnt++];
1065  }
1066  }
1067 
1068 #else
1069 
1070  libmesh_error_msg("ERROR: Functionality is not available.\n" \
1071  << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
1072  << "The XDR interface is not available in this installation");
1073 
1074 #endif
1075  return;
1076  }
1077 
1078  case READ:
1079  {
1080  libmesh_assert(in.get());
1081  libmesh_assert (in->good());
1082 
1083  for (unsigned int i=0; i<len; i++)
1084  {
1085  libmesh_assert(in.get());
1086  libmesh_assert (in->good());
1087  *in >> val[i];
1088  }
1089 
1090  return;
1091  }
1092 
1093  case WRITE:
1094  {
1095  libmesh_assert(out.get());
1096  libmesh_assert (out->good());
1097 
1098  // Save stream flags
1099  std::ios_base::fmtflags out_flags = out->flags();
1100 
1101  // We will use scientific notation with specified digit
1102  // count in the following output. The desired precision and
1103  // format will automatically determine the width.
1104  *out << std::scientific
1105  << std::setprecision(n_digits);
1106 
1107  if (line_break == libMesh::invalid_uint)
1108  for (unsigned int i=0; i<len; i++)
1109  {
1110  libmesh_assert(out.get());
1111  libmesh_assert (out->good());
1112  *out << val[i] << ' ';
1113  }
1114  else
1115  {
1116  const unsigned imax = std::min(line_break, len);
1117  unsigned int cnt=0;
1118  while (cnt < len)
1119  {
1120  for (unsigned int i=0; (i<imax && cnt<len); i++)
1121  {
1122  libmesh_assert(out.get());
1123  libmesh_assert (out->good());
1124  *out << val[cnt++];
1125 
1126  // Write a space unless this is the last character on the current line.
1127  if (i+1 != imax)
1128  *out << " ";
1129  }
1130  libmesh_assert(out.get());
1131  libmesh_assert (out->good());
1132  *out << '\n';
1133  }
1134  }
1135 
1136  // Restore stream flags
1137  out->flags(out_flags);
1138 
1139  return;
1140  }
1141 
1142  default:
1143  libmesh_error_msg("Invalid mode = " << mode);
1144  }
1145 }
1146 
1147 
1148 
1149 template <>
1150 void Xdr::data_stream (std::complex<double> * val, const unsigned int len, const unsigned int line_break)
1151 {
1152  this->_complex_data_stream(val, len, line_break);
1153 }
1154 
1155 
1156 
1157 template <>
1158 void Xdr::data_stream (std::complex<long double> * val, const unsigned int len, const unsigned int line_break)
1159 {
1160  this->_complex_data_stream(val, len, line_break);
1161 }
1162 
1163 
1164 
1165 template <typename T>
1166 void Xdr::_complex_data_stream (std::complex<T> * val, const unsigned int len, const unsigned int line_break)
1167 {
1168  switch (mode)
1169  {
1170  case ENCODE:
1171  case DECODE:
1172  {
1173 #ifdef LIBMESH_HAVE_XDR
1174 
1175  libmesh_assert (this->is_open());
1176 
1177  // FIXME[JWP]: How to implement this for long double? Mac OS
1178  // X defines 'xdr_quadruple' but AFAICT, it does not exist for
1179  // Linux... for now, reading/writing XDR files with long
1180  // doubles drops back to double precision, but you can still
1181  // write long double ASCII files of course.
1182 
1183  if (len > 0)
1184  {
1185  std::vector<double> io_buffer (2*len);
1186 
1187  // Fill io_buffer if we are writing.
1188  if (mode == ENCODE)
1189  for (unsigned int i=0, cnt=0; i<len; i++)
1190  {
1191  io_buffer[cnt++] = val[i].real();
1192  io_buffer[cnt++] = val[i].imag();
1193  }
1194 
1195  xdr_vector(xdrs.get(),
1196  reinterpret_cast<char *>(io_buffer.data()),
1197  2*len,
1198  sizeof(double),
1199  (xdrproc_t) xdr_double);
1200 
1201  // Fill val array if we are reading.
1202  if (mode == DECODE)
1203  for (unsigned int i=0, cnt=0; i<len; i++)
1204  {
1205  double re = io_buffer[cnt++];
1206  double im = io_buffer[cnt++];
1207  val[i] = std::complex<T>(re, im);
1208  }
1209  }
1210 #else
1211 
1212  libmesh_error_msg("ERROR: Functionality is not available.\n" \
1213  << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
1214  << "The XDR interface is not available in this installation");
1215 
1216 #endif
1217  return;
1218  }
1219 
1220  case READ:
1221  {
1222  libmesh_assert(in.get());
1223  libmesh_assert (in->good());
1224 
1225  for (unsigned int i=0; i<len; i++)
1226  {
1227  libmesh_assert(in.get());
1228  libmesh_assert (in->good());
1229  T re, im;
1230  *in >> re >> im;
1231  val[i] = std::complex<T>(re,im);
1232  }
1233 
1234  return;
1235  }
1236 
1237  case WRITE:
1238  {
1239  libmesh_assert(out.get());
1240  libmesh_assert (out->good());
1241 
1242 
1243  // Save stream flags
1244  std::ios_base::fmtflags out_flags = out->flags();
1245 
1246  // We will use scientific notation with a precision of
1247  // 'max_digits10' digits in the following output. The desired
1248  // precision and format will automatically determine the
1249  // width. Note: digit10 is the number of digits (in decimal
1250  // base) that can be represented without change. Equivalent
1251  // to FLT_DIG, DBL_DIG or LDBL_DIG for floating types.
1252  *out << std::scientific
1253  << std::setprecision(std::numeric_limits<T>::max_digits10);
1254 
1255  if (line_break == libMesh::invalid_uint)
1256  for (unsigned int i=0; i<len; i++)
1257  {
1258  libmesh_assert(out.get());
1259  libmesh_assert (out->good());
1260  *out << val[i].real() << ' ' << val[i].imag() << ' ';
1261  }
1262  else
1263  {
1264  const unsigned imax = std::min(line_break, len);
1265  unsigned int cnt=0;
1266  while (cnt < len)
1267  {
1268  for (unsigned int i=0; (i<imax && cnt<len); i++)
1269  {
1270  libmesh_assert(out.get());
1271  libmesh_assert (out->good());
1272  *out << val[cnt].real() << ' ' << val[cnt].imag();
1273  cnt++;
1274 
1275  // Write a space unless this is the last character on the current line.
1276  if (i+1 != imax)
1277  *out << " ";
1278  }
1279  libmesh_assert(out.get());
1280  libmesh_assert (out->good());
1281  *out << '\n';
1282  }
1283  }
1284 
1285  // Restore stream flags
1286  out->flags(out_flags);
1287 
1288  return;
1289  }
1290 
1291  default:
1292  libmesh_error_msg("Invalid mode = " << mode);
1293  }
1294 }
1295 
1296 
1297 
1298 void Xdr::comment (std::string & comment_in)
1299 {
1300  switch (mode)
1301  {
1302  case ENCODE:
1303  case DECODE:
1304  {
1305  return;
1306  }
1307 
1308  case READ:
1309  {
1310  libmesh_assert(in.get());
1311  libmesh_assert (in->good());
1312  in->getline(comm, comm_len);
1313  return;
1314  }
1315 
1316  case WRITE:
1317  {
1318  libmesh_assert(out.get());
1319  libmesh_assert (out->good());
1320  *out << "\t " << comment_in << '\n';
1321  return;
1322  }
1323 
1324  default:
1325  libmesh_error_msg("Invalid mode = " << mode);
1326  }
1327 }
1328 
1329 
1330 #undef xdr_REAL
1331 
1332 
1333 //
1334 template LIBMESH_EXPORT void Xdr::data<int> (int &, std::string_view);
1335 template LIBMESH_EXPORT void Xdr::data<unsigned int> (unsigned int &, std::string_view);
1336 template LIBMESH_EXPORT void Xdr::data<unsigned short int> (unsigned short int &, std::string_view);
1337 template LIBMESH_EXPORT void Xdr::data<short int> (short int &, std::string_view);
1338 template LIBMESH_EXPORT void Xdr::data<unsigned long int> (unsigned long int &, std::string_view);
1339 template LIBMESH_EXPORT void Xdr::data<unsigned long long> (unsigned long long &, std::string_view);
1340 template LIBMESH_EXPORT void Xdr::data<long int> (long int &, std::string_view);
1341 template LIBMESH_EXPORT void Xdr::data<long long> (long long &, std::string_view);
1342 template LIBMESH_EXPORT void Xdr::data<char> (char &, std::string_view);
1343 template LIBMESH_EXPORT void Xdr::data<signed char> (signed char &, std::string_view);
1344 template LIBMESH_EXPORT void Xdr::data<unsigned char> (unsigned char &, std::string_view);
1345 template LIBMESH_EXPORT void Xdr::data<float> (float &, std::string_view);
1346 template LIBMESH_EXPORT void Xdr::data<double> (double &, std::string_view);
1347 template LIBMESH_EXPORT void Xdr::data<long double> (long double &, std::string_view);
1348 template LIBMESH_EXPORT void Xdr::data<std::complex<float>> (std::complex<float> &, std::string_view);
1349 template LIBMESH_EXPORT void Xdr::data<std::complex<double>> (std::complex<double> &, std::string_view);
1350 template LIBMESH_EXPORT void Xdr::data<std::complex<long double>> (std::complex<long double> &, std::string_view);
1351 template LIBMESH_EXPORT void Xdr::data<std::string> (std::string &, std::string_view);
1352 template LIBMESH_EXPORT void Xdr::data<std::vector<int>> (std::vector<int> &, std::string_view);
1353 template LIBMESH_EXPORT void Xdr::data<std::vector<unsigned int>> (std::vector<unsigned int> &, std::string_view);
1354 template LIBMESH_EXPORT void Xdr::data<std::vector<short int>> (std::vector<short int> &, std::string_view);
1355 template LIBMESH_EXPORT void Xdr::data<std::vector<unsigned short int>> (std::vector<unsigned short int> &, std::string_view);
1356 template LIBMESH_EXPORT void Xdr::data<std::vector<long int>> (std::vector<long int> &, std::string_view);
1357 template LIBMESH_EXPORT void Xdr::data<std::vector<long long>> (std::vector<long long> &, std::string_view);
1358 template LIBMESH_EXPORT void Xdr::data<std::vector<unsigned long int>> (std::vector<unsigned long int> &, std::string_view);
1359 template LIBMESH_EXPORT void Xdr::data<std::vector<unsigned long long>> (std::vector<unsigned long long> &, std::string_view);
1360 template LIBMESH_EXPORT void Xdr::data<std::vector<char>> (std::vector<char> &, std::string_view);
1361 template LIBMESH_EXPORT void Xdr::data<std::vector<signed char>> (std::vector<signed char> &, std::string_view);
1362 template LIBMESH_EXPORT void Xdr::data<std::vector<unsigned char>> (std::vector<unsigned char> &, std::string_view);
1363 template LIBMESH_EXPORT void Xdr::data<std::vector<float>> (std::vector<float> &, std::string_view);
1364 template LIBMESH_EXPORT void Xdr::data<std::vector<double>> (std::vector<double> &, std::string_view);
1365 template LIBMESH_EXPORT void Xdr::data<std::vector<long double>> (std::vector<long double> &, std::string_view);
1366 template LIBMESH_EXPORT void Xdr::data<std::vector<std::complex<float>>> (std::vector<std::complex<float>> &, std::string_view);
1367 template LIBMESH_EXPORT void Xdr::data<std::vector<std::complex<double>>> (std::vector<std::complex<double>> &, std::string_view);
1368 template LIBMESH_EXPORT void Xdr::data<std::vector<std::complex<long double>>> (std::vector<std::complex<long double>> &, std::string_view);
1369 template LIBMESH_EXPORT void Xdr::data<std::vector<std::string>> (std::vector<std::string> &, std::string_view);
1370 template LIBMESH_EXPORT void Xdr::data_stream<unsigned char> (unsigned char * val, const unsigned int len, const unsigned int line_break);
1371 template LIBMESH_EXPORT void Xdr::data_stream<short int> (short int * val, const unsigned int len, const unsigned int line_break);
1372 template LIBMESH_EXPORT void Xdr::data_stream<int> (int * val, const unsigned int len, const unsigned int line_break);
1373 template LIBMESH_EXPORT void Xdr::data_stream<long long> (long long * val, const unsigned int len, const unsigned int line_break);
1374 template LIBMESH_EXPORT void Xdr::data_stream<unsigned short int> (unsigned short int * val, const unsigned int len, const unsigned int line_break);
1375 template LIBMESH_EXPORT void Xdr::data_stream<unsigned int> (unsigned int * val, const unsigned int len, const unsigned int line_break);
1376 template LIBMESH_EXPORT void Xdr::data_stream<unsigned long int> (unsigned long int * val, const unsigned int len, const unsigned int line_break);
1377 template LIBMESH_EXPORT void Xdr::data_stream<unsigned long long> (unsigned long long * val, const unsigned int len, const unsigned int line_break);
1378 
1379 #ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
1380 template LIBMESH_EXPORT void Xdr::data<Real> (Real &, std::string_view);
1381 template LIBMESH_EXPORT void Xdr::data<std::complex<Real>> (std::complex<Real> &, std::string_view);
1382 template LIBMESH_EXPORT void Xdr::data<std::vector<Real>> (std::vector<Real> &, std::string_view);
1383 template LIBMESH_EXPORT void Xdr::data<std::vector<std::complex<Real>>> (std::vector<std::complex<Real>> &, std::string_view);
1384 #endif
1385 
1386 } // namespace libMesh
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
Definition: elem_quality.C:42
~Xdr()
Destructor.
Definition: xdr_cxx.C:159
FILE * fp
File pointer.
Definition: xdr_cxx.h:252
Xdr(std::string name="", const XdrMODE m=UNKNOWN)
File-based constructor.
Definition: xdr_cxx.C:103
const int comm_len
A buffer to put comment strings into.
Definition: xdr_cxx.h:269
std::string file_name
The file name.
Definition: xdr_cxx.h:239
const unsigned int xdr_MAX_STRING_LENGTH
Definition: xdr_cxx.h:45
void do_write(T &a)
Helper method for writing different data types.
Definition: xdr_cxx.C:729
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
Definition: libmesh.h:310
char comm[xdr_MAX_STRING_LENGTH]
Definition: xdr_cxx.h:270
void comment(std::string &)
Writes or reads (ignores) a comment line.
Definition: xdr_cxx.C:1298
void close()
Closes the file if it is open.
Definition: xdr_cxx.C:277
bool xzipped_file
Definition: xdr_cxx.h:275
bool bzipped_file
Definition: xdr_cxx.h:275
The libMesh namespace provides an interface to certain functionality in the library.
const XdrMODE mode
The mode used for accessing the file.
Definition: xdr_cxx.h:234
void do_read(T &a)
Helper method for reading different data types.
Definition: xdr_cxx.C:664
bool gzipped_file
Are we reading/writing zipped files?
Definition: xdr_cxx.h:275
void _complex_data_stream(std::complex< T > *val, const unsigned int len, const unsigned int line_break)
Helper method for complex types.
Definition: xdr_cxx.C:1166
XdrMODE
Defines an enum for read/write mode in Xdr format.
Definition: enum_xdr_mode.h:35
void data(T &a, std::string_view comment="")
Inputs or outputs a single value.
Definition: xdr_cxx.C:778
std::unique_ptr< std::istream > in
The input file stream.
Definition: xdr_cxx.h:259
std::unique_ptr< std::ostream > out
The output file stream.
Definition: xdr_cxx.h:264
std::string unzip_file(std::string_view name)
Create an unzipped copy of a bz2 or xz file, returning the name of the now-unzipped file that can be ...
Definition: utility.C:164
libmesh_assert(ctx)
bool is_eof()
Definition: xdr_cxx.C:395
std::unique_ptr< XDR > xdrs
Pointer to the standard XDR struct.
Definition: xdr_cxx.h:247
static const unsigned int next[3]
A lookup table for the increment modulo 3 operation, for iterating through the three nodes per elemen...
void _xfp_data_stream(XFP *val, const unsigned int len, #ifdef LIBMESH_HAVE_XDR xdrproc_t #else void *#endif xdr_proc, const unsigned int line_break, const int n_digits)
Helper method for extended FP types.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
bool is_open() const
Definition: xdr_cxx.C:345
OStreamProxy out
void open(std::string name)
Opens the file.
Definition: xdr_cxx.C:166
void data_stream(T *val, const unsigned int len, const unsigned int line_break=libMesh::invalid_uint)
Inputs or outputs a raw data stream.
Definition: xdr_cxx.C:843