DCCL v4
field_codec_presence.h
1 // Copyright 2019-2023:
2 // GobySoft, LLC (2013-)
3 // Community contributors (see AUTHORS file)
4 // File authors:
5 // Toby Schneider <toby@gobysoft.org>
6 // Kyle Guilbert <kguilbert@aphysci.com>
7 //
8 //
9 // This file is part of the Dynamic Compact Control Language Library
10 // ("DCCL").
11 //
12 // DCCL is free software: you can redistribute it and/or modify
13 // it under the terms of the GNU Lesser General Public License as published by
14 // the Free Software Foundation, either version 2.1 of the License, or
15 // (at your option) any later version.
16 //
17 // DCCL is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU Lesser General Public License for more details.
21 //
22 // You should have received a copy of the GNU Lesser General Public License
23 // along with DCCL. If not, see <http://www.gnu.org/licenses/>.
24 #ifndef FIELD_CODEC_PRESENCE_20190722H
25 #define FIELD_CODEC_PRESENCE_20190722H
26 
27 #include "../field_codec_typed.h"
28 
29 namespace dccl
30 {
31 namespace v3
32 {
43 template <typename WrappedType>
45  : public TypedFieldCodec<typename WrappedType::wire_type, typename WrappedType::field_type>
46 {
47  public:
49 
51  using wrapped_type = WrappedType;
52 
54  using wire_type = typename Base::wire_type;
55 
57  using field_type = typename Base::field_type;
58 
59  private:
61  WrappedType _inner_codec;
62 
63  public:
64  PresenceBitCodec() { _inner_codec.set_force_use_required(true); }
65 
66  // required when wire_type != field_type
67  wire_type pre_encode(const field_type& field_value) override
68  {
69  return _inner_codec.pre_encode(field_value);
70  }
71 
72  // required when wire_type != field_type
73  field_type post_decode(const wire_type& wire_value) override
74  {
75  return _inner_codec.post_decode(wire_value);
76  }
77 
79  void validate() override { _inner_codec.validate(); }
80 
82  Bitset encode() override
83  {
84  return Bitset(1, 0); // presence bit == false
85  }
86 
88  Bitset encode(const wire_type& value) override
89  {
90  Bitset encoded = _inner_codec.encode(value);
91 
92  if (!this->use_required())
93  {
94  encoded.push_front(true);
95  }
96  return encoded;
97  }
98 
100  wire_type decode(Bitset* bits) override
101  {
102  if (!this->use_required())
103  {
104  // optional field: bits contains only the presence bit
105  bool present = bits->front();
106  if (!present)
107  {
108  throw NullValueException();
109  }
110  // the single bit was the presence bit; consume it and get the rest
111  bits->pop_front();
112  bits->get_more_bits(_inner_codec.size());
113  }
114 
115  return _inner_codec.decode(bits);
116  }
117 
119  unsigned size() override
120  {
121  // empty field is always 1 bit (only occurs for optional fields)
122  return 1;
123  }
124 
126  unsigned size(const wire_type& wire_value) override
127  {
128  int presence_bits = this->use_required() ? 0 : 1;
129  return presence_bits + _inner_codec.size(wire_value);
130  }
131 
132  unsigned max_size() override
133  {
134  if (this->use_required())
135  {
136  // def to "wrapped" codec
137  return _inner_codec.max_size();
138  }
139  else
140  {
141  // optional fields have the extra presence bit
142  return _inner_codec.max_size() + 1;
143  }
144  }
145 
146  unsigned min_size() override
147  {
148  if (this->use_required())
149  {
150  // defer to "wrapped" codec
151  return _inner_codec.min_size();
152  }
153  else
154  {
155  // optional fields encode as 1 bit minimum
156  return 1;
157  }
158  }
159 
160  void set_manager(FieldCodecManagerLocal* manager) override
161  {
162  _inner_codec.set_manager(manager);
163  FieldCodecBase::set_manager(manager);
164  }
165 };
166 } // namespace v3
167 } // namespace dccl
168 
169 #endif /* FIELD_CODEC_PRESENCE_20190722H */
dccl::v3::PresenceBitCodec::encode
Bitset encode(const wire_type &value) override
Encodes a non-empty field, adding a 1 bit to the front for optional fields.
Definition: field_codec_presence.h:88
dccl::FieldCodecManagerLocal
A class for managing the various field codecs. Here you can add and remove field codecs....
Definition: field_codec_manager.h:39
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
Dynamic Compact Control Language namespace.
Definition: any.h:46
dccl::v3::PresenceBitCodec::field_type
typename Base::field_type field_type
The field_type of the "wrapped" codec.
Definition: field_codec_presence.h:57
dccl::v3::PresenceBitCodec::wrapped_type
WrappedType wrapped_type
The codec type of the "wrapped" codec.
Definition: field_codec_presence.h:51
dccl::v3::PresenceBitCodec::validate
void validate() override
Calls _inner_codec.validate()
Definition: field_codec_presence.h:79
dccl::FieldCodecBase::set_force_use_required
void set_force_use_required(bool force_required=true)
Force the codec to always use the "required" field encoding, regardless of the FieldDescriptor settin...
Definition: field_codec.h:122
dccl::v3::PresenceBitCodec::max_size
unsigned max_size() override
Calculate maximum size of the field in bits.
Definition: field_codec_presence.h:132
dccl::v3::PresenceBitCodec::decode
wire_type decode(Bitset *bits) override
Decodes a field, first evaluating the presence bit if necessary.
Definition: field_codec_presence.h:100
dccl::v3::PresenceBitCodec::encode
Bitset encode() override
Encodes an empty field as a single 0 bit.
Definition: field_codec_presence.h:82
dccl::v3::PresenceBitCodec::size
unsigned size(const wire_type &wire_value) override
Size of a non-empty field; gets size from "wrapped" codec, adds 1 for optional fields.
Definition: field_codec_presence.h:126
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::v3::PresenceBitCodec::wire_type
typename Base::wire_type wire_type
The wire_type of the "wrapped" codec.
Definition: field_codec_presence.h:54
dccl::TypedFieldCodec
Base class for static-typed (no dccl::any) field encoders/decoders. Most single-valued user defined v...
Definition: field_codec_typed.h:72
dccl::v3::PresenceBitCodec
Encodes empty optional fields with a single "presence" bit.
Definition: field_codec_presence.h:44
dccl::FieldCodecBase::use_required
bool use_required()
Whether to use the required or optional encoding.
Definition: field_codec.h:385
dccl::v3::PresenceBitCodec::min_size
unsigned min_size() override
Calculate minimum size of the field in bits.
Definition: field_codec_presence.h:146
dccl::v3::PresenceBitCodec::size
unsigned size() override
Size of an empty field (1 bit)
Definition: field_codec_presence.h:119