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
Copyright © 2006-2010 Savarese Software Research Corporation. All rights reserved.
Copyright © 2011 Savarese Software Research Corporation. All rights reserved