/********************************************************************************
 * 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 IDL_PARSER_INTERFACE_H
#define IDL_PARSER_INTERFACE_H

/**
 * @brief Suppress loading core types... these are generated by the compiler.
 */
#define DONT_LOAD_CORE_TYPES
#include <support/interface.h>
#include <support/except.h>
#include <cstdint>
#include <typeinfo>
#include <map>
#include <string>

#ifdef _MSC_VER
    // Prevent bogus warnings about uninitialized members during static code analysis.
    #pragma warning(push)
    #pragma warning(disable : 26495)
#endif

namespace sdv
{
    /**
     * @brief Access interface
     */
    interface IInterfaceAccess
    {
        /** Interface ID. */
        static constexpr ::sdv::interface_id _id = 0x9D93731520AD52C8;

        /**
         * @brief Get access to another interface.
         * 
         * @param[in] idInterface The interface id to get access to.
         * @return Returns a pointer to the interface or NULL when the interface is not supported.
         */
        virtual sdv::interface_t GetInterface(/*in*/ sdv::interface_id idInterface) = 0;

        /**
         * @brief Templated version of GetInterface.
         * @tparam TInterface The interface type.
         * @return Returns a pointer to the interface or NULL when the interface is not supported.
         */
        template <typename TInterface>
        TInterface* GetInterface()
        {
            return GetInterface(sdv::GetInterfaceId<TInterface>()).template get<TInterface>();
        }
    };

    /**
     * @brief Object type enumeration.
     */
    enum class EObjectType : uint32_t
    {
        /// System object
        SystemObject = 0,

        /// Abstract device
        Device = 10,

        /// Basic service
        BasicService = 20,

        /// Complex service
        ComplexService = 21,

        /// Application
        Application = 30,

        /// Proxy object
        Proxy = 100,

        /// Stub object
        Stub = 101,

        /// Utility object
        Utility = 1000,
    };

    /*
     * @brief Interface that might be exposed by objects to allow self-destruction if the owner doesn't need to object any more.
     */
    interface IObjectDestroy
    {
        /** Interface ID. */
        static constexpr ::sdv::interface_id _id = 0xBCE042046AED46D7;

        /**
         * @brief Destroy the object.
         * @attention After a call of this function, all exposed interfaces render invalid and should not be used any more.
         */
        virtual void DestroyObject() = 0;
    };

    /**
     * @brief Lifetime management through reference counting.
     */
    interface IObjectLifetime
    {
        /** Interface ID. */
        static constexpr ::sdv::interface_id _id = 0x8E5315B6428769CA;

        /**
         * @brief Increment the lifetime. Needs to be balanced by a call to Decrement.
         */
        virtual void Increment() = 0;

        /**
         * @brief Decrement the lifetime. If the lifetime reaches zero, the object will be destroyed (through the exposed
         * IObjectDestroy interface).
         * @return Returns 'true' if the object was destroyed, false if not.
         */
        virtual bool Decrement() = 0;

        /**
         * @brief Get the current lifetime count.
         * @remarks The GetCount function returns a momentary value, which can be changed at any moment.
         * @return Returns the current counter value.
         */
        virtual uint32_t GetCount() const = 0;
    };

    /**
     * @brief System exception.
     */
    except XSysExcept
    {
        /** Exception ID. */
        inline static const ::sdv::exception_id _id = 0xE1BCB80EB2F0DCB8;

        /** Explanatory string. */
        inline static const char _description[] = "XSysExcept exception";

        /** Return the explanatory string. @return The descriptive string. */
        virtual const char* what() const noexcept { return _description; }

        /** Return the id. @return The id of the exception.*/
        virtual ::sdv::exception_id id() const noexcept { return _id; }
    };

    /**
     * @brief No interface found exception.
     */
    except XNoInterface : XSysExcept
    {
        // _id might also be member of the base class. Suppress in static code analysis.
        // cppcheck-suppress duplInheritedMember
        /** Exception ID. */
        inline static const ::sdv::exception_id _id = 0xB67CF66C856DCD04;

        // _description might also be member of the base class. Suppress in static code analysis.
        // cppcheck-suppress duplInheritedMember
        /**
         * Description
         */
        inline static const char _description[] = "The interface could not be found.";

        /** Return the explanatory string. @return The descriptive string. */
        virtual const char* what() const noexcept override { return _description; }

        /** Return the id. @return The id of the exception.*/
        virtual ::sdv::exception_id id() const noexcept override { return _id; }
    };

    /**
     * @brief Invalid index (index >= size or index < 0).
     */
    except XIndexOutOfRange : XSysExcept
    {
        // _id might also be member of the base class. Suppress in static code analysis.
        // cppcheck-suppress duplInheritedMember
        /** Exception ID. */
        inline static const ::sdv::exception_id _id = 0xCB72D113B2C57CB6;

        // _description might also be member of the base class. Suppress in static code analysis.
        // cppcheck-suppress duplInheritedMember
        /**
         * Description
         */
        inline static const char _description[] = "The supplied index was out of range.";

        /// Index
        uint32_t uiIndex;

        /// Size
        uint32_t uiSize;

        /** Return the explanatory string. @return The descriptive string. */
        virtual const char* what() const noexcept override { return _description; }

        /** Return the id. @return The id of the exception.*/
        virtual ::sdv::exception_id id() const noexcept override { return _id; }
    };

    /**
     * @brief Invalid iterator.
     */
    except XInvalidIterator : XSysExcept
    {
        // _id might also be member of the base class. Suppress in static code analysis.
        // cppcheck-suppress duplInheritedMember
        /** Exception ID. */
        inline static const ::sdv::exception_id _id = 0xE12D4F227521A71E;

        // _description might also be member of the base class. Suppress in static code analysis.
        // cppcheck-suppress duplInheritedMember
        /**
         * Description
         */
        inline static const char _description[] = "The supplied iterator was invalid.";

        /** Return the explanatory string. @return The descriptive string. */
        virtual const char* what() const noexcept override { return _description; }

        /** Return the id. @return The id of the exception.*/
        virtual ::sdv::exception_id id() const noexcept override { return _id; }
    };

    /**
     * @brief Null pointer.
     */
    except XNullPointer : XSysExcept
    {
        // _id might also be member of the base class. Suppress in static code analysis.
        // cppcheck-suppress duplInheritedMember
        /** Exception ID. */
        inline static const ::sdv::exception_id _id = 0xEEF0101F215DAB3F;

        // _description might also be member of the base class. Suppress in static code analysis.
        // cppcheck-suppress duplInheritedMember
        /**
         * Description
         */
        inline static const char _description[] = "A NULL-pointer was supplied.";

        /** Return the explanatory string. @return The descriptive string. */
        virtual const char* what() const noexcept override { return _description; }

        /** Return the id. @return The id of the exception.*/
        virtual ::sdv::exception_id id() const noexcept override { return _id; }
    };

    /**
     * @brief Invalid value for the reference counter.
     */
    except XInvalidRefCount : XSysExcept
    {
        // _id might also be member of the base class. Suppress in static code analysis.
        // cppcheck-suppress duplInheritedMember
        /** Exception ID. */
        inline static const ::sdv::exception_id _id = 0x02E02E52488E61DB;

        // _description might also be member of the base class. Suppress in static code analysis.
        // cppcheck-suppress duplInheritedMember
        /**
         * Description
         */
        inline static const char _description[] = "The reference counter has an invalid/unexpected value.";

        /// Reference counter value.
        uint32_t uiCount;

        /** Return the explanatory string. @return The descriptive string. */
        virtual const char* what() const noexcept override { return _description; }

        /** Return the id. @return The id of the exception.*/
        virtual ::sdv::exception_id id() const noexcept override { return _id; }
    };

    /**
     * @brief Buffer is too small.
     */
    except XBufferTooSmall : XSysExcept
    {
        // _id might also be member of the base class. Suppress in static code analysis.
        // cppcheck-suppress duplInheritedMember
        /** Exception ID. */
        inline static const ::sdv::exception_id _id = 0x3C494554A6187FE2;

        // _description might also be member of the base class. Suppress in static code analysis.
        // cppcheck-suppress duplInheritedMember
        /**
         * Description
         */
        inline static const char _description[] = "The buffer was too small to store the data.";

        /// Requested size.
        uint64_t uiSize;

        /// Size of the buffer.
        uint64_t uiCapacity;

        /** Return the explanatory string. @return The descriptive string. */
        virtual const char* what() const noexcept override { return _description; }

        /** Return the id. @return The id of the exception.*/
        virtual ::sdv::exception_id id() const noexcept override { return _id; }
    };

    /**
     * @brief Hash value doesn't match.
     */
    except XHashNotMatching : XSysExcept
    {
        // _id might also be member of the base class. Suppress in static code analysis.
        // cppcheck-suppress duplInheritedMember
        /** Exception ID. */
        inline static const ::sdv::exception_id _id = 0x7618626C6A824D7D;

        // _description might also be member of the base class. Suppress in static code analysis.
        // cppcheck-suppress duplInheritedMember
        /**
         * Description
         */
        inline static const char _description[] = "The provided hash value doesn't match to the calculated hash value.";

        /// Calculated hash value.
        uint64_t uiCalculated;

        /// Provided hash value.
        uint64_t uiProvided;

        /** Return the explanatory string. @return The descriptive string. */
        virtual const char* what() const noexcept override { return _description; }

        /** Return the id. @return The id of the exception.*/
        virtual ::sdv::exception_id id() const noexcept override { return _id; }
    };

    /**
     * @brief Offset out of range.
     */
    except XOffsetPastBufferSize : XSysExcept
    {
        // _id might also be member of the base class. Suppress in static code analysis.
        // cppcheck-suppress duplInheritedMember
        /** Exception ID. */
        inline static const ::sdv::exception_id _id = 0xD58CE8122B835FCB;

        // _description might also be member of the base class. Suppress in static code analysis.
        // cppcheck-suppress duplInheritedMember
        /**
         * Description
         */
        inline static const char _description[] = "The provided offset doesn't is not pointing to a location within the buffer.";

        /// Offset value.
        uint64_t uiOffset;

        /// Buffer size.
        uint64_t uiSize;

        /** Return the explanatory string. @return The descriptive string. */
        virtual const char* what() const noexcept override { return _description; }

        /** Return the id. @return The id of the exception.*/
        virtual ::sdv::exception_id id() const noexcept override { return _id; }
    };

    /**
     * @brief Unknown exception.
     */
    except XUnknownException : XSysExcept
    {
        // _id might also be member of the base class. Suppress in static code analysis.
        // cppcheck-suppress duplInheritedMember
        /** Exception ID. */
        inline static const ::sdv::exception_id _id = 0x18504F1A91F6FC94;

        // _description might also be member of the base class. Suppress in static code analysis.
        // cppcheck-suppress duplInheritedMember
        /**
         * Description
         */
        inline static const char _description[] = "An exception was fired, but no handler found for it.";

        /// The ID of the unknown exception.
        sdv::exception_id unknown_id;

        /** Return the explanatory string. @return The descriptive string. */
        virtual const char* what() const noexcept override { return _description; }

        /** Return the id. @return The id of the exception.*/
        virtual ::sdv::exception_id id() const noexcept override { return _id; }
    };

    /**
     * @brief Unhandled exception.
     */
    except XUnhandledException : XSysExcept
    {
        // _id might also be member of the base class. Suppress in static code analysis.
        // cppcheck-suppress duplInheritedMember
        /** Exception ID. */
        inline static const ::sdv::exception_id _id = 0x560CDFE1BF94C8C1;

        // _description might also be member of the base class. Suppress in static code analysis.
        // cppcheck-suppress duplInheritedMember
        /**
         * Description
         */
        inline static const char _description[] = "An unhandled exception was caught.";

        /** Return the explanatory string. @return The descriptive string. */
        virtual const char* what() const noexcept override { return _description; }

        /** Return the id. @return The id of the exception.*/
        virtual ::sdv::exception_id id() const noexcept override { return _id; }
    };

    /**
     * @brief Core features.
     */
    namespace core
    {
        /**
         * @brief No memory manager available exception.
         */
        except XNoMemMgr : XSysExcept
        {
            // _id might also be member of the base class. Suppress in static code analysis.
            // cppcheck-suppress duplInheritedMember
            /** Exception ID. */
            inline static const ::sdv::exception_id _id = 0xA0CB36340BFEECB3;

            // _description might also be member of the base class. Suppress in static code analysis.
            // cppcheck-suppress duplInheritedMember
            /**
             * Description
             */
            inline static const char _description[] = "The memory manager could not be accessed.";

            /** Return the explanatory string. @return The descriptive string. */
            virtual const char* what() const noexcept override { return _description; }

            /** Return the id. @return The id of the exception.*/
            virtual ::sdv::exception_id id() const noexcept override { return _id; }
        };

        /**
         * @brief Allocation failed exception
         */
        except XAllocFailed : XSysExcept
        {
            // _id might also be member of the base class. Suppress in static code analysis.
            // cppcheck-suppress duplInheritedMember
            /** Exception ID. */
            inline static const ::sdv::exception_id _id = 0x48383EE6B2D75A0F;

            // _description might also be member of the base class. Suppress in static code analysis.
            // cppcheck-suppress duplInheritedMember
            /**
             * Description
             */
            inline static const char _description[] = "The allocation of memory failed.";

            /// Size of the allocation.
            uint32_t uiSize;

            /** Return the explanatory string. @return The descriptive string. */
            virtual const char* what() const noexcept override { return _description; }

            /** Return the id. @return The id of the exception.*/
            virtual ::sdv::exception_id id() const noexcept override { return _id; }
        };
    }
} // namespace sdv

#include <support/iterator.h>
#include <support/pointer.h>
#include <support/sequence.h>
#include <support/string.h>

#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
#endif
namespace sdv
{
    /**
     * @brief IDL features.
     */
    namespace idl
    {
        /**
        * @brief Compilation error.
        */
        except XCompileError
        {
            /** Exception ID. */
            inline static const ::sdv::exception_id _id = 0x650594E6C9489FBB;

            /** Explanatory string. */
            static constexpr char _description[] = "XCompileError exception";

            /// Explanation of the compilation error.
            sdv::u8string ssReason;

            /// Path to the file causing the compilation error.
            sdv::u8string ssFile;

            /// Line in the source file that contains the error (starts at 1).
            uint32_t uiLine;

            /// Column in the source file that contains the error (starts at 1).
            uint32_t uiCol;

            /// Token that caused the error.
            sdv::u8string ssToken;

            /// Source code line that contains the error.
            sdv::u8string ssLine;

            /** Return the explanatory string. @return The descriptive string. */
            virtual const char* what() const noexcept { return _description; }

            /** Return the id. @return The id of the exception.*/
            virtual ::sdv::exception_id id() const noexcept { return _id; }
        };

        /// The installation directory of the compiler.
        static const sdv::u8string ssOptionDevEnvDir = u8"DevEnvDir";

        /// Path to the output file directory. Default "." - relative to the file path.
        static const sdv::u8string ssOptionOutDir = u8"OutDir";

        /// Name of the input file.
        static const sdv::u8string ssOptionFilename = u8"Filename";

        /// Path to the input file.
        static const sdv::u8string ssOptionFilePath = u8"FilePath";

        /// List of code generators
        static const sdv::u8string ssOptionCodeGen = u8"CodeGen";

        /**
        * @brief Compiler option access.
        */
        interface ICompilerOption
        {
            /** Interface ID. */
            static constexpr ::sdv::interface_id _id = 0xC27C1ABDE939E87F;

            /**
            * @brief Get the compiler option.
            * @param[in] rssOption Reference to the string containing the name of the option to retrieve.
            * @return The requested compiler option (if available).
            */
            virtual sdv::u8string GetOption(/*in*/ const sdv::u8string& rssOption) const = 0;

            /**
            * @brief Get the amount of option values.
            * @param[in] rssOption Reference to the string containing the name of the option to retrieve.
            * @return The amount of option values.
            */
            virtual uint32_t GetOptionCnt(/*in*/ const sdv::u8string& rssOption) const = 0;

            /**
            * @brief Get the compiler option.
            * @param[in] rssOption Reference to the string containing the name of the option to retrieve.
            * @param[in] uiIndex The index of the option value.
            * @return The requested compiler option value.
            */
            virtual sdv::u8string GetOptionN(/*in*/ const sdv::u8string& rssOption, /*in*/ uint32_t uiIndex) const = 0;
        };

        /**
        * @brief Compiler information access.
        */
        interface ICompilerInfo
        {
            /** Interface ID. */
            static constexpr ::sdv::interface_id _id = 0x7A9A8C8060A409A2;

            /**
            * @brief Get the path of the processed file.
            * @return The path string.
            */
            virtual sdv::u8string GetFilePath() const = 0;

            /**
            * @brief Return the path to the output directory.
            * @return The directory string.
            */
            virtual sdv::u8string GetOutputDir() const = 0;
        };

        /**
        * @brief The entity type.
        * @remarks Const entities, declaration entities and typedef entities return the base type of the entity they declare/define.
        */
        enum class EEntityType : uint32_t
        {
            /// Unknown entity type
            type_unknown,

            /// Variable entity type
            type_variable,

            /// Enum entity type
            type_enum,

            /// Struct entity type
            type_struct,

            /// Union entity type
            type_union,

            /// Module entity type
            type_module,

            /// Interface entity type
            type_interface,

            /// Interface entity type
            type_exception,

            /// Attribute entity type
            type_attribute,

            /// Operation entity type
            type_operation,

            /// Parameter entity type
            type_parameter,

            /// Enum entry entity type
            type_enum_entry,

            /// Case entry entity type
            type_case_entry,

            /// Switch variable entity type (used by unions)
            type_switch_variable,

            /// Typedef entity type
            type_typedef,

            /// Meta data entity type
            type_meta,
        };

        /**
        * @brief The entity declaration type.
        */
        enum class EDeclType : uint32_t
        {
            /// Unknown type
            decltype_unknown,

            /// Integer type (int16_t)
            decltype_short,

            /// Integer type (int32_t)
            decltype_long,

            /// Integer type (int64_t)
            decltype_long_long,

            /// Octet type (uint8_t)
            decltype_octet,

            /// Integer type (uint16_t)
            decltype_unsigned_short,

            /// Integer type (uint32)
            decltype_unsigned_long,

            /// Integer type (uint64_t)
            decltype_unsigned_long_long,

            /// Floating point type
            decltype_float,

            /// Floating point type
            decltype_double,

            /// Floating point type
            decltype_long_double,

            /// Fixed point templated type
            decltype_fixed,

            /// Character type (int8_t)
            decltype_char,

            /// UTF-16 character
            decltype_char16,

            /// UTF-32 character
            decltype_char32,

            /// Character type
            decltype_wchar,

            /// Boolean type
            decltype_boolean,

            /// Native type
            decltype_native,

            /// ASCII templated string type
            decltype_string,

            /// UTF-8 templated string type
            decltype_u8string,

            /// UTF-16 templated string type
            decltype_u16string,

            /// UTF-32 templated string type
            decltype_u32string,

            /// Wide templated string type
            decltype_wstring,

            /// Enum type
            decltype_enum,

            /// Struct type
            decltype_struct,

            /// Union type
            decltype_union,

            /// Module type
            decltype_module,

            /// Interface type (not used in declarations)
            decltype_interface,

            /// Interface type (not used in declarations)
            decltype_exception,

            /// Attribute type (not used in declarations)
            decltype_attribute,

            /// Operation type (not used in declarations)
            decltype_operation,

            /// Parameter type (only for operations)
            decltype_parameter,

            /// Enum entry type (only for enums)
            decltype_enum_entry,

            /// Case entry type (only for unions)
            decltype_case_entry,

            /// Typedef type
            decltype_typedef,

            /// Void type (only for operations)
            decltype_void,

            /// Meta data type
            decltype_meta,

            /// Pointer templated data type
            decltype_pointer,

            /// Sequence templated data type
            decltype_sequence,

            /// Map templated data type
            decltype_map,

            /// Bitset data type
            decltype_bitset,

            /// Bitfield templated data type
            decltype_bitfield,

            /// Bitmask data type
            decltype_bitmask,

            /// Any composite data type
            decltype_any,

            /// Interface ID data type
            decltype_interface_id,

            /// Interface data type
            decltype_interface_type,

            /// Exception ID data type
            decltype_exception_id,
        };

        /**
        * @brief Entity base information interface.
        */
        interface IEntityInfo
        {
            /** Interface ID. */
            static constexpr ::sdv::interface_id _id = 0x46BEDE6CC5C91F72;

            /**
            * @brief Get the type of the entity. Default type is EEntityType::type_unknown.
            * @return Returns the type of the entity.
            */
            virtual EEntityType GetType() const = 0;

            /**
            * @brief Get the name of the entity.
            * @return Returns the name string.
            */
            virtual sdv::u8string GetName() const = 0;

            /**
            * @brief Get the scoped name of the entity (including the modules separated by the scope separator).
            * @details The scoped name is composed of the entities of the parents separated by the scope operator '::'. For
            * members of a compound entity (struct, union), the separation is done through the member operator '.'.
            * @return The scoped name build from the entities of the parents separated by '::'. An empty name means global
            * scope.
            */
            virtual sdv::u8string GetScopedName() const = 0;

            /**
            * @brief Is the entity defined as (forward) declaration only?
            * @return Returns 'true' when the entity is defined as forward declaration; otherwise returns 'false'.
            */
            virtual bool ForwardDeclaration() const = 0;

            /**
            * @brief Get the entity ID. This ID is a hash value composed from its definition and all declarative members not
            * including const values. The ID can be used to uniquely identify the entity (e.g. as interface ID or exception ID).
            * @return The ID of the entity.
            */
            virtual uint64_t GetId() const = 0;

            /**
            * @brief Get the parent entity of this entity.
            * @return Returns an interface to the parent entity or NULL when this is the root parent (when there is no parent).
            */
            virtual IInterfaceAccess* GetParent() const = 0;
        };

        /**
        * @brief Iterate through a vector of entities.
        */
        interface IEntityIterator
        {
            /** Interface ID. */
            static constexpr ::sdv::interface_id _id = 0x7177BA8E9BF61AA7;

            /**
            * @brief Get amount of entities.
            * @return Returns the amount of entities available to this iterator.
            */
            virtual uint32_t GetCount() const = 0;

            /**
            * @brief Get entity at supplied index.
            * @param[in] uiIndex The index to get the entity for.
            * @return The entity at the index or NULL when there is no entity at this index.
            */
            virtual IInterfaceAccess* GetEntityByIndex(/*in*/ uint32_t uiIndex) = 0;
        };

        /**
        * @brief Context information interface.
        */
        interface IEntityContext
        {
            /** Interface ID. */
            static constexpr ::sdv::interface_id _id = 0xCDC79F5E7E643529;

            /**
            * @brief The location of the parsed file.
            */
            enum class ELocation : uint32_t
            {
                /// Source code or source file.
                source,

                /// Local include file.
                local_include,

                /// Global include file.
                global_include,
            };

            /**
            * @brief Get the location.
            * @return Returns context location.
            */
            virtual ELocation GetLocation() const = 0;

            /**
            * @brief Get the path to the file.
            * @return Returns the source path string.
            */
            virtual sdv::u8string GetSourcePath() const = 0;

            /**
            * @brief Get the position in the file.
            * @remarks Not all entities have a position. If no position is available, the position return value has the
            * value 0.
            * @param[out] ruiLineBegin Reference to the variable receiving the line number of the entity beginning.
            * @param[out] ruiColBegin Reference to the variable receiving the column number of the entity beginning.
            * @param[out] ruiLineEnd Reference to the variable receiving the line number of the entity ending.
            * @param[out] ruiColEnd Reference to the variable receiving the column number of the entity ending.
            */
            virtual void GetPosition(/*out*/ uint32_t& ruiLineBegin, /*out*/ uint32_t& ruiColBegin, /*out*/ uint32_t& ruiLineEnd, /*out*/ uint32_t& ruiColEnd) = 0;
        };

        /**
        * @brief Meta information interface. Exposed by the meta entity.
        */
        interface IMetaEntity
        {
            /** Interface ID. */
            static constexpr ::sdv::interface_id _id = 0xE33E8D1A971D0D7C;

            /**
            * @brief Token meta type (valid when token is a meta token).
            */
            enum class EType : uint32_t
            {
                /// Local include file
                include_local = 10,

                /// Global include file
                include_global = 11,

                /// Definition
                define = 20,

                /// Remove definition
                undef = 21,

                /// Verbatim text to be inserted in the generated code
                verbatim = 100,
            };

            /**
            * @brief Get the meta data type.
            * @return Returns the meta type.
            */
            virtual EType GetMetaType() const = 0;

            /**
            * @brief Get the meta data content.
            * @return Returns a string object.
            */
            virtual sdv::u8string GetContent() const = 0;
        };

        /**
        * @brief Comment interface.
        */
        interface IEntityComments
        {
            /** Interface ID. */
            static constexpr ::sdv::interface_id _id = 0xEE1AD4FC2B9217BB;

            /**
            * @brief Comment mask
            */
            enum class ECommentMask : uint32_t
            {
                /// Comment of the form "/** ... */"
                c_style_javadoc = 0x40001000,

                /// Comment of the form "/**< ... */"
                c_style_javadoc_post = 0x40201000,

                /// Comment of the form "/*! ... */"
                c_style_qt = 0x40002000,

                /// Comment of the form "/*!< ... */"
                c_style_qt_post = 0x40202000,

                /// Comment of the form "/* ... */"
                c_style = 0x40000000,

                /// Comment of the form "/// ..."
                cpp_style_javadoc = 0x80001000,

                /// Comment of the form "///< ..."
                cpp_style_javadoc_post = 0x80201000,

                /// Comment of the form "//! ..."
                cpp_style_qt = 0x80002000,

                /// Comment of the form "///< ..."
                cpp_style_qt_post = 0x80202000,

                /// Comment of the form "// ..."
                cpp_style = 0x80000000,

                /// Comment location is succeeding statement
                loc_succeeding = 0x00200000,

                /// Comment using javadoc form
                format_javadoc = 0x00001000,

                /// Comment using QT form
                format_qt = 0x00002000,

                /// Comment formatting mask
                format_mask = 0x0000f000,
            };

            /**
            * @brief Get the comment lines for this entity as one string.
            * @remarks For c-style multi-line comments, the indentation and additional asterisk character at the beginning of
            * each line is removed.
            * @param[out] ruiFlags Reference to the variable receiving the comment flags (a bitmask combination of
            * sdv::idl::IEntityComments::ECommentMask).
            * @return Returns the comment string. If the comment contains multiple lines, each line is ending with a newline.
            */
            virtual sdv::u8string GetComments(/*out*/ uint32_t& ruiFlags) const = 0;
        };

        /**
        * @brief Entity definition information interface.
        */
        interface IDefinitionEntity
        {
            /** Interface ID. */
            static constexpr ::sdv::interface_id _id = 0xC7BB02340D82D7AE;

            /**
            * @brief Does the entity have an unnamed definition.
            * @return Returns 'true' when the entity has an unnamed definition; otherwise returns 'false'.
            */
            virtual bool IsUnnamed() const = 0;

            /**
            * @brief Get child entity iterator if children are available and supported by the definition.
            * @return Returns a pointer to the child entity iterator or NULL when not available.
            */
            virtual IEntityIterator* GetChildren() = 0;

            /**
            * @brief Get inheritance entity iterator if the definition was inheriting from other entities.
            * @return Returns a pointer to the inheritance entity iterator or NULL when not available.
            */
            virtual IEntityIterator* GetInheritance() = 0;
        };

        /**
        * @brief Entities declared in a forward declaration expose this interface.
        */
        interface IForwardDeclarationEntity
        {
            /** Interface ID. */
            static constexpr ::sdv::interface_id _id = 0x3BE934D755332130;

            /**
            * @brief Get access to the actual declaration (if there is one).
            * @return Pointer to the interface of the entity definition or NULL when there is no definition.
            */
            virtual IInterfaceAccess* GetEntity() = 0;
        };

        /**
        * @brief Declaration type interface containing the base type, type string as defined in the code as well as the
        * definition object interface and template parameters.
        */
        interface IDeclarationType
        {
            /** Interface ID. */
            static constexpr ::sdv::interface_id _id = 0x50100506F3C91498;

            /**
            * @brief Return the base type.
            * @details The bse type might be a templated type (string, sequence, map, etc.) which means that additional
            * information is needed. Furthermore, the type might be a complex type (struct, union, enum) or a typedef. In these
            * cases the type definition interface is available.
            * @return The base type of this type.
            */
            virtual EDeclType GetBaseType() const = 0;

            /**
            * @brief Return the string that described the type in the code.
            * @return The type string.
            */
            virtual sdv::u8string GetTypeString() const = 0;

            /**
            * @brief Return the type definition for complex types or typedefs.
            * @return Pointer to the interface representing the type definition. Will be NULL for all other types.
            */
            virtual IInterfaceAccess* GetTypeDefinition() const = 0;

            /**
            * @brief Fixed length parameter for some templated types.
            * @details Fixed length template parameter for "fixed", "string", "sequence", "pointer", "map" and "bitfields".
            * When not compulsory (for "fixed", "string", "sequence", "pointer" and "map") could be 0 to indicate a dynamic
            * length (or defined over assignment with "fixed"). Bitfields allow a length between 1 and 64 bits.
            * @return Returns the fixed length for some templated types or 0 for all other other types.
            */
            virtual uint32_t GetFixedLength() const = 0;

            /**
            * @brief The amount of decimals of the "fixed" data type. Must be equal or smaller than the fixed length.
            * @return The amount of decimals for the "fixed" data type or 0 for all other data types.
            */
            virtual uint32_t GetDecimals() const = 0;

            /**
            * @brief The value type template parameter for the "sequence", "pointer", "map" and "bitfield" data types.
            * @return Interface to the value data type for some templated types of NULL for all other types.
            */
            virtual IInterfaceAccess* GetValueType() const = 0;

            /**
            * @brief The key type template parameter for the "map" data type.
            * @return Interface to the key data type for the "map" type of NULL for all other types.
            */
            virtual IInterfaceAccess* GetKeyType() const = 0;
        };

        /**
        * @brief Array dimension definition.
        * @details Multi-dimensional arrays are possible. Each dimension is defined between square-brackets
        * (eg. var[a][b][]). An unbound dimension can only occur as the last dimension. Fixed-bound dimensions can be
        * specified using a constant expression. If variables are used in the constant expression, they need to be in
        * scope of the array variable.
        */
        struct SArrayDimension
        {
            /**
            * @brief Dimension type.
            */
            enum class EDimensionType : uint32_t
            {
                /// Bound array
                bound = 0,

                /// Unbound array
                unbound = 2,
            };

            /// The dimension type
            EDimensionType eType;

            /// Expression defining the dimension size either as constant- or as runtime-expression.
            sdv::u8string ssExpression;
        };

        /**
        * @brief Declaration entity information interface.
        */
        interface IDeclarationEntity
        {
            /** Interface ID. */
            static constexpr ::sdv::interface_id _id = 0xE0135FBD85B21E86;

            /**
            * @brief Get declaration type.
            * @return Interface to the declaration type object.
            */
            virtual IInterfaceAccess* GetDeclarationType() const = 0;

            /**
            * @brief Is the entity readonly?
            * @return Returns 'true' when the declaration is defined as readonly declaration; otherwise returns 'false'.
            */
            virtual bool IsReadOnly() const = 0;

            /**
            * @brief Is the entity anonymous when used in a struct/union (unnamed and not declared)?
            * @details Returns whether the entity is anonymous when used in a struct/union. This allows its members to appear
            * directly as members within the struct.
            * @return Returns 'true' when the declaration is defined as anonymous declaration; otherwise returns 'false'.
            */
            virtual bool IsAnonymous() const = 0;

            /**
            * @brief Has array?
            * @return Returns 'true' when the declaration is part of an array; otherwise returns 'false'.
            */
            virtual bool HasArray() const = 0;

            /**
            * @brief Get the array dimensions (if there are any).
            * @return Smart pointer to the sequence of array dimensions.
            */
            virtual sdv::sequence<SArrayDimension> GetArrayDimensions() const = 0;

            /**
            * @brief Has assignment?
            * @return Returns 'true' when the declaration is followed by an assignment; otherwise returns 'false'.
            */
            virtual bool HasAssignment() const = 0;

            /**
            * @brief Get assignment string.
            * @details The assignment can be an algebraic expression composed from constants and variables. If the assignment is an
            * array, the expression is composed like this: {{expr1},{expr2},{expr...}}
            * @return Returns the assignment string when available.
            */
            virtual sdv::u8string GetAssignment() const = 0;
        };

        /**
        * @brief Interface entity
        */
        interface IInterfaceEntity
        {
            /** Interface ID. */
            static constexpr ::sdv::interface_id _id = 0x1C7491088C1C6C3F;

            /**
            * @brief Is this interface local?
            * @details When set, the interface is defined as local and not intended to be marshalled.
            * @return Returns 'true' when the interface is defined as local interface; otherwise returns 'false'.
            */
            virtual bool IsLocal() const = 0;
        };

        /**
        * @brief Operation entity
        */
        interface IOperationEntity
        {
            /** Interface ID. */
            static constexpr ::sdv::interface_id _id = 0x75F2DA445EB605EE;

            /**
            * @brief Get parameter entity iterator if the definition has any parameters.
            * @return Returns a pointer to the parameter entity iterator or NULL when not available.
            */
            virtual IEntityIterator* GetParameters() = 0;

            /**
            * @brief Get the list of possible exceptions that might be fired for this operation.
            * @return Returns a pointer to the exception entity iterator or NULL when not available.
            */
            virtual IEntityIterator* GetExceptions() = 0;
        };

        /**
        * @brief Attribute entity
        */
        interface IAttributeEntity
        {
            /** Interface ID. */
            static constexpr ::sdv::interface_id _id = 0x492ABA076F15A69B;

            /**
            * @brief Get the list of possible exceptions that might be fired during a read operation.
            * @return Returns a pointer to the exception entity iterator or NULL when not available.
            */
            virtual IEntityIterator* GetReadExceptions() = 0;

            /**
            * @brief Get the list of possible exceptions that might be fired during a write operation.
            * @return Returns a pointer to the exception entity iterator or NULL when not available.
            */
            virtual IEntityIterator* GetWriteExceptions() = 0;
        };

        /**
        * @brief Parameter entity information interface.
        */
        interface IParameterEntity
        {
            /** Interface ID. */
            static constexpr ::sdv::interface_id _id = 0xCF79131CE1B17AA3;

            /**
            * @brief Parameter direction enumeration
            */
            enum class EParameterDirection : uint32_t
            {
                /// The parameter direction is not known.
                unknown,

                /// The parameter is defined as input parameter.
                input,

                /// The parameter is defined as output parameter.
                output,

                /// The parameter is defined as input and output parameter.
                in_out,
            };

            /**
            * @brief Get the parameter direction.
            * @return Returns the parameter direction.
            */
            virtual EParameterDirection GetDirection() const = 0;
        };

        /**
        * @brief Enum entity information interface.
        */
        interface IEnumEntity
        {
            /** Interface ID. */
            static constexpr ::sdv::interface_id _id = 0xCF4D94C9746CA76F;

            /**
            * @brief Get the enumerator base type.
            * @param[out] reType Reference to the declaration type. The type if EEntityType::type_unknown if not available.
            * @param[out] rpType Reference to the interface pointer if the type is a complex type. Otherwise is NULL.
            */
            virtual void GetBaseType(/*out*/ EDeclType& reType, /*out*/ IInterfaceAccess*& rpType) const = 0;
        };

        /**
        * @brief Union entity information interface.
        */
        interface IUnionEntity
        {
            /** Interface ID. */
            static constexpr ::sdv::interface_id _id = 0x23A3AFF91945A3B3;

            /**
            * @brief The interpretation of the switch case.
            */
            enum class ESwitchInterpret : uint32_t
            {
                /// The switch case is determined by a variable of the parent struct.
                switch_variable,

                /// The switch case is determined by the value of a type.
                switch_type,
            };

            /**
            * @brief Return the switch interpretation.
            * @return The interpretation of the switch case of this union.
            */
            virtual ESwitchInterpret GetSwitchInterpretation() const = 0;

            /**
            * @brief Return type information for the switch case. If the switch case is type base, this is the type information
            * that is used to select. If the switch case is variable based, this is the type of the variable.
            * @param[out] reType Reference to the declaration type (either enum or an integral type).
            * @param[out] rpType Reference to the type entity if existing.
            */
            virtual void GetSwitchType(/*out*/ EDeclType& reType, /*out*/ IInterfaceAccess*& rpType) const = 0;

            /**
            * @brief Get the switch variable information if the switch case is variable based. Will be empty/NULL when the switch
            * case is type based.
            * @param[out] rssVarStr Reference to the string receiving the exact scoped declaration name of the switch variable if
            * the interpretation is variable based. The variable name uses the scope separator '::' to define the common parent
            * definition and the member separator '.' to define the variable declaration as member from the common parent.
            * @param[out] rpVarEntity Reference to the variable entity if the interpretation is variable based.
            * @param[out] rpVarContainer Reference to the variable entity of the container of both the switch variable and the
            * union.
            */
            virtual void GetSwitchVar(/*out*/ sdv::u8string& rssVarStr, /*out*/ IInterfaceAccess*& rpVarEntity, /*out*/ IInterfaceAccess*& rpVarContainer) const = 0;
        };

        /**
        * @brief Case entity information interface.
        */
        interface ICaseEntity
        {
            /** Interface ID. */
            static constexpr ::sdv::interface_id _id = 0x6018B17C44F736F3;

            /**
            * @brief Get the case label string. The case label string will be empty for the default case entry.
            * @return Returns the label (of not default).
            */
            virtual sdv::u8string GetLabel() const = 0;

            /**
            * @brief Is this case entry the default entry.
            * @return Return whether the case entry is the default entry.
            */
            virtual bool IsDefault() const = 0;
        };
    }
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif

namespace sdv
{
    namespace core
    {
        namespace internal
        {
            /**
            * @brief Local memory manager imitating the sdv memory management
            */
            class CMemMgr : public sdv::internal::IInternalMemAlloc
            {
            public:
                /**
                 * @brief Allocate memory. Overload of sdv::internal::IInternalMemAlloc::Alloc.
                 * @param[in] nSize The size of the memory to allocate (in bytes).
                 * @return Pointer to the memory allocation or NULL when memory allocation failed.
                 */
                virtual void* Alloc(size_t nSize) override { return malloc(nSize); }

                /**
                 * @brief Reallocate memory. Overload of sdv::internal::IInternalMemAlloc::Realloc.
                 * @param[in] pData Pointer to a previous allocation or NULL when no previous allocation was available.
                 * @param[in] nSize The size of the memory to allocate (in bytes).
                 * @return Pointer to the memory allocation or NULL when memory allocation failed.
                 */
                virtual void* Realloc(void* pData, size_t nSize) override { return realloc(pData, nSize); }

                /**
                 * @brief Free a memory allocation. Overload of sdv::internal::IInternalMemAlloc::Free.
                 * @param[in] pData Pointer to a previous allocation.
                 */
                virtual void Free(void* pData) override { return free(pData); }
            };

            /**
             * @brief Get access to the memory manager
             * @return Pointer to the memory manager interface.
             */
            inline sdv::internal::IInternalMemAlloc* GetMemMgr()
            {
                static CMemMgr memmgr;
                return &memmgr;
            }
        } // namespace internal

        /**
         * @brief Allocate memory as byte pointer.
         * @param[in] nAmount The amount of bytes to allocate.
         * @return Returns a pointer to the allocated memory or NULL when the allocation failed.
         */
        inline pointer<uint8_t> AllocMemBytes(size_t nAmount)
        {
            return sdv::internal::make_ptr<uint8_t>(internal::GetMemMgr(), nAmount);
        }

        /**
         * @brief Allocate memory
         * @tparam T The type to use for the allocation. Default is uint8_t.
         * @param[in] nAmount The amount of elements to allocate memory for.
         * @return Returns a pointer to the allocated memory of type T or NULL when the allocation failed.
         */
        template <typename T /*= uint8_t*/>
        inline pointer<T> AllocMem(size_t nAmount)
        {
            return sdv::internal::make_ptr<T>(internal::GetMemMgr(), nAmount);
        }
    } // namespace core
} // namespace sdv

#ifdef interface_defined_locally
#undef interface
#endif

#ifdef _MSC_VER
    #pragma warning(pop)
#endif

#endif // !defined(IDL_PARSER_INTERFACE_H)
