Savarese Software Research Corporation
serialization.h
Go to the documentation of this file.
1 /* Copyright 2006-2008 Savarese Software Research Corporation
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.savarese.com/software/ApacheLicense-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
21 #ifndef __SSRC_WISP_SERIALIZATION_H
22 #define __SSRC_WISP_SERIALIZATION_H
23 
24 #include <ssrc/wisp-packages.h>
25 #include <ssrc/spread/detail/ByteBuffer.h>
26 
27 #include <utility>
28 
29 #include <boost/iostreams/stream.hpp>
30 #include <boost/iostreams/device/array.hpp>
31 
32 #include <boost/archive/binary_iarchive.hpp>
33 #include <boost/archive/binary_oarchive.hpp>
34 
35 #include <boost/serialization/split_free.hpp>
36 #include <boost/serialization/binary_object.hpp>
37 
43 #define __BEGIN_BOOST_SERIALIZATION \
44 namespace boost { \
45  namespace serialization {
46 
51 #define __END_BOOST_SERIALIZATION \
52  } \
53 }
54 
56 
57 using NS_SSRC_SPREAD::detail::ByteBuffer;
58 
59 namespace detail {
67  template<typename Ch, typename mode_type = boost::iostreams::seekable>
69  public:
70  typedef Ch char_type;
71  typedef std::pair<char_type*, char_type*> pair_type;
72 
73  struct category :
74  public mode_type,
77  { };
78 
79  private:
80  char_type *_begin, *_end;
81 
82  public:
83 
84  array_device_adapter() : _begin(0), _end(0) { }
85 
86  array_device_adapter(char_type* begin, char_type* end) :
87  _begin(begin), _end(end)
88  { }
89 
90  array_device_adapter(char_type* begin, std::size_t size) :
91  _begin(begin), _end(begin + size)
92  { }
93 
94  void init(char_type* begin, char_type* end) {
95  _begin = begin;
96  _end = end;
97  }
98 
99  void init(char_type* begin, std::size_t size) {
100  _begin = begin;
101  _end = begin + size;
102  }
103 
104  void set_size(std::size_t size) {
105  _end = _begin + size;
106  }
107 
108  pair_type input_sequence() {
109  return pair_type(_begin, _end);
110  }
111 
112  pair_type output_sequence() {
113  return pair_type(_begin, _end);
114  }
115  };
116 
119 
120  // This class is an unfortunately required workaround for a change
121  // and possible bug in Boost 1.42.0 which causes stream_buffer::open to
122  // throw an "already open" exception even if the buffer has been closed.
123  template<typename DeviceAdapter>
125  public boost::iostreams::stream_buffer<DeviceAdapter>
126  {
128  typedef
129  boost::iostreams::detail::direct_streambuf<DeviceAdapter,
130  typename super::traits_type>
132 
133  void open(const DeviceAdapter & device_adapter) {
134  direct_streambuf::open(device_adapter, 0, 0);
135  }
136  };
137 
140 }
141 
149 template<typename Archive>
150 class Packer {
151 public:
154  typedef Archive output_archive;
155 
156 protected:
157  sink_type _sink;
158  sink_buffer _out_buf;
159 
160 public:
161 
180  template<typename T>
181  unsigned int pack(const T & obj, ByteBuffer & buffer,
182  const unsigned int archive_flags =
183  boost::archive::no_header | boost::archive::no_codecvt |
184  boost::archive::no_tracking)
185  SSRC_DECL_THROW(boost::archive::archive_exception, std::ios_base::failure)
186  {
187  unsigned int offset, bytes_written;
188 
189  _sink.init(&buffer[0], buffer.capacity());
190  _out_buf.open(_sink);
191  _out_buf.pubseekoff(buffer.offset(), std::basic_ios<sink_buffer>::beg);
192 
193  output_archive out_ar(_out_buf, archive_flags);
194  out_ar << obj;
195 
196  offset = _out_buf.pubseekoff(0, std::basic_ios<sink_buffer>::cur);
197  bytes_written = offset - buffer.offset();
198  buffer.resize(offset);
199  buffer.seek(offset);
200 
201  return bytes_written;
202  }
203 };
204 
213 template<typename Archive>
214 class Unpacker {
215 public:
218  typedef Archive input_archive;
219 
220 protected:
221  source_type _source;
222  source_buffer _in_buf;
223 
224 public:
225 
241  template<typename T>
242  unsigned int unpack(T & obj, ByteBuffer & buffer,
243  const unsigned int archive_flags =
244  boost::archive::no_header | boost::archive::no_codecvt |
245  boost::archive::no_tracking)
246  SSRC_DECL_THROW(boost::archive::archive_exception, std::ios_base::failure)
247  {
248  unsigned int bytes_read(0);
249 
250  if(buffer.size() > 0) {
251  unsigned int offset;
252 
253  _source.init(&buffer[0], buffer.size());
254  _in_buf.open(_source);
255  _in_buf.pubseekoff(buffer.offset(), std::basic_ios<source_buffer>::beg);
256 
257  input_archive in_ar(_in_buf, archive_flags);
258  in_ar >> obj;
259 
260  offset = _in_buf.pubseekoff(0, std::basic_ios<source_buffer>::cur);
261  bytes_read = offset - buffer.offset();
262  buffer.seek(offset);
263  }
264 
265  return bytes_read;
266  }
267 
268 
283  template<typename T>
284  unsigned int unpack(T & obj, const void *buffer, unsigned int size,
285  const unsigned int archive_flags =
286  boost::archive::no_header | boost::archive::no_codecvt |
287  boost::archive::no_tracking)
288  SSRC_DECL_THROW(boost::archive::archive_exception, std::ios_base::failure)
289  {
290  unsigned int bytes_read(0);
291 
292  if(size > 0) {
293  _source.init(static_cast<typename detail::char_array_source::char_type *>(const_cast<void *>(buffer)), size);
294  _in_buf.open(_source);
295  _in_buf.pubseekoff(0, std::basic_ios<source_buffer>::beg);
296 
297  input_archive in_ar(_in_buf, archive_flags);
298  in_ar >> obj;
299 
300  bytes_read = _in_buf.pubseekoff(0, std::basic_ios<source_buffer>::cur);
301  }
302 
303  return bytes_read;
304  }
305 };
306 
307 template<typename P, typename U>
308 struct PackingTraits {
309  typedef P packer_type;
310  typedef U unpacker_type;
311 };
312 
316 
318 
320 
321 template<class Archive>
322 inline
323 void save_construct_data(Archive & ar,
324  const NS_SSRC_SPREAD::detail::ByteBuffer *buffer,
325  const unsigned int)
326 {
327  // Could use capacity, but lets keep it as small as we can.
328  ar << buffer->size();
329 }
330 
331 template<class Archive>
332 inline
333 void load_construct_data(Archive & ar,
334  NS_SSRC_SPREAD::detail::ByteBuffer *buffer,
335  const unsigned int)
336 {
337  unsigned int capacity;
338 
339  ar >> capacity;
340  ::new(buffer)NS_SSRC_SPREAD::detail::ByteBuffer(capacity);
341 }
342 
343 template<class Archive>
344 inline void save(Archive & ar,
345  const NS_SSRC_SPREAD::detail::ByteBuffer & buffer,
346  const unsigned int)
347 {
348  unsigned int size = buffer.size();
349 
350  ar & size;
351 
352  if(size > 0) {
353  const binary_object obj(&buffer[0], size);
354  unsigned int offset = buffer.offset();
355  ar & offset & obj;
356  }
357 }
358 
359 template<class Archive>
360 inline void load(Archive & ar,
361  NS_SSRC_SPREAD::detail::ByteBuffer & buffer,
362  const unsigned int)
363 {
364  unsigned int size;
365 
366  ar & size;
367 
368  buffer.resize(size);
369 
370  if(size > 0) {
371  binary_object obj(&buffer[0], size);
372  unsigned int offset;
373  ar & offset & obj;
374  buffer.seek(offset);
375  } else
376  buffer.rewind();
377 }
378 
380 
381 BOOST_SERIALIZATION_SPLIT_FREE(NS_SSRC_SPREAD::detail::ByteBuffer)
382 
383 #endif

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