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