22 #ifndef DCCLFIELDCODEC20110322H
23 #define DCCLFIELDCODEC20110322H
28 #include <boost/any.hpp>
29 #include <boost/lexical_cast.hpp>
31 #include <google/protobuf/message.h>
32 #include <google/protobuf/descriptor.pb.h>
33 #include <google/protobuf/descriptor.h>
36 #include "exception.h"
37 #include "dccl/option_extensions.pb.h"
38 #include "internal/type_helper.h"
39 #include "internal/field_codec_message_stack.h"
40 #include "dccl/binary.h"
59 std::string
name()
const {
return name_; }
64 google::protobuf::FieldDescriptor::Type
field_type()
const {
return field_type_; }
69 google::protobuf::FieldDescriptor::CppType
wire_type()
const {
return wire_type_; }
75 const google::protobuf::FieldDescriptor*
this_field()
const
76 {
return !internal::MessageStack::field_.empty() ? internal::MessageStack::field_.back() : 0; }
92 {
return !internal::MessageStack::desc_.empty() ? internal::MessageStack::desc_.back() : 0; }
96 {
return root_message_; }
98 static bool has_codec_group()
102 return root_descriptor_->options().GetExtension(dccl::msg).has_codec_group() ||
103 root_descriptor_->options().GetExtension(dccl::msg).has_codec_version();
109 static std::string codec_group(
const google::protobuf::Descriptor* desc);
111 static std::string codec_group()
112 {
return codec_group(root_descriptor_); }
114 static int codec_version()
115 {
return root_descriptor_->options().GetExtension(dccl::msg).codec_version(); }
118 static MessagePart
part() {
return part_; }
120 static bool strict() {
return strict_; }
125 force_required_ = force_required;
173 void base_max_size(
unsigned* bit_size,
const google::protobuf::Descriptor* desc, MessagePart
part);
180 void base_min_size(
unsigned* bit_size,
const google::protobuf::Descriptor* desc, MessagePart
part);
193 void base_info(std::ostream* os,
const google::protobuf::Descriptor* desc, MessagePart
part);
220 const std::vector<boost::any>& field_values)
221 { any_pre_encode_repeated(wire_values, field_values); }
231 const boost::any& field_value,
232 const google::protobuf::FieldDescriptor* field);
240 const std::vector<boost::any>& field_values,
241 const google::protobuf::FieldDescriptor* field);
248 void field_size(
unsigned* bit_size,
const boost::any& field_value,
249 const google::protobuf::FieldDescriptor* field);
257 const google::protobuf::FieldDescriptor* field);
266 boost::any* field_value,
267 const google::protobuf::FieldDescriptor* field);
275 std::vector<boost::any>* field_values,
276 const google::protobuf::FieldDescriptor* field);
290 std::vector<boost::any>* field_values)
291 { any_post_decode_repeated(wire_values, field_values); }
300 void field_max_size(
unsigned* bit_size,
const google::protobuf::FieldDescriptor* field);
305 void field_min_size(
unsigned* bit_size,
const google::protobuf::FieldDescriptor* field);
312 void field_validate(
bool* b,
const google::protobuf::FieldDescriptor* field);
318 void field_info(std::ostream* os,
const google::protobuf::FieldDescriptor* field);
329 return this_field()->options().GetExtension(dccl::field);
331 throw(
Exception(
"Cannot call dccl_field on base message (has no *field* option extension"));
340 void require(
bool b,
const std::string& description)
358 const google::protobuf::FieldDescriptor* field =
this_field();
361 else if(codec_version() > 2)
362 return field->is_required() || field->is_repeated();
364 return field->is_required();
390 const boost::any& field_value)
391 { *wire_value = field_value; }
398 boost::any* field_value)
399 { *field_value = wire_value; }
405 virtual unsigned any_size(
const boost::any& wire_value) = 0;
414 virtual std::string
info();
426 virtual void any_encode_repeated(
Bitset* bits,
const std::vector<boost::any>& wire_values);
427 virtual void any_decode_repeated(
Bitset* repeated_bits, std::vector<boost::any>* field_values);
429 virtual void any_pre_encode_repeated(std::vector<boost::any>* wire_values,
430 const std::vector<boost::any>& field_values);
432 virtual void any_post_decode_repeated(
const std::vector<boost::any>& wire_values,
433 std::vector<boost::any>* field_values);
435 virtual unsigned any_size_repeated(
const std::vector<boost::any>& wire_values);
436 virtual unsigned max_size_repeated();
437 virtual unsigned min_size_repeated();
442 void set_name(
const std::string&
name)
444 void set_field_type(google::protobuf::FieldDescriptor::Type type)
445 { field_type_ = type; }
446 void set_wire_type(google::protobuf::FieldDescriptor::CppType type)
447 { wire_type_ = type; }
452 return max_size_repeated() != min_size_repeated();
457 int repeated_vector_field_size(
int max_repeat)
460 void disp_size(
const google::protobuf::FieldDescriptor* field,
const Bitset& new_bits,
int depth,
int vector_size = -1);
468 BaseRAII(MessagePart
part,
469 const google::protobuf::Descriptor* root_descriptor,
472 FieldCodecBase::part_ =
part;
473 FieldCodecBase::strict_ = strict;
474 FieldCodecBase::root_message_ = 0;
475 FieldCodecBase::root_descriptor_ = root_descriptor;
478 BaseRAII(MessagePart
part,
482 FieldCodecBase::part_ =
part;
483 FieldCodecBase::strict_ = strict;
484 FieldCodecBase::root_message_ = root_message;
485 FieldCodecBase::root_descriptor_ = root_message->GetDescriptor();
489 FieldCodecBase::part_ = dccl::UNKNOWN;
490 FieldCodecBase::strict_ =
false;
491 FieldCodecBase::root_message_ = 0;
492 FieldCodecBase::root_descriptor_ = 0;
497 static MessagePart part_;
500 static const google::protobuf::Descriptor* root_descriptor_;
503 google::protobuf::FieldDescriptor::Type field_type_;
504 google::protobuf::FieldDescriptor::CppType wire_type_;
506 bool force_required_;
510 inline std::ostream& operator<<(std::ostream& os,
const FieldCodecBase& field_codec )
512 using google::protobuf::FieldDescriptor;
513 using internal::TypeHelper;
514 return os <<
"[FieldCodec '" << field_codec.name() <<
"']: field type: "
515 << TypeHelper::find(field_codec.field_type())->as_str()
516 <<
" (" << TypeHelper::find(FieldDescriptor::TypeToCppType(field_codec.field_type()))->as_str()
517 <<
") | wire type: " << TypeHelper::find(field_codec.wire_type())->as_str();
520 inline Exception type_error(
const std::string& action,
521 const std::type_info& expected,
522 const std::type_info& got)
524 std::string e =
"error " + action +
", expected: ";
525 e += expected.name();
void base_encode(Bitset *bits, const google::protobuf::Message &msg, MessagePart part, bool strict)
Encode this part (body or head) of the base message.
virtual void any_decode(Bitset *bits, boost::any *wire_value)=0
Virtual method used to decode.
virtual void any_pre_encode(boost::any *wire_value, const boost::any &field_value)
Virtual method used to pre-encode (convert from FieldType to WireType). The default implementation of...
void field_decode_repeated(Bitset *bits, std::vector< boost::any > *field_values, const google::protobuf::FieldDescriptor *field)
Decode a repeated field.
virtual std::string info()
Write field specific information (in addition to general information such as sizes that are automatic...
virtual unsigned min_size()=0
Calculate minimum size of the field in bits.
Provides a base class for defining DCCL field encoders / decoders. Most users who wish to define cust...
virtual unsigned max_size()=0
Calculate maximum size of the field in bits.
const google::protobuf::FieldDescriptor * this_field() const
Returns the FieldDescriptor (field schema meta-data) for this field.
Dynamic Compact Control Language namespace.
Exception class for DCCL.
void field_min_size(unsigned *bit_size, const google::protobuf::FieldDescriptor *field)
Calculate the lower bound on this field's size (in bits)
virtual void any_post_decode(const boost::any &wire_value, boost::any *field_value)
Virtual method used to post-decode (convert from WireType to FieldType). The default implementation o...
void base_min_size(unsigned *bit_size, const google::protobuf::Descriptor *desc, MessagePart part)
Calculate the minimum size of a message given its Descriptor alone (no data)
void field_encode_repeated(Bitset *bits, const std::vector< boost::any > &field_values, const google::protobuf::FieldDescriptor *field)
Encode a repeated field.
void base_max_size(unsigned *bit_size, const google::protobuf::Descriptor *desc, MessagePart part)
Calculate the maximum size of a message given its Descriptor alone (no data)
void require(bool b, const std::string &description)
Essentially an assertion to be used in the validate() virtual method.
void set_force_use_required(bool force_required=true)
Force the codec to always use the "required" field encoding, regardless of the FieldDescriptor settin...
virtual void validate()
Validate a field. Use require() inside your overloaded validate() to assert requirements or throw Exc...
google::protobuf::FieldDescriptor::Type field_type() const
the type exposed to the user in the original and decoded Protobuf messages
unsigned ceil_log2(dccl::uint64 v)
void field_size_repeated(unsigned *bit_size, const std::vector< boost::any > &field_values, const google::protobuf::FieldDescriptor *field)
Calculate the size of a repeated field.
void field_decode(Bitset *bits, boost::any *field_value, const google::protobuf::FieldDescriptor *field)
Decode a non-repeated field.
static const google::protobuf::Descriptor * this_descriptor()
Returns the Descriptor (message schema meta-data) for the immediate parent Message.
void field_post_decode(const boost::any &wire_value, boost::any *field_value)
Post-decodes a non-repeated (i.e. optional or required) field by converting the WireType (the type us...
A variable size container of bits (subclassed from std::deque<bool>) with an optional hierarchy....
void field_encode(Bitset *bits, const boost::any &field_value, const google::protobuf::FieldDescriptor *field)
Encode a non-repeated field.
void field_validate(bool *b, const google::protobuf::FieldDescriptor *field)
Validate this field, checking that all required option extensions are set (e.g. (dccl....
void field_max_size(unsigned *bit_size, const google::protobuf::FieldDescriptor *field)
Calculate the upper bound on this field's size (in bits)
virtual void any_encode(Bitset *bits, const boost::any &wire_value)=0
Virtual method used to encode.
void field_pre_encode_repeated(std::vector< boost::any > *wire_values, const std::vector< boost::any > &field_values)
Pre-encodes a repeated field.
A class for managing the various field codecs. Here you can add and remove field codecs....
void field_post_decode_repeated(const std::vector< boost::any > &wire_values, std::vector< boost::any > *field_values)
Post-decodes a repeated field.
void field_pre_encode(boost::any *wire_value, const boost::any &field_value)
Pre-encodes a non-repeated (i.e. optional or required) field by converting the FieldType representati...
void base_info(std::ostream *os, const google::protobuf::Descriptor *desc, MessagePart part)
Get human readable information (size of fields, etc.) about this part of the DCCL message.
void field_info(std::ostream *os, const google::protobuf::FieldDescriptor *field)
Write human readable information about the field and its bounds to the provided stream.
bool use_required()
Whether to use the required or optional encoding.
static MessagePart part()
the part of the message currently being encoded (head or body).
void base_validate(const google::protobuf::Descriptor *desc, MessagePart part)
Validate this part of the message to make sure all required extensions are set.
void base_size(unsigned *bit_size, const google::protobuf::Message &msg, MessagePart part)
Calculate the size (in bits) of a part of the base message when it is encoded.
void base_decode(Bitset *bits, google::protobuf::Message *msg, MessagePart part)
Decode part of a message.
virtual unsigned any_size(const boost::any &wire_value)=0
Virtual method for calculating the size of a field (in bits).
std::string name() const
the name of the codec used to identifier it in the .proto custom option extension
dccl::DCCLFieldOptions dccl_field_options() const
Get the DCCL field option extension value for the current field.
void field_size(unsigned *bit_size, const boost::any &field_value, const google::protobuf::FieldDescriptor *field)
Calculate the size of a field.
google::protobuf::FieldDescriptor::CppType wire_type() const
the C++ type used "on the wire". This is the type visible after pre_encode and before post_decode fun...