COMMS
Template library intended to help with implementation of communication protocols.
IntValue.h
Go to the documentation of this file.
1 //
2 // Copyright 2015 - 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 <ratio>
14 #include <limits>
15 #include <type_traits>
16 
17 #include "comms/CompileControl.h"
18 #include "comms/ErrorStatus.h"
19 #include "comms/options.h"
20 #include "comms/util/type_traits.h"
21 #include "basic/IntValue.h"
22 #include "details/AdaptBasicField.h"
23 #include "comms/details/tag.h"
24 
25 COMMS_MSVC_WARNING_PUSH
26 COMMS_MSVC_WARNING_DISABLE(4127) // Disable warning about constant conditional expressions
27 
28 namespace comms
29 {
30 
31 namespace field
32 {
33 
70 template <typename TFieldBase, typename T, typename... TOptions>
71 class IntValue : public details::AdaptBasicFieldT<basic::IntValue<TFieldBase, T>, TOptions...>
72 {
73  using BaseImpl = details::AdaptBasicFieldT<basic::IntValue<TFieldBase, T>, TOptions...>;
74 public:
75 
77  using FieldBase = TFieldBase;
78 
80  using Endian = typename BaseImpl::Endian;
81 
84 
86  using ParsedOptions = details::OptionsParser<TOptions...>;
87 
89  using CommsTag = typename BaseImpl::CommsTag;
90 
93  using ValueType = typename BaseImpl::ValueType;
94 
97  using UnitsType = typename ParsedOptions::UnitsType;
98 
102 
105  using UnitsRatio = typename ParsedOptions::UnitsRatio;
106 
111 
114  IntValue() = default;
115 
117  explicit IntValue(const ValueType& val)
118  : BaseImpl(val)
119  {
120  }
121 
123  IntValue(const IntValue&) = default;
124 
126  ~IntValue() noexcept = default;
127 
129  IntValue& operator=(const IntValue&) = default;
130 
133  static constexpr bool hasFailOnInvalid()
134  {
135  return ParsedOptions::HasFailOnInvalid;
136  }
137 
140  static constexpr bool hasIgnoreInvalid()
141  {
142  return ParsedOptions::HasIgnoreInvalid;
143  }
144 
147  static constexpr bool hasEmptySerialization()
148  {
149  return ParsedOptions::HasEmptySerialization;
150  }
151 
154  static constexpr bool hasUnits()
155  {
156  return ParsedOptions::HasUnits;
157  }
158 
161  static constexpr bool hasScaling()
162  {
163  return ParsedOptions::HasScalingRatio && !std::is_same<ScalingRatio, std::ratio<1, 1> >::value;
164  }
165 
168  static constexpr bool hasFieldType()
169  {
170  return ParsedOptions::HasFieldType;
171  }
172 
175  static constexpr bool hasVarLength()
176  {
177  return ParsedOptions::HasVarLengthLimits;
178  }
179 
187  template <typename TRet>
188  constexpr TRet getScaled() const
189  {
190  using TagTmp =
191  typename comms::util::LazyShallowConditional<
192  ParsedOptions::HasScalingRatio
193  >::template Type<
194  HasScalingRatioTag,
195  NoScalingRatioTag
196  >;
197 
198  return scaleAsInternal<TRet>(TagTmp());
199  }
200 
202  template <typename TRet>
203  constexpr TRet scaleAs() const
204  {
205  return getScaled<TRet>();
206  }
207 
212  template <typename TScaled>
213  void setScaled(TScaled val)
214  {
215  using TagTmp =
216  typename comms::util::LazyShallowConditional<
217  ParsedOptions::HasScalingRatio
218  >::template Type<
219  HasScalingRatioTag,
220  NoScalingRatioTag
221  >;
222 
223  return setScaledInternal(val, TagTmp());
224  }
225 
227  const ValueType& value() const
228  {
229  return BaseImpl::value();
230  }
231 
234  {
235  return BaseImpl::value();
236  }
237 
240  const ValueType& getValue() const
241  {
242  return BaseImpl::getValue();
243  }
244 
247  template <typename U>
248  void setValue(U&& val)
249  {
250  BaseImpl::setValue(std::forward<U>(val));
251  }
252 
254  static constexpr ValueType maxValue()
255  {
256  return std::numeric_limits<ValueType>::max();
257  }
258 
260  static constexpr ValueType minValue()
261  {
262  return std::numeric_limits<ValueType>::min();
263  }
264 
267  constexpr std::size_t length() const
268  {
269  return BaseImpl::length();
270  }
271 
274  static constexpr std::size_t minLength()
275  {
276  return BaseImpl::minLength();
277  }
278 
281  static constexpr std::size_t maxLength()
282  {
283  return BaseImpl::maxLength();
284  }
285 
287  bool valid() const
288  {
289  return BaseImpl::valid();
290  }
291 
294  bool refresh()
295  {
296  return BaseImpl::refresh();
297  }
298 
304  template <typename TIter>
305  ErrorStatus read(TIter& iter, std::size_t size)
306  {
307  return BaseImpl::read(iter, size);
308  }
309 
312  static constexpr bool hasReadNoStatus()
313  {
314  return BaseImpl::hasReadNoStatus();
315  }
316 
322  template <typename TIter>
323  void readNoStatus(TIter& iter)
324  {
325  BaseImpl::readNoStatus(iter);
326  }
327 
329  bool canWrite() const
330  {
331  return BaseImpl::canWrite();
332  }
333 
339  template <typename TIter>
340  ErrorStatus write(TIter& iter, std::size_t size) const
341  {
342  return BaseImpl::write(iter, size);
343  }
344 
347  static constexpr bool hasWriteNoStatus()
348  {
349  return BaseImpl::hasWriteNoStatus();
350  }
351 
357  template <typename TIter>
358  void writeNoStatus(TIter& iter) const
359  {
360  BaseImpl::writeNoStatus(iter);
361  }
362 
364  static constexpr bool isVersionDependent()
365  {
366  return ParsedOptions::HasCustomVersionUpdate || BaseImpl::isVersionDependent();
367  }
368 
370  static constexpr bool hasNonDefaultRefresh()
371  {
372  return BaseImpl::hasNonDefaultRefresh();
373  }
374 
378  {
379  return BaseImpl::getVersion();
380  }
381 
385  {
386  return BaseImpl::setVersion(version);
387  }
388 
396  void setForcedLength(int len)
397  {
398  BaseImpl::setForcedLength(len);
399  }
400 
403  int getForcedLength() const
404  {
405  return BaseImpl::getForcedLength();
406  }
407 
408 protected:
409  using BaseImpl::readData;
410  using BaseImpl::writeData;
411 
412 private:
413  template <typename... TParams>
414  using HasScalingRatioTag = comms::details::tag::Tag1<>;
415 
416  template <typename... TParams>
417  using NoScalingRatioTag = comms::details::tag::Tag2<>;
418 
419  template <typename... TParams>
420  using ScaleAsFpTag = comms::details::tag::Tag3<>;
421 
422  template <typename... TParams>
423  using ScaleAsIntTag = comms::details::tag::Tag4<>;
424 
425  template <typename TRet, typename... TParams>
426  TRet scaleAsInternal(HasScalingRatioTag<TParams...>) const
427  {
428  using TagTmp =
429  typename comms::util::LazyShallowConditional<
430  std::is_floating_point<TRet>::value
431  >::template Type<
432  ScaleAsFpTag,
433  ScaleAsIntTag
434  >;
435 
436  return scaleAsInternal<TRet>(TagTmp());
437  }
438 
439  template <typename TRet, typename... TParams>
440  TRet scaleAsInternal(ScaleAsFpTag<TParams...>) const
441  {
442  static_assert(std::is_floating_point<TRet>::value,
443  "TRet is expected to be floating point type");
444  return static_cast<TRet>(BaseImpl::value()) * (static_cast<TRet>(ParsedOptions::ScalingRatio::num) / static_cast<TRet>(ParsedOptions::ScalingRatio::den));
445  }
446 
447  template <typename TRet, typename... TParams>
448  TRet scaleAsInternal(ScaleAsIntTag<TParams...>) const
449  {
450  static_assert(std::is_integral<TRet>::value,
451  "TRet is expected to be integral type");
452 
453  using CastType =
454  typename comms::util::Conditional<
455  std::is_signed<TRet>::value
456  >::template Type<
457  std::intmax_t,
458  std::uintmax_t
459  >;
460 
461  return
462  static_cast<TRet>(
463  (static_cast<CastType>(BaseImpl::value()) * ParsedOptions::ScalingRatio::num) / ParsedOptions::ScalingRatio::den);
464  }
465 
466  template <typename TRet, typename... TParams>
467  TRet scaleAsInternal(NoScalingRatioTag<TParams...>) const
468  {
469  return static_cast<TRet>(BaseImpl::value());
470  }
471 
472  template <typename TScaled, typename... TParams>
473  void setScaledInternal(TScaled val, HasScalingRatioTag<TParams...>)
474  {
475  using TagTmp =
476  typename comms::util::LazyShallowConditional<
477  std::is_floating_point<typename std::decay<decltype(val)>::type>::value
478  >::template Type<
479  ScaleAsFpTag,
480  ScaleAsIntTag
481  >;
482 
483  setScaledInternal(val, TagTmp());
484  }
485 
486  template <typename TScaled, typename... TParams>
487  void setScaledInternal(TScaled val, ScaleAsFpTag<TParams...>)
488  {
489  using DecayedType = typename std::decay<decltype(val)>::type;
490  auto epsilon = DecayedType(0);
491  if (ParsedOptions::ScalingRatio::num < ParsedOptions::ScalingRatio::den) {
492  epsilon = static_cast<DecayedType>(ParsedOptions::ScalingRatio::num) / static_cast<DecayedType>(ParsedOptions::ScalingRatio::den + 1);
493  }
494 
495  if (epsilon < DecayedType(0)) {
496  epsilon = -epsilon;
497  }
498 
499  if (val < DecayedType(0)) {
500  epsilon = -epsilon;
501  }
502 
503  BaseImpl::value() =
504  static_cast<ValueType>(
505  ((val + epsilon) * static_cast<DecayedType>(ParsedOptions::ScalingRatio::den)) / static_cast<DecayedType>(ParsedOptions::ScalingRatio::num));
506  }
507 
508  template <typename TScaled, typename... TParams>
509  void setScaledInternal(TScaled val, ScaleAsIntTag<TParams...>)
510  {
511  using CastType =
512  typename comms::util::Conditional<
513  std::is_signed<typename std::decay<decltype(val)>::type>::value
514  >::template Type<
515  std::intmax_t,
516  std::uintmax_t
517  >;
518 
519  BaseImpl::value() =
520  static_cast<ValueType>(
521  (static_cast<CastType>(val) * ParsedOptions::ScalingRatio::den) / static_cast<CastType>(ParsedOptions::ScalingRatio::num));
522  }
523 
524  template <typename TScaled, typename... TParams>
525  void setScaledInternal(TScaled val, NoScalingRatioTag<TParams...>)
526  {
527  BaseImpl::value() = static_cast<ValueType>(val);
528  }
529 
530  static_assert(!ParsedOptions::HasSequenceElemLengthForcing,
531  "comms::option::def::SequenceElemLengthForcingEnabled option is not applicable to IntValue field");
532  static_assert(!ParsedOptions::HasSequenceSizeForcing,
533  "comms::option::def::SequenceSizeForcingEnabled option is not applicable to IntValue field");
534  static_assert(!ParsedOptions::HasSequenceLengthForcing,
535  "comms::option::def::SequenceLengthForcingEnabled option is not applicable to IntValue field");
536  static_assert(!ParsedOptions::HasSequenceFixedSize,
537  "comms::option::def::SequenceFixedSize option is not applicable to IntValue field");
538  static_assert(!ParsedOptions::HasSequenceFixedSizeUseFixedSizeStorage,
539  "comms::option::app::SequenceFixedSizeUseFixedSizeStorage option is not applicable to IntValue field");
540  static_assert(!ParsedOptions::HasSequenceSizeFieldPrefix,
541  "comms::option::def::SequenceSizeFieldPrefix option is not applicable to IntValue field");
542  static_assert(!ParsedOptions::HasSequenceSerLengthFieldPrefix,
543  "comms::option::def::SequenceSerLengthFieldPrefix option is not applicable to IntValue field");
544  static_assert(!ParsedOptions::HasSequenceElemSerLengthFieldPrefix,
545  "comms::option::def::SequenceElemSerLengthFieldPrefix option is not applicable to IntValue field");
546  static_assert(!ParsedOptions::HasSequenceElemFixedSerLengthFieldPrefix,
547  "comms::option::def::SequenceElemSerLengthFixedFieldPrefix option is not applicable to IntValue field");
548  static_assert(!ParsedOptions::HasSequenceTrailingFieldSuffix,
549  "comms::option::def::SequenceTrailingFieldSuffix option is not applicable to IntValue field");
550  static_assert(!ParsedOptions::HasSequenceTerminationFieldSuffix,
551  "comms::option::def::SequenceTerminationFieldSuffix option is not applicable to IntValue field");
552  static_assert(!ParsedOptions::HasFixedSizeStorage,
553  "comms::option::app::FixedSizeStorage option is not applicable to IntValue field");
554  static_assert(!ParsedOptions::HasCustomStorageType,
555  "comms::option::app::CustomStorageType option is not applicable to IntValue field");
556  static_assert(!ParsedOptions::HasOrigDataView,
557  "comms::option::app::OrigDataView option is not applicable to IntValue field");
558  static_assert(!ParsedOptions::HasVersionsRange,
559  "comms::option::def::ExistsBetweenVersions (or similar) option is not applicable to IntValue field");
560  static_assert(!ParsedOptions::HasMissingOnReadFail,
561  "comms::option::def::MissingOnReadFail option is not applicable to IntValue field");
562  static_assert(!ParsedOptions::HasMissingOnInvalid,
563  "comms::option::def::MissingOnInvalid option is not applicable to IntValue field");
564 };
565 
566 
572 template <typename TFieldBase, typename T, typename... TOptions>
575  const IntValue<TFieldBase, T, TOptions...>& field2) noexcept
576 {
577  return field1.value() == field2.value();
578 }
579 
585 template <typename TFieldBase, typename T, typename... TOptions>
588  const IntValue<TFieldBase, T, TOptions...>& field2) noexcept
589 {
590  return field1.value() != field2.value();
591 }
592 
598 template <typename TFieldBase, typename T, typename... TOptions>
601  const IntValue<TFieldBase, T, TOptions...>& field2) noexcept
602 {
603  return field1.value() < field2.value();
604 }
605 
611 template <typename T>
612 constexpr bool isIntValue()
613 {
614  return std::is_same<typename T::CommsTag, tag::Int>::value;
615 }
616 
620 template <typename TFieldBase, typename T, typename... TOptions>
621 inline
622 IntValue<TFieldBase, T, TOptions...>&
624 {
625  return field;
626 }
627 
631 template <typename TFieldBase, typename T, typename... TOptions>
632 inline
633 const IntValue<TFieldBase, T, TOptions...>&
635 {
636  return field;
637 }
638 
639 } // namespace field
640 
641 } // namespace comms
642 
643 COMMS_MSVC_WARNING_POP
644 
Contains various compiler related definitions.
This file contain definition of error statuses used by comms module.
Field that represent integral value.
Definition: IntValue.h:72
static constexpr ValueType minValue()
Get minimal numeric value the field can hold.
Definition: IntValue.h:260
typename BaseImpl::ValueType ValueType
Type of underlying integral value.
Definition: IntValue.h:93
IntValue()=default
Default constructor.
static constexpr bool hasFieldType()
Compile time inquiry of whether comms::option::def::FieldType option has been used.
Definition: IntValue.h:168
details::OptionsParser< TOptions... > ParsedOptions
All the options provided to this class bundled into struct.
Definition: IntValue.h:86
void setScaled(TScaled val)
Opposite operation to getScaled().
Definition: IntValue.h:213
IntValue< TFieldBase, T, TOptions... > & toFieldBase(IntValue< TFieldBase, T, TOptions... > &field)
Upcast type of the field definition to its parent comms::field::IntValue type in order to have access...
Definition: IntValue.h:623
typename BaseImpl::CommsTag CommsTag
Tag indicating type of the field.
Definition: IntValue.h:89
~IntValue() noexcept=default
Destructor.
typename BaseImpl::VersionType VersionType
Version type.
Definition: IntValue.h:83
bool setVersion(VersionType version)
Default implementation of version update.
Definition: IntValue.h:384
typename ParsedOptions::FieldType FieldType
Type of actual extending field specified via comms::option::def::FieldType.
Definition: IntValue.h:110
IntValue(const IntValue &)=default
Copy constructor.
bool valid() const
Check validity of the field value.
Definition: IntValue.h:287
static constexpr bool hasScaling()
Compile time inquiry of whether scaling ratio has been provided via comms::option::def::ScalingRatio ...
Definition: IntValue.h:161
typename ParsedOptions::UnitsType UnitsType
Units type defined by any of the comms::option::def::Units* option.
Definition: IntValue.h:97
static constexpr bool hasWriteNoStatus()
Compile time check of whether the field has proper writeNoStatus() member function.
Definition: IntValue.h:347
int getForcedLength() const
Get forced serialization length.
Definition: IntValue.h:403
static constexpr bool hasIgnoreInvalid()
Compile time inquiry of whether comms::option::def::IgnoreInvalid option has been used.
Definition: IntValue.h:140
const IntValue< TFieldBase, T, TOptions... > & toFieldBase(const IntValue< TFieldBase, T, TOptions... > &field)
Upcast type of the field definition to its parent comms::field::IntValue type in order to have access...
Definition: IntValue.h:634
bool operator==(const IntValue< TFieldBase, T, TOptions... > &field1, const IntValue< TFieldBase, T, TOptions... > &field2) noexcept
Equality comparison operator.
Definition: IntValue.h:573
const ValueType & value() const
Get access to integral value storage.
Definition: IntValue.h:227
typename ParsedOptions::ScalingRatio ScalingRatio
Scaling ratio defined by the comms::option::def::ScalingRatio option.
Definition: IntValue.h:101
ValueType & value()
Get access to integral value storage.
Definition: IntValue.h:233
typename ParsedOptions::UnitsRatio UnitsRatio
Scaling ratio determined by the forced units via the comms::option::def::Units* option.
Definition: IntValue.h:105
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 bool hasEmptySerialization()
Compile time inquiry of whether comms::option::def::EmptySerialization option has been used.
Definition: IntValue.h:147
static constexpr std::size_t minLength()
Get minimal length that is required to serialise field of this type.
Definition: IntValue.h:274
bool operator<(const IntValue< TFieldBase, T, TOptions... > &field1, const IntValue< TFieldBase, T, TOptions... > &field2) noexcept
Equivalence comparison operator.
Definition: IntValue.h:599
TFieldBase FieldBase
Base class provided in the first template parameter.
Definition: IntValue.h:77
bool operator!=(const IntValue< TFieldBase, T, TOptions... > &field1, const IntValue< TFieldBase, T, TOptions... > &field2) noexcept
Non-equality comparison operator.
Definition: IntValue.h:586
static constexpr ValueType maxValue()
Get maximal numeric value the field can hold.
Definition: IntValue.h:254
static constexpr bool hasReadNoStatus()
Compile time check of whether the field has proper readNoStatus() member function.
Definition: IntValue.h:312
constexpr TRet getScaled() const
Scales value according to ratio specified in provided comms::option::def::ScalingRatio option.
Definition: IntValue.h:188
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
constexpr TRet scaleAs() const
Same as getScaled()
Definition: IntValue.h:203
ErrorStatus write(TIter &iter, std::size_t size) const
Write current field value to output data sequence.
Definition: IntValue.h:340
static constexpr bool hasNonDefaultRefresh()
Compile time check if this class has non-default refresh functionality.
Definition: IntValue.h:370
static constexpr bool hasUnits()
Compile time inquiry of whether units have been set via any of the comms::option::def::Units* options...
Definition: IntValue.h:154
typename BaseImpl::Endian Endian
Endian used for serialisation.
Definition: IntValue.h:80
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
IntValue(const ValueType &val)
Constructor.
Definition: IntValue.h:117
bool canWrite() const
Check of whether the field has a consistent value for writing.
Definition: IntValue.h:329
static constexpr bool hasVarLength()
Compile time inquiry of whether comms::option::def::VarLength option has been used.
Definition: IntValue.h:175
constexpr bool isIntValue()
Compile time check function of whether a provided type is any variant of comms::field::IntValue.
Definition: IntValue.h:612
comms::option::def::HasCustomVersionUpdate HasCustomVersionUpdate
Same as comms::option::def::HasCustomVersionUpdate.
Definition: options.h:1800
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
comms::option::def::ScalingRatio< TNum, TDenom > ScalingRatio
Same as comms::option::def::ScalingRatio.
Definition: options.h:1504
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
Contains definition of all the options used by the COMMS library.
Replacement to std::conditional.
Definition: type_traits.h:28
Replacement to some types from standard type_traits.