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 <sstream>
23 #include <algorithm>
24 
25 #include "dccl/codecs2/field_codec_default.h"
26 #include "dccl/codec.h"
27 
28 using namespace dccl::logger;
29 
30 
31 //
32 // DefaultBoolCodec
33 //
34 
35 dccl::Bitset dccl::v2::DefaultBoolCodec::encode()
36 {
37  return Bitset(size());
38 }
39 
40 dccl::Bitset dccl::v2::DefaultBoolCodec::encode(const bool& wire_value)
41 {
42  return Bitset(size(), use_required() ? wire_value : wire_value + 1);
43 }
44 
45 bool dccl::v2::DefaultBoolCodec::decode(Bitset* bits)
46 {
47  unsigned long t = bits->to_ulong();
48  if(use_required())
49  {
50  return t;
51  }
52  else if(t)
53  {
54  --t;
55  return t;
56  }
57  else
58  {
59  throw NullValueException();
60  }
61 }
62 
63 
64 unsigned dccl::v2::DefaultBoolCodec::size()
65 {
66  // true and false
67  const unsigned BOOL_VALUES = 2;
68  // if field unspecified
69  const unsigned NULL_VALUE = use_required() ? 0 : 1;
70 
71  return dccl::ceil_log2(BOOL_VALUES + NULL_VALUE);
72 }
73 
74 void dccl::v2::DefaultBoolCodec::validate()
75 { }
76 
77 //
78 // DefaultStringCodec
79 //
80 
81 dccl::Bitset dccl::v2::DefaultStringCodec::encode()
82 {
83  return Bitset(min_size());
84 }
85 
86 dccl::Bitset dccl::v2::DefaultStringCodec::encode(const std::string& wire_value)
87 {
88  std::string s = wire_value;
89  if(s.size() > dccl_field_options().max_length())
90  {
91  if(this->strict())
92  throw(dccl::OutOfRangeException(std::string("String too long for field: ") + FieldCodecBase::this_field()->DebugString(), this->this_field()));
93 
94  dccl::dlog.is(DEBUG2) && dccl::dlog << "String " << s << " exceeds `dccl.max_length`, truncating" << std::endl;
95  s.resize(dccl_field_options().max_length());
96  }
97 
98 
99  Bitset value_bits;
100  value_bits.from_byte_string(s);
101 
102  Bitset length_bits(min_size(), s.length());
103 
104  dccl::dlog.is(DEBUG2) && dccl::dlog << "DefaultStringCodec value_bits: " << value_bits << std::endl;
105 
106 
107  dccl::dlog.is(DEBUG2) && dccl::dlog << "DefaultStringCodec length_bits: " << length_bits << std::endl;
108 
109  // adds to MSBs
110  for(int i = 0, n = value_bits.size(); i < n; ++i)
111  length_bits.push_back(value_bits[i]);
112 
113  dccl::dlog.is(DEBUG2) && dccl::dlog << "DefaultStringCodec created: " << length_bits << std::endl;
114 
115 
116  return length_bits;
117 }
118 
119 std::string dccl::v2::DefaultStringCodec::decode(Bitset* bits)
120 {
121  unsigned value_length = bits->to_ulong();
122 
123  if(value_length)
124  {
125 
126  unsigned header_length = min_size();
127 
128  dccl::dlog.is(DEBUG2) && dccl::dlog << "Length of string is = " << value_length << std::endl;
129 
130  dccl::dlog.is(DEBUG2) && dccl::dlog << "bits before get_more_bits " << *bits << std::endl;
131 
132  // grabs more bits to add to the MSBs of `bits`
133  bits->get_more_bits(value_length*BITS_IN_BYTE);
134 
135 
136  dccl::dlog.is(DEBUG2) && dccl::dlog << "bits after get_more_bits " << *bits << std::endl;
137  Bitset string_body_bits = *bits;
138  string_body_bits >>= header_length;
139  string_body_bits.resize(bits->size() - header_length);
140 
141  return string_body_bits.to_byte_string();
142  }
143  else
144  {
145  throw NullValueException();
146  }
147 
148 }
149 
150 unsigned dccl::v2::DefaultStringCodec::size()
151 {
152  return min_size();
153 }
154 
155 unsigned dccl::v2::DefaultStringCodec::size(const std::string& wire_value)
156 {
157  return std::min(min_size() + static_cast<unsigned>(wire_value.length()*BITS_IN_BYTE), max_size());
158 }
159 
160 
161 unsigned dccl::v2::DefaultStringCodec::max_size()
162 {
163  // string length + actual string
164  return min_size() + dccl_field_options().max_length() * BITS_IN_BYTE;
165 }
166 
167 unsigned dccl::v2::DefaultStringCodec::min_size()
168 {
169  return dccl::ceil_log2(MAX_STRING_LENGTH+1);
170 }
171 
172 
173 void dccl::v2::DefaultStringCodec::validate()
174 {
175  require(dccl_field_options().has_max_length(), "missing (dccl.field).max_length");
176  require(dccl_field_options().max_length() <= MAX_STRING_LENGTH,
177  "(dccl.field).max_length must be <= " + boost::lexical_cast<std::string>(static_cast<int>(MAX_STRING_LENGTH)));
178 }
179 
180 //
181 // DefaultBytesCodec
182 //
183 dccl::Bitset dccl::v2::DefaultBytesCodec::encode()
184 {
185  return Bitset(min_size(), 0);
186 }
187 
188 
189 dccl::Bitset dccl::v2::DefaultBytesCodec::encode(const std::string& wire_value)
190 {
191  Bitset bits;
192  bits.from_byte_string(wire_value);
193 
194  if(bits.size() > max_size() && this->strict())
195  throw(dccl::OutOfRangeException(std::string("Bytes too long for field: ") + FieldCodecBase::this_field()->DebugString(), this->this_field()));
196 
197  bits.resize(max_size());
198 
199  if(!use_required())
200  {
201  bits <<= 1;
202  bits.set(0, true); // presence bit
203  }
204 
205  return bits;
206 }
207 
208 unsigned dccl::v2::DefaultBytesCodec::size()
209 {
210  return min_size();
211 }
212 
213 
214 unsigned dccl::v2::DefaultBytesCodec::size(const std::string& wire_value)
215 {
216  return max_size();
217 }
218 
219 
220 std::string dccl::v2::DefaultBytesCodec::decode(Bitset* bits)
221 {
222  if(!use_required())
223  {
224  if(bits->to_ulong())
225  {
226  // grabs more bits to add to the MSBs of `bits`
227  bits->get_more_bits(max_size()- min_size());
228 
229  Bitset bytes_body_bits = *bits;
230  bytes_body_bits >>= min_size();
231  bytes_body_bits.resize(bits->size() - min_size());
232 
233  return bytes_body_bits.to_byte_string();
234  }
235  else
236  {
237  throw NullValueException();
238  }
239  }
240  else
241  {
242  return bits->to_byte_string();
243  }
244 }
245 
246 unsigned dccl::v2::DefaultBytesCodec::max_size()
247 {
248  return dccl_field_options().max_length() * BITS_IN_BYTE +
249  (use_required() ? 0 : 1); // presence bit?
250 }
251 
252 unsigned dccl::v2::DefaultBytesCodec::min_size()
253 {
254  if(use_required())
255  return max_size();
256  else
257  return 1; // presence bit
258 }
259 
260 void dccl::v2::DefaultBytesCodec::validate()
261 {
262  require(dccl_field_options().has_max_length(), "missing (dccl.field).max_length");
263 }
264 
265 //
266 // DefaultEnumCodec
267 //
268 dccl::int32 dccl::v2::DefaultEnumCodec::pre_encode(const google::protobuf::EnumValueDescriptor* const& field_value)
269 {
270  return field_value->index();
271 }
272 
273 const google::protobuf::EnumValueDescriptor* dccl::v2::DefaultEnumCodec::post_decode(const dccl::int32& wire_value)
274 {
275  const google::protobuf::EnumDescriptor* e = this_field()->enum_type();
276 
277  if(wire_value < e->value_count())
278  {
279  const google::protobuf::EnumValueDescriptor* return_value = e->value(wire_value);
280  return return_value;
281  }
282  else
283  throw NullValueException();
284 }
285 
286 
287 
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
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...
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
void from_byte_string(const std::string &s)
Sets the value of the Bitset to the contents of a byte string, where each character represents 8 bits...
Definition: bitset.h:348
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