DCCL v3
field_codec_default.cpp
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 #include "dccl/codecs3/field_codec_default.h"
23 
24 using namespace dccl::logger;
25 
26 //
27 // DefaultStringCodec
28 //
29 
30 dccl::Bitset dccl::v3::DefaultStringCodec::encode()
31 {
32  return Bitset(min_size());
33 }
34 
35 dccl::Bitset dccl::v3::DefaultStringCodec::encode(const std::string& wire_value)
36 {
37  std::string s = wire_value;
38  if(s.size() > dccl_field_options().max_length())
39  {
40  if(this->strict())
41  throw(dccl::OutOfRangeException(std::string("String too long for field: ") + FieldCodecBase::this_field()->DebugString(), this->this_field()));
42 
43  dccl::dlog.is(DEBUG2) && dccl::dlog << "String " << s << " exceeds `dccl.max_length`, truncating" << std::endl;
44  s.resize(dccl_field_options().max_length());
45  }
46 
47 
48  Bitset value_bits;
49  value_bits.from_byte_string(s);
50 
51  Bitset length_bits(min_size(), s.length());
52 
53  dccl::dlog.is(DEBUG2) && dccl::dlog << "DefaultStringCodec value_bits: " << value_bits << std::endl;
54 
55 
56  dccl::dlog.is(DEBUG2) && dccl::dlog << "DefaultStringCodec length_bits: " << length_bits << std::endl;
57 
58  // adds to MSBs
59  for(int i = 0, n = value_bits.size(); i < n; ++i)
60  length_bits.push_back(value_bits[i]);
61 
62  dccl::dlog.is(DEBUG2) && dccl::dlog << "DefaultStringCodec created: " << length_bits << std::endl;
63 
64 
65  return length_bits;
66 }
67 
68 std::string dccl::v3::DefaultStringCodec::decode(Bitset* bits)
69 {
70  unsigned value_length = bits->to_ulong();
71 
72  if(value_length)
73  {
74 
75  unsigned header_length = min_size();
76 
77  dccl::dlog.is(DEBUG2) && dccl::dlog << "Length of string is = " << value_length << std::endl;
78 
79  dccl::dlog.is(DEBUG2) && dccl::dlog << "bits before get_more_bits " << *bits << std::endl;
80 
81  // grabs more bits to add to the MSBs of `bits`
82  bits->get_more_bits(value_length*BITS_IN_BYTE);
83 
84 
85  dccl::dlog.is(DEBUG2) && dccl::dlog << "bits after get_more_bits " << *bits << std::endl;
86  Bitset string_body_bits = *bits;
87  string_body_bits >>= header_length;
88  string_body_bits.resize(bits->size() - header_length);
89 
90  return string_body_bits.to_byte_string();
91  }
92  else
93  {
94  throw NullValueException();
95  }
96 
97 }
98 
99 unsigned dccl::v3::DefaultStringCodec::size()
100 {
101  return min_size();
102 }
103 
104 unsigned dccl::v3::DefaultStringCodec::size(const std::string& wire_value)
105 {
106  return std::min(min_size() + static_cast<unsigned>(wire_value.length()*BITS_IN_BYTE), max_size());
107 }
108 
109 
110 unsigned dccl::v3::DefaultStringCodec::max_size()
111 {
112  // string length + actual string
113  return min_size() + dccl_field_options().max_length() * BITS_IN_BYTE;
114 }
115 
116 unsigned dccl::v3::DefaultStringCodec::min_size()
117 {
118  return dccl::ceil_log2(dccl_field_options().max_length()+1);
119 }
120 
121 
122 void dccl::v3::DefaultStringCodec::validate()
123 {
124  require(dccl_field_options().has_max_length(), "missing (dccl.field).max_length");
125 }
126 
127 //
128 // DefaultEnumCodec
129 //
130 double dccl::v3::DefaultEnumCodec::max()
131 {
132  const google::protobuf::EnumDescriptor* e = this_field()->enum_type();
133 
134  if (dccl_field_options().packed_enum()) {
135  return e->value_count()-1;
136  } else {
137  const google::protobuf::EnumValueDescriptor* value = e->value(0);
138  int32 maxVal = value->number();
139  for (int i=1; i < e->value_count(); ++i) {
140  value = e->value(i);
141  if (value->number() > maxVal) { maxVal = value->number(); }
142  }
143  return maxVal;
144  }
145 }
146 
147 double dccl::v3::DefaultEnumCodec::min()
148 {
149  if (dccl_field_options().packed_enum()) {
150  return 0;
151  } else {
152  const google::protobuf::EnumDescriptor* e = this_field()->enum_type();
153  const google::protobuf::EnumValueDescriptor* value = e->value(0);
154  int32 minVal = value->number();
155  for (int i=1; i < e->value_count(); ++i) {
156  value = e->value(i);
157  if (value->number() < minVal) { minVal = value->number(); }
158  }
159  return minVal;
160  }
161 }
162 
163 dccl::int32 dccl::v3::DefaultEnumCodec::pre_encode(const google::protobuf::EnumValueDescriptor* const& field_value)
164 {
165  if (dccl_field_options().packed_enum())
166  return field_value->index();
167  else
168  return field_value->number();
169 }
170 
171 const google::protobuf::EnumValueDescriptor* dccl::v3::DefaultEnumCodec::post_decode(const dccl::int32& wire_value)
172 {
173  const google::protobuf::EnumDescriptor* e = this_field()->enum_type();
174 
175  if (dccl_field_options().packed_enum()) {
176  if(wire_value < e->value_count()) {
177  const google::protobuf::EnumValueDescriptor* return_value = e->value(wire_value);
178  return return_value;
179  }
180  else
181  throw NullValueException();
182  } else {
183  const google::protobuf::EnumValueDescriptor* return_value = e->FindValueByNumber(wire_value);
184  if(return_value != NULL)
185  return return_value;
186  else
187  throw NullValueException();
188  }
189 }
const google::protobuf::EnumValueDescriptor * post_decode(const int32 &wire_value)
Convert from the WireType representation (used with encode() and decode(), i.e. "on the wire") to the...
Exception used to signal null (non-existent) value within field codecs during decode.
Definition: exception.h:40
const google::protobuf::FieldDescriptor * this_field() const
Returns the FieldDescriptor (field schema meta-data) for this field.
Definition: field_codec.h:75
int32 pre_encode(const google::protobuf::EnumValueDescriptor *const &field_value)
Convert from the FieldType representation (used in the Google Protobuf message) to the WireType repre...
unsigned ceil_log2(dccl::uint64 v)
Definition: binary.h:180
bool is(logger::Verbosity verbosity, logger::Group group=logger::GENERAL)
Indicates the verbosity of the Logger until the next std::flush or std::endl. The boolean return is u...
Definition: logger.h:145
google::protobuf::int32 int32
a signed 32 bit integer
Definition: common.h:57
A variable size container of bits (subclassed from std::deque<bool>) with an optional hierarchy...
Definition: bitset.h:38