DCCL v5
Loading...
Searching...
No Matches
field_codec_var_bytes.cpp
1// Copyright 2018-2023:
2// GobySoft, LLC (2013-)
3// Community contributors (see AUTHORS file)
4// File authors:
5// Toby Schneider <toby@gobysoft.org>
6//
7//
8// This file is part of the Dynamic Compact Control Language Library
9// ("DCCL").
10//
11// DCCL is free software: you can redistribute it and/or modify
12// it under the terms of the GNU Lesser General Public License as published by
13// the Free Software Foundation, either version 2.1 of the License, or
14// (at your option) any later version.
15//
16// DCCL is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Lesser General Public License for more details.
20//
21// You should have received a copy of the GNU Lesser General Public License
22// along with DCCL. If not, see <http://www.gnu.org/licenses/>.
23#include "field_codec_var_bytes.h"
24#include "../logger.h"
25
26using namespace dccl::logger;
27
29
30dccl::Bitset dccl::v3::VarBytesCodec::encode(const std::string& wire_value)
31{
32 std::string s = wire_value;
33 if (s.size() > dccl_field_options().max_length())
34 {
35 if (this->strict())
36 throw(dccl::OutOfRangeException(std::string("Bytes too long for field: ") +
37 FieldCodecBase::this_field()->DebugString(),
38 this->this_field(), this->this_descriptor()));
39
40 dccl::dlog.is(DEBUG2) &&
41 dccl::dlog << "Bytes " << s << " exceeds `dccl.max_length`, truncating" << std::endl;
42 s.resize(dccl_field_options().max_length());
43 }
44
45 if (s.size() < dccl_field_options().min_length())
46 {
47 if (this->strict())
48 throw(dccl::OutOfRangeException(std::string("Bytes too short for field: ") +
49 FieldCodecBase::this_field()->DebugString(),
50 this->this_field(), this->this_descriptor()));
51
52 dccl::dlog.is(DEBUG2) &&
53 dccl::dlog << "Bytes " << s << " is shorter than `dccl.min_length`, padding"
54 << std::endl;
55 s.resize(dccl_field_options().min_length(), '\0');
56 }
57
58 dccl::Bitset value_bits;
59 value_bits.from_byte_string(s);
60
61 dccl::Bitset length_bits(presence_size() + prefix_size(),
62 s.length() - dccl_field_options().min_length());
63
64 if (!use_required()) // set the presence bit
65 {
66 length_bits <<= 1;
67 length_bits.set(0);
68 }
69
70 dccl::dlog.is(DEBUG2) && dccl::dlog << "dccl::v3::VarBytesCodec value_bits: " << value_bits
71 << std::endl;
72
73 dccl::dlog.is(DEBUG2) && dccl::dlog << "dccl::v3::VarBytesCodec length_bits: " << length_bits
74 << std::endl;
75
76 // adds to MSBs
77 for (int i = 0, n = value_bits.size(); i < n; ++i) length_bits.push_back(value_bits[i]);
78
79 dccl::dlog.is(DEBUG2) && dccl::dlog << "dccl::v3::VarBytesCodec created: " << length_bits
80 << std::endl;
81
82 return length_bits;
83}
84
86{
87 if (!use_required())
88 {
89 if (bits->to_ulong() == 0)
90 {
92 }
93 else
94 {
95 bits->get_more_bits(prefix_size());
96 (*bits) >>= 1;
97 }
98 }
99
100 unsigned value_length = bits->to_ulong() + dccl_field_options().min_length();
101 unsigned header_length = presence_size() + prefix_size();
102
103 dccl::dlog.is(DEBUG2) && dccl::dlog << "Length of string is = " << value_length << std::endl;
104
105 dccl::dlog.is(DEBUG2) && dccl::dlog << "bits before get_more_bits " << *bits << std::endl;
106
107 // grabs more bits to add to the MSBs of `bits`
108 bits->get_more_bits(value_length * dccl::BITS_IN_BYTE);
109
110 dccl::dlog.is(DEBUG2) && dccl::dlog << "bits after get_more_bits " << *bits << std::endl;
111 dccl::Bitset string_body_bits = *bits;
112 string_body_bits >>= header_length;
113 string_body_bits.resize(bits->size() - header_length);
114
115 dccl::dlog.is(DEBUG2) && dccl::dlog << "string_body_bits " << string_body_bits << std::endl;
116
117 return string_body_bits.to_byte_string();
118}
119
120unsigned dccl::v3::VarBytesCodec::size() { return min_size(); }
121
122unsigned dccl::v3::VarBytesCodec::size(const std::string& wire_value)
123{
124 unsigned length =
125 std::max(static_cast<unsigned>(wire_value.length()),
126 static_cast<unsigned>(dccl_field_options().min_length()));
127 return std::min(presence_size() + prefix_size() + length * dccl::BITS_IN_BYTE, max_size());
128}
129
131{
132 return presence_size() + prefix_size() + dccl_field_options().max_length() * dccl::BITS_IN_BYTE;
133}
134
136{
137 if (use_required())
138 return prefix_size();
139 else
140 return presence_size();
141}
142
144{
145 require(dccl_field_options().has_max_length(), "missing (dccl.field).max_length");
146 require(dccl_field_options().max_length() >= dccl_field_options().min_length(),
147 "(dccl.field).max_length must be >= (dccl.field).min_length");
148}
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
Bitset & set(size_type n, bool val=true)
Set a bit to a given value.
Definition bitset.h:175
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:191
Exception used to signal null (non-existent) value within field codecs during decode.
Definition exception.h:62
std::string decode(dccl::Bitset *bits) override
Decode a field. If the field is empty (i.e. was encoded using the zero-argument encode()),...
unsigned max_size() override
Calculate maximum size of the field in bits.
void validate() override
Validate a field. Use require() inside your overloaded validate() to assert requirements or throw Exc...
dccl::Bitset encode() override
Encode an empty field.
unsigned min_size() override
Calculate minimum size of the field in bits.
unsigned size() override
Calculate the size (in bits) of an empty field.