DCCL v4
field_codec_presence.h
1 // Copyright 2019:
2 // GobySoft, LLC (2013-)
3 // Community contributors (see AUTHORS file)
4 // File authors:
5 // Kyle Guilbert <kguilbert@aphysci.com>
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 #ifndef FIELD_CODEC_PRESENCE_20190722H
24 #define FIELD_CODEC_PRESENCE_20190722H
25 
26 #include "../field_codec_typed.h"
27 
28 namespace dccl
29 {
30 namespace v3
31 {
42 template <typename WrappedType>
44  : public TypedFieldCodec<typename WrappedType::wire_type, typename WrappedType::field_type>
45 {
46  public:
48 
50  using wrapped_type = WrappedType;
51 
53  using wire_type = typename Base::wire_type;
54 
56  using field_type = typename Base::field_type;
57 
58  private:
60  WrappedType _inner_codec;
61 
62  public:
63  PresenceBitCodec() { _inner_codec.set_force_use_required(true); }
64 
65  // required when wire_type != field_type
66  wire_type pre_encode(const field_type& field_value) override
67  {
68  return _inner_codec.pre_encode(field_value);
69  }
70 
71  // required when wire_type != field_type
72  field_type post_decode(const wire_type& wire_value) override
73  {
74  return _inner_codec.post_decode(wire_value);
75  }
76 
78  void validate() override { _inner_codec.validate(); }
79 
81  Bitset encode() override
82  {
83  return Bitset(1, 0); // presence bit == false
84  }
85 
87  Bitset encode(const wire_type& value) override
88  {
89  Bitset encoded = _inner_codec.encode(value);
90 
91  if (!this->use_required())
92  {
93  encoded.push_front(true);
94  }
95  return encoded;
96  }
97 
99  wire_type decode(Bitset* bits) override
100  {
101  if (!this->use_required())
102  {
103  // optional field: bits contains only the presence bit
104  bool present = bits->front();
105  if (!present)
106  {
107  throw NullValueException();
108  }
109  // the single bit was the presence bit; consume it and get the rest
110  bits->pop_front();
111  bits->get_more_bits(_inner_codec.size());
112  }
113 
114  return _inner_codec.decode(bits);
115  }
116 
118  unsigned size() override
119  {
120  // empty field is always 1 bit (only occurs for optional fields)
121  return 1;
122  }
123 
125  unsigned size(const wire_type& wire_value) override
126  {
127  int presence_bits = this->use_required() ? 0 : 1;
128  return presence_bits + _inner_codec.size(wire_value);
129  }
130 
131  unsigned max_size() override
132  {
133  if (this->use_required())
134  {
135  // def to "wrapped" codec
136  return _inner_codec.max_size();
137  }
138  else
139  {
140  // optional fields have the extra presence bit
141  return _inner_codec.max_size() + 1;
142  }
143  }
144 
145  unsigned min_size() override
146  {
147  if (this->use_required())
148  {
149  // defer to "wrapped" codec
150  return _inner_codec.min_size();
151  }
152  else
153  {
154  // optional fields encode as 1 bit minimum
155  return 1;
156  }
157  }
158 
159  void set_manager(FieldCodecManagerLocal* manager) override
160  {
161  _inner_codec.set_manager(manager);
162  FieldCodecBase::set_manager(manager);
163  }
164 };
165 } // namespace v3
166 } // namespace dccl
167 
168 #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:87
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:419
dccl
Dynamic Compact Control Language namespace.
Definition: any.h:49
dccl::v3::PresenceBitCodec::field_type
typename Base::field_type field_type
The field_type of the "wrapped" codec.
Definition: field_codec_presence.h:56
dccl::v3::PresenceBitCodec::wrapped_type
WrappedType wrapped_type
The codec type of the "wrapped" codec.
Definition: field_codec_presence.h:50
dccl::v3::PresenceBitCodec::validate
void validate() override
Calls _inner_codec.validate()
Definition: field_codec_presence.h:78
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:123
dccl::v3::PresenceBitCodec::max_size
unsigned max_size() override
Calculate maximum size of the field in bits.
Definition: field_codec_presence.h:131
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:99
dccl::v3::PresenceBitCodec::encode
Bitset encode() override
Encodes an empty field as a single 0 bit.
Definition: field_codec_presence.h:81
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:125
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::v3::PresenceBitCodec::wire_type
typename Base::wire_type wire_type
The wire_type of the "wrapped" codec.
Definition: field_codec_presence.h:53
dccl::TypedFieldCodec
Base class for static-typed (no dccl::any) field encoders/decoders. Most single-valued user defined v...
Definition: field_codec_typed.h:73
dccl::v3::PresenceBitCodec
Encodes empty optional fields with a single "presence" bit.
Definition: field_codec_presence.h:43
dccl::FieldCodecBase::use_required
bool use_required()
Whether to use the required or optional encoding.
Definition: field_codec.h:386
dccl::v3::PresenceBitCodec::min_size
unsigned min_size() override
Calculate minimum size of the field in bits.
Definition: field_codec_presence.h:145
dccl::v3::PresenceBitCodec::size
unsigned size() override
Size of an empty field (1 bit)
Definition: field_codec_presence.h:118