OpenMesh
OpenMesh/Core/IO/SR_binary_spec.hh
00001 /*===========================================================================*\
00002  *                                                                           *
00003  *                               OpenMesh                                    *
00004  *      Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen      *
00005  *                           www.openmesh.org                                *
00006  *                                                                           *
00007  *---------------------------------------------------------------------------* 
00008  *  This file is part of OpenMesh.                                           *
00009  *                                                                           *
00010  *  OpenMesh is free software: you can redistribute it and/or modify         * 
00011  *  it under the terms of the GNU Lesser General Public License as           *
00012  *  published by the Free Software Foundation, either version 3 of           *
00013  *  the License, or (at your option) any later version with the              *
00014  *  following exceptions:                                                    *
00015  *                                                                           *
00016  *  If other files instantiate templates or use macros                       *
00017  *  or inline functions from this file, or you compile this file and         *
00018  *  link it with other files to produce an executable, this file does        *
00019  *  not by itself cause the resulting executable to be covered by the        *
00020  *  GNU Lesser General Public License. This exception does not however       *
00021  *  invalidate any other reasons why the executable file might be            *
00022  *  covered by the GNU Lesser General Public License.                        *
00023  *                                                                           *
00024  *  OpenMesh is distributed in the hope that it will be useful,              *
00025  *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
00026  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
00027  *  GNU Lesser General Public License for more details.                      *
00028  *                                                                           *
00029  *  You should have received a copy of the GNU LesserGeneral Public          *
00030  *  License along with OpenMesh.  If not,                                    *
00031  *  see <http://www.gnu.org/licenses/>.                                      *
00032  *                                                                           *
00033 \*===========================================================================*/ 
00034 
00035 /*===========================================================================*\
00036  *                                                                           *             
00037  *   $Revision: 362 $                                                         *
00038  *   $Date: 2011-01-26 10:21:12 +0100 (Mi, 26 Jan 2011) $                   *
00039  *                                                                           *
00040 \*===========================================================================*/
00041 
00042 
00043 //=============================================================================
00044 //
00045 //  Helper Functions for binary reading / writing
00046 //
00047 //=============================================================================
00048 
00049 #ifndef OPENMESH_SR_BINARY_SPEC_HH
00050 #define OPENMESH_SR_BINARY_SPEC_HH
00051 
00052 //== INCLUDES =================================================================
00053 
00054 #include <OpenMesh/Core/System/config.h>
00055 // -------------------- STL
00056 #include <iterator>
00057 #include <string>
00058 #if defined(OM_CC_GCC) && (OM_CC_VERSION < 30000)
00059 #  include <OpenMesh/Tools/Utils/NumLimitsT.hh>
00060 #else
00061 #  include <limits>
00062 #endif
00063 #include <vector>
00064 #include <stdexcept> // logic_error
00065 #include <numeric>   // accumulate
00066 // -------------------- OpenMesh
00067 #include <OpenMesh/Core/Geometry/VectorT.hh>
00068 #include <OpenMesh/Core/Mesh/Status.hh>
00069 #include <OpenMesh/Core/IO/SR_types.hh>
00070 #include <OpenMesh/Core/IO/SR_rbo.hh>
00071 #include <OpenMesh/Core/IO/SR_binary.hh>
00072 
00073 //== NAMESPACES ===============================================================
00074 
00075 namespace OpenMesh {
00076 namespace IO {
00077 
00078 
00079 //=============================================================================
00080 
00081 #ifndef DOXY_IGNORE_THIS
00082 
00083 //-----------------------------------------------------------------------------
00084 // struct binary, helper for storing/restoring
00085 
00086 #define SIMPLE_BINARY( T ) \
00087   template <> struct binary< T > {                           \
00088     typedef T value_type;                                    \
00089     static const bool is_streamable = true;                  \
00090     static size_t size_of(const value_type&) { return sizeof(value_type); }   \
00091     static size_t size_of(void) { return sizeof(value_type); }   \
00092     static size_t store( std::ostream& _os, const value_type& _val, \
00093                          bool _swap=false) {                 \
00094       value_type tmp = _val;                                 \
00095       if (_swap) reverse_byte_order(tmp);                    \
00096       _os.write( (const char*)&tmp, sizeof(value_type) );    \
00097       return _os.good() ? sizeof(value_type) : 0;            \
00098     }                                                        \
00099                                                              \
00100     static size_t restore( std::istream& _is, value_type& _val, \
00101                          bool _swap=false) {                 \
00102       _is.read( (char*)&_val, sizeof(value_type) );          \
00103       if (_swap) reverse_byte_order(_val);                   \
00104       return _is.good() ? sizeof(value_type) : 0;            \
00105     }                                                        \
00106   }
00107 
00108 SIMPLE_BINARY(bool);
00109 //SIMPLE_BINARY(int);
00110 
00111 // Why is this needed? Should not be used as not 32 bit compatible
00112 //SIMPLE_BINARY(unsigned long);
00113 SIMPLE_BINARY(float);
00114 SIMPLE_BINARY(double);
00115 SIMPLE_BINARY(long double);
00116 
00117 SIMPLE_BINARY(int8_t);
00118 SIMPLE_BINARY(int16_t);
00119 SIMPLE_BINARY(int32_t);
00120 SIMPLE_BINARY(int64_t);
00121 SIMPLE_BINARY(uint8_t);
00122 SIMPLE_BINARY(uint16_t);
00123 SIMPLE_BINARY(uint32_t);
00124 SIMPLE_BINARY(uint64_t);
00125 
00126 #undef SIMPLE_BINARY
00127 
00128 // For unsigned long which is of size 64 bit on 64 bit
00129 // architectures: convert into 32 bit unsigned integer value
00130 // in order to stay compatible between 32/64 bit architectures.
00131 // This allows cross reading BUT forbids storing unsigned longs
00132 // as data type since higher order word (4 bytes) will be truncated.
00133 // Does not work in case the data type that is to be stored
00134 // exceeds the value range of unsigned int in size, which is improbable...
00135 
00136 #define SIMPLE_BINARY( T ) \
00137   template <> struct binary< T > {                           \
00138     typedef T value_type;                                    \
00139     static const bool is_streamable = true;                  \
00140     static size_t size_of(const value_type&) { return sizeof(value_type); }   \
00141     static size_t size_of(void) { return sizeof(value_type); }   \
00142     static size_t store( std::ostream& _os, const value_type& _val, \
00143                          bool _swap=false) {                 \
00144       value_type tmp = _val;                                 \
00145       if (_swap) reverse_byte_order(tmp);                    \
00146       /* Convert unsigned long to unsigned int for compatibility reasons */ \
00147       unsigned int t1 = static_cast<unsigned int>(tmp);      \
00148       _os.write( (const char*)&t1, sizeof(unsigned int) );   \
00149       return _os.good() ? sizeof(unsigned int) : 0;          \
00150     }                                                        \
00151                                                              \
00152     static size_t restore( std::istream& _is, value_type& _val, \
00153                          bool _swap=false) {                             \
00154         unsigned int t1;                                     \
00155       _is.read( (char*)&t1, sizeof(unsigned int) );          \
00156       _val = t1;                                             \
00157       if (_swap) reverse_byte_order(_val);                   \
00158       return _is.good() ? sizeof(unsigned int) : 0;            \
00159     }                                                        \
00160   }
00161 
00162 SIMPLE_BINARY(unsigned long);
00163 
00164 #undef SIMPLE_BINARY
00165 
00166 #define VECTORT_BINARY( T ) \
00167   template <> struct binary< T > {                              \
00168     typedef T value_type;                                       \
00169     static const bool is_streamable = true;                     \
00170     static size_t size_of(void) { return sizeof(value_type); }  \
00171     static size_t size_of(const value_type&) { return size_of(); } \
00172     static size_t store( std::ostream& _os, const value_type& _val, \
00173                          bool _swap=false) {                    \
00174       value_type tmp = _val;                                    \
00175       size_t i, b = size_of(_val), N = value_type::size_;       \
00176       if (_swap) for (i=0; i<N; ++i)                            \
00177         reverse_byte_order( tmp[i] );                           \
00178       _os.write( (const char*)&tmp[0], b );                     \
00179       return _os.good() ? b : 0;                                \
00180     }                                                           \
00181                                                                 \
00182     static size_t restore( std::istream& _is, value_type& _val, \
00183                          bool _swap=false) {                    \
00184       size_t i, N=value_type::size_;                            \
00185       size_t b = N * sizeof(value_type::value_type);            \
00186       _is.read( (char*)&_val[0], b );                           \
00187       if (_swap) for (i=0; i<N; ++i)                            \
00188         reverse_byte_order( _val[i] );                          \
00189       return _is.good() ? b : 0;                                \
00190     }                                                           \
00191   }
00192 
00193 #define VECTORTS_BINARY( N ) \
00194    VECTORT_BINARY( Vec##N##c  ); \
00195    VECTORT_BINARY( Vec##N##uc ); \
00196    VECTORT_BINARY( Vec##N##s  ); \
00197    VECTORT_BINARY( Vec##N##us ); \
00198    VECTORT_BINARY( Vec##N##i  ); \
00199    VECTORT_BINARY( Vec##N##ui ); \
00200    VECTORT_BINARY( Vec##N##f  ); \
00201    VECTORT_BINARY( Vec##N##d  );
00202 
00203 VECTORTS_BINARY( 1 );
00204 VECTORTS_BINARY( 2 );
00205 VECTORTS_BINARY( 3 );
00206 VECTORTS_BINARY( 4 );
00207 VECTORTS_BINARY( 6 );
00208 
00209 #undef VECTORTS_BINARY
00210 #undef VECTORT_BINARY
00211 
00212 template <> struct binary< std::string > {
00213   typedef std::string value_type;
00214   typedef uint16_t    length_t;
00215 
00216   static const bool is_streamable = true;
00217 
00218   static size_t size_of() { return UnknownSize; }
00219   static size_t size_of(const value_type &_v)
00220   { return sizeof(length_t) + _v.size(); }
00221 
00222   static
00223   size_t store(std::ostream& _os, const value_type& _v, bool _swap=false)
00224   {
00225 #if defined(OM_CC_GCC) && (OM_CC_VERSION < 30000)
00226     if (_v.size() < Utils::NumLimitsT<length_t>::max() )
00227 #else
00228     if (_v.size() < std::numeric_limits<length_t>::max() )
00229 #endif
00230     {
00231       length_t len = _v.size();
00232 
00233       if (_swap) reverse_byte_order(len);
00234 
00235       size_t bytes = binary<length_t>::store( _os, len, _swap );
00236       _os.write( _v.data(), len );
00237       return _os.good() ? len+bytes : 0;
00238     }
00239     throw std::runtime_error("Cannot store string longer than 64Kb");
00240   }
00241 
00242   static
00243   size_t restore(std::istream& _is, value_type& _val, bool _swap=false)
00244   {
00245     length_t len;
00246     size_t   bytes = binary<length_t>::restore( _is, len, _swap );
00247     if (_swap)
00248       reverse_byte_order(len);
00249     _val.resize(len);
00250     _is.read( const_cast<char*>(_val.data()), len );
00251 
00252     return _is.good() ? (len+bytes) : 0;
00253   }
00254 };
00255 
00256 
00257 template <> struct binary<OpenMesh::Attributes::StatusInfo>
00258 {
00259   typedef OpenMesh::Attributes::StatusInfo value_type;
00260   typedef value_type::value_type           status_t;
00261 
00262   static const bool is_streamable = true;
00263 
00264   static size_t size_of() { return sizeof(status_t); }
00265   static size_t size_of(const value_type&) { return size_of(); }
00266 
00267   static size_t n_bytes(size_t _n_elem)
00268   { return _n_elem*sizeof(status_t); }
00269 
00270   static
00271   size_t store(std::ostream& _os, const value_type& _v, bool _swap=false)
00272   {
00273     status_t v=_v.bits();
00274     return binary<status_t>::store(_os, v, _swap);
00275   }
00276 
00277   static
00278   size_t restore( std::istream& _os, value_type& _v, bool _swap=false)
00279   {
00280     status_t v;
00281     size_t   b = binary<status_t>::restore(_os, v, _swap);
00282     _v.set_bits(v);
00283     return b;
00284   }
00285 };
00286 
00287 
00288 //-----------------------------------------------------------------------------
00289 // std::vector<T> specializations for struct binary<>
00290 
00291 template <typename T>
00292 struct FunctorStore {
00293   FunctorStore( std::ostream& _os, bool _swap) : os_(_os), swap_(_swap) { }
00294   size_t operator () ( size_t _v1, const T& _s2 )
00295   { return _v1+binary<T>::store(os_, _s2, swap_ ); }
00296 
00297   std::ostream& os_;
00298   bool          swap_;
00299 };
00300 
00301 
00302 template <typename T>
00303 struct FunctorRestore {
00304   FunctorRestore( std::istream& _is, bool _swap) : is_(_is), swap_(_swap) { }
00305   size_t operator () ( size_t _v1, T& _s2 )
00306   { return _v1+binary<T>::restore(is_, _s2, swap_ ); }
00307   std::istream& is_;
00308   bool          swap_;
00309 };
00310 
00311 #include <OpenMesh/Core/IO/SR_binary_vector_of_fundamentals.inl>
00312 #include <OpenMesh/Core/IO/SR_binary_vector_of_string.inl>
00313 #include <OpenMesh/Core/IO/SR_binary_vector_of_bool.inl>
00314 
00315 // ----------------------------------------------------------------------------
00316 
00317 #endif // DOXY_IGNORE_THIS
00318 
00319 //=============================================================================
00320 } // namespace IO
00321 } // namespace OpenMesh
00322 //=============================================================================
00323 #endif // OPENMESH_SR_BINARY_SPEC_HH defined
00324 //=============================================================================
00325