• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

Serialization.h

Go to the documentation of this file.
00001 /*
00002  * AbiCollab - Code to enable the modification of remote documents.
00003  * Copyright (C) 2007 by Marc Maurer <uwog@uwog.net>
00004  * Copyright (C) 2007 One Laptop Per Child
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00019  * 02110-1301 USA.
00020  */
00021 
00022 #ifndef ABICOLLAB_SERIALIZATION_H
00023 #define ABICOLLAB_SERIALIZATION_H
00024 
00025 #include <map>
00026 #include <vector>
00027 #include <string>
00028 #include <string.h>
00029 #include <ut_types.h>
00030 #include <ut_string_class.h>
00031 
00032 //
00033 // Quick n' compact serialization implementation
00034 //          by Marc 'Foddex' Oude Kotte (marc@solcon.nl)
00035 //
00036 
00037 // POD type traits
00038 #define DEFINE_POD_OPERATOR_ONE(T)                  \
00039     Archive& operator<<( T& Val )                   \
00040     {                                               \
00041         Serialize( &Val, sizeof(T) );               \
00042         return *this;                               \
00043     }
00044 #define DEFINE_POD_OPERATOR_VECTOR(T)               \
00045     Archive& operator<<( std::vector<T>& Val )      \
00046     {                                               \
00047         unsigned int count;                         \
00048         if (isLoading()) {                          \
00049             *this << COMPACT_INT(count);            \
00050             Val.resize( count );                    \
00051         } else {                                    \
00052             count = Val.size();                     \
00053             *this << COMPACT_INT(count);            \
00054         }                                           \
00055         Serialize( &Val[0], count*sizeof(T) );      \
00056         return *this;                               \
00057     }
00058 
00059 #define DEFINE_POD_OPERATOR(T)                      \
00060     DEFINE_POD_OPERATOR_ONE(T)                      \
00061     DEFINE_POD_OPERATOR_VECTOR(T)
00062 
00063 class Archive;
00064 
00072 #define COMPACT_INT(v) (*(CompactInt*)&v)
00073 struct  CompactInt {
00074 public:
00075     friend Archive& operator<<( Archive& ar, CompactInt& c );
00076 protected:
00077     int Val;
00078 };
00079 
00081 class Archive
00082 {
00083 public:
00084     virtual ~Archive() {}
00085     bool isLoading() const { return m_bLoading; }
00086     bool isSaving() const { return !m_bLoading; }
00087     virtual void Serialize( void* Buffer, unsigned int Count ) = 0;
00088     virtual unsigned int Size() const = 0;
00089     virtual void Skip( unsigned int Count ) = 0;
00090     virtual bool EndOfFile() const = 0;
00091 protected:
00092     Archive( bool bLoading )
00093     : m_bLoading( bLoading )
00094     {}
00095 private:
00096     bool    m_bLoading;
00097 
00098 public:
00099     // pod types
00100     DEFINE_POD_OPERATOR(unsigned char);
00101     DEFINE_POD_OPERATOR(unsigned short);
00102     DEFINE_POD_OPERATOR(unsigned int);
00103     DEFINE_POD_OPERATOR(UT_uint64);
00104     DEFINE_POD_OPERATOR(char);
00105     DEFINE_POD_OPERATOR(short);
00106     DEFINE_POD_OPERATOR(int);
00107     DEFINE_POD_OPERATOR(float);
00108     DEFINE_POD_OPERATOR(double);
00109     DEFINE_POD_OPERATOR_ONE(bool);
00110 
00111     // basic string
00112     Archive& operator<<( std::string& Val )
00113     {
00114         unsigned int s; // NOTE: not size_t's !!
00115         if (isLoading()) {
00116             // get size, resize, and then get characters
00117             *this << COMPACT_INT(s);
00118             Val.resize( s );
00119         } else {
00120             // save size & then characters
00121             s = Val.size();
00122             *this << COMPACT_INT(s);
00123         }
00124         Serialize( &Val[0], s );
00125         return *this;
00126     }
00127 #if !defined(SERIALIZATION_TEST)
00128     // UT_UTF8String
00129     Archive& operator<<( UT_UTF8String& Val )
00130     {
00131         // easy, but not really the most efficient implementation :-)
00132         if (isLoading()) {
00133             std::string s;
00134             *this << s;
00135             Val = UT_UTF8String( s.c_str() );
00136         } else {
00137             std::string s = Val.utf8_str();
00138             *this << s;
00139         }
00140         return *this;
00141     }
00142 #endif
00143     // Default, expects it's an object and will attempt to call serialize on it.
00144     // If compilation fails here, write a custom operator for the type you're trying
00145     // to serialize, or add a serialize member to your class.
00146     template<typename _T>
00147     Archive& operator<<( _T& Val )
00148     {
00149         Val.serialize( *this );
00150         return *this;
00151     }
00152 #if !defined(SERIALIZATION_TEST)
00153     // Vector serialization (note: there are optimized version of this
00154     // for the various POD types)
00155     template<typename _K>
00156     Archive& operator<<( std::vector<_K>& Val )
00157     {
00158         unsigned int count;
00159         if (isLoading()) {
00160             *this << count;
00161             Val.resize( count );
00162         } else {
00163             count = Val.size();
00164             *this << count;
00165         }
00166         for (unsigned int i=0; i<count; ++i) {
00167             *this << Val[i];
00168         }
00169         return *this;
00170     }
00171     // Map serialization
00172     template<typename _K, typename _V>
00173     Archive& operator<<( std::map<_K,_V>& Val )
00174     {
00175         unsigned int count;
00176         if (isLoading())
00177         {
00178             Val.clear();
00179             *this << count;
00180             for (unsigned int i=0; i<count; ++i)
00181             {
00182                 _K k;
00183                 _V v;
00184                 *this << k << v;
00185                 Val.insert( typename std::map<_K,_V>::value_type( k, v ) );
00186             }
00187         }
00188         else
00189         {
00190             count = Val.size();
00191             *this << count;
00192             for (typename std::map<_K,_V>::iterator it=Val.begin(); it!=Val.end(); ++it) {
00193                 *this << (_K&)(*it).first << (_V&)(*it).second;
00194             }
00195         }
00196         return *this;
00197     }
00198 #endif
00199 };
00200 
00202 class StrArchive : public Archive
00203 {
00204 public:
00205     unsigned int Size() const { return m_sSource.size(); }
00206     const std::string& getData() const { return m_sSource; }
00207 protected:
00208     StrArchive()
00209     : Archive( false )
00210     {}
00211     StrArchive( const std::string& sSource )
00212     : Archive( true )
00213     , m_sSource( sSource )
00214     {}
00215     std::string         m_sSource;
00216 };
00217 
00219 class IStrArchive : public StrArchive
00220 {
00221 public:
00222     IStrArchive( const std::string& sSource )
00223     : StrArchive( sSource )
00224     , m_uPosition( 0 )
00225     {}
00226     virtual void Serialize( void* Buffer, unsigned int Count )
00227     {
00228 #if !defined(SERIALIZATION_TEST)
00229         UT_ASSERT( m_uPosition + Count <= m_sSource.size() );   // check if we're overshooting!
00230 #endif
00231         memcpy( Buffer, &m_sSource[m_uPosition], Count );
00232         m_uPosition += Count;
00233     }
00234     virtual void Skip( unsigned int Count )
00235     {
00236 #if !defined(SERIALIZATION_TEST)
00237         UT_ASSERT( m_uPosition + Count <= m_sSource.size() );   // check if we're overshooting!
00238 #endif
00239         m_uPosition += Count;
00240     }
00241     virtual bool EndOfFile() const
00242     {
00243         return m_uPosition >= m_sSource.size();
00244     }
00245 protected:
00246     unsigned int                m_uPosition;
00247 };
00248 
00250 class OStrArchive : public StrArchive
00251 {
00252 public:
00253     OStrArchive()
00254     : StrArchive()
00255     {}
00256     virtual void Serialize( void* Buffer, unsigned int Count )
00257     {
00258         unsigned int pos = m_sSource.size();
00259         m_sSource.resize( pos + Count );
00260         memcpy( &m_sSource[pos], Buffer, Count );
00261     }
00262     virtual void Skip( unsigned int /*Count*/ )
00263     {
00264 #if !defined(SERIALIZATION_TEST)
00265         UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
00266 #endif
00267     }
00268     virtual bool EndOfFile() const
00269     {
00270         return true;    // writing file is always at EOF ;)
00271     }
00272 };
00273 
00274 #endif /* ABICOLLAB_SERIALIZATION_H */

Generated on Sun Feb 14 2021 for AbiWord by  doxygen 1.7.1