COMMS
Template library intended to help with implementation of communication protocols.
String.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 <vector>
14 
15 #include "comms/CompileControl.h"
16 
17 #if COMMS_HAS_CPP17_STRING_VIEW
18 #include <string_view>
19 #endif // #if COMMS_HAS_CPP17_STRING_VIEW
20 
21 #include "comms/ErrorStatus.h"
22 #include "comms/options.h"
24 #include "comms/util/StringView.h"
25 #include "comms/util/detect.h"
26 #include "comms/util/type_traits.h"
27 #include "comms/field/basic/String.h"
28 #include "comms/field/details/AdaptBasicField.h"
29 #include "comms/field/details/OptionsParser.h"
30 #include "comms/details/tag.h"
31 
32 namespace comms
33 {
34 
35 namespace field
36 {
37 
38 namespace details
39 {
40 
41 template <bool THasOrigDataViewStorage>
42 struct StringOrigDataViewStorageType;
43 
44 template <>
45 struct StringOrigDataViewStorageType<true>
46 {
47 #if COMMS_HAS_CPP17_STRING_VIEW
48  using Type = std::string_view;
49 #else // #if COMMS_HAS_CPP17_STRING_VIEW
50  using Type = comms::util::StringView;
51 #endif // #if COMMS_HAS_CPP17_STRING_VIEW
52 };
53 
54 template <>
55 struct StringOrigDataViewStorageType<false>
56 {
57  using Type = std::string;
58 };
59 
60 template <bool THasSequenceFixedSizeUseFixedSizeStorage>
61 struct StringFixedSizeUseFixedSizeStorageType;
62 
63 template <>
64 struct StringFixedSizeUseFixedSizeStorageType<true>
65 {
66  template <typename TOpt>
68 };
69 
70 template <>
71 struct StringFixedSizeUseFixedSizeStorageType<false>
72 {
73  template <typename TOpt>
74  using Type = typename StringOrigDataViewStorageType<TOpt::HasOrigDataView>::Type;
75 };
76 
77 template <bool THasFixedSizeStorage>
78 struct StringFixedSizeStorageType;
79 
80 template <>
81 struct StringFixedSizeStorageType<true>
82 {
83  template <typename TOpt>
85 };
86 
87 template <>
88 struct StringFixedSizeStorageType<false>
89 {
90  template <typename TOpt>
91  using Type = typename StringFixedSizeUseFixedSizeStorageType<TOpt::HasSequenceFixedSizeUseFixedSizeStorage>
92  ::template Type<TOpt>;
93 };
94 
95 template <bool THasCustomStorage>
96 struct StringCustomStringStorageType;
97 
98 template <>
99 struct StringCustomStringStorageType<true>
100 {
101  template <typename TOpt>
102  using Type = typename TOpt::CustomStorageType;
103 };
104 
105 template <>
106 struct StringCustomStringStorageType<false>
107 {
108  template <typename TOpt>
109  using Type =
110  typename StringFixedSizeStorageType<TOpt::HasFixedSizeStorage>::template Type<TOpt>;
111 };
112 
113 template <typename TOpt>
114 using StringStorageTypeT =
115  typename StringCustomStringStorageType<TOpt::HasCustomStorageType>::template Type<TOpt>;
116 
117 template <typename TFieldBase, typename... TOptions>
118 using StringBase =
119  AdaptBasicFieldT<
120  basic::String<TFieldBase, StringStorageTypeT<OptionsParser<TOptions...> > >,
121  TOptions...
122  >;
123 
124 } // namespace details
125 
157 template <typename TFieldBase, typename... TOptions>
158 class String : public details::StringBase<TFieldBase, TOptions...>
159 {
160  using BaseImpl = details::StringBase<TFieldBase, TOptions...>;
161 public:
163  using FieldBase = TFieldBase;
164 
166  using Endian = typename BaseImpl::Endian;
167 
170 
172  using ParsedOptions = details::OptionsParser<TOptions...>;
173 
175  using CommsTag = typename BaseImpl::CommsTag;
176 
182  using ValueType = typename BaseImpl::ValueType;
183 
188 
192 
196 
200 
204 
206  String() = default;
207 
209  explicit String(const ValueType& val)
210  : BaseImpl(val)
211  {
212  }
213 
215  explicit String(ValueType&& val)
216  : BaseImpl(std::move(val))
217  {
218  }
219 
221  explicit String(const char* str)
222  {
223  setValue(str);
224  }
225 
227  String(const String&) = default;
228 
230  String(String&&) = default;
231 
233  ~String() noexcept = default;
234 
236  String& operator=(const String&) = default;
237 
239  String& operator=(String&&) = default;
240 
243  static constexpr bool hasFailOnInvalid()
244  {
245  return ParsedOptions::HasFailOnInvalid;
246  }
247 
250  static constexpr bool hasIgnoreInvalid()
251  {
252  return ParsedOptions::HasIgnoreInvalid;
253  }
254 
257  static constexpr bool hasEmptySerialization()
258  {
259  return ParsedOptions::HasEmptySerialization;
260  }
261 
264  static constexpr bool hasFieldType()
265  {
266  return ParsedOptions::HasFieldType;
267  }
268 
271  static constexpr bool hasSizeFieldPrefix()
272  {
273  return ParsedOptions::HasSequenceSizeFieldPrefix;
274  }
275 
278  static constexpr bool hasSerLengthFieldPrefix()
279  {
280  return ParsedOptions::HasSequenceSerLengthFieldPrefix;
281  }
282 
285  static constexpr bool hasTerminationFieldSuffix()
286  {
287  return ParsedOptions::HasSequenceTerminationFieldSuffix;
288  }
289 
292  static constexpr bool hasTrailingFieldSuffix()
293  {
294  return ParsedOptions::HasSequenceTrailingFieldSuffix;
295  }
296 
299  static constexpr bool hasFixedSize()
300  {
301  return ParsedOptions::HasSequenceFixedSize;
302  }
303 
307  static constexpr bool fixedSize()
308  {
310  }
311 
322  template <typename TIter>
323  ErrorStatus read(TIter& iter, std::size_t len)
324  {
325  auto es = BaseImpl::read(iter, len);
326  using TagTmp =
327  typename comms::util::LazyShallowConditional<
328  ParsedOptions::HasSequenceFixedSize
329  >::template Type<
330  AdjustmentNeededTag,
331  NoAdjustmentTag
332  >;
333 
334  adjustValue(TagTmp());
335  return es;
336  }
337 
340  static constexpr bool hasReadNoStatus()
341  {
342  return BaseImpl::hasReadNoStatus();
343  }
344 
350  template <typename TIter>
351  void readNoStatus(TIter& iter)
352  {
353  BaseImpl::readNoStatus(iter);
354  using TagTmp =
355  typename comms::util::LazyShallowConditional<
356  ParsedOptions::HasSequenceFixedSize
357  >::template Type<
358  AdjustmentNeededTag,
359  NoAdjustmentTag
360  >;
361 
362  adjustValue(TagTmp());
363  }
364 
367  {
368  return BaseImpl::value();
369  }
370 
372  const ValueType& value() const
373  {
374  return BaseImpl::value();
375  }
376 
379  const ValueType& getValue() const
380  {
381  return BaseImpl::getValue();
382  }
383 
386  template <typename U>
387  void setValue(U&& val)
388  {
389  BaseImpl::setValue(std::forward<U>(val));
390  }
391 
393  std::size_t length() const
394  {
395  return BaseImpl::length();
396  }
397 
399  bool valid() const
400  {
401  return BaseImpl::valid();
402  }
403 
406  bool refresh()
407  {
408  return BaseImpl::refresh();
409  }
410 
412  bool canWrite() const
413  {
414  return BaseImpl::canWrite();
415  }
416 
429  template <typename TIter>
430  ErrorStatus write(TIter& iter, std::size_t len) const
431  {
432  return BaseImpl::write(iter, len);
433  }
434 
437  static constexpr bool hasWriteNoStatus()
438  {
439  return BaseImpl::hasWriteNoStatus();
440  }
441 
447  template <typename TIter>
448  void writeNoStatus(TIter& iter) const
449  {
450  BaseImpl::writeNoStatus(iter);
451  }
452 
454  static constexpr std::size_t minLength()
455  {
456  return BaseImpl::minLength();
457  }
458 
460  static constexpr std::size_t maxLength()
461  {
462  return BaseImpl::maxLength();
463  }
464 
470  void forceReadElemCount(std::size_t count)
471  {
472  BaseImpl::forceReadElemCount(count);
473  }
474 
480  {
481  BaseImpl::clearReadElemCount();
482  }
483 
488  void forceReadLength(std::size_t count)
489  {
490  return BaseImpl::forceReadLength(count);
491  }
492 
498  {
499  return BaseImpl::clearReadLengthForcing();
500  }
501 
503  static constexpr bool isVersionDependent()
504  {
505  return ParsedOptions::HasCustomVersionUpdate || BaseImpl::isVersionDependent();
506  }
507 
509  static constexpr bool hasNonDefaultRefresh()
510  {
511  return BaseImpl::hasNonDefaultRefresh();
512  }
513 
517  {
518  return BaseImpl::getVersion();
519  }
520 
524  {
525  return BaseImpl::setVersion(version);
526  }
527 
528 protected:
529  using BaseImpl::readData;
530  using BaseImpl::writeData;
531 
532 private:
533  template <typename... TParams>
534  using NoAdjustmentTag = comms::details::tag::Tag1<>;
535 
536  template <typename... TParams>
537  using AdjustmentNeededTag = comms::details::tag::Tag2<>;
538 
539  template <typename... TParams>
540  using HasResizeTag = comms::details::tag::Tag3<>;
541 
542  template <typename... TParams>
543  using HasRemoveSuffixTag = comms::details::tag::Tag4<>;
544 
545  template <typename... TParams>
546  void adjustValue(NoAdjustmentTag<TParams...>)
547  {
548  }
549 
550  template <typename... TParams>
551  void adjustValue(AdjustmentNeededTag<TParams...>)
552  {
553  std::size_t count = 0;
554  for (auto iter = BaseImpl::value().begin(); iter != BaseImpl::value().end(); ++iter) {
555  if (*iter == 0) {
556  break;
557  }
558  ++count;
559  }
560 
561  doResize(count);
562  }
563 
564  void doResize(std::size_t count)
565  {
566  using TagTmp =
567  typename comms::util::Conditional<
568  comms::util::detect::hasResizeFunc<ValueType>()
569  >::template Type<
570  HasResizeTag<>,
571  typename comms::util::Conditional<
572  comms::util::detect::hasRemoveSuffixFunc<ValueType>()
573  >::template Type<
574  HasRemoveSuffixTag<>,
575  void
576  >
577  >;
578 
579  static_assert(!std::is_void<TagTmp>::value,
580  "The string storage value type must have either resize() or remove_suffix() "
581  "member functions");
582  doResize(count, TagTmp());
583  }
584 
585  template <typename... TParams>
586  void doResize(std::size_t count, HasResizeTag<TParams...>)
587  {
588  BaseImpl::value().resize(count);
589  }
590 
591  template <typename... TParams>
592  void doResize(std::size_t count, HasRemoveSuffixTag<TParams...>)
593  {
594  BaseImpl::value().remove_suffix(BaseImpl::value().size() - count);
595  }
596 
597  static_assert(!ParsedOptions::HasSerOffset,
598  "comms::option::def::NumValueSerOffset option is not applicable to String field");
599  static_assert(!ParsedOptions::HasFixedLengthLimit,
600  "comms::option::def::FixedLength option is not applicable to String field");
601  static_assert(!ParsedOptions::HasFixedBitLengthLimit,
602  "comms::option::def::FixedBitLength option is not applicable to String field");
603  static_assert(!ParsedOptions::HasVarLengthLimits,
604  "comms::option::def::VarLength option is not applicable to String field");
605  static_assert(!ParsedOptions::HasAvailableLengthLimit,
606  "comms::option::def::AvailableLengthLimit option is not applicable to String field");
607  static_assert(!ParsedOptions::HasScalingRatio,
608  "comms::option::def::ScalingRatio option is not applicable to String field");
609  static_assert(!ParsedOptions::HasUnits,
610  "comms::option::def::Units option is not applicable to String field");
611  static_assert(!ParsedOptions::HasMultiRangeValidation,
612  "comms::option::def::ValidNumValueRange (or similar) option is not applicable to String field");
613  static_assert(!ParsedOptions::HasSequenceElemSerLengthFieldPrefix,
614  "comms::option::def::SequenceElemSerLengthFieldPrefix option is not applicable to String field");
615  static_assert(!ParsedOptions::HasSequenceElemFixedSerLengthFieldPrefix,
616  "comms::option::def::SequenceElemSerLengthFixedFieldPrefix option is not applicable to String field");
617  static_assert(!ParsedOptions::HasVersionsRange,
618  "comms::option::def::ExistsBetweenVersions (or similar) option is not applicable to String field");
619  static_assert(!ParsedOptions::HasMissingOnReadFail,
620  "comms::option::def::MissingOnReadFail option is not applicable to String field");
621  static_assert(!ParsedOptions::HasMissingOnInvalid,
622  "comms::option::def::MissingOnInvalid option is not applicable to String field");
623 };
624 
630 template <typename TFieldBase, typename... TOptions>
632  const String<TFieldBase, TOptions...>& field1,
633  const String<TFieldBase, TOptions...>& field2) noexcept
634 {
635  return field1.value() == field2.value();
636 }
637 
643 template <typename TFieldBase, typename... TOptions>
645  const String<TFieldBase, TOptions...>& field1,
646  const String<TFieldBase, TOptions...>& field2) noexcept
647 {
648  return field1.value() != field2.value();
649 }
650 
657 template <typename TFieldBase, typename... TOptions>
659  const String<TFieldBase, TOptions...>& field1,
660  const String<TFieldBase, TOptions...>& field2) noexcept
661 {
662  return field1.value() < field2.value();
663 }
664 
670 template <typename T>
671 constexpr bool isString()
672 {
673  return std::is_same<typename T::CommsTag, tag::String>::value;
674 }
675 
679 template <typename TFieldBase, typename... TOptions>
680 inline
681 String<TFieldBase, TOptions...>&
683 {
684  return field;
685 }
686 
690 template <typename TFieldBase, typename... TOptions>
691 inline
692 const String<TFieldBase, TOptions...>&
694 {
695  return field;
696 }
697 
698 } // namespace field
699 
700 } // namespace comms
701 
702 
Contains various compiler related definitions.
This file contain definition of error statuses used by comms module.
Contains comms::util::StaticString class.
Contains comms::util::StringView class.
Field that represents a string.
Definition: String.h:159
TFieldBase FieldBase
Base class provided in the first template parameter.
Definition: String.h:163
typename ParsedOptions::SequenceTrailingFieldSuffix TrailingFieldSuffix
Type of trailing field suffix specified via comms::option::def::SequenceTrailingFieldSuffix.
Definition: String.h:203
ValueType & value()
Get access to the value storage.
Definition: String.h:366
static constexpr bool hasFailOnInvalid()
Compile time inquiry of whether comms::option::def::FailOnInvalid option has been used.
Definition: String.h:243
String(const ValueType &val)
Constructor.
Definition: String.h:209
constexpr bool isString()
Compile time check function of whether a provided type is any variant of comms::field::String.
Definition: String.h:671
typename ParsedOptions::FieldType FieldType
Type of actual extending field specified via comms::option::def::FieldType.
Definition: String.h:187
static constexpr bool hasTerminationFieldSuffix()
Compile time inquiry of whether comms::option::def::SequenceTerminationFieldSuffix option has been us...
Definition: String.h:285
static constexpr bool hasWriteNoStatus()
Compile time check of whether the field has proper writeNoStatus() member function.
Definition: String.h:437
static constexpr bool hasFieldType()
Compile time inquiry of whether comms::option::def::FieldType option has been used.
Definition: String.h:264
typename ParsedOptions::SequenceTerminationFieldSuffix TerminationFieldSuffix
Type of termination field suffix specified via comms::option::def::SequenceTerminationFieldSuffix.
Definition: String.h:199
typename ParsedOptions::SequenceSerLengthFieldPrefix SerLengthFieldPrefix
Type of length field prefix specified via comms::option::def::SequenceSerLengthFieldPrefix.
Definition: String.h:195
static constexpr std::size_t minLength()
Get minimal length that is required to serialise field of this type.
Definition: String.h:454
ErrorStatus read(TIter &iter, std::size_t len)
Read field value from input data sequence.
Definition: String.h:323
const ValueType & value() const
Get access to the value storage.
Definition: String.h:372
static constexpr bool hasSerLengthFieldPrefix()
Compile time inquiry of whether comms::option::def::SequenceSerLengthFieldPrefix option has been used...
Definition: String.h:278
~String() noexcept=default
Destructor.
void forceReadElemCount(std::size_t count)
Force number of characters that must be read in the next read() invocation.
Definition: String.h:470
void setValue(U &&val)
Set value.
Definition: String.h:387
bool operator!=(const String< TFieldBase, TOptions... > &field1, const String< TFieldBase, TOptions... > &field2) noexcept
Non-equality comparison operator.
Definition: String.h:644
bool canWrite() const
Check of whether the field has a consistent value for writing.
Definition: String.h:412
static constexpr bool hasSizeFieldPrefix()
Compile time inquiry of whether comms::option::def::SequenceSizeFieldPrefix option has been used.
Definition: String.h:271
VersionType getVersion() const
Get version of the field.
Definition: String.h:516
void forceReadLength(std::size_t count)
Force available length for the next read() invocation.
Definition: String.h:488
bool setVersion(VersionType version)
Default implementation of version update.
Definition: String.h:523
ErrorStatus write(TIter &iter, std::size_t len) const
Write current field value to output data sequence.
Definition: String.h:430
static constexpr bool hasIgnoreInvalid()
Compile time inquiry of whether comms::option::def::IgnoreInvalid option has been used.
Definition: String.h:250
void clearReadElemCount()
Clear forcing of the number of characters that must be read in the next read() invocation.
Definition: String.h:479
bool operator<(const String< TFieldBase, TOptions... > &field1, const String< TFieldBase, TOptions... > &field2) noexcept
Equivalence comparison operator.
Definition: String.h:658
typename BaseImpl::CommsTag CommsTag
Tag indicating type of the field.
Definition: String.h:175
static constexpr bool hasReadNoStatus()
Compile time check of whether the field has proper readNoStatus() member function.
Definition: String.h:340
typename BaseImpl::ValueType ValueType
Type of underlying value.
Definition: String.h:182
bool valid() const
Check validity of the field value.
Definition: String.h:399
static constexpr bool hasFixedSize()
Compile time inquiry of whether comms::option::def::SequenceFixedSize option has been used.
Definition: String.h:299
String< TFieldBase, TOptions... > & toFieldBase(String< TFieldBase, TOptions... > &field)
Upcast type of the field definition to its parent comms::field::String type in order to have access t...
Definition: String.h:682
bool refresh()
Refresh the field's value.
Definition: String.h:406
String(const char *str)
Constructor.
Definition: String.h:221
const ValueType & getValue() const
Get value.
Definition: String.h:379
String()=default
Default constructor.
typename BaseImpl::VersionType VersionType
Version type.
Definition: String.h:169
String(String &&)=default
Move constructor.
std::size_t length() const
Get length of serialised data.
Definition: String.h:393
details::OptionsParser< TOptions... > ParsedOptions
All the options provided to this class bundled into struct.
Definition: String.h:172
static constexpr bool hasEmptySerialization()
Compile time inquiry of whether comms::option::def::EmptySerialization option has been used.
Definition: String.h:257
typename BaseImpl::Endian Endian
Endian used for serialisation.
Definition: String.h:166
String(const String &)=default
Copy constructor.
const String< TFieldBase, TOptions... > & toFieldBase(const String< TFieldBase, TOptions... > &field)
Upcast type of the field definition to its parent comms::field::String type in order to have access t...
Definition: String.h:693
static constexpr bool hasNonDefaultRefresh()
Compile time check if this class has non-default refresh functionality.
Definition: String.h:509
String(ValueType &&val)
Constructor.
Definition: String.h:215
typename ParsedOptions::SequenceSizeFieldPrefix SizeFieldPrefix
Type of size field prefix specified via comms::option::def::SequenceSizeFieldPrefix.
Definition: String.h:191
void clearReadLengthForcing()
Clear forcing of the available length in the next read() invocation.
Definition: String.h:497
static constexpr bool hasTrailingFieldSuffix()
Compile time inquiry of whether comms::option::def::SequenceTrailingFieldSuffix option has been used.
Definition: String.h:292
void writeNoStatus(TIter &iter) const
Write current field value to output data sequence without error check and status report.
Definition: String.h:448
static constexpr std::size_t maxLength()
Get maximal length that is required to serialise field of this type.
Definition: String.h:460
void readNoStatus(TIter &iter)
Read field value from input data sequence without error check and status report.
Definition: String.h:351
bool operator==(const String< TFieldBase, TOptions... > &field1, const String< TFieldBase, TOptions... > &field2) noexcept
Equality comparison operator.
Definition: String.h:631
static constexpr bool isVersionDependent()
Compile time check if this class is version dependent.
Definition: String.h:503
static constexpr bool fixedSize()
Compile time inquiry of fixed size provided via comms::option::def::SequenceFixedSize option.
Definition: String.h:307
Replacement to std::string when no dynamic memory allocation is allowed.
Definition: StaticString.h:789
Describes an object that can refer to a constant contiguous sequence of char-like objects with the fi...
Definition: StringView.h:35
comms::option::def::SequenceTrailingFieldSuffix< TField > SequenceTrailingFieldSuffix
Same as comms::option::def::SequenceTrailingFieldSuffix.
Definition: options.h:1531
comms::option::def::SequenceTerminationFieldSuffix< TField > SequenceTerminationFieldSuffix
Same as comms::option::def::SequenceTerminationFieldSuffix.
Definition: options.h:1527
comms::option::def::SequenceSerLengthFieldPrefix< TField, TReadErrorStatus > SequenceSerLengthFieldPrefix
Same as comms::option::def::SequenceSerLengthFieldPrefix.
Definition: options.h:1513
comms::option::def::SequenceFixedSize< TSize > SequenceFixedSize
Same as comms::option::def::SequenceFixedSize.
Definition: options.h:1544
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::app::CustomStorageType< TType > CustomStorageType
Same as comms::option::app::CustomStorageType.
Definition: options.h:1891
comms::option::def::Endian< TEndian > Endian
Same as comms::option::def::Endian.
Definition: options.h:1438
comms::option::def::SequenceSizeFieldPrefix< TField > SequenceSizeFieldPrefix
Same as comms::option::def::SequenceSizeFieldPrefix.
Definition: options.h:1508
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.
Various compile-time detection functions of whether specific member functions and/or types exist.