Program Listing for File param_impl.h#

Return to documentation for file (support\param_impl.h)

[Sensor.ADAS]
[Sensor.Radar]
/********************************************************************************
 * Copyright (c) 2025-2026 Contributors to the Eclipse Foundation
 *
 * This program and the accompanying materials are made available under the
 * terms of the Apache License Version 2.0 which is available at
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Contributors:
 *   Erik Verhoeven - initial API and implementation
 ********************************************************************************/

#ifndef PARAM_IMPL_H
#define PARAM_IMPL_H

#include "../interfaces/param.h"
#include "interface_ptr.h"
#include <cstdint>
#include <map>
#include <string>
#include <type_traits>
#include <algorithm>
#include <memory>

namespace sdv
{
    // Forward declaration
    class CSdvParamMap;

    class CSdvParamInfo : private SParamInfo
    {
    public:
        template <typename TVar, typename TDefaultType>
        CSdvParamInfo(TVar& rtVar, const std::string& rssName, TDefaultType tDefaultVal, const std::string& rssUnit,
            const std::string& rssCategory, const std::string& rssDescription, uint32_t uiFlags);

        template <typename TVar, typename TDefaultType>
        CSdvParamInfo(TVar& rtVar, const std::string& rssName, TDefaultType tDefaultVal, const any_t& ranyLimitLow,
            bool bIncludeLow, const any_t& ranyLimitHigh, bool bIncludeHigh, const std::string& rssUnit,
            const std::string& rssCategory, const std::string& rssDescription, uint32_t uiFlags);

        template <typename TVar, typename TDefaultType>
        CSdvParamInfo(TVar& rtVar, const std::string& rssName, TDefaultType tDefaultVal, const std::string& rssPattern,
            const std::string& rssUnit, const std::string& rssCategory, const std::string& rssDescription, uint32_t uiFlags);

        template <typename TVar, typename TDefaultType>
        CSdvParamInfo(TVar& rtVar, const std::string& rssName, TDefaultType tDefaultVal,
            const sequence<SLabelInfo::SLabel>& rseqLabels, const std::string& rssCategory, const std::string& rssDescription,
            uint32_t uiFlags);

        CSdvParamInfo(const SParamInfo& rInfo);

        CSdvParamInfo(SParamInfo&& rInfo);

        virtual ~CSdvParamInfo() = default;

        CSdvParamInfo& operator=(const SParamInfo& rsInfo);

        CSdvParamInfo& operator=(SParamInfo&& rsInfo);

        virtual SParamInfo InfoStruct() const;

        const u8string& Name() const;

        u8string Path() const;

        const any_t& DefaultVal() const;

        const u8string& Group() const;

        const u8string& Description() const;

        const u8string& Unit() const;

        virtual uint32_t Flags() const;

        bool ReadOnly() const;

        bool Temporary() const;

        virtual bool Dirty() const;

        virtual bool Locked() const;

        bool Boolean() const;

        bool Numeric() const;

        bool String() const;

        bool Enum() const;

        bool Bitmask() const;

        std::pair<any_t, bool> NumericLimitLow() const;

        std::pair<any_t, bool> NumericLimitHigh() const;

        std::string StringPattern() const;

        sequence<SLabelInfo::SLabel> EnumBitmaskLabels() const;

    protected:
        template <typename TType>
        static constexpr bool TypeIsString();

        template <typename TType>
        static constexpr bool TypeIsReadOnly();

    private:
        void Init(EParamType eType, const std::string& rssName, const any_t& ranyDefaultVal, const std::string& rssUnit,
            const std::string& rssCategory, const std::string& rssDescription, uint32_t uiFlags);
    };

    namespace internal
    {
        class CParamGuardian : public CSdvParamInfo
        {
        public:
            template <typename... TInfoConstruct>
            CParamGuardian(bool bLockable, bool bAutoDirty, TInfoConstruct... tConstruct);

            virtual sdv::SParamInfo InfoStruct() const override;

            virtual uint32_t Flags() const override;

            bool UpdateDirty(const sdv::any_t& ranyValue);

            bool SetDirty();

            bool ResetDirty();

            virtual bool Dirty() const override;

            bool Lockable() const;

            bool Lock();

            bool Unlock();

            virtual bool Locked() const override;

            virtual bool Set(const any_t& ranyValue) = 0;

            virtual any_t Get() const = 0;

        protected:
            bool CheckRestrictions(const any_t& ranyValue);

        private:
            bool    m_bLockable = false;
            bool    m_bLocked = false;
            bool    m_bAutoDirty = false;
            bool    m_bDirty = false;
            any_t   m_anyStored;
        };

        template <typename TVar>
        class CParamValue : public CParamGuardian
        {
        public:
            template <typename... TInfoConstruct>
            CParamValue(TVar& rtVar, bool bLockable, bool bAutoDirty, TInfoConstruct... tConstruct);

            virtual bool Set(const any_t& ranyValue) override;

            virtual any_t Get() const override;

        private:
            TVar&   m_rtVar;
        };

        class CLabelMapHelper
        {
        public:
            void Clear()
            {
                m_mapLabelCollections.clear();
            }

            struct SLabelLocal
            {
                sdv::any_t  anyValue;
                std::string ssLabel;
            };

            template <typename TEnum>
            bool StoreLabelMap(const std::vector<SLabelLocal>& rseqLabels)
            {
                m_mapLabelCollections[typeid(TEnum).name()] = rseqLabels;
                return true;
            }

            template <typename TEnum>
            sequence<SLabelInfo::SLabel> GetLabelMap() const
            {
                using TEnumLocal = std::remove_reference_t<TEnum>;
                static const sequence<SLabelInfo::SLabel> seqEmpty;
                auto itEnum = m_mapLabelCollections.find(typeid(TEnumLocal).name());
                if (itEnum == m_mapLabelCollections.end())
                    return seqEmpty;

                // Create a copy pf the data using the SDV memory manager.
                sequence<SLabelInfo::SLabel> seqLabels;
                for (const SLabelLocal& rsLabel : itEnum->second)
                    seqLabels.push_back(SLabelInfo::SLabel{rsLabel.anyValue, rsLabel.ssLabel});

                return seqLabels;
            }

        private:
            std::map<std::string, std::vector<SLabelLocal>>    m_mapLabelCollections;
        };

        inline CLabelMapHelper& GetLabelMapHelper()
        {
            static CLabelMapHelper helper;
            return helper;
        }

        enum class ELimitType
        {
            up_to_limit,
            up_to_and_include_limit,
            no_limit
        };

        struct SLowerLimit
        {
            template <typename TType>
            std::pair<TType, ELimitType> operator>(TType tLimit) const
            {
                return std::make_pair(tLimit, ELimitType::up_to_limit);
            }

            template <typename TType>
            std::pair<TType, ELimitType> operator>=(TType tLimit) const
            {
                return std::make_pair(tLimit, ELimitType::up_to_and_include_limit);
            }

            std::pair<size_t, ELimitType> operator!=(size_t n) const
            {
                return std::make_pair(n, ELimitType::no_limit);
            }
        };

        struct SUpperLimit
        {
            template <typename TType>
            std::pair<TType, ELimitType> operator<(TType tLimit) const
            {
                return std::make_pair(tLimit, ELimitType::up_to_limit);
            }

            template <typename TType>
            std::pair<TType, ELimitType> operator<=(TType tLimit) const
            {
                return std::make_pair(tLimit, ELimitType::up_to_and_include_limit);
            }

            std::pair<size_t, ELimitType> operator!=(size_t n) const
            {
                return std::make_pair(n, ELimitType::no_limit);
            }
        };

        template <typename T>
        struct is_shared_ptr : std::false_type
        {};

        template <typename T>
        struct is_shared_ptr<std::shared_ptr<T>> : std::true_type
        {};

        template <typename T>
        inline constexpr bool is_shared_ptr_v = is_shared_ptr<T>::value;

        struct SMemberMapAccess
        {
            virtual std::shared_ptr<internal::CParamGuardian> FindParamObject(const sdv::u8string& rssName) = 0;

            virtual CSdvParamMap* Access() = 0;
            virtual const CSdvParamMap* Access() const = 0;
        };

        template <typename TMember>
        struct SMemberMap : SMemberMapAccess
        {
            static_assert(std::is_base_of_v<CSdvParamMap, TMember>, "The member type must derive from sdv::CSdvParamMap.");

            using TType = TMember;

            SMemberMap(TMember& rMember, sdv::CSdvParamMap* pEventObject) : m_pEventObject(pEventObject), refMember(rMember)
            {}

            virtual ~SMemberMap() = default;

            static std::vector<std::shared_ptr<sdv::CSdvParamInfo>> BuildStatic()
            {
                return TMember::BuildParamMap(nullptr, nullptr);
            }

            void BuildMap()
            {
                refMember.get().BuildParamMap(&refMember.get(), m_pEventObject);
            }

            virtual std::shared_ptr<internal::CParamGuardian> FindParamObject(const sdv::u8string& rssName) override
            {
                return refMember.get().FindParamObject(rssName);
            }

            virtual CSdvParamMap* Access() override
            {
                return &refMember.get();
            }
            virtual const CSdvParamMap* Access() const override
            {
                return &refMember.get();
            }
        private:
            sdv::CSdvParamMap*              m_pEventObject;
            std::reference_wrapper<TMember> refMember;
        };

        template <typename TMember>
        struct SMemberMap<TMember*> : SMemberMapAccess
        {
            static_assert(std::is_base_of_v<CSdvParamMap, TMember>, "The member type must derive from sdv::CSdvParamMap.");

            using TType = TMember;

            SMemberMap(TMember*& rpMember, sdv::CSdvParamMap* pEventObject) : m_pEventObject(pEventObject), refpMember(rpMember)
            {}

            virtual ~SMemberMap() = default;

            static std::vector<std::shared_ptr<sdv::CSdvParamInfo>> BuildStatic()
            {
                return TMember::BuildParamMap(nullptr, nullptr);
            }

            void BuildMap()
            {
                if (refpMember.get())
                    refpMember.get()->BuildParamMap(refpMember.get(), m_pEventObject);
            }

            virtual std::shared_ptr<internal::CParamGuardian> FindParamObject(const sdv::u8string& rssName) override
            {
                if (!refpMember.get()) return {};
                return refpMember.get()->FindParamObject(rssName);
            }

            virtual CSdvParamMap* Access() override
            {
                // In case a change has happened, or the member was not build previously...
                if (refpMember.get())
                    refpMember.get()->BuildParamMap(refpMember.get(), m_pEventObject);

                return refpMember.get();
            }
            virtual const CSdvParamMap* Access() const override
            {
                if (!refpMember.get()) return nullptr;

                // In case a change has happened, or the member was not build previously...
                if (refpMember.get())
                    refpMember.get()->BuildParamMap(refpMember.get(), m_pEventObject);

                return refpMember;
            }
        private:
            sdv::CSdvParamMap*      m_pEventObject;
            mutable std::reference_wrapper<TMember*> refpMember;
        };

        template <typename TMember>
        struct SMemberMap<std::shared_ptr<TMember>> : SMemberMapAccess
        {
            static_assert(std::is_base_of_v<CSdvParamMap, TMember>, "The member type must derive from sdv::CSdvParamMap.");

            using TType = TMember;

            // Warning of cppcheck 2.7 for missing m_pEventObject member variable instantiation. Suppress warning.
            // cppcheck-suppress uninitMemberVar
            SMemberMap(std::shared_ptr<TMember>& rptrMember, sdv::CSdvParamMap* pEventObject) :
                m_pEventObject(pEventObject), refptrMember(rptrMember)
            {}

            virtual ~SMemberMap() = default;

            static std::vector<std::shared_ptr<sdv::CSdvParamInfo>> BuildStatic()
            {
                return TMember::BuildParamMap(nullptr, nullptr);
            }

            void BuildMap()
            {
                if (refptrMember.get())
                    refptrMember.get()->BuildParamMap(refptrMember.get().get(), m_pEventObject);
            }

            virtual std::shared_ptr<internal::CParamGuardian> FindParamObject(const sdv::u8string& rssName) override
            {
                if (!refptrMember.get()) return {};
                return refptrMember.get()->FindParamObject(rssName);
            }

            virtual CSdvParamMap* Access() override
            {
                if (!refptrMember.get()) return nullptr;

                // In case a change has happened, or the member was not build previously...
                if (refptrMember.get())
                    refptrMember.get()->BuildParamMap(refptrMember.get().get(), m_pEventObject);

                return refptrMember.get().get();
            }
            virtual const CSdvParamMap* Access() const override
            {
                if (!refptrMember.get()) return nullptr;

                // In case a change has happened, or the member was not build previously...
                if (refptrMember.get())
                    refptrMember.get()->BuildParamMap(refptrMember.get().get(), m_pEventObject);

                return refptrMember.get().get();
            }
        private:
            sdv::CSdvParamMap*      m_pEventObject;
            mutable std::reference_wrapper<std::shared_ptr<TMember>> refptrMember;
        };
    } // namespace internal

#define SDV_CONCAT_IMPL(a, b) a##b

#define SDV_CONCAT(a, b) SDV_CONCAT_IMPL(a, b)

#define SDV_UNIQUE_VAR(prefix) SDV_CONCAT(prefix, __COUNTER__)

#define BEGIN_SDV_LABEL_MAP(enum_type)                                                                                             \
                                          \
    [[maybe_unused]] static inline bool SDV_UNIQUE_VAR(_bLabelMap) = sdv::internal::GetLabelMapHelper().StoreLabelMap<enum_type>({

#define SDV_LABEL_ENTRY(enum_element, name_string)                                                                                 \
            { static_cast<std::underlying_type_t<decltype(enum_element)>>(enum_element), name_string },

#define END_SDV_LABEL_MAP()                                                                                                        \
        });

#define BEGIN_SDV_PARAM_MAP()                                                                                                      \
                                                                                                                        \
        template <typename TClassPtr = std::nullptr_t>                                                                             \
        static std::vector<std::shared_ptr<sdv::CSdvParamInfo>> BuildParamMap([[maybe_unused]] TClassPtr pObject,                  \
            [[maybe_unused]] sdv::CSdvParamMap* pEventObject)                                                                      \
        {                                                                                                                          \
            bool constexpr bStatic = std::is_same_v<TClassPtr, std::nullptr_t>;                                                    \
            static_assert(bStatic || (std::is_pointer_v<TClassPtr> &&                                                              \
                    std::is_base_of_v<sdv::CSdvParamMap, std::remove_pointer_t<TClassPtr>>),                                       \
                "The class needs to derive from sdv::CSdvParamMap.");                                                              \
            if constexpr (!bStatic)                                                                                                \
            {                                                                                                                      \
                /* Build only if necessary */                                                                                      \
                if (!pObject->BuildNecessary()) return {};                                                                         \
            }                                                                                                                      \
            std::vector<std::shared_ptr<sdv::CSdvParamInfo>> vecParamInfo;                                                         \
            [[maybe_unused]] uint32_t uiFlags = 0;                                                                                 \
            [[maybe_unused]] std::string ssGroup;                                                                               \
            [[maybe_unused]] bool bLockable = false;

#define END_SDV_PARAM_MAP()                                                                                                        \
            return vecParamInfo;                                                                                                   \
        }                                                                                                                          \
                                                                                                                                   \
                                                                                                                        \
        static std::vector<std::shared_ptr<sdv::CSdvParamInfo>> GetParamMapInfoStatic()                                            \
        {                                                                                                                          \
            std::vector<std::shared_ptr<sdv::CSdvParamInfo>> vecParamInfo = BuildParamMap(nullptr, nullptr);                       \
            return vecParamInfo;                                                                                                   \
        }                                                                                                                          \
                                                                                                                                   \
                                                                                                                        \
        virtual void InitParamMap() override                                                                                       \
        {                                                                                                                          \
            BuildParamMap(this, this);                                                                                             \
        }


#define SDV_PARAM_GROUP(group_string)                                                                                              \
            ssGroup = group_string;                                                                                                 \


#define SDV_PARAM_NO_GROUP()                                                                                                       \
            ssGroup.clear();

#define SDV_PARAM_RESET_ATTRIBUTES()                                                                                               \
            uiFlags = 0;                                                                                                           \
            bLockable = false;

#define SDV_PARAM_SET_READONLY()                                                                                                   \
            uiFlags |= static_cast<uint32_t>(::sdv::EParamFlags::read_only);

#define SDV_PARAM_RESET_READONLY()                                                                                                 \
            uiFlags &= ~static_cast<uint32_t>(::sdv::EParamFlags::read_only);

#define SDV_PARAM_ENABLE_LOCKING()                                                                                                 \
            bLockable = true;

#define SDV_PARAM_DISABLE_LOCKING()                                                                                                \
            bLockable = false;

#define SDV_PARAM_SET_TEMPORARY()                                                                                                  \
            uiFlags |= static_cast<uint32_t>(::sdv::EParamFlags::temporary);

#define SDV_PARAM_RESET_TEMPORARY()                                                                                                \
            uiFlags &= ~static_cast<uint32_t>(::sdv::EParamFlags::temporary);

#define SDV_PARAM_ENTRY(var, name_string, default_val, unit_string, description_string)                                            \
    if constexpr (bStatic)                                                                                                         \
    {                                                                                                                              \
        decltype(var) temp{};                                                                                                      \
        std::shared_ptr<sdv::CSdvParamInfo> ptrParamInfo = std::make_shared<sdv::CSdvParamInfo>(temp, name_string, default_val,    \
            unit_string, ssGroup, description_string, uiFlags);                                                                    \
        if (ptrParamInfo) vecParamInfo.push_back(std::move(ptrParamInfo));                                                         \
    }                                                                                                                              \
    else                                                                                                                           \
    {                                                                                                                              \
        std::shared_ptr<sdv::CSdvParamInfo> ptrParamInfo = pObject->RegisterParameter(pObject->var, bLockable, true, name_string,  \
            default_val, unit_string, ssGroup, description_string, uiFlags);                                                       \
        if (ptrParamInfo) vecParamInfo.push_back(std::move(ptrParamInfo));                                                         \
    }

#define NO_LIMIT != 0

#define SDV_PARAM_NUMBER_ENTRY(var, name_string, default_val, low_limit, high_limit, unit_string, description_string)              \
    {                                                                                                                              \
        auto prLowLimit = sdv::internal::SLowerLimit() low_limit;                                                                  \
        sdv::any_t anyLower;                                                                                                       \
        if (prLowLimit.second != sdv::internal::ELimitType::no_limit) anyLower = prLowLimit.first;                                 \
        auto prHighLimit = sdv::internal::SUpperLimit() high_limit;                                                                \
        sdv::any_t anyUpper;                                                                                                       \
        if (prHighLimit.second != sdv::internal::ELimitType::no_limit) anyUpper = prHighLimit.first;                               \
        if constexpr (bStatic)                                                                                                     \
        {                                                                                                                          \
            decltype(var) temp{};                                                                                                  \
            std::shared_ptr<sdv::CSdvParamInfo> ptrParamInfo = std::make_shared<sdv::CSdvParamInfo>(temp, name_string,             \
                default_val, anyLower, prLowLimit.second != sdv::internal::ELimitType::up_to_limit, anyUpper,                      \
                prHighLimit.second != sdv::internal::ELimitType::up_to_limit, unit_string, ssGroup, description_string,            \
                uiFlags);                                                                                                          \
            if (ptrParamInfo) vecParamInfo.push_back(std::move(ptrParamInfo));                                                     \
        }                                                                                                                          \
        else                                                                                                                       \
        {                                                                                                                          \
            std::shared_ptr<sdv::CSdvParamInfo> ptrParamInfo = pObject->RegisterParameter(pObject->var, bLockable, true,           \
                name_string, default_val, anyLower, prLowLimit.second != sdv::internal::ELimitType::up_to_limit, anyUpper,         \
                prHighLimit.second != sdv::internal::ELimitType::up_to_limit, unit_string, ssGroup, description_string,            \
                uiFlags);                                                                                                          \
            if (ptrParamInfo)vecParamInfo.push_back(std::move(ptrParamInfo));                                                      \
        }                                                                                                                          \
    }

#define SDV_PARAM_ENUM_ENTRY(var, name_string, default_val, description_string)                                                    \
    SDV_PARAM_ENTRY(var, name_string, default_val, "", description_string)

#define SDV_PARAM_STRING_ENTRY(var, name_string, default_val, pattern_string, unit_string, description_string)                     \
    if constexpr (bStatic)                                                                                                         \
    {                                                                                                                              \
        decltype(var) temp{};                                                                                                      \
        std::shared_ptr<sdv::CSdvParamInfo> ptrParamInfo = std::make_shared<sdv::CSdvParamInfo>(temp, name_string, default_val,    \
            pattern_string, unit_string, ssGroup, description_string, uiFlags);                                                    \
        if (ptrParamInfo) vecParamInfo.push_back(std::move(ptrParamInfo));                                                         \
    }                                                                                                                              \
    else                                                                                                                           \
    {                                                                                                                              \
        std::shared_ptr<sdv::CSdvParamInfo> ptrParamInfo = pObject->RegisterParameter(pObject->var, bLockable, true, name_string,  \
            default_val, pattern_string, unit_string, ssGroup, description_string, uiFlags);                                       \
        if (ptrParamInfo) vecParamInfo.push_back(std::move(ptrParamInfo));                                                         \
    }

#define SDV_PARAM_PATH_ENTRY(var, name_string, default_val, description_string)                                                    \
    SDV_PARAM_ENTRY(var, name_string, default_val, "", description_string)

#define SDV_PARAM_BITMASK_ENTRY(TEnum, var, name_string, default_val, description_string)                                          \
    if constexpr (bStatic)                                                                                                         \
    {                                                                                                                              \
        decltype(var) temp{};                                                                                                      \
        std::shared_ptr<sdv::CSdvParamInfo> ptrParamInfo = std::make_shared<sdv::CSdvParamInfo>(temp, name_string, default_val,    \
            sdv::internal::GetLabelMapHelper().GetLabelMap<TEnum>(), ssGroup, description_string, uiFlags);                        \
        if (ptrParamInfo) vecParamInfo.push_back(std::move(ptrParamInfo));                                                         \
    }                                                                                                                              \
    else                                                                                                                           \
    {                                                                                                                              \
        std::shared_ptr<sdv::CSdvParamInfo> ptrParamInfo = pObject->RegisterParameter(pObject->var, bLockable, true, name_string,  \
            default_val, sdv::internal::GetLabelMapHelper().GetLabelMap<TEnum>(), ssGroup, description_string, uiFlags);           \
        if (ptrParamInfo) vecParamInfo.push_back(std::move(ptrParamInfo));                                                         \
    }

#define SDV_PARAM_CHAIN_BASE(base_class)                                                                                           \
    {                                                                                                                              \
        auto vecBaseParamInfo = base_class::BuildParamMap(pObject, pEventObject);                                                  \
        vecParamInfo.insert(vecParamInfo.end(), vecBaseParamInfo.begin(), vecBaseParamInfo.end());                                 \
    }

#define SDV_PARAM_CHAIN_MEMBER(member)                                                                                             \
    {                                                                                                                              \
        std::vector<std::shared_ptr<sdv::CSdvParamInfo>> vecParamInfoMember;                                                       \
        if constexpr (bStatic)                                                                                                     \
        {                                                                                                                          \
            vecParamInfoMember = sdv::internal::SMemberMap<decltype(member)>::BuildStatic();                                       \
        }                                                                                                                          \
        else                                                                                                                       \
        {                                                                                                                          \
            auto ptrMemberMap = std::make_shared<sdv::internal::SMemberMap<decltype(member)>>(pObject->member, pObject);           \
            if (ptrMemberMap)                                                                                                      \
            {                                                                                                                      \
                ptrMemberMap->BuildMap();                                                                                          \
                pObject->RegisterMemberMap(ptrMemberMap);                                                                          \
            }                                                                                                                      \
        }                                                                                                                          \
        vecParamInfo.insert(vecParamInfo.end(), vecParamInfoMember.begin(), vecParamInfoMember.end());                             \
    }

    class CSdvParamMap : public IParameters
    {
    public:

        virtual ~CSdvParamMap() = default;

        std::shared_ptr<internal::CParamGuardian> FindParamObject(const sdv::u8string& rssName);
        std::shared_ptr<const internal::CParamGuardian> FindParamObject(const sdv::u8string& rssName) const;
        virtual sequence<u8string> GetParamPaths() const override;

        virtual any_t GetParam(/*in*/ const u8string& ssPath) const override;

        virtual bool SetParam(/*in*/ const u8string& ssPath, /*in*/ any_t anyValue) override;

        virtual SParamInfo GetParamInfo(/*in*/ const u8string& ssPath) const override;

        virtual bool IsParamDirty(/*in*/ const u8string& ssPath) const override;

        void SetParamDirtyFlag(const std::string& rssPath);

        virtual void ResetParamDirtyFlag(/*in*/ const u8string& ssPath) override;

        virtual bool IsParamMapDirty() const override;

        virtual void ResetParamMapDirtyFlags() override;

        void LockParamMap();

        void UnlockParamMap();

        virtual void OnParamChanged([[maybe_unused]] const std::string& rssPath, [[maybe_unused]] const any_t& rvarOld,
            [[maybe_unused]] const any_t& rvarNew, [[maybe_unused]] const std::shared_ptr<CSdvParamInfo>& rptrParamInfo) {}

        virtual void OnParamFlagChanged([[maybe_unused]] const std::string& rssPath, [[maybe_unused]] uint32_t uiOldFlags,
            [[maybe_unused]] uint32_t uiNewFlags, [[maybe_unused]] uint32_t uiMask, [[maybe_unused]] const any_t& rvar,
            [[maybe_unused]] const std::shared_ptr<CSdvParamInfo>& rptrParamInfo) {}

    protected:
        template <typename TVar, typename... TConstruct>
        std::shared_ptr<CSdvParamInfo> RegisterParameter(TVar& rtVar, bool bLockable, bool bAutoDirty, TConstruct... tConstruct);

        void RegisterMemberMap(const std::shared_ptr<internal::SMemberMapAccess>& rptrMember);

        virtual void InitParamMap();

        bool BuildNecessary() const;

    public:
        static std::vector<std::shared_ptr<sdv::CSdvParamInfo>> GetParamMapInfoStatic()
        {
            return {};
        }

    private:

        struct SParamRegistration
        {
            template <typename TVar>
            SParamRegistration(const std::shared_ptr<internal::CParamValue<TVar>>& rptrParameter) :
                eType(EType::parameter), ptrParameter(rptrParameter)
            {}

            SParamRegistration(const std::shared_ptr<internal::SMemberMapAccess>& rptrMember) :
                eType(EType::member_map), ptrMemberMap(rptrMember)
            {}

            SParamRegistration(const SParamRegistration& rRegistration)
            {
                eType = rRegistration.eType;
                switch (rRegistration.eType)
                {
                case EType::parameter:
                    new (&ptrParameter) std::shared_ptr<internal::CParamGuardian>(rRegistration.ptrParameter);
                    break;
                case EType::member_map:
                    new (&ptrMemberMap) std::shared_ptr<internal::SMemberMapAccess>(rRegistration.ptrMemberMap);
                    break;
                }
            }

            SParamRegistration(SParamRegistration&& rRegistration)
            {
                eType = rRegistration.eType;
                switch (rRegistration.eType)
                {
                case EType::parameter:
                    new (&ptrParameter) std::shared_ptr<internal::CParamGuardian>(std::move(rRegistration.ptrParameter));
                    break;
                case EType::member_map:
                    new (&ptrMemberMap) std::shared_ptr<internal::SMemberMapAccess>(std::move(rRegistration.ptrMemberMap));
                    break;
                }
            }

            ~SParamRegistration()
            {
                switch (eType)
                {
                case EType::parameter:
                    ptrParameter.~shared_ptr();
                    break;
                case EType::member_map:
                    ptrMemberMap.~shared_ptr();
                    break;
                }
            }

            std::shared_ptr<internal::CParamGuardian> Parameter() const
            {
                if (eType == EType::parameter)
                    return ptrParameter;
                return {};
            }

            std::shared_ptr<internal::SMemberMapAccess> MemberMap() const
            {
                if (eType == EType::member_map)
                    return ptrMemberMap;
                return {};
            }

        private:
            enum class EType {parameter, member_map}        eType;
            union
            {
                std::shared_ptr<internal::CParamGuardian>   ptrParameter;
                std::shared_ptr<internal::SMemberMapAccess> ptrMemberMap;
            };
        };

        mutable std::vector<SParamRegistration>     m_vecParamMapRegistration;
    };
}; // namespace sdv

#include "param_impl.inl"

#endif // !defined PARAM_IMPL_H