Swarm-NG  1.1
binarystream.hpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005 by Mario Juric *
3  * mjuric@astro.Princeton.EDU *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
20 
26 /*
27  * This file has been copied/modified from Mario Juric's libpeyton.
28  */
29 
30 #ifndef binarystream_h__
31 #define binarystream_h__
32 
33 #define HAVE_BOOST_IOSTREAMS
34 #ifdef HAVE_BOOST_IOSTREAMS
35 
36 #include <iostream>
37 #include <algorithm>
38 #include <vector>
39 
40 #include "util.hpp"
41 
42 #include <boost/type_traits.hpp>
43 
44 namespace peyton {
45 namespace io {
46 
48  template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
51 
52  template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
55 
56  template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
59 
60 }
61 }
62 
66 namespace std
67 {
69  template<typename T, typename A> class vector;
70  template<typename T, typename A> class deque;
71  template<typename T, typename A> class list;
72 
74  template<typename T, typename C, typename A> class set;
75  template<typename T, typename C, typename A> class multiset;
76  template<typename K, typename V, typename C, typename A> class map;
77  template<typename K, typename V, typename C, typename A> class multimap;
78 
80  template<typename T> class valarray;
81 }
82 
86 namespace boost
87 {
89  template <typename First, typename Second>
90  class is_pod< ::std::pair<First, Second> > :
91  public ::boost::integral_constant<bool,
92  is_pod<First>::value && is_pod<Second>::value
93  >
94  {};
95 }
96 
100 namespace peyton {
101 namespace io {
103  namespace binary
104  {
107  {
108  std::string name;
109  int type_size;
110  bool ispod;
111 
112  datatype_info(const std::string &_name, int _type_size, bool _ispod)
113  : name(_name), type_size(_type_size), ispod(_ispod)
114  {}
115  datatype_info(const datatype_info& di)
116  : name(di.name), type_size(di.type_size), ispod(di.ispod)
117  {}
118  };
120  inline bool operator<(const datatype_info& a, const datatype_info& b) { return a.name < b.name; }
122  inline bool operator==(const datatype_info& a, const datatype_info& b) { return a.name == b.name; }
124  inline std::ostream &operator<<(std::ostream &out, const datatype_info &di);
125 
126  typedef std::vector<datatype_info> manifest_t;
127  extern manifest_t manifest;
128  extern bool track_manifest;
129 
131  std::ostream &operator<<(std::ostream &out, const manifest_t &manifest);
132 
140  template<typename T>
141  inline void add_to_manifest()
142  {
143  static bool passed = false;
144  if(track_manifest && !passed)
145  {
146  std::string tname = peyton::util::type_name<T>();
147  typedef typename ::boost::is_pod<T> pod;
148 
149  // 'T' and 'const T' map to same datatype name, so check if T
150  // is already in the vector
151  datatype_info dti(tname, sizeof(T), pod::value);
152  if(std::find(manifest.begin(), manifest.end(), dti) == manifest.end())
153  {
154  manifest.push_back(dti);
155  }
156 
157  if(!pod::value)
158  {
159  std::cerr << "WARNING: Binary I/O as POD for type '" << peyton::util::type_name<T>() << "'\n";
160  }
161 
162  passed = true;
163  }
164  }
165  } // namespace binary
166 
169  #define BLESS_POD(T) \
170  namespace boost { \
171  template <> \
172  class is_pod<T> : public true_type \
173  {}; \
174  }
175 
176 
177 
178 
180  template<typename _CharT, typename _Traits>
181  class basic_obstream : public std::basic_ostream<_CharT, _Traits>
182  {
183  protected:
184 // explicit basic_obstream() : std::basic_ostream<_CharT, _Traits>() {}
185  public:
186  template<typename X>
187  basic_obstream& write_pod(const X* v, size_t n)
188  {
189  binary::add_to_manifest<X>();
190  this->write(reinterpret_cast<const char *>(v), n*sizeof(X));
191  return *this;
192  }
193  public:
194  explicit basic_obstream(std::basic_streambuf<_CharT, _Traits> *sb)
195  : std::basic_ostream<_CharT, _Traits>(sb)
196  { }
197  explicit basic_obstream(std::basic_ostream<_CharT, _Traits> &out)
198  : std::basic_ostream<_CharT, _Traits>(out.rdbuf())
199  { }
200  };
201 
203  template<typename _CharT, typename _Traits>
204  class basic_ibstream : public std::basic_istream<_CharT, _Traits>
205  {
206  protected:
207  explicit basic_ibstream() : std::basic_istream<_CharT, _Traits>() {}
208  public:
209  template<typename X>
210  basic_ibstream& read_pod(X* v, size_t n)
211  {
212  binary::add_to_manifest<X>();
213  this->read((char *)(v), n*sizeof(X));
214  return *this;
215  }
216  public:
217  explicit basic_ibstream(std::basic_streambuf<_CharT, _Traits> *sb)
218  : std::basic_istream<_CharT, _Traits>(sb)
219  { }
220  explicit basic_ibstream(std::basic_istream<_CharT, _Traits> &in)
221  : std::basic_istream<_CharT, _Traits>(in.rdbuf())
222  { }
223  };
224 
226  template<typename _CharT, typename _Traits>
227  class basic_bstream :
228  public basic_obstream<_CharT, _Traits>,
229  public basic_ibstream<_CharT, _Traits>
230  {
231  public:
232  explicit basic_bstream(std::basic_streambuf<_CharT, _Traits> *sb)
233  : basic_obstream<_CharT, _Traits>(sb),
234  basic_ibstream<_CharT, _Traits>(sb)
235  {
236  //this->init(sb);
237  }
238  explicit basic_bstream(std::basic_iostream<_CharT, _Traits> &io)
239  : basic_obstream<_CharT, _Traits>(io.rdbuf()),
240  basic_ibstream<_CharT, _Traits>(io.rdbuf())
241  {
242  //this->init(io.rdbuf());
243  }
244  };
245 
246 
247 
248 
252 
253 #ifdef _MSC_VER
254  #define BOSTREAM2(...) peyton::io::obstream& operator<<(peyton::io::obstream &out, __VA_ARGS__)
255  #define BISTREAM2(...) peyton::io::ibstream& operator>>(peyton::io::ibstream &in, __VA_ARGS__)
256 #else
257  #define BOSTREAM2(T...) peyton::io::obstream& operator<<(peyton::io::obstream &out, T)
258  #define BISTREAM2(T...) peyton::io::ibstream& operator>>(peyton::io::ibstream &in, T)
259 #endif
260 
264 
265  template<typename T>
266  inline BOSTREAM2(const T &v)
267  {
268  return out.write_pod(&v, 1);
269  }
270 
271  template<typename T>
272  inline BISTREAM2(T &v)
273  {
274  return in.read_pod(&v, 1);
275  }
276 
281 
282  #define RETFAIL(x) if(!(x)) return in;
283 
284  template<>
285  inline BOSTREAM2(char* const& v)
286  {
287  size_t len = strlen(v);
288  out << len;
289  return out.write_pod(v, len);
290  }
291 
293  template<>
294  inline BOSTREAM2(std::string const& v)
295  {
296  out << v.size();
297  return out.write_pod(v.c_str(), v.size());
298  }
299 
301  template<>
302  inline BISTREAM2(std::string &v)
303  {
304  size_t len;
305  RETFAIL(in >> len);
306 
307  // FIXME: stack overflow likely
308  char *buf = (char*)alloca(len+1);
309  buf[len] = 0;
310  RETFAIL(in.read_pod(buf, len));
311 
312  v = buf;
313 
314  return in;
315  }
316 
317  namespace details
318  {
319  template <typename IT>
320  inline obstream& itwrite(obstream &out, unsigned int size, IT start, const ::boost::false_type&)
321  {
322  for(IT i = start; size != 0; --size, ++i) { out << *i; }
323  return out;
324  }
325 
326  template <typename IT>
327  inline obstream& itwrite(obstream &out, unsigned int size, IT start, const ::boost::true_type&)
328  {
329  return out.write_pod(start, size);
330  }
331  }
332 
339  template <typename IT>
340  inline obstream& itwrite(obstream &out, unsigned int size, IT start)
341  {
342  out << size;
343 
344  // Dispatching to an optimized version, if we're dealing with an
345  // array of POD-like types.
346  // NOTE: we assume that iterators which are pointers do not have
347  // overloaded * and ++ operators. If they do, this code will malfunction.
348  typedef ::boost::is_pointer<IT> is_simple;
349  typedef ::boost::is_pod<typename std::iterator_traits<IT>::value_type> is_podd;
350  typedef ::boost::integral_constant<bool,
351  is_simple::value && is_podd::value
352  > is_optimizable;
353 
354  return details::itwrite(out, size, start, is_optimizable());
355  }
356 
360  template <typename C>
361  inline ibstream& itread(ibstream &in, C &a)
362  {
363  unsigned int size;
364  RETFAIL(in >> size);
365 
366  a.clear();
367 
368  typename C::value_type tmp;
369  while(size--)
370  {
371  RETFAIL(in >> tmp);
372  a.insert(a.end(), tmp);
373  }
374  return in;
375  }
376 
380  template <typename C>
381  inline ibstream& itreadvec(ibstream &in, C &a)
382  {
383  unsigned int size;
384  RETFAIL(in >> size);
385  a.resize(size);
386 
387  typedef ::boost::is_pod<typename C::value_type> is_podd;
388  if(is_podd::value)
389  {
390  in.read_pod(&a[0], size);
391  }
392  else
393  {
394  for(int i = 0; i != size; ++i) { in >> a[i]; }
395  }
396  return in;
397  }
398 
402  template <typename C>
403  inline ibstream& itreadmap(ibstream &in, C &a)
404  {
405  unsigned int size;
406  RETFAIL(in >> size);
407 
408  a.clear();
409 
410  typename C::key_type key;
411  while(size--)
412  {
413  RETFAIL(in >> key);
414  RETFAIL(in >> a[key]);
415  }
416  return in;
417  }
418 
419  #undef RETFAIL
420 
424 
425  template<typename First, typename Second> // std::pair<First, Second>
426  inline BOSTREAM2(const std::pair<First, Second> &v) { return out << v.first << v.second; }
427 
428  template <typename T, typename A>
429  inline BOSTREAM2(const std::vector<T, A> &a) { return itwrite(out, a.size(), &a[0]); }
430  template <typename T, typename A>
431  inline BOSTREAM2(const std::deque<T, A> &a) { return itwrite(out, a.size(), a.begin()); }
432  template <typename T, typename A>
433  inline BOSTREAM2(const std::list<T, A> &a) { return itwrite(out, a.size(), a.begin()); }
434 
435  template <typename T, typename C, typename A>
436  inline BOSTREAM2(const std::set<T, C, A> &a) { return itwrite(out, a.size(), a.begin()); }
437  template <typename T, typename C, typename A>
438  inline BOSTREAM2(const std::multiset<T, C, A> &a) { return itwrite(out, a.size(), a.begin()); }
439 
440  template <typename K, typename V, typename C, typename A>
441  inline BOSTREAM2(const std::map<K, V, C, A> &a) { return itwrite(out, a.size(), a.begin()); }
442  template <typename K, typename V, typename C, typename A>
443  inline BOSTREAM2(const std::multimap<K, V, C, A> &a) { return itwrite(out, a.size(), a.begin()); }
444 
445  template <typename T>
446  inline BOSTREAM2(const std::valarray<T> &a) { return itwrite(out, a.size(), &a[0]); }
447 
448 
449 
450 
451  template<typename First, typename Second> // std::pair<First, Second>
452  inline BISTREAM2(std::pair<First, Second> &v) { return in >> v.first >> v.second; }
453 
454  template <typename T, typename A>
455  inline BISTREAM2(std::vector<T, A> &a) { return itreadvec(in, a); }
456  template <typename T, typename A>
457  inline BISTREAM2(std::deque<T, A> &a) { return itread(in, a); }
458  template <typename T, typename A>
459  inline BISTREAM2(std::list<T, A> &a) { return itread(in, a); }
460 
461  template <typename T, typename C, typename A>
462  inline BISTREAM2(std::set<T, C, A> &a) { return itread(in, a); }
463  template <typename T, typename C, typename A>
464  inline BISTREAM2(std::multiset<T, C, A> &a) { return itread(in, a); }
465 
466  template <typename K, typename V, typename C, typename A>
467  inline BISTREAM2(std::map<K, V, C, A> &a) { return itreadmap(in, a); }
468  template <typename K, typename V, typename C, typename A>
469  inline BISTREAM2(std::multimap<K, V, C, A> &a) { return itreadmap(in, a); }
470 
471  template <typename T>
472  inline BISTREAM2(std::valarray<T> &a) { return itreadvec(in, a); }
473 
474 } // namespace io
475 } // namespace peyton
476 
477 #endif // HAVE_BOOST_IOSTREAMS
478 
479 using namespace peyton::io;
480 
481 #endif // binarystream_h__