$extrastylesheet
xdr_cxx.C
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 
00019 // C/C++ includes
00020 #include <cstring>
00021 #include <limits>
00022 #include <iomanip>
00023 #include <sstream>
00024 #include <fstream>
00025 
00026 #include <unistd.h> // for getpid()
00027 
00028 // Local includes
00029 #include "libmesh/xdr_cxx.h"
00030 #include "libmesh/libmesh_logging.h"
00031 #ifdef LIBMESH_HAVE_GZSTREAM
00032 # include "gzstream.h"
00033 #endif
00034 
00035 
00036 // Anonymous namespace for implementation details.
00037 namespace {
00038 
00039 // Nasty hacks for reading/writing zipped files
00040 void bzip_file (const std::string &unzipped_name)
00041 {
00042 #ifdef LIBMESH_HAVE_BZIP
00043   START_LOG("system(bzip2)", "XdrIO");
00044 
00045   std::string system_string = "bzip2 -f ";
00046   system_string += unzipped_name;
00047   if (std::system(system_string.c_str()))
00048     libmesh_file_error(system_string);
00049 
00050   STOP_LOG("system(bzip2)", "XdrIO");
00051 #else
00052   libmesh_error_msg("ERROR: need bzip2/bunzip2 to create " << unzipped_name << ".bz2");
00053 #endif
00054 }
00055 
00056 std::string unzip_file (const std::string &name)
00057 {
00058   std::ostringstream pid_suffix;
00059   pid_suffix << '_' << getpid();
00060 
00061   std::string new_name = name;
00062   if (name.size() - name.rfind(".bz2") == 4)
00063     {
00064 #ifdef LIBMESH_HAVE_BZIP
00065       new_name.erase(new_name.end() - 4, new_name.end());
00066       new_name += pid_suffix.str();
00067       START_LOG("system(bunzip2)", "XdrIO");
00068       std::string system_string = "bunzip2 -f -k -c ";
00069       system_string += name + " > " + new_name;
00070       if (std::system(system_string.c_str()))
00071         libmesh_file_error(system_string);
00072       STOP_LOG("system(bunzip2)", "XdrIO");
00073 #else
00074       libmesh_error_msg("ERROR: need bzip2/bunzip2 to open .bz2 file " << name);
00075 #endif
00076     }
00077   else if (name.size() - name.rfind(".xz") == 3)
00078     {
00079 #ifdef LIBMESH_HAVE_XZ
00080       new_name.erase(new_name.end() - 3, new_name.end());
00081       new_name += pid_suffix.str();
00082       START_LOG("system(xz -d)", "XdrIO");
00083       std::string system_string = "xz -f -d -k -c ";
00084       system_string += name + " > " + new_name;
00085       if (std::system(system_string.c_str()))
00086         libmesh_file_error(system_string);
00087       STOP_LOG("system(xz -d)", "XdrIO");
00088 #else
00089       libmesh_error_msg("ERROR: need xz to open .xz file " << name);
00090 #endif
00091     }
00092   return new_name;
00093 }
00094 
00095 void xzip_file (const std::string &unzipped_name)
00096 {
00097 #ifdef LIBMESH_HAVE_XZ
00098   START_LOG("system(xz)", "XdrIO");
00099 
00100   std::string system_string = "xz -f ";
00101   system_string += unzipped_name;
00102   if (std::system(system_string.c_str()))
00103     libmesh_file_error(system_string);
00104 
00105   STOP_LOG("system(xz)", "XdrIO");
00106 #else
00107   libmesh_error_msg("ERROR: need xz to create " << unzipped_name << ".xz");
00108 #endif
00109 }
00110 
00111 
00112 // remove an unzipped file
00113 void remove_unzipped_file (const std::string &name)
00114 {
00115   std::ostringstream pid_suffix;
00116   pid_suffix << '_' << getpid();
00117 
00118   // If we temporarily decompressed a file, remove the
00119   // uncompressed version
00120   if (name.size() - name.rfind(".bz2") == 4)
00121     {
00122       std::string new_name(name.begin(), name.end()-4);
00123       new_name += pid_suffix.str();
00124       std::remove(new_name.c_str());
00125     }
00126   if (name.size() - name.rfind(".xz") == 3)
00127     {
00128       std::string new_name(name.begin(), name.end()-3);
00129       new_name += pid_suffix.str();
00130       std::remove(new_name.c_str());
00131     }
00132 }
00133 }
00134 
00135 namespace libMesh
00136 {
00137 
00138 //-------------------------------------------------------------
00139 // Xdr class implementation
00140 Xdr::Xdr (const std::string& name, const XdrMODE m) :
00141   mode(m),
00142   file_name(name),
00143 #ifdef LIBMESH_HAVE_XDR
00144   xdrs(NULL),
00145   fp(NULL),
00146 #endif
00147   in(),
00148   out(),
00149   comm_len(xdr_MAX_STRING_LENGTH),
00150   gzipped_file(false),
00151   bzipped_file(false),
00152   xzipped_file(false)
00153 {
00154   this->open(name);
00155 }
00156 
00157 
00158 
00159 Xdr::~Xdr()
00160 {
00161   this->close();
00162 }
00163 
00164 
00165 
00166 void Xdr::open (const std::string& name)
00167 {
00168   file_name = name;
00169 
00170   if (name == "")
00171     return;
00172 
00173   switch (mode)
00174     {
00175     case ENCODE:
00176     case DECODE:
00177       {
00178 #ifdef LIBMESH_HAVE_XDR
00179 
00180         fp = fopen(name.c_str(), (mode == ENCODE) ? "w" : "r");
00181         if (!fp)
00182           libmesh_file_error(name.c_str());
00183         xdrs = new XDR;
00184         xdrstdio_create (xdrs, fp, (mode == ENCODE) ? XDR_ENCODE : XDR_DECODE);
00185 #else
00186 
00187         libmesh_error_msg("ERROR: Functionality is not available.\n" \
00188                           << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
00189                           << "The XDR interface is not available in this installation");
00190 
00191 #endif
00192         return;
00193 
00194       }
00195 
00196     case READ:
00197       {
00198         gzipped_file = (name.size() - name.rfind(".gz")  == 3);
00199         bzipped_file = (name.size() - name.rfind(".bz2") == 4);
00200         xzipped_file = (name.size() - name.rfind(".xz") == 3);
00201 
00202         if (gzipped_file)
00203           {
00204 #ifdef LIBMESH_HAVE_GZSTREAM
00205             igzstream *inf = new igzstream;
00206             libmesh_assert(inf);
00207             in.reset(inf);
00208             inf->open(name.c_str(), std::ios::in);
00209 #else
00210             libmesh_error_msg("ERROR: need gzstream to handle .gz files!!!");
00211 #endif
00212           }
00213         else
00214           {
00215             std::ifstream *inf = new std::ifstream;
00216             libmesh_assert(inf);
00217             in.reset(inf);
00218 
00219             std::string new_name = unzip_file(name);
00220 
00221             inf->open(new_name.c_str(), std::ios::in);
00222           }
00223 
00224         libmesh_assert(in.get());
00225 
00226         if (!in->good())
00227           libmesh_file_error(name);
00228         return;
00229       }
00230 
00231     case WRITE:
00232       {
00233         gzipped_file = (name.size() - name.rfind(".gz")  == 3);
00234         bzipped_file = (name.size() - name.rfind(".bz2") == 4);
00235         xzipped_file = (name.size() - name.rfind(".xz")  == 3);
00236 
00237         if (gzipped_file)
00238           {
00239 #ifdef LIBMESH_HAVE_GZSTREAM
00240             ogzstream *outf = new ogzstream;
00241             libmesh_assert(outf);
00242             out.reset(outf);
00243             outf->open(name.c_str(), std::ios::out);
00244 #else
00245             libmesh_error_msg("ERROR: need gzstream to handle .gz files!!!");
00246 #endif
00247           }
00248         else
00249           {
00250             std::ofstream *outf = new std::ofstream;
00251             libmesh_assert(outf);
00252             out.reset(outf);
00253 
00254             std::string new_name = name;
00255 
00256             if (bzipped_file)
00257               new_name.erase(new_name.end() - 4, new_name.end());
00258 
00259             if (xzipped_file)
00260               new_name.erase(new_name.end() - 3, new_name.end());
00261 
00262             outf->open(new_name.c_str(), std::ios::out);
00263           }
00264 
00265         libmesh_assert(out.get());
00266         libmesh_assert (out->good());
00267         return;
00268       }
00269 
00270     default:
00271       libmesh_error_msg("Invalid mode = " << mode);
00272     }
00273 }
00274 
00275 
00276 
00277 void Xdr::close ()
00278 {
00279   switch (mode)
00280     {
00281     case ENCODE:
00282     case DECODE:
00283       {
00284 #ifdef LIBMESH_HAVE_XDR
00285 
00286         if (xdrs)
00287           {
00288             xdr_destroy (xdrs);
00289             delete xdrs;
00290             xdrs = NULL;
00291           }
00292 
00293         if (fp)
00294           {
00295             fflush(fp);
00296             fclose(fp);
00297             fp = NULL;
00298           }
00299 #else
00300 
00301         libmesh_error_msg("ERROR: Functionality is not available.\n" \
00302                           << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
00303                           << "The XDR interface is not available in this installation");
00304 
00305 #endif
00306         file_name = "";
00307         return;
00308       }
00309 
00310     case READ:
00311       {
00312         if (in.get() != NULL)
00313           {
00314             in.reset();
00315 
00316             if (bzipped_file || xzipped_file)
00317               remove_unzipped_file(file_name);
00318           }
00319         file_name = "";
00320         return;
00321       }
00322 
00323     case WRITE:
00324       {
00325         if (out.get() != NULL)
00326           {
00327             out.reset();
00328 
00329             if (bzipped_file)
00330               bzip_file(std::string(file_name.begin(), file_name.end()-4));
00331 
00332             else if (xzipped_file)
00333               xzip_file(std::string(file_name.begin(), file_name.end()-3));
00334           }
00335         file_name = "";
00336         return;
00337       }
00338 
00339     default:
00340       libmesh_error_msg("Invalid mode = " << mode);
00341     }
00342 }
00343 
00344 
00345 
00346 bool Xdr::is_open() const
00347 {
00348   switch (mode)
00349     {
00350     case ENCODE:
00351     case DECODE:
00352       {
00353 #ifdef LIBMESH_HAVE_XDR
00354 
00355         if (fp)
00356           if (xdrs)
00357             return true;
00358 
00359         return false;
00360 
00361 #else
00362 
00363         libmesh_error_msg("ERROR: Functionality is not available.\n"    \
00364                           << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
00365                           << "The XDR interface is not available in this installation");
00366 
00367         return false;
00368 
00369 #endif
00370 
00371       }
00372 
00373     case READ:
00374       {
00375         if (in.get() != NULL)
00376           return in->good();
00377         return false;
00378       }
00379 
00380     case WRITE:
00381       {
00382         if (out.get() != NULL)
00383           return out->good();
00384         return false;
00385       }
00386 
00387     default:
00388       libmesh_error_msg("Invalid mode = " << mode);
00389     }
00390 
00391   return false;
00392 }
00393 
00394 
00395 #ifdef LIBMESH_HAVE_XDR
00396 
00397 // Anonymous namespace for Xdr::data helper functions
00398 namespace
00399 {
00400 
00401 template <typename T>
00402 xdrproc_t xdr_translator();
00403 
00404 template <typename T>
00405 bool xdr_translate(XDR* x, T& a) {return (xdr_translator<T>())(x, &a, 0); }
00406 
00407 template <>
00408 bool xdr_translate(XDR* x, std::string& s) {
00409   char* sptr = new char[xdr_MAX_STRING_LENGTH+1];
00410   std::copy(s.begin(), s.end(), sptr);
00411   sptr[s.size()] = 0;
00412   unsigned int length = xdr_MAX_STRING_LENGTH;
00413   bool b = xdr_string(x, &sptr, length);
00414 
00415   // This is necessary when reading, but inefficient when writing...
00416   length = cast_int<unsigned int>(std::strlen(sptr));
00417   s.resize(length);
00418   std::copy(sptr, sptr+length, s.begin());
00419 
00420   delete [] sptr;
00421   return b;
00422 }
00423 
00424 template <typename T>
00425 bool xdr_translate(XDR* x, std::complex<T>& a) {
00426   T r = a.real(), i = a.imag();
00427   bool b1 = xdr_translate(x, r);
00428   bool b2 = xdr_translate(x, i);
00429   a = std::complex<T>(r,i);
00430   return (b1 && b2);
00431 }
00432 
00433 template <typename T>
00434 bool xdr_translate(XDR* x, std::vector<T>& a) {
00435   unsigned int length = cast_int<unsigned int>(a.size());
00436   xdr_u_int(x, &length);
00437   if (length > 0)
00438     {
00439       a.resize(length);
00440       return xdr_vector(x, (char*) &a[0], length, sizeof(T),
00441                         xdr_translator<T>());
00442     }
00443   else
00444     return true;
00445 }
00446 
00447 template <typename T>
00448 bool xdr_translate(XDR* x, std::vector<std::complex<T> >& a) {
00449   unsigned int length = cast_int<unsigned int>(a.size());
00450   bool b = xdr_u_int(x, &length);
00451   a.resize(length);
00452   typename std::vector<std::complex<T> >::iterator iter = a.begin();
00453   for (; iter != a.end(); ++iter)
00454     if (!xdr_translate(x, *iter))
00455       b = false;
00456   return b;
00457 }
00458 
00459 template <>
00460 bool xdr_translate(XDR* x, std::vector<std::string>& s) {
00461   unsigned int length = cast_int<unsigned int>(s.size());
00462   bool b = xdr_u_int(x, &length);
00463   s.resize(length);
00464   std::vector<std::string>::iterator iter = s.begin();
00465   for (; iter != s.end(); ++iter)
00466     if (!xdr_translate(x, *iter))
00467       b = false;
00468   return b;
00469 }
00470 
00471 template <>
00472 xdrproc_t xdr_translator<int>() { return (xdrproc_t)(xdr_int); }
00473 
00474 template <>
00475 xdrproc_t xdr_translator<unsigned int>() { return (xdrproc_t)(xdr_u_int); }
00476 
00477 template <>
00478 xdrproc_t xdr_translator<long int>() { return (xdrproc_t)(xdr_long); }
00479 
00480 template <>
00481 xdrproc_t xdr_translator<unsigned long int>() { return (xdrproc_t)(xdr_u_long); }
00482 
00483 template <>
00484 xdrproc_t xdr_translator<unsigned long long>() { return (xdrproc_t)(xdr_u_longlong_t); }
00485 
00486 template <>
00487 xdrproc_t xdr_translator<short int>() { return (xdrproc_t)(xdr_short); }
00488 
00489 template <>
00490 xdrproc_t xdr_translator<unsigned short int>() { return (xdrproc_t)(xdr_u_short); }
00491 
00492 template <>
00493 xdrproc_t xdr_translator<char>() { return (xdrproc_t)(xdr_char); }
00494 
00495 template <>
00496 xdrproc_t xdr_translator<signed char>() { return (xdrproc_t)(xdr_char); }
00497 
00498 template <>
00499 xdrproc_t xdr_translator<unsigned char>() { return (xdrproc_t)(xdr_u_char); }
00500 
00501 template <>
00502 xdrproc_t xdr_translator<float>() { return (xdrproc_t)(xdr_float); }
00503 
00504 template <>
00505 xdrproc_t xdr_translator<double>() { return (xdrproc_t)(xdr_double); }
00506 
00507 // FIXME - no XDR love for long doubles?
00508 template <>
00509 xdrproc_t xdr_translator<long double>() { return (xdrproc_t)(xdr_double); }
00510 
00511 } // end anonymous namespace
00512 
00513 #endif
00514 
00515 template <typename T>
00516 void Xdr::do_read(T& a) {
00517   *in >> a;
00518   in->getline(comm, comm_len);
00519 }
00520 
00521 template <typename T>
00522 void Xdr::do_read(std::complex<T>& a) {
00523   T r, i;
00524   *in >> r >> i;
00525   a = std::complex<T>(r,i);
00526   in->getline(comm, comm_len);
00527 }
00528 
00529 template <>
00530 void Xdr::do_read(std::string& a) {
00531   in->getline(comm, comm_len);
00532 
00533   a = "";
00534 
00535   for (unsigned int c=0; c<std::strlen(comm); c++)
00536     {
00537       if (comm[c] == '\t')
00538         break;
00539       a.push_back(comm[c]);
00540     }
00541 }
00542 
00543 template <typename T>
00544 void Xdr::do_read(std::vector<T>& a) {
00545   unsigned int length=0;
00546   data(length, "# vector length");
00547   a.resize(length);
00548 
00549   for (unsigned int i=0; i<a.size(); i++)
00550     {
00551       libmesh_assert(in.get());
00552       libmesh_assert (in->good());
00553       *in >> a[i];
00554     }
00555   in->getline(comm, comm_len);
00556 }
00557 
00558 template <typename T>
00559 void Xdr::do_read(std::vector<std::complex<T> >& a) {
00560   unsigned int length=0;
00561   data(length, "# vector length x 2 (complex)");
00562   a.resize(length);
00563 
00564   for (unsigned int i=0; i<a.size(); i++)
00565     {
00566       T r, im;
00567       libmesh_assert(in.get());
00568       libmesh_assert (in->good());
00569       *in >> r >> im;
00570       a[i] = std::complex<T>(r,im);
00571     }
00572   in->getline(comm, comm_len);
00573 }
00574 
00575 template <typename T>
00576 void Xdr::do_write(T& a) { *out << a; }
00577 
00578 template <typename T>
00579 void Xdr::do_write(std::complex<T>& a) {
00580   *out << a.real() << "\t " << a.imag();
00581 }
00582 
00583 template <typename T>
00584 void Xdr::do_write(std::vector<T>& a) {
00585   std::size_t length = a.size();
00586   data(length, "# vector length");
00587 
00588   for (std::size_t i=0; i<a.size(); i++)
00589     {
00590       libmesh_assert(out.get());
00591       libmesh_assert (out->good());
00592       this->do_write(a[i]);
00593       *out << "\t ";
00594     }
00595 }
00596 
00597 template <typename T>
00598 void Xdr::do_write(std::vector<std::complex<T> >& a) {
00599   std::size_t length=a.size();
00600   data(length, "# vector length x 2 (complex)");
00601 
00602   for (std::size_t i=0; i<a.size(); i++)
00603     {
00604       libmesh_assert(out.get());
00605       libmesh_assert (out->good());
00606       this->do_write(a[i]);
00607       *out << "\t ";
00608     }
00609 }
00610 
00611 
00612 
00613 template <typename T>
00614 void Xdr::data (T& a, const char* comment_in)
00615 {
00616   switch (mode)
00617     {
00618     case ENCODE:
00619     case DECODE:
00620       {
00621 #ifdef LIBMESH_HAVE_XDR
00622 
00623         libmesh_assert (is_open());
00624 
00625         xdr_translate(xdrs, a);
00626 
00627 #else
00628 
00629         libmesh_error_msg("ERROR: Functionality is not available.\n"    \
00630                           << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
00631                           << "The XDR interface is not available in this installation");
00632 
00633 #endif
00634         return;
00635       }
00636 
00637     case READ:
00638       {
00639         libmesh_assert(in.get());
00640         libmesh_assert (in->good());
00641 
00642         this->do_read(a);
00643 
00644         return;
00645       }
00646 
00647     case WRITE:
00648       {
00649         libmesh_assert(out.get());
00650         libmesh_assert (out->good());
00651 
00652         this->do_write(a);
00653         *out << "\t " << comment_in << '\n';
00654 
00655         return;
00656       }
00657 
00658     default:
00659       libmesh_error_msg("Invalid mode = " << mode);
00660     }
00661 }
00662 
00663 
00664 template <typename T>
00665 void Xdr::data_stream (T *val, const unsigned int len, const unsigned int line_break)
00666 {
00667   switch (mode)
00668     {
00669     case ENCODE:
00670       {
00671 #ifdef LIBMESH_HAVE_XDR
00672 
00673         libmesh_assert (this->is_open());
00674 
00675         unsigned int size_of_type = cast_int<unsigned int>(sizeof(T));
00676 
00677         if (size_of_type <= 4) // 32-bit types
00678           {
00679             xdr_vector(xdrs,
00680                        (char*) val,
00681                        len,
00682                        size_of_type,
00683                        (xdrproc_t) xdr_u_int);
00684           }
00685         else // 64-bit types
00686           {
00687             xdr_vector(xdrs,
00688                        (char*) val,
00689                        len,
00690                        size_of_type,
00691                        (xdrproc_t) xdr_u_hyper);
00692           }
00693 
00694 #else
00695 
00696         libmesh_error_msg("ERROR: Functionality is not available.\n"    \
00697                           << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
00698                           << "The XDR interface is not available in this installation");
00699 
00700 #endif
00701         return;
00702       }
00703 
00704     case DECODE:
00705       {
00706 #ifdef LIBMESH_HAVE_XDR
00707 
00708         libmesh_assert (this->is_open());
00709 
00710         unsigned int size_of_type = cast_int<unsigned int>(sizeof(T));
00711 
00712         if (size_of_type <= 4) // 32-bit types
00713           {
00714             if (len > 0)
00715               xdr_vector(xdrs,
00716                          (char*) val,
00717                          len,
00718                          size_of_type,
00719                          (xdrproc_t) xdr_u_int);
00720           }
00721         else // 64-bit types
00722           {
00723             if (len > 0)
00724               xdr_vector(xdrs,
00725                          (char*) val,
00726                          len,
00727                          size_of_type,
00728                          (xdrproc_t) xdr_u_hyper);
00729 
00730           }
00731 
00732 #else
00733 
00734         libmesh_error_msg("ERROR: Functionality is not available.\n"    \
00735                           << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
00736                           << "The XDR interface is not available in this installation");
00737 
00738 #endif
00739         return;
00740       }
00741 
00742     case READ:
00743       {
00744         libmesh_assert(in.get());
00745         libmesh_assert (in->good());
00746 
00747         for (unsigned int i=0; i<len; i++)
00748           {
00749             libmesh_assert(in.get());
00750             libmesh_assert (in->good());
00751             *in >> val[i];
00752           }
00753 
00754         return;
00755       }
00756 
00757     case WRITE:
00758       {
00759         libmesh_assert(out.get());
00760         libmesh_assert (out->good());
00761 
00762         if (line_break == libMesh::invalid_uint)
00763           for (unsigned int i=0; i<len; i++)
00764             {
00765               libmesh_assert(out.get());
00766               libmesh_assert (out->good());
00767               *out << val[i] << " ";
00768             }
00769         else
00770           {
00771             unsigned int cnt=0;
00772             while (cnt < len)
00773               {
00774                 for (unsigned int i=0; i<std::min(line_break,len); i++)
00775                   {
00776                     libmesh_assert(out.get());
00777                     libmesh_assert (out->good());
00778                     *out << val[cnt++] << " ";
00779                   }
00780                 libmesh_assert(out.get());
00781                 libmesh_assert (out->good());
00782                 *out << '\n';
00783               }
00784           }
00785 
00786         return;
00787       }
00788 
00789     default:
00790       libmesh_error_msg("Invalid mode = " << mode);
00791     }
00792 }
00793 
00794 
00795 
00796 template <>
00797 void Xdr::data_stream (double *val, const unsigned int len, const unsigned int line_break)
00798 {
00799   switch (mode)
00800     {
00801     case ENCODE:
00802     case DECODE:
00803       {
00804 #ifdef LIBMESH_HAVE_XDR
00805 
00806         libmesh_assert (this->is_open());
00807 
00808         if (len > 0)
00809           xdr_vector(xdrs,
00810                      (char*) val,
00811                      len,
00812                      sizeof(double),
00813                      (xdrproc_t) xdr_double);
00814 
00815 #else
00816 
00817         libmesh_error_msg("ERROR: Functionality is not available.\n"    \
00818                           << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
00819                           << "The XDR interface is not available in this installation");
00820 
00821 #endif
00822         return;
00823       }
00824 
00825     case READ:
00826       {
00827         libmesh_assert(in.get());
00828         libmesh_assert (in->good());
00829 
00830         for (unsigned int i=0; i<len; i++)
00831           {
00832             libmesh_assert(in.get());
00833             libmesh_assert (in->good());
00834             *in >> val[i];
00835           }
00836 
00837         return;
00838       }
00839 
00840     case WRITE:
00841       {
00842         libmesh_assert(out.get());
00843         libmesh_assert (out->good());
00844 
00845         // Save stream flags
00846         std::ios_base::fmtflags out_flags = out->flags();
00847 
00848         // We will use scientific notation with a precision of 16
00849         // digits in the following output.  The desired precision and
00850         // format will automatically determine the width.
00851         *out << std::scientific
00852              << std::setprecision(16);
00853 
00854         if (line_break == libMesh::invalid_uint)
00855           for (unsigned int i=0; i<len; i++)
00856             {
00857               libmesh_assert(out.get());
00858               libmesh_assert (out->good());
00859               *out << val[i] << ' ';
00860             }
00861         else
00862           {
00863             unsigned int cnt=0;
00864             while (cnt < len)
00865               {
00866                 for (unsigned int i=0; i<std::min(line_break,len); i++)
00867                   {
00868                     libmesh_assert(out.get());
00869                     libmesh_assert (out->good());
00870                     *out << val[cnt++] << ' ';
00871                   }
00872                 libmesh_assert(out.get());
00873                 libmesh_assert (out->good());
00874                 *out << '\n';
00875               }
00876           }
00877 
00878         // Restore stream flags
00879         out->flags(out_flags);
00880 
00881         return;
00882       }
00883 
00884     default:
00885       libmesh_error_msg("Invalid mode = " << mode);
00886     }
00887 }
00888 
00889 
00890 template <>
00891 void Xdr::data_stream (float *val, const unsigned int len, const unsigned int line_break)
00892 {
00893   switch (mode)
00894     {
00895     case ENCODE:
00896     case DECODE:
00897       {
00898 #ifdef LIBMESH_HAVE_XDR
00899 
00900         libmesh_assert (this->is_open());
00901 
00902         if (len > 0)
00903           xdr_vector(xdrs,
00904                      (char*) val,
00905                      len,
00906                      sizeof(float),
00907                      (xdrproc_t) xdr_float);
00908 
00909 #else
00910 
00911         libmesh_error_msg("ERROR: Functionality is not available.\n"    \
00912                           << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
00913                           << "The XDR interface is not available in this installation");
00914 
00915 #endif
00916         return;
00917       }
00918 
00919     case READ:
00920       {
00921         libmesh_assert(in.get());
00922         libmesh_assert (in->good());
00923 
00924         for (unsigned int i=0; i<len; i++)
00925           {
00926             libmesh_assert(in.get());
00927             libmesh_assert (in->good());
00928             *in >> val[i];
00929           }
00930 
00931         return;
00932       }
00933 
00934     case WRITE:
00935       {
00936         libmesh_assert(out.get());
00937         libmesh_assert (out->good());
00938 
00939         // Save stream flags
00940         std::ios_base::fmtflags out_flags = out->flags();
00941 
00942         // We will use scientific notation with a precision of 16
00943         // digits in the following output.  The desired precision and
00944         // format will automatically determine the width.
00945         *out << std::scientific
00946              << std::setprecision(16);
00947 
00948         if (line_break == libMesh::invalid_uint)
00949           for (unsigned int i=0; i<len; i++)
00950             {
00951               libmesh_assert(out.get());
00952               libmesh_assert (out->good());
00953               *out << val[i] << ' ';
00954             }
00955         else
00956           {
00957             unsigned int cnt=0;
00958             while (cnt < len)
00959               {
00960                 for (unsigned int i=0; i<std::min(line_break,len); i++)
00961                   {
00962                     libmesh_assert(out.get());
00963                     libmesh_assert (out->good());
00964                     *out << val[cnt++] << ' ';
00965                   }
00966                 libmesh_assert(out.get());
00967                 libmesh_assert (out->good());
00968                 *out << '\n';
00969               }
00970           }
00971 
00972         // Restore stream flags
00973         out->flags(out_flags);
00974 
00975         return;
00976       }
00977 
00978     default:
00979       libmesh_error_msg("Invalid mode = " << mode);
00980     }
00981 }
00982 template <>
00983 void Xdr::data_stream (long double *val, const unsigned int len, const unsigned int line_break)
00984 {
00985   switch (mode)
00986     {
00987     case ENCODE:
00988     case DECODE:
00989       {
00990 #ifdef LIBMESH_HAVE_XDR
00991 
00992         libmesh_assert (this->is_open());
00993 
00994         // FIXME[JWP]: How to implement this for long double?  Mac OS
00995         // X defines 'xdr_quadruple' but AFAICT, it does not exist for
00996         // Linux... for now, reading/writing XDR files with long
00997         // doubles drops back to double precision, but you can still
00998         // write long double ASCII files of course.
00999         // if (len > 0)
01000         //   xdr_vector(xdrs,
01001         //      (char*) val,
01002         //      len,
01003         //      sizeof(double),
01004         //      (xdrproc_t) xdr_quadruple);
01005 
01006         if (len > 0)
01007           {
01008             std::vector<double> io_buffer (len);
01009 
01010             // Fill io_buffer if we are writing.
01011             if (mode == ENCODE)
01012               for (unsigned int i=0, cnt=0; i<len; i++)
01013                 io_buffer[cnt++] = val[i];
01014 
01015             xdr_vector(xdrs,
01016                        (char*) &io_buffer[0],
01017                        len,
01018                        sizeof(double),
01019                        (xdrproc_t) xdr_double);
01020 
01021             // Fill val array if we are reading.
01022             if (mode == DECODE)
01023               for (unsigned int i=0, cnt=0; i<len; i++)
01024                 {
01025                   val[i] = io_buffer[cnt++];
01026                 }
01027           }
01028 
01029 #else
01030 
01031         libmesh_error_msg("ERROR: Functionality is not available.\n"    \
01032                           << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
01033                           << "The XDR interface is not available in this installation");
01034 
01035 #endif
01036         return;
01037       }
01038 
01039     case READ:
01040       {
01041         libmesh_assert(in.get());
01042         libmesh_assert (in->good());
01043 
01044         for (unsigned int i=0; i<len; i++)
01045           {
01046             libmesh_assert(in.get());
01047             libmesh_assert (in->good());
01048             *in >> val[i];
01049           }
01050 
01051         return;
01052       }
01053 
01054     case WRITE:
01055       {
01056         libmesh_assert(out.get());
01057         libmesh_assert (out->good());
01058 
01059         // Save stream flags
01060         std::ios_base::fmtflags out_flags = out->flags();
01061 
01062         // We will use scientific notation with a precision of 16
01063         // digits in the following output.  The desired precision and
01064         // format will automatically determine the width.
01065         *out << std::scientific
01066              << std::setprecision(16);
01067 
01068         if (line_break == libMesh::invalid_uint)
01069           for (unsigned int i=0; i<len; i++)
01070             {
01071               libmesh_assert(out.get());
01072               libmesh_assert (out->good());
01073               *out << val[i] << ' ';
01074             }
01075         else
01076           {
01077             unsigned int cnt=0;
01078             while (cnt < len)
01079               {
01080                 for (unsigned int i=0; i<std::min(line_break,len); i++)
01081                   {
01082                     libmesh_assert(out.get());
01083                     libmesh_assert (out->good());
01084                     *out << val[cnt++] << ' ';
01085                   }
01086                 libmesh_assert(out.get());
01087                 libmesh_assert (out->good());
01088                 *out << '\n';
01089               }
01090           }
01091 
01092         // Restore stream flags
01093         out->flags(out_flags);
01094 
01095         return;
01096       }
01097 
01098     default:
01099       libmesh_error_msg("Invalid mode = " << mode);
01100     }
01101 }
01102 
01103 
01104 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
01105 template <>
01106 void Xdr::data_stream (std::complex<double> *val, const unsigned int len, const unsigned int line_break)
01107 {
01108   switch (mode)
01109     {
01110     case ENCODE:
01111     case DECODE:
01112       {
01113 #ifdef LIBMESH_HAVE_XDR
01114 
01115         libmesh_assert (this->is_open());
01116 
01117 
01118         if (len > 0)
01119           {
01120             std::vector<double> io_buffer (2*len);
01121 
01122             // Fill io_buffer if we are writing.
01123             if (mode == ENCODE)
01124               for (unsigned int i=0, cnt=0; i<len; i++)
01125                 {
01126                   io_buffer[cnt++] = val[i].real();
01127                   io_buffer[cnt++] = val[i].imag();
01128                 }
01129 
01130             xdr_vector(xdrs,
01131                        (char*) &io_buffer[0],
01132                        2*len,
01133                        sizeof(double),
01134                        (xdrproc_t) xdr_double);
01135 
01136             // Fill val array if we are reading.
01137             if (mode == DECODE)
01138               for (unsigned int i=0, cnt=0; i<len; i++)
01139                 {
01140                   double re = io_buffer[cnt++];
01141                   double im = io_buffer[cnt++];
01142                   val[i] = std::complex<double>(re,im);
01143                 }
01144           }
01145 #else
01146 
01147         libmesh_error_msg("ERROR: Functionality is not available.\n"    \
01148                           << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
01149                           << "The XDR interface is not available in this installation");
01150 
01151 #endif
01152         return;
01153       }
01154 
01155     case READ:
01156       {
01157         libmesh_assert(in.get());
01158         libmesh_assert (in->good());
01159 
01160         for (unsigned int i=0; i<len; i++)
01161           {
01162             libmesh_assert(in.get());
01163             libmesh_assert (in->good());
01164             double re, im;
01165             *in >> re >> im;
01166             val[i] = std::complex<double>(re,im);
01167           }
01168 
01169         return;
01170       }
01171 
01172     case WRITE:
01173       {
01174         libmesh_assert(out.get());
01175         libmesh_assert (out->good());
01176 
01177         // Save stream flags
01178         std::ios_base::fmtflags out_flags = out->flags();
01179 
01180         // We will use scientific notation with a precision of 16
01181         // digits in the following output.  The desired precision and
01182         // format will automatically determine the width.
01183         *out << std::scientific
01184              << std::setprecision(16);
01185 
01186         if (line_break == libMesh::invalid_uint)
01187           for (unsigned int i=0; i<len; i++)
01188             {
01189               libmesh_assert(out.get());
01190               libmesh_assert (out->good());
01191               *out << val[i].real() << ' ';
01192               *out << val[i].imag() << ' ';
01193             }
01194         else
01195           {
01196             unsigned int cnt=0;
01197             while (cnt < len)
01198               {
01199                 for (unsigned int i=0; i<std::min(line_break,len); i++)
01200                   {
01201                     libmesh_assert(out.get());
01202                     libmesh_assert (out->good());
01203                     *out << val[cnt].real() << ' ';
01204                     *out << val[cnt].imag() << ' ';
01205                     cnt++;
01206                   }
01207                 libmesh_assert(out.get());
01208                 libmesh_assert (out->good());
01209                 *out << '\n';
01210               }
01211           }
01212 
01213         // Restore stream flags
01214         out->flags(out_flags);
01215 
01216         return;
01217       }
01218 
01219     default:
01220       libmesh_error_msg("Invalid mode = " << mode);
01221     }
01222 }
01223 
01224 template <>
01225 void Xdr::data_stream (std::complex<long double> *val, const unsigned int len, const unsigned int line_break)
01226 {
01227   switch (mode)
01228     {
01229     case ENCODE:
01230     case DECODE:
01231       {
01232 #ifdef LIBMESH_HAVE_XDR
01233 
01234         libmesh_assert (this->is_open());
01235 
01236         // FIXME[JWP]: How to implement this for long double?  Mac OS
01237         // X defines 'xdr_quadruple' but AFAICT, it does not exist for
01238         // Linux... for now, reading/writing XDR files with long
01239         // doubles drops back to double precision, but you can still
01240         // write long double ASCII files of course.
01241 
01242         if (len > 0)
01243           {
01244             std::vector<double> io_buffer (2*len);
01245 
01246             // Fill io_buffer if we are writing.
01247             if (mode == ENCODE)
01248               for (unsigned int i=0, cnt=0; i<len; i++)
01249                 {
01250                   io_buffer[cnt++] = val[i].real();
01251                   io_buffer[cnt++] = val[i].imag();
01252                 }
01253 
01254             xdr_vector(xdrs,
01255                        (char*) &io_buffer[0],
01256                        2*len,
01257                        sizeof(double),
01258                        (xdrproc_t) xdr_double);
01259 
01260             // Fill val array if we are reading.
01261             if (mode == DECODE)
01262               for (unsigned int i=0, cnt=0; i<len; i++)
01263                 {
01264                   double re = io_buffer[cnt++];
01265                   double im = io_buffer[cnt++];
01266                   val[i] = std::complex<long double>(re, im);
01267                 }
01268           }
01269 #else
01270 
01271         libmesh_error_msg("ERROR: Functionality is not available.\n"    \
01272                           << "Make sure LIBMESH_HAVE_XDR is defined at build time\n" \
01273                           << "The XDR interface is not available in this installation");
01274 
01275 #endif
01276         return;
01277       }
01278 
01279     case READ:
01280       {
01281         libmesh_assert(in.get());
01282         libmesh_assert (in->good());
01283 
01284         for (unsigned int i=0; i<len; i++)
01285           {
01286             libmesh_assert(in.get());
01287             libmesh_assert (in->good());
01288             long double re, im;
01289             *in >> re >> im;
01290             val[i] = std::complex<long double>(re,im);
01291           }
01292 
01293         return;
01294       }
01295 
01296     case WRITE:
01297       {
01298         libmesh_assert(out.get());
01299         libmesh_assert (out->good());
01300 
01301 
01302         // Save stream flags
01303         std::ios_base::fmtflags out_flags = out->flags();
01304 
01305         // We will use scientific notation with a precision of
01306         // 'digits10' digits in the following output.  The desired
01307         // precision and format will automatically determine the
01308         // width.  Note: digit10 is the number of digits (in decimal
01309         // base) that can be represented without change.  Equivalent
01310         // to FLT_DIG, DBL_DIG or LDBL_DIG for floating types.
01311         *out << std::scientific
01312              << std::setprecision(std::numeric_limits<long double>::digits10);
01313 
01314         if (line_break == libMesh::invalid_uint)
01315           for (unsigned int i=0; i<len; i++)
01316             {
01317               libmesh_assert(out.get());
01318               libmesh_assert (out->good());
01319               *out << val[i].real() << ' ' << val[i].imag() << ' ';
01320             }
01321         else
01322           {
01323             unsigned int cnt=0;
01324             while (cnt < len)
01325               {
01326                 for (unsigned int i=0; i<std::min(line_break,len); i++)
01327                   {
01328                     libmesh_assert(out.get());
01329                     libmesh_assert (out->good());
01330                     *out << val[cnt].real() << ' ' << val[cnt].imag() << ' ';
01331                     cnt++;
01332                   }
01333                 libmesh_assert(out.get());
01334                 libmesh_assert (out->good());
01335                 *out << '\n';
01336               }
01337           }
01338 
01339         // Restore stream flags
01340         out->flags(out_flags);
01341 
01342         return;
01343       }
01344 
01345     default:
01346       libmesh_error_msg("Invalid mode = " << mode);
01347     }
01348 }
01349 #endif // # LIBMESH_USE_COMPLEX_NUMBERS
01350 
01351 void Xdr::comment (std::string &comment_in)
01352 {
01353   switch (mode)
01354     {
01355     case ENCODE:
01356     case DECODE:
01357       {
01358         return;
01359       }
01360 
01361     case READ:
01362       {
01363         libmesh_assert(in.get());
01364         libmesh_assert (in->good());
01365         in->getline(comm, comm_len);
01366         return;
01367       }
01368 
01369     case WRITE:
01370       {
01371         libmesh_assert(out.get());
01372         libmesh_assert (out->good());
01373         *out << "\t " << comment_in << '\n';
01374         return;
01375       }
01376 
01377     default:
01378       libmesh_error_msg("Invalid mode = " << mode);
01379     }
01380 }
01381 
01382 
01383 #undef xdr_REAL
01384 
01385 
01386 //
01387 template void Xdr::data<int>                              (int&,                             const char*);
01388 template void Xdr::data<unsigned int>                     (unsigned int&,                    const char*);
01389 template void Xdr::data<unsigned short int>               (unsigned short int&,              const char*);
01390 template void Xdr::data<short int>                        (short int&,                       const char*);
01391 template void Xdr::data<unsigned long int>                (unsigned long int&,               const char*);
01392 template void Xdr::data<unsigned long long>               (unsigned long long&,              const char*);
01393 template void Xdr::data<long int>                         (long int&,                        const char*);
01394 template void Xdr::data<char>                             (char&,                            const char*);
01395 template void Xdr::data<signed char>                      (signed char&,                     const char*);
01396 template void Xdr::data<unsigned char>                    (unsigned char&,                   const char*);
01397 template void Xdr::data<float>                            (float&,                           const char*);
01398 template void Xdr::data<double>                           (double&,                          const char*);
01399 template void Xdr::data<long double>                      (long double&,                     const char*);
01400 template void Xdr::data<std::complex<float> >             (std::complex<float>&,             const char*);
01401 template void Xdr::data<std::complex<double> >            (std::complex<double>&,            const char*);
01402 template void Xdr::data<std::complex<long double> >       (std::complex<long double>&,       const char*);
01403 template void Xdr::data<std::string>                      (std::string&,                     const char*);
01404 template void Xdr::data<std::vector<int> >                (std::vector<int>&,                const char*);
01405 template void Xdr::data<std::vector<unsigned int> >       (std::vector<unsigned int>&,       const char*);
01406 template void Xdr::data<std::vector<short int> >          (std::vector<short int>&,          const char*);
01407 template void Xdr::data<std::vector<unsigned short int> > (std::vector<unsigned short int>&, const char*);
01408 template void Xdr::data<std::vector<long int> >           (std::vector<long int>&,           const char*);
01409 template void Xdr::data<std::vector<unsigned long int> >  (std::vector<unsigned long int>&,  const char*);
01410 template void Xdr::data<std::vector<unsigned long long> > (std::vector<unsigned long long>&, const char*);
01411 template void Xdr::data<std::vector<char> >               (std::vector<char>&,               const char*);
01412 template void Xdr::data<std::vector<signed char> >        (std::vector<signed char>&,        const char*);
01413 template void Xdr::data<std::vector<unsigned char> >      (std::vector<unsigned char>&,      const char*);
01414 template void Xdr::data<std::vector<float> >              (std::vector<float>&,              const char*);
01415 template void Xdr::data<std::vector<double> >             (std::vector<double>&,             const char*);
01416 template void Xdr::data<std::vector<long double> >        (std::vector<long double>&,        const char*);
01417 template void Xdr::data<std::vector<std::complex<float> > >  (std::vector<std::complex<float> >&,  const char*);
01418 template void Xdr::data<std::vector<std::complex<double> > > (std::vector<std::complex<double> >&, const char*);
01419 template void Xdr::data<std::vector<std::complex<long double> > > (std::vector<std::complex<long double> >&, const char*);
01420 template void Xdr::data<std::vector<std::string> >        (std::vector<std::string>&,        const char*);
01421 template void Xdr::data_stream<int>                (int *val,                const unsigned int len, const unsigned int line_break);
01422 template void Xdr::data_stream<unsigned short int> (unsigned short int *val, const unsigned int len, const unsigned int line_break);
01423 template void Xdr::data_stream<unsigned int>       (unsigned int *val,       const unsigned int len, const unsigned int line_break);
01424 template void Xdr::data_stream<unsigned long int>  (unsigned long int *val,  const unsigned int len, const unsigned int line_break);
01425 template void Xdr::data_stream<unsigned long long> (unsigned long long *val, const unsigned int len, const unsigned int line_break);
01426 
01427 } // namespace libMesh