Savarese Software Research Corporation
serialization.h
Go to the documentation of this file.
00001 /*
00002  * Copyright 2006-2008 Savarese Software Research Corporation
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.savarese.com/software/ApacheLicense-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00022 #ifndef __SSRC_WISP_SERIALIZATION_H
00023 #define __SSRC_WISP_SERIALIZATION_H
00024 
00025 #include <ssrc/wisp-packages.h>
00026 #include <ssrc/spread/detail/ByteBuffer.h>
00027 
00028 #include <utility>
00029 
00030 #include <boost/iostreams/stream.hpp>
00031 #include <boost/iostreams/device/array.hpp>
00032 
00033 #include <boost/archive/binary_iarchive.hpp>
00034 #include <boost/archive/binary_oarchive.hpp>
00035 
00036 #include <boost/serialization/split_free.hpp>
00037 #include <boost/serialization/binary_object.hpp>
00038 
00044 #define __BEGIN_BOOST_SERIALIZATION \
00045 namespace boost { \
00046   namespace serialization { 
00047 
00052 #define __END_BOOST_SERIALIZATION \
00053   } \
00054 }
00055 
00056 __BEGIN_NS_SSRC_WISP
00057 
00058 using NS_SSRC_SPREAD::detail::ByteBuffer;
00059 
00060 namespace detail {
00068   template<typename Ch, typename mode_type = boost::iostreams::seekable>
00069   class array_device_adapter {
00070   public:
00071     typedef Ch char_type;
00072     typedef std::pair<char_type*, char_type*>  pair_type;
00073 
00074     struct category :
00075       public mode_type,
00076       public boost::iostreams::device_tag,
00077       public boost::iostreams::direct_tag
00078     { };
00079 
00080   private:
00081     char_type *_begin, *_end;
00082 
00083   public:
00084 
00085     array_device_adapter() : _begin(0), _end(0) { }
00086 
00087     array_device_adapter(char_type* begin, char_type* end) :
00088       _begin(begin), _end(end)
00089     { }
00090 
00091     array_device_adapter(char_type* begin, std::size_t size) :
00092       _begin(begin), _end(begin + size)
00093     { }
00094 
00095     void init(char_type* begin, char_type* end) {
00096       _begin = begin;
00097       _end   = end;
00098     }
00099 
00100     void init(char_type* begin, std::size_t size) {
00101       _begin = begin;
00102       _end   = begin + size;
00103     }
00104 
00105     void set_size(std::size_t size) {
00106       _end = _begin + size;
00107     }
00108 
00109     pair_type input_sequence() {
00110       return pair_type(_begin, _end);
00111     }
00112 
00113     pair_type output_sequence() {
00114       return pair_type(_begin, _end);
00115     }
00116   };
00117 
00118   typedef array_device_adapter<char> char_array_source;
00119   typedef array_device_adapter<char> char_array_sink;
00120 
00121   // This class is an unfortunately required workaround for a change
00122   // and possible bug in Boost 1.42.0 which causes stream_buffer::open to
00123   // throw an "already open" exception even if the buffer has been closed.
00124   template<typename DeviceAdapter>
00125   struct char_array_streambuf :
00126     public boost::iostreams::stream_buffer<DeviceAdapter>
00127   {
00128     typedef boost::iostreams::stream_buffer<DeviceAdapter> super;
00129     typedef
00130     boost::iostreams::detail::direct_streambuf<DeviceAdapter,
00131                                                typename super::traits_type>
00132     direct_streambuf;
00133 
00134     void open(const DeviceAdapter & device_adapter) {
00135       direct_streambuf::open(device_adapter, 0, 0);
00136     }
00137   };
00138 
00139   typedef char_array_streambuf<char_array_source> char_array_source_buffer;
00140   typedef char_array_streambuf<char_array_sink> char_array_sink_buffer;
00141 }
00142 
00150 template<typename Archive>
00151 class Packer {
00152 public:
00153   typedef detail::char_array_sink sink_type; 
00154   typedef detail::char_array_sink_buffer sink_buffer;
00155   typedef Archive output_archive;
00156 
00157 protected:
00158   sink_type _sink;
00159   sink_buffer _out_buf;
00160 
00161 public:
00162 
00181   template<typename T>
00182   unsigned int pack(const T & obj, ByteBuffer & buffer,
00183                     const unsigned int archive_flags =
00184                     boost::archive::no_header | boost::archive::no_codecvt |
00185                     boost::archive::no_tracking)
00186     SSRC_DECL_THROW(boost::archive::archive_exception, std::ios_base::failure)
00187   {
00188     unsigned int offset, bytes_written;
00189 
00190     _sink.init(&buffer[0], buffer.capacity());
00191     _out_buf.open(_sink);
00192     _out_buf.pubseekoff(buffer.offset(), std::basic_ios<sink_buffer>::beg);
00193 
00194     output_archive out_ar(_out_buf, archive_flags);
00195     out_ar << obj;
00196 
00197     offset = _out_buf.pubseekoff(0, std::basic_ios<sink_buffer>::cur);
00198     bytes_written = offset - buffer.offset();
00199     buffer.resize(offset);
00200     buffer.seek(offset);
00201 
00202     return bytes_written;
00203   }
00204 };
00205 
00214 template<typename Archive>
00215 class Unpacker {
00216 public:
00217   typedef detail::char_array_source source_type; 
00218   typedef detail::char_array_sink_buffer source_buffer;
00219   typedef Archive input_archive;
00220 
00221 protected:
00222   source_type _source;
00223   source_buffer _in_buf;
00224 
00225 public:
00226 
00242   template<typename T>
00243   unsigned int unpack(T & obj, ByteBuffer & buffer,
00244                       const unsigned int archive_flags =
00245                       boost::archive::no_header | boost::archive::no_codecvt |
00246                       boost::archive::no_tracking)
00247     SSRC_DECL_THROW(boost::archive::archive_exception, std::ios_base::failure)
00248   {
00249     unsigned int bytes_read(0);
00250 
00251     if(buffer.size() > 0) {
00252       unsigned int offset;
00253 
00254       _source.init(&buffer[0], buffer.size());
00255       _in_buf.open(_source);
00256       _in_buf.pubseekoff(buffer.offset(), std::basic_ios<source_buffer>::beg);
00257 
00258       input_archive in_ar(_in_buf, archive_flags);
00259       in_ar >> obj;
00260 
00261       offset = _in_buf.pubseekoff(0, std::basic_ios<source_buffer>::cur);
00262       bytes_read = offset - buffer.offset();
00263       buffer.seek(offset);
00264     }
00265 
00266     return bytes_read;
00267   }
00268 
00269 
00284   template<typename T>
00285   unsigned int unpack(T & obj, const void *buffer, unsigned int size,
00286                       const unsigned int archive_flags =
00287                       boost::archive::no_header | boost::archive::no_codecvt |
00288                       boost::archive::no_tracking)
00289     SSRC_DECL_THROW(boost::archive::archive_exception, std::ios_base::failure)
00290   {
00291     unsigned int bytes_read(0);
00292 
00293     if(size > 0) {
00294       _source.init(static_cast<typename detail::char_array_source::char_type *>(const_cast<void *>(buffer)), size);
00295       _in_buf.open(_source);
00296       _in_buf.pubseekoff(0, std::basic_ios<source_buffer>::beg);
00297 
00298       input_archive in_ar(_in_buf, archive_flags);
00299       in_ar >> obj;
00300 
00301       bytes_read = _in_buf.pubseekoff(0, std::basic_ios<source_buffer>::cur);
00302     }
00303 
00304     return bytes_read;
00305   }
00306 };
00307 
00308 template<typename P, typename U>
00309 struct PackingTraits {
00310   typedef P packer_type;
00311   typedef U unpacker_type;
00312 };
00313 
00314 typedef Packer<boost::archive::binary_oarchive> BinaryPacker;
00315 typedef Unpacker<boost::archive::binary_iarchive> BinaryUnpacker;
00316 typedef PackingTraits<BinaryPacker, BinaryUnpacker> BinaryPackingTraits;
00317 
00318 __END_NS_SSRC_WISP
00319 
00320 __BEGIN_BOOST_SERIALIZATION
00321 
00322 template<class Archive>
00323 inline
00324 void save_construct_data(Archive & ar,
00325                          const NS_SSRC_SPREAD::detail::ByteBuffer *buffer,
00326                          const unsigned int)
00327 {
00328   // Could use capacity, but lets keep it as small as we can.
00329   ar << buffer->size();
00330 }
00331 
00332 template<class Archive>
00333 inline
00334 void load_construct_data(Archive & ar,
00335                          NS_SSRC_SPREAD::detail::ByteBuffer *buffer,
00336                          const unsigned int)
00337 {
00338   unsigned int capacity;
00339 
00340   ar >> capacity;
00341   ::new(buffer)NS_SSRC_SPREAD::detail::ByteBuffer(capacity);
00342 }
00343 
00344 template<class Archive>
00345 inline void save(Archive & ar,
00346                  const NS_SSRC_SPREAD::detail::ByteBuffer & buffer,
00347                  const unsigned int)
00348 {
00349   unsigned int size = buffer.size();
00350 
00351   ar & size;
00352 
00353   if(size > 0) {
00354     const binary_object obj(&buffer[0], size);
00355     unsigned int offset = buffer.offset();
00356     ar & offset & obj;
00357   }
00358 }
00359 
00360 template<class Archive>
00361 inline void load(Archive & ar,
00362                  NS_SSRC_SPREAD::detail::ByteBuffer & buffer,
00363                  const unsigned int)
00364 {
00365   unsigned int size;
00366 
00367   ar & size;
00368 
00369   buffer.resize(size);
00370 
00371   if(size > 0) {
00372     binary_object obj(&buffer[0], size);
00373     unsigned int offset;
00374     ar & offset & obj;
00375     buffer.seek(offset);
00376   } else
00377     buffer.rewind();
00378 }
00379 
00380 __END_BOOST_SERIALIZATION
00381 
00382 BOOST_SERIALIZATION_SPLIT_FREE(NS_SSRC_SPREAD::detail::ByteBuffer)
00383 
00384 #endif

Savarese Software Research Corporation
Copyright © 2006-2010 Savarese Software Research Corporation. All rights reserved.