Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

more/io/syncstream.h

Go to the documentation of this file.
00001 
00002 //  Copyright (C) 2000--2001  Petter Urkedal (petter.urkedal@matfys.lth.se)
00003 
00004 //  This file is free software; you can redistribute it and/or modify
00005 //  it under the terms of the GNU General Public License as published by
00006 //  the Free Software Foundation; either version 2 of the License, or
00007 //  (at your option) any later version.
00008 
00009 //  This file 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
00012 //  GNU General Public License for more details.
00013 
00014 //  You should have received a copy of the GNU General Public License
00015 //  along with this program; if not, write to the Free Software
00016 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 //  As a special exception, you may use this file as part of a free
00019 //  software library without restriction.  Specifically, if other files
00020 //  instantiate templates or use macros or inline functions from this
00021 //  file, or you compile this file and link it with other files to
00022 //  produce an executable, this file does not by itself cause the
00023 //  resulting executable to be covered by the GNU General Public
00024 //  License.  This exception does not however invalidate any other
00025 //  reasons why the executable file might be covered by the GNU General
00026 //  Public License.
00027 
00028 //  $Id: syncstream.h,v 1.1 2002/05/30 18:01:37 petter_urkedal Exp $
00029 
00030 
00031 
00032 //  Here is a way to implement versioning in a sub-structure
00033 //
00034 //      void someclass::sync(more::syncstream& sio) {
00035 //          int version = 1;
00036 //          sio | version;
00037 //          switch (version) {
00038 //            case 0:
00039 //              sio | a | c;
00040 //              b = b_default;
00041 //              break;
00042 //            case 1:
00043 //              sio | a | b | c;
00044 //            break;
00045 //          }
00046 //     }
00047 
00048 #ifndef MORE_SYNCSTREAM_H
00049 #define MORE_SYNCSTREAM_H
00050 
00051 #include <stdexcept>
00052 #include <string>
00053 #include <utility>
00054 #include <iostream>
00055 #include <fstream>
00056 #include <more/io/binary_io.h>
00057 #include <complex>
00058 
00059 namespace more {
00060 namespace io {
00061 
00062   using std::size_t;
00063 
00064 
00065   /** \class syncstream syncstream.h more/io/syncstream.h
00066    **
00067    ** A stream which provides both input and output using the same
00068    ** calls.  The data is binary encoded, but architecture
00069    ** independent.  */
00070   struct syncstream
00071   {
00072       enum openmode
00073       {
00074           in = 1,
00075           out = 2,
00076           test = 3
00077       };
00078 
00079     protected:
00080       syncstream(std::streambuf* buf);
00081       syncstream(std::streambuf* buf, std::ios_base::openmode mode_);
00082       void prolog(std::ios_base::openmode mode_);
00083 
00084     public:
00085       /** Use \a dig mantissa bits precision for writing floats.  This
00086           defaults to \c std::numeric_limits<double>::digits.  This is
00087           an upper limit.  When writing a floating point number of
00088           type \c T, the smaller of \c std::numeric_limits<T>::digits
00089           and \a dig is used. */
00090       void set_digits(int dig) { m_dig = dig; }
00091 
00092       /** Use \a dig10 decimal digits precision for writing floats. */
00093       void set_digits10(int dig10);
00094 
00095       /** Return the mantissa bits precision as set by \c set_digits. */
00096       int digits() { return m_dig; }
00097 
00098       /** Return \c digits() converted to decimal digits. */
00099       int digits10();
00100 
00101       /** Return true if this is an input stream. */
00102       bool is_input() { return m_mode & std::ios_base::in; }
00103 
00104       /** Return true if this is an output stream. */
00105       bool is_output() { return m_mode & std::ios_base::out; }
00106 
00107       /** Return true if no errors has occured. */
00108       bool good() { return m_ios.good(); }
00109 
00110       /** Return true if an error has occured. */
00111       bool fail() { return m_ios.fail(); }
00112 
00113       /** Return true if a file read error has occured. */
00114       bool bad()  { return m_ios.bad(); }
00115 
00116       /** Set the fail state of the stream. */
00117       void setstate(std::ios_base::iostate st) { m_ios.setstate(st); }
00118 
00119       /** Clear the fail state of the stream. */
00120       void clear() { m_ios.clear(); }
00121 
00122       /** Sync known size raw data.  This breaks the binary dump
00123        ** utility.  Be careful if architecture independence is
00124        ** needed. */
00125       void sync_raw_data(void* p, size_t n);
00126 
00127       /** Call \c x.sync(*this) and return \c *this. */
00128       template<typename T>
00129         syncstream& operator|(T& x) { x.sync(*this); return *this; }
00130 
00131       ///@{
00132       /** Sync \a x into or out of the stream and return \c *this. */
00133       syncstream& operator|(char& x) { sync(x); return *this; }
00134       syncstream& operator|(signed char& x) { sync(x); return *this; }
00135       syncstream& operator|(unsigned char& x) { sync(x); return *this; }
00136       syncstream& operator|(short& x) { sync(x); return *this; }
00137       syncstream& operator|(unsigned short& x) { sync(x); return *this; }
00138       syncstream& operator|(int& x) { sync(x); return *this; }
00139       syncstream& operator|(unsigned int& x) { sync(x); return *this; }
00140       syncstream& operator|(long& x) { sync(x); return *this; }
00141       syncstream& operator|(unsigned long& x) { sync(x); return *this; }
00142 #ifdef MORE_HAVE_LONG_LONG
00143       syncstream& operator|(long long& x) { sync(x); return *this; }
00144       syncstream& operator|(unsigned long long& x) {sync(x);return*this;}
00145 #endif
00146 
00147       syncstream& operator|(bool& x) { sync(x); return *this; }
00148 
00149       syncstream& operator|(float& x) { sync_fp(x); return *this; }
00150       syncstream& operator|(double& x) { sync_fp(x); return *this; }
00151       syncstream& operator|(long double& x) { sync_fp(x); return *this; }
00152       syncstream& operator|(std::complex<float>& x)
00153       { sync_cplx(x); return *this; }
00154       syncstream& operator|(std::complex<double>& x)
00155       { sync_cplx(x); return *this; }
00156       syncstream& operator|(std::complex<long double>& x)
00157       { sync_cplx(x); return *this; }
00158 
00159       syncstream& operator|(std::string& x) { sync(x); return *this; }
00160       template<typename T, typename U>
00161         syncstream& operator|(std::pair<T, U>& x)
00162         {
00163             *this | x.first | x.second;
00164             return *this;
00165         }
00166       ///@}
00167 
00168       syncstream& operator|(void (*f)(syncstream&)) { f(*this); return *this; }
00169 
00170       /// \internal
00171       int _version() const { return m_version; }
00172 
00173     private:
00174       std::iostream             m_ios;
00175       std::ios_base::openmode   m_mode;
00176       int                       m_dig;
00177       int                       m_version;
00178 
00179       template<typename T>
00180         void sync(T& x)
00181         {
00182             if (m_mode & std::ios_base::binary) {
00183                 if (m_mode & std::ios_base::out)
00184                     binary_write(m_ios, x);
00185                 if (m_mode & std::ios_base::in)
00186                     binary_read(m_ios, x);
00187             }
00188             else
00189                 throw std::logic_error
00190                   ("syncstream: ascii mode not implemented");
00191         }
00192 
00193       template<typename T>
00194         void sync_fp(T& x)
00195         {
00196             if (m_mode & std::ios_base::binary) {
00197                 if (m_mode & std::ios_base::out)
00198                     binary_write(m_ios, x,
00199                                  std::min(std::numeric_limits<T>
00200                                           ::digits, m_dig));
00201                 if (m_mode & std::ios_base::in)
00202                     binary_read(m_ios, x);
00203             }
00204             else
00205                 throw std::logic_error
00206                   ("syncstream: ascii mode not implemented");
00207         }
00208 
00209       template<typename T>
00210         void sync_cplx(std::complex<T>& x)
00211         {
00212             T re = x.real();
00213             T im = x.imag();
00214             *this | re | im;
00215             x = std::complex<T>(re, im);
00216         }
00217   };
00218 
00219   /** \class setdigits syncstream.h more/io/syncstream.h
00220    ** 
00221    ** IO manipulator to set the precision of floats written by \c
00222    ** syncstream. */
00223   struct setdigits {
00224       setdigits(int dig_) : m_dig(dig_) {}
00225 
00226       friend syncstream&
00227       operator|(syncstream& sync, setdigits x)
00228       {
00229           sync.set_digits(x.m_dig);
00230           return sync;
00231       }
00232     private:
00233       int m_dig;
00234   };
00235 
00236   /** \class setdigits10 syncstream.h more/io/syncstream.h
00237    **
00238    ** IO manipulator to set the precision of floats written by \c
00239    ** syncstream. */
00240   struct setdigits10
00241   {
00242       setdigits10(int dig_) : m_dig(dig_) {}
00243 
00244       friend syncstream&
00245       operator|(syncstream& sync, setdigits10 x)
00246       {
00247           sync.set_digits10(x.m_dig);
00248           return sync;
00249       }
00250     private:
00251       int m_dig;
00252   };
00253 
00254   /** \class fsyncstream syncstream.h more/io/syncstream.h
00255    **
00256    ** A file-based syncstream. */
00257   struct fsyncstream : syncstream
00258   {
00259       fsyncstream()
00260           : syncstream(&sb) {}
00261 
00262       fsyncstream(const char* name, std::ios_base::openmode mode)
00263           : syncstream(&sb)
00264       {
00265           this->open(name, mode);
00266       }
00267 
00268       fsyncstream(const char* name, syncstream::openmode mode)
00269           : syncstream(&sb)
00270       {
00271           if (mode & in) {
00272               open(name, std::ios_base::binary | std::ios_base::in);
00273               if (!good() && (mode & out))
00274                   open(name, std::ios_base::binary | std::ios_base::out);
00275           }
00276       }
00277 
00278       std::filebuf* rdbuf() { return &sb; }
00279       std::filebuf const* rdbuf() const { return &sb; }
00280 
00281       bool is_open() const { return rdbuf()->is_open(); }
00282 
00283       void open(const char* name, std::ios_base::openmode mode) {
00284           rdbuf()->open(name, mode);
00285           prolog(mode);
00286       }
00287 
00288       void close() {
00289           clear();
00290           if (!rdbuf()->close())
00291               setstate(std::ios_base::failbit);
00292       }
00293 
00294     private:
00295       std::filebuf sb;
00296   };
00297 
00298   /** \class ifsyncstream syncstream.h more/io/syncstream.h
00299    **
00300    ** A file-based syncstream which will be opened for input. */
00301   struct ifsyncstream : fsyncstream
00302   {
00303       /** Construct a stream which be opend later with \c open. */
00304       ifsyncstream() {}
00305 
00306       /** Construct a syncstream with input from the file named \a name. */
00307       ifsyncstream(const char* name,
00308                    std::ios_base::openmode mode
00309                    = std::ios_base::in | std::ios_base::binary)
00310           : fsyncstream(name, mode) {}
00311 
00312       /** Open the file named \a name for input and attach it to this
00313        ** stream. */
00314       void open(const char* name,
00315                 std::ios_base::openmode mode
00316                 = std::ios_base::in | std::ios_base::binary)
00317       {
00318           fsyncstream::open(name, mode);
00319       }
00320   };
00321 
00322   /** \class ofsyncstream syncstream.h more/io/syncstream.h
00323    **
00324    ** A file-based syncstream which will be opened for output. */
00325   struct ofsyncstream : fsyncstream
00326   {
00327       /** Construct a stream which be opend later with \c open. */
00328       ofsyncstream() {}
00329 
00330       /** Construct a syncstream with output to the file named \a name. */
00331       ofsyncstream(const char* name,
00332                    std::ios_base::openmode mode
00333                    = std::ios_base::out | std::ios_base::binary)
00334           : fsyncstream(name, mode) {}
00335 
00336       /** Open \a name for writing and set it as output for this
00337        ** \c syncstream. */
00338       void
00339       open(const char* name,
00340            std::ios_base::openmode mode
00341            = std::ios_base::out | std::ios_base::binary)
00342       {
00343           fsyncstream::open(name, mode);
00344       }
00345   };
00346 
00347   /** Skip \a i items of type \a T. */
00348   template<typename T>
00349     void sync_skip(syncstream& sio, int i = 1)
00350     {
00351         T x;
00352         while (i) {
00353             sio | x;
00354             --i;
00355         }
00356     }
00357 
00358   /** Sync an length iterator range of known length. */
00359   template<typename Iterator>
00360     void sync_range(syncstream& sio, Iterator first, Iterator last)
00361     {
00362         while (first != last) sio | *first, ++first;
00363     }
00364 
00365   /** Sync a sequence (like a <tt>std::list</tt> or a
00366       <tt>std::vector</tt>). */
00367   template<typename Seq>
00368     void sync_sequence(syncstream& sio, Seq& c)
00369     {
00370         typename Seq::size_type n;
00371         if (sio.is_input()) {
00372             sio | n;
00373             if (!sio.good()) return;
00374             c.resize(n);
00375         }
00376         else {
00377             n = c.size();
00378             sio | n;
00379             if (!sio.good()) return;
00380         }
00381         sync_range(sio, c.begin(), c.end());
00382     }
00383 
00384   /** Sync an associative container (like a <tt>std::set</tt>).  */
00385   template<typename Assoc>
00386     void sync_associative_container(syncstream& sio, Assoc& x)
00387     {
00388         typename Assoc::size_type n;
00389         typename Assoc::value_type v;
00390         if (sio.is_input()) {
00391             sio | n;
00392             while (n--) {
00393                 sio | v;
00394                 x.insert(x.end(), v);
00395             }
00396         }
00397         else {
00398             n = x.size();
00399             sio | n;
00400             for (typename Assoc::iterator it = x.begin();
00401                  it != x.end(); ++it) {
00402                 v = *it;
00403                 sio | v;
00404             }
00405         }
00406     }
00407 
00408   /** Sync a pair-associative container (like a <tt>std::map</tt>). */
00409   template<typename Assoc>
00410     void sync_pair_associative_container(syncstream& sio, Assoc& x)
00411     {
00412         typename Assoc::size_type n;
00413         typename Assoc::key_type k;
00414         typename Assoc::data_type d;
00415         if (sio.is_input()) {
00416             sio | n;
00417             while (n--) {
00418                 sio | k | d;
00419                 x.insert(typename Assoc::value_type(k, d));
00420             }
00421         }
00422         else {
00423             n = x.size();
00424             sio | n;
00425             for (typename Assoc::iterator it = x.begin(); it != x.end();
00426                  ++it) {
00427                 k = it->first;
00428                 d = it->second;
00429                 sio | k | d;
00430             }
00431         }
00432     }
00433 
00434 }
00435 #if defined(MORE_BACKWARD) && MORE_BACKWARD < 20010615
00436 using namespace io;
00437 #endif
00438 }
00439 
00440 #endif

Generated on Sat Sep 7 19:11:16 2002 for more with Doxygen 1.2.13.1. Doxygen 1.2.13.1 is written and copyright 1997-2002 by Dimitri van Heesch.