/******************************************************************************** * Copyright (c) 2025-2026 ZF Friedrichshafen AG * * 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 ENTITIY_VALUE_H #define ENTITIY_VALUE_H #include "entity_base.h" #include "../constvariant.h" #include "../token.h" #include "../tokenlist.h" #include #include // Forward declarations class CDeclarationEntity; /** * @brief The entity value node base class. * @details Entity values form a value tree made of all the values that are part of one assignment. Each value has its special * value grammar when used in a assignment. All entities have their own personal linked list, which can be formed from other * entities when they are defined as type of a declaration. Variable declarations can also be part of a larger linked list. Arrays * form their own links within the linked list * Examples: * @code * // Value tree for i: CSimpleTypeValueNode assigning the value 10. * int32 i = 10; * * // Value tree for S1: CCompoundTypeValueNode with child CSimpleTypeValueNode assigning the value 20. * struct S1 * { * const int32 m_i1 = 10; // Value node for m_i1: CSimpleTypeValueNode assigning the value 10. * int32 m_i2 = 20; // Part of the value tree of S1. * }; * * // Value tree for s1: sub-tree of S1 assigning the value 200 to m_i2. * S1 s1 = {200}; * * // Value tree for S2: CCompoundTypeValueNode with children sub-tree of S1 and CSimpleTypeValueNode assigning the value 5. * struct S2 : S1 * { * int32 m_i3 = 5; // Part of value tree of S2. * }; * * // Value tree for s2: sub-tree of S2 assigning the value 150 to S1 and 100 to m_i3. * s2 = {{150}, 100}; * * // Value tree for rgi: CArrayValueNode having two children assigning the value 10 and 20. * int32 rgi[2] = {10, 20}; * * // Value tree for rgs3: CarrayValueNode having two children S1 assigning the values 1000 and 2000. * S1 rgs3[2] = {{1000}, {2000}}; * @endcode */ class CEntityValueNode : public std::enable_shared_from_this { public: /** * @brief Constructor * @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr. * @param[in] ptrParent Smart pointer to the parent value. Can only be nullptr for const and declaration entities or when * creating a value node for a definition which will be copied in a larger declaration at a later stage. */ CEntityValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent); /** * @brief Copy constructor with new parent and entity. * @param[in] rValueNode Reference to the value node to copy from. * @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr. * @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr. */ CEntityValueNode(const CEntityValueNode& rValueNode, CEntityPtr ptrEntity, const CValueNodePtr ptrParent); /** * @brief Default destructor * @remarks This constructor needs to be virtual to allow derived classes to be destroyed correctly. * */ virtual ~CEntityValueNode() = default; /** * @brief Create a copy of the value. Prototype to be implemented from derived class. * @param[in] ptrEntity Smart pointer to the entity receiving the copy of the value node. * @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr. * @return Returns a smart pointer of the copy of the value. */ virtual CValueNodePtr CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const = 0; /** * @brief Process the assignment. Prototype, to be implemented by derived value class. * @param[in] rlstExpression Reference to the expression token list. */ virtual void ProcessValueAssignment(const CTokenList& rlstExpression) = 0; /** * @brief Process the child nodes. * @param[in] rlstExpression Reference to the expression token list. */ virtual void ProcessChildNodes(const CTokenList& rlstExpression); /** * @{ * @brief Get the derived value class. * @tparam TValue The value class to request a pointer for. * @return Returns a pointer to the derived class or NULL when the requested class didn't derive from this value. */ template TValue* Get(); template const TValue* Get() const; /** * @} */ /** * @brief Add a child node * @param[in] ptrChild Pointer to the child value node. */ void AddChild(CValueNodePtr ptrChild); /** * @brief Get the parent node. * @return Returns a reference to the smart pointer of the parent node (if assigned). */ const CValueNodePtr& GetParentNode() const { return m_ptrParent; } /** * @{ * @brief Get the attached declaration entity. * @return Returns the smart pointer to the entity. */ const CDeclarationEntity* GetDeclEntity() const { return m_ptrEntity->Get(); } CDeclarationEntity* GetDeclEntity() { return m_ptrEntity->Get(); } /** * @} */ /** * @brief Get the declaration type build from the value chain. * @details The declaration type consists of " ". * @param[in] bResolveTypedef When set, resolve the typedef type into the base type. * @return Returns a string with entity type. */ virtual std::string GetDeclTypeStr(bool bResolveTypedef) const; /** * @{ * @brief Information functions. * @details Each function is implemented by an entity value class. The IsConst function traverses through the parents to find * out whether or not a value is a const value (this is the case when the entity holding the top most value is a const * entity.) * @return Returns the information. */ virtual bool IsArray() const { return false; } virtual bool IsUnbound() const { return false; } virtual bool IsConst() const; virtual bool IsDeclaration() const; virtual bool IsDynamic() const { return false; } virtual bool IsLiteral() const { return false; } virtual bool IsComplex() const { return false; } virtual bool HasParent() const{ return m_ptrParent ? true : false; } virtual bool HasChildren() const{ return !m_vecChildren.empty(); } /** * @} */ protected: CEntityPtr m_ptrEntity; ///< The entity implementing the value type. const CValueNodePtr m_ptrParent; ///< Parent value node - can be nullptr for root node. std::vector m_vecChildren; ///< Child nodes. }; /** * @brief Entity declaration value (used as const variable assignment as well as default declaration assignment). */ class CSimpleTypeValueNode : public CEntityValueNode { public: /** * @brief Constructor * @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr. * @param[in] ptrParent Smart pointer to the parent value. Can only be nullptr for upper most value level. */ CSimpleTypeValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent); /** * @brief Copy constructor with new parent and entity. * @param[in] rValueNode Reference to the value node to copy from. * @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr. * @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr. */ CSimpleTypeValueNode(const CSimpleTypeValueNode& rValueNode, CEntityPtr ptrEntity, const CValueNodePtr ptrParent); /** * @brief Default destructor * @remarks This constructor needs to be virtual to allow derived classes to be destroyed correctly. * */ virtual ~CSimpleTypeValueNode() override = default; /** * @brief Create a copy of the value. Overload of CEntityValueNode::CreateCopy. * @param[in] ptrEntity Smart pointer to the entity receiving the copy of the value node. * @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr. * @return Returns a smart pointer of the copy of the value. */ virtual CValueNodePtr CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const override; /** * @brief Process the assignment. Overload of CEntityValueNode::ProcessValueAssignment. * @param[in] rlstExpression Reference to the expression token list. */ virtual void ProcessValueAssignment(const CTokenList& rlstExpression) override; /** * @brief Set to a fixed value. * @remarks In case the entity is not a const entity, the value is considered to be a default value. * @param[in] rvarValue Reference to the fixed value. * @param[in] rlstExpression Reference to the expression list used to calculate the value. */ void SetFixedValue(const CConstVariant& rvarValue, const CTokenList& rlstExpression); /** * @brief Set to a dynamic value * @remarks This function can only be called when the entity of any of the parent entities is not a const entity. * @param[in] rlstExpression Reference to the expression list used to calculate the value. */ void SetDynamicValue(const CTokenList& rlstExpression); /** * @brief Is the value defined? * @return Returns 'true' when the value is defined; 'false' otherwise. */ virtual bool IsDefined() const { return m_eValueDef != EValueDef::not_defined; } /** * @brief Is this value dynamic (will it be defined through a non-const variable definition)? * @return Returns 'true' when the value is dynamic; 'false' otherwise. */ virtual bool IsDynamic() const override { return m_eValueDef != EValueDef::dynamic; } /** * @brief Get access to the underlying const variant. * @return The const variant storing the calculated value. */ const CConstVariant &Variant() const { return m_varValue; } private: /** * @brief The definition of the size is either fixed or not fixed. When it is fixed, it could be derived from assigning its * values. */ enum class EValueDef { not_defined, ///< Currently not defined yet. fixed, ///< The value is fixed; could be used for const and declaration entities. dynamic, ///< The value is dependable on a variable declaration. Only to be used with a declaration entity. }; CConstVariant m_varValue; ///< The calculated value. CTokenList m_lstExpression; ///< List of tokens holding the value expression. EValueDef m_eValueDef = EValueDef::not_defined; ///< Dynamic value based on variables. }; /** * @brief Entity array value (containing an array of value pointers). * @remarks When the array contains non-allocated value pointers, the array has been declared, but the values haven't been * assigned. */ class CArrayValueNode : public CEntityValueNode { public: /** * @brief Constructor * @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr. * @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr. */ CArrayValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent); /** * @brief Copy constructor with new parent and entity. * @param[in] rValueNode Reference to the value node to copy from. * @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr. * @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr. */ CArrayValueNode(const CArrayValueNode& rValueNode, CEntityPtr ptrEntity, const CValueNodePtr ptrParent); /** * @brief Default destructor * @remarks This constructor needs to be virtual to allow derived classes to be destroyed correctly. * */ virtual ~CArrayValueNode() override = default; /** * @brief Create a copy of the value. Overload of CEntityValueNode::CreateCopy. * @param[in] ptrEntity Smart pointer to the entity receiving the copy of the value node. * @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr. * @return Returns a smart pointer of the copy of the value. */ virtual CValueNodePtr CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const override; /** * @brief Process the assignment. Overload of CEntityValueNode::ProcessValueAssignment. * @param[in] rlstExpression Reference to the expression token list. */ virtual void ProcessValueAssignment(const CTokenList& rlstExpression) override; /** * @brief Process the child nodes. Overload of CEntityValueNode::ProcessChildNodes. * @param[in] rlstExpression Reference to the expression token list. */ void ProcessChildNodes(const CTokenList& rlstExpression) override; /** * @brief Process the string nodes. This is an array processing function based on a string as character array. * @param[in] rToken Reference to the string literal token. */ void ProcessStringNode(const CToken& rToken); /** * @brief Set the fixed size of the array when available during declaration. * @attention Must not be called after the value has been set to dynamic or set to a delayed fixed size. * @param[in] nSize The calculated size of the array. * @param[in] rlstExpression Reference to the expression list used to calculate the value. */ void SetFixedSize(size_t nSize, const CTokenList& rlstExpression); /** * @brief Set the array to a dynamic size based on a variable declaration. This is only allowed for entities that are not * declared as const entity (where all the parent values are not defined as const). * @attention Must not be called after the value has been set to a fixed size (delayed or not). * @param[in] nSize The calculated size of the array. * @param[in] rlstExpression Reference to the expression list used to calculate the size. */ void SetDynamicSize(size_t nSize, const CTokenList& rlstExpression); /** * @brief Set the array to a fixed size through its value assignment. This is only allowed for entities that are declared as * const entity (where one of the parents was defined as const). * @attention Must not be called after the value has been set to a fixed size (not delayed) or a dynamic size. */ void SetFixedSizeUnbound(); /** * @{ * @brief Element access of the array. * @param[in] nIndex The index of the element. For dynamic arrays, only an index of 0 is allowed. * @return Returns a reference to the element. */ const CValueNodePtr& operator[](size_t nIndex) const; CValueNodePtr& operator[](size_t nIndex); /** * @} */ /** * @brief Get the size of the array. * @return The size of the array. */ size_t GetSize() const; /** * @brief This is an array entity. * @return Returns 'true'. */ virtual bool IsArray() const override; /** * @brief Is the size of the array defined through the assignment? * @return Returns 'true' when the size of the array has to be defined through the assignment. */ virtual bool IsUnbound() const override; /** * @brief Get the size expression. * @return The size expression string. */ std::string GetSizeExpression() const; /** * @brief Get the declaration type build from the value chain. Overload of CEntityValueNode::GetDeclTypeStr. * @details The declaration type consists of " ". * @param[in] bResolveTypedef When set, resolve the typedef type into the base type. * @return Returns a string with entity type. */ virtual std::string GetDeclTypeStr(bool bResolveTypedef) const override; private: /** * @brief The definition of the size is either fixed or not fixed. When it is fixed, it could be derived from assigning its * values. */ enum class ESizeDef { not_defined, ///< Currently not defined yet. fixed, ///< The size is fixed; could be used for const and declaration entities. dynamic, ///< The size is dependable on a variable declaration. Only to be used with a declaration entity. fixed_unbound, ///< The size is fixed, but gets defined during value assignment. Only to be used with a const ///< entity. }; CTokenList m_lstArraySizeExpression; ///< List of tokens holding the array size expression. ESizeDef m_eSizeDef = ESizeDef::not_defined; ///< The size definition. }; /** * @brief Entity struct value containing two arrays of value pointers, one array for the member const declarations and one array * for the member variable declarations. */ class CCompoundTypeValueNode : public CEntityValueNode { public: /** * @brief Constructor * @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr. * @param[in] ptrParent Smart pointer to the parent value. Can only be nullptr when creating a value node for a definition * which will be copied in a larger declaration at a later stage. */ CCompoundTypeValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent); /** * @brief Copy constructor with new parent and entity. * @param[in] rValueNode Reference to the value node to copy from. * @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr. * @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr. */ CCompoundTypeValueNode(const CCompoundTypeValueNode& rValueNode, CEntityPtr ptrEntity, const CValueNodePtr ptrParent); /** * @brief Default destructor * @remarks This constructor needs to be virtual to allow derived classes to be destroyed correctly. * */ virtual ~CCompoundTypeValueNode() override = default; /** * @brief Create a copy of the value. Overload of CEntityValueNode::CreateCopy. * @param[in] ptrEntity Smart pointer to the entity receiving the copy of the value node. * @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr. * @return Returns a smart pointer of the copy of the value. */ virtual CValueNodePtr CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const override; /** * @brief Process the assignment. Overload of CEntityValueNode::ProcessValueAssignment. * @param[in] rlstExpression Reference to the expression token list. */ virtual void ProcessValueAssignment(const CTokenList& rlstExpression) override; /** * @brief Return the value for the supplied member. * @param[in] rssName Name Reference to the string object containing the name of the member. * @return Returns the value node smart pointer of the requested member, or nullptr when member doesn't have a value or * doesn't exist. */ CValueNodePtr Member(const std::string& rssName) const; }; /** * @brief Interface value node. * @note The only assignable values of an interface are "null" and "0". No variable is allowed to be assigned and an interface * cannot be const. */ class CInterfaceValueNode : public CEntityValueNode { public: /** * @brief Constructor * @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr. * @param[in] ptrParent Smart pointer to the parent value. Can only be nullptr for upper most value level. */ CInterfaceValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent); /** * @brief Copy constructor with new parent and entity. * @param[in] rValueNode Reference to the value node to copy from. * @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr. * @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr. */ CInterfaceValueNode(const CInterfaceValueNode& rValueNode, CEntityPtr ptrEntity, const CValueNodePtr ptrParent); /** * @brief Default destructor * @remarks This constructor needs to be virtual to allow derived classes to be destroyed correctly. * */ virtual ~CInterfaceValueNode() override = default; /** * @brief Create a copy of the value. Overload of CEntityValueNode::CreateCopy. * @param[in] ptrEntity Smart pointer to the entity receiving the copy of the value node. * @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr. * @return Returns a smart pointer of the copy of the value. */ virtual CValueNodePtr CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const override; /** * @brief Process the assignment. Overload of CEntityValueNode::ProcessValueAssignment. * @param[in] rlstExpression Reference to the expression token list. */ virtual void ProcessValueAssignment(const CTokenList& rlstExpression) override; /** * @brief Is this value dynamic (will it be defined through a non-const variable definition)? This is always the case. * @return Returns 'true' when the value is dynamic; 'false' otherwise. */ virtual bool IsDynamic() const override { return true; } }; /** * @brief Enum entity declaration value. */ class CEnumValueNode : public CEntityValueNode { public: /** * @brief Constructor * @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr. * @param[in] ptrParent Smart pointer to the parent value. Can only be nullptr for upper most value level. */ CEnumValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent); /** * @brief Copy constructor with new parent and entity. * @param[in] rValueNode Reference to the value node to copy from. * @param[in] ptrEntity Smart pointer to the entity implementing the type. Cannot be nullptr. * @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr. */ CEnumValueNode(const CEnumValueNode& rValueNode, CEntityPtr ptrEntity, const CValueNodePtr ptrParent); /** * @brief Default destructor * @remarks This constructor needs to be virtual to allow derived classes to be destroyed correctly. * */ virtual ~CEnumValueNode() override = default; /** * @brief Create a copy of the value. Overload of CEntityValueNode::CreateCopy. * @param[in] ptrEntity Smart pointer to the entity receiving the copy of the value node. * @param[in] ptrParent Smart pointer to the parent value. Cannot be nullptr. * @return Returns a smart pointer of the copy of the value. */ virtual CValueNodePtr CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const override; /** * @brief Process the assignment. Overload of CEntityValueNode::ProcessValueAssignment. * @param[in] rlstExpression Reference to the expression token list. */ virtual void ProcessValueAssignment(const CTokenList& rlstExpression) override; /** * @brief Is the value defined? * @return Returns 'true' when the value is defined; 'false' otherwise. */ virtual bool IsDefined() const { return m_ptrEntryVal ? true : false; } /** * @brief Get access to the assigned const variant of the enum entry. * @return The const variant storing the value. */ const CConstVariant& Variant() const; /** * @brief Get access to the assigned name string of the enum entry. * @return The name string of the enum entry. */ std::string String() const; private: CEntityPtr m_ptrEntryVal; ///< The enum entry value when assigned. CTokenList m_lstExpression; ///< List of tokens holding the value expression. }; template TValue* CEntityValueNode::Get() { return dynamic_cast(this); } template const TValue* CEntityValueNode::Get() const { return dynamic_cast(this); } #endif // !define(ENTITY_VALUE_H)