bstream.h

Go to the documentation of this file.
00001 /*
00002  *  This file is part of libcxxsupport.
00003  *
00004  *  libcxxsupport 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  *  libcxxsupport 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 libcxxsupport; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00017  */
00018 
00019 /*
00020  *  libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
00021  *  and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
00022  *  (DLR).
00023  */
00024 
00025 /*! \file bstream.h
00026  *  Classes for binary I/O with streams
00027  *
00028  *  Copyright (C) 2010 Max-Planck-Society
00029  *  \author Martin Reinecke
00030  */
00031 
00032 #ifndef PLANCK_BSTREAM_H
00033 #define PLANCK_BSTREAM_H
00034 
00035 #include <iostream>
00036 #include <fstream>
00037 #include <algorithm>
00038 #include "datatypes.h"
00039 
00040 /*! An object of this class can be cast to a \a bool, which indicates whether
00041     the computer architecture is big-endian (true) or little-endian (false). */
00042 class EndianTest__
00043   {
00044   private:
00045     bool big_end;
00046 
00047   public:
00048     EndianTest__()
00049       {
00050       union { uint16 i16; uint8 i8; } tmp;
00051       tmp.i16 = 1;
00052       big_end = (tmp.i8==0);
00053       }
00054     operator bool() const { return big_end; }
00055   };
00056 
00057 const EndianTest__ big_endian;
00058 
00059 template<size_t size> inline void byteswap_helper__ (char *);
00060 template<> inline void byteswap_helper__<1> (char *)
00061   {}
00062 template<> inline void byteswap_helper__<2> (char *val)
00063   {
00064   using namespace std; 
00065   swap (val[0],val[1]);
00066   }
00067 template<> inline void byteswap_helper__<4> (char *val)
00068   {
00069   using namespace std;
00070   swap (val[0],val[3]); swap (val[1],val[2]);
00071   }
00072 template<> inline void byteswap_helper__<8> (char *val)
00073   {
00074   using namespace std;
00075   swap (val[0],val[7]); swap (val[1],val[6]);
00076   swap (val[2],val[5]); swap (val[3],val[4]);
00077   }
00078 
00079 /*! Performs an endianness conversion on \a val.
00080     \note \a T must be a primitive data type! */
00081 template<typename T> inline void byteswap (T &val)
00082   { byteswap_helper__<sizeof(T)> (reinterpret_cast<char *> (&val)); }
00083 
00084 const bool file_is_lsb=big_endian, file_is_msb=!big_endian,
00085            file_is_natural=false;
00086 
00087 /*! Class for writing binary data to a stream. */
00088 class bostream
00089   {
00090   private:
00091     std::ostream &s;
00092     bool doswap;
00093 
00094   public:
00095     /*! Creates a new object which is attached to \a s_ and performs
00096         endianness conversion if \a doswap_==true. */
00097     bostream (std::ostream &s_, bool doswap_=false)
00098       : s(s_), doswap(doswap_) {}
00099 
00100     /*! Writes a binary representation of \a num objects of type \a T
00101         (stored in \a data) to the attached stream. Endianness conversion
00102         is performed if requested in the constructor.
00103         \note \a T must be a primitive data type! */
00104     template<typename T> bostream &put (const T *data, size_t num)
00105       {
00106       if ((sizeof(T)>1) && doswap)
00107         for (size_t m=0; m<num; ++m)
00108           {
00109           T tmp=data[m];
00110           byteswap (tmp);
00111           s.write (reinterpret_cast<const char *> (&tmp), sizeof(T));
00112           }
00113       else
00114         s.write (reinterpret_cast<const char *> (data), num*sizeof(T));
00115       return *this;
00116       }
00117     /*! Writes a binary representation of \a data to the attached stream.
00118         Endianness conversion is performed if requested in the constructor.
00119         \note \a T must be a primitive data type! */
00120     template<typename T> bostream &operator<< (const T &data)
00121       {
00122       put(&data,1);
00123       return *this;
00124       }
00125 
00126     bool getSwap() const
00127       { return doswap; }
00128     void setSwap(bool newswap)
00129       { doswap=newswap; }
00130     void flipSwap()
00131       { doswap=!doswap; }
00132   };
00133 
00134 /*! Class for reading binary data from a stream. */
00135 class bistream
00136   {
00137   private:
00138     std::istream &s;
00139     bool doswap;
00140 
00141   public:
00142     /*! Creates a new object which is attached to \a s_ and performs
00143         endianness conversion if \a doswap_==true. */
00144     bistream (std::istream &s_, bool doswap_=false)
00145       : s(s_), doswap(doswap_) {}
00146 
00147     /*! Reads a binary representation of \a num objects of type \a T
00148         from the attached stream and stores them in \a data. Endianness
00149         conversion is performed if requested in the constructor.
00150         \note \a T must be a primitive data type! */
00151     template<typename T> bistream &get (T *data, size_t num)
00152       {
00153       s.read (reinterpret_cast<char *> (data), num*sizeof(T));
00154       if ((sizeof(T)>1) && doswap)
00155         for (size_t m=0; m<num; ++m)
00156           byteswap (data[m]);
00157       return *this;
00158       }
00159     /*! Reads a binary representation of \a data from the attached stream.
00160         Endianness conversion is performed if requested in the constructor.
00161         \note \a T must be a primitive data type! */
00162     template<typename T> bistream &operator>> (T &data)
00163       {
00164       get (&data,1);
00165       return *this;
00166       }
00167 
00168     bool getSwap() const
00169       { return doswap; }
00170     void setSwap(bool newswap)
00171       { doswap=newswap; }
00172     void flipSwap()
00173       { doswap=!doswap; }
00174   };
00175 
00176 class bofstream: public std::ofstream
00177   {
00178   private:
00179     bool doswap;
00180 
00181   public:
00182     /*! */
00183     bofstream (const char *fname, bool doswap_)
00184       : std::ofstream(fname,std::ios::binary), doswap(doswap_) {}
00185 
00186     template<typename T> bofstream &operator<< (const T &data)
00187       {
00188       if (doswap)
00189         {
00190         T tmp = data;
00191         byteswap (tmp);
00192         write (reinterpret_cast<const char *> (&tmp), sizeof(T));
00193         }
00194       else
00195         write (reinterpret_cast<const char *> (&data), sizeof(T));
00196       return *this;
00197       }
00198     template<typename T> bofstream &put (const T *data, size_t num)
00199       {
00200       if (doswap)
00201         for (size_t m=0; m<num; ++m)
00202           {
00203           T tmp=data[m];
00204           byteswap (tmp);
00205           write (reinterpret_cast<const char *> (&tmp), sizeof(T));
00206           }
00207       else
00208         write (reinterpret_cast<const char *> (data), num*sizeof(T));
00209       return *this;
00210       }
00211 
00212     bool getSwap() const
00213       { return doswap; }
00214     void setSwap(bool newswap)
00215       { doswap=newswap; }
00216     void flipSwap()
00217       { doswap=!doswap; }
00218   };
00219 
00220 class bifstream: public std::ifstream
00221   {
00222   private:
00223     bool doswap;
00224 
00225   public:
00226     /*! */
00227     bifstream ()
00228       : doswap(false) {}
00229     bifstream (const char *fname, bool doswap_)
00230       : std::ifstream(fname,std::ios::binary), doswap(doswap_) {}
00231 
00232     void open (const char *fname, bool doswap_)
00233       {
00234       doswap=doswap_;
00235       std::ifstream::open(fname,std::ios::binary);
00236       }
00237 
00238     template<typename T> bifstream &operator>> (T &data)
00239       {
00240       read (reinterpret_cast<char *> (&data), sizeof(T));
00241       if (doswap) byteswap (data);
00242       return *this;
00243       }
00244     template<typename T> bifstream &get (T *data, size_t num)
00245       {
00246       read (reinterpret_cast<char *> (data), num*sizeof(T));
00247       if (doswap)
00248         for (size_t m=0; m<num; ++m)
00249           byteswap (data[m]);
00250       return *this;
00251       }
00252 
00253     void rewind()
00254       { seekg(0,std::ios::beg); }
00255     void skip(std::streamoff nbytes)
00256       { seekg(nbytes,std::ios::cur); }
00257 
00258     bool getSwap() const
00259       { return doswap; }
00260     void setSwap(bool newswap)
00261       { doswap=newswap; }
00262     void flipSwap()
00263       { doswap=!doswap; }
00264   };
00265 
00266 #endif

Generated on Thu Oct 8 14:48:51 2015 for LevelS C++ support library