DCCL v3
field_codec_default_message.h
1 // Copyright 2009-2017 Toby Schneider (http://gobysoft.org/index.wt/people/toby)
2 // GobySoft, LLC (for 2013-)
3 // Massachusetts Institute of Technology (for 2007-2014)
4 // Community contributors (see AUTHORS file)
5 //
6 //
7 // This file is part of the Dynamic Compact Control Language Library
8 // ("DCCL").
9 //
10 // DCCL is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 2.1 of the License, or
13 // (at your option) any later version.
14 //
15 // DCCL is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with DCCL. If not, see <http://www.gnu.org/licenses/>.
22 #ifndef DCCLFIELDCODECDEFAULTMESSAGEV320140421H
23 #define DCCLFIELDCODECDEFAULTMESSAGEV320140421H
24 
25 #include "dccl/field_codec.h"
26 #include "dccl/field_codec_manager.h"
27 
28 #include "dccl/option_extensions.pb.h"
29 
30 namespace dccl
31 {
32  namespace v3
33  {
36  {
37  private:
38 
39  void any_encode(Bitset* bits, const boost::any& wire_value);
40  void any_decode(Bitset* bits, boost::any* wire_value);
41  unsigned max_size();
42  unsigned min_size();
43  unsigned any_size(const boost::any& wire_value);
44 
45 
46  boost::shared_ptr<FieldCodecBase> find(const google::protobuf::FieldDescriptor* field_desc)
47  {
48  return FieldCodecManager::find(field_desc, has_codec_group(), codec_group());
49  }
50 
51  bool is_optional()
52  { return this_field() && this_field()->is_optional(); }
53 
54 
55  void validate();
56  std::string info();
57  bool check_field(const google::protobuf::FieldDescriptor* field);
58 
59  struct Size
60  {
61  static void repeated(boost::shared_ptr<FieldCodecBase> codec,
62  unsigned* return_value,
63  const std::vector<boost::any>& field_values,
64  const google::protobuf::FieldDescriptor* field_desc)
65  {
66  codec->field_size_repeated(return_value, field_values, field_desc);
67  }
68 
69  static void single(boost::shared_ptr<FieldCodecBase> codec,
70  unsigned* return_value,
71  const boost::any& field_value,
72  const google::protobuf::FieldDescriptor* field_desc)
73  {
74  codec->field_size(return_value, field_value, field_desc);
75  }
76 
77  };
78 
79  struct Encoder
80  {
81  static void repeated(boost::shared_ptr<FieldCodecBase> codec,
82  Bitset* return_value,
83  const std::vector<boost::any>& field_values,
84  const google::protobuf::FieldDescriptor* field_desc)
85  {
86  codec->field_encode_repeated(return_value, field_values, field_desc);
87  }
88 
89  static void single(boost::shared_ptr<FieldCodecBase> codec,
90  Bitset* return_value,
91  const boost::any& field_value,
92  const google::protobuf::FieldDescriptor* field_desc)
93  {
94  codec->field_encode(return_value, field_value, field_desc);
95  }
96  };
97 
98  struct MaxSize
99  {
100  static void field(boost::shared_ptr<FieldCodecBase> codec,
101  unsigned* return_value,
102  const google::protobuf::FieldDescriptor* field_desc)
103  {
104  codec->field_max_size(return_value, field_desc);
105  }
106  };
107 
108  struct MinSize
109  {
110  static void field(boost::shared_ptr<FieldCodecBase> codec,
111  unsigned* return_value,
112  const google::protobuf::FieldDescriptor* field_desc)
113  {
114  codec->field_min_size(return_value, field_desc);
115  }
116  };
117 
118 
119  struct Validate
120  {
121  static void field(boost::shared_ptr<FieldCodecBase> codec,
122  bool* return_value,
123  const google::protobuf::FieldDescriptor* field_desc)
124  {
125  codec->field_validate(return_value, field_desc);
126  }
127  };
128 
129  struct Info
130  {
131  static void field(boost::shared_ptr<FieldCodecBase> codec,
132  std::stringstream* return_value,
133  const google::protobuf::FieldDescriptor* field_desc)
134  {
135  codec->field_info(return_value, field_desc);
136  }
137  };
138 
139 
140  template<typename Action, typename ReturnType>
141  void traverse_descriptor(ReturnType* return_value)
142  {
143  const google::protobuf::Descriptor* desc =
145 
146  for(int i = 0, n = desc->field_count(); i < n; ++i)
147  {
148  const google::protobuf::FieldDescriptor* field_desc = desc->field(i);
149 
150  if(!check_field(field_desc))
151  continue;
152 
153  Action::field(find(field_desc), return_value, field_desc);
154  }
155  }
156 
157 
158  template<typename Action, typename ReturnType>
159  ReturnType traverse_const_message(const boost::any& wire_value)
160  {
161  try
162  {
163  ReturnType return_value = ReturnType();
164 
165  const google::protobuf::Message* msg = boost::any_cast<const google::protobuf::Message*>(wire_value);
166  const google::protobuf::Descriptor* desc = msg->GetDescriptor();
167  const google::protobuf::Reflection* refl = msg->GetReflection();
168  for(int i = 0, n = desc->field_count(); i < n; ++i)
169  {
170  const google::protobuf::FieldDescriptor* field_desc = desc->field(i);
171 
172  if(!check_field(field_desc))
173  continue;
174 
175  boost::shared_ptr<FieldCodecBase> codec = find(field_desc);
176  boost::shared_ptr<internal::FromProtoCppTypeBase> helper =
177  internal::TypeHelper::find(field_desc);
178 
179 
180  if(field_desc->is_repeated())
181  {
182  std::vector<boost::any> field_values;
183  for(int j = 0, m = refl->FieldSize(*msg, field_desc); j < m; ++j)
184  field_values.push_back(helper->get_repeated_value(field_desc, *msg, j));
185 
186  Action::repeated(codec, &return_value, field_values, field_desc);
187  }
188  else
189  {
190  Action::single(codec, &return_value, helper->get_value(field_desc, *msg), field_desc);
191  }
192  }
193  return return_value;
194  }
195  catch(boost::bad_any_cast& e)
196  {
197  throw(Exception("Bad type given to traverse const, expecting const google::protobuf::Message*, got " + std::string(wire_value.type().name())));
198  }
199 
200  }
201  };
202 
203  }
204 }
205 
206 //encode, size, etc.
207 
208 
209 
210 
211 #endif
dccl::FieldCodecBase
Provides a base class for defining DCCL field encoders / decoders. Most users who wish to define cust...
Definition: field_codec.h:47
dccl::FieldCodecBase::this_field
const google::protobuf::FieldDescriptor * this_field() const
Returns the FieldDescriptor (field schema meta-data) for this field.
Definition: field_codec.h:75
dccl
Dynamic Compact Control Language namespace.
Definition: gen_units_class_plugin.h:49
dccl::Exception
Exception class for DCCL.
Definition: exception.h:31
dccl::FieldCodecBase::this_descriptor
static const google::protobuf::Descriptor * this_descriptor()
Returns the Descriptor (message schema meta-data) for the immediate parent Message.
Definition: field_codec.h:91
dccl::Bitset
A variable size container of bits (subclassed from std::deque<bool>) with an optional hierarchy....
Definition: bitset.h:38
dccl::FieldCodecManager::find
static boost::shared_ptr< FieldCodecBase > find(const google::protobuf::FieldDescriptor *field, bool has_codec_group, const std::string &codec_group)
Find the codec for a given field. For embedded messages, prefers (dccl.field).codec (inside field) ov...
Definition: field_codec_manager.h:121
Message
dccl::v3::DefaultMessageCodec
Provides the default codec for encoding a base Google Protobuf message or an embedded message by call...
Definition: field_codec_default_message.h:35