LCOV - code coverage report
Current view: top level - src/utils - xdr_cxx.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4475 (55045b) with base a68cc6 Lines: 335 532 63.0 %
Date: 2026-06-03 14:29:06 Functions: 63 188 33.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2026 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             : #include <tuple> // For XDR API probing trick
      27             : 
      28             : // Local includes
      29             : #include "libmesh/xdr_cxx.h"
      30             : #include "libmesh/libmesh_logging.h"
      31             : #ifdef LIBMESH_HAVE_GZSTREAM
      32             : # include "gzstream.h" // For reading/writing compressed streams
      33             : #endif
      34             : #include "libmesh/utility.h" // unzip_file
      35             : 
      36             : #ifdef LIBMESH_HAVE_UNISTD_H
      37             : #include <unistd.h> // for getpid() on Unix
      38             : #endif
      39             : #ifdef LIBMESH_HAVE_PROCESS_H
      40             : #include <process.h> // for getpid() on Windows
      41             : #endif
      42             : 
      43             : // Anonymous namespace for implementation details.
      44             : namespace {
      45             : 
      46             : // Nasty hacks for reading/writing zipped files
      47           0 : void bzip_file (std::string_view unzipped_name)
      48             : {
      49             : #ifdef LIBMESH_HAVE_BZIP
      50           0 :   LOG_SCOPE("system(bzip2)", "XdrIO");
      51             : 
      52           0 :   std::string system_string = "bzip2 -f ";
      53           0 :   system_string += unzipped_name;
      54           0 :   if (std::system(system_string.c_str()))
      55           0 :     libmesh_file_error(system_string);
      56             : #else
      57             :   libmesh_error_msg("ERROR: need bzip2/bunzip2 to create " << unzipped_name << ".bz2");
      58             : #endif
      59           0 : }
      60             : 
      61           0 : void xzip_file (std::string_view unzipped_name)
      62             : {
      63             : #ifdef LIBMESH_HAVE_XZ
      64           0 :   LOG_SCOPE("system(xz)", "XdrIO");
      65             : 
      66           0 :   std::string system_string = "xz -f ";
      67           0 :   system_string += unzipped_name;
      68           0 :   if (std::system(system_string.c_str()))
      69           0 :     libmesh_file_error(system_string);
      70             : #else
      71             :   libmesh_error_msg("ERROR: need xz to create " << unzipped_name << ".xz");
      72             : #endif
      73           0 : }
      74             : 
      75             : 
      76             : // remove an unzipped file
      77           0 : void remove_unzipped_file (std::string_view name)
      78             : {
      79           0 :   std::ostringstream pid_suffix;
      80           0 :   pid_suffix << '_' << getpid();
      81             : 
      82             :   // If we temporarily decompressed a file, remove the
      83             :   // uncompressed version
      84           0 :   if (libMesh::Utility::ends_with(name, ".bz2"))
      85             :     {
      86           0 :       std::string new_name(name.begin(), name.end()-4);
      87           0 :       new_name += pid_suffix.str();
      88           0 :       std::remove(new_name.c_str());
      89             :     }
      90           0 :   if (libMesh::Utility::ends_with(name, ".xz"))
      91             :     {
      92           0 :       std::string new_name(name.begin(), name.end()-3);
      93           0 :       new_name += pid_suffix.str();
      94           0 :       std::remove(new_name.c_str());
      95             :     }
      96           0 : }
      97             : }
      98             : 
      99             : namespace libMesh
     100             : {
     101             : 
     102             : //-------------------------------------------------------------
     103             : // Xdr class implementation
     104       43824 : Xdr::Xdr (std::string name,
     105       43824 :           const XdrMODE m) :
     106       41114 :   mode(m),
     107       42469 :   file_name(std::move(name)),
     108             : #ifdef LIBMESH_HAVE_XDR
     109       41114 :   fp(nullptr),
     110             : #endif
     111       41114 :   in(),
     112       41114 :   out(),
     113       41114 :   comm_len(xdr_MAX_STRING_LENGTH),
     114       41114 :   gzipped_file(false),
     115       41114 :   bzipped_file(false),
     116       41114 :   xzipped_file(false),
     117       46534 :   version_number(LIBMESH_VERSION_ID(LIBMESH_MAJOR_VERSION, LIBMESH_MINOR_VERSION, LIBMESH_MICRO_VERSION))
     118             : {
     119       43824 :   this->open(file_name);
     120       43824 : }
     121             : 
     122             : 
     123             : 
     124         142 : Xdr::Xdr (std::ostream & stream) :
     125         134 :   mode(WRITE),
     126         134 :   file_name(),
     127             : #ifdef LIBMESH_HAVE_XDR
     128         134 :   fp(nullptr),
     129             : #endif
     130         134 :   in(),
     131         142 :   out(std::make_unique<std::ostream>(stream.rdbuf())),
     132         134 :   comm_len(xdr_MAX_STRING_LENGTH),
     133         134 :   gzipped_file(false),
     134         134 :   bzipped_file(false),
     135         134 :   xzipped_file(false),
     136         154 :   version_number(LIBMESH_VERSION_ID(LIBMESH_MAJOR_VERSION, LIBMESH_MINOR_VERSION, LIBMESH_MICRO_VERSION))
     137             : {
     138         142 : }
     139             : 
     140             : 
     141             : 
     142         142 : Xdr::Xdr (std::istream & stream) :
     143         134 :   mode(READ),
     144         134 :   file_name(),
     145             : #ifdef LIBMESH_HAVE_XDR
     146         134 :   fp(nullptr),
     147             : #endif
     148         138 :   in(std::make_unique<std::istream>(stream.rdbuf())),
     149             :   out(),
     150         134 :   comm_len(xdr_MAX_STRING_LENGTH),
     151         134 :   gzipped_file(false),
     152         134 :   bzipped_file(false),
     153         134 :   xzipped_file(false),
     154         146 :   version_number(LIBMESH_VERSION_ID(LIBMESH_MAJOR_VERSION, LIBMESH_MINOR_VERSION, LIBMESH_MICRO_VERSION))
     155             : {
     156         142 : }
     157             : 
     158             : 
     159             : 
     160       45471 : Xdr::~Xdr()
     161             : {
     162       44108 :   this->close();
     163       44108 : }
     164             : 
     165             : 
     166             : 
     167       43824 : void Xdr::open (std::string name)
     168             : {
     169       43824 :   file_name = std::move(name);
     170             : 
     171       43824 :   if (file_name == "")
     172         526 :     return;
     173             : 
     174       13472 :   switch (mode)
     175             :     {
     176        8213 :     case ENCODE:
     177             :     case DECODE:
     178             :       {
     179             : #ifdef LIBMESH_HAVE_XDR
     180             : 
     181       14353 :         fp = fopen(file_name.c_str(), (mode == ENCODE) ? "w" : "r");
     182        8213 :         if (!fp)
     183           0 :           libmesh_file_error(file_name.c_str());
     184       15686 :         xdrs = std::make_unique<XDR>();
     185        8683 :         xdrstdio_create (xdrs.get(), fp, (mode == ENCODE) ? XDR_ENCODE : XDR_DECODE);
     186             : #else
     187             : 
     188             :         libmesh_error_msg("ERROR: Functionality is not available.\n" \
     189             :                           << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
     190             :                           << "The XDR interface is not available in this installation");
     191             : 
     192             : #endif
     193        8213 :         return;
     194             : 
     195             :       }
     196             : 
     197         281 :     case READ:
     198             :       {
     199        3199 :         gzipped_file = Utility::ends_with(file_name, ".gz");
     200        3199 :         bzipped_file = Utility::ends_with(file_name, ".bz2");
     201        3199 :         xzipped_file = Utility::ends_with(file_name, ".xz");
     202             : 
     203        3199 :         if (gzipped_file)
     204             :           {
     205             : #ifdef LIBMESH_HAVE_GZSTREAM
     206          39 :             auto inf = std::make_unique<igzstream>();
     207           3 :             libmesh_assert(inf);
     208           3 :             inf->open(file_name.c_str(), std::ios::in);
     209          33 :             in = std::move(inf);
     210             : #else
     211             :             libmesh_error_msg("ERROR: need gzstream to handle .gz files!!!");
     212             : #endif
     213          30 :           }
     214             :         else
     215             :           {
     216        3441 :             auto inf = std::make_unique<std::ifstream>();
     217         278 :             libmesh_assert(inf);
     218             : 
     219        3441 :             std::string new_name = Utility::unzip_file(file_name);
     220             : 
     221        3163 :             inf->open(new_name.c_str(), std::ios::in);
     222        2885 :             in = std::move(inf);
     223        2607 :           }
     224             : 
     225         281 :         libmesh_assert(in.get());
     226             : 
     227        3480 :         if (!in->good())
     228           0 :           libmesh_file_error(file_name);
     229         281 :         return;
     230             :       }
     231             : 
     232        2060 :     case WRITE:
     233             :       {
     234        2060 :         gzipped_file = (file_name.rfind(".gz") == file_name.size() - 3);
     235        2060 :         bzipped_file = (file_name.rfind(".bz2") == file_name.size() - 4);
     236        2060 :         xzipped_file = (file_name.rfind(".xz") == file_name.size() - 3);
     237             : 
     238        2060 :         if (gzipped_file)
     239             :           {
     240             : #ifdef LIBMESH_HAVE_GZSTREAM
     241           0 :             auto outf = std::make_unique<ogzstream>();
     242           0 :             libmesh_assert(outf);
     243           0 :             outf->open(file_name.c_str(), std::ios::out);
     244           0 :             out = std::move(outf);
     245             : #else
     246             :             libmesh_error_msg("ERROR: need gzstream to handle .gz files!!!");
     247             : #endif
     248           0 :           }
     249             :         else
     250             :           {
     251        2238 :             auto outf = std::make_unique<std::ofstream>();
     252         178 :             libmesh_assert(outf);
     253             : 
     254        2060 :             std::string new_name = file_name;
     255             : 
     256        2060 :             if (bzipped_file)
     257           0 :               new_name.erase(new_name.end() - 4, new_name.end());
     258             : 
     259        2060 :             if (xzipped_file)
     260           0 :               new_name.erase(new_name.end() - 3, new_name.end());
     261             : 
     262        2060 :             outf->open(new_name.c_str(), std::ios::out);
     263        1882 :             out = std::move(outf);
     264        1704 :           }
     265             : 
     266         178 :         libmesh_assert(out.get());
     267         178 :         libmesh_assert (out->good());
     268         178 :         return;
     269             :       }
     270             : 
     271           0 :     default:
     272           0 :       libmesh_error_msg("Invalid mode = " << mode);
     273             :     }
     274             : }
     275             : 
     276             : 
     277             : 
     278       64561 : void Xdr::close ()
     279             : {
     280       64561 :   switch (mode)
     281             :     {
     282       22939 :     case ENCODE:
     283             :     case DECODE:
     284             :       {
     285             : #ifdef LIBMESH_HAVE_XDR
     286             : 
     287       22939 :         if (xdrs)
     288             :           {
     289        8213 :             xdr_destroy (xdrs.get());
     290         370 :             xdrs.reset();
     291             :           }
     292             : 
     293       22939 :         if (fp)
     294             :           {
     295        8213 :             fflush(fp);
     296        8213 :             fclose(fp);
     297        8213 :             fp = nullptr;
     298             :           }
     299             : #else
     300             : 
     301             :         libmesh_error_msg("ERROR: Functionality is not available.\n" \
     302             :                           << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
     303             :                           << "The XDR interface is not available in this installation");
     304             : 
     305             : #endif
     306       22939 :         file_name = "";
     307         785 :         return;
     308             :       }
     309             : 
     310       18442 :     case READ:
     311             :       {
     312       18442 :         if (in.get() != nullptr)
     313             :           {
     314         285 :             in.reset();
     315             : 
     316        3341 :             if (bzipped_file || xzipped_file)
     317           0 :               remove_unzipped_file(file_name);
     318             :           }
     319       18442 :         file_name = "";
     320         554 :         return;
     321             :       }
     322             : 
     323       23180 :     case WRITE:
     324             :       {
     325       23180 :         if (out.get() != nullptr)
     326             :           {
     327         182 :             out.reset();
     328             : 
     329        2202 :             if (bzipped_file)
     330           0 :               bzip_file(std::string(file_name.begin(), file_name.end()-4));
     331             : 
     332        2202 :             else if (xzipped_file)
     333           0 :               xzip_file(std::string(file_name.begin(), file_name.end()-3));
     334             :           }
     335       23180 :         file_name = "";
     336         677 :         return;
     337             :       }
     338             : 
     339           0 :     default:
     340           0 :       libmesh_error_msg("Invalid mode = " << mode);
     341             :     }
     342             : }
     343             : 
     344             : 
     345             : 
     346       81825 : bool Xdr::is_open() const
     347             : {
     348       81825 :   switch (mode)
     349             :     {
     350       81825 :     case ENCODE:
     351             :     case DECODE:
     352             :       {
     353             : #ifdef LIBMESH_HAVE_XDR
     354             : 
     355       81825 :         if (fp)
     356       81825 :           if (xdrs)
     357       81825 :             return true;
     358             : 
     359           0 :         return false;
     360             : 
     361             : #else
     362             : 
     363             :         libmesh_error_msg("ERROR: Functionality is not available.\n"    \
     364             :                           << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
     365             :                           << "The XDR interface is not available in this installation");
     366             : 
     367             :         return false;
     368             : 
     369             : #endif
     370             : 
     371             :       }
     372             : 
     373           0 :     case READ:
     374             :       {
     375           0 :         if (in.get() != nullptr)
     376           0 :           return in->good();
     377           0 :         return false;
     378             :       }
     379             : 
     380           0 :     case WRITE:
     381             :       {
     382           0 :         if (out.get() != nullptr)
     383           0 :           return out->good();
     384           0 :         return false;
     385             :       }
     386             : 
     387           0 :     default:
     388           0 :       libmesh_error_msg("Invalid mode = " << mode);
     389             :     }
     390             : 
     391             :   return false;
     392             : }
     393             : 
     394             : 
     395             : 
     396           0 : bool Xdr::is_eof()
     397             : {
     398           0 :   switch (mode)
     399             :     {
     400           0 :     case ENCODE:
     401             :     case DECODE:
     402             :       {
     403             : #ifdef LIBMESH_HAVE_XDR
     404           0 :         libmesh_assert(fp);
     405             : 
     406             :         // Are we already at eof?
     407           0 :         if (feof(fp))
     408           0 :           return true;
     409             : 
     410             :         // Or about to reach eof?
     411           0 :         int next = fgetc(fp);
     412           0 :         if (next == EOF)
     413             :           {
     414             :             // We should *only* be at EOF, not otherwise broken
     415           0 :             libmesh_assert(feof(fp));
     416           0 :             libmesh_assert(!ferror(fp));
     417             : 
     418             :             // Reset the EOF indicator
     419           0 :             clearerr(fp);
     420           0 :             libmesh_assert(!ferror(fp));
     421             : 
     422             :             // We saw EOF
     423           0 :             return true;
     424             :           }
     425             : 
     426             :         // We didn't see EOF; restore whatever we did see.
     427           0 :         ungetc(next, fp);
     428           0 :         break;
     429             : #else
     430             : 
     431             :         libmesh_error_msg("ERROR: Functionality is not available.\n"    \
     432             :                           << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
     433             :                           << "The XDR interface is not available in this installation");
     434             : 
     435             :         return false;
     436             : 
     437             : #endif
     438             : 
     439             :       }
     440           0 :     case READ:
     441             :       {
     442           0 :         libmesh_assert(in.get());
     443             : 
     444             :         // Are we already at eof?
     445           0 :         if (in->eof())
     446           0 :           return true;
     447             : 
     448             :         // Or about to reach eof?
     449           0 :         int next = in->peek();
     450           0 :         if (next == EOF)
     451             :           {
     452             :             // We should *only* be at EOF, not otherwise broken
     453           0 :             libmesh_assert(in->eof());
     454           0 :             libmesh_assert(!in->fail());
     455             : 
     456             :             // Reset the EOF indicator
     457           0 :             in->clear();
     458           0 :             libmesh_assert(in->good());
     459             : 
     460             :             // We saw EOF
     461           0 :             return true;
     462             :           }
     463           0 :         break;
     464             :       }
     465           0 :     default:
     466           0 :       libmesh_error();
     467             :     }
     468             : 
     469           0 :   return false;
     470             : }
     471             : 
     472             : 
     473             : 
     474             : #ifdef LIBMESH_HAVE_XDR
     475             : 
     476             : // Anonymous namespace for Xdr::data helper functions
     477             : namespace
     478             : {
     479             : 
     480             : template <typename T>
     481             : xdrproc_t xdr_translator();
     482             : 
     483             : template <typename T>
     484       50351 : bool xdr_translate(XDR * x, T & a)
     485             : {
     486     1320447 :   return (xdr_translator<T>())(x, &a, 0);
     487             : }
     488             : 
     489             : template <>
     490       39714 : bool xdr_translate(XDR * x,
     491             :                    std::string & s)
     492             : {
     493             :   char sptr[xdr_MAX_STRING_LENGTH+1];
     494       36507 :   std::copy(s.begin(), s.end(), sptr);
     495       39714 :   sptr[s.size()] = 0;
     496        3207 :   unsigned int length = xdr_MAX_STRING_LENGTH;
     497             : 
     498             :   // Get a pointer to the beginning of the buffer.  We need to pass
     499             :   // its address to the xdr API.
     500       39714 :   char * begin = sptr;
     501       39714 :   bool b = xdr_string(x, &begin, length);
     502             : 
     503             :   // This is necessary when reading, but inefficient when writing...
     504       39714 :   length = cast_int<unsigned int>(std::strlen(sptr));
     505        3207 :   s.resize(length);
     506       36507 :   std::copy(sptr, sptr+length, s.begin());
     507             : 
     508       39714 :   return b;
     509             : }
     510             : 
     511             : template <typename T>
     512       17154 : bool xdr_translate(XDR * x, std::complex<T> & a)
     513             : {
     514       17154 :   T r = a.real(), i = a.imag();
     515           0 :   bool b1 = xdr_translate(x, r);
     516           0 :   bool b2 = xdr_translate(x, i);
     517       17154 :   a = std::complex<T>(r,i);
     518       17154 :   return (b1 && b2);
     519             : }
     520             : 
     521             : template <typename T>
     522        9840 : bool xdr_translate(XDR * x, std::vector<T> & a)
     523             : {
     524        9840 :   unsigned int length = cast_int<unsigned int>(a.size());
     525        9840 :   xdr_u_int(x, &length);
     526        9840 :   if (length > 0)
     527             :     {
     528        7348 :       a.resize(length);
     529        7348 :       return xdr_vector(x, reinterpret_cast<char *>(a.data()), length, sizeof(T),
     530        7348 :                         xdr_translator<T>());
     531             :     }
     532             :   else
     533         160 :     return true;
     534             : }
     535             : 
     536             : template <typename T>
     537           0 : bool xdr_translate(XDR * x, std::vector<std::complex<T>> & a)
     538             : {
     539           0 :   unsigned int length = cast_int<unsigned int>(a.size());
     540           0 :   bool b = xdr_u_int(x, &length);
     541           0 :   a.resize(length);
     542           0 :   for (auto & val : a)
     543           0 :     if (!xdr_translate(x, val))
     544           0 :       b = false;
     545           0 :   return b;
     546             : }
     547             : 
     548             : template <>
     549        8244 : bool xdr_translate(XDR * x, std::vector<std::string> & s)
     550             : {
     551        8244 :   unsigned int length = cast_int<unsigned int>(s.size());
     552        8244 :   bool b = xdr_u_int(x, &length);
     553        8244 :   s.resize(length);
     554       38196 :   for (auto & val : s)
     555       29952 :     if (!xdr_translate(x, val))
     556           0 :       b = false;
     557        8244 :   return b;
     558             : }
     559             : 
     560             : 
     561             : // https://lists.libguestfs.org/archives/list/[email protected]/message/JNRVVA5VOIDBBQHTF7QYRSWZ2AQG4P7U/
     562             : //
     563             : //  With Mac OS X 10.9, xdrproc_t is no longer defined as:
     564             : //  typedef bool_t (*xdrproc_t)(XDR *, ...);
     565             : //  but instead as:
     566             : //  typdef bool_t (*xdrproc_t)(XDR *, void *, unsigned int);
     567             : //  For reference, Linux systems typically define it as:
     568             : //  typedef bool_t (*xdrproc_t)(XDR *, void *, ...);
     569             : //
     570             : // I'm not sure why it took over a decade later, but we're starting to
     571             : // get "converts to incompatible function type" errors on some OSX
     572             : // builds when trying to pass XDR's own functions to xdrproc_t
     573             : // arguments - apparently because the xdr_foo functions now only take
     574             : // two arguments?  We'll add some shims to convert them.
     575             : 
     576             : #ifdef __APPLE__
     577             : 
     578             : // We want these shims to be as robust as possible, and it turns out
     579             : // that *every* XDR implementation sucks in its own way: in TIRPC,
     580             : // xdr_longlong_t does not actually take a long long *, it takes a
     581             : // quad_t *, which my system defines as long *.  My long and long long
     582             : // are the same size, but a pointer to one can't be implicitly
     583             : // converted into a pointer to the other.  So, we'll do crazy template
     584             : // tricks to make sure that, even when we reinterpret_cast that
     585             : // pointer, we're not changing the underlying meaning.
     586             : 
     587             : template<typename F>
     588             : struct function_signature;
     589             : 
     590             : template<typename returnval, typename... Args>
     591             : struct function_signature<returnval (*)(Args...)>
     592             : {
     593             :   template <std::size_t N>
     594             :   struct arg {
     595             :     static_assert(N < sizeof...(Args), "Function argument index too high");
     596             :     using type = typename std::tuple_element<N, std::tuple<Args...>>::type;
     597             :   };
     598             : };
     599             : 
     600             : #define libmesh_define_xdr(ourfunc, theirfunc, cxx_type) \
     601             :   bool_t libmesh_xdr_##ourfunc(XDR * x, cxx_type * v, unsigned int) { \
     602             :     using api_type = \
     603             :       std::remove_pointer<typename function_signature<decltype(&xdr_##theirfunc)>::template arg<1>::type>::type; \
     604             :     static_assert(sizeof(cxx_type) == \
     605             :                   sizeof(api_type), \
     606             :                   "Cannot safely cast data for use with XDR"); \
     607             :     return xdr_##theirfunc(x, reinterpret_cast<api_type *>(v)); \
     608             :   }
     609             : 
     610             : // In my OSX SDK, xdr_long is defined to take int*, not long*, despite
     611             : // their sizes not matching.  We'll use the long long* functions to be
     612             : // safe while we wait for Apple programmers to repent of their sins.
     613             : #ifdef __LP64__
     614             : libmesh_define_xdr(long, longlong_t, long long)
     615             : libmesh_define_xdr(u_long, u_longlong_t, unsigned long long)
     616             : #else
     617             : libmesh_define_xdr(long, long, long)
     618             : libmesh_define_xdr(u_long, u_long, unsigned long)
     619             : #endif
     620             : 
     621             : #else
     622             :   #define libmesh_define_xdr(ourfunc, theirfunc, type) \
     623             :     const xdrproc_t libmesh_xdr_##ourfunc = (xdrproc_t)xdr_##theirfunc;
     624             : 
     625             : libmesh_define_xdr(long, long, long)
     626             : libmesh_define_xdr(u_long, u_long, unsigned long)
     627             : #endif
     628             : 
     629             : libmesh_define_xdr(char, char, char)
     630             : libmesh_define_xdr(short, short, short)
     631             : libmesh_define_xdr(int, int, int)
     632             : libmesh_define_xdr(longlong_t, longlong_t, long long)
     633             : libmesh_define_xdr(u_char, u_char, unsigned char)
     634             : libmesh_define_xdr(u_short, u_short, unsigned short)
     635             : libmesh_define_xdr(u_int, u_int, unsigned int)
     636             : libmesh_define_xdr(u_longlong_t, u_longlong_t, unsigned long long)
     637             : libmesh_define_xdr(float, float, float)
     638             : libmesh_define_xdr(double, double, double)
     639             : 
     640             : 
     641             : template <>
     642          90 : xdrproc_t xdr_translator<int>()
     643             : {
     644             :   // Don't let XDR truncate anything on systems where int is 64-bit;
     645             :   // xdr_int is hard-coded to write 32 bits.
     646             :   if (sizeof(int) <= 4)
     647          90 :     return (xdrproc_t)(libmesh_xdr_int);
     648             :   else if (sizeof(int) == sizeof(long long))
     649             :     return (xdrproc_t)(libmesh_xdr_longlong_t);
     650             :   else if (sizeof(int) == sizeof(long))
     651             :     return (xdrproc_t)(libmesh_xdr_long);
     652             :   else
     653             :     libmesh_error();
     654             : }
     655             : 
     656             : template <>
     657          76 : xdrproc_t xdr_translator<unsigned int>()
     658             : {
     659             :   // Don't let XDR truncate anything on systems where int is 64-bit;
     660             :   // xdr_u_int is hard-coded to write 32 bits.
     661             :   if (sizeof(unsigned int) <= 4)
     662          76 :     return (xdrproc_t)(libmesh_xdr_u_int);
     663             :   else if (sizeof(unsigned int) == sizeof(unsigned long))
     664             :     return (xdrproc_t)(libmesh_xdr_u_long);
     665             :   else if (sizeof(unsigned int) == sizeof(unsigned long long))
     666             :     return (xdrproc_t)(libmesh_xdr_u_longlong_t);
     667             :   else
     668             :     libmesh_error();
     669             : }
     670             : 
     671             : template <>
     672           0 : xdrproc_t xdr_translator<long int>()
     673             : {
     674             :   // Don't let XDR truncate anything on systems where long is 64-bit;
     675             :   // xdr_long is hard-coded to write 32 bits.
     676             :   if (sizeof(long int) <= 4)
     677             :     return (xdrproc_t)(libmesh_xdr_long);
     678             :   else if (sizeof(long int) == sizeof(long long))
     679           0 :     return (xdrproc_t)(libmesh_xdr_longlong_t);
     680             :   else
     681             :     libmesh_error();
     682             : }
     683             : 
     684             : template <>
     685       27853 : xdrproc_t xdr_translator<unsigned long int>()
     686             : {
     687             :   // Don't let XDR truncate anything on systems where long is 64-bit;
     688             :   // xdr_u_long is hard-coded to write 32 bits.  This bit us HARD.
     689             :   if (sizeof(unsigned long int) <= 4)
     690             :     return (xdrproc_t)(libmesh_xdr_u_long);
     691             :   else if (sizeof(unsigned long int) == sizeof(unsigned long long))
     692       27853 :     return (xdrproc_t)(libmesh_xdr_u_longlong_t);
     693             :   else
     694             :     libmesh_error();
     695             : }
     696             : 
     697             : // All the other XDR routines should be safe, unless
     698             : // 1. You're on a system with sizeof(short)==8 and you want to store
     699             : // n>2^32 in a short; this will never happen since we assume
     700             : // sizeof(short) may be as small as 2 bytes and we use at least int
     701             : // for anything larger.
     702             : // 2. You're on a system with sizeof(long long) > 8, and you want to
     703             : // store n>2^64 in one.  Welcome, 22nd century programmers; sorry we
     704             : // couldn't accommodate you.
     705             : template <>
     706           0 : xdrproc_t xdr_translator<long long>() { return (xdrproc_t)(libmesh_xdr_longlong_t); }
     707             : 
     708             : template <>
     709           0 : xdrproc_t xdr_translator<unsigned long long>() { return (xdrproc_t)(libmesh_xdr_u_longlong_t); }
     710             : 
     711             : template <>
     712           0 : xdrproc_t xdr_translator<short int>() { return (xdrproc_t)(libmesh_xdr_short); }
     713             : 
     714             : template <>
     715         780 : xdrproc_t xdr_translator<unsigned short int>() { return (xdrproc_t)(libmesh_xdr_u_short); }
     716             : 
     717             : template <>
     718           0 : xdrproc_t xdr_translator<char>() { return (xdrproc_t)(libmesh_xdr_char); }
     719             : 
     720             : template <>
     721           0 : xdrproc_t xdr_translator<signed char>() { return (xdrproc_t)(libmesh_xdr_char); }
     722             : 
     723             : template <>
     724           0 : xdrproc_t xdr_translator<unsigned char>() { return (xdrproc_t)(libmesh_xdr_u_char); }
     725             : 
     726             : template <>
     727           0 : xdrproc_t xdr_translator<float>() { return (xdrproc_t)(libmesh_xdr_float); }
     728             : 
     729             : template <>
     730       46598 : xdrproc_t xdr_translator<double>() { return (xdrproc_t)(libmesh_xdr_double); }
     731             : 
     732             : // FIXME - no XDR love for quadruple precision; not even for long double?
     733             : template <>
     734           0 : xdrproc_t xdr_translator<long double>() { return (xdrproc_t)(libmesh_xdr_double); }
     735             : 
     736             : #ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
     737             : template <>
     738             : xdrproc_t xdr_translator<Real>() { return (xdrproc_t)(libmesh_xdr_double); }
     739             : #endif
     740             : 
     741             : } // end anonymous namespace
     742             : 
     743             : #endif
     744             : 
     745             : template <typename T>
     746       90110 : void Xdr::do_read(T & a)
     747             : {
     748       32507 :   *in >> a;
     749       90110 :   in->getline(comm, comm_len);
     750       90110 : }
     751             : 
     752             : template <typename T>
     753           0 : void Xdr::do_read(std::complex<T> & a)
     754             : {
     755             :   T r, i;
     756           0 :   *in >> r >> i;
     757           0 :   a = std::complex<T>(r,i);
     758           0 :   in->getline(comm, comm_len);
     759           0 : }
     760             : 
     761             : template <>
     762       24452 : void Xdr::do_read(std::string & a)
     763             : {
     764       24452 :   in->getline(comm, comm_len);
     765             : 
     766        2205 :   a = "";
     767             : 
     768      306175 :   for (unsigned int c=0, sl=std::strlen(comm); c!=sl; c++)
     769             :     {
     770      305036 :       if (comm[c] == '\t')
     771        2104 :         break;
     772      281723 :       a.push_back(comm[c]);
     773             :     }
     774       24452 : }
     775             : 
     776             : template <typename T>
     777       14013 : void Xdr::do_read(std::vector<T> & a)
     778             : {
     779       14013 :   unsigned int length=0;
     780       14013 :   data(length, "# vector length");
     781       14013 :   a.resize(length);
     782             : 
     783       62298 :   for (T & a_i : a)
     784             :     {
     785        4033 :       libmesh_assert(in.get());
     786        4033 :       libmesh_assert (in->good());
     787       23242 :       *in >> a_i;
     788             :     }
     789       14013 :   in->getline(comm, comm_len);
     790       14013 : }
     791             : 
     792             : template <typename T>
     793           0 : void Xdr::do_read(std::vector<std::complex<T>> & a)
     794             : {
     795           0 :   unsigned int length=0;
     796           0 :   data(length, "# vector length x 2 (complex)");
     797           0 :   a.resize(length);
     798             : 
     799           0 :   for (std::complex<T> & a_i : a)
     800             :     {
     801             :       T r, im;
     802           0 :       libmesh_assert(in.get());
     803           0 :       libmesh_assert (in->good());
     804           0 :       *in >> r >> im;
     805           0 :       a_i = std::complex<T>(r,im);
     806             :     }
     807           0 :   in->getline(comm, comm_len);
     808           0 : }
     809             : 
     810             : template <typename T>
     811       77258 : void Xdr::do_write(T & a) { *out << a; }
     812             : 
     813             : template <typename T>
     814           0 : void Xdr::do_write(std::complex<T> & a)
     815             : {
     816           0 :   *out << a.real() << "\t " << a.imag();
     817           0 : }
     818             : 
     819             : template <typename T>
     820        8961 : void Xdr::do_write(std::vector<T> & a)
     821             : {
     822        9677 :   std::size_t length = a.size();
     823        8961 :   data(length, "# vector length");
     824             : 
     825             :   // Use scientific precision with lots of digits for the original type T.
     826         716 :   *out << std::scientific
     827         716 :        << std::setprecision(std::numeric_limits<T>::max_digits10);
     828             : 
     829       37982 :   for (T & a_i : a)
     830             :     {
     831        2417 :       libmesh_assert(out.get());
     832        2417 :       libmesh_assert (out->good());
     833        3885 :       this->do_write(a_i);
     834       29021 :       *out << "\t ";
     835             :     }
     836        8961 : }
     837             : 
     838             : template <typename T>
     839           0 : void Xdr::do_write(std::vector<std::complex<T>> & a)
     840             : {
     841           0 :   std::size_t length=a.size();
     842           0 :   data(length, "# vector length x 2 (complex)");
     843             : 
     844             :   // Use scientific precision with lots of digits for the original type T.
     845           0 :   *out << std::scientific
     846           0 :        << std::setprecision(std::numeric_limits<T>::max_digits10);
     847             : 
     848           0 :   for (std::complex<T> & a_i : a)
     849             :     {
     850           0 :       libmesh_assert(out.get());
     851           0 :       libmesh_assert (out->good());
     852           0 :       this->do_write(a_i);
     853           0 :       *out << "\t ";
     854             :     }
     855           0 : }
     856             : 
     857             : 
     858             : 
     859             : template <typename T>
     860     1564358 : void Xdr::data (T & a, std::string_view comment_in)
     861             : {
     862     1564358 :   switch (mode)
     863             :     {
     864     1348293 :     case ENCODE:
     865             :     case DECODE:
     866             :       {
     867             : #ifdef LIBMESH_HAVE_XDR
     868             : 
     869       52470 :         libmesh_assert (is_open());
     870             : 
     871       95351 :         xdr_translate(xdrs.get(), a);
     872             : 
     873             : #else
     874             : 
     875             :         libmesh_error_msg("ERROR: Functionality is not available.\n"    \
     876             :                           << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
     877             :                           << "The XDR interface is not available in this installation");
     878             : 
     879             : #endif
     880       95351 :         return;
     881             :       }
     882             : 
     883      128575 :     case READ:
     884             :       {
     885       11592 :         libmesh_assert(in.get());
     886       11592 :         libmesh_assert (in->good());
     887             : 
     888      128575 :         this->do_read(a);
     889             : 
     890      128575 :         return;
     891             :       }
     892             : 
     893       87490 :     case WRITE:
     894             :       {
     895        7886 :         libmesh_assert(out.get());
     896        7886 :         libmesh_assert (out->good());
     897             : 
     898             :         // We will use scientific notation sufficient to exactly
     899             :         // represent our floating point precision in the following
     900             :         // output.  The desired precision and format will
     901             :         // automatically determine the width.
     902        7886 :         *out << std::scientific
     903        7886 :              << std::setprecision(std::numeric_limits<T>::max_digits10);
     904             : 
     905       21830 :         this->do_write(a);
     906             : 
     907             :         // If there's a comment provided, write a tab character and
     908             :         // then the comment.
     909       87490 :         if (comment_in != "")
     910       74952 :           *out << "\t " << comment_in;
     911             : 
     912             :         // Go to the next line.
     913       87490 :         *out << '\n';
     914             : 
     915       87490 :         return;
     916             :       }
     917             : 
     918           0 :     default:
     919           0 :       libmesh_error_msg("Invalid mode = " << mode);
     920             :     }
     921             : }
     922             : 
     923             : 
     924             : template <typename T>
     925      646888 : void Xdr::data_stream (T * val, const unsigned int len, const unsigned int line_break)
     926             : {
     927      646888 :   switch (mode)
     928             :     {
     929        4255 :     case ENCODE:
     930             :       {
     931             : #ifdef LIBMESH_HAVE_XDR
     932             : 
     933        4255 :         libmesh_assert (this->is_open());
     934             : 
     935        4255 :         unsigned int size_of_type = cast_int<unsigned int>(sizeof(T));
     936             : 
     937       52385 :         xdr_vector(xdrs.get(),
     938             :                    (char *) val,
     939             :                    len,
     940             :                    size_of_type,
     941             :                    xdr_translator<T>());
     942             : #else
     943             :         libmesh_error_msg("ERROR: Functionality is not available.\n"    \
     944             :                           << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
     945             :                           << "The XDR interface is not available in this installation");
     946             : 
     947             : #endif
     948       48130 :         return;
     949             :       }
     950             : 
     951       24614 :     case DECODE:
     952             :       {
     953             : #ifdef LIBMESH_HAVE_XDR
     954             : 
     955       24614 :         libmesh_assert (this->is_open());
     956             : 
     957       24614 :         unsigned int size_of_type = cast_int<unsigned int>(sizeof(T));
     958             : 
     959      249189 :         if (len > 0)
     960      204141 :           xdr_vector(xdrs.get(),
     961             :                      (char *) val,
     962             :                      len,
     963             :                      size_of_type,
     964             :                      xdr_translator<T>());
     965             : #else
     966             :         libmesh_error_msg("ERROR: Functionality is not available.\n"    \
     967             :                           << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
     968             :                           << "The XDR interface is not available in this installation");
     969             : 
     970             : #endif
     971       24614 :         return;
     972             :       }
     973             : 
     974       25824 :     case READ:
     975             :       {
     976       25824 :         libmesh_assert(in.get());
     977       25824 :         libmesh_assert (in->good());
     978             : 
     979     1233767 :         for (unsigned int i=0; i<len; i++)
     980             :           {
     981       78961 :             libmesh_assert(in.get());
     982       78961 :             libmesh_assert (in->good());
     983      930405 :             *in >> val[i];
     984             :           }
     985             : 
     986       25824 :         return;
     987             :       }
     988             : 
     989       46207 :     case WRITE:
     990             :       {
     991        3595 :         libmesh_assert(out.get());
     992        3595 :         libmesh_assert (out->good());
     993             : 
     994             :         // We will use scientific notation sufficient to exactly
     995             :         // represent our floating point precision in the following
     996             :         // output.  The desired precision and format will
     997             :         // automatically determine the width.
     998        3595 :         *out << std::scientific
     999        3595 :              << std::setprecision(std::numeric_limits<T>::max_digits10);
    1000             : 
    1001       46207 :         if (line_break == libMesh::invalid_uint)
    1002           0 :           for (unsigned int i=0; i<len; i++)
    1003             :             {
    1004           0 :               libmesh_assert(out.get());
    1005           0 :               libmesh_assert (out->good());
    1006           0 :               *out << val[i] << " ";
    1007             :             }
    1008             :         else
    1009             :           {
    1010       46207 :             const unsigned imax = std::min(line_break, len);
    1011        3595 :             unsigned int cnt=0;
    1012      194830 :             while (cnt < len)
    1013             :               {
    1014      703700 :                 for (unsigned int i=0; (i<imax && cnt<len); i++)
    1015             :                   {
    1016       46961 :                     libmesh_assert(out.get());
    1017       46961 :                     libmesh_assert (out->good());
    1018      555077 :                     *out << val[cnt++];
    1019             : 
    1020             :                     // Write a space unless this is the last character on the current line.
    1021      555077 :                     if (i+1 != imax)
    1022      406454 :                       *out << " ";
    1023             :                   }
    1024       12567 :                 libmesh_assert(out.get());
    1025       12567 :                 libmesh_assert (out->good());
    1026      148623 :                 *out << '\n';
    1027             :               }
    1028             :           }
    1029             : 
    1030        3595 :         return;
    1031             :       }
    1032             : 
    1033           0 :     default:
    1034           0 :       libmesh_error_msg("Invalid mode = " << mode);
    1035             :     }
    1036             : }
    1037             : 
    1038             : 
    1039             : 
    1040             : template <>
    1041       36913 : void Xdr::data_stream (double * val, const unsigned int len, const unsigned int line_break)
    1042             : {
    1043             :   this->_xfp_data_stream
    1044       36913 :     (val, len,
    1045             : #ifdef LIBMESH_HAVE_XDR
    1046             :      (xdrproc_t)libmesh_xdr_double,
    1047             : #else
    1048             :      nullptr,
    1049             : #endif
    1050             :      line_break, std::numeric_limits<double>::max_digits10);
    1051       36913 : }
    1052             : 
    1053             : 
    1054             : 
    1055             : template <>
    1056           0 : void Xdr::data_stream (float * val, const unsigned int len, const unsigned int line_break)
    1057             : {
    1058             :   this->_xfp_data_stream
    1059           0 :     (val, len,
    1060             : #ifdef LIBMESH_HAVE_XDR
    1061             :      (xdrproc_t)libmesh_xdr_float,
    1062             : #else
    1063             :      nullptr,
    1064             : #endif
    1065             :      line_break, std::numeric_limits<float>::max_digits10);
    1066           0 : }
    1067             : 
    1068             : 
    1069             : 
    1070             : template <>
    1071           0 : void Xdr::data_stream (long double * val, const unsigned int len, const unsigned int line_break)
    1072             : {
    1073             :   this->_xfp_data_stream
    1074           0 :     (val, len, nullptr, line_break,
    1075             :      std::numeric_limits<long double>::max_digits10);
    1076           0 : }
    1077             : 
    1078             : 
    1079             : #ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
    1080             : template <>
    1081             : void Xdr::data_stream (Real * val, const unsigned int len, const unsigned int line_break)
    1082             : {
    1083             :   this->_xfp_data_stream(val, len, nullptr, line_break, 36);
    1084             : }
    1085             : #endif // LIBMESH_DEFAULT_QUADRUPLE_PRECISION
    1086             : 
    1087             : 
    1088             : 
    1089             : template <typename XFP>
    1090       36913 : void Xdr::_xfp_data_stream (XFP * val, const unsigned int len,
    1091             : #ifdef LIBMESH_HAVE_XDR
    1092             :                             xdrproc_t xdr_proc,
    1093             : #else
    1094             :                             void *,
    1095             : #endif
    1096             :                             const unsigned int line_break,
    1097             :                             const int n_digits)
    1098             : {
    1099       36913 :   switch (mode)
    1100             :     {
    1101        7780 :     case ENCODE:
    1102             :     case DECODE:
    1103             :       {
    1104             : #ifdef LIBMESH_HAVE_XDR
    1105         486 :         libmesh_assert (this->is_open());
    1106             : 
    1107        7780 :         if (len > 0)
    1108             :           {
    1109        7780 :             if (xdr_proc)
    1110             :               {
    1111        7780 :                 xdr_vector(xdrs.get(),
    1112             :                            (char *) val,
    1113             :                            len,
    1114             :                            sizeof(XFP),
    1115             :                            xdr_proc);
    1116        7780 :                 return;
    1117             :               }
    1118             : 
    1119             :             // FIXME[JWP]: How to implement this for long double?  Mac
    1120             :             // OS X defines 'xdr_quadruple' but AFAICT, it does not
    1121             :             // exist for Linux... for now, reading/writing XDR files
    1122             :             // with long doubles drops back to double precision, but
    1123             :             // you can still write long double ASCII files of course.
    1124             : 
    1125             :             // FIXME[RHS]: 128 bit FP has the same problem as long
    1126             :             // double, only much worse since even _Quad/__float128
    1127             :             // aren't standard either.
    1128             : 
    1129           0 :             std::vector<double> io_buffer (len);
    1130             : 
    1131             :             // Fill io_buffer if we are writing.
    1132           0 :             if (mode == ENCODE)
    1133           0 :               for (unsigned int i=0, cnt=0; i<len; i++)
    1134           0 :                 io_buffer[cnt++] = double(val[i]);
    1135             : 
    1136           0 :             xdr_vector(xdrs.get(),
    1137           0 :                        reinterpret_cast<char *>(io_buffer.data()),
    1138             :                        len,
    1139             :                        sizeof(double),
    1140             :                        (xdrproc_t) libmesh_xdr_double);
    1141             : 
    1142             :             // Fill val array if we are reading.
    1143           0 :             if (mode == DECODE)
    1144           0 :               for (unsigned int i=0, cnt=0; i<len; i++)
    1145             :                 {
    1146           0 :                   val[i] = io_buffer[cnt++];
    1147             :                 }
    1148             :           }
    1149             : 
    1150             : #else
    1151             : 
    1152             :         libmesh_error_msg("ERROR: Functionality is not available.\n"    \
    1153             :                           << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
    1154             :                           << "The XDR interface is not available in this installation");
    1155             : 
    1156             : #endif
    1157           0 :         return;
    1158             :       }
    1159             : 
    1160        1483 :     case READ:
    1161             :       {
    1162        1483 :         libmesh_assert(in.get());
    1163        1483 :         libmesh_assert (in->good());
    1164             : 
    1165    14581457 :         for (unsigned int i=0; i<len; i++)
    1166             :           {
    1167     1321500 :             libmesh_assert(in.get());
    1168     1321500 :             libmesh_assert (in->good());
    1169    14564843 :             *in >> val[i];
    1170             :           }
    1171             : 
    1172        1483 :         return;
    1173             :       }
    1174             : 
    1175       12519 :     case WRITE:
    1176             :       {
    1177        1111 :         libmesh_assert(out.get());
    1178        1111 :         libmesh_assert (out->good());
    1179             : 
    1180             :         // Save stream flags
    1181       12519 :         std::ios_base::fmtflags out_flags = out->flags();
    1182             : 
    1183             :         // We will use scientific notation with specified digit
    1184             :         // count in the following output.  The desired precision and
    1185             :         // format will automatically determine the width.
    1186        1111 :         *out << std::scientific
    1187        1111 :              << std::setprecision(n_digits);
    1188             : 
    1189       12519 :         if (line_break == libMesh::invalid_uint)
    1190    14625538 :           for (unsigned int i=0; i<len; i++)
    1191             :             {
    1192     1330248 :               libmesh_assert(out.get());
    1193     1330248 :               libmesh_assert (out->good());
    1194    15945939 :               *out << val[i] << ' ';
    1195             :             }
    1196             :         else
    1197             :           {
    1198        2672 :             const unsigned imax = std::min(line_break, len);
    1199         215 :             unsigned int cnt=0;
    1200       79010 :             while (cnt < len)
    1201             :               {
    1202      311909 :                 for (unsigned int i=0; (i<imax && cnt<len); i++)
    1203             :                   {
    1204       19647 :                     libmesh_assert(out.get());
    1205       19647 :                     libmesh_assert (out->good());
    1206      235571 :                     *out << val[cnt++];
    1207             : 
    1208             :                     // Write a space unless this is the last character on the current line.
    1209      235571 :                     if (i+1 != imax)
    1210      159316 :                       *out << " ";
    1211             :                   }
    1212        6470 :                 libmesh_assert(out.get());
    1213        6470 :                 libmesh_assert (out->good());
    1214       76338 :                 *out << '\n';
    1215             :               }
    1216             :           }
    1217             : 
    1218             :         // Restore stream flags
    1219       12519 :         out->flags(out_flags);
    1220             : 
    1221        1111 :         return;
    1222             :       }
    1223             : 
    1224           0 :     default:
    1225           0 :       libmesh_error_msg("Invalid mode = " << mode);
    1226             :     }
    1227             : }
    1228             : 
    1229             : 
    1230             : 
    1231             : template <>
    1232          20 : void Xdr::data_stream (std::complex<double> * val, const unsigned int len, const unsigned int line_break)
    1233             : {
    1234          20 :   this->_complex_data_stream(val, len, line_break);
    1235          20 : }
    1236             : 
    1237             : 
    1238             : 
    1239             : template <>
    1240           0 : void Xdr::data_stream (std::complex<long double> * val, const unsigned int len, const unsigned int line_break)
    1241             : {
    1242           0 :   this->_complex_data_stream(val, len, line_break);
    1243           0 : }
    1244             : 
    1245             : 
    1246             : 
    1247             : template <typename T>
    1248          20 : void Xdr::_complex_data_stream (std::complex<T> * val, const unsigned int len, const unsigned int line_break)
    1249             : {
    1250          20 :   switch (mode)
    1251             :     {
    1252           8 :     case ENCODE:
    1253             :     case DECODE:
    1254             :       {
    1255             : #ifdef LIBMESH_HAVE_XDR
    1256             : 
    1257           0 :         libmesh_assert (this->is_open());
    1258             : 
    1259             :         // FIXME[JWP]: How to implement this for long double?  Mac OS
    1260             :         // X defines 'xdr_quadruple' but AFAICT, it does not exist for
    1261             :         // Linux... for now, reading/writing XDR files with long
    1262             :         // doubles drops back to double precision, but you can still
    1263             :         // write long double ASCII files of course.
    1264             : 
    1265           8 :         if (len > 0)
    1266             :           {
    1267           8 :             std::vector<double> io_buffer (2*len);
    1268             : 
    1269             :             // Fill io_buffer if we are writing.
    1270           8 :             if (mode == ENCODE)
    1271      111216 :               for (unsigned int i=0, cnt=0; i<len; i++)
    1272             :                 {
    1273      111212 :                   io_buffer[cnt++] = val[i].real();
    1274      111212 :                   io_buffer[cnt++] = val[i].imag();
    1275             :                 }
    1276             : 
    1277           8 :             xdr_vector(xdrs.get(),
    1278           0 :                        reinterpret_cast<char *>(io_buffer.data()),
    1279             :                        2*len,
    1280             :                        sizeof(double),
    1281             :                        (xdrproc_t) libmesh_xdr_double);
    1282             : 
    1283             :             // Fill val array if we are reading.
    1284           8 :             if (mode == DECODE)
    1285      111216 :               for (unsigned int i=0, cnt=0; i<len; i++)
    1286             :                 {
    1287      111212 :                   double re = io_buffer[cnt++];
    1288      111212 :                   double im = io_buffer[cnt++];
    1289      111212 :                   val[i] = std::complex<T>(re, im);
    1290             :                 }
    1291             :           }
    1292             : #else
    1293             : 
    1294             :         libmesh_error_msg("ERROR: Functionality is not available.\n"    \
    1295             :                           << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
    1296             :                           << "The XDR interface is not available in this installation");
    1297             : 
    1298             : #endif
    1299           0 :         return;
    1300             :       }
    1301             : 
    1302           0 :     case READ:
    1303             :       {
    1304           0 :         libmesh_assert(in.get());
    1305           0 :         libmesh_assert (in->good());
    1306             : 
    1307        1144 :         for (unsigned int i=0; i<len; i++)
    1308             :           {
    1309           0 :             libmesh_assert(in.get());
    1310           0 :             libmesh_assert (in->good());
    1311             :             T re, im;
    1312           0 :             *in >> re >> im;
    1313        1139 :             val[i] = std::complex<T>(re,im);
    1314             :           }
    1315             : 
    1316           0 :         return;
    1317             :       }
    1318             : 
    1319           7 :     case WRITE:
    1320             :       {
    1321           0 :         libmesh_assert(out.get());
    1322           0 :         libmesh_assert (out->good());
    1323             : 
    1324             : 
    1325             :         // Save stream flags
    1326           7 :         std::ios_base::fmtflags out_flags = out->flags();
    1327             : 
    1328             :         // We will use scientific notation with a precision of
    1329             :         // 'max_digits10' digits in the following output.  The desired
    1330             :         // precision and format will automatically determine the
    1331             :         // width.  Note: digit10 is the number of digits (in decimal
    1332             :         // base) that can be represented without change.  Equivalent
    1333             :         // to FLT_DIG, DBL_DIG or LDBL_DIG for floating types.
    1334           0 :         *out << std::scientific
    1335           0 :              << std::setprecision(std::numeric_limits<T>::max_digits10);
    1336             : 
    1337           7 :         if (line_break == libMesh::invalid_uint)
    1338        4314 :           for (unsigned int i=0; i<len; i++)
    1339             :             {
    1340           0 :               libmesh_assert(out.get());
    1341           0 :               libmesh_assert (out->good());
    1342        8614 :               *out << val[i].real() << ' ' << val[i].imag() << ' ';
    1343             :             }
    1344             :         else
    1345             :           {
    1346           0 :             const unsigned imax = std::min(line_break, len);
    1347           0 :             unsigned int cnt=0;
    1348           0 :             while (cnt < len)
    1349             :               {
    1350           0 :                 for (unsigned int i=0; (i<imax && cnt<len); i++)
    1351             :                   {
    1352           0 :                     libmesh_assert(out.get());
    1353           0 :                     libmesh_assert (out->good());
    1354           0 :                     *out << val[cnt].real() << ' ' << val[cnt].imag();
    1355           0 :                     cnt++;
    1356             : 
    1357             :                     // Write a space unless this is the last character on the current line.
    1358           0 :                     if (i+1 != imax)
    1359           0 :                       *out << " ";
    1360             :                   }
    1361           0 :                 libmesh_assert(out.get());
    1362           0 :                 libmesh_assert (out->good());
    1363           0 :                 *out << '\n';
    1364             :               }
    1365             :           }
    1366             : 
    1367             :         // Restore stream flags
    1368           7 :         out->flags(out_flags);
    1369             : 
    1370           0 :         return;
    1371             :       }
    1372             : 
    1373           0 :     default:
    1374           0 :       libmesh_error_msg("Invalid mode = " << mode);
    1375             :     }
    1376             : }
    1377             : 
    1378             : 
    1379             : 
    1380       22898 : void Xdr::comment (std::string & comment_in)
    1381             : {
    1382       22898 :   switch (mode)
    1383             :     {
    1384           2 :     case ENCODE:
    1385             :     case DECODE:
    1386             :       {
    1387           2 :         return;
    1388             :       }
    1389             : 
    1390       13061 :     case READ:
    1391             :       {
    1392        1187 :         libmesh_assert(in.get());
    1393        1187 :         libmesh_assert (in->good());
    1394       13061 :         in->getline(comm, comm_len);
    1395       13061 :         return;
    1396             :       }
    1397             : 
    1398        9831 :     case WRITE:
    1399             :       {
    1400         894 :         libmesh_assert(out.get());
    1401         894 :         libmesh_assert (out->good());
    1402       17874 :         *out << "\t " << comment_in << '\n';
    1403        9831 :         return;
    1404             :       }
    1405             : 
    1406           0 :     default:
    1407           0 :       libmesh_error_msg("Invalid mode = " << mode);
    1408             :     }
    1409             : }
    1410             : 
    1411             : 
    1412             : #undef xdr_REAL
    1413             : 
    1414             : 
    1415             : //
    1416             : template LIBMESH_EXPORT void Xdr::data<int>                              (int &,                             std::string_view);
    1417             : template LIBMESH_EXPORT void Xdr::data<unsigned int>                     (unsigned int &,                    std::string_view);
    1418             : template LIBMESH_EXPORT void Xdr::data<unsigned short int>               (unsigned short int &,              std::string_view);
    1419             : template LIBMESH_EXPORT void Xdr::data<short int>                        (short int &,                       std::string_view);
    1420             : template LIBMESH_EXPORT void Xdr::data<unsigned long int>                (unsigned long int &,               std::string_view);
    1421             : template LIBMESH_EXPORT void Xdr::data<unsigned long long>               (unsigned long long &,              std::string_view);
    1422             : template LIBMESH_EXPORT void Xdr::data<long int>                         (long int &,                        std::string_view);
    1423             : template LIBMESH_EXPORT void Xdr::data<long long>                        (long long &,                       std::string_view);
    1424             : template LIBMESH_EXPORT void Xdr::data<char>                             (char &,                            std::string_view);
    1425             : template LIBMESH_EXPORT void Xdr::data<signed char>                      (signed char &,                     std::string_view);
    1426             : template LIBMESH_EXPORT void Xdr::data<unsigned char>                    (unsigned char &,                   std::string_view);
    1427             : template LIBMESH_EXPORT void Xdr::data<float>                            (float &,                           std::string_view);
    1428             : template LIBMESH_EXPORT void Xdr::data<double>                           (double &,                          std::string_view);
    1429             : template LIBMESH_EXPORT void Xdr::data<long double>                      (long double &,                     std::string_view);
    1430             : template LIBMESH_EXPORT void Xdr::data<std::complex<float>>              (std::complex<float> &,             std::string_view);
    1431             : template LIBMESH_EXPORT void Xdr::data<std::complex<double>>             (std::complex<double> &,            std::string_view);
    1432             : template LIBMESH_EXPORT void Xdr::data<std::complex<long double>>        (std::complex<long double> &,       std::string_view);
    1433             : template LIBMESH_EXPORT void Xdr::data<std::string>                      (std::string &,                     std::string_view);
    1434             : template LIBMESH_EXPORT void Xdr::data<std::vector<int>>                 (std::vector<int> &,                std::string_view);
    1435             : template LIBMESH_EXPORT void Xdr::data<std::vector<unsigned int>>        (std::vector<unsigned int> &,       std::string_view);
    1436             : template LIBMESH_EXPORT void Xdr::data<std::vector<short int>>           (std::vector<short int> &,          std::string_view);
    1437             : template LIBMESH_EXPORT void Xdr::data<std::vector<unsigned short int>>  (std::vector<unsigned short int> &, std::string_view);
    1438             : template LIBMESH_EXPORT void Xdr::data<std::vector<long int>>            (std::vector<long int> &,           std::string_view);
    1439             : template LIBMESH_EXPORT void Xdr::data<std::vector<long long>>           (std::vector<long long> &,          std::string_view);
    1440             : template LIBMESH_EXPORT void Xdr::data<std::vector<unsigned long int>>   (std::vector<unsigned long int> &,  std::string_view);
    1441             : template LIBMESH_EXPORT void Xdr::data<std::vector<unsigned long long>>  (std::vector<unsigned long long> &, std::string_view);
    1442             : template LIBMESH_EXPORT void Xdr::data<std::vector<char>>                (std::vector<char> &,               std::string_view);
    1443             : template LIBMESH_EXPORT void Xdr::data<std::vector<signed char>>         (std::vector<signed char> &,        std::string_view);
    1444             : template LIBMESH_EXPORT void Xdr::data<std::vector<unsigned char>>       (std::vector<unsigned char> &,      std::string_view);
    1445             : template LIBMESH_EXPORT void Xdr::data<std::vector<float>>               (std::vector<float> &,              std::string_view);
    1446             : template LIBMESH_EXPORT void Xdr::data<std::vector<double>>              (std::vector<double> &,             std::string_view);
    1447             : template LIBMESH_EXPORT void Xdr::data<std::vector<long double>>         (std::vector<long double> &,        std::string_view);
    1448             : template LIBMESH_EXPORT void Xdr::data<std::vector<std::complex<float>>>  (std::vector<std::complex<float>> &,  std::string_view);
    1449             : template LIBMESH_EXPORT void Xdr::data<std::vector<std::complex<double>>> (std::vector<std::complex<double>> &, std::string_view);
    1450             : template LIBMESH_EXPORT void Xdr::data<std::vector<std::complex<long double>>> (std::vector<std::complex<long double>> &, std::string_view);
    1451             : template LIBMESH_EXPORT void Xdr::data<std::vector<std::string>>        (std::vector<std::string> &,        std::string_view);
    1452             : template LIBMESH_EXPORT void Xdr::data_stream<unsigned char>      (unsigned char * val,      const unsigned int len, const unsigned int line_break);
    1453             : template LIBMESH_EXPORT void Xdr::data_stream<short int>          (short int * val,          const unsigned int len, const unsigned int line_break);
    1454             : template LIBMESH_EXPORT void Xdr::data_stream<int>                (int * val,                const unsigned int len, const unsigned int line_break);
    1455             : template LIBMESH_EXPORT void Xdr::data_stream<long long>          (long long * val,          const unsigned int len, const unsigned int line_break);
    1456             : template LIBMESH_EXPORT void Xdr::data_stream<unsigned short int> (unsigned short int * val, const unsigned int len, const unsigned int line_break);
    1457             : template LIBMESH_EXPORT void Xdr::data_stream<unsigned int>       (unsigned int * val,       const unsigned int len, const unsigned int line_break);
    1458             : template LIBMESH_EXPORT void Xdr::data_stream<unsigned long int>  (unsigned long int * val,  const unsigned int len, const unsigned int line_break);
    1459             : template LIBMESH_EXPORT void Xdr::data_stream<unsigned long long> (unsigned long long * val, const unsigned int len, const unsigned int line_break);
    1460             : 
    1461             : #ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
    1462             : template LIBMESH_EXPORT void Xdr::data<Real>                             (Real &,                            std::string_view);
    1463             : template LIBMESH_EXPORT void Xdr::data<std::complex<Real>>               (std::complex<Real> &,              std::string_view);
    1464             : template LIBMESH_EXPORT void Xdr::data<std::vector<Real>>                (std::vector<Real> &,               std::string_view);
    1465             : template LIBMESH_EXPORT void Xdr::data<std::vector<std::complex<Real>>>  (std::vector<std::complex<Real>> &, std::string_view);
    1466             : #endif
    1467             : 
    1468             : } // namespace libMesh

Generated by: LCOV version 1.14