DCCL v4
Loading...
Searching...
No Matches
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
27using namespace dccl::logger;
28
29//
30// DefaultStringCodec
31//
32
34
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
99unsigned dccl::v3::DefaultStringCodec::size() { return min_size(); }
100
101unsigned 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//
126double 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
150double 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
173dccl::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
182const google::protobuf::EnumValueDescriptor*
183dccl::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}
A variable size container of bits (subclassed from std::deque<bool>) with an optional hierarchy....
Definition bitset.h:43
void get_more_bits(size_type num_bits)
Retrieve more bits from the parent Bitset.
Definition bitset.h:420
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
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
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
const google::protobuf::FieldDescriptor * this_field() const
Returns the FieldDescriptor (field schema meta-data) for this field.
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
Exception used to signal null (non-existent) value within field codecs during decode.
Definition exception.h:62
unsigned max_size() override
Calculate maximum size of the field in bits.
unsigned min_size() override
Calculate minimum size of the field in bits.
std::string decode(Bitset *bits) override
Decode a field. If the field is empty (i.e. was encoded using the zero-argument encode()),...
Bitset encode() override
Encode an empty field.
unsigned size() override
Calculate the size (in bits) of an empty field.
void validate() override
Validate a field. Use require() inside your overloaded validate() to assert requirements or throw Exc...
google::protobuf::int32 int32
a signed 32 bit integer
Definition common.h:58
unsigned ceil_log2(dccl::uint64 v)
Definition binary.h:178