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  dccl::dlog.is(DEBUG2) && dccl::dlog << "String " << s << " exceeds `dccl.max_length`, truncating" << std::endl;
92  s.resize(dccl_field_options().max_length());
93  }
94 
95 
96  Bitset value_bits;
97  value_bits.from_byte_string(s);
98 
99  Bitset length_bits(min_size(), s.length());
100 
101  dccl::dlog.is(DEBUG2) && dccl::dlog << "DefaultStringCodec value_bits: " << value_bits << std::endl;
102 
103 
104  dccl::dlog.is(DEBUG2) && dccl::dlog << "DefaultStringCodec length_bits: " << length_bits << std::endl;
105 
106  // adds to MSBs
107  for(int i = 0, n = value_bits.size(); i < n; ++i)
108  length_bits.push_back(value_bits[i]);
109 
110  dccl::dlog.is(DEBUG2) && dccl::dlog << "DefaultStringCodec created: " << length_bits << std::endl;
111 
112 
113  return length_bits;
114 }
115 
116 std::string dccl::v2::DefaultStringCodec::decode(Bitset* bits)
117 {
118  unsigned value_length = bits->to_ulong();
119 
120  if(value_length)
121  {
122 
123  unsigned header_length = min_size();
124 
125  dccl::dlog.is(DEBUG2) && dccl::dlog << "Length of string is = " << value_length << std::endl;
126 
127  dccl::dlog.is(DEBUG2) && dccl::dlog << "bits before get_more_bits " << *bits << std::endl;
128 
129  // grabs more bits to add to the MSBs of `bits`
130  bits->get_more_bits(value_length*BITS_IN_BYTE);
131 
132 
133  dccl::dlog.is(DEBUG2) && dccl::dlog << "bits after get_more_bits " << *bits << std::endl;
134  Bitset string_body_bits = *bits;
135  string_body_bits >>= header_length;
136  string_body_bits.resize(bits->size() - header_length);
137 
138  return string_body_bits.to_byte_string();
139  }
140  else
141  {
142  throw NullValueException();
143  }
144 
145 }
146 
147 unsigned dccl::v2::DefaultStringCodec::size()
148 {
149  return min_size();
150 }
151 
152 unsigned dccl::v2::DefaultStringCodec::size(const std::string& wire_value)
153 {
154  return std::min(min_size() + static_cast<unsigned>(wire_value.length()*BITS_IN_BYTE), max_size());
155 }
156 
157 
158 unsigned dccl::v2::DefaultStringCodec::max_size()
159 {
160  // string length + actual string
161  return min_size() + dccl_field_options().max_length() * BITS_IN_BYTE;
162 }
163 
164 unsigned dccl::v2::DefaultStringCodec::min_size()
165 {
166  return dccl::ceil_log2(MAX_STRING_LENGTH+1);
167 }
168 
169 
170 void dccl::v2::DefaultStringCodec::validate()
171 {
172  require(dccl_field_options().has_max_length(), "missing (dccl.field).max_length");
173  require(dccl_field_options().max_length() <= MAX_STRING_LENGTH,
174  "(dccl.field).max_length must be <= " + boost::lexical_cast<std::string>(static_cast<int>(MAX_STRING_LENGTH)));
175 }
176 
177 //
178 // DefaultBytesCodec
179 //
180 dccl::Bitset dccl::v2::DefaultBytesCodec::encode()
181 {
182  return Bitset(min_size(), 0);
183 }
184 
185 
186 dccl::Bitset dccl::v2::DefaultBytesCodec::encode(const std::string& wire_value)
187 {
188  Bitset bits;
189  bits.from_byte_string(wire_value);
190  bits.resize(max_size());
191 
192  if(!use_required())
193  {
194  bits <<= 1;
195  bits.set(0, true); // presence bit
196  }
197 
198  return bits;
199 }
200 
201 unsigned dccl::v2::DefaultBytesCodec::size()
202 {
203  return min_size();
204 }
205 
206 
207 unsigned dccl::v2::DefaultBytesCodec::size(const std::string& wire_value)
208 {
209  return max_size();
210 }
211 
212 
213 std::string dccl::v2::DefaultBytesCodec::decode(Bitset* bits)
214 {
215  if(!use_required())
216  {
217  if(bits->to_ulong())
218  {
219  // grabs more bits to add to the MSBs of `bits`
220  bits->get_more_bits(max_size()- min_size());
221 
222  Bitset bytes_body_bits = *bits;
223  bytes_body_bits >>= min_size();
224  bytes_body_bits.resize(bits->size() - min_size());
225 
226  return bytes_body_bits.to_byte_string();
227  }
228  else
229  {
230  throw NullValueException();
231  }
232  }
233  else
234  {
235  return bits->to_byte_string();
236  }
237 }
238 
239 unsigned dccl::v2::DefaultBytesCodec::max_size()
240 {
241  return dccl_field_options().max_length() * BITS_IN_BYTE +
242  (use_required() ? 0 : 1); // presence bit?
243 }
244 
245 unsigned dccl::v2::DefaultBytesCodec::min_size()
246 {
247  if(use_required())
248  return max_size();
249  else
250  return 1; // presence bit
251 }
252 
253 void dccl::v2::DefaultBytesCodec::validate()
254 {
255  require(dccl_field_options().has_max_length(), "missing (dccl.field).max_length");
256 }
257 
258 //
259 // DefaultEnumCodec
260 //
261 dccl::int32 dccl::v2::DefaultEnumCodec::pre_encode(const google::protobuf::EnumValueDescriptor* const& field_value)
262 {
263  return field_value->index();
264 }
265 
266 const google::protobuf::EnumValueDescriptor* dccl::v2::DefaultEnumCodec::post_decode(const dccl::int32& wire_value)
267 {
268  const google::protobuf::EnumDescriptor* e = this_field()->enum_type();
269 
270  if(wire_value < e->value_count())
271  {
272  const google::protobuf::EnumValueDescriptor* return_value = e->value(wire_value);
273  return return_value;
274  }
275  else
276  throw NullValueException();
277 }
278 
279 
280 
Exception used to signal null (non-existent) value within field codecs during decode.
Definition: exception.h:39
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:178
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