COMMS
Template library intended to help with implementation of communication protocols.
BitmaskValue.h
Go to the documentation of this file.
1 //
2 // Copyright 2014 - 2024 (C). Alex Robenko. All rights reserved.
3 //
4 // This Source Code Form is subject to the terms of the Mozilla Public
5 // License, v. 2.0. If a copy of the MPL was not distributed with this
6 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 
10 
11 #pragma once
12 
13 #include <limits>
14 #include "comms/Field.h"
15 
16 #include "comms/util/SizeToType.h"
17 #include "details/AdaptBasicField.h"
18 #include "details/OptionsParser.h"
19 #include "comms/details/gen_enum.h"
20 #include "comms/details/bits_access.h"
21 #include "comms/field/IntValue.h"
22 #include "comms/field/tag.h"
23 
24 namespace comms
25 {
26 
27 namespace field
28 {
29 
30 namespace details
31 {
32 
33 template <bool THasFixedLength>
34 struct BitmaskUndertlyingType;
35 
36 template <>
37 struct BitmaskUndertlyingType<true>
38 {
39  template <typename TOptionsBundle>
40  using Type = typename comms::util::SizeToType<TOptionsBundle::FixedLength, false>::Type;
41 };
42 
43 template <>
44 struct BitmaskUndertlyingType<false>
45 {
46  template <typename TOptionsBundle>
47  using Type = unsigned;
48 };
49 
50 template <typename TOptionsBundle>
51 using BitmaskUndertlyingTypeT =
52  typename BitmaskUndertlyingType<TOptionsBundle::HasFixedLengthLimit>::template Type<TOptionsBundle>;
53 
54 
55 } // namespace details
56 
101 template <typename TFieldBase, typename... TOptions>
102 class BitmaskValue : public TFieldBase
103 {
104  using BaseImpl = TFieldBase;
105 
106  using OptionsBundle = details::OptionsParser<TOptions...>;
107 
108  using IntValueType = details::BitmaskUndertlyingTypeT<OptionsBundle>;
109 
110  using IntValueField =
111  IntValue<
112  TFieldBase,
113  IntValueType,
114  TOptions...
115  >;
116 
117 public:
119  using FieldBase = TFieldBase;
120 
122  using Endian = typename BaseImpl::Endian;
123 
126 
128  using ParsedOptions = OptionsBundle;
129 
131  using CommsTag = tag::Bitmask;
132 
137 
142 
145  BitmaskValue() = default;
146 
149  explicit BitmaskValue(const ValueType& val)
150  : intValue_(val)
151  {
152  }
153 
155  BitmaskValue(const BitmaskValue&) = default;
156 
158  ~BitmaskValue() noexcept = default;
159 
161  BitmaskValue& operator=(const BitmaskValue&) = default;
162 
165  static constexpr bool hasFailOnInvalid()
166  {
167  return ParsedOptions::HasFailOnInvalid;
168  }
169 
172  static constexpr bool hasIgnoreInvalid()
173  {
174  return ParsedOptions::HasIgnoreInvalid;
175  }
176 
179  static constexpr bool hasEmptySerialization()
180  {
181  return ParsedOptions::HasEmptySerialization;
182  }
183 
186  static constexpr bool hasFieldType()
187  {
188  return ParsedOptions::HasFieldType;
189  }
190 
193  const ValueType& value() const
194  {
195  return intValue_.value();
196  }
197 
201  {
202  return intValue_.value();
203  }
204 
206  const ValueType& getValue() const
207  {
208  return intValue_.getValue();
209  }
210 
212  template <typename U>
213  void setValue(U&& val)
214  {
215  intValue_.setValue(std::forward<U>(val));
216  }
217 
220  constexpr std::size_t length() const
221  {
222  return intValue_.length();
223  }
224 
227  static constexpr std::size_t maxLength()
228  {
229  return IntValueField::maxLength();
230  }
231 
234  static constexpr std::size_t minLength()
235  {
236  return IntValueField::minLength();
237  }
238 
244  template <typename TIter>
245  ErrorStatus read(TIter& iter, std::size_t size)
246  {
247  return intValue_.read(iter, size);
248  }
249 
252  static constexpr bool hasReadNoStatus()
253  {
254  return BaseImpl::hasReadNoStatus();
255  }
256 
262  template <typename TIter>
263  void readNoStatus(TIter& iter)
264  {
265  intValue_.readNoStatus(iter);
266  }
267 
269  bool canWrite() const
270  {
271  return BaseImpl::canWrite();
272  }
273 
279  template <typename TIter>
280  ErrorStatus write(TIter& iter, std::size_t size) const
281  {
282  return intValue_.write(iter, size);
283  }
284 
287  static constexpr bool hasWriteNoStatus()
288  {
289  return BaseImpl::hasWriteNoStatus();
290  }
291 
297  template <typename TIter>
298  void writeNoStatus(TIter& iter) const
299  {
300  intValue_.writeNoStatus(iter);
301  }
302 
304  constexpr bool valid() const
305  {
306  return intValue_.valid();
307  }
308 
311  bool refresh()
312  {
313  return intValue_.refresh();
314  }
315 
319  bool hasAllBitsSet(ValueType mask) const
320  {
321  return (value() & mask) == mask;
322  }
323 
327  bool hasAnyBitsSet(ValueType mask) const
328  {
329  return (value() & mask) != 0;
330  }
331 
335  void setBits(ValueType mask)
336  {
337  value() |= mask;
338  }
339 
343  void clearBits(ValueType mask)
344  {
345  value() &= static_cast<ValueType>(~mask);
346  }
347 
349  bool getBitValue(unsigned bitNum) const
350  {
351  return hasAllBitsSet(
352  static_cast<ValueType>(static_cast<ValueType>(1U) << bitNum));
353  }
354 
356  void setBitValue(unsigned bitNum, bool val)
357  {
358  auto mask = static_cast<ValueType>(static_cast<ValueType>(1U) << bitNum);
359  if (val) {
360  setBits(mask);
361  }
362  else {
363  clearBits(mask);
364  }
365  }
366 
368  static constexpr bool isVersionDependent()
369  {
371  }
372 
374  static constexpr bool hasNonDefaultRefresh()
375  {
376  return BaseImpl::hasNonDefaultRefresh();
377  }
378 
382  {
383  return intValue_.getVersion();
384  }
385 
389  {
390  return intValue_.setVersion(version);
391  }
392 
400  void setForcedLength(int len)
401  {
402  intValue_.setForcedLength(len);
403  }
404 
407  int getForcedLength() const
408  {
409  return intValue_.getForcedLength();
410  }
411 
412 protected:
413  using BaseImpl::readData;
414  using BaseImpl::writeData;
415 
416 private:
417 
418  static_assert(!ParsedOptions::HasSerOffset,
419  "comms::option::def::NumValueSerOffset option is not applicable to BitmaskValue field");
420  static_assert(!ParsedOptions::HasVarLengthLimits,
421  "comms::option::def::VarLength option is not applicable to BitmaskValue field");
422  static_assert(!ParsedOptions::HasSequenceElemLengthForcing,
423  "comms::option::def::SequenceElemLengthForcingEnabled option is not applicable to BitmaskValue field");
424  static_assert(!ParsedOptions::HasSequenceSizeForcing,
425  "comms::option::def::SequenceSizeForcingEnabled option is not applicable to BitmaskValue field");
426  static_assert(!ParsedOptions::HasSequenceLengthForcing,
427  "comms::option::def::SequenceLengthForcingEnabled option is not applicable to BitmaskValue field");
428  static_assert(!ParsedOptions::HasSequenceFixedSize,
429  "comms::option::def::SequenceFixedSize option is not applicable to BitmaskValue field");
430  static_assert(!ParsedOptions::HasSequenceFixedSizeUseFixedSizeStorage,
431  "comms::option::app::SequenceFixedSizeUseFixedSizeStorage option is not applicable to BitmaskValue field");
432  static_assert(!ParsedOptions::HasSequenceSizeFieldPrefix,
433  "comms::option::def::SequenceSizeFieldPrefix option is not applicable to BitmaskValue field");
434  static_assert(!ParsedOptions::HasSequenceSerLengthFieldPrefix,
435  "comms::option::def::SequenceSerLengthFieldPrefix option is not applicable to BitmaskValue field");
436  static_assert(!ParsedOptions::HasSequenceElemSerLengthFieldPrefix,
437  "comms::option::def::SequenceElemSerLengthFieldPrefix option is not applicable to BitmaskValue field");
438  static_assert(!ParsedOptions::HasSequenceElemFixedSerLengthFieldPrefix,
439  "comms::option::def::SequenceElemSerLengthFixedFieldPrefix option is not applicable to BitmaskValue field");
440  static_assert(!ParsedOptions::HasSequenceTrailingFieldSuffix,
441  "comms::option::def::SequenceTrailingFieldSuffix option is not applicable to BitmaskValue field");
442  static_assert(!ParsedOptions::HasSequenceTerminationFieldSuffix,
443  "comms::option::def::SequenceTerminationFieldSuffix option is not applicable to BitmaskValue field");
444  static_assert(!ParsedOptions::HasFixedSizeStorage,
445  "comms::option::app::FixedSizeStorage option is not applicable to BitmaskValue field");
446  static_assert(!ParsedOptions::HasCustomStorageType,
447  "comms::option::app::CustomStorageType option is not applicable to BitmaskValue field");
448  static_assert(!ParsedOptions::HasScalingRatio,
449  "comms::option::def::ScalingRatio option is not applicable to BitmaskValue field");
450  static_assert(!ParsedOptions::HasUnits,
451  "comms::option::def::Units option is not applicable to BitmaskValue field");
452  static_assert(!ParsedOptions::HasOrigDataView,
453  "comms::option::app::OrigDataView option is not applicable to BitmaskValue field");
454  static_assert(!ParsedOptions::HasMultiRangeValidation,
455  "comms::option::def::ValidNumValueRange (or similar) option is not applicable to BitmaskValue field");
456  static_assert(!ParsedOptions::HasVersionsRange,
457  "comms::option::def::ExistsBetweenVersions (or similar) option is not applicable to BitmaskValue field");
458  static_assert(!ParsedOptions::HasInvalidByDefault,
459  "comms::option::def::InvalidByDefault option is not applicable to BitmaskValue field");
460  static_assert(!ParsedOptions::HasMissingOnReadFail,
461  "comms::option::def::MissingOnReadFail option is not applicable to BitmaskValue field");
462  static_assert(!ParsedOptions::HasMissingOnInvalid,
463  "comms::option::def::MissingOnInvalid option is not applicable to BitmaskValue field");
464  IntValueField intValue_;
465 };
466 
467 // Implementation
468 
474 template <typename TFieldBase, typename... TOptions>
477  const BitmaskValue<TFieldBase, TOptions...>& field2) noexcept
478 {
479  return field1.value() == field2.value();
480 }
481 
487 template <typename TFieldBase, typename... TOptions>
490  const BitmaskValue<TFieldBase, TOptions...>& field2) noexcept
491 {
492  return field1.value() != field2.value();
493 }
494 
500 template <typename TFieldBase, typename... TOptions>
503  const BitmaskValue<TFieldBase, TOptions...>& field2) noexcept
504 {
505  return field1.value() < field2.value();
506 }
507 
513 template <typename T>
514 constexpr bool isBitmaskValue()
515 {
516  return std::is_same<typename T::CommsTag, tag::Bitmask>::value;
517 }
518 
522 template <typename TFieldBase, typename... TOptions>
523 inline
524 BitmaskValue<TFieldBase, TOptions...>&
526 {
527  return field;
528 }
529 
533 template <typename TFieldBase, typename... TOptions>
534 inline
535 const BitmaskValue<TFieldBase, TOptions...>&
537 {
538  return field;
539 }
540 
541 
590 #define COMMS_BITMASK_BITS(...) COMMS_DEFINE_ENUM(BitIdx, __VA_ARGS__)
591 
684 #define COMMS_BITMASK_BITS_ACCESS(...) \
685  COMMS_AS_BITMASK_FUNC { \
686  return comms::field::toFieldBase(*this); \
687  }\
688  COMMS_AS_BITMASK_CONST_FUNC { \
689  return comms::field::toFieldBase(*this); \
690  } \
691  COMMS_DO_BIT_ACC_FUNC(asBitmask(), __VA_ARGS__)
692 
703 #define COMMS_BITMASK_BITS_ACCESS_NOTEMPLATE(...) \
704  COMMS_DO_BIT_ACC_FUNC((*this), __VA_ARGS__)
705 
706 
776 #define COMMS_BITMASK_BITS_SEQ(...) \
777  COMMS_BITMASK_BITS(__VA_ARGS__) \
778  COMMS_BITMASK_BITS_ACCESS(__VA_ARGS__)
779 
791 #define COMMS_BITMASK_BITS_SEQ_NOTEMPLATE(...) \
792  COMMS_BITMASK_BITS(__VA_ARGS__) \
793  COMMS_BITMASK_BITS_ACCESS_NOTEMPLATE(__VA_ARGS__)
794 
795 
796 } // namespace field
797 
798 } // namespace comms
799 
800 
Contains definition of comms::Field class.
Contains definition of comms::field::IntValue.
Bitmask value field.
Definition: BitmaskValue.h:103
void setForcedLength(int len)
Force serialization length of the field.
Definition: BitmaskValue.h:400
void clearBits(ValueType mask)
Set all the provided bits.
Definition: BitmaskValue.h:343
int getForcedLength() const
Get forced serialization length.
Definition: BitmaskValue.h:407
void setValue(U &&val)
Set value.
Definition: BitmaskValue.h:213
VersionType getVersion() const
Get version of the field.
Definition: BitmaskValue.h:381
ErrorStatus read(TIter &iter, std::size_t size)
Read field value from input data sequence.
Definition: BitmaskValue.h:245
bool operator<(const BitmaskValue< TFieldBase, TOptions... > &field1, const BitmaskValue< TFieldBase, TOptions... > &field2) noexcept
Equivalence comparison operator.
Definition: BitmaskValue.h:501
typename IntValueField::ValueType ValueType
Type of underlying integral value.
Definition: BitmaskValue.h:136
ValueType & value()
Get access to underlying mask value storage.
Definition: BitmaskValue.h:200
bool getBitValue(unsigned bitNum) const
Get bit value.
Definition: BitmaskValue.h:349
static constexpr bool hasWriteNoStatus()
Compile time check of whether the field has proper writeNoStatus() member function.
Definition: BitmaskValue.h:287
static constexpr bool isVersionDependent()
Compile time check if this class is version dependent.
Definition: BitmaskValue.h:368
static constexpr bool hasReadNoStatus()
Compile time check of whether the field has proper readNoStatus() member function.
Definition: BitmaskValue.h:252
const ValueType & value() const
Get access to underlying mask value storage.
Definition: BitmaskValue.h:193
constexpr bool valid() const
Check validity of the field value.
Definition: BitmaskValue.h:304
typename BaseImpl::VersionType VersionType
Version type.
Definition: BitmaskValue.h:125
bool setVersion(VersionType version)
Default implementation of version update.
Definition: BitmaskValue.h:388
void readNoStatus(TIter &iter)
Read field value from input data sequence without error check and status report.
Definition: BitmaskValue.h:263
static constexpr bool hasEmptySerialization()
Compile time inquiry of whether comms::option::def::EmptySerialization option has been used.
Definition: BitmaskValue.h:179
static constexpr std::size_t minLength()
Get minimal length that is required to serialise field of this type.
Definition: BitmaskValue.h:234
constexpr bool isBitmaskValue()
Compile time check function of whether a provided type is any variant of comms::field::BitmaskValue.
Definition: BitmaskValue.h:514
static constexpr bool hasFieldType()
Compile time inquiry of whether comms::option::def::FieldType option has been used.
Definition: BitmaskValue.h:186
void setBitValue(unsigned bitNum, bool val)
Set bit value.
Definition: BitmaskValue.h:356
bool canWrite() const
Check of whether the field has a consistent value for writing.
Definition: BitmaskValue.h:269
static constexpr bool hasIgnoreInvalid()
Compile time inquiry of whether comms::option::def::IgnoreInvalid option has been used.
Definition: BitmaskValue.h:172
tag::Bitmask CommsTag
Tag indicating type of the field.
Definition: BitmaskValue.h:131
const BitmaskValue< TFieldBase, TOptions... > & toFieldBase(const BitmaskValue< TFieldBase, TOptions... > &field)
Upcast type of the field definition to its parent comms::field::BitmaskValue type in order to have ac...
Definition: BitmaskValue.h:536
~BitmaskValue() noexcept=default
Destructor.
bool hasAnyBitsSet(ValueType mask) const
Check whether any bits from provided mask are set.
Definition: BitmaskValue.h:327
bool refresh()
Refresh contents of the field.
Definition: BitmaskValue.h:311
typename ParsedOptions::FieldType FieldType
Type of actual extending field specified via comms::option::def::FieldType.
Definition: BitmaskValue.h:141
OptionsBundle ParsedOptions
All the options provided to this class bundled into struct.
Definition: BitmaskValue.h:128
BitmaskValue(const ValueType &val)
Constructor.
Definition: BitmaskValue.h:149
ErrorStatus write(TIter &iter, std::size_t size) const
Write current field value to output data sequence.
Definition: BitmaskValue.h:280
constexpr std::size_t length() const
Get length required to serialise the current field value.
Definition: BitmaskValue.h:220
const ValueType & getValue() const
Get value.
Definition: BitmaskValue.h:206
BitmaskValue(const BitmaskValue &)=default
Copy constructor.
TFieldBase FieldBase
Base class provided in the first template parameter.
Definition: BitmaskValue.h:119
bool operator!=(const BitmaskValue< TFieldBase, TOptions... > &field1, const BitmaskValue< TFieldBase, TOptions... > &field2) noexcept
Non-equality comparison operator.
Definition: BitmaskValue.h:488
static constexpr std::size_t maxLength()
Get maximal length that is required to serialise field of this type.
Definition: BitmaskValue.h:227
void setBits(ValueType mask)
Set all the provided bits.
Definition: BitmaskValue.h:335
static constexpr bool hasFailOnInvalid()
Compile time inquiry of whether comms::option::def::FailOnInvalid option has been used.
Definition: BitmaskValue.h:165
BitmaskValue()=default
Default constructor.
static constexpr bool hasNonDefaultRefresh()
Compile time check if this class has non-default refresh functionality.
Definition: BitmaskValue.h:374
BitmaskValue< TFieldBase, TOptions... > & toFieldBase(BitmaskValue< TFieldBase, TOptions... > &field)
Upcast type of the field definition to its parent comms::field::BitmaskValue type in order to have ac...
Definition: BitmaskValue.h:525
void writeNoStatus(TIter &iter) const
Write current field value to output data sequence without error check and status report.
Definition: BitmaskValue.h:298
bool operator==(const BitmaskValue< TFieldBase, TOptions... > &field1, const BitmaskValue< TFieldBase, TOptions... > &field2) noexcept
Equality comparison operator.
Definition: BitmaskValue.h:475
bool hasAllBitsSet(ValueType mask) const
Check whether all bits from provided mask are set.
Definition: BitmaskValue.h:319
typename BaseImpl::Endian Endian
Endian used for serialisation.
Definition: BitmaskValue.h:122
typename BaseImpl::ValueType ValueType
Type of underlying integral value.
Definition: IntValue.h:93
bool setVersion(VersionType version)
Default implementation of version update.
Definition: IntValue.h:384
bool valid() const
Check validity of the field value.
Definition: IntValue.h:287
int getForcedLength() const
Get forced serialization length.
Definition: IntValue.h:403
const ValueType & value() const
Get access to integral value storage.
Definition: IntValue.h:227
VersionType getVersion() const
Get version of the field.
Definition: IntValue.h:377
constexpr std::size_t length() const
Get length required to serialise the current field value.
Definition: IntValue.h:267
static constexpr std::size_t maxLength()
Get maximal length that is required to serialise field of this type.
Definition: IntValue.h:281
void readNoStatus(TIter &iter)
Read field value from input data sequence without error check and status report.
Definition: IntValue.h:323
static constexpr std::size_t minLength()
Get minimal length that is required to serialise field of this type.
Definition: IntValue.h:274
ErrorStatus read(TIter &iter, std::size_t size)
Read field value from input data sequence.
Definition: IntValue.h:305
void setForcedLength(int len)
Force serialization length of the field.
Definition: IntValue.h:396
void setValue(U &&val)
Set value.
Definition: IntValue.h:248
const ValueType & getValue() const
Get value.
Definition: IntValue.h:240
ErrorStatus write(TIter &iter, std::size_t size) const
Write current field value to output data sequence.
Definition: IntValue.h:340
void writeNoStatus(TIter &iter) const
Write current field value to output data sequence without error check and status report.
Definition: IntValue.h:358
static constexpr bool isVersionDependent()
Compile time check if this class is version dependent.
Definition: IntValue.h:364
bool refresh()
Refresh the field's value.
Definition: IntValue.h:294
Contains definition of various tag classes.
comms::option::def::VersionType< T > VersionType
Same as comms::option::def::VersionType.
Definition: options.h:1797
comms::option::def::FieldType< TMsg > FieldType
Same as comms::option::def::FieldType.
Definition: options.h:1463
comms::option::def::Endian< TEndian > Endian
Same as comms::option::def::Endian.
Definition: options.h:1438
T readData(TIter &iter, const traits::endian::Big &endian)
Same as readBig<T, TIter>()
Definition: access.h:766
void writeData(T value, TIter &iter, const traits::endian::Big &endian)
Same as writeBig<T, TIter>()
Definition: access.h:698
Main namespace for all classes / functions of COMMS library.
ErrorStatus
Error statuses reported by the Communication module.
Definition: ErrorStatus.h:17
constexpr unsigned version()
Version of the COMMS library as single numeric value.
Definition: version.h:64