1 #ifndef DUNE_FEM_STANDARDSTREAMS_HH
2 #define DUNE_FEM_STANDARDSTREAMS_HH
3 
4 #include <fstream>
5 #include <utility>
6 #include <memory>
7 
8 #ifdef SYSTEM_ENDIAN_HEADER
9 #include SYSTEM_ENDIAN_HEADER
10 #endif
11 
12 #include <dune/fem/io/streams/streams.hh>
13 
14 namespace Dune
15 {
16 
17   namespace Fem
18   {
19 
20     struct ByteOrder
21     {
22       // the default endianess is little, e.g. 0
23       static const char defaultEndian = 0;
24       static const char order =
25 #if __BYTE_ORDER == __LITTLE_ENDIAN
26           0 ;
27 #elif __BYTE_ORDER == __BIG_ENDIAN
28           1 ;
29 #else
30           0 ; // default is zero (in case no endian header was found)
31 #endif
mapDune::Fem::ByteOrder32       static inline size_t map( const size_t pos,
33                                 const size_t size )
34       {
35         // if byte order is not little endian, swap bytes
36         return ( order == defaultEndian ) ? pos : ( size - pos - 1 );
37       }
38     };
39 
40     class StandardOutStream;
41     class StandardInStream;
42 
43     struct StandardOutStreamTraits
44     {
45       typedef StandardOutStream OutStreamType;
46     };
47 
48     /** \class StandardOutStream
49      *  \ingroup InOutStreams
50      *  \brief output stream writing into a given std::ostream
51      *
52      *  \note This stream directly stores the binary representation of the data.
53      *        The binary representation of the stored data is always little endian.
54      *        On write the data is converted accordingly on machines
55      *        with different endianess.
56      *
57      *  \newimplementation
58      */
59     class StandardOutStream
60     : public OutStreamInterface< StandardOutStreamTraits >
61     {
62       typedef StandardOutStream ThisType;
63       typedef OutStreamInterface< StandardOutStreamTraits > BaseType;
64 
65     public:
66       //! type of the traits
67       typedef StandardOutStreamTraits Traits;
68 
69     protected:
70       using BaseType::writeError;
71 
72     public:
73       /** \brief constructor
74        *
75        *  \param[in]  stream  std::ostream to write to
76        */
StandardOutStream(std::ostream & stream)77       explicit StandardOutStream ( std::ostream& stream )
78       : stream_( stream )
79       {
80         if( ! stream )
81           DUNE_THROW( Dune::IOError, "Stream not valid!" );
82       }
83 
84       /** return reference to internal ostream */
stream()85       std::ostream& stream() { return stream_; }
86 
87       /** \copydoc Dune::Fem::OutStreamInterface::flush */
flush()88       void flush ()
89       {
90         stream_.flush();
91       }
92 
93       /** \copydoc Dune::Fem::OutStreamInterface::writeDouble */
writeDouble(const double value)94       void writeDouble ( const double value )
95       {
96         writePrimitive( value );
97       }
98 
99       /** \copydoc Dune::Fem::OutStreamInterface::writeFloat */
writeFloat(const float value)100       void writeFloat ( const float value )
101       {
102         writePrimitive( value );
103       }
104 
105       /** \copydoc Dune::Fem::OutStreamInterface::writeInt */
writeInt(const int value)106       void writeInt ( const int value )
107       {
108         writePrimitive( value );
109       }
110 
111       /** \copydoc Dune::Fem::OutStreamInterface::writeChar */
writeChar(const char value)112       void writeChar ( const char value )
113       {
114         writePrimitive( value );
115       }
116 
117       /** \copydoc Dune::Fem::OutStreamInterface::writeChar */
writeBool(const bool value)118       void writeBool ( const bool value )
119       {
120         writePrimitive( value );
121       }
122 
123       /** \copydoc Dune::Fem::OutStreamInterface::writeString */
writeString(const std::string & s)124       void writeString ( const std::string &s )
125       {
126         const unsigned int length = s.length();
127         writePrimitive( length );
128         for( unsigned int i = 0; i < length; ++i )
129           writePrimitive( s[ i ] );
130       }
131 
132       /** \copydoc Dune::Fem::OutStreamInterface::writeUnsignedInt */
writeUnsignedInt(unsigned int value)133       void writeUnsignedInt ( unsigned int value )
134       {
135         writePrimitive( value );
136       }
137 
138       /** \copydoc Dune::Fem::OutStreamInterface::writeUnsignedInt64 */
writeUnsignedInt64(uint64_t value)139       void writeUnsignedInt64 ( uint64_t value )
140       {
141         writePrimitive( value );
142       }
143 
144     protected:
valid() const145       bool valid () const
146       {
147         return bool( stream_ );
148       }
149 
150       template< class T >
writePrimitive(const T & value)151       void writePrimitive ( const T &value )
152       {
153         const size_t tsize = sizeof( T );
154         union { T value; char bytes[ tsize ]; } convert;
155 
156         // copy  value
157         convert.value = value;
158 
159         // make sure that char is only one byte
160         assert( sizeof(char) == 1 ) ;
161 
162         // write with byte order little endian
163         for( size_t i=0; i<tsize; ++i )
164         {
165           stream_.put( convert.bytes[ ByteOrder :: map( i, tsize ) ] );
166         }
167 
168         if( !valid () )
169           writeError();
170       }
171 
172     protected:
173       std::ostream& stream_;
174     };
175 
176 
177     struct StandardInStreamTraits
178     {
179       typedef StandardInStream InStreamType;
180     };
181 
182 
183     /** \class StandardInStream
184      *  \ingroup InOutStreams
185      *  \brief input stream reading from a given std::istream
186      *
187      *  \note This stream directly stores the binary representation of the data.
188      *        The binary representation of the stored data is always little endian.
189      *        On read the data is converted accordingly on machines
190      *        with different endianess.
191      *
192      *  \newimplementation
193      */
194     class StandardInStream
195     : public InStreamInterface< StandardInStreamTraits >
196     {
197       typedef StandardInStream ThisType;
198       typedef InStreamInterface< StandardInStreamTraits > BaseType;
199 
200     public:
201       //! type of the traits
202       typedef StandardInStreamTraits Traits;
203 
204     protected:
205       using BaseType::readError;
206 
207     public:
208       /** \brief constructor
209        *
210        *  \param[in]  stream  std::istream to read from
211        */
StandardInStream(std::istream & stream)212       explicit StandardInStream ( std::istream& stream )
213       : stream_( stream )
214       {
215         if( ! valid() )
216           DUNE_THROW( Dune::IOError, "Stream not valid!" );
217       }
218 
219       /** return reference to internal istream */
stream()220       std::istream& stream() { return stream_; }
221 
222       /** \copydoc Dune::Fem::InStreamInterface::readDouble */
readDouble(double & value)223       void readDouble ( double &value )
224       {
225         readPrimitive( value );
226       }
227 
228       /** \copydoc Dune::Fem::InStreamInterface::readFloat */
readFloat(float & value)229       void readFloat ( float &value )
230       {
231         readPrimitive( value );
232       }
233 
234       /** \copydoc Dune::Fem::InStreamInterface::readInt */
readInt(int & value)235       void readInt ( int &value )
236       {
237         readPrimitive( value );
238       }
239 
240       /** \copydoc Dune::Fem::InStreamInterface::readChar */
readChar(char & value)241       void readChar ( char &value )
242       {
243         readPrimitive( value );
244       }
245 
246       /** \copydoc Dune::Fem::InStreamInterface::readBool */
readBool(bool & value)247       void readBool ( bool &value )
248       {
249         readPrimitive( value );
250       }
251 
252       /** \copydoc Dune::Fem::InStreamInterface::readString */
readString(std::string & s)253       void readString ( std::string &s )
254       {
255         unsigned int length;
256         readPrimitive( length );
257 
258         // resize string
259         s.resize( length );
260         for( unsigned int i = 0; i < length; ++i )
261         {
262           readPrimitive( s[ i ] );
263         }
264       }
265 
266       /** \copydoc Dune::Fem::InStreamInterface::readUnsignedInt */
readUnsignedInt(unsigned int & value)267       void readUnsignedInt ( unsigned int &value )
268       {
269         readPrimitive( value );
270       }
271 
272       /** \copydoc Dune::Fem::InStreamInterface::readUnsignedInt64 */
readUnsignedInt64(uint64_t & value)273       void readUnsignedInt64 ( uint64_t &value )
274       {
275         readPrimitive( value );
276       }
277 
278     protected:
valid() const279       bool valid () const
280       {
281         return stream_.good() | stream_.eof();
282       }
283 
284       template< class T >
readPrimitive(T & value)285       void readPrimitive ( T &value )
286       {
287         const size_t tsize = sizeof( T ) ;
288         union { T value; char bytes[ tsize ]; } convert;
289 
290         // char should be only 1 byte
291         assert( sizeof(char) == 1 ) ;
292 
293         // read from stream with byte order little endian
294         for( size_t i=0; i<tsize; ++i )
295         {
296           convert.bytes[ ByteOrder :: map( i, tsize ) ] = stream_.get();
297         }
298 
299         // store result to value
300         value = convert.value;
301 
302         if( !valid() )
303           readError();
304       }
305 
306     protected:
307       std::istream& stream_;
308     };
309 
310   } // namespace Fem
311 
312 } // namespace Dune
313 
314 #endif // #ifndef DUNE_FEM_BINARYSTREAMS_HH
315