DCCL v4
field_codec_var_bytes.cpp
1 // Copyright 2018-2019:
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 
24 #include "field_codec_var_bytes.h"
25 #include "../field_codec_manager.h"
26 #include "field_codec_default.h"
27 
28 using namespace dccl::logger;
29 
31 
32 dccl::Bitset dccl::v3::VarBytesCodec::encode(const std::string& wire_value)
33 {
34  std::string s = wire_value;
35  if (s.size() > dccl_field_options().max_length())
36  {
37  if (this->strict())
38  throw(dccl::OutOfRangeException(std::string("Bytes too long for field: ") +
39  FieldCodecBase::this_field()->DebugString(),
40  this->this_field(), this->this_descriptor()));
41 
42  dccl::dlog.is(DEBUG2) &&
43  dccl::dlog << "Bytes " << s << " exceeds `dccl.max_length`, truncating" << std::endl;
44  s.resize(dccl_field_options().max_length());
45  }
46 
47  dccl::Bitset value_bits;
48  value_bits.from_byte_string(s);
49 
50  dccl::Bitset length_bits(presence_size() + prefix_size(), s.length());
51 
52  if (!use_required()) // set the presence bit
53  {
54  length_bits <<= 1;
55  length_bits.set(0);
56  }
57 
58  dccl::dlog.is(DEBUG2) && dccl::dlog << "dccl::v3::VarBytesCodec value_bits: " << value_bits
59  << std::endl;
60 
61  dccl::dlog.is(DEBUG2) && dccl::dlog << "dccl::v3::VarBytesCodec length_bits: " << length_bits
62  << std::endl;
63 
64  // adds to MSBs
65  for (int i = 0, n = value_bits.size(); i < n; ++i) length_bits.push_back(value_bits[i]);
66 
67  dccl::dlog.is(DEBUG2) && dccl::dlog << "dccl::v3::VarBytesCodec created: " << length_bits
68  << std::endl;
69 
70  return length_bits;
71 }
72 
74 {
75  if (!use_required())
76  {
77  if (bits->to_ulong() == 0)
78  {
80  }
81  else
82  {
83  bits->get_more_bits(prefix_size());
84  (*bits) >>= 1;
85  }
86  }
87 
88  unsigned value_length = bits->to_ulong();
89  unsigned header_length = presence_size() + prefix_size();
90 
91  dccl::dlog.is(DEBUG2) && dccl::dlog << "Length of string is = " << value_length << std::endl;
92 
93  dccl::dlog.is(DEBUG2) && dccl::dlog << "bits before get_more_bits " << *bits << std::endl;
94 
95  // grabs more bits to add to the MSBs of `bits`
96  bits->get_more_bits(value_length * dccl::BITS_IN_BYTE);
97 
98  dccl::dlog.is(DEBUG2) && dccl::dlog << "bits after get_more_bits " << *bits << std::endl;
99  dccl::Bitset string_body_bits = *bits;
100  string_body_bits >>= header_length;
101  string_body_bits.resize(bits->size() - header_length);
102 
103  dccl::dlog.is(DEBUG2) && dccl::dlog << "string_body_bits " << string_body_bits << std::endl;
104 
105  return string_body_bits.to_byte_string();
106 }
107 
108 unsigned dccl::v3::VarBytesCodec::size() { return min_size(); }
109 
110 unsigned dccl::v3::VarBytesCodec::size(const std::string& wire_value)
111 {
112  return std::min(presence_size() + prefix_size() +
113  static_cast<unsigned>(wire_value.length() * dccl::BITS_IN_BYTE),
114  max_size());
115 }
116 
118 {
119  return presence_size() + prefix_size() + dccl_field_options().max_length() * dccl::BITS_IN_BYTE;
120 }
121 
123 {
124  if (use_required())
125  return prefix_size();
126  else
127  return presence_size();
128 }
129 
131 {
132  require(dccl_field_options().has_max_length(), "missing (dccl.field).max_length");
133 }
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:274
dccl::Bitset::get_more_bits
void get_more_bits(size_type num_bits)
Retrieve more bits from the parent Bitset.
Definition: bitset.h:419
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:653
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::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:334
dccl::v3::VarBytesCodec::encode
dccl::Bitset encode() override
Encode an empty field.
Definition: field_codec_var_bytes.cpp:30
dccl::v3::VarBytesCodec::decode
std::string decode(dccl::Bitset *bits) override
Decode a field. If the field is empty (i.e. was encoded using the zero-argument encode()),...
Definition: field_codec_var_bytes.cpp:73
dccl::v3::VarBytesCodec::max_size
unsigned max_size() override
Calculate maximum size of the field in bits.
Definition: field_codec_var_bytes.cpp:117
dccl::NullValueException
Exception used to signal null (non-existent) value within field codecs during decode.
Definition: exception.h:62
dccl::Bitset
A variable size container of bits (subclassed from std::deque<bool>) with an optional hierarchy....
Definition: bitset.h:41
dccl::OutOfRangeException
Definition: exception.h:68
dccl::v3::VarBytesCodec::validate
void validate() override
Validate a field. Use require() inside your overloaded validate() to assert requirements or throw Exc...
Definition: field_codec_var_bytes.cpp:130
dccl::v3::VarBytesCodec::min_size
unsigned min_size() override
Calculate minimum size of the field in bits.
Definition: field_codec_var_bytes.cpp:122
dccl::Bitset::set
Bitset & set(size_type n, bool val=true)
Set a bit to a given value.
Definition: bitset.h:174
dccl::v3::VarBytesCodec::size
unsigned size() override
Calculate the size (in bits) of an empty field.
Definition: field_codec_var_bytes.cpp:108
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:296