22 #include <boost/algorithm/string.hpp>
24 #include "field_codec.h"
25 #include "exception.h"
26 #include "dccl/codec.h"
28 dccl::MessagePart dccl::FieldCodecBase::part_ =
31 bool dccl::FieldCodecBase::strict_ =
false;
34 const google::protobuf::Descriptor* dccl::FieldCodecBase::root_descriptor_ = 0;
37 using namespace dccl::logger;
42 dccl::FieldCodecBase::FieldCodecBase() : force_required_(false) { }
49 BaseRAII scoped_globals(part, &field_value, strict);
54 internal::TypeHelper::find(field_value.GetDescriptor())->get_value(field_value),
60 const boost::any& field_value,
61 const google::protobuf::FieldDescriptor* field)
66 dlog.
is(DEBUG2, ENCODE) && dlog <<
"Starting encode for field: " << field->DebugString() << std::flush;
68 boost::any wire_value;
69 field_pre_encode(&wire_value, field_value);
72 any_encode(&new_bits, wire_value);
73 disp_size(field, new_bits, msg_handler.field_.size());
78 const std::vector<boost::any>& field_values,
79 const google::protobuf::FieldDescriptor* field)
83 std::vector<boost::any> wire_values;
84 field_pre_encode_repeated(&wire_values, field_values);
87 any_encode_repeated(&new_bits, wire_values);
88 disp_size(field, new_bits, msg_handler.field_.size(), wire_values.size());
97 BaseRAII scoped_globals(part, &msg);
101 field_size(bit_size, &msg, 0);
106 const boost::any& field_value,
107 const google::protobuf::FieldDescriptor* field)
111 boost::any wire_value;
112 field_pre_encode(&wire_value, field_value);
114 *bit_size += any_size(wire_value);
118 const std::vector<boost::any>& field_values,
119 const google::protobuf::FieldDescriptor* field)
123 std::vector<boost::any> wire_values;
124 field_pre_encode_repeated(&wire_values, field_values);
126 *bit_size += any_size_repeated(wire_values);
136 BaseRAII scoped_globals(part, field_value);
137 boost::any value(field_value);
138 field_decode(bits, &value, 0);
143 boost::any* field_value,
144 const google::protobuf::FieldDescriptor* field)
149 throw(
Exception(
"Decode called with NULL boost::any"));
151 throw(
Exception(
"Decode called with NULL Bitset"));
154 dlog.
is(DEBUG2, DECODE) && dlog <<
"Starting decode for field: " << field->DebugString() << std::flush;
157 dlog.
is(DEBUG3, DECODE) && dlog <<
"Message thus far is: " << root_message()->DebugString() << std::flush;
161 unsigned bits_to_transfer = 0;
162 field_min_size(&bits_to_transfer, field);
165 dlog.
is(DEBUG2, DECODE) && dlog <<
"... using these bits: " << these_bits << std::endl;
167 boost::any wire_value = *field_value;
169 any_decode(&these_bits, &wire_value);
171 field_post_decode(wire_value, field_value);
175 std::vector<boost::any>* field_values,
176 const google::protobuf::FieldDescriptor* field)
181 throw(
Exception(
"Decode called with NULL field_values"));
183 throw(
Exception(
"Decode called with NULL Bitset"));
186 dlog.
is(DEBUG2, DECODE) && dlog <<
"Starting repeated decode for field: " << field->DebugString();
190 unsigned bits_to_transfer = 0;
191 field_min_size(&bits_to_transfer, field);
194 dlog.
is(DEBUG2, DECODE) && dlog <<
"using these " <<
195 these_bits.size() <<
" bits: " << these_bits << std::endl;
197 std::vector<boost::any> wire_values = *field_values;
198 any_decode_repeated(&these_bits, &wire_values);
200 field_values->clear();
201 field_post_decode_repeated(wire_values, field_values);
206 const google::protobuf::Descriptor* desc,
209 BaseRAII scoped_globals(part, desc);
214 msg_handler.push(desc);
216 throw(
Exception(
"Max Size called with NULL Descriptor"));
218 field_max_size(bit_size,
static_cast<google::protobuf::FieldDescriptor*
>(0));
222 const google::protobuf::FieldDescriptor* field)
227 *bit_size += this_field()->is_repeated() ? max_size_repeated() : max_size();
229 *bit_size += max_size();
235 const google::protobuf::Descriptor* desc,
238 BaseRAII scoped_globals(part, desc);
244 msg_handler.push(desc);
246 throw(
Exception(
"Min Size called with NULL Descriptor"));
248 field_min_size(bit_size,
static_cast<google::protobuf::FieldDescriptor*
>(0));
252 const google::protobuf::FieldDescriptor* field)
258 *bit_size += this_field()->is_repeated() ? min_size_repeated() : min_size();
260 *bit_size += min_size();
267 BaseRAII scoped_globals(part, desc);
271 msg_handler.push(desc);
273 throw(
Exception(
"Validate called with NULL Descriptor"));
276 field_validate(&b,
static_cast<google::protobuf::FieldDescriptor*
>(0));
281 const google::protobuf::FieldDescriptor* field)
285 if(field && dccl_field_options().in_head() && variable_size())
286 throw(
Exception(
"Variable size codec used in header - header fields must be encoded with fixed size codec."));
293 BaseRAII scoped_globals(part, desc);
297 msg_handler.push(desc);
299 throw(
Exception(
"info called with NULL Descriptor"));
301 field_info(os,
static_cast<google::protobuf::FieldDescriptor*
>(0));
306 const google::protobuf::FieldDescriptor* field)
311 std::stringstream ss;
312 int depth = msg_handler.count();
314 std::string name = ((this_field()) ? boost::lexical_cast<std::string>(this_field()->number()) +
". " + this_field()->name() : this_descriptor()->full_name());
315 if(this_field() && this_field()->is_repeated())
316 name +=
"[" + boost::lexical_cast<std::string>(dccl_field_options().max_repeat()) +
"]";
319 if(!this_field() || this_field()->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE)
322 const int spaces = 8;
323 std::string indent = std::string(spaces*(depth),
' ');
325 const int full_width = 40;
327 bool is_zero_size =
false;
329 std::stringstream range;
332 unsigned max_sz = 0, min_sz = 0;
333 field_max_size(&max_sz, field);
334 field_min_size(&min_sz, field);
335 if(!max_sz) is_zero_size =
true;
336 range << min_sz <<
"-" << max_sz;
341 field_max_size(&sz, field);
342 if(!sz) is_zero_size =
true;
346 int width = this_field() ? full_width-name.size() : full_width-name.size()+spaces;
347 ss << indent << name <<
348 std::setfill(
'.') << std::setw(std::max(1, width)) << range.str()
359 *os << ss.str() <<
"\n";
361 std::string specific_info = info();
362 if(!specific_info.empty())
363 *os << specific_info;
367 std::string dccl::FieldCodecBase::codec_group(
const google::protobuf::Descriptor* desc)
369 if(desc->options().GetExtension(dccl::msg).has_codec_group())
370 return desc->options().GetExtension(dccl::msg).codec_group();
372 return Codec::default_codec_name(desc->options().GetExtension(dccl::msg).codec_version());
382 return std::string();
385 void dccl::FieldCodecBase::any_encode_repeated(
dccl::Bitset* bits,
const std::vector<boost::any>& wire_values)
389 unsigned wire_vector_size = dccl_field_options().max_repeat();
391 if(wire_values.size() > wire_vector_size)
395 if(codec_version() > 2)
397 wire_vector_size = std::min((
int)dccl_field_options().max_repeat(), (
int)wire_values.size());
398 Bitset size_bits(repeated_vector_field_size(dccl_field_options().max_repeat()), wire_values.size());
402 for(
unsigned i = 0, n = wire_vector_size; i < n; ++i)
405 if(i < wire_values.size())
406 any_encode(&new_bits, wire_values[i]);
408 any_encode(&new_bits, boost::any());
416 void dccl::FieldCodecBase::any_decode_repeated(Bitset* repeated_bits, std::vector<boost::any>* wire_values)
419 unsigned wire_vector_size = dccl_field_options().max_repeat();
420 if(codec_version() > 2)
422 Bitset size_bits(repeated_bits);
423 size_bits.get_more_bits(repeated_vector_field_size(dccl_field_options().max_repeat()));
425 wire_vector_size = size_bits.to_ulong();
428 wire_values->resize(wire_vector_size);
430 for(
unsigned i = 0, n = wire_vector_size; i < n; ++i)
432 Bitset these_bits(repeated_bits);
433 these_bits.get_more_bits(min_size());
434 any_decode(&these_bits, &(*wire_values)[i]);
438 unsigned dccl::FieldCodecBase::any_size_repeated(
const std::vector<boost::any>& wire_values)
441 unsigned wire_vector_size = dccl_field_options().max_repeat();
443 if(codec_version() > 2)
445 wire_vector_size = std::min((
int)dccl_field_options().max_repeat(), (
int)wire_values.size());
446 out += repeated_vector_field_size(dccl_field_options().max_repeat());
449 for(
unsigned i = 0, n = wire_vector_size; i < n; ++i)
451 if(i < wire_values.size())
452 out += any_size(wire_values[i]);
454 out += any_size(boost::any());
459 unsigned dccl::FieldCodecBase::max_size_repeated()
461 if(!dccl_field_options().has_max_repeat())
462 throw(Exception(
"Missing (dccl.field).max_repeat option on `repeated` field: " + this_field()->DebugString()));
463 else if(codec_version() > 2)
464 return repeated_vector_field_size(dccl_field_options().max_repeat()) + max_size() * dccl_field_options().max_repeat();
466 return max_size() * dccl_field_options().max_repeat();
469 unsigned dccl::FieldCodecBase::min_size_repeated()
471 if(!dccl_field_options().has_max_repeat())
472 throw(Exception(
"Missing (dccl.field).max_repeat option on `repeated` field " + this_field()->DebugString()));
473 else if(codec_version() > 2)
474 return repeated_vector_field_size(dccl_field_options().max_repeat());
476 return min_size() * dccl_field_options().max_repeat();
479 void dccl::FieldCodecBase::any_pre_encode_repeated(std::vector<boost::any>* wire_values,
const std::vector<boost::any>& field_values)
481 for(std::vector<boost::any>::const_iterator it = field_values.begin(),
482 end = field_values.end(); it != end; ++it)
484 boost::any wire_value;
485 any_pre_encode(&wire_value, *it);
486 wire_values->push_back(wire_value);
490 void dccl::FieldCodecBase::any_post_decode_repeated(
491 const std::vector<boost::any>& wire_values, std::vector<boost::any>* field_values)
493 for(std::vector<boost::any>::const_iterator it = wire_values.begin(),
494 end = wire_values.end(); it != end; ++it)
496 boost::any field_value;
497 any_post_decode(*it, &field_value);
498 field_values->push_back(field_value);
507 void dccl::FieldCodecBase::disp_size(
const google::protobuf::FieldDescriptor* field,
const Bitset& new_bits,
int depth,
int vector_size )
509 if(!root_descriptor_)
512 if(dlog.
is(DEBUG2, SIZE))
514 std::string name = ((field) ? field->name() : root_descriptor_->full_name());
516 name +=
"[" + boost::lexical_cast<std::string>(vector_size) +
"]";
519 dlog << std::string(depth,
'|') << name << std::setfill(
'.') << std::setw(40-name.size()-depth) << new_bits.size() << std::endl;