12#include "comms/details/detect.h" 
   13#include "comms/details/tag.h" 
   15#include "comms/field/basic/CommonFuncs.h" 
   16#include "comms/field/details/VersionStorage.h" 
   21#include "comms/util/MaxSizeOf.h" 
   44template <
typename TStorage>
 
   45struct ArrayListMaxLengthRetrieveHelper
 
   47    static const std::size_t Value = CommonFuncs::maxSupportedLength();
 
   50template <
typename T, std::
size_t TSize>
 
   51struct ArrayListMaxLengthRetrieveHelper<
comms::util::StaticVector<T, TSize> >
 
   53    static const std::size_t Value = TSize;
 
   56template <std::
size_t TSize>
 
   57struct ArrayListMaxLengthRetrieveHelper<
comms::util::StaticString<TSize> >
 
   59    static const std::size_t Value = TSize - 1;
 
   62template <
typename TElem>
 
   63using ArrayListFieldHasVarLengthBoolType = 
 
   64    typename comms::util::LazyDeepConditional<
 
   65        std::is_integral<TElem>::value
 
   67        comms::util::FalseType,
 
   68        comms::util::FieldCheckVarLength,
 
   72template <
typename TElem>
 
   73using HasArrayListElemNonDefaultRefreshBoolType = 
 
   74    typename comms::util::LazyDeepConditional<
 
   75        std::is_integral<TElem>::value
 
   77        comms::util::FalseType,
 
   78        comms::util::FieldCheckNonDefaultRefresh,
 
   82template <
typename TElem>
 
   83using IsArrayListElemVersionDependentBoolType = 
 
   84    typename comms::util::LazyDeepConditional<
 
   85        std::is_integral<TElem>::value
 
   87        comms::util::FalseType,
 
   88        comms::util::FieldCheckVersionDependent,
 
   92template <
typename TFieldBase, 
typename TStorage>
 
   93using ArrayListVersionStorageBase = 
 
   94    typename comms::util::LazyShallowConditional<
 
   95        IsArrayListElemVersionDependentBoolType<typename TStorage::value_type>::value
 
   97        comms::field::details::VersionStorage,
 
   98        comms::util::EmptyStruct,
 
   99        typename TFieldBase::VersionType
 
  104template <
typename TFieldBase, 
typename TStorage>
 
  107        public details::ArrayListVersionStorageBase<TFieldBase, TStorage>
 
  109    using BaseImpl = TFieldBase;
 
  110    using VersionBaseImpl = details::ArrayListVersionStorageBase<TFieldBase, TStorage>;
 
  113    using Endian = 
typename BaseImpl::Endian;
 
  114    using VersionType = 
typename BaseImpl::VersionType;
 
  115    using ElementType = 
typename TStorage::value_type;
 
  116    using ValueType = TStorage;
 
  119            std::is_integral<ElementType>::value
 
  121            comms::field::tag::RawArrayList,
 
  122            comms::field::tag::ArrayList
 
  125    ArrayList() = 
default;
 
  127    explicit ArrayList(
const ValueType& val)
 
  132    explicit ArrayList(ValueType&& val)
 
  133      : m_value(
std::move(val))
 
  137    ArrayList(
const ArrayList&) = 
default;
 
  138    ArrayList(ArrayList&&) = 
default;
 
  139    ArrayList& operator=(
const ArrayList&) = 
default;
 
  140    ArrayList& operator=(ArrayList&&) = 
default;
 
  141    ~ArrayList() noexcept = default;
 
  143    const ValueType& value()
 const 
  153    const ValueType& getValue()
 const 
  158    template <
typename T>
 
  159    void setValue(T&& val)
 
  161        value() = std::forward<T>(val);
 
  164    ElementType& createBack()
 
  167        m_value.emplace_back();
 
  168        updateElemVersion(m_value.back(), VersionTag<>());
 
  169        return m_value.back();
 
  174        static_assert(comms::util::detect::hasClearFunc<ValueType>(),
 
  175            "The used storage type for ArrayList must have clear() member function");
 
  180    constexpr std::size_t length()
 const 
  182        return lengthInternal(ElemTag<>());
 
  185    static constexpr std::size_t minLength()
 
  190    static constexpr std::size_t maxLength()
 
  193            details::ArrayListMaxLengthRetrieveHelper<TStorage>::Value *
 
  194            maxLengthInternal(ElemTag<>());
 
  197    constexpr bool valid()
 const 
  199        return validInternal(ElemTag<>());
 
  204        return refreshInternal(ElemTag<>());
 
  207    static constexpr std::size_t minElementLength()
 
  209        return minElemLengthInternal(ElemTag<>());
 
  212    static constexpr std::size_t maxElementLength()
 
  214        return maxElemLengthInternal(ElemTag<>());
 
  217    static constexpr std::size_t elementLength(
const ElementType& elem)
 
  219        return elementLengthInternal(elem, ElemTag<>());
 
  222    template <
typename TIter>
 
  223    static ErrorStatus readElement(ElementType& elem, TIter& iter, std::size_t& len)
 
  225        return readElementInternal(elem, iter, len, ElemTag<>());
 
  228    template <
typename TIter>
 
  229    static void readElementNoStatus(ElementType& elem, TIter& iter)
 
  231        return readElementNoStatusInternal(elem, iter, ElemTag<>());
 
  234    template <
typename TIter>
 
  237        using IterType = 
typename std::decay<
decltype(iter)>::type;
 
  239            typename std::iterator_traits<IterType>::iterator_category;
 
  240        static const bool IsRandomAccessIter =
 
  241            std::is_base_of<std::random_access_iterator_tag, IterCategory>::value;
 
  242        static const bool IsRawData =
 
  243            std::is_integral<ElementType>::value && (
sizeof(ElementType) == 
sizeof(std::uint8_t));
 
  246            typename comms::util::LazyShallowConditional<
 
  247                IsRandomAccessIter && IsRawData
 
  252        return readInternal(iter, len, Tag());
 
  255    static constexpr bool hasReadNoStatus()
 
  260    template <
typename TIter>
 
  261    void readNoStatus(TIter& iter) = 
delete;
 
  263    template <
typename TIter>
 
  264    ErrorStatus readN(std::size_t count, TIter& iter, std::size_t& len)
 
  266        using IterType = 
typename std::decay<
decltype(iter)>::type;
 
  268            typename std::iterator_traits<IterType>::iterator_category;
 
  269        static const bool IsRandomAccessIter =
 
  270            std::is_base_of<std::random_access_iterator_tag, IterCategory>::value;
 
  271        static const bool IsRawData =
 
  272            std::is_integral<ElementType>::value && (
sizeof(ElementType) == 
sizeof(std::uint8_t));
 
  275            typename comms::util::LazyShallowConditional<
 
  276                IsRandomAccessIter && IsRawData
 
  282        return readInternalN(count, iter, len, Tag());
 
  285    template <
typename TIter>
 
  286    void readNoStatusN(std::size_t count, TIter& iter)
 
  288        using IterType = 
typename std::decay<
decltype(iter)>::type;
 
  290            typename std::iterator_traits<IterType>::iterator_category;
 
  291        static const bool IsRandomAccessIter =
 
  292            std::is_base_of<std::random_access_iterator_tag, IterCategory>::value;
 
  293        static const bool IsRawData =
 
  294            std::is_integral<ElementType>::value && (
sizeof(ElementType) == 
sizeof(std::uint8_t));
 
  297            typename comms::util::LazyShallowConditional<
 
  298                IsRandomAccessIter && IsRawData
 
  304        return readNoStatusInternalN(count, iter, Tag());
 
  307    static bool canWriteElement(
const ElementType& elem)
 
  309        return canWriteElementInternal(elem, ElemTag<>());
 
  312    template <
typename TIter>
 
  313    static ErrorStatus writeElement(
const ElementType& elem, TIter& iter, std::size_t& len)
 
  315        return writeElementInternal(elem, iter, len, ElemTag<>());
 
  318    template <
typename TIter>
 
  319    static void writeElementNoStatus(
const ElementType& elem, TIter& iter)
 
  321        return writeElementNoStatusInternal(elem, iter, ElemTag<>());
 
  324    bool canWrite()
 const 
  326        return CommonFuncs::canWriteSequence(*
this);
 
  329    template <
typename TIter>
 
  330    ErrorStatus write(TIter& iter, std::size_t len)
 const 
  332        return CommonFuncs::writeSequence(*
this, iter, len);
 
  335    static constexpr bool hasWriteNoStatus()
 
  337        return hasWriteNoStatusInternal(ElemTag<>());
 
  340    template <
typename TIter>
 
  341    void writeNoStatus(TIter& iter)
 const 
  343        CommonFuncs::writeSequenceNoStatus(*
this, iter);
 
  346    template <
typename TIter>
 
  347    ErrorStatus writeN(std::size_t count, TIter& iter, std::size_t& len)
 const 
  349        return CommonFuncs::writeSequenceN(*
this, count, iter, len);
 
  352    template <
typename TIter>
 
  353    void writeNoStatusN(std::size_t count, TIter& iter)
 const 
  355        CommonFuncs::writeSequenceNoStatusN(*
this, count, iter);
 
  358    static constexpr bool isVersionDependent()
 
  360        return details::IsArrayListElemVersionDependentBoolType<ElementType>::value;
 
  363    static constexpr bool hasNonDefaultRefresh()
 
  365        return details::HasArrayListElemNonDefaultRefreshBoolType<ElementType>::value;
 
  368    bool setVersion(VersionType 
version)
 
  370        return setVersionInternal(
version, VersionTag<>());
 
  374    template <
typename... TParams>
 
  375    using FieldElemTag = comms::details::tag::Tag1<>;
 
  377    template <
typename... TParams>
 
  378    using IntegralElemTag = comms::details::tag::Tag2<>;
 
  380    template <
typename... TParams>
 
  381    using FixedLengthTag = comms::details::tag::Tag3<>;
 
  383    template <
typename... TParams>
 
  384    using VarLengthTag = comms::details::tag::Tag4<>;
 
  386    template <
typename... TParams>
 
  387    using RawDataTag = comms::details::tag::Tag5<>;
 
  389    template <
typename... TParams>
 
  390    using VersionDependentTag = comms::details::tag::Tag6<>;    
 
  392    template <
typename... TParams>
 
  393    using NoVersionDependencyTag = comms::details::tag::Tag7<>;
 
  395    template <
typename... TParams>
 
  398            std::is_integral<ElementType>::value
 
  400            IntegralElemTag<TParams...>,
 
  401            FieldElemTag<TParams...>
 
  404    template <
typename... TParams>
 
  407            details::IsArrayListElemVersionDependentBoolType<ElementType>::value
 
  409            VersionDependentTag<TParams...>,
 
  410            NoVersionDependencyTag<TParams...>
 
  413    template <
typename... TParams>
 
  414    constexpr std::size_t lengthInternal(FieldElemTag<TParams...>)
 const 
  417            typename comms::util::LazyShallowConditional<
 
  418                details::ArrayListFieldHasVarLengthBoolType<ElementType>::value
 
  424        return fieldLength(Tag());
 
  427    template <
typename... TParams>
 
  428    constexpr std::size_t lengthInternal(IntegralElemTag<TParams...>)
 const 
  430        return m_value.size() * 
sizeof(ElementType);
 
  433    template <
typename... TParams>
 
  434    constexpr std::size_t fieldLength(FixedLengthTag<TParams...>)
 const 
  436        return ElementType().length() * m_value.size();
 
  439    template <
typename... TParams>
 
  440    std::size_t fieldLength(VarLengthTag<TParams...>)
 const 
  443            std::accumulate(m_value.begin(), m_value.end(), std::size_t(0),
 
  444                [](std::size_t sum, 
typename ValueType::const_reference e) -> std::size_t
 
  446                    return sum + e.length();
 
  450    template <
typename... TParams>
 
  451    static constexpr std::size_t maxLengthInternal(FieldElemTag<TParams...>)
 
  453        return ElementType::maxLength();
 
  456    template <
typename... TParams>
 
  457    static constexpr std::size_t maxLengthInternal(IntegralElemTag<TParams...>)
 
  459        return sizeof(ElementType);
 
  462    template <
typename TIter>
 
  463    static ErrorStatus readFieldElement(ElementType& elem, TIter& iter, std::size_t& len)
 
  465        auto fromIter = iter;
 
  466        auto es = elem.read(iter, len);
 
  468            auto diff = 
static_cast<std::size_t
>(std::distance(fromIter, iter));
 
  475    template <
typename TIter>
 
  476    static ErrorStatus readIntegralElement(ElementType& elem, TIter& iter, std::size_t& len)
 
  478        if (len < 
sizeof(ElementType)) {
 
  482        elem = comms::util::readData<ElementType>(iter,  
Endian());
 
  483        len -= 
sizeof(ElementType);
 
  487    template <
typename TIter, 
typename... TParams>
 
  488    static ErrorStatus readElementInternal(ElementType& elem, TIter& iter, std::size_t& len, FieldElemTag<TParams...>)
 
  490        return readFieldElement(elem, iter, len);
 
  493    template <
typename TIter, 
typename... TParams>
 
  494    static ErrorStatus readElementInternal(ElementType& elem, TIter& iter, std::size_t& len, IntegralElemTag<TParams...>)
 
  496        return readIntegralElement(elem, iter, len);
 
  499    template <
typename TIter>
 
  500    static void readNoStatusFieldElement(ElementType& elem, TIter& iter)
 
  502        elem.readNoStatus(iter);
 
  505    template <
typename TIter>
 
  506    static void readNoStatusIntegralElement(ElementType& elem, TIter& iter)
 
  508        elem = comms::util::readData<ElementType>(iter, 
Endian());
 
  511    template <
typename TIter, 
typename... TParams>
 
  512    static void readElementNoStatusInternal(ElementType& elem, TIter& iter, FieldElemTag<TParams...>)
 
  514        readNoStatusFieldElement(elem, iter);
 
  517    template <
typename TIter, 
typename... TParams>
 
  518    static void readElementNoStatusInternal(ElementType& elem, TIter& iter, IntegralElemTag<TParams...>)
 
  520        readElementNoStatusInternal(elem, iter);
 
  523    template <
typename TIter>
 
  524    static ErrorStatus writeFieldElement(
const ElementType& elem, TIter& iter, std::size_t& len)
 
  526        auto es = elem.write(iter, len);
 
  528            len -= elem.length();
 
  533    template <
typename TIter>
 
  534    static ErrorStatus writeIntegralElement(
const ElementType& elem, TIter& iter, std::size_t& len)
 
  536        if (len < 
sizeof(ElementType)) {
 
  540        BaseImpl::writeData(elem, iter);
 
  541        len -= 
sizeof(ElementType);
 
  545    template <
typename TIter, 
typename... TParams>
 
  546    static ErrorStatus writeElementInternal(
const ElementType& elem, TIter& iter, std::size_t& len, FieldElemTag<TParams...>)
 
  548        return writeFieldElement(elem, iter, len);
 
  551    template <
typename TIter, 
typename... TParams>
 
  552    static ErrorStatus writeElementInternal(
const ElementType& elem, TIter& iter, std::size_t& len, IntegralElemTag<TParams...>)
 
  554        return writeIntegralElement(elem, iter, len);
 
  557    template <
typename TIter>
 
  558    static void writeNoStatusFieldElement(
const ElementType& elem, TIter& iter)
 
  560        elem.writeNoStatus(iter);
 
  563    template <
typename TIter>
 
  564    static void writeNoStatusIntegralElement(
const ElementType& elem, TIter& iter)
 
  566        BaseImpl::writeData(elem, iter);
 
  569    template <
typename TIter, 
typename... TParams>
 
  570    static void writeElementNoStatusInternal(
const ElementType& elem, TIter& iter, FieldElemTag<TParams...>)
 
  572        return writeNoStatusFieldElement(elem, iter);
 
  575    template <
typename TIter, 
typename... TParams>
 
  576    static void writeElementNoStatusInternal(
const ElementType& elem, TIter& iter, IntegralElemTag<TParams...>)
 
  578        return writeNoStatusIntegralElement(elem, iter);
 
  581    template <
typename... TParams>
 
  582    constexpr bool validInternal(FieldElemTag<TParams...>)
 const 
  585            m_value.begin(), m_value.end(),
 
  586            [](
const ElementType& e) -> 
bool 
  592    template <
typename... TParams>
 
  593    static constexpr bool validInternal(IntegralElemTag<TParams...>)
 
  598    template <
typename... TParams>
 
  599    bool refreshInternal(FieldElemTag<TParams...>)
 
  603                m_value.begin(), m_value.end(), 
false,
 
  604                [](
bool prev, 
typename ValueType::reference elem) -> 
bool 
  606                    return elem.refresh() || prev;
 
  610    template <
typename... TParams>
 
  611    static constexpr bool refreshInternal(IntegralElemTag<TParams...>)
 
  616    template <
typename... TParams>
 
  617    static constexpr std::size_t minElemLengthInternal(IntegralElemTag<TParams...>)
 
  619        return sizeof(ElementType);
 
  622    template <
typename... TParams>
 
  623    static constexpr std::size_t minElemLengthInternal(FieldElemTag<TParams...>)
 
  625        return ElementType::minLength();
 
  628    template <
typename... TParams>
 
  629    static constexpr std::size_t maxElemLengthInternal(IntegralElemTag<TParams...>)
 
  631        return sizeof(ElementType);
 
  634    template <
typename... TParams>
 
  635    static constexpr std::size_t maxElemLengthInternal(FieldElemTag<TParams...>)
 
  637        return ElementType::maxLength();
 
  640    template <
typename... TParams>
 
  641    static constexpr std::size_t elementLengthInternal(
const ElementType&, IntegralElemTag<TParams...>)
 
  643        return sizeof(ElementType);
 
  646    template <
typename... TParams>
 
  647    static constexpr std::size_t elementLengthInternal(
const ElementType& elem, FieldElemTag<TParams...>)
 
  649        return elem.length();
 
  652    template <
typename TIter, 
typename... TParams>
 
  653    ErrorStatus readInternal(TIter& iter, std::size_t len, FieldElemTag<TParams...>)
 
  655        static_assert(comms::util::detect::hasClearFunc<ValueType>(),
 
  656            "The used storage type for ArrayList must have clear() member function");
 
  660            auto es = createAndReadNextElementInternal(iter, remLen);
 
  669    template <
typename TIter, 
typename... TParams>
 
  670    ErrorStatus readInternal(TIter& iter, std::size_t len, RawDataTag<TParams...>)
 
  673        std::advance(iter, len);
 
  677    template <
typename TIter, 
typename... TParams>
 
  678    ErrorStatus readInternalN(std::size_t count, TIter& iter, std::size_t len, FieldElemTag<TParams...>)
 
  682            auto es = createAndReadNextElementInternal(iter, len);
 
  693    template <
typename TIter, 
typename... TParams>
 
  694    ErrorStatus readInternalN(std::size_t count, TIter& iter, std::size_t len, RawDataTag<TParams...>)
 
  700        return readInternal(iter, count, RawDataTag<>());
 
  703    template <
typename TIter, 
typename... TParams>
 
  704    void readNoStatusInternalN(std::size_t count, TIter& iter, FieldElemTag<TParams...>)
 
  708            if (m_value.size() < m_value.max_size()) {
 
  709                auto& elem = createBack();
 
  710                readElementNoStatus(elem, iter);
 
  714                readElementNoStatus(elem, iter);
 
  720    template <
typename TIter, 
typename... TParams>
 
  721    void readNoStatusInternalN(std::size_t count, TIter& iter, RawDataTag<TParams...>)
 
  723        readInternal(iter, count, RawDataTag<>());
 
  726    template <
typename... TParams>
 
  727    bool updateElemVersion(ElementType& elem, VersionDependentTag<TParams...>)
 
  729        return elem.setVersion(VersionBaseImpl::m_version);
 
  732    template <
typename... TParams>
 
  733    static constexpr bool updateElemVersion(ElementType&, NoVersionDependencyTag<TParams...>)
 
  738    template <
typename... TParams>
 
  739    bool setVersionInternal(VersionType 
version, VersionDependentTag<TParams...>)
 
  741        VersionBaseImpl::m_version = 
version;
 
  742        bool updated = 
false;
 
  743        for (
auto& elem : value()) {
 
  744            updated = elem.setVersion(
version) || updated;
 
  750    template <
typename... TParams>
 
  751    static constexpr bool setVersionInternal(VersionType, NoVersionDependencyTag<TParams...>)
 
  756    template <
typename... TParams>
 
  757    static bool canWriteElementInternal(
const ElementType& elem, FieldElemTag<TParams...>)
 
  759        return elem.canWrite();
 
  762    template <
typename... TParams>
 
  763    static bool canWriteElementInternal(
const ElementType& elem, IntegralElemTag<TParams...>)
 
  765        static_cast<void>(elem);
 
  769    template <
typename... TParams>
 
  770    static constexpr bool hasWriteNoStatusInternal(FieldElemTag<TParams...>)
 
  772        return ElementType::hasWriteNoStatus();
 
  775    template <
typename... TParams>
 
  776    static constexpr bool hasWriteNoStatusInternal(IntegralElemTag<TParams...>)
 
  781    template <
typename TIter>
 
  784        if (m_value.size() < m_value.max_size()) {
 
  785            auto& elem = createBack();
 
  786            auto es = readElement(elem, iter, len);
 
  795        return readElement(elem, iter, len);
 
This file contains classes required for generic custom assertion functionality.
#define COMMS_ASSERT(expr)
Generic assert macro.
Definition Assert.h:170
Contains various compiler related definitions.
This file contain definition of error statuses used by comms module.
Contains comms::util::StaticString class.
Contains comms::util::StaticVector class.
Contains functions for raw data access / (de)serialization.
Provides helper assign() function to allow easy assignment of values to collections or views.
Contains definition of various tag classes.
comms::option::def::VersionType< T > VersionType
Same as comms::option::def::VersionType.
Definition options.h:1917
comms::option::def::Endian< TEndian > Endian
Same as comms::option::def::Endian.
Definition options.h:1460
void assign(T &obj, TIter from, TIter to)
Assigns a new value to provided object.
Definition assign.h:39
Main namespace for all classes / functions of COMMS library.
ErrorStatus
Error statuses reported by the Communication module.
Definition ErrorStatus.h:17
@ Success
Used to indicate successful outcome of the operation.
constexpr unsigned version()
Version of the COMMS library as single numeric value.
Definition version.h:64
Replacement to std::conditional.
Definition type_traits.h:29
Replacement to some types from standard type_traits.
Various compile-time detection functions of whether specific member functions and/or types exist.