DCCL v4
field_codec_default.cpp
1 // Copyright 2014-2023:
2 // GobySoft, LLC (2013-)
3 // Massachusetts Institute of Technology (2007-2014)
4 // Community contributors (see AUTHORS file)
5 // File authors:
6 // Toby Schneider <toby@gobysoft.org>
7 // Chris Murphy <cmurphy@aphysci.com>
8 //
9 //
10 // This file is part of the Dynamic Compact Control Language Library
11 // ("DCCL").
12 //
13 // DCCL is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU Lesser General Public License as published by
15 // the Free Software Foundation, either version 2.1 of the License, or
16 // (at your option) any later version.
17 //
18 // DCCL is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU Lesser General Public License for more details.
22 //
23 // You should have received a copy of the GNU Lesser General Public License
24 // along with DCCL. If not, see <http://www.gnu.org/licenses/>.
25 #include "field_codec_default.h"
26 
27 using namespace dccl::logger;
28 
29 //
30 // DefaultStringCodec
31 //
32 
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: ") +
42  FieldCodecBase::this_field()->DebugString(),
43  this->this_field(), this->this_descriptor()));
44 
45  dccl::dlog.is(DEBUG2) &&
46  dccl::dlog << "String " << s << " exceeds `dccl.max_length`, truncating" << std::endl;
47  s.resize(dccl_field_options().max_length());
48  }
49 
50  Bitset value_bits;
51  value_bits.from_byte_string(s);
52 
53  Bitset length_bits(min_size(), s.length());
54 
55  dccl::dlog.is(DEBUG2) && dccl::dlog << "DefaultStringCodec value_bits: " << value_bits
56  << std::endl;
57 
58  dccl::dlog.is(DEBUG2) && dccl::dlog << "DefaultStringCodec length_bits: " << length_bits
59  << std::endl;
60 
61  // adds to MSBs
62  for (int i = 0, n = value_bits.size(); i < n; ++i) length_bits.push_back(value_bits[i]);
63 
64  dccl::dlog.is(DEBUG2) && dccl::dlog << "DefaultStringCodec created: " << length_bits
65  << std::endl;
66 
67  return length_bits;
68 }
69 
71 {
72  unsigned value_length = bits->to_ulong();
73 
74  if (value_length)
75  {
76  unsigned header_length = min_size();
77 
78  dccl::dlog.is(DEBUG2) && dccl::dlog << "Length of string is = " << value_length
79  << std::endl;
80 
81  dccl::dlog.is(DEBUG2) && dccl::dlog << "bits before get_more_bits " << *bits << std::endl;
82 
83  // grabs more bits to add to the MSBs of `bits`
84  bits->get_more_bits(value_length * BITS_IN_BYTE);
85 
86  dccl::dlog.is(DEBUG2) && dccl::dlog << "bits after get_more_bits " << *bits << std::endl;
87  Bitset string_body_bits = *bits;
88  string_body_bits >>= header_length;
89  string_body_bits.resize(bits->size() - header_length);
90 
91  return string_body_bits.to_byte_string();
92  }
93  else
94  {
95  throw NullValueException();
96  }
97 }
98 
99 unsigned dccl::v3::DefaultStringCodec::size() { return min_size(); }
100 
101 unsigned dccl::v3::DefaultStringCodec::size(const std::string& wire_value)
102 {
103  return std::min(min_size() + static_cast<unsigned>(wire_value.length() * BITS_IN_BYTE),
104  max_size());
105 }
106 
108 {
109  // string length + actual string
110  return min_size() + dccl_field_options().max_length() * BITS_IN_BYTE;
111 }
112 
114 {
115  return dccl::ceil_log2(dccl_field_options().max_length() + 1);
116 }
117 
119 {
120  require(dccl_field_options().has_max_length(), "missing (dccl.field).max_length");
121 }
122 
123 //
124 // DefaultEnumCodec
125 //
126 double dccl::v3::DefaultEnumCodec::max()
127 {
128  const google::protobuf::EnumDescriptor* e = this_field()->enum_type();
129 
130  if (dccl_field_options().packed_enum())
131  {
132  return e->value_count() - 1;
133  }
134  else
135  {
136  const google::protobuf::EnumValueDescriptor* value = e->value(0);
137  int32 maxVal = value->number();
138  for (int i = 1; i < e->value_count(); ++i)
139  {
140  value = e->value(i);
141  if (value->number() > maxVal)
142  {
143  maxVal = value->number();
144  }
145  }
146  return maxVal;
147  }
148 }
149 
150 double dccl::v3::DefaultEnumCodec::min()
151 {
152  if (dccl_field_options().packed_enum())
153  {
154  return 0;
155  }
156  else
157  {
158  const google::protobuf::EnumDescriptor* e = this_field()->enum_type();
159  const google::protobuf::EnumValueDescriptor* value = e->value(0);
160  int32 minVal = value->number();
161  for (int i = 1; i < e->value_count(); ++i)
162  {
163  value = e->value(i);
164  if (value->number() < minVal)
165  {
166  minVal = value->number();
167  }
168  }
169  return minVal;
170  }
171 }
172 
173 dccl::int32 dccl::v3::DefaultEnumCodec::pre_encode(
174  const google::protobuf::EnumValueDescriptor* const& field_value)
175 {
176  if (dccl_field_options().packed_enum())
177  return field_value->index();
178  else
179  return field_value->number();
180 }
181 
182 const google::protobuf::EnumValueDescriptor*
183 dccl::v3::DefaultEnumCodec::post_decode(const dccl::int32& wire_value)
184 {
185  const google::protobuf::EnumDescriptor* e = this_field()->enum_type();
186 
187  if (dccl_field_options().packed_enum())
188  {
189  if (wire_value < e->value_count())
190  {
191  const google::protobuf::EnumValueDescriptor* return_value = e->value(wire_value);
192  return return_value;
193  }
194  else
195  throw NullValueException();
196  }
197  else
198  {
199  const google::protobuf::EnumValueDescriptor* return_value =
200  e->FindValueByNumber(wire_value);
201  if (return_value != nullptr)
202  return return_value;
203  else
204  throw NullValueException();
205  }
206 }
dccl::Bitset::to_ulong
unsigned long to_ulong() const
Returns the value of the Bitset as an unsigned long integer. Equivalent to to<unsigned long>().
Definition: bitset.h:275
dccl::Bitset::get_more_bits
void get_more_bits(size_type num_bits)
Retrieve more bits from the parent Bitset.
Definition: bitset.h:420
dccl::FieldCodecBase::this_field
const google::protobuf::FieldDescriptor * this_field() const
Returns the FieldDescriptor (field schema meta-data) for this field.
Definition: field_codec.cpp:652
dccl::Logger::is
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:192
dccl::v3::DefaultStringCodec::validate
void validate() override
Validate a field. Use require() inside your overloaded validate() to assert requirements or throw Exc...
Definition: field_codec_default.cpp:118
dccl::Bitset::from_byte_string
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:335
dccl::v3::DefaultStringCodec::min_size
unsigned min_size() override
Calculate minimum size of the field in bits.
Definition: field_codec_default.cpp:113
dccl::ceil_log2
unsigned ceil_log2(dccl::uint64 v)
Definition: binary.h:178
dccl::NullValueException
Exception used to signal null (non-existent) value within field codecs during decode.
Definition: exception.h:61
dccl::Bitset
A variable size container of bits (subclassed from std::deque<bool>) with an optional hierarchy....
Definition: bitset.h:42
dccl::OutOfRangeException
Definition: exception.h:67
dccl::v3::DefaultStringCodec::size
unsigned size() override
Calculate the size (in bits) of an empty field.
Definition: field_codec_default.cpp:99
dccl::int32
google::protobuf::int32 int32
a signed 32 bit integer
Definition: common.h:58
dccl::v3::DefaultStringCodec::decode
std::string decode(Bitset *bits) override
Decode a field. If the field is empty (i.e. was encoded using the zero-argument encode()),...
Definition: field_codec_default.cpp:70
dccl::v3::DefaultStringCodec::max_size
unsigned max_size() override
Calculate maximum size of the field in bits.
Definition: field_codec_default.cpp:107
dccl::v3::DefaultStringCodec::encode
Bitset encode() override
Encode an empty field.
Definition: field_codec_default.cpp:33
dccl::Bitset::to_byte_string
std::string to_byte_string()
Returns the value of the Bitset to a byte string, where each character represents 8 bits of the Bitse...
Definition: bitset.h:297