iarchive.hpp

00001 /*
00002 This file is part of GraphLab.
00003 
00004 GraphLab is free software: you can redistribute it and/or modify
00005 it under the terms of the GNU Lesser General Public License as 
00006 published by the Free Software Foundation, either version 3 of 
00007 the License, or (at your option) any later version.
00008 
00009 GraphLab 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 Lesser General Public License for more details.
00013 
00014 You should have received a copy of the GNU Lesser General Public 
00015 License along with GraphLab.  If not, see <http://www.gnu.org/licenses/>.
00016 */
00017 
00018 #ifndef GRAPHLAB_SERIALIZE_HPP
00019 #include <graphlab/serialization/serialize.hpp>
00020 
00021 #else
00022 
00023 
00024 #ifndef GRAPHLAB_IARCHIVE_HPP
00025 #define GRAPHLAB_IARCHIVE_HPP
00026 
00027 #include <iostream>
00028 #include <graphlab/logger/assertions.hpp>
00029 #include <graphlab/serialization/is_pod.hpp>
00030 #include <graphlab/serialization/has_load.hpp>
00031 namespace graphlab {
00032 
00033   /**
00034    * The input archive object.
00035    * It is just a simple wrapper around a istream 
00036    */
00037   class iarchive {
00038   public:
00039     std::istream* i;
00040     /// constructor. Takes a generic std::istream object
00041     iarchive(std::istream& is)
00042       :i(&is) { }
00043       
00044     ~iarchive() {}
00045   };
00046 
00047 
00048   /**
00049    * An alternate input archive object. 
00050    * When this object is used to deserialize an object,
00051    * and the object does not support serialization,
00052    * failure will only occur at runtime.
00053    * \see iarchive
00054    */
00055   class iarchive_soft_fail{
00056   public:
00057     std::istream *i;
00058 
00059     iarchive_soft_fail(std::istream &is)
00060       : i(&is) {}
00061 
00062     iarchive_soft_fail(iarchive &iarc):i(iarc.i){}
00063   
00064     ~iarchive_soft_fail() { }
00065   };
00066 
00067 
00068   namespace archive_detail {
00069 
00070     /// called by the regular archive The regular archive will do a hard fail
00071     template <typename ArcType, typename T>
00072     struct deserialize_hard_or_soft_fail {
00073       static void exec(ArcType &i, T& t) {
00074         t.load(i);
00075       }
00076     };
00077 
00078     /// called by the soft fail archive 
00079     template <typename T>
00080     struct deserialize_hard_or_soft_fail<iarchive_soft_fail, T> {
00081       static void exec(iarchive_soft_fail &i, T& t) {
00082         iarchive iarc(*(i.i));
00083         load_or_fail(iarc, t);
00084       }
00085     };
00086 
00087 
00088     /**
00089        Implementation of the deserializer for different types.
00090        This is the catch-all. If it gets here, it must be a non-POD and is a class.
00091        We therefore call the .save function.
00092        Here we pick between the archive types using serialize_hard_or_soft_fail
00093     */
00094     template <typename ArcType, typename T, bool IsPOD>
00095     struct deserialize_impl {
00096       static void exec(ArcType &i, T& t) {
00097         deserialize_hard_or_soft_fail<ArcType, T>::exec(i, t);
00098       }
00099     };
00100 
00101     // catch if type is a POD
00102     template <typename ArcType, typename T>
00103     struct deserialize_impl<ArcType, T, true>{
00104       static void exec(ArcType &a, T &t) {
00105         a.i->read(reinterpret_cast<char*>(&t), sizeof(T));
00106       }
00107     };
00108 
00109   } //namespace archive_detail
00110 
00111   /**
00112      Allows Use of the "stream" syntax for serialization 
00113   */
00114   template <typename T>
00115   iarchive& operator>>(iarchive& a, T &i) {
00116     archive_detail::deserialize_impl<iarchive, T, gl_is_pod<T>::value >::exec(a, i);
00117     return a;
00118   }
00119 
00120 
00121 
00122   /**
00123      Allows Use of the "stream" syntax for serialization 
00124   */
00125   template <typename T>
00126   iarchive_soft_fail& operator>>(iarchive_soft_fail& a, T &i) {
00127     archive_detail::deserialize_impl<iarchive_soft_fail, T, gl_is_pod<T>::value >::exec(a, i);
00128     return a;
00129   }
00130 
00131 
00132   /**
00133      deserializes an arbitrary pointer + length from an archive 
00134   */
00135   inline iarchive& deserialize(iarchive& a, void* const i,const size_t length) {
00136     // Save the length and check if lengths match
00137     size_t length2;
00138     operator>>(a, length2);
00139     ASSERT_EQ(length, length2);
00140 
00141     //operator>> the rest
00142     a.i->read(reinterpret_cast<char*>(i), (std::streamsize)length);
00143     assert(!a.i->fail());
00144     return a;
00145   }
00146 
00147 
00148 
00149   /**
00150      deserializes an arbitrary pointer + length from an archive 
00151   */
00152   inline iarchive_soft_fail& deserialize(iarchive_soft_fail& a, void* const i,const size_t length) {
00153     // Save the length and check if lengths match
00154     size_t length2;
00155     operator>>(a, length2);
00156     ASSERT_EQ(length, length2);
00157 
00158     //operator>> the rest
00159     a.i->read(reinterpret_cast<char*>(i), (std::streamsize)length);
00160     assert(!a.i->fail());
00161     return a;
00162   }
00163 
00164   /**
00165      Macro to make it easy to define out-of-place saves (and loads)
00166      to define an "out of place" load
00167      OUT_OF_PLACE_LOAD(arc, typename, tval) 
00168      arc >> tval;    // do whatever deserialization stuff you need here
00169      END_OUT_OF_PLACE_LOAD()
00170 
00171      \note important! this must be defined in the global namespace!
00172      See unsupported_serialize for an example
00173   */
00174 #define BEGIN_OUT_OF_PLACE_LOAD(arc, tname, tval)                       \
00175   namespace graphlab{ namespace archive_detail {                        \
00176   template <typename ArcType> struct deserialize_impl<ArcType, tname, false>{ \
00177   static void exec(ArcType& arc, tname & tval) {             
00178 
00179 #define END_OUT_OF_PLACE_LOAD() } }; } }
00180 
00181 
00182 
00183 
00184 } // namespace graphlab
00185 
00186 
00187 #endif 
00188 
00189 #endif
00190 
00191 
00192 
00193 
00194 
00195 
00196 
00197