Remote Call Framework 3.1
variant.hpp
1 
2 //******************************************************************************
3 // RCF - Remote Call Framework
4 //
5 // Copyright (c) 2005 - 2019, Delta V Software. All rights reserved.
6 // http://www.deltavsoft.com
7 //
8 // RCF is distributed under dual licenses - closed source or GPL.
9 // Consult your particular license for conditions of use.
10 //
11 // If you have not purchased a commercial license, you are using RCF
12 // under GPL terms.
13 //
14 // Version: 3.1
15 // Contact: support <at> deltavsoft.com
16 //
17 //******************************************************************************
18 
19 #ifndef INCLUDE_SF_VARIANT_HPP
20 #define INCLUDE_SF_VARIANT_HPP
21 
22 #include <boost/variant.hpp>
23 
24 #include <boost/mpl/front.hpp>
25 #include <boost/mpl/pop_front.hpp>
26 #include <boost/mpl/eval_if.hpp>
27 #include <boost/mpl/identity.hpp>
28 #include <boost/mpl/size.hpp>
29 #include <boost/mpl/empty.hpp>
30 
31 namespace SF {
32 
33  class Archive;
34 
35  class VariantSerializer : public boost::static_visitor<>
36  {
37  public:
38  VariantSerializer(SF::Archive &ar) : mAr(ar)
39  {}
40 
41  template<typename T>
42  void operator()(const T &t) const
43  {
44  mAr & t;
45  }
46 
47  private:
48  SF::Archive &mAr;
49  };
50 
51  template<class S>
52  struct VariantDeserializer
53  {
54  struct LoadNull
55  {
56  template<class V>
57  static void invoke(
58  SF::Archive &,
59  int,
60  V &)
61  {}
62  };
63 
64  struct Load
65  {
66  template<class V>
67  static void invoke(
68  SF::Archive & ar,
69  int which,
70  V & v)
71  {
72  using namespace boost::mpl;
73  if (which == 0)
74  {
75  typedef BOOST_DEDUCED_TYPENAME front<S>::type head_type;
76  head_type value;
77  ar & value;
78  v = value;
79  }
80  else
81  {
82  typedef BOOST_DEDUCED_TYPENAME pop_front<S>::type type;
83  VariantDeserializer<type>::load(ar, which - 1, v);
84  }
85  }
86  };
87 
88  template<class V>
89  static void load(
90  SF::Archive & ar,
91  int which,
92  V & v)
93  {
94  using namespace boost::mpl;
95 
96  typedef BOOST_DEDUCED_TYPENAME eval_if<empty<S>,
97  boost::mpl::identity<LoadNull>,
98  boost::mpl::identity<Load>
99  >::type typex;
100 
101  typex::invoke(ar, which, v);
102  }
103 
104  };
105 
106  template< BOOST_VARIANT_ENUM_PARAMS(class T) >
107  void serialize_vc6(
108  SF::Archive & ar,
109  boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) > & v,
110  const unsigned int)
111  {
112  if (ar.isWrite())
113  {
114  ar & int(v.which());
115  VariantSerializer variantSerializer(ar);
116  v.apply_visitor(variantSerializer);
117  }
118  else
119  {
120  int which = 0;
121  ar & which;
122 
123  typedef BOOST_DEDUCED_TYPENAME
124  boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types types;
125 
126  if(which >= boost::mpl::size<types>::value)
127  {
128  RCF::Exception e(
129  RCF::RcfError_VariantDeserialization,
130  which,
131  boost::mpl::size<types>::value);
132 
133  RCF_THROW(e);
134  }
135 
136  VariantDeserializer<types>::load(ar, which, v);
137  }
138  }
139 } // namespace SF
140 
141 #endif // ! INCLUDE_SF_VARIANT_HPP
Represents an archive, in which serialized objects are stored.
Definition: Archive.hpp:32
Base class for all RCF exceptions.
Definition: Exception.hpp:64
Definition: ByteBuffer.hpp:189
bool isWrite() const
Returns true if this archive is being written to.